From e7c2a24e7fafba4e01b799961d2df1e549a94f4b Mon Sep 17 00:00:00 2001 From: Rong Wang Date: Tue, 10 Sep 2019 20:23:15 +1000 Subject: [PATCH] [heap] Additional V8_DISABLE_WRITE_BARRIERS guards This CL is necessary for disabling write-barriers that involoves referencing pages via address arithmetic, which is required from third-party heap implementation. Change-Id: I1d3f572d48015e5c8cf691b2dc71a32834621c2f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1781008 Reviewed-by: Jakob Gruber Reviewed-by: Ulan Degenbaev Commit-Queue: Ulan Degenbaev Cr-Commit-Position: refs/heads/master@{#63644} --- src/codegen/arm/assembler-arm-inl.h | 3 ++- src/codegen/arm64/assembler-arm64-inl.h | 3 ++- src/codegen/ia32/assembler-ia32-inl.h | 3 ++- src/codegen/mips/assembler-mips-inl.h | 3 ++- src/codegen/mips64/assembler-mips64-inl.h | 3 ++- src/codegen/ppc/assembler-ppc-inl.h | 3 ++- src/codegen/reloc-info.cc | 2 +- src/codegen/s390/assembler-s390-inl.h | 3 ++- src/codegen/x64/assembler-x64-inl.h | 3 ++- src/heap/factory.cc | 2 ++ src/heap/heap-write-barrier-inl.h | 4 ++++ src/heap/heap.cc | 6 ++++++ src/objects/js-objects-inl.h | 2 ++ src/objects/map-inl.h | 2 ++ src/objects/map.cc | 6 ++++++ src/objects/objects-inl.h | 6 ++++++ src/snapshot/deserializer.cc | 8 +++++--- src/snapshot/object-deserializer.cc | 2 ++ 18 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/codegen/arm/assembler-arm-inl.h b/src/codegen/arm/assembler-arm-inl.h index 3fbd679104..45ec07a382 100644 --- a/src/codegen/arm/assembler-arm-inl.h +++ b/src/codegen/arm/assembler-arm-inl.h @@ -118,7 +118,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT); Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/arm64/assembler-arm64-inl.h b/src/codegen/arm64/assembler-arm64-inl.h index baae106c1c..8e412de716 100644 --- a/src/codegen/arm64/assembler-arm64-inl.h +++ b/src/codegen/arm64/assembler-arm64-inl.h @@ -711,7 +711,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); } - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/ia32/assembler-ia32-inl.h b/src/codegen/ia32/assembler-ia32-inl.h index e274b41fa3..ba2bb18ef8 100644 --- a/src/codegen/ia32/assembler-ia32-inl.h +++ b/src/codegen/ia32/assembler-ia32-inl.h @@ -103,7 +103,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, if (icache_flush_mode != SKIP_ICACHE_FLUSH) { FlushInstructionCache(pc_, sizeof(Address)); } - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/mips/assembler-mips-inl.h b/src/codegen/mips/assembler-mips-inl.h index d8181ad8f5..fc4a8e4920 100644 --- a/src/codegen/mips/assembler-mips-inl.h +++ b/src/codegen/mips/assembler-mips-inl.h @@ -183,7 +183,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, DCHECK(IsCodeTarget(rmode_) || IsFullEmbeddedObject(rmode_)); Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/mips64/assembler-mips64-inl.h b/src/codegen/mips64/assembler-mips64-inl.h index 7b9946d16e..cacdbd8f8b 100644 --- a/src/codegen/mips64/assembler-mips64-inl.h +++ b/src/codegen/mips64/assembler-mips64-inl.h @@ -159,7 +159,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, DCHECK(IsCodeTarget(rmode_) || IsFullEmbeddedObject(rmode_)); Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/ppc/assembler-ppc-inl.h b/src/codegen/ppc/assembler-ppc-inl.h index 166b9d4423..c55a5a9c0b 100644 --- a/src/codegen/ppc/assembler-ppc-inl.h +++ b/src/codegen/ppc/assembler-ppc-inl.h @@ -144,7 +144,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT); Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/reloc-info.cc b/src/codegen/reloc-info.cc index a889a8b9c7..039a6746b1 100644 --- a/src/codegen/reloc-info.cc +++ b/src/codegen/reloc-info.cc @@ -366,7 +366,7 @@ void RelocInfo::set_target_address(Address target, Assembler::set_target_address_at(pc_, constant_pool_, target, icache_flush_mode); if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && - IsCodeTargetMode(rmode_)) { + IsCodeTargetMode(rmode_) && !FLAG_disable_write_barriers) { Code target_code = Code::GetCodeFromTargetAddress(target); MarkingBarrierForCode(host(), this, target_code); } diff --git a/src/codegen/s390/assembler-s390-inl.h b/src/codegen/s390/assembler-s390-inl.h index 5e7b193c8a..f911bdabf6 100644 --- a/src/codegen/s390/assembler-s390-inl.h +++ b/src/codegen/s390/assembler-s390-inl.h @@ -150,7 +150,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, DCHECK(IsCodeTarget(rmode_) || rmode_ == FULL_EMBEDDED_OBJECT); Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), icache_flush_mode); - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/codegen/x64/assembler-x64-inl.h b/src/codegen/x64/assembler-x64-inl.h index f5d0c0ffcf..fbb8a906b8 100644 --- a/src/codegen/x64/assembler-x64-inl.h +++ b/src/codegen/x64/assembler-x64-inl.h @@ -363,7 +363,8 @@ void RelocInfo::set_target_object(Heap* heap, HeapObject target, if (icache_flush_mode != SKIP_ICACHE_FLUSH) { FlushInstructionCache(pc_, sizeof(Address)); } - if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) { + if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && + !FLAG_disable_write_barriers) { WriteBarrierForCode(host(), this, target); } } diff --git a/src/heap/factory.cc b/src/heap/factory.cc index e0accf75dc..b2c4e96bfd 100644 --- a/src/heap/factory.cc +++ b/src/heap/factory.cc @@ -2703,7 +2703,9 @@ Handle Factory::CopyCode(Handle code) { // allocation is on. heap->incremental_marking()->ProcessBlackAllocatedObject(*new_code); // Record all references to embedded objects in the new code object. +#ifndef V8_DISABLE_WRITE_BARRIERS WriteBarrierForCode(*new_code); +#endif } #ifdef VERIFY_HEAP diff --git a/src/heap/heap-write-barrier-inl.h b/src/heap/heap-write-barrier-inl.h index 5687284b1e..a0d9902006 100644 --- a/src/heap/heap-write-barrier-inl.h +++ b/src/heap/heap-write-barrier-inl.h @@ -212,6 +212,7 @@ inline void MarkingBarrierForDescriptorArray(Heap* heap, HeapObject host, inline WriteBarrierMode GetWriteBarrierModeForObject( HeapObject object, const DisallowHeapAllocation* promise) { + if (FLAG_disable_write_barriers) return SKIP_WRITE_BARRIER; DCHECK(Heap_PageFlagsAreConsistent(object)); heap_internals::MemoryChunk* chunk = heap_internals::MemoryChunk::FromHeapObject(object); @@ -221,6 +222,9 @@ inline WriteBarrierMode GetWriteBarrierModeForObject( } inline bool ObjectInYoungGeneration(Object object) { + // TODO(rong): Fix caller of this function when we deploy + // v8_use_third_party_heap. + if (FLAG_single_generation) return false; if (object.IsSmi()) return false; return heap_internals::MemoryChunk::FromHeapObject(HeapObject::cast(object)) ->InYoungGeneration(); diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 8137443780..0fd9e898c4 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -5542,6 +5542,7 @@ void Heap::MoveStoreBufferEntriesToRememberedSet() { } void Heap::ClearRecordedSlot(HeapObject object, ObjectSlot slot) { +#ifndef V8_DISABLE_WRITE_BARRIERS DCHECK(!IsLargeObject(object)); Page* page = Page::FromAddress(slot.address()); if (!page->InYoungGeneration()) { @@ -5549,10 +5550,12 @@ void Heap::ClearRecordedSlot(HeapObject object, ObjectSlot slot) { store_buffer()->MoveAllEntriesToRememberedSet(); RememberedSet::Remove(page, slot.address()); } +#endif } #ifdef DEBUG void Heap::VerifyClearedSlot(HeapObject object, ObjectSlot slot) { +#ifndef V8_DISABLE_WRITE_BARRIERS DCHECK(!IsLargeObject(object)); if (InYoungGeneration(object)) return; Page* page = Page::FromAddress(slot.address()); @@ -5562,10 +5565,12 @@ void Heap::VerifyClearedSlot(HeapObject object, ObjectSlot slot) { // Old to old slots are filtered with invalidated slots. CHECK_IMPLIES(RememberedSet::Contains(page, slot.address()), page->RegisteredObjectWithInvalidatedSlots(object)); +#endif } #endif void Heap::ClearRecordedSlotRange(Address start, Address end) { +#ifndef V8_DISABLE_WRITE_BARRIERS Page* page = Page::FromAddress(start); DCHECK(!page->IsLargePage()); if (!page->InYoungGeneration()) { @@ -5574,6 +5579,7 @@ void Heap::ClearRecordedSlotRange(Address start, Address end) { RememberedSet::RemoveRange(page, start, end, SlotSet::KEEP_EMPTY_BUCKETS); } +#endif } PagedSpace* PagedSpaceIterator::Next() { diff --git a/src/objects/js-objects-inl.h b/src/objects/js-objects-inl.h index f8fe069d3d..4741eeb447 100644 --- a/src/objects/js-objects-inl.h +++ b/src/objects/js-objects-inl.h @@ -540,7 +540,9 @@ Code JSFunction::code() const { void JSFunction::set_code(Code value) { DCHECK(!ObjectInYoungGeneration(value)); RELAXED_WRITE_FIELD(*this, kCodeOffset, value); +#ifndef V8_DISABLE_WRITE_BARRIERS MarkingBarrier(*this, RawField(kCodeOffset), value); +#endif } void JSFunction::set_code_no_write_barrier(Code value) { diff --git a/src/objects/map-inl.h b/src/objects/map-inl.h index 48bb86e2da..3bd168cb8c 100644 --- a/src/objects/map-inl.h +++ b/src/objects/map-inl.h @@ -675,8 +675,10 @@ void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) { // barrier. descriptors.Append(desc); SetNumberOfOwnDescriptors(number_of_own_descriptors + 1); +#ifndef V8_DISABLE_WRITE_BARRIERS MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors, number_of_own_descriptors + 1); +#endif } // Properly mark the map if the {desc} is an "interesting symbol". if (desc->GetKey()->IsInterestingSymbol()) { diff --git a/src/objects/map.cc b/src/objects/map.cc index b0713d2c2e..b2eeda8b16 100644 --- a/src/objects/map.cc +++ b/src/objects/map.cc @@ -625,8 +625,10 @@ void Map::ReplaceDescriptors(Isolate* isolate, DescriptorArray new_descriptors, // descriptors will not be trimmed in the mark-compactor, we need to mark // all its elements. Map current = *this; +#ifndef V8_DISABLE_WRITE_BARRIERS MarkingBarrierForDescriptorArray(isolate->heap(), current, to_replace, to_replace.number_of_descriptors()); +#endif while (current.instance_descriptors(isolate) == to_replace) { Object next = current.GetBackPointer(isolate); if (next.IsUndefined(isolate)) break; // Stop overwriting at initial map. @@ -1108,8 +1110,10 @@ void Map::EnsureDescriptorSlack(Isolate* isolate, Handle map, int slack) { // Replace descriptors by new_descriptors in all maps that share it. The old // descriptors will not be trimmed in the mark-compactor, we need to mark // all its elements. +#ifndef V8_DISABLE_WRITE_BARRIERS MarkingBarrierForDescriptorArray(isolate->heap(), *map, *descriptors, descriptors->number_of_descriptors()); +#endif Map current = *map; while (current.instance_descriptors() == *descriptors) { @@ -2548,8 +2552,10 @@ void Map::SetInstanceDescriptors(Isolate* isolate, DescriptorArray descriptors, int number_of_own_descriptors) { set_synchronized_instance_descriptors(descriptors); SetNumberOfOwnDescriptors(number_of_own_descriptors); +#ifndef V8_DISABLE_WRITE_BARRIERS MarkingBarrierForDescriptorArray(isolate->heap(), *this, descriptors, number_of_own_descriptors); +#endif } // static diff --git a/src/objects/objects-inl.h b/src/objects/objects-inl.h index cf8c3ffad2..df00e0e7dc 100644 --- a/src/objects/objects-inl.h +++ b/src/objects/objects-inl.h @@ -756,11 +756,13 @@ void HeapObject::set_map(Map value) { #endif } set_map_word(MapWord::FromMap(value)); +#ifndef V8_DISABLE_WRITE_BARRIERS if (!value.is_null()) { // TODO(1600) We are passing kNullAddress as a slot because maps can never // be on an evacuation candidate. MarkingBarrier(*this, ObjectSlot(kNullAddress), value); } +#endif } DEF_GETTER(HeapObject, synchronized_map, Map) { @@ -774,11 +776,13 @@ void HeapObject::synchronized_set_map(Map value) { #endif } synchronized_set_map_word(MapWord::FromMap(value)); +#ifndef V8_DISABLE_WRITE_BARRIERS if (!value.is_null()) { // TODO(1600) We are passing kNullAddress as a slot because maps can never // be on an evacuation candidate. MarkingBarrier(*this, ObjectSlot(kNullAddress), value); } +#endif } // Unsafe accessor omitting write barrier. @@ -793,12 +797,14 @@ void HeapObject::set_map_no_write_barrier(Map value) { void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) { set_map_word(MapWord::FromMap(value)); +#ifndef V8_DISABLE_WRITE_BARRIERS if (mode != SKIP_WRITE_BARRIER) { DCHECK(!value.is_null()); // TODO(1600) We are passing kNullAddress as a slot because maps can never // be on an evacuation candidate. MarkingBarrier(*this, ObjectSlot(kNullAddress), value); } +#endif } ObjectSlot HeapObject::map_slot() const { diff --git a/src/snapshot/deserializer.cc b/src/snapshot/deserializer.cc index 98a453b0da..1b4fc655b4 100644 --- a/src/snapshot/deserializer.cc +++ b/src/snapshot/deserializer.cc @@ -527,9 +527,10 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, // Write barrier support costs around 1% in startup time. In fact there // are no new space objects in current boot snapshots, so it's not needed, // but that may change. - bool write_barrier_needed = (current_object_address != kNullAddress && - source_space != SnapshotSpace::kNew && - source_space != SnapshotSpace::kCode); + bool write_barrier_needed = + (current_object_address != kNullAddress && + source_space != SnapshotSpace::kNew && + source_space != SnapshotSpace::kCode && !FLAG_disable_write_barriers); while (current < limit) { byte data = source_.Get(); switch (data) { @@ -846,6 +847,7 @@ TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current, // Don't update current pointer here as it may be needed for write barrier. Write(current, heap_object_ref); if (emit_write_barrier && write_barrier_needed) { + DCHECK_IMPLIES(FLAG_disable_write_barriers, !write_barrier_needed); HeapObject host_object = HeapObject::FromAddress(current_object_address); SLOW_DCHECK(isolate->heap()->Contains(host_object)); GenerationalBarrier(host_object, MaybeObjectSlot(current.address()), diff --git a/src/snapshot/object-deserializer.cc b/src/snapshot/object-deserializer.cc index 63a0cfca17..daada252ba 100644 --- a/src/snapshot/object-deserializer.cc +++ b/src/snapshot/object-deserializer.cc @@ -60,7 +60,9 @@ void ObjectDeserializer::FlushICache() { DCHECK(deserializing_user_code()); for (Code code : new_code_objects()) { // Record all references to embedded objects in the new code object. +#ifndef V8_DISABLE_WRITE_BARRIERS WriteBarrierForCode(code); +#endif FlushInstructionCache(code.raw_instruction_start(), code.raw_instruction_size()); }