diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index 133fb24c40..30332f5133 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc @@ -2404,11 +2404,10 @@ void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { const int header = TransitionArray::kProtoTransitionHeaderSize; int new_number_of_transitions = 0; for (int i = 0; i < number_of_transitions; i++) { - Object* cached_map = prototype_transitions->get(header + i); - if (IsMarked(cached_map)) { + Object* cell = prototype_transitions->get(header + i); + if (!WeakCell::cast(cell)->cleared()) { if (new_number_of_transitions != i) { - prototype_transitions->set(header + new_number_of_transitions, - cached_map, SKIP_WRITE_BARRIER); + prototype_transitions->set(header + new_number_of_transitions, cell); } new_number_of_transitions++; } diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index d1d52a4c7a..7f83f483ba 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -571,13 +571,8 @@ void StaticMarkingVisitor::MarkTransitionArray( if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return; if (transitions->HasPrototypeTransitions()) { - // Mark prototype transitions array but do not push it onto marking - // stack, this will make references from it weak. We will clean dead - // prototype transitions in ClearNonLiveReferences. - Object** slot = transitions->GetPrototypeTransitionsSlot(); - HeapObject* obj = HeapObject::cast(*slot); - heap->mark_compact_collector()->RecordSlot(slot, slot, obj); - StaticVisitor::MarkObjectWithoutPush(heap, obj); + StaticVisitor::VisitPointer(heap, + transitions->GetPrototypeTransitionsSlot()); } int num_transitions = TransitionArray::NumberOfTransitions(transitions); diff --git a/src/transitions.cc b/src/transitions.cc index 63bb7fa68f..c39534bbb5 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -233,17 +233,19 @@ bool TransitionArray::CanHaveMoreTransitions(Handle map) { // static -Handle TransitionArray::PutPrototypeTransition(Handle map, - Handle prototype, - Handle target_map) { +void TransitionArray::PutPrototypeTransition(Handle map, + Handle prototype, + Handle target_map) { DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); // Don't cache prototype transition if this map is either shared, or a map of // a prototype. - if (map->is_prototype_map()) return map; - if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map; + if (map->is_prototype_map()) return; + if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return; const int header = kProtoTransitionHeaderSize; + Handle target_cell = Map::WeakCellForMap(target_map); + Handle cache(GetPrototypeTransitions(*map)); int capacity = cache->length() - header; int transitions = NumberOfPrototypeTransitions(*cache) + 1; @@ -251,7 +253,7 @@ Handle TransitionArray::PutPrototypeTransition(Handle map, if (transitions > capacity) { // Grow array by factor 2 up to MaxCachedPrototypeTransitions. int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); - if (new_capacity == capacity) return map; + if (new_capacity == capacity) return; cache = FixedArray::CopySize(cache, header + new_capacity); if (capacity < 0) { @@ -267,10 +269,8 @@ Handle TransitionArray::PutPrototypeTransition(Handle map, int last = NumberOfPrototypeTransitions(*cache); int entry = header + last; - cache->set(entry, *target_map); + cache->set(entry, *target_cell); SetNumberOfPrototypeTransitions(*cache, last + 1); - - return map; } @@ -281,8 +281,12 @@ Handle TransitionArray::GetPrototypeTransition(Handle map, FixedArray* cache = GetPrototypeTransitions(*map); int number_of_transitions = NumberOfPrototypeTransitions(cache); for (int i = 0; i < number_of_transitions; i++) { - Map* target = Map::cast(cache->get(kProtoTransitionHeaderSize + i)); - if (target->prototype() == *prototype) return handle(target); + WeakCell* target_cell = + WeakCell::cast(cache->get(kProtoTransitionHeaderSize + i)); + if (!target_cell->cleared() && + Map::cast(target_cell->value())->prototype() == *prototype) { + return handle(Map::cast(target_cell->value())); + } } return Handle(); } @@ -436,8 +440,9 @@ void TransitionArray::TraverseTransitionTreeInternal(Map* map, FixedArray* proto_trans = transitions->GetPrototypeTransitions(); for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { int index = TransitionArray::kProtoTransitionHeaderSize + i; - TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), - callback, data); + WeakCell* cell = WeakCell::cast(proto_trans->get(index)); + TraverseTransitionTreeInternal(Map::cast(cell->value()), callback, + data); } } for (int i = 0; i < transitions->number_of_transitions(); ++i) { diff --git a/src/transitions.h b/src/transitions.h index 1cb91a222e..b0aab9502e 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -92,9 +92,8 @@ class TransitionArray: public FixedArray { // 0: finger - index of the first free cell in the cache // 1 + i: target map static const int kMaxCachedPrototypeTransitions = 256; - static Handle PutPrototypeTransition(Handle map, - Handle prototype, - Handle target_map); + static void PutPrototypeTransition(Handle map, Handle prototype, + Handle target_map); static Handle GetPrototypeTransition(Handle map, Handle prototype); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index f0dc643fc6..0a4cf2b1e4 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -2521,7 +2521,8 @@ TEST(PrototypeTransitionClearing) { TransitionArray::GetPrototypeTransitions(baseObject->map()); for (int i = initialTransitions; i < initialTransitions + transitions; i++) { int j = TransitionArray::kProtoTransitionHeaderSize + i; - CHECK(trans->get(j)->IsMap()); + CHECK(trans->get(j)->IsWeakCell()); + CHECK(WeakCell::cast(trans->get(j))->value()->IsMap()); } // Make sure next prototype is placed on an old-space evacuation candidate.