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 {
"weakcollection_process=%.1f "
"weakcollection_clear=%.1f "
"weakcollection_abort=%.1f "
"weakcells=%.1f "
"nonlive_refs=%.1f "
"extract_dependent_code=%.1f "
"deopt_dependent_code=%.1f "
"clear=%1f"
"clear_weakcell=%.1f "
"clear_map=%.1f "
"clear_dependent_code=%.1f "
"steps_count=%d "
"steps_took=%.1f "
"longest_step=%.1f "
......@@ -613,10 +613,10 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MC_WEAKCOLLECTION_PROCESS],
current_.scopes[Scope::MC_WEAKCOLLECTION_CLEAR],
current_.scopes[Scope::MC_WEAKCOLLECTION_ABORT],
current_.scopes[Scope::MC_WEAKCELL],
current_.scopes[Scope::MC_NONLIVEREFERENCES],
current_.scopes[Scope::MC_EXTRACT_DEPENDENT_CODE],
current_.scopes[Scope::MC_DEOPT_DEPENDENT_CODE],
current_.scopes[Scope::MC_CLEAR],
current_.scopes[Scope::MC_CLEAR_WEAKCELL],
current_.scopes[Scope::MC_CLEAR_MAP],
current_.scopes[Scope::MC_CLEAR_DEPENDENT_CODE],
current_.incremental_marking_steps,
current_.incremental_marking_duration,
current_.longest_incremental_marking_step,
......
......@@ -130,10 +130,10 @@ class GCTracer {
MC_WEAKCOLLECTION_PROCESS,
MC_WEAKCOLLECTION_CLEAR,
MC_WEAKCOLLECTION_ABORT,
MC_WEAKCELL,
MC_EXTRACT_DEPENDENT_CODE,
MC_NONLIVEREFERENCES,
MC_DEOPT_DEPENDENT_CODE,
MC_CLEAR,
MC_CLEAR_WEAKCELL,
MC_CLEAR_MAP,
MC_CLEAR_DEPENDENT_CODE,
MC_FLUSH_CODE,
SCAVENGER_CODE_FLUSH_CANDIDATES,
SCAVENGER_OBJECT_GROUPS,
......
......@@ -2486,7 +2486,7 @@ AllocationResult Heap::AllocateWeakCell(HeapObject* value) {
}
result->set_map_no_write_barrier(weak_cell_map());
WeakCell::cast(result)->initialize(value);
WeakCell::cast(result)->clear_next(this);
WeakCell::cast(result)->clear_next(the_hole_value());
return result;
}
......
......@@ -649,6 +649,7 @@ void IncrementalMarking::ProcessWeakCells() {
DCHECK(!finalize_marking_completed_);
DCHECK(IsMarking());
Object* the_hole_value = heap()->the_hole_value();
Object* weak_cell_obj = heap()->encountered_weak_cells();
Object* weak_cell_head = Smi::FromInt(0);
WeakCell* prev_weak_cell_obj = NULL;
......@@ -668,7 +669,7 @@ void IncrementalMarking::ProcessWeakCells() {
prev_weak_cell_obj->set_next(weak_cell->next());
}
weak_cell_obj = weak_cell->next();
weak_cell->clear_next(heap());
weak_cell->clear_next(the_hole_value);
} else {
if (weak_cell_head == Smi::FromInt(0)) {
weak_cell_head = weak_cell;
......
This diff is collapsed.
......@@ -649,15 +649,20 @@ class MarkCompactCollector {
// heap object.
static bool IsUnmarkedHeapObject(Object** p);
// Map transitions from a live map to a dead map must be killed.
// We replace them with a null descriptor, with the same key.
// Clear non-live references in weak cells, transition and descriptor arrays,
// and deoptimize dependent code of non-live maps.
void ClearNonLiveReferences();
void ClearNonLiveMapTransitions(Map* map);
void ClearMapTransitions(Map* map, Map* dead_transition);
bool ClearMapBackPointer(Map* map);
void MarkDependentCodeListForDeoptimization(DependentCode* list_head);
void TrimDescriptorArray(Map* map, DescriptorArray* descriptors,
int number_of_own_descriptors);
void MarkDependentCodeForDeoptimization(DependentCode* list);
// Find non-live targets of simple transitions in the given list. Clear
// transitions to non-live targets and if needed trim descriptors arrays.
void ClearSimpleMapTransitions(Object* non_live_map_list);
void ClearSimpleMapTransition(Map* map, Map* dead_transition);
// 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);
// Mark all values associated with reachable keys in weak collections
......@@ -674,10 +679,10 @@ class MarkCompactCollector {
// collections when incremental marking is aborted.
void AbortWeakCollections();
void ProcessAndClearWeakCells();
void ClearWeakCells(Object** non_live_map_list,
DependentCode** dependent_code_list);
void AbortWeakCells();
void ProcessAndClearTransitionArrays();
void AbortTransitionArrays();
// After all reachable objects have been marked, those entries within
......@@ -685,9 +690,6 @@ class MarkCompactCollector {
// trimming or clearing out the entire optimized code map.
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
// a non-compacting collection.
......
......@@ -359,9 +359,17 @@ void StaticMarkingVisitor<StaticVisitor>::VisitWeakCell(Map* map,
template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray(
Map* map, HeapObject* object) {
typedef FlexibleBodyVisitor<StaticVisitor, TransitionArray::BodyDescriptor,
int> TransitionArrayBodyVisitor;
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
// not already in the list.
if (array->next_link()->IsUndefined()) {
......@@ -370,8 +378,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitTransitionArray(
UPDATE_WEAK_WRITE_BARRIER);
heap->set_encountered_transition_arrays(array);
}
// TODO(ulan): Move MarkTransitionArray logic here.
TransitionArrayBodyVisitor::Visit(map, object);
}
......@@ -540,11 +546,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitBytecodeArray(
template <typename StaticVisitor>
void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(Heap* heap,
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
// 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
......@@ -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>
void StaticMarkingVisitor<StaticVisitor>::MarkOptimizedCodeMap(
Heap* heap, FixedArray* code_map) {
......
......@@ -372,10 +372,8 @@ class StaticMarkingVisitor : public StaticVisitorBase {
INLINE(static void VisitNativeContext(Map* map, HeapObject* object));
INLINE(static void VisitBytecodeArray(Map* map, HeapObject* object));
// Mark pointers in a Map and its TransitionArray together, possibly
// treating transitions or back pointers weak.
// Mark pointers in a Map treating some elements of the descriptor array weak.
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
// references, possibly treating some entries weak.
......
......@@ -2060,8 +2060,9 @@ void WeakCell::set_next(Object* val, WriteBarrierMode mode) {
}
void WeakCell::clear_next(Heap* heap) {
set_next(heap->the_hole_value(), SKIP_WRITE_BARRIER);
void WeakCell::clear_next(Object* the_hole_value) {
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) {
void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) ||
(value->IsMap() && GetBackPointer()->IsUndefined()));
DCHECK((value->IsMap() && GetBackPointer()->IsUndefined()));
DCHECK(!value->IsMap() ||
Map::cast(value)->GetConstructor() == constructor_or_backpointer());
set_constructor_or_backpointer(value, mode);
......
......@@ -9463,7 +9463,7 @@ class WeakCell : public HeapObject {
DECL_ACCESSORS(next, Object)
inline void clear_next(Heap* heap);
inline void clear_next(Object* the_hole_value);
inline bool next_cleared();
......
......@@ -1919,7 +1919,7 @@ class UnlinkWeakCellScope {
if (object->IsWeakCell()) {
weak_cell_ = WeakCell::cast(object);
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