Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Unified Diff: src/heap/mark-compact.cc

Issue 871253005: Use weak cells in dependent code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/objects-visiting-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
}
« no previous file with comments | « src/heap/mark-compact.h ('k') | src/heap/objects-visiting-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698