[heap] Remove snapshot-based visitation of JSObjects in the marker
Now that double unboxing is removed, the concurrent marker can directly visit all JSObjects without snapshotting them first. Bug: v8:11422 Change-Id: Ib5cb4d0b39fd2654f4e417a09c9497d134fea1ff Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2732009 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Cr-Commit-Position: refs/heads/master@{#73211}
This commit is contained in:
parent
807807658e
commit
ae9aeb5aa4
@ -215,12 +215,16 @@ class ConcurrentMarkingVisitor final
|
||||
|
||||
template <typename T, typename TBodyDescriptor = typename T::BodyDescriptor>
|
||||
int VisitJSObjectSubclass(Map map, T object) {
|
||||
if (!ShouldVisit(object)) return 0;
|
||||
int size = TBodyDescriptor::SizeOf(map, object);
|
||||
int used_size = map.UsedInstanceSize();
|
||||
DCHECK_LE(used_size, size);
|
||||
DCHECK_GE(used_size, JSObject::GetHeaderSize(map));
|
||||
return VisitPartiallyWithSnapshot<T, TBodyDescriptor>(map, object,
|
||||
used_size, size);
|
||||
this->VisitMapPointer(object);
|
||||
// It is important to visit only the used field and ignore the slack fields
|
||||
// because the slack fields may be trimmed concurrently.
|
||||
TBodyDescriptor::IterateBody(map, object, used_size, this);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -252,17 +256,11 @@ class ConcurrentMarkingVisitor final
|
||||
|
||||
template <typename T>
|
||||
int VisitFullyWithSnapshot(Map map, T object) {
|
||||
if (!ShouldVisit(object)) return 0;
|
||||
using TBodyDescriptor = typename T::BodyDescriptor;
|
||||
int size = TBodyDescriptor::SizeOf(map, object);
|
||||
return VisitPartiallyWithSnapshot<T, TBodyDescriptor>(map, object, size,
|
||||
size);
|
||||
}
|
||||
|
||||
template <typename T, typename TBodyDescriptor = typename T::BodyDescriptor>
|
||||
int VisitPartiallyWithSnapshot(Map map, T object, int used_size, int size) {
|
||||
const SlotSnapshot& snapshot =
|
||||
MakeSlotSnapshot<T, TBodyDescriptor>(map, object, used_size);
|
||||
if (!ShouldVisit(object)) return 0;
|
||||
MakeSlotSnapshot<T, TBodyDescriptor>(map, object, size);
|
||||
VisitPointersInSnapshot(object, snapshot);
|
||||
return size;
|
||||
}
|
||||
|
@ -3575,28 +3575,30 @@ void Heap::VerifyObjectLayoutChange(HeapObject object, Map new_map) {
|
||||
// use object->set_map_after_allocation() to initialize its map.
|
||||
if (pending_layout_change_object_.is_null()) {
|
||||
if (object.IsJSObject()) {
|
||||
DCHECK(!object.map().TransitionRequiresSynchronizationWithGC(new_map));
|
||||
} else if (object.IsString() &&
|
||||
(new_map == ReadOnlyRoots(this).thin_string_map() ||
|
||||
new_map == ReadOnlyRoots(this).thin_one_byte_string_map())) {
|
||||
// Without double unboxing all in-object fields of a JSObject are tagged.
|
||||
return;
|
||||
}
|
||||
if (object.IsString() &&
|
||||
(new_map == ReadOnlyRoots(this).thin_string_map() ||
|
||||
new_map == ReadOnlyRoots(this).thin_one_byte_string_map())) {
|
||||
// When transitioning a string to ThinString,
|
||||
// Heap::NotifyObjectLayoutChange doesn't need to be invoked because only
|
||||
// tagged fields are introduced.
|
||||
} else {
|
||||
// Check that the set of slots before and after the transition match.
|
||||
SlotCollectingVisitor old_visitor;
|
||||
object.IterateFast(&old_visitor);
|
||||
MapWord old_map_word = object.map_word();
|
||||
// Temporarily set the new map to iterate new slots.
|
||||
object.set_map_word(MapWord::FromMap(new_map));
|
||||
SlotCollectingVisitor new_visitor;
|
||||
object.IterateFast(&new_visitor);
|
||||
// Restore the old map.
|
||||
object.set_map_word(old_map_word);
|
||||
DCHECK_EQ(new_visitor.number_of_slots(), old_visitor.number_of_slots());
|
||||
for (int i = 0; i < new_visitor.number_of_slots(); i++) {
|
||||
DCHECK(new_visitor.slot(i) == old_visitor.slot(i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Check that the set of slots before and after the transition match.
|
||||
SlotCollectingVisitor old_visitor;
|
||||
object.IterateFast(&old_visitor);
|
||||
MapWord old_map_word = object.map_word();
|
||||
// Temporarily set the new map to iterate new slots.
|
||||
object.set_map_word(MapWord::FromMap(new_map));
|
||||
SlotCollectingVisitor new_visitor;
|
||||
object.IterateFast(&new_visitor);
|
||||
// Restore the old map.
|
||||
object.set_map_word(old_map_word);
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
DCHECK_EQ(pending_layout_change_object_, object);
|
||||
|
@ -2918,10 +2918,6 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
|
||||
|
||||
Heap* heap = isolate->heap();
|
||||
|
||||
// Invalidate slots manually later in case of tagged to untagged translation.
|
||||
// In all other cases the recorded slot remains dereferenceable.
|
||||
heap->NotifyObjectLayoutChange(*object, no_gc, InvalidateRecordedSlots::kNo);
|
||||
|
||||
// Copy (real) inobject properties. If necessary, stop at number_of_fields to
|
||||
// avoid overwriting |one_pointer_filler_map|.
|
||||
int limit = std::min(inobject, number_of_fields);
|
||||
@ -3035,11 +3031,6 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
|
||||
|
||||
Heap* heap = isolate->heap();
|
||||
|
||||
// Invalidate slots manually later in case the new map has in-object
|
||||
// properties. If not, it is not possible to store an untagged value
|
||||
// in a recorded slot.
|
||||
heap->NotifyObjectLayoutChange(*object, no_gc, InvalidateRecordedSlots::kNo);
|
||||
|
||||
// Resize the object in the heap if necessary.
|
||||
int old_instance_size = map->instance_size();
|
||||
int new_instance_size = new_map->instance_size();
|
||||
|
@ -500,12 +500,6 @@ MaybeHandle<Map> Map::CopyWithConstant(Isolate* isolate, Handle<Map> map,
|
||||
PropertyConstness::kConst, representation, flag);
|
||||
}
|
||||
|
||||
bool Map::TransitionRequiresSynchronizationWithGC(Map target) const {
|
||||
int inobject = NumberOfFields();
|
||||
int target_inobject = target.NumberOfFields();
|
||||
return target_inobject < inobject;
|
||||
}
|
||||
|
||||
bool Map::InstancesNeedRewriting(Map target) const {
|
||||
int target_number_of_fields = target.NumberOfFields();
|
||||
int target_inobject = target.GetInObjectProperties();
|
||||
|
@ -481,10 +481,6 @@ class Map : public HeapObject {
|
||||
|
||||
bool HasOutOfObjectProperties() const;
|
||||
|
||||
// Returns true if transition to the given map requires special
|
||||
// synchronization with the concurrent marker.
|
||||
bool TransitionRequiresSynchronizationWithGC(Map target) const;
|
||||
|
||||
// TODO(ishell): candidate with JSObject::MigrateToMap().
|
||||
bool InstancesNeedRewriting(Map target) const;
|
||||
bool InstancesNeedRewriting(Map target, int target_number_of_fields,
|
||||
|
Loading…
Reference in New Issue
Block a user