Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index c48c6f2b6a098f21b1a347a0b4c4303678ee8a5f..e4e525883d50eec5ad3095f88b8ad3000893d580 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -301,10 +301,13 @@ void MarkCompactCollector::CollectGarbage() { |
MarkLiveObjects(); |
DCHECK(heap_->incremental_marking()->IsStopped()); |
- if (FLAG_collect_maps) ClearNonLiveReferences(); |
- |
+ // ClearNonLiveReferences can deoptimize code in dependent code arrays. |
+ // Process weak cells before so that weak cells in dependent code |
+ // arrays are cleared or contain only live code objects. |
ProcessAndClearWeakCells(); |
+ if (FLAG_collect_maps) ClearNonLiveReferences(); |
+ |
ClearWeakCollections(); |
heap_->set_encountered_weak_cells(Smi::FromInt(0)); |
@@ -318,9 +321,7 @@ void MarkCompactCollector::CollectGarbage() { |
SweepSpaces(); |
#ifdef VERIFY_HEAP |
- if (heap()->weak_embedded_objects_verification_enabled()) { |
- VerifyWeakEmbeddedObjectsInCode(); |
- } |
+ VerifyWeakEmbeddedObjectsInCode(); |
if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { |
VerifyOmittedMapChecks(); |
} |
@@ -1958,8 +1959,6 @@ void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
// Handle the string table specially. |
MarkStringTable(visitor); |
- MarkWeakObjectToCodeTable(); |
- |
// There may be overflowed objects in the heap. Visit them now. |
while (marking_deque_.overflowed()) { |
RefillMarkingDeque(); |
@@ -2000,16 +1999,6 @@ void MarkCompactCollector::MarkImplicitRefGroups() { |
} |
-void MarkCompactCollector::MarkWeakObjectToCodeTable() { |
- HeapObject* weak_object_to_code_table = |
- HeapObject::cast(heap()->weak_object_to_code_table()); |
- if (!IsMarked(weak_object_to_code_table)) { |
- MarkBit mark = Marking::MarkBitFrom(weak_object_to_code_table); |
- SetMark(weak_object_to_code_table, mark); |
- } |
-} |
- |
- |
// Mark all objects reachable from the objects on the marking stack. |
// Before: the marking stack contains zero or more heap object pointers. |
// After: the marking stack is empty, and all objects reachable from the |
@@ -2328,67 +2317,29 @@ void MarkCompactCollector::ClearNonLiveReferences() { |
ClearNonLivePrototypeTransitions(map); |
ClearNonLiveMapTransitions(map, map_mark); |
- if (map_mark.Get()) { |
- ClearNonLiveDependentCode(map->dependent_code()); |
- } else { |
- ClearDependentCode(map->dependent_code()); |
+ if (!map_mark.Get()) { |
+ have_code_to_deoptimize_ |= |
+ map->dependent_code()->MarkCodeForDeoptimization( |
+ isolate(), DependentCode::kWeakCodeGroup); |
map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); |
} |
} |
- // Iterate over property cell space, removing dependent code that is not |
- // otherwise kept alive by strong references. |
- HeapObjectIterator cell_iterator(heap_->property_cell_space()); |
- for (HeapObject* cell = cell_iterator.Next(); cell != NULL; |
- cell = cell_iterator.Next()) { |
- if (IsMarked(cell)) { |
- ClearNonLiveDependentCode(PropertyCell::cast(cell)->dependent_code()); |
- } |
- } |
- |
- // Iterate over allocation sites, removing dependent code that is not |
- // otherwise kept alive by strong references. |
- Object* undefined = heap()->undefined_value(); |
- for (Object* site = heap()->allocation_sites_list(); site != undefined; |
- site = AllocationSite::cast(site)->weak_next()) { |
- if (IsMarked(site)) { |
- ClearNonLiveDependentCode(AllocationSite::cast(site)->dependent_code()); |
- } |
- } |
- |
- if (heap_->weak_object_to_code_table()->IsHashTable()) { |
- WeakHashTable* table = |
- WeakHashTable::cast(heap_->weak_object_to_code_table()); |
- uint32_t capacity = table->Capacity(); |
- for (uint32_t i = 0; i < capacity; i++) { |
- uint32_t key_index = table->EntryToIndex(i); |
- Object* key = table->get(key_index); |
- if (!table->IsKey(key)) continue; |
- uint32_t value_index = table->EntryToValueIndex(i); |
- Object* value = table->get(value_index); |
- if (key->IsCell() && !IsMarked(key)) { |
- Cell* cell = Cell::cast(key); |
- Object* object = cell->value(); |
- if (IsMarked(object)) { |
- MarkBit mark = Marking::MarkBitFrom(cell); |
- SetMark(cell, mark); |
- Object** value_slot = HeapObject::RawField(cell, Cell::kValueOffset); |
- RecordSlot(value_slot, value_slot, *value_slot); |
- } |
- } |
- if (IsMarked(key)) { |
- if (!IsMarked(value)) { |
- HeapObject* obj = HeapObject::cast(value); |
- MarkBit mark = Marking::MarkBitFrom(obj); |
- SetMark(obj, mark); |
- } |
- ClearNonLiveDependentCode(DependentCode::cast(value)); |
- } else { |
- ClearDependentCode(DependentCode::cast(value)); |
- table->set(key_index, heap_->the_hole_value()); |
- table->set(value_index, heap_->the_hole_value()); |
- table->ElementRemoved(); |
- } |
+ WeakHashTable* table = heap_->weak_object_to_code_table(); |
+ uint32_t capacity = table->Capacity(); |
+ for (uint32_t i = 0; i < capacity; i++) { |
+ uint32_t key_index = table->EntryToIndex(i); |
+ Object* key = table->get(key_index); |
+ if (!table->IsKey(key)) continue; |
+ uint32_t value_index = table->EntryToValueIndex(i); |
+ Object* value = table->get(value_index); |
+ if (WeakCell::cast(key)->cleared()) { |
+ have_code_to_deoptimize_ |= |
+ DependentCode::cast(value)->MarkCodeForDeoptimization( |
+ isolate(), DependentCode::kWeakCodeGroup); |
+ table->set(key_index, heap_->the_hole_value()); |
+ table->set(value_index, heap_->the_hole_value()); |
+ table->ElementRemoved(); |
} |
} |
} |
@@ -2560,70 +2511,6 @@ void MarkCompactCollector::TrimEnumCache(Map* map, |
} |
-void MarkCompactCollector::ClearDependentCode(DependentCode* entries) { |
- DisallowHeapAllocation no_allocation; |
- DependentCode::GroupStartIndexes starts(entries); |
- int number_of_entries = starts.number_of_entries(); |
- if (number_of_entries == 0) return; |
- int g = DependentCode::kWeakCodeGroup; |
- for (int i = starts.at(g); i < starts.at(g + 1); i++) { |
- // If the entry is compilation info then the map must be alive, |
- // and ClearDependentCode shouldn't be called. |
- DCHECK(entries->is_code_at(i)); |
- Code* code = entries->code_at(i); |
- if (IsMarked(code) && !code->marked_for_deoptimization()) { |
- DependentCode::SetMarkedForDeoptimization( |
- code, static_cast<DependentCode::DependencyGroup>(g)); |
- code->InvalidateEmbeddedObjects(); |
- have_code_to_deoptimize_ = true; |
- } |
- } |
- for (int i = 0; i < number_of_entries; i++) { |
- entries->clear_at(i); |
- } |
-} |
- |
- |
-int MarkCompactCollector::ClearNonLiveDependentCodeInGroup( |
- DependentCode* entries, int group, int start, int end, int new_start) { |
- int survived = 0; |
- for (int i = start; i < end; i++) { |
- Object* obj = entries->object_at(i); |
- DCHECK(obj->IsCode() || IsMarked(obj)); |
- if (IsMarked(obj) && |
- (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { |
- if (new_start + survived != i) { |
- entries->set_object_at(new_start + survived, obj); |
- } |
- Object** slot = entries->slot_at(new_start + survived); |
- RecordSlot(slot, slot, obj); |
- survived++; |
- } |
- } |
- entries->set_number_of_entries( |
- static_cast<DependentCode::DependencyGroup>(group), survived); |
- return survived; |
-} |
- |
- |
-void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { |
- DisallowHeapAllocation no_allocation; |
- DependentCode::GroupStartIndexes starts(entries); |
- int number_of_entries = starts.number_of_entries(); |
- if (number_of_entries == 0) return; |
- int new_number_of_entries = 0; |
- // Go through all groups, remove dead codes and compact. |
- for (int g = 0; g < DependentCode::kGroupCount; g++) { |
- int survived = ClearNonLiveDependentCodeInGroup( |
- entries, g, starts.at(g), starts.at(g + 1), new_number_of_entries); |
- new_number_of_entries += survived; |
- } |
- for (int i = new_number_of_entries; i < number_of_entries; i++) { |
- entries->clear_at(i); |
- } |
-} |
- |
- |
void MarkCompactCollector::ProcessWeakCollections() { |
GCTracer::Scope gc_scope(heap()->tracer(), |
GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); |
@@ -2699,10 +2586,31 @@ void MarkCompactCollector::ProcessAndClearWeakCells() { |
// cannot be a Smi here. |
HeapObject* value = HeapObject::cast(weak_cell->value()); |
if (!MarkCompactCollector::IsMarked(value)) { |
- weak_cell->clear(); |
+ // Cells for new-space objects embedded in optimized code are wrapped in |
+ // WeakCell and put into Heap::weak_object_to_code_table. |
+ // Such cells do not have any strong references but we want to keep them |
+ // alive as long as the cell value is alive. |
+ // TODO(ulan): remove this once we remove Heap::weak_object_to_code_table. |
+ if (value->IsCell()) { |
+ Object* cell_value = Cell::cast(value)->value(); |
+ if (cell_value->IsHeapObject() && |
+ MarkCompactCollector::IsMarked(HeapObject::cast(cell_value))) { |
+ // Resurrect the cell. |
+ MarkBit mark = Marking::MarkBitFrom(value); |
+ SetMark(value, mark); |
+ Object** slot = HeapObject::RawField(value, Cell::kValueOffset); |
+ RecordSlot(slot, slot, *slot); |
+ slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); |
+ RecordSlot(slot, slot, *slot); |
+ } else { |
+ weak_cell->clear(); |
+ } |
+ } else { |
+ weak_cell->clear(); |
+ } |
} else { |
Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); |
- heap()->mark_compact_collector()->RecordSlot(slot, slot, value); |
+ RecordSlot(slot, slot, *slot); |
} |
weak_cell_obj = weak_cell->next(); |
weak_cell->set_next(undefined, SKIP_WRITE_BARRIER); |
@@ -3548,13 +3456,6 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
} |
heap_->string_table()->Iterate(&updating_visitor); |
- updating_visitor.VisitPointer(heap_->weak_object_to_code_table_address()); |
- if (heap_->weak_object_to_code_table()->IsHashTable()) { |
- WeakHashTable* table = |
- WeakHashTable::cast(heap_->weak_object_to_code_table()); |
- table->Iterate(&updating_visitor); |
- table->Rehash(heap_->isolate()->factory()->undefined_value()); |
- } |
// Update pointers from external string table. |
heap_->UpdateReferencesInExternalStringTable( |
@@ -3576,6 +3477,10 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
DCHECK(migration_slots_buffer_ == NULL); |
+ |
+ // The hashing of weak_object_to_code_table is no longer valid. |
+ heap()->weak_object_to_code_table()->Rehash( |
+ heap()->isolate()->factory()->undefined_value()); |
} |