summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/heap/marking_verifier.cc
blob: 5e0e7fed6dbf15937475797529abdabf11a2e15d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/heap/marking_verifier.h"

#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap_page.h"

namespace blink {

void MarkingVerifier::VerifyObject(HeapObjectHeader* header) {
  // Verify only non-free marked objects.
  if (header->IsFree() || !header->IsMarked())
    return;

  const GCInfo* info =
      GCInfoTable::Get().GCInfoFromIndex(header->GcInfoIndex());
  const bool can_verify =
      !info->has_v_table || blink::VTableInitialized(header->Payload());
  if (can_verify) {
    parent_ = header;
    info->trace(this, header->Payload());
  }
}

void MarkingVerifier::Visit(void* object, TraceDescriptor desc) {
  VerifyChild(object, desc.base_object_payload);
}

void MarkingVerifier::VisitWeak(void* object,
                                void* object_weak_ref,
                                TraceDescriptor desc,
                                WeakCallback callback) {
  // Weak objects should have been cleared at this point. As a consequence, all
  // objects found through weak references have to point to live objects at this
  // point.
  VerifyChild(object, desc.base_object_payload);
}

void MarkingVerifier::VisitBackingStoreStrongly(void* object,
                                                void**,
                                                TraceDescriptor desc) {
  if (!object)
    return;

  // Contents of backing stores are verified through page iteration. The
  // verification here only makes sure that the backing itself is properly
  // marked.
  VerifyChild(object, desc.base_object_payload);
}

void MarkingVerifier::VisitBackingStoreWeakly(void* object,
                                              void**,
                                              TraceDescriptor strong_desc,
                                              TraceDescriptor weak_desc,
                                              WeakCallback,
                                              void*) {
  if (!object)
    return;

  // Contents of weak backing stores are found themselves through page
  // iteration and are treated strongly that way, similar to how they are
  // treated strongly when found through stack scanning. The verification
  // here only makes sure that the backing itself is properly marked. Weak
  // backing stores found through
  VerifyChild(object, weak_desc.base_object_payload);
}

void MarkingVerifier::VerifyChild(void* object, void* base_object_payload) {
  CHECK(object);
  // Verification may check objects that are currently under construction and
  // would require vtable access to figure out their headers. A nullptr in
  // |base_object_payload| indicates that a mixin object is in construction
  // and the vtable cannot be used to get to the object header.
  const HeapObjectHeader* const child_header =
      (base_object_payload) ? HeapObjectHeader::FromPayload(base_object_payload)
                            : HeapObjectHeader::FromInnerAddress(object);
  // These checks ensure that any children reachable from marked parents are
  // also marked. If you hit these checks then marking is in an inconsistent
  // state meaning that there are unmarked objects reachable from marked
  // ones.
  CHECK(child_header);
  if (!child_header->IsMarked()) {
    // Pre-finalizers may allocate. In that case the newly allocated objects
    // reside on a page that is not scheduled for sweeping.
    if (PageFromObject(child_header->Payload())->HasBeenSwept())
      return;

    LOG(FATAL) << "MarkingVerifier: Encountered unmarked object. " << std::endl
               << std::endl
               << "Hint (use v8_enable_raw_heap_snapshots for better naming): "
               << std::endl
               << parent_->Name() << std::endl
               << "\\-> " << child_header->Name() << std::endl;
  }
}

}  // namespace blink