| Index: src/objects-visiting-inl.h
|
| diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
|
| index 33af4038b6b0aedfd29609f412d7261a287de0db..25c1cb75ec69fe43d8f6809b458bcbcdea3c2d60 100644
|
| --- a/src/objects-visiting-inl.h
|
| +++ b/src/objects-visiting-inl.h
|
| @@ -262,12 +262,9 @@ void StaticMarkingVisitor<StaticVisitor>::VisitMap(
|
| map_object->ClearCodeCache(heap);
|
| }
|
|
|
| - // When map collection is enabled we have to mark through map's
|
| - // transitions and back pointers in a special way to make these links
|
| - // weak. Only maps for subclasses of JSReceiver can have transitions.
|
| - STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
|
| - if (FLAG_collect_maps &&
|
| - map_object->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
|
| + // When map collection is enabled we have to mark through map's transitions
|
| + // and back pointers in a special way to make these links weak.
|
| + if (FLAG_collect_maps && map_object->CanTransition()) {
|
| MarkMapContents(heap, map_object);
|
| } else {
|
| StaticVisitor::VisitPointers(heap,
|
| @@ -288,7 +285,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCode(
|
| if (FLAG_age_code && !Serializer::enabled()) {
|
| code->MakeOlder(heap->mark_compact_collector()->marking_parity());
|
| }
|
| - code->CodeIterateBody<StaticVisitor>(heap);
|
| + code->CodeIterateBody<StaticVisitor, Code::SKIP_EMBEDDED_MAPS>(heap);
|
| }
|
|
|
|
|
| @@ -395,6 +392,15 @@ void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(
|
| ASSERT(transitions->IsMap() || transitions->IsUndefined());
|
| }
|
|
|
| + // Mark prototype dependent codes array but do not push it onto marking
|
| + // stack, this will make references from it weak. We will clean dead
|
| + // dead codes when we iterate over maps in ClearNonLiveTransitions.
|
| + Object** slot = HeapObject::RawField(reinterpret_cast<HeapObject*>(map),
|
| + Map::kDependentCodesOffset);
|
| + HeapObject* obj = HeapObject::cast(*slot);
|
| + heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
|
| + StaticVisitor::MarkObjectWithoutPush(heap, obj);
|
| +
|
| // Mark the pointer fields of the Map. Since the transitions array has
|
| // been marked already, it is fine that one of these fields contains a
|
| // pointer to it.
|
| @@ -638,8 +644,13 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
|
| RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
|
| RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
|
|
|
| - // There are two places where we iterate code bodies: here and the
|
| - // templated CodeIterateBody (below). They should be kept in sync.
|
| + // There are two places where we iterate code bodies: here and the non-
|
| + // templated CodeIterateBody (above). They should be kept in sync. The only
|
| + // difference between the two versions is in handling of embedded maps.
|
| + // Static marking visitors do not visit embedded maps, but most of the non-
|
| + // static visitors need to visit embedded maps. Non-static visitor can skip
|
| + // embedded maps by overriding VisitEmbeddedPointer, like
|
| + // VerifyMarkingVisitor does.
|
| IteratePointer(v, kRelocationInfoOffset);
|
| IteratePointer(v, kHandlerTableOffset);
|
| IteratePointer(v, kDeoptimizationDataOffset);
|
| @@ -652,7 +663,7 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
|
| }
|
|
|
|
|
| -template<typename StaticVisitor>
|
| +template<typename StaticVisitor, Code::EmbeddedMapVisitMode map_visit_mode>
|
| void Code::CodeIterateBody(Heap* heap) {
|
| int mode_mask = RelocInfo::kCodeTargetMask |
|
| RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
| @@ -662,8 +673,13 @@ void Code::CodeIterateBody(Heap* heap) {
|
| RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
|
| RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
|
|
|
| - // There are two places where we iterate code bodies: here and the
|
| - // non-templated CodeIterateBody (above). They should be kept in sync.
|
| + // There are two places where we iterate code bodies: here and the non-
|
| + // templated CodeIterateBody (above). They should be kept in sync. The only
|
| + // difference between the two versions is in handling of embedded maps.
|
| + // Static marking visitors do not visit embedded maps, but most of the non-
|
| + // static visitors need to visit embedded maps. Non-static visitor can skip
|
| + // embedded maps by overriding VisitEmbeddedPointer, like
|
| + // VerifyMarkingVisitor does.
|
| StaticVisitor::VisitPointer(
|
| heap,
|
| reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
|
| @@ -678,8 +694,20 @@ void Code::CodeIterateBody(Heap* heap) {
|
| reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset));
|
|
|
| RelocIterator it(this, mode_mask);
|
| - for (; !it.done(); it.next()) {
|
| - it.rinfo()->template Visit<StaticVisitor>(heap);
|
| + if (map_visit_mode == SKIP_EMBEDDED_MAPS && kind() == OPTIMIZED_FUNCTION) {
|
| + // Treat embedded maps in optimized code as weak.
|
| + for (; !it.done(); it.next()) {
|
| + RelocInfo* info = it.rinfo();
|
| + if (!RelocInfo::IsEmbeddedObject(info->rmode()) ||
|
| + !info->target_object()->IsMap() ||
|
| + !Map::cast(info->target_object())->CanTransition()) {
|
| + it.rinfo()->template Visit<StaticVisitor>(heap);
|
| + }
|
| + }
|
| + } else {
|
| + for (; !it.done(); it.next()) {
|
| + it.rinfo()->template Visit<StaticVisitor>(heap);
|
| + }
|
| }
|
| }
|
|
|
|
|