1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
6 #define V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
7
8 // Clients of this interface shouldn't depend on lots of heap internals.
9 // Do not include anything from src/heap here!
10
11 #include "src/heap/heap-write-barrier.h"
12
13 #include "src/globals.h"
14 #include "src/objects-inl.h"
15 #include "src/objects/maybe-object-inl.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // Do not use these internal details anywhere outside of this file. These
21 // internals are only intended to shortcut write barrier checks.
22 namespace heap_internals {
23
24 struct MemoryChunk {
25 static constexpr uintptr_t kFlagsOffset = sizeof(size_t);
26 static constexpr uintptr_t kMarkingBit = uintptr_t{1} << 18;
27 static constexpr uintptr_t kFromSpaceBit = uintptr_t{1} << 3;
28 static constexpr uintptr_t kToSpaceBit = uintptr_t{1} << 4;
29
FromHeapObjectMemoryChunk30 V8_INLINE static heap_internals::MemoryChunk* FromHeapObject(
31 HeapObject* object) {
32 return reinterpret_cast<MemoryChunk*>(reinterpret_cast<Address>(object) &
33 ~kPageAlignmentMask);
34 }
35
IsMarkingMemoryChunk36 V8_INLINE bool IsMarking() const { return GetFlags() & kMarkingBit; }
37
InNewSpaceMemoryChunk38 V8_INLINE bool InNewSpace() const {
39 constexpr uintptr_t kNewSpaceMask = kFromSpaceBit | kToSpaceBit;
40 return GetFlags() & kNewSpaceMask;
41 }
42
GetFlagsMemoryChunk43 V8_INLINE uintptr_t GetFlags() const {
44 return *reinterpret_cast<const uintptr_t*>(
45 reinterpret_cast<const uint8_t*>(this) + kFlagsOffset);
46 }
47 };
48
GenerationalBarrierInternal(HeapObject * object,Address slot,HeapObject * value)49 inline void GenerationalBarrierInternal(HeapObject* object, Address slot,
50 HeapObject* value) {
51 DCHECK(Heap::PageFlagsAreConsistent(object));
52 heap_internals::MemoryChunk* value_chunk =
53 heap_internals::MemoryChunk::FromHeapObject(value);
54 heap_internals::MemoryChunk* object_chunk =
55 heap_internals::MemoryChunk::FromHeapObject(object);
56
57 if (!value_chunk->InNewSpace() || object_chunk->InNewSpace()) return;
58
59 Heap::GenerationalBarrierSlow(object, slot, value);
60 }
61
MarkingBarrierInternal(HeapObject * object,Address slot,HeapObject * value)62 inline void MarkingBarrierInternal(HeapObject* object, Address slot,
63 HeapObject* value) {
64 DCHECK(Heap::PageFlagsAreConsistent(object));
65 heap_internals::MemoryChunk* value_chunk =
66 heap_internals::MemoryChunk::FromHeapObject(value);
67
68 if (!value_chunk->IsMarking()) return;
69
70 Heap::MarkingBarrierSlow(object, slot, value);
71 }
72
73 } // namespace heap_internals
74
WriteBarrierForCode(Code * host,RelocInfo * rinfo,Object * value)75 inline void WriteBarrierForCode(Code* host, RelocInfo* rinfo, Object* value) {
76 DCHECK(!HasWeakHeapObjectTag(value));
77 if (!value->IsHeapObject()) return;
78 HeapObject* object = HeapObject::cast(value);
79 GenerationalBarrierForCode(host, rinfo, object);
80 MarkingBarrierForCode(host, rinfo, object);
81 }
82
WriteBarrierForCode(Code * host)83 inline void WriteBarrierForCode(Code* host) {
84 Heap::WriteBarrierForCodeSlow(host);
85 }
86
GenerationalBarrier(HeapObject * object,Object ** slot,Object * value)87 inline void GenerationalBarrier(HeapObject* object, Object** slot,
88 Object* value) {
89 DCHECK(!HasWeakHeapObjectTag(*slot));
90 DCHECK(!HasWeakHeapObjectTag(value));
91 if (!value->IsHeapObject()) return;
92 heap_internals::GenerationalBarrierInternal(
93 object, reinterpret_cast<Address>(slot), HeapObject::cast(value));
94 }
95
GenerationalBarrier(HeapObject * object,MaybeObject ** slot,MaybeObject * value)96 inline void GenerationalBarrier(HeapObject* object, MaybeObject** slot,
97 MaybeObject* value) {
98 HeapObject* value_heap_object;
99 if (!value->ToStrongOrWeakHeapObject(&value_heap_object)) return;
100 heap_internals::GenerationalBarrierInternal(
101 object, reinterpret_cast<Address>(slot), value_heap_object);
102 }
103
GenerationalBarrierForElements(Heap * heap,FixedArray * array,int offset,int length)104 inline void GenerationalBarrierForElements(Heap* heap, FixedArray* array,
105 int offset, int length) {
106 heap_internals::MemoryChunk* array_chunk =
107 heap_internals::MemoryChunk::FromHeapObject(array);
108 if (array_chunk->InNewSpace()) return;
109
110 Heap::GenerationalBarrierForElementsSlow(heap, array, offset, length);
111 }
112
GenerationalBarrierForCode(Code * host,RelocInfo * rinfo,HeapObject * object)113 inline void GenerationalBarrierForCode(Code* host, RelocInfo* rinfo,
114 HeapObject* object) {
115 heap_internals::MemoryChunk* object_chunk =
116 heap_internals::MemoryChunk::FromHeapObject(object);
117 if (!object_chunk->InNewSpace()) return;
118 Heap::GenerationalBarrierForCodeSlow(host, rinfo, object);
119 }
120
MarkingBarrier(HeapObject * object,Object ** slot,Object * value)121 inline void MarkingBarrier(HeapObject* object, Object** slot, Object* value) {
122 DCHECK_IMPLIES(slot != nullptr, !HasWeakHeapObjectTag(*slot));
123 DCHECK(!HasWeakHeapObjectTag(value));
124 if (!value->IsHeapObject()) return;
125 heap_internals::MarkingBarrierInternal(
126 object, reinterpret_cast<Address>(slot), HeapObject::cast(value));
127 }
128
MarkingBarrier(HeapObject * object,MaybeObject ** slot,MaybeObject * value)129 inline void MarkingBarrier(HeapObject* object, MaybeObject** slot,
130 MaybeObject* value) {
131 HeapObject* value_heap_object;
132 if (!value->ToStrongOrWeakHeapObject(&value_heap_object)) return;
133 heap_internals::MarkingBarrierInternal(
134 object, reinterpret_cast<Address>(slot), value_heap_object);
135 }
136
MarkingBarrierForElements(Heap * heap,HeapObject * object)137 inline void MarkingBarrierForElements(Heap* heap, HeapObject* object) {
138 heap_internals::MemoryChunk* object_chunk =
139 heap_internals::MemoryChunk::FromHeapObject(object);
140 if (!object_chunk->IsMarking()) return;
141
142 Heap::MarkingBarrierForElementsSlow(heap, object);
143 }
144
MarkingBarrierForCode(Code * host,RelocInfo * rinfo,HeapObject * object)145 inline void MarkingBarrierForCode(Code* host, RelocInfo* rinfo,
146 HeapObject* object) {
147 DCHECK(!HasWeakHeapObjectTag(object));
148 heap_internals::MemoryChunk* object_chunk =
149 heap_internals::MemoryChunk::FromHeapObject(object);
150 if (!object_chunk->IsMarking()) return;
151 Heap::MarkingBarrierForCodeSlow(host, rinfo, object);
152 }
153
154 } // namespace internal
155 } // namespace v8
156
157 #endif // V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
158