• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 #include "src/heap/heap-write-barrier.h"
6 
7 #include "src/heap/embedder-tracing.h"
8 #include "src/heap/heap-write-barrier-inl.h"
9 #include "src/heap/marking-barrier.h"
10 #include "src/objects/code-inl.h"
11 #include "src/objects/descriptor-array.h"
12 #include "src/objects/js-objects.h"
13 #include "src/objects/maybe-object.h"
14 #include "src/objects/slots-inl.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 namespace {
20 thread_local MarkingBarrier* current_marking_barrier = nullptr;
21 }  // namespace
22 
CurrentMarkingBarrier(Heap * heap)23 MarkingBarrier* WriteBarrier::CurrentMarkingBarrier(Heap* heap) {
24   return current_marking_barrier ? current_marking_barrier
25                                  : heap->marking_barrier();
26 }
27 
SetForThread(MarkingBarrier * marking_barrier)28 void WriteBarrier::SetForThread(MarkingBarrier* marking_barrier) {
29   DCHECK_NULL(current_marking_barrier);
30   current_marking_barrier = marking_barrier;
31 }
32 
ClearForThread(MarkingBarrier * marking_barrier)33 void WriteBarrier::ClearForThread(MarkingBarrier* marking_barrier) {
34   DCHECK_EQ(current_marking_barrier, marking_barrier);
35   current_marking_barrier = nullptr;
36 }
37 
MarkingSlow(Heap * heap,HeapObject host,HeapObjectSlot slot,HeapObject value)38 void WriteBarrier::MarkingSlow(Heap* heap, HeapObject host, HeapObjectSlot slot,
39                                HeapObject value) {
40   MarkingBarrier* marking_barrier = current_marking_barrier
41                                         ? current_marking_barrier
42                                         : heap->marking_barrier();
43   marking_barrier->Write(host, slot, value);
44 }
45 
46 // static
MarkingSlowFromGlobalHandle(Heap * heap,HeapObject value)47 void WriteBarrier::MarkingSlowFromGlobalHandle(Heap* heap, HeapObject value) {
48   heap->marking_barrier()->WriteWithoutHost(value);
49 }
50 
51 // static
MarkingSlowFromInternalFields(Heap * heap,JSObject host)52 void WriteBarrier::MarkingSlowFromInternalFields(Heap* heap, JSObject host) {
53   auto* local_embedder_heap_tracer = heap->local_embedder_heap_tracer();
54   if (!local_embedder_heap_tracer->InUse()) return;
55 
56   local_embedder_heap_tracer->EmbedderWriteBarrier(heap, host);
57 }
58 
MarkingSlow(Heap * heap,Code host,RelocInfo * reloc_info,HeapObject value)59 void WriteBarrier::MarkingSlow(Heap* heap, Code host, RelocInfo* reloc_info,
60                                HeapObject value) {
61   MarkingBarrier* marking_barrier = current_marking_barrier
62                                         ? current_marking_barrier
63                                         : heap->marking_barrier();
64   marking_barrier->Write(host, reloc_info, value);
65 }
66 
MarkingSlow(Heap * heap,JSArrayBuffer host,ArrayBufferExtension * extension)67 void WriteBarrier::MarkingSlow(Heap* heap, JSArrayBuffer host,
68                                ArrayBufferExtension* extension) {
69   MarkingBarrier* marking_barrier = current_marking_barrier
70                                         ? current_marking_barrier
71                                         : heap->marking_barrier();
72   marking_barrier->Write(host, extension);
73 }
74 
MarkingSlow(Heap * heap,DescriptorArray descriptor_array,int number_of_own_descriptors)75 void WriteBarrier::MarkingSlow(Heap* heap, DescriptorArray descriptor_array,
76                                int number_of_own_descriptors) {
77   MarkingBarrier* marking_barrier = current_marking_barrier
78                                         ? current_marking_barrier
79                                         : heap->marking_barrier();
80   marking_barrier->Write(descriptor_array, number_of_own_descriptors);
81 }
82 
MarkingFromCode(Address raw_host,Address raw_slot)83 int WriteBarrier::MarkingFromCode(Address raw_host, Address raw_slot) {
84   HeapObject host = HeapObject::cast(Object(raw_host));
85   MaybeObjectSlot slot(raw_slot);
86   Address value = (*slot).ptr();
87 #ifdef V8_MAP_PACKING
88   if (slot.address() == host.address()) {
89     // Clear metadata bits and fix object tag.
90     value = (value & ~Internals::kMapWordMetadataMask &
91              ~Internals::kMapWordXorMask) |
92             (uint64_t)kHeapObjectTag;
93   }
94 #endif
95   WriteBarrier::Marking(host, slot, MaybeObject(value));
96   // Called by WriteBarrierCodeStubAssembler, which doesnt accept void type
97   return 0;
98 }
99 
100 #ifdef ENABLE_SLOW_DCHECKS
IsImmortalImmovableHeapObject(HeapObject object)101 bool WriteBarrier::IsImmortalImmovableHeapObject(HeapObject object) {
102   BasicMemoryChunk* basic_chunk = BasicMemoryChunk::FromHeapObject(object);
103   // All objects in readonly space are immortal and immovable.
104   if (basic_chunk->InReadOnlySpace()) return true;
105   MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
106   // There are also objects in "regular" spaces which are immortal and
107   // immovable. Objects on a page that can get compacted are movable and can be
108   // filtered out.
109   if (!chunk->IsFlagSet(MemoryChunk::NEVER_EVACUATE)) return false;
110   // Now we know the object is immovable, check whether it is also immortal.
111   // Builtins are roots and therefore always kept alive by the GC.
112   return object.IsCode() && Code::cast(object).is_builtin();
113 }
114 #endif
115 
116 }  // namespace internal
117 }  // namespace v8
118