blob: 461af50f9803a46ee6fda884b18d4618062d474f [file] [log] [blame]
// Copyright 2020 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/heap/heap-write-barrier.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/marking-barrier.h"
#include "src/objects/code-inl.h"
#include "src/objects/descriptor-array.h"
#include "src/objects/js-objects.h"
#include "src/objects/maybe-object.h"
#include "src/objects/slots-inl.h"
namespace v8 {
namespace internal {
namespace {
thread_local MarkingBarrier* current_marking_barrier = nullptr;
} // namespace
MarkingBarrier* WriteBarrier::CurrentMarkingBarrier(Heap* heap) {
return current_marking_barrier ? current_marking_barrier
: heap->marking_barrier();
}
void WriteBarrier::SetForThread(MarkingBarrier* marking_barrier) {
DCHECK_NULL(current_marking_barrier);
current_marking_barrier = marking_barrier;
}
void WriteBarrier::ClearForThread(MarkingBarrier* marking_barrier) {
DCHECK_EQ(current_marking_barrier, marking_barrier);
current_marking_barrier = nullptr;
}
void WriteBarrier::MarkingSlow(Heap* heap, HeapObject host, HeapObjectSlot slot,
HeapObject value) {
MarkingBarrier* marking_barrier = current_marking_barrier
? current_marking_barrier
: heap->marking_barrier();
marking_barrier->Write(host, slot, value);
}
// static
void WriteBarrier::MarkingSlowFromGlobalHandle(Heap* heap, HeapObject value) {
heap->marking_barrier()->WriteWithoutHost(value);
}
// static
void WriteBarrier::MarkingSlowFromInternalFields(Heap* heap, JSObject host) {
auto* local_embedder_heap_tracer = heap->local_embedder_heap_tracer();
if (!local_embedder_heap_tracer->InUse()) return;
local_embedder_heap_tracer->EmbedderWriteBarrier(heap, host);
}
void WriteBarrier::MarkingSlow(Heap* heap, Code host, RelocInfo* reloc_info,
HeapObject value) {
MarkingBarrier* marking_barrier = current_marking_barrier
? current_marking_barrier
: heap->marking_barrier();
marking_barrier->Write(host, reloc_info, value);
}
void WriteBarrier::MarkingSlow(Heap* heap, JSArrayBuffer host,
ArrayBufferExtension* extension) {
MarkingBarrier* marking_barrier = current_marking_barrier
? current_marking_barrier
: heap->marking_barrier();
marking_barrier->Write(host, extension);
}
void WriteBarrier::MarkingSlow(Heap* heap, DescriptorArray descriptor_array,
int number_of_own_descriptors) {
MarkingBarrier* marking_barrier = current_marking_barrier
? current_marking_barrier
: heap->marking_barrier();
marking_barrier->Write(descriptor_array, number_of_own_descriptors);
}
int WriteBarrier::MarkingFromCode(Address raw_host, Address raw_slot) {
HeapObject host = HeapObject::cast(Object(raw_host));
MaybeObjectSlot slot(raw_slot);
Address value = (*slot).ptr();
#ifdef V8_MAP_PACKING
if (slot.address() == host.address()) {
// Clear metadata bits and fix object tag.
value = (value & ~Internals::kMapWordMetadataMask &
~Internals::kMapWordXorMask) |
(uint64_t)kHeapObjectTag;
}
#endif
WriteBarrier::Marking(host, slot, MaybeObject(value));
// Called by WriteBarrierCodeStubAssembler, which doesnt accept void type
return 0;
}
#ifdef ENABLE_SLOW_DCHECKS
bool WriteBarrier::IsImmortalImmovableHeapObject(HeapObject object) {
BasicMemoryChunk* basic_chunk = BasicMemoryChunk::FromHeapObject(object);
// All objects in readonly space are immortal and immovable.
if (basic_chunk->InReadOnlySpace()) return true;
MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
// There are also objects in "regular" spaces which are immortal and
// immovable. Objects on a page that can get compacted are movable and can be
// filtered out.
if (!chunk->IsFlagSet(MemoryChunk::NEVER_EVACUATE)) return false;
// Now we know the object is immovable, check whether it is also immortal.
// Builtins are roots and therefore always kept alive by the GC.
return object.IsCode() && Code::cast(object).is_builtin();
}
#endif
} // namespace internal
} // namespace v8