1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/platform/heap/marking_verifier.h"
6 
7 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
8 #include "third_party/blink/renderer/platform/heap/heap_page.h"
9 
10 namespace blink {
11 
VerifyObject(HeapObjectHeader * header)12 void MarkingVerifier::VerifyObject(HeapObjectHeader* header) {
13   // Verify only non-free marked objects.
14   if (header->IsFree() || !header->IsMarked())
15     return;
16 
17   const GCInfo& info = GCInfo::From(header->GcInfoIndex());
18   const bool can_verify =
19       !info.has_v_table || blink::VTableInitialized(header->Payload());
20   if (can_verify) {
21     parent_ = header;
22     info.trace(this, header->Payload());
23   }
24 }
25 
Visit(const void * object,TraceDescriptor desc)26 void MarkingVerifier::Visit(const void* object, TraceDescriptor desc) {
27   VerifyChild(object, desc.base_object_payload);
28 }
29 
VisitWeak(const void * object,const void * object_weak_ref,TraceDescriptor desc,WeakCallback callback)30 void MarkingVerifier::VisitWeak(const void* object,
31                                 const void* object_weak_ref,
32                                 TraceDescriptor desc,
33                                 WeakCallback callback) {
34   // Weak objects should have been cleared at this point. As a consequence, all
35   // objects found through weak references have to point to live objects at this
36   // point.
37   VerifyChild(object, desc.base_object_payload);
38 }
39 
VisitBackingStoreStrongly(const void * object,const void * const *,TraceDescriptor desc)40 void MarkingVerifier::VisitBackingStoreStrongly(const void* object,
41                                                 const void* const*,
42                                                 TraceDescriptor desc) {
43   if (!object)
44     return;
45 
46   // Contents of backing stores are verified through page iteration. The
47   // verification here only makes sure that the backing itself is properly
48   // marked.
49   VerifyChild(object, desc.base_object_payload);
50 }
51 
VisitBackingStoreWeakly(const void * object,const void * const *,TraceDescriptor strong_desc,TraceDescriptor weak_desc,WeakCallback,const void *)52 void MarkingVerifier::VisitBackingStoreWeakly(const void* object,
53                                               const void* const*,
54                                               TraceDescriptor strong_desc,
55                                               TraceDescriptor weak_desc,
56                                               WeakCallback,
57                                               const void*) {
58   if (!object)
59     return;
60 
61   // Contents of weak backing stores are found themselves through page
62   // iteration and are treated strongly that way, similar to how they are
63   // treated strongly when found through stack scanning. The verification
64   // here only makes sure that the backing itself is properly marked. Weak
65   // backing stores found through
66   VerifyChild(object, weak_desc.base_object_payload);
67 }
68 
VerifyChild(const void * object,const void * base_object_payload)69 void MarkingVerifier::VerifyChild(const void* object,
70                                   const void* base_object_payload) {
71   CHECK(object);
72   // Verification may check objects that are currently under construction and
73   // would require vtable access to figure out their headers. A nullptr in
74   // |base_object_payload| indicates that a mixin object is in construction
75   // and the vtable cannot be used to get to the object header.
76   const HeapObjectHeader* const child_header =
77       (base_object_payload) ? HeapObjectHeader::FromPayload(base_object_payload)
78                             : HeapObjectHeader::FromInnerAddress(object);
79   // These checks ensure that any children reachable from marked parents are
80   // also marked. If you hit these checks then marking is in an inconsistent
81   // state meaning that there are unmarked objects reachable from marked
82   // ones.
83   CHECK(child_header);
84   if (!child_header->IsMarked()) {
85     CHECK(!PageFromObject(child_header->Payload())->HasBeenSwept());
86     LOG(FATAL) << "MarkingVerifier: Encountered unmarked object. " << std::endl
87                << std::endl
88                << "Hint: " << std::endl
89                << parent_->Name() << std::endl
90                << "\\-> " << child_header->Name() << std::endl;
91   }
92 }
93 
94 }  // namespace blink
95