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