| 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());
|
| }
|
|
|
|
|
|
|