[ext-code-space] Change representation of forwared MapWord
... to make it independent of the pointer compression scheme used for the main cage and for code cage. When external code space is enabled forwarding pointers are encoded as Smi values representing a diff from the source or map word host object address in kObjectAlignment chunks. Such a representation has the following properties: a) it can hold both positive an negative diffs for full pointer compression cage size (HeapObject address has only valuable 30 bits while Smis have 30 bits + 1 sign bit), b) it's independent of the pointer compression base and pointer compression scheme used for main cage and code cage. When external code space is not enabled the old encoding is used: the forwared pointer represents the address of the new object location. Bug: v8:11880 Change-Id: I8bd302874c45fce346d30d91ffcbc9b4ef2c1353 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4023081 Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/main@{#84260}
This commit is contained in:
parent
9a5a020975
commit
1870170a50
@ -1116,7 +1116,7 @@ void VisitSpillSlot(Isolate* isolate, RootVisitor* v,
|
||||
HeapObject raw = HeapObject::cast(Object(*spill_slot.location()));
|
||||
MapWord map_word = raw.map_word(cage_base, kRelaxedLoad);
|
||||
HeapObject forwarded = map_word.IsForwardingAddress()
|
||||
? map_word.ToForwardingAddress()
|
||||
? map_word.ToForwardingAddress(raw)
|
||||
: raw;
|
||||
bool is_self_forwarded =
|
||||
forwarded.map_word(cage_base, kRelaxedLoad).ptr() ==
|
||||
@ -1132,7 +1132,7 @@ void VisitSpillSlot(Isolate* isolate, RootVisitor* v,
|
||||
MapWord fwd_map_map_word =
|
||||
forwarded_map.map_word(cage_base, kRelaxedLoad);
|
||||
if (fwd_map_map_word.IsForwardingAddress()) {
|
||||
forwarded_map = fwd_map_map_word.ToForwardingAddress();
|
||||
forwarded_map = fwd_map_map_word.ToForwardingAddress(forwarded_map);
|
||||
}
|
||||
CHECK(forwarded_map.IsMap(cage_base));
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ T ForwardingAddress(T heap_obj) {
|
||||
MapWord map_word = heap_obj.map_word(kRelaxedLoad);
|
||||
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
return T::cast(map_word.ToForwardingAddress());
|
||||
return T::cast(map_word.ToForwardingAddress(heap_obj));
|
||||
} else if (Heap::InFromPage(heap_obj)) {
|
||||
DCHECK(!v8_flags.minor_mc);
|
||||
return T();
|
||||
|
@ -498,11 +498,11 @@ void HeapVerifier::VerifySafeMapTransition(Heap* heap, HeapObject object,
|
||||
object.IterateFast(cage_base, &old_visitor);
|
||||
MapWord old_map_word = object.map_word(cage_base, kRelaxedLoad);
|
||||
// Temporarily set the new map to iterate new slots.
|
||||
object.set_map_word(MapWord::FromMap(new_map), kRelaxedStore);
|
||||
object.set_map_word(new_map, kRelaxedStore);
|
||||
SlotCollectingVisitor new_visitor;
|
||||
object.IterateFast(cage_base, &new_visitor);
|
||||
// Restore the old map.
|
||||
object.set_map_word(old_map_word, kRelaxedStore);
|
||||
object.set_map_word(old_map_word.ToMap(), kRelaxedStore);
|
||||
DCHECK_EQ(new_visitor.number_of_slots(), old_visitor.number_of_slots());
|
||||
for (int i = 0; i < new_visitor.number_of_slots(); i++) {
|
||||
DCHECK_EQ(new_visitor.slot(i), old_visitor.slot(i));
|
||||
|
@ -973,13 +973,13 @@ void UpdateRetainersMapAfterScavenge(UnorderedHeapObjectMap<HeapObject>* map) {
|
||||
if (Heap::InFromPage(object)) {
|
||||
MapWord map_word = object.map_word(kRelaxedLoad);
|
||||
if (!map_word.IsForwardingAddress()) continue;
|
||||
object = map_word.ToForwardingAddress();
|
||||
object = map_word.ToForwardingAddress(object);
|
||||
}
|
||||
|
||||
if (Heap::InFromPage(retainer)) {
|
||||
MapWord map_word = retainer.map_word(kRelaxedLoad);
|
||||
if (!map_word.IsForwardingAddress()) continue;
|
||||
retainer = map_word.ToForwardingAddress();
|
||||
retainer = map_word.ToForwardingAddress(retainer);
|
||||
}
|
||||
|
||||
updated_map[object] = retainer;
|
||||
@ -1005,7 +1005,7 @@ void Heap::UpdateRetainersAfterScavenge() {
|
||||
if (Heap::InFromPage(object)) {
|
||||
MapWord map_word = object.map_word(kRelaxedLoad);
|
||||
if (!map_word.IsForwardingAddress()) continue;
|
||||
object = map_word.ToForwardingAddress();
|
||||
object = map_word.ToForwardingAddress(object);
|
||||
}
|
||||
|
||||
updated_retaining_root[object] = pair.second;
|
||||
@ -2756,7 +2756,7 @@ String Heap::UpdateYoungReferenceInExternalStringTableEntry(Heap* heap,
|
||||
heap->FinalizeExternalString(string);
|
||||
return String();
|
||||
}
|
||||
new_string = String::cast(first_word.ToForwardingAddress());
|
||||
new_string = String::cast(first_word.ToForwardingAddress(obj));
|
||||
} else {
|
||||
new_string = String::cast(obj);
|
||||
}
|
||||
@ -6999,12 +6999,7 @@ Map Heap::GcSafeMapOfCodeSpaceObject(HeapObject object) {
|
||||
PtrComprCageBase cage_base(isolate());
|
||||
MapWord map_word = object.map_word(cage_base, kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
PtrComprCageBase code_cage_base(isolate()->code_cage_base());
|
||||
#else
|
||||
PtrComprCageBase code_cage_base = cage_base;
|
||||
#endif
|
||||
return map_word.ToForwardingAddress(code_cage_base).map(cage_base);
|
||||
return map_word.ToForwardingAddress(object).map(cage_base);
|
||||
}
|
||||
return map_word.ToMap();
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ void IncrementalMarking::UpdateMarkingWorklistAfterYoungGenGC() {
|
||||
// Hence, we can discard them.
|
||||
return false;
|
||||
}
|
||||
HeapObject dest = map_word.ToForwardingAddress();
|
||||
HeapObject dest = map_word.ToForwardingAddress(obj);
|
||||
USE(this);
|
||||
DCHECK_IMPLIES(marking_state->IsWhite(obj), obj.IsFreeSpaceOrFiller());
|
||||
if (dest.InSharedHeap()) {
|
||||
|
@ -1680,7 +1680,7 @@ class EvacuateVisitorBase : public HeapObjectVisitor {
|
||||
if (mode != MigrationMode::kFast)
|
||||
base->ExecuteMigrationObservers(dest, src, dst, size);
|
||||
}
|
||||
src.set_map_word(MapWord::FromForwardingAddress(dst), kRelaxedStore);
|
||||
src.set_map_word_forwarded(dst, kRelaxedStore);
|
||||
}
|
||||
|
||||
EvacuateVisitorBase(Heap* heap, EvacuationAllocator* local_allocator,
|
||||
@ -1835,8 +1835,7 @@ class EvacuateNewSpaceVisitor final : public EvacuateVisitorBase {
|
||||
if (map.visitor_id() == kVisitThinString) {
|
||||
HeapObject actual = ThinString::cast(object).unchecked_actual();
|
||||
if (MarkCompactCollector::IsOnEvacuationCandidate(actual)) return false;
|
||||
object.set_map_word(MapWord::FromForwardingAddress(actual),
|
||||
kRelaxedStore);
|
||||
object.set_map_word_forwarded(actual, kRelaxedStore);
|
||||
return true;
|
||||
}
|
||||
// TODO(mlippautz): Handle ConsString.
|
||||
@ -3705,7 +3704,7 @@ MaybeObject MakeSlotValue<FullMaybeObjectSlot, HeapObjectReferenceType::STRONG>(
|
||||
// The following specialization
|
||||
// MakeSlotValue<FullMaybeObjectSlot, HeapObjectReferenceType::WEAK>()
|
||||
// is not used.
|
||||
#endif
|
||||
#endif // V8_COMPRESS_POINTERS
|
||||
|
||||
template <AccessMode access_mode, HeapObjectReferenceType reference_type,
|
||||
typename TSlot>
|
||||
@ -3725,10 +3724,8 @@ static inline void UpdateSlot(PtrComprCageBase cage_base, TSlot slot,
|
||||
MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) ||
|
||||
Page::FromHeapObject(heap_obj)->IsFlagSet(
|
||||
Page::COMPACTION_WAS_ABORTED));
|
||||
PtrComprCageBase host_cage_base =
|
||||
V8_EXTERNAL_CODE_SPACE_BOOL ? GetPtrComprCageBase(heap_obj) : cage_base;
|
||||
typename TSlot::TObject target = MakeSlotValue<TSlot, reference_type>(
|
||||
map_word.ToForwardingAddress(host_cage_base));
|
||||
map_word.ToForwardingAddress(heap_obj));
|
||||
if (access_mode == AccessMode::NON_ATOMIC) {
|
||||
// Needs to be atomic for map space compaction: This slot could be a map
|
||||
// word which we update while loading the map word for updating the slot
|
||||
@ -3925,7 +3922,7 @@ static String UpdateReferenceInExternalStringTableEntry(Heap* heap,
|
||||
MapWord map_word = old_string.map_word(kRelaxedLoad);
|
||||
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
String new_string = String::cast(map_word.ToForwardingAddress());
|
||||
String new_string = String::cast(map_word.ToForwardingAddress(old_string));
|
||||
|
||||
if (new_string.IsExternalString()) {
|
||||
MemoryChunk::MoveExternalBackingStoreBytes(
|
||||
@ -4533,7 +4530,7 @@ class EvacuationWeakObjectRetainer : public WeakObjectRetainer {
|
||||
HeapObject heap_object = HeapObject::cast(object);
|
||||
MapWord map_word = heap_object.map_word(kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
return map_word.ToForwardingAddress();
|
||||
return map_word.ToForwardingAddress(heap_object);
|
||||
}
|
||||
}
|
||||
return object;
|
||||
@ -4895,7 +4892,7 @@ class RememberedSetUpdatingItem : public UpdatingItem {
|
||||
MapWord map_word = heap_object.map_word(kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
HeapObjectReference::Update(THeapObjectSlot(slot),
|
||||
map_word.ToForwardingAddress());
|
||||
map_word.ToForwardingAddress(heap_object));
|
||||
}
|
||||
bool success = (*slot).GetHeapObject(&heap_object);
|
||||
USE(success);
|
||||
@ -4918,8 +4915,8 @@ class RememberedSetUpdatingItem : public UpdatingItem {
|
||||
if (v8_flags.minor_mc) {
|
||||
MapWord map_word = heap_object.map_word(kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
HeapObjectReference::Update(THeapObjectSlot(slot),
|
||||
map_word.ToForwardingAddress());
|
||||
HeapObjectReference::Update(
|
||||
THeapObjectSlot(slot), map_word.ToForwardingAddress(heap_object));
|
||||
bool success = (*slot).GetHeapObject(&heap_object);
|
||||
USE(success);
|
||||
DCHECK(success);
|
||||
@ -5181,7 +5178,7 @@ class EphemeronTableUpdatingItem : public UpdatingItem {
|
||||
HeapObject key = key_slot.ToHeapObject();
|
||||
MapWord map_word = key.map_word(cage_base, kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
key = map_word.ToForwardingAddress();
|
||||
key = map_word.ToForwardingAddress(key);
|
||||
key_slot.StoreHeapObject(key);
|
||||
}
|
||||
if (!heap_->InYoungGeneration(key)) {
|
||||
|
@ -25,7 +25,7 @@ void PretenturingHandler::MergeAllocationSitePretenuringFeedback(
|
||||
site = site_and_count.first;
|
||||
MapWord map_word = site.map_word(cage_base, kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
site = AllocationSite::cast(map_word.ToForwardingAddress());
|
||||
site = AllocationSite::cast(map_word.ToForwardingAddress(site));
|
||||
}
|
||||
|
||||
// We have not validated the allocation site yet, since we have not
|
||||
|
@ -96,13 +96,13 @@ bool Scavenger::MigrateObject(Map map, HeapObject source, HeapObject target,
|
||||
int size,
|
||||
PromotionHeapChoice promotion_heap_choice) {
|
||||
// Copy the content of source to target.
|
||||
target.set_map_word(MapWord::FromMap(map), kRelaxedStore);
|
||||
target.set_map_word(map, kRelaxedStore);
|
||||
heap()->CopyBlock(target.address() + kTaggedSize,
|
||||
source.address() + kTaggedSize, size - kTaggedSize);
|
||||
|
||||
// This release CAS is paired with the load acquire in ScavengeObject.
|
||||
if (!source.release_compare_and_swap_map_word(
|
||||
MapWord::FromMap(map), MapWord::FromForwardingAddress(target))) {
|
||||
if (!source.release_compare_and_swap_map_word_forwarded(MapWord::FromMap(map),
|
||||
target)) {
|
||||
// Other task migrated the object.
|
||||
return false;
|
||||
}
|
||||
@ -141,7 +141,7 @@ CopyAndForwardResult Scavenger::SemiSpaceCopyObject(
|
||||
if (!self_success) {
|
||||
allocator_.FreeLast(NEW_SPACE, target, object_size);
|
||||
MapWord map_word = object.map_word(kAcquireLoad);
|
||||
HeapObjectReference::Update(slot, map_word.ToForwardingAddress());
|
||||
HeapObjectReference::Update(slot, map_word.ToForwardingAddress(object));
|
||||
DCHECK(!Heap::InFromPage(*slot));
|
||||
return Heap::InToPage(*slot)
|
||||
? CopyAndForwardResult::SUCCESS_YOUNG_GENERATION
|
||||
@ -189,7 +189,7 @@ CopyAndForwardResult Scavenger::PromoteObject(Map map, THeapObjectSlot slot,
|
||||
if (!self_success) {
|
||||
allocator_.FreeLast(OLD_SPACE, target, object_size);
|
||||
MapWord map_word = object.map_word(kAcquireLoad);
|
||||
HeapObjectReference::Update(slot, map_word.ToForwardingAddress());
|
||||
HeapObjectReference::Update(slot, map_word.ToForwardingAddress(object));
|
||||
DCHECK(!Heap::InFromPage(*slot));
|
||||
return Heap::InToPage(*slot)
|
||||
? CopyAndForwardResult::SUCCESS_YOUNG_GENERATION
|
||||
@ -223,8 +223,8 @@ bool Scavenger::HandleLargeObject(Map map, HeapObject object, int object_size,
|
||||
BasicMemoryChunk::FromHeapObject(object)->InNewLargeObjectSpace())) {
|
||||
DCHECK_EQ(NEW_LO_SPACE,
|
||||
MemoryChunk::FromHeapObject(object)->owner_identity());
|
||||
if (object.release_compare_and_swap_map_word(
|
||||
MapWord::FromMap(map), MapWord::FromForwardingAddress(object))) {
|
||||
if (object.release_compare_and_swap_map_word_forwarded(
|
||||
MapWord::FromMap(map), object)) {
|
||||
surviving_new_large_objects_.insert({object, map});
|
||||
promoted_size_ += object_size;
|
||||
if (object_fields == ObjectFields::kMaybePointers) {
|
||||
@ -324,25 +324,23 @@ SlotCallbackResult Scavenger::EvacuateShortcutCandidate(Map map,
|
||||
HeapObjectReference::Update(slot, first);
|
||||
|
||||
if (!Heap::InYoungGeneration(first)) {
|
||||
object.set_map_word(MapWord::FromForwardingAddress(first), kReleaseStore);
|
||||
object.set_map_word_forwarded(first, kReleaseStore);
|
||||
return REMOVE_SLOT;
|
||||
}
|
||||
|
||||
MapWord first_word = first.map_word(kAcquireLoad);
|
||||
if (first_word.IsForwardingAddress()) {
|
||||
HeapObject target = first_word.ToForwardingAddress();
|
||||
HeapObject target = first_word.ToForwardingAddress(first);
|
||||
|
||||
HeapObjectReference::Update(slot, target);
|
||||
object.set_map_word(MapWord::FromForwardingAddress(target),
|
||||
kReleaseStore);
|
||||
object.set_map_word_forwarded(target, kReleaseStore);
|
||||
return Heap::InYoungGeneration(target) ? KEEP_SLOT : REMOVE_SLOT;
|
||||
}
|
||||
Map first_map = first_word.ToMap();
|
||||
SlotCallbackResult result = EvacuateObjectDefault(
|
||||
first_map, slot, first, first.SizeFromMap(first_map),
|
||||
Map::ObjectFieldsFrom(first_map.visitor_id()));
|
||||
object.set_map_word(MapWord::FromForwardingAddress(slot.ToHeapObject()),
|
||||
kReleaseStore);
|
||||
object.set_map_word_forwarded(slot.ToHeapObject(), kReleaseStore);
|
||||
return result;
|
||||
}
|
||||
DCHECK_EQ(ObjectFields::kMaybePointers,
|
||||
@ -423,7 +421,7 @@ SlotCallbackResult Scavenger::ScavengeObject(THeapObjectSlot p,
|
||||
// If the first word is a forwarding address, the object has already been
|
||||
// copied.
|
||||
if (first_word.IsForwardingAddress()) {
|
||||
HeapObject dest = first_word.ToForwardingAddress();
|
||||
HeapObject dest = first_word.ToForwardingAddress(object);
|
||||
HeapObjectReference::Update(p, dest);
|
||||
DCHECK_IMPLIES(Heap::InYoungGeneration(dest),
|
||||
Heap::InToPage(dest) || Heap::IsLargeObject(dest));
|
||||
|
@ -296,7 +296,7 @@ class GlobalHandlesWeakRootsUpdatingVisitor final : public RootVisitor {
|
||||
CHECK(Heap::InFromPage(heap_object));
|
||||
MapWord first_word = heap_object.map_word(kRelaxedLoad);
|
||||
CHECK(first_word.IsForwardingAddress());
|
||||
HeapObject dest = first_word.ToForwardingAddress();
|
||||
HeapObject dest = first_word.ToForwardingAddress(heap_object);
|
||||
HeapObjectReference::Update(FullHeapObjectSlot(p), dest);
|
||||
CHECK_IMPLIES(Heap::InYoungGeneration(dest),
|
||||
Heap::InToPage(dest) || Heap::IsLargeObject(dest));
|
||||
@ -552,7 +552,7 @@ void ScavengerCollector::HandleSurvivingNewLargeObjects() {
|
||||
Map map = update_info.second;
|
||||
// Order is important here. We have to re-install the map to have access
|
||||
// to meta-data like size during page promotion.
|
||||
object.set_map_word(MapWord::FromMap(map), kRelaxedStore);
|
||||
object.set_map_word(map, kRelaxedStore);
|
||||
|
||||
if (is_compacting && marking_state->IsBlack(object) &&
|
||||
MarkCompactCollector::IsOnEvacuationCandidate(map)) {
|
||||
|
@ -60,8 +60,8 @@ class HeapObject : public Object {
|
||||
|
||||
// Compare-and-swaps map word using release store, returns true if the map
|
||||
// word was actually swapped.
|
||||
inline bool release_compare_and_swap_map_word(MapWord old_map_word,
|
||||
MapWord new_map_word);
|
||||
inline bool release_compare_and_swap_map_word_forwarded(
|
||||
MapWord old_map_word, HeapObject new_target_object);
|
||||
|
||||
// Initialize the map immediately after the object is allocated.
|
||||
// Do not use this outside Heap.
|
||||
@ -71,11 +71,13 @@ class HeapObject : public Object {
|
||||
// During garbage collection, the map word of a heap object does not
|
||||
// necessarily contain a map pointer.
|
||||
DECL_RELAXED_GETTER(map_word, MapWord)
|
||||
inline void set_map_word(MapWord map_word, RelaxedStoreTag);
|
||||
inline void set_map_word(Map map, RelaxedStoreTag);
|
||||
inline void set_map_word_forwarded(HeapObject target_object, RelaxedStoreTag);
|
||||
|
||||
// Access the map word using acquire load and release store.
|
||||
DECL_ACQUIRE_GETTER(map_word, MapWord)
|
||||
inline void set_map_word(MapWord map_word, ReleaseStoreTag);
|
||||
inline void set_map_word(Map map, ReleaseStoreTag);
|
||||
inline void set_map_word_forwarded(HeapObject target_object, ReleaseStoreTag);
|
||||
|
||||
// This method exists to help remove GetIsolate/GetHeap from HeapObject, in a
|
||||
// way that doesn't require passing Isolate/Heap down huge call chains or to
|
||||
|
@ -725,34 +725,41 @@ Map MapWord::ToMap() const {
|
||||
}
|
||||
|
||||
bool MapWord::IsForwardingAddress() const {
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
// When external code space is enabled forwarding pointers are encoded as
|
||||
// Smi representing a diff from the source object address in kObjectAlignment
|
||||
// chunks.
|
||||
return HAS_SMI_TAG(value_);
|
||||
#else
|
||||
return (value_ & kForwardingTagMask) == kForwardingTag;
|
||||
#endif // V8_EXTERNAL_CODE_SPACE
|
||||
}
|
||||
|
||||
MapWord MapWord::FromForwardingAddress(HeapObject object) {
|
||||
MapWord MapWord::FromForwardingAddress(HeapObject map_word_host,
|
||||
HeapObject object) {
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
// When external code space is enabled forwarding pointers are encoded as
|
||||
// Smi representing a diff from the source object address in kObjectAlignment
|
||||
// chunks.
|
||||
intptr_t diff = static_cast<intptr_t>(object.ptr() - map_word_host.ptr());
|
||||
DCHECK(IsAligned(diff, kObjectAlignment));
|
||||
MapWord map_word(Smi::FromIntptr(diff / kObjectAlignment).ptr());
|
||||
DCHECK(map_word.IsForwardingAddress());
|
||||
return map_word;
|
||||
#else
|
||||
return MapWord(object.ptr() - kHeapObjectTag);
|
||||
#endif // V8_EXTERNAL_CODE_SPACE
|
||||
}
|
||||
|
||||
HeapObject MapWord::ToForwardingAddress() {
|
||||
DCHECK(IsForwardingAddress());
|
||||
HeapObject obj = HeapObject::FromAddress(value_);
|
||||
// For objects allocated outside of the main pointer compression cage the
|
||||
// variant with explicit cage base must be used.
|
||||
DCHECK_IMPLIES(V8_EXTERNAL_CODE_SPACE_BOOL, !IsCodeSpaceObject(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
HeapObject MapWord::ToForwardingAddress(PtrComprCageBase host_cage_base) {
|
||||
HeapObject MapWord::ToForwardingAddress(HeapObject map_word_host) {
|
||||
DCHECK(IsForwardingAddress());
|
||||
#ifdef V8_EXTERNAL_CODE_SPACE
|
||||
// Recompress value_ using proper host_cage_base and compression scheme
|
||||
// since the map word is decompressed using the default compression scheme
|
||||
// in an assumption it'll contain Map pointer.
|
||||
// TODO(v8:11880): this code must be updated once a different scheme is used
|
||||
// for external code fields.
|
||||
Tagged_t compressed = V8HeapCompressionScheme::CompressTagged(value_);
|
||||
Address value = V8HeapCompressionScheme::DecompressTaggedPointer(
|
||||
host_cage_base, compressed);
|
||||
return HeapObject::FromAddress(value);
|
||||
// When external code space is enabled forwarding pointers are encoded as
|
||||
// Smi representing a diff from the source object address in kObjectAlignment
|
||||
// chunks.
|
||||
intptr_t diff = static_cast<intptr_t>(Smi(value_).value()) * kObjectAlignment;
|
||||
Address address = map_word_host.address() + diff;
|
||||
return HeapObject::FromAddress(address);
|
||||
#else
|
||||
return HeapObject::FromAddress(value_);
|
||||
#endif // V8_EXTERNAL_CODE_SPACE
|
||||
@ -866,7 +873,7 @@ void HeapObject::set_map(Map value, MemoryOrder order, VerificationMode mode) {
|
||||
HeapVerifier::VerifyObjectLayoutChange(heap, *this, value);
|
||||
}
|
||||
}
|
||||
set_map_word(MapWord::FromMap(value), order);
|
||||
set_map_word(value, order);
|
||||
#ifndef V8_DISABLE_WRITE_BARRIERS
|
||||
if (!value.is_null()) {
|
||||
if (emit_write_barrier == EmitWriteBarrier::kYes) {
|
||||
@ -880,8 +887,7 @@ void HeapObject::set_map(Map value, MemoryOrder order, VerificationMode mode) {
|
||||
}
|
||||
|
||||
void HeapObject::set_map_after_allocation(Map value, WriteBarrierMode mode) {
|
||||
MapWord mapword = MapWord::FromMap(value);
|
||||
set_map_word(mapword, kRelaxedStore);
|
||||
set_map_word(value, kRelaxedStore);
|
||||
#ifndef V8_DISABLE_WRITE_BARRIERS
|
||||
if (mode != SKIP_WRITE_BARRIER) {
|
||||
DCHECK(!value.is_null());
|
||||
@ -913,8 +919,14 @@ MapWord HeapObject::map_word(PtrComprCageBase cage_base,
|
||||
return MapField::Relaxed_Load_Map_Word(cage_base, *this);
|
||||
}
|
||||
|
||||
void HeapObject::set_map_word(MapWord map_word, RelaxedStoreTag) {
|
||||
MapField::Relaxed_Store_Map_Word(*this, map_word);
|
||||
void HeapObject::set_map_word(Map map, RelaxedStoreTag) {
|
||||
MapField::Relaxed_Store_Map_Word(*this, MapWord::FromMap(map));
|
||||
}
|
||||
|
||||
void HeapObject::set_map_word_forwarded(HeapObject target_object,
|
||||
RelaxedStoreTag) {
|
||||
MapField::Relaxed_Store_Map_Word(
|
||||
*this, MapWord::FromForwardingAddress(*this, target_object));
|
||||
}
|
||||
|
||||
MapWord HeapObject::map_word(AcquireLoadTag tag) const {
|
||||
@ -930,14 +942,21 @@ MapWord HeapObject::map_word(PtrComprCageBase cage_base,
|
||||
return MapField::Acquire_Load_No_Unpack(cage_base, *this);
|
||||
}
|
||||
|
||||
void HeapObject::set_map_word(MapWord map_word, ReleaseStoreTag) {
|
||||
MapField::Release_Store_Map_Word(*this, map_word);
|
||||
void HeapObject::set_map_word(Map map, ReleaseStoreTag) {
|
||||
MapField::Release_Store_Map_Word(*this, MapWord::FromMap(map));
|
||||
}
|
||||
|
||||
bool HeapObject::release_compare_and_swap_map_word(MapWord old_map_word,
|
||||
MapWord new_map_word) {
|
||||
Tagged_t result =
|
||||
MapField::Release_CompareAndSwap(*this, old_map_word, new_map_word);
|
||||
void HeapObject::set_map_word_forwarded(HeapObject target_object,
|
||||
ReleaseStoreTag) {
|
||||
MapField::Release_Store_Map_Word(
|
||||
*this, MapWord::FromForwardingAddress(*this, target_object));
|
||||
}
|
||||
|
||||
bool HeapObject::release_compare_and_swap_map_word_forwarded(
|
||||
MapWord old_map_word, HeapObject new_target_object) {
|
||||
Tagged_t result = MapField::Release_CompareAndSwap(
|
||||
*this, old_map_word,
|
||||
MapWord::FromForwardingAddress(*this, new_target_object));
|
||||
return result == static_cast<Tagged_t>(old_map_word.ptr());
|
||||
}
|
||||
|
||||
|
@ -869,6 +869,16 @@ V8_INLINE static bool HasWeakHeapObjectTag(const Object value) {
|
||||
// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
|
||||
// encoded in the first word. The class MapWord is an abstraction of the
|
||||
// value in a heap object's first word.
|
||||
//
|
||||
// When external code space is enabled forwarding pointers are encoded as
|
||||
// Smi values representing a diff from the source or map word host object
|
||||
// address in kObjectAlignment chunks. Such a representation has the following
|
||||
// properties:
|
||||
// a) it can hold both positive an negative diffs for full pointer compression
|
||||
// cage size (HeapObject address has only valuable 30 bits while Smis have
|
||||
// 31 bits),
|
||||
// b) it's independent of the pointer compression base and pointer compression
|
||||
// scheme.
|
||||
class MapWord {
|
||||
public:
|
||||
// Normal state: the map word contains a map pointer.
|
||||
@ -888,16 +898,11 @@ class MapWord {
|
||||
inline bool IsForwardingAddress() const;
|
||||
|
||||
// Create a map word from a forwarding address.
|
||||
static inline MapWord FromForwardingAddress(HeapObject object);
|
||||
static inline MapWord FromForwardingAddress(HeapObject map_word_host,
|
||||
HeapObject object);
|
||||
|
||||
// View this map word as a forwarding address. The parameterless version
|
||||
// is allowed to be used for objects allocated in the main pointer compression
|
||||
// cage, while the second variant uses the value of the cage base explicitly
|
||||
// and thus can be used in situations where one has to deal with both cases.
|
||||
// Note, that the parameterless version is preferred because it avoids
|
||||
// unnecessary recompressions.
|
||||
inline HeapObject ToForwardingAddress();
|
||||
inline HeapObject ToForwardingAddress(PtrComprCageBase host_cage_base);
|
||||
// View this map word as a forwarding address.
|
||||
inline HeapObject ToForwardingAddress(HeapObject map_word_host);
|
||||
|
||||
inline Address ptr() { return value_; }
|
||||
|
||||
|
@ -76,7 +76,7 @@ void StringForwardingTable::Block::UpdateAfterEvacuation(
|
||||
DCHECK(!object.InSharedWritableHeap());
|
||||
MapWord map_word = object.map_word(kRelaxedLoad);
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
HeapObject forwarded_object = map_word.ToForwardingAddress();
|
||||
HeapObject forwarded_object = map_word.ToForwardingAddress(object);
|
||||
record(index)->set_original_string(forwarded_object);
|
||||
} else {
|
||||
record(index)->set_original_string(deleted_element());
|
||||
|
Loading…
Reference in New Issue
Block a user