blob: adaa70406da063620a98923afb506a9d6af587ed [file]
// Copyright 2022 the V8 project 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 "src/codegen/assembler-inl.h"
#include "src/codegen/reloc-info.h"
#include "src/heap/evacuation-verifier-inl.h"
#include "src/objects/map-inl.h"
namespace v8 {
namespace internal {
#ifdef VERIFY_HEAP
EvacuationVerifier::EvacuationVerifier(Heap* heap)
: ObjectVisitorWithCageBases(heap), heap_(heap) {}
void EvacuationVerifier::VisitPointers(HeapObject host, ObjectSlot start,
ObjectSlot end) {
VerifyPointers(start, end);
}
void EvacuationVerifier::VisitPointers(HeapObject host, MaybeObjectSlot start,
MaybeObjectSlot end) {
VerifyPointers(start, end);
}
void EvacuationVerifier::VisitCodePointer(Code host, CodeObjectSlot slot) {
VerifyCodePointer(slot);
}
void EvacuationVerifier::VisitRootPointers(Root root, const char* description,
FullObjectSlot start,
FullObjectSlot end) {
VerifyRootPointers(start, end);
}
void EvacuationVerifier::VisitMapPointer(HeapObject object) {
VerifyMap(object.map(cage_base()));
}
void EvacuationVerifier::VerifyRoots() {
heap_->IterateRootsIncludingClients(
this,
base::EnumSet<SkipRoot>{SkipRoot::kWeak, SkipRoot::kConservativeStack});
}
void EvacuationVerifier::VerifyEvacuationOnPage(Address start, Address end) {
Address current = start;
while (current < end) {
HeapObject object = HeapObject::FromAddress(current);
if (!object.IsFreeSpaceOrFiller(cage_base())) {
object.Iterate(cage_base(), this);
}
current += ALIGN_TO_ALLOCATION_ALIGNMENT(object.Size(cage_base()));
}
}
void EvacuationVerifier::VerifyEvacuation(NewSpace* space) {
if (!space) return;
if (v8_flags.minor_mc) {
VerifyEvacuation(PagedNewSpace::From(space)->paged_space());
return;
}
PageRange range(space->first_allocatable_address(), space->top());
for (auto it = range.begin(); it != range.end();) {
Page* page = *(it++);
Address current = page->area_start();
Address limit = it != range.end() ? page->area_end() : space->top();
CHECK(limit == space->top() || !page->Contains(space->top()));
VerifyEvacuationOnPage(current, limit);
}
}
void EvacuationVerifier::VerifyEvacuation(PagedSpaceBase* space) {
for (Page* p : *space) {
if (p->IsEvacuationCandidate()) continue;
if (p->Contains(space->top())) {
CodePageMemoryModificationScope memory_modification_scope(p);
heap_->CreateFillerObjectAt(
space->top(), static_cast<int>(space->limit() - space->top()));
}
VerifyEvacuationOnPage(p->area_start(), p->area_end());
}
}
FullEvacuationVerifier::FullEvacuationVerifier(Heap* heap)
: EvacuationVerifier(heap) {}
void FullEvacuationVerifier::Run() {
DCHECK(!heap_->sweeping_in_progress());
VerifyRoots();
VerifyEvacuation(heap_->new_space());
VerifyEvacuation(heap_->old_space());
VerifyEvacuation(heap_->code_space());
if (heap_->shared_space()) VerifyEvacuation(heap_->shared_space());
}
void FullEvacuationVerifier::VerifyMap(Map map) { VerifyHeapObjectImpl(map); }
void FullEvacuationVerifier::VerifyPointers(ObjectSlot start, ObjectSlot end) {
VerifyPointersImpl(start, end);
}
void FullEvacuationVerifier::VerifyPointers(MaybeObjectSlot start,
MaybeObjectSlot end) {
VerifyPointersImpl(start, end);
}
void FullEvacuationVerifier::VerifyCodePointer(CodeObjectSlot slot) {
Object maybe_code = slot.load(code_cage_base());
HeapObject code;
// The slot might contain smi during Code creation, so skip it.
if (maybe_code.GetHeapObject(&code)) {
VerifyHeapObjectImpl(code);
}
}
void FullEvacuationVerifier::VisitCodeTarget(InstructionStream host,
RelocInfo* rinfo) {
InstructionStream target =
InstructionStream::FromTargetAddress(rinfo->target_address());
VerifyHeapObjectImpl(target);
}
void FullEvacuationVerifier::VisitEmbeddedPointer(InstructionStream host,
RelocInfo* rinfo) {
VerifyHeapObjectImpl(rinfo->target_object(cage_base()));
}
void FullEvacuationVerifier::VerifyRootPointers(FullObjectSlot start,
FullObjectSlot end) {
VerifyPointersImpl(start, end);
}
YoungGenerationEvacuationVerifier::YoungGenerationEvacuationVerifier(Heap* heap)
: EvacuationVerifier(heap) {}
void YoungGenerationEvacuationVerifier::YoungGenerationEvacuationVerifier::
Run() {
DCHECK(!heap_->sweeping_in_progress());
VerifyRoots();
VerifyEvacuation(heap_->new_space());
VerifyEvacuation(heap_->old_space());
VerifyEvacuation(heap_->code_space());
}
void YoungGenerationEvacuationVerifier::VerifyMap(Map map) {
VerifyHeapObjectImpl(map);
}
void YoungGenerationEvacuationVerifier::VerifyPointers(ObjectSlot start,
ObjectSlot end) {
VerifyPointersImpl(start, end);
}
void YoungGenerationEvacuationVerifier::VerifyPointers(MaybeObjectSlot start,
MaybeObjectSlot end) {
VerifyPointersImpl(start, end);
}
void YoungGenerationEvacuationVerifier::VerifyCodePointer(CodeObjectSlot slot) {
Object maybe_code = slot.load(code_cage_base());
HeapObject code;
// The slot might contain smi during Code creation, so skip it.
if (maybe_code.GetHeapObject(&code)) {
VerifyHeapObjectImpl(code);
}
}
void YoungGenerationEvacuationVerifier::VisitCodeTarget(InstructionStream host,
RelocInfo* rinfo) {
InstructionStream target =
InstructionStream::FromTargetAddress(rinfo->target_address());
VerifyHeapObjectImpl(target);
}
void YoungGenerationEvacuationVerifier::VisitEmbeddedPointer(
InstructionStream host, RelocInfo* rinfo) {
VerifyHeapObjectImpl(rinfo->target_object(cage_base()));
}
void YoungGenerationEvacuationVerifier::VerifyRootPointers(FullObjectSlot start,
FullObjectSlot end) {
VerifyPointersImpl(start, end);
}
#endif // VERIFY_HEAP
} // namespace internal
} // namespace v8