blob: 58b049ef54a13a0d7c9b0dd5063990657ff45054 [file] [log] [blame]
// 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/impl/marking_verifier.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/impl/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 = GCInfo::From(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(const void* object, TraceDescriptor desc) {
VerifyChild(object, desc.base_object_payload);
}
void MarkingVerifier::VisitWeak(const void* object,
const 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::VisitWeakContainer(const void* object,
const void* const*,
TraceDescriptor,
TraceDescriptor weak_desc,
WeakCallback,
const 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(const void* object,
const 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()) {
CHECK(!PageFromObject(child_header->Payload())->HasBeenSwept());
LOG(FATAL) << "MarkingVerifier: Encountered unmarked object. " << std::endl
<< std::endl
<< "Hint: " << std::endl
<< parent_->Name() << std::endl
<< "\\-> " << child_header->Name() << std::endl;
}
}
} // namespace blink