blob: 1e4550679c05ec89b41754e997bae5380e63be5e [file] [log] [blame]
// Copyright 2018 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.
#ifndef V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
#define V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
// Clients of this interface shouldn't depend on lots of heap internals.
// Do not include anything from src/heap here!
#include "src/heap/heap-write-barrier.h"
#include "src/globals.h"
#include "src/objects-inl.h"
#include "src/objects/maybe-object-inl.h"
namespace v8 {
namespace internal {
// Do not use these internal details anywhere outside of this file. These
// internals are only intended to shortcut write barrier checks.
namespace heap_internals {
struct MemoryChunk {
static constexpr uintptr_t kFlagsOffset = sizeof(size_t);
static constexpr uintptr_t kMarkingBit = uintptr_t{1} << 18;
static constexpr uintptr_t kFromSpaceBit = uintptr_t{1} << 3;
static constexpr uintptr_t kToSpaceBit = uintptr_t{1} << 4;
V8_INLINE static heap_internals::MemoryChunk* FromHeapObject(
HeapObject* object) {
return reinterpret_cast<MemoryChunk*>(reinterpret_cast<Address>(object) &
~kPageAlignmentMask);
}
V8_INLINE bool IsMarking() const { return GetFlags() & kMarkingBit; }
V8_INLINE bool InNewSpace() const {
constexpr uintptr_t kNewSpaceMask = kFromSpaceBit | kToSpaceBit;
return GetFlags() & kNewSpaceMask;
}
V8_INLINE uintptr_t GetFlags() const {
return *reinterpret_cast<const uintptr_t*>(
reinterpret_cast<const uint8_t*>(this) + kFlagsOffset);
}
};
inline void GenerationalBarrierInternal(HeapObject* object, Address slot,
HeapObject* value) {
DCHECK(Heap::PageFlagsAreConsistent(object));
heap_internals::MemoryChunk* value_chunk =
heap_internals::MemoryChunk::FromHeapObject(value);
heap_internals::MemoryChunk* object_chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
if (!value_chunk->InNewSpace() || object_chunk->InNewSpace()) return;
Heap::GenerationalBarrierSlow(object, slot, value);
}
inline void MarkingBarrierInternal(HeapObject* object, Address slot,
HeapObject* value) {
DCHECK(Heap::PageFlagsAreConsistent(object));
heap_internals::MemoryChunk* value_chunk =
heap_internals::MemoryChunk::FromHeapObject(value);
if (!value_chunk->IsMarking()) return;
Heap::MarkingBarrierSlow(object, slot, value);
}
} // namespace heap_internals
inline void WriteBarrierForCode(Code* host, RelocInfo* rinfo, Object* value) {
DCHECK(!HasWeakHeapObjectTag(value));
if (!value->IsHeapObject()) return;
HeapObject* object = HeapObject::cast(value);
GenerationalBarrierForCode(host, rinfo, object);
MarkingBarrierForCode(host, rinfo, object);
}
inline void WriteBarrierForCode(Code* host) {
Heap::WriteBarrierForCodeSlow(host);
}
inline void GenerationalBarrier(HeapObject* object, Object** slot,
Object* value) {
DCHECK(!HasWeakHeapObjectTag(*slot));
DCHECK(!HasWeakHeapObjectTag(value));
if (!value->IsHeapObject()) return;
heap_internals::GenerationalBarrierInternal(
object, reinterpret_cast<Address>(slot), HeapObject::cast(value));
}
inline void GenerationalBarrier(HeapObject* object, MaybeObject** slot,
MaybeObject* value) {
HeapObject* value_heap_object;
if (!value->ToStrongOrWeakHeapObject(&value_heap_object)) return;
heap_internals::GenerationalBarrierInternal(
object, reinterpret_cast<Address>(slot), value_heap_object);
}
inline void GenerationalBarrierForElements(Heap* heap, FixedArray* array,
int offset, int length) {
heap_internals::MemoryChunk* array_chunk =
heap_internals::MemoryChunk::FromHeapObject(array);
if (array_chunk->InNewSpace()) return;
Heap::GenerationalBarrierForElementsSlow(heap, array, offset, length);
}
inline void GenerationalBarrierForCode(Code* host, RelocInfo* rinfo,
HeapObject* object) {
heap_internals::MemoryChunk* object_chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
if (!object_chunk->InNewSpace()) return;
Heap::GenerationalBarrierForCodeSlow(host, rinfo, object);
}
inline void MarkingBarrier(HeapObject* object, Object** slot, Object* value) {
DCHECK_IMPLIES(slot != nullptr, !HasWeakHeapObjectTag(*slot));
DCHECK(!HasWeakHeapObjectTag(value));
if (!value->IsHeapObject()) return;
heap_internals::MarkingBarrierInternal(
object, reinterpret_cast<Address>(slot), HeapObject::cast(value));
}
inline void MarkingBarrier(HeapObject* object, MaybeObject** slot,
MaybeObject* value) {
HeapObject* value_heap_object;
if (!value->ToStrongOrWeakHeapObject(&value_heap_object)) return;
heap_internals::MarkingBarrierInternal(
object, reinterpret_cast<Address>(slot), value_heap_object);
}
inline void MarkingBarrierForElements(Heap* heap, HeapObject* object) {
heap_internals::MemoryChunk* object_chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
if (!object_chunk->IsMarking()) return;
Heap::MarkingBarrierForElementsSlow(heap, object);
}
inline void MarkingBarrierForCode(Code* host, RelocInfo* rinfo,
HeapObject* object) {
DCHECK(!HasWeakHeapObjectTag(object));
heap_internals::MemoryChunk* object_chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
if (!object_chunk->IsMarking()) return;
Heap::MarkingBarrierForCodeSlow(host, rinfo, object);
}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_HEAP_WRITE_BARRIER_INL_H_