Chromium Code Reviews| Index: src/mark-compact.cc |
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
| index 0bf82863d745e2e12f5c55b23508a24bda0e07c6..754056d365ff8b9f4087da2cbcfb09b499686000 100644 |
| --- a/src/mark-compact.cc |
| +++ b/src/mark-compact.cc |
| @@ -71,6 +71,7 @@ void MarkCompactCollector::CollectGarbage() { |
| // Make sure that Prepare() has been called. The individual steps below will |
| // update the state as they proceed. |
| ASSERT(state_ == PREPARE_GC); |
| + ASSERT(heap()->encountered_weak_maps() == Smi::FromInt(0)); |
| // Prepare has selected whether to compact the old generation or not. |
| // Tell the tracer. |
| @@ -80,6 +81,8 @@ void MarkCompactCollector::CollectGarbage() { |
| if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| + ClearWeakMaps(); |
| + |
| SweepLargeObjectSpace(); |
| if (IsCompacting()) { |
| @@ -407,6 +410,8 @@ class StaticMarkingVisitor : public StaticVisitorBase { |
| table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); |
| table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); |
| + table_.Register(kVisitJSWeakMap, &VisitJSWeakMap); |
| + |
| table_.Register(kVisitOddball, |
| &FixedBodyVisitor<StaticMarkingVisitor, |
| Oddball::BodyDescriptor, |
| @@ -556,6 +561,33 @@ class StaticMarkingVisitor : public StaticVisitorBase { |
| StructBodyDescriptor, |
| void> StructObjectVisitor; |
| + static void VisitJSWeakMap(Map* map, HeapObject* object) { |
| + Heap* heap = map->heap(); |
| + JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object); |
| + |
| + // Enqueue weak map in linked list of encountered weak maps. |
| + ASSERT(weak_map->next() == Smi::FromInt(0)); |
| + weak_map->set_next(heap->encountered_weak_maps()); |
| + heap->set_encountered_weak_maps(weak_map); |
| + |
| + // Skip visiting the backing hash table containing the mappings. |
| + int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object); |
| + BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( |
| + map->heap(), |
| + object, |
| + JSWeakMap::BodyDescriptor::kStartOffset, |
| + JSWeakMap::kTableOffset); |
| + BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( |
| + map->heap(), |
| + object, |
| + JSWeakMap::kTableOffset + kPointerSize, |
| + object_size); |
| + |
| + // Mark the backing hash table without pushing it on the marking stack. |
| + ASSERT(!weak_map->unchecked_table()->IsMarked()); |
| + heap->mark_compact_collector()->SetMark(weak_map->unchecked_table()); |
|
Vyacheslav Egorov (Chromium)
2011/08/02 16:32:00
What about marking unchecked_table()->map() or at
Michael Starzinger
2011/08/03 08:47:05
Done.
|
| + } |
| + |
| static void VisitCode(Map* map, HeapObject* object) { |
| reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( |
| map->heap()); |
| @@ -1369,20 +1401,26 @@ void MarkCompactCollector::MarkImplicitRefGroups() { |
| // marking stack have been marked, or are overflowed in the heap. |
| void MarkCompactCollector::EmptyMarkingStack() { |
| while (!marking_stack_.is_empty()) { |
| - HeapObject* object = marking_stack_.Pop(); |
| - ASSERT(object->IsHeapObject()); |
| - ASSERT(heap()->Contains(object)); |
| - ASSERT(object->IsMarked()); |
| - ASSERT(!object->IsOverflowed()); |
| - |
| - // Because the object is marked, we have to recover the original map |
| - // pointer and use it to mark the object's body. |
| - MapWord map_word = object->map_word(); |
| - map_word.ClearMark(); |
| - Map* map = map_word.ToMap(); |
| - MarkObject(map); |
| + while (!marking_stack_.is_empty()) { |
| + HeapObject* object = marking_stack_.Pop(); |
| + ASSERT(object->IsHeapObject()); |
| + ASSERT(heap()->Contains(object)); |
| + ASSERT(object->IsMarked()); |
| + ASSERT(!object->IsOverflowed()); |
| - StaticMarkingVisitor::IterateBody(map, object); |
| + // Because the object is marked, we have to recover the original map |
| + // pointer and use it to mark the object's body. |
| + MapWord map_word = object->map_word(); |
| + map_word.ClearMark(); |
| + Map* map = map_word.ToMap(); |
| + MarkObject(map); |
| + |
| + StaticMarkingVisitor::IterateBody(map, object); |
| + } |
| + |
| + // Process encountered weak maps, mark objects only reachable by those |
| + // weak maps and repeat until fix-point is reached. |
| + ProcessWeakMaps(); |
| } |
| } |
| @@ -1735,6 +1773,41 @@ void MarkCompactCollector::ClearNonLiveTransitions() { |
| } |
| } |
| + |
| +void MarkCompactCollector::ProcessWeakMaps() { |
| + Object* weak_map_obj = heap()->encountered_weak_maps(); |
| + while (weak_map_obj != Smi::FromInt(0)) { |
| + ASSERT(HeapObject::cast(weak_map_obj)->IsMarked()); |
| + JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
| + ObjectHashTable* table = weak_map->unchecked_table(); |
| + for (int i = 0; i < table->Capacity(); i++) { |
| + if (HeapObject::cast(table->KeyAt(i))->IsMarked()) { |
| + Object* value = table->ValueAt(i); |
| + StaticMarkingVisitor::MarkObjectByPointer(heap(), &value); |
|
Vyacheslav Egorov (Chromium)
2011/08/02 16:32:00
MarkObjectByPointer might modify the value (short
Michael Starzinger
2011/08/03 08:47:05
Done.
|
| + } |
| + } |
| + weak_map_obj = weak_map->next(); |
| + } |
| +} |
| + |
| + |
| +void MarkCompactCollector::ClearWeakMaps() { |
| + Object* weak_map_obj = heap()->encountered_weak_maps(); |
| + while (weak_map_obj != Smi::FromInt(0)) { |
| + ASSERT(HeapObject::cast(weak_map_obj)->IsMarked()); |
| + JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
| + ObjectHashTable* table = weak_map->unchecked_table(); |
| + for (int i = 0; i < table->Capacity(); i++) { |
| + if (!HeapObject::cast(table->KeyAt(i))->IsMarked()) { |
| + table->RemoveEntry(i, heap()); |
| + } |
| + } |
| + weak_map_obj = weak_map->next(); |
| + weak_map->set_next(Smi::FromInt(0)); |
| + } |
| + heap()->set_encountered_weak_maps(Smi::FromInt(0)); |
| +} |
| + |
| // ------------------------------------------------------------------------- |
| // Phase 2: Encode forwarding addresses. |
| // When compacting, forwarding addresses for objects in old space and map |