Commit 8c376b46 authored by ulan's avatar ulan Committed by Commit bot

Optimize clearing of map transitions.

Instead of iterating the whole map space to find dead transitions,
look in weak cell list and transition array list.

Simple transitions are in the weak cell list.

Full transitions are in the transitions array list.

BUG=chromium:554488
LOG=NO

Review URL: https://codereview.chromium.org/1488593003

Cr-Commit-Position: refs/heads/master@{#32684}
parent 14613c16
...@@ -541,10 +541,10 @@ void GCTracer::PrintNVP() const { ...@@ -541,10 +541,10 @@ void GCTracer::PrintNVP() const {
"weakcollection_process=%.1f " "weakcollection_process=%.1f "
"weakcollection_clear=%.1f " "weakcollection_clear=%.1f "
"weakcollection_abort=%.1f " "weakcollection_abort=%.1f "
"weakcells=%.1f " "clear=%1f"
"nonlive_refs=%.1f " "clear_weakcell=%.1f "
"extract_dependent_code=%.1f " "clear_map=%.1f "
"deopt_dependent_code=%.1f " "clear_dependent_code=%.1f "
"steps_count=%d " "steps_count=%d "
"steps_took=%.1f " "steps_took=%.1f "
"longest_step=%.1f " "longest_step=%.1f "
...@@ -613,10 +613,10 @@ void GCTracer::PrintNVP() const { ...@@ -613,10 +613,10 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MC_WEAKCOLLECTION_PROCESS], current_.scopes[Scope::MC_WEAKCOLLECTION_PROCESS],
current_.scopes[Scope::MC_WEAKCOLLECTION_CLEAR], current_.scopes[Scope::MC_WEAKCOLLECTION_CLEAR],
current_.scopes[Scope::MC_WEAKCOLLECTION_ABORT], current_.scopes[Scope::MC_WEAKCOLLECTION_ABORT],
current_.scopes[Scope::MC_WEAKCELL], current_.scopes[Scope::MC_CLEAR],
current_.scopes[Scope::MC_NONLIVEREFERENCES], current_.scopes[Scope::MC_CLEAR_WEAKCELL],
current_.scopes[Scope::MC_EXTRACT_DEPENDENT_CODE], current_.scopes[Scope::MC_CLEAR_MAP],
current_.scopes[Scope::MC_DEOPT_DEPENDENT_CODE], current_.scopes[Scope::MC_CLEAR_DEPENDENT_CODE],
current_.incremental_marking_steps, current_.incremental_marking_steps,
current_.incremental_marking_duration, current_.incremental_marking_duration,
current_.longest_incremental_marking_step, current_.longest_incremental_marking_step,
......
...@@ -130,10 +130,10 @@ class GCTracer { ...@@ -130,10 +130,10 @@ class GCTracer {
MC_WEAKCOLLECTION_PROCESS, MC_WEAKCOLLECTION_PROCESS,
MC_WEAKCOLLECTION_CLEAR, MC_WEAKCOLLECTION_CLEAR,
MC_WEAKCOLLECTION_ABORT, MC_WEAKCOLLECTION_ABORT,
MC_WEAKCELL, MC_CLEAR,
MC_EXTRACT_DEPENDENT_CODE, MC_CLEAR_WEAKCELL,
MC_NONLIVEREFERENCES, MC_CLEAR_MAP,
MC_DEOPT_DEPENDENT_CODE, MC_CLEAR_DEPENDENT_CODE,
MC_FLUSH_CODE, MC_FLUSH_CODE,
SCAVENGER_CODE_FLUSH_CANDIDATES, SCAVENGER_CODE_FLUSH_CANDIDATES,
SCAVENGER_OBJECT_GROUPS, SCAVENGER_OBJECT_GROUPS,
......
...@@ -2486,7 +2486,7 @@ AllocationResult Heap::AllocateWeakCell(HeapObject* value) { ...@@ -2486,7 +2486,7 @@ AllocationResult Heap::AllocateWeakCell(HeapObject* value) {
} }
result->set_map_no_write_barrier(weak_cell_map()); result->set_map_no_write_barrier(weak_cell_map());
WeakCell::cast(result)->initialize(value); WeakCell::cast(result)->initialize(value);
WeakCell::cast(result)->clear_next(this); WeakCell::cast(result)->clear_next(the_hole_value());
return result; return result;
} }
......
...@@ -649,6 +649,7 @@ void IncrementalMarking::ProcessWeakCells() { ...@@ -649,6 +649,7 @@ void IncrementalMarking::ProcessWeakCells() {
DCHECK(!finalize_marking_completed_); DCHECK(!finalize_marking_completed_);
DCHECK(IsMarking()); DCHECK(IsMarking());
Object* the_hole_value = heap()->the_hole_value();
Object* weak_cell_obj = heap()->encountered_weak_cells(); Object* weak_cell_obj = heap()->encountered_weak_cells();
Object* weak_cell_head = Smi::FromInt(0); Object* weak_cell_head = Smi::FromInt(0);
WeakCell* prev_weak_cell_obj = NULL; WeakCell* prev_weak_cell_obj = NULL;
...@@ -668,7 +669,7 @@ void IncrementalMarking::ProcessWeakCells() { ...@@ -668,7 +669,7 @@ void IncrementalMarking::ProcessWeakCells() {
prev_weak_cell_obj->set_next(weak_cell->next()); prev_weak_cell_obj->set_next(weak_cell->next());
} }
weak_cell_obj = weak_cell->next(); weak_cell_obj = weak_cell->next();
weak_cell->clear_next(heap()); weak_cell->clear_next(the_hole_value);
} else { } else {
if (weak_cell_head == Smi::FromInt(0)) { if (weak_cell_head == Smi::FromInt(0)) {
weak_cell_head = weak_cell; weak_cell_head = weak_cell;
......
This diff is collapsed.
...@@ -649,15 +649,20 @@ class MarkCompactCollector { ...@@ -649,15 +649,20 @@ class MarkCompactCollector {
// heap object. // heap object.
static bool IsUnmarkedHeapObject(Object** p); static bool IsUnmarkedHeapObject(Object** p);
// Map transitions from a live map to a dead map must be killed. // Clear non-live references in weak cells, transition and descriptor arrays,
// We replace them with a null descriptor, with the same key. // and deoptimize dependent code of non-live maps.
void ClearNonLiveReferences(); void ClearNonLiveReferences();
void ClearNonLiveMapTransitions(Map* map); void MarkDependentCodeForDeoptimization(DependentCode* list);
void ClearMapTransitions(Map* map, Map* dead_transition); // Find non-live targets of simple transitions in the given list. Clear
bool ClearMapBackPointer(Map* map); // transitions to non-live targets and if needed trim descriptors arrays.
void MarkDependentCodeListForDeoptimization(DependentCode* list_head); void ClearSimpleMapTransitions(Object* non_live_map_list);
void TrimDescriptorArray(Map* map, DescriptorArray* descriptors, void ClearSimpleMapTransition(Map* map, Map* dead_transition);
int number_of_own_descriptors); // Compact every array in the global list of transition arrays and
// trim the corresponding descriptor array if a transition target is non-live.
void ClearFullMapTransitions();
bool CompactTransitionArray(Map* map, TransitionArray* transitions,
DescriptorArray* descriptors);
void TrimDescriptorArray(Map* map, DescriptorArray* descriptors);
void TrimEnumCache(Map* map, DescriptorArray* descriptors); void TrimEnumCache(Map* map, DescriptorArray* descriptors);
// Mark all values associated with reachable keys in weak collections // Mark all values associated with reachable keys in weak collections
...@@ -674,10 +679,10 @@ class MarkCompactCollector { ...@@ -674,10 +679,10 @@ class MarkCompactCollector {
// collections when incremental marking is aborted. // collections when incremental marking is aborted.
void AbortWeakCollections(); void AbortWeakCollections();
void ProcessAndClearWeakCells(); void ClearWeakCells(Object** non_live_map_list,
DependentCode** dependent_code_list);
void AbortWeakCells(); void AbortWeakCells();
void ProcessAndClearTransitionArrays();
void AbortTransitionArrays(); void AbortTransitionArrays();
// After all reachable objects have been marked, those entries within // After all reachable objects have been marked, those entries within
...@@ -685,9 +690,6 @@ class MarkCompactCollector { ...@@ -685,9 +690,6 @@ class MarkCompactCollector {
// trimming or clearing out the entire optimized code map. // trimming or clearing out the entire optimized code map.
void ProcessAndClearOptimizedCodeMaps(); void ProcessAndClearOptimizedCodeMaps();
// Process non-live references in maps and optimized code.
void ProcessWeakReferences();
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Phase 2: Sweeping to clear mark bits and free non-live objects for // Phase 2: Sweeping to clear mark bits and free non-live objects for
// a non-compacting collection. // a non-compacting collection.
......
...@@ -359,9 +359,17 @@ void StaticMarkingVisitor<StaticVisitor>::VisitWeakCell(Map* map, ...@@ -359,9 +359,17 @@ void StaticMarkingVisitor<StaticVisitor>::VisitWeakCell(Map* map,
template <typename StaticVisitor> template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray( void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray(
Map* map, HeapObject* object) { Map* map, HeapObject* object) {
typedef FlexibleBodyVisitor<StaticVisitor, TransitionArray::BodyDescriptor,
int> TransitionArrayBodyVisitor;
TransitionArray* array = TransitionArray::cast(object); TransitionArray* array = TransitionArray::cast(object);
Heap* heap = array->GetHeap();
// Visit strong references.
if (array->HasPrototypeTransitions()) {
StaticVisitor::VisitPointer(heap, array,
array->GetPrototypeTransitionsSlot());
}
int num_transitions = TransitionArray::NumberOfTransitions(array);
for (int i = 0; i < num_transitions; ++i) {
StaticVisitor::VisitPointer(heap, array, array->GetKeySlot(i));
}
// Enqueue the array in linked list of encountered transition arrays if it is // Enqueue the array in linked list of encountered transition arrays if it is
// not already in the list. // not already in the list.
if (array->next_link()->IsUndefined()) { if (array->next_link()->IsUndefined()) {
...@@ -370,8 +378,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray( ...@@ -370,8 +378,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray(
UPDATE_WEAK_WRITE_BARRIER); UPDATE_WEAK_WRITE_BARRIER);
heap->set_encountered_transition_arrays(array); heap->set_encountered_transition_arrays(array);
} }
// TODO(ulan): Move MarkTransitionArray logic here.
TransitionArrayBodyVisitor::Visit(map, object);
} }
...@@ -540,11 +546,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitBytecodeArray( ...@@ -540,11 +546,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitBytecodeArray(
template <typename StaticVisitor> template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(Heap* heap, void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(Heap* heap,
Map* map) { Map* map) {
Object* raw_transitions = map->raw_transitions();
if (TransitionArray::IsFullTransitionArray(raw_transitions)) {
MarkTransitionArray(heap, TransitionArray::cast(raw_transitions));
}
// Since descriptor arrays are potentially shared, ensure that only the // Since descriptor arrays are potentially shared, ensure that only the
// descriptors that belong to this map are marked. The first time a non-empty // descriptors that belong to this map are marked. The first time a non-empty
// descriptor array is marked, its header is also visited. The slot holding // descriptor array is marked, its header is also visited. The slot holding
...@@ -577,23 +578,6 @@ void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(Heap* heap, ...@@ -577,23 +578,6 @@ void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(Heap* heap,
} }
template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray(
Heap* heap, TransitionArray* transitions) {
if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return;
if (transitions->HasPrototypeTransitions()) {
StaticVisitor::VisitPointer(heap, transitions,
transitions->GetPrototypeTransitionsSlot());
}
int num_transitions = TransitionArray::NumberOfTransitions(transitions);
for (int i = 0; i < num_transitions; ++i) {
StaticVisitor::VisitPointer(heap, transitions, transitions->GetKeySlot(i));
}
}
template <typename StaticVisitor> template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::MarkOptimizedCodeMap( void StaticMarkingVisitor<StaticVisitor>::MarkOptimizedCodeMap(
Heap* heap, FixedArray* code_map) { Heap* heap, FixedArray* code_map) {
......
...@@ -372,10 +372,8 @@ class StaticMarkingVisitor : public StaticVisitorBase { ...@@ -372,10 +372,8 @@ class StaticMarkingVisitor : public StaticVisitorBase {
INLINE(static void VisitNativeContext(Map* map, HeapObject* object)); INLINE(static void VisitNativeContext(Map* map, HeapObject* object));
INLINE(static void VisitBytecodeArray(Map* map, HeapObject* object)); INLINE(static void VisitBytecodeArray(Map* map, HeapObject* object));
// Mark pointers in a Map and its TransitionArray together, possibly // Mark pointers in a Map treating some elements of the descriptor array weak.
// treating transitions or back pointers weak.
static void MarkMapContents(Heap* heap, Map* map); static void MarkMapContents(Heap* heap, Map* map);
static void MarkTransitionArray(Heap* heap, TransitionArray* transitions);
// Mark pointers in the optimized code map that should act as strong // Mark pointers in the optimized code map that should act as strong
// references, possibly treating some entries weak. // references, possibly treating some entries weak.
......
...@@ -2060,8 +2060,9 @@ void WeakCell::set_next(Object* val, WriteBarrierMode mode) { ...@@ -2060,8 +2060,9 @@ void WeakCell::set_next(Object* val, WriteBarrierMode mode) {
} }
void WeakCell::clear_next(Heap* heap) { void WeakCell::clear_next(Object* the_hole_value) {
set_next(heap->the_hole_value(), SKIP_WRITE_BARRIER); DCHECK_EQ(GetHeap()->the_hole_value(), the_hole_value);
set_next(the_hole_value, SKIP_WRITE_BARRIER);
} }
...@@ -5489,8 +5490,7 @@ void Map::set_prototype_info(Object* value, WriteBarrierMode mode) { ...@@ -5489,8 +5490,7 @@ void Map::set_prototype_info(Object* value, WriteBarrierMode mode) {
void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || DCHECK((value->IsMap() && GetBackPointer()->IsUndefined()));
(value->IsMap() && GetBackPointer()->IsUndefined()));
DCHECK(!value->IsMap() || DCHECK(!value->IsMap() ||
Map::cast(value)->GetConstructor() == constructor_or_backpointer()); Map::cast(value)->GetConstructor() == constructor_or_backpointer());
set_constructor_or_backpointer(value, mode); set_constructor_or_backpointer(value, mode);
......
...@@ -9463,7 +9463,7 @@ class WeakCell : public HeapObject { ...@@ -9463,7 +9463,7 @@ class WeakCell : public HeapObject {
DECL_ACCESSORS(next, Object) DECL_ACCESSORS(next, Object)
inline void clear_next(Heap* heap); inline void clear_next(Object* the_hole_value);
inline bool next_cleared(); inline bool next_cleared();
......
...@@ -1919,7 +1919,7 @@ class UnlinkWeakCellScope { ...@@ -1919,7 +1919,7 @@ class UnlinkWeakCellScope {
if (object->IsWeakCell()) { if (object->IsWeakCell()) {
weak_cell_ = WeakCell::cast(object); weak_cell_ = WeakCell::cast(object);
next_ = weak_cell_->next(); next_ = weak_cell_->next();
weak_cell_->clear_next(object->GetHeap()); weak_cell_->clear_next(object->GetHeap()->the_hole_value());
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment