[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:
Ulan Degenbaev 2021-03-04 10:36:34 +01:00 committed by Commit Bot
parent 807807658e
commit ae9aeb5aa4
5 changed files with 29 additions and 48 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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,