[heap] Add thread-safe shared barrier for code objects

In order to make the shared code write barrier thread-safe, we simply
lock the page mutex when appending to the typed_slot_set. We can later
improve this when performance isn't good enough.

Bug: v8:13018
Change-Id: I5e12f83f459f8976c22ec488cfa9b6f16d4a8a8e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3763867
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81855}
This commit is contained in:
Dominik Inführ 2022-07-19 17:38:32 +02:00 committed by V8 LUCI CQ
parent b3179fe760
commit aee4f59521
5 changed files with 44 additions and 17 deletions

View File

@ -140,7 +140,7 @@ inline void WriteBarrierForCode(Code host, RelocInfo* rinfo, Object value) {
inline void WriteBarrierForCode(Code host, RelocInfo* rinfo, HeapObject value) {
GenerationalBarrierForCode(host, rinfo, value);
SharedHeapBarrierForCode(host, rinfo, value);
WriteBarrier::Shared(host, rinfo, value);
WriteBarrier::Marking(host, rinfo, value);
}
@ -218,18 +218,6 @@ inline void GenerationalBarrierForCode(Code host, RelocInfo* rinfo,
Heap_GenerationalBarrierForCodeSlow(host, rinfo, object);
}
inline void SharedHeapBarrierForCode(Code host, RelocInfo* rinfo,
HeapObject object) {
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) return;
heap_internals::MemoryChunk* object_chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
if (!object_chunk->InSharedHeap()) return;
// TODO(v8:11708): Implement a thread-safe shared heap barrier. The barrier is
// executed from the main thread as well from concurrent compilation threads.
}
inline WriteBarrierMode GetWriteBarrierModeForObject(
HeapObject object, const DisallowGarbageCollection* promise) {
if (FLAG_disable_write_barriers) return SKIP_WRITE_BARRIER;
@ -271,6 +259,14 @@ base::Optional<Heap*> WriteBarrier::GetHeapIfMarking(HeapObject object) {
return chunk->GetHeap();
}
Heap* WriteBarrier::GetHeap(HeapObject object) {
DCHECK(!V8_ENABLE_THIRD_PARTY_HEAP_BOOL);
heap_internals::MemoryChunk* chunk =
heap_internals::MemoryChunk::FromHeapObject(object);
DCHECK(!chunk->InReadOnlySpace());
return chunk->GetHeap();
}
void WriteBarrier::Marking(HeapObject host, ObjectSlot slot, Object value) {
DCHECK(!HasWeakHeapObjectTag(value));
if (!value.IsHeapObject()) return;
@ -310,6 +306,21 @@ void WriteBarrier::Marking(Code host, RelocInfo* reloc_info, HeapObject value) {
MarkingSlow(*heap, host, reloc_info, value);
}
void WriteBarrier::Shared(Code host, RelocInfo* reloc_info, HeapObject value) {
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) return;
// There are no code objects in the shared heap.
DCHECK(!MemoryChunk::FromHeapObject(host)->InSharedHeap());
heap_internals::MemoryChunk* value_chunk =
heap_internals::MemoryChunk::FromHeapObject(value);
if (!value_chunk->InSharedHeap()) return;
Heap* heap = GetHeap(host);
DCHECK_NOT_NULL(heap);
SharedSlow(heap, host, reloc_info, value);
}
void WriteBarrier::Marking(JSArrayBuffer host,
ArrayBufferExtension* extension) {
if (!extension) return;

View File

@ -7,6 +7,7 @@
#include "src/heap/embedder-tracing.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/marking-barrier.h"
#include "src/heap/remembered-set.h"
#include "src/objects/code-inl.h"
#include "src/objects/descriptor-array.h"
#include "src/objects/js-objects.h"
@ -61,6 +62,16 @@ void WriteBarrier::MarkingSlow(Heap* heap, Code host, RelocInfo* reloc_info,
marking_barrier->Write(host, reloc_info, value);
}
void WriteBarrier::SharedSlow(Heap* heap, Code host, RelocInfo* reloc_info,
HeapObject value) {
MarkCompactCollector::RecordRelocSlotInfo info =
MarkCompactCollector::ProcessRelocInfo(host, reloc_info, value);
base::MutexGuard write_scope(info.memory_chunk->mutex());
RememberedSet<OLD_TO_SHARED>::InsertTyped(info.memory_chunk, info.slot_type,
info.offset);
}
void WriteBarrier::MarkingSlow(Heap* heap, JSArrayBuffer host,
ArrayBufferExtension* extension) {
MarkingBarrier* marking_barrier = CurrentMarkingBarrier(heap);

View File

@ -44,9 +44,6 @@ void CombinedEphemeronWriteBarrier(EphemeronHashTable object, ObjectSlot slot,
// Generational write barrier.
void GenerationalBarrierForCode(Code host, RelocInfo* rinfo, HeapObject object);
// Shared heap write barrier.
void SharedHeapBarrierForCode(Code host, RelocInfo* rinfo, HeapObject object);
inline bool IsReadOnlyHeapObject(HeapObject object);
class V8_EXPORT_PRIVATE WriteBarrier {
@ -59,6 +56,8 @@ class V8_EXPORT_PRIVATE WriteBarrier {
static inline void Marking(JSArrayBuffer host, ArrayBufferExtension*);
static inline void Marking(DescriptorArray, int number_of_own_descriptors);
static inline void Shared(Code host, RelocInfo*, HeapObject value);
// It is invoked from generated code and has to take raw addresses.
static int MarkingFromCode(Address raw_host, Address raw_slot);
// Invoked from global handles where no host object is available.
@ -81,6 +80,7 @@ class V8_EXPORT_PRIVATE WriteBarrier {
private:
static inline base::Optional<Heap*> GetHeapIfMarking(HeapObject object);
static inline Heap* GetHeap(HeapObject object);
static void MarkingSlow(Heap* heap, Code host, RelocInfo*, HeapObject value);
static void MarkingSlow(Heap* heap, JSArrayBuffer host,
@ -89,6 +89,10 @@ class V8_EXPORT_PRIVATE WriteBarrier {
int number_of_own_descriptors);
static void MarkingSlowFromGlobalHandle(Heap* heap, HeapObject value);
static void MarkingSlowFromInternalFields(Heap* heap, JSObject host);
static void SharedSlow(Heap* heap, Code host, RelocInfo*, HeapObject value);
friend class Heap;
};
} // namespace internal

View File

@ -7276,6 +7276,7 @@ void Heap::WriteBarrierForCodeSlow(Code code) {
it.next()) {
HeapObject target_object = it.rinfo()->target_object(cage_base);
GenerationalBarrierForCode(code, it.rinfo(), target_object);
WriteBarrier::Shared(code, it.rinfo(), target_object);
WriteBarrier::Marking(code, it.rinfo(), target_object);
}
}

View File

@ -3,7 +3,7 @@
// found in the LICENSE file.
//
// Flags: --shared-string-table --harmony-struct --allow-natives-syntax
// Flags: --verify-heapo
// Flags: --verify-heap
"use strict";