diff --git a/src/heap/concurrent-marking.cc b/src/heap/concurrent-marking.cc index 95b3a230ab..540566a35d 100644 --- a/src/heap/concurrent-marking.cc +++ b/src/heap/concurrent-marking.cc @@ -215,11 +215,12 @@ class ConcurrentMarkingVisitor final } int VisitTransitionArray(Map* map, TransitionArray* array) { - if (marking_state_.IsGrey(array)) { - // TODO(ulan): process transition arrays. - bailout_.Push(array); - } - return 0; + if (!ShouldVisit(array)) return 0; + VisitMapPointer(array, array->map_slot()); + int size = TransitionArray::BodyDescriptor::SizeOf(map, array); + TransitionArray::BodyDescriptor::IterateBody(array, size, this); + weak_objects_->transition_arrays.Push(task_id_, array); + return size; } int VisitWeakCell(Map* map, WeakCell* object) { diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index f573d0a9cd..53e1d46055 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -2878,12 +2878,8 @@ bool MarkCompactCollector::CompactTransitionArray( RecordSlot(transitions, key_slot, key); Object* raw_target = transitions->GetRawTarget(i); transitions->SetTarget(transition_index, raw_target); - // Maps are not compacted, but for cached handlers the target slot - // must be recorded. - if (!raw_target->IsMap()) { - Object** target_slot = transitions->GetTargetSlot(transition_index); - RecordSlot(transitions, target_slot, raw_target); - } + Object** target_slot = transitions->GetTargetSlot(transition_index); + RecordSlot(transitions, target_slot, raw_target); } transition_index++; } diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index 64532e74bb..0548ab4abf 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -194,23 +194,10 @@ template int MarkingVisitor::VisitTransitionArray( Map* map, TransitionArray* array) { ConcreteVisitor* visitor = static_cast(this); - // Visit strong references. - if (array->HasPrototypeTransitions()) { - visitor->VisitPointer(array, array->GetPrototypeTransitionsSlot()); - } - int num_transitions = array->number_of_entries(); - for (int i = 0; i < num_transitions; ++i) { - visitor->VisitPointer(array, array->GetKeySlot(i)); - // A TransitionArray can hold maps or (transitioning StoreIC) handlers. - // Maps have custom weak handling; handlers (which in turn weakly point - // to maps) are marked strongly for now, and will be cleared during - // compaction when the maps they refer to are dead. - if (!array->GetRawTarget(i)->IsMap()) { - visitor->VisitPointer(array, array->GetTargetSlot(i)); - } - } + int size = TransitionArray::BodyDescriptor::SizeOf(map, array); + TransitionArray::BodyDescriptor::IterateBody(array, size, visitor); collector_->AddTransitionArray(array); - return TransitionArray::BodyDescriptor::SizeOf(map, array); + return size; } template diff --git a/src/transitions-inl.h b/src/transitions-inl.h index b9690e8b86..b75980e09c 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -119,8 +119,9 @@ PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) { // static Map* TransitionsAccessor::GetTargetFromRaw(Object* raw) { - if (raw->IsMap()) return Map::cast(raw); - if (raw->IsTuple3()) { + if (raw->IsWeakCell()) { + return Map::cast(WeakCell::cast(raw)->value()); + } else if (raw->IsTuple3()) { return Map::cast(StoreHandler::GetTuple3TransitionCell(raw)->value()); } else { DCHECK(raw->IsFixedArray()); @@ -162,6 +163,7 @@ Map* TransitionsAccessor::GetTarget(int transition_number) { } void TransitionArray::SetTarget(int transition_number, Object* value) { + DCHECK(!value->IsMap()); DCHECK(transition_number < number_of_transitions()); set(ToTargetIndex(transition_number), value); } diff --git a/src/transitions.cc b/src/transitions.cc index 90f2cc01ca..aeb7acbd55 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -68,12 +68,14 @@ void TransitionsAccessor::Insert(Handle name, Handle target, SimpleTransitionFlag flag) { DCHECK(!map_handle_.is_null()); Isolate* isolate = map_->GetIsolate(); + Handle weak_cell_with_target = Map::WeakCellForMap(target); + Reload(); target->SetBackPointer(map_); // If the map doesn't have any transitions at all yet, install the new one. if (encoding() == kUninitialized) { if (flag == SIMPLE_PROPERTY_TRANSITION) { - ReplaceTransitions(*Map::WeakCellForMap(target)); + ReplaceTransitions(*weak_cell_with_target); return; } // If the flag requires a full TransitionArray, allocate one. @@ -94,7 +96,7 @@ void TransitionsAccessor::Insert(Handle name, Handle target, if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && old_details.kind() == new_details.kind() && old_details.attributes() == new_details.attributes()) { - ReplaceTransitions(*Map::WeakCellForMap(target)); + ReplaceTransitions(*weak_cell_with_target); return; } // Otherwise allocate a full TransitionArray with slack for a new entry. @@ -103,10 +105,8 @@ void TransitionsAccessor::Insert(Handle name, Handle target, Reload(); simple_transition = GetSimpleTransition(); if (simple_transition != nullptr) { - Object* value = raw_transitions_->IsWeakCell() - ? WeakCell::cast(raw_transitions_)->value() - : raw_transitions_; - result->Set(0, GetSimpleTransitionKey(simple_transition), value); + result->Set(0, GetSimpleTransitionKey(simple_transition), + raw_transitions_); } else { result->SetNumberOfTransitions(0); } @@ -138,7 +138,7 @@ void TransitionsAccessor::Insert(Handle name, Handle target, &insertion_index); // If an existing entry was found, overwrite it and return. if (index != kNotFound) { - array->SetTarget(index, *target); + array->SetTarget(index, *weak_cell_with_target); return; } @@ -154,7 +154,7 @@ void TransitionsAccessor::Insert(Handle name, Handle target, array->SetTarget(index, array->GetRawTarget(index - 1)); } array->SetKey(index, *name); - array->SetTarget(index, *target); + array->SetTarget(index, *weak_cell_with_target); SLOW_DCHECK(array->IsSortedNoDuplicates()); return; } @@ -202,7 +202,7 @@ void TransitionsAccessor::Insert(Handle name, Handle target, for (int i = 0; i < insertion_index; ++i) { result->Set(i, array->GetKey(i), array->GetRawTarget(i)); } - result->Set(insertion_index, *name, *target); + result->Set(insertion_index, *name, *weak_cell_with_target); for (int i = insertion_index; i < number_of_transitions; ++i) { result->Set(i + 1, array->GetKey(i), array->GetRawTarget(i)); } @@ -456,6 +456,7 @@ void TransitionsAccessor::PutPrototypeTransition(Handle prototype, int entry = header + last; Handle target_cell = Map::WeakCellForMap(target_map); + Reload(); // Reload after possible GC. cache->set(entry, *target_cell); TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1); } @@ -553,18 +554,19 @@ void TransitionsAccessor::EnsureHasFullTransitionArray() { int nof = encoding() == kUninitialized ? 0 : 1; Handle result = TransitionArray::Allocate(map_->GetIsolate(), nof); - DisallowHeapAllocation no_gc; Reload(); // Reload after possible GC. if (nof == 1) { - Map* target = GetSimpleTransition(); - if (target == nullptr) { + if (encoding() == kUninitialized) { // If allocation caused GC and cleared the target, trim the new array. result->Shrink(TransitionArray::ToKeyIndex(0)); result->SetNumberOfTransitions(0); } else { // Otherwise populate the new array. - Name* key = GetSimpleTransitionKey(target); - result->Set(0, key, target); + Handle target(GetSimpleTransition()); + Handle weak_cell_with_target = Map::WeakCellForMap(target); + Reload(); // Reload after possible GC. + Name* key = GetSimpleTransitionKey(*target); + result->Set(0, key, *weak_cell_with_target); } } ReplaceTransitions(*result);