Index: src/heap/mark-compact.cc |
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc |
index 122de1d87dd241ba00e5bffc371590b18d1d6418..917e87d75f3221828086686fac15de5e86e391a1 100644 |
--- a/src/heap/mark-compact.cc |
+++ b/src/heap/mark-compact.cc |
@@ -984,85 +984,6 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() { |
} |
-void CodeFlusher::ProcessOptimizedCodeMaps() { |
- STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4); |
- |
- SharedFunctionInfo* holder = optimized_code_map_holder_head_; |
- SharedFunctionInfo* next_holder; |
- |
- while (holder != NULL) { |
- next_holder = GetNextCodeMap(holder); |
- ClearNextCodeMap(holder); |
- |
- // Process context-dependent entries in the optimized code map. |
- FixedArray* code_map = FixedArray::cast(holder->optimized_code_map()); |
- int new_length = SharedFunctionInfo::kEntriesStart; |
- int old_length = code_map->length(); |
- for (int i = SharedFunctionInfo::kEntriesStart; i < old_length; |
- i += SharedFunctionInfo::kEntryLength) { |
- // Each entry contains [ context, code, literals, ast-id ] as fields. |
- STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4); |
- Context* context = |
- Context::cast(code_map->get(i + SharedFunctionInfo::kContextOffset)); |
- HeapObject* code = HeapObject::cast( |
- code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); |
- FixedArray* literals = FixedArray::cast( |
- code_map->get(i + SharedFunctionInfo::kLiteralsOffset)); |
- Smi* ast_id = |
- Smi::cast(code_map->get(i + SharedFunctionInfo::kOsrAstIdOffset)); |
- if (Marking::IsWhite(Marking::MarkBitFrom(context))) continue; |
- DCHECK(Marking::IsBlack(Marking::MarkBitFrom(context))); |
- if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue; |
- DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code))); |
- if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue; |
- DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals))); |
- // Move every slot in the entry and record slots when needed. |
- code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code); |
- code_map->set(new_length + SharedFunctionInfo::kContextOffset, context); |
- code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals); |
- code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id); |
- Object** code_slot = code_map->RawFieldOfElementAt( |
- new_length + SharedFunctionInfo::kCachedCodeOffset); |
- isolate_->heap()->mark_compact_collector()->RecordSlot( |
- code_map, code_slot, *code_slot); |
- Object** context_slot = code_map->RawFieldOfElementAt( |
- new_length + SharedFunctionInfo::kContextOffset); |
- isolate_->heap()->mark_compact_collector()->RecordSlot( |
- code_map, context_slot, *context_slot); |
- Object** literals_slot = code_map->RawFieldOfElementAt( |
- new_length + SharedFunctionInfo::kLiteralsOffset); |
- isolate_->heap()->mark_compact_collector()->RecordSlot( |
- code_map, literals_slot, *literals_slot); |
- new_length += SharedFunctionInfo::kEntryLength; |
- } |
- |
- // Process context-independent entry in the optimized code map. |
- Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex); |
- if (shared_object->IsCode()) { |
- Code* shared_code = Code::cast(shared_object); |
- if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) { |
- code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex); |
- } else { |
- DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code))); |
- Object** slot = |
- code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex); |
- isolate_->heap()->mark_compact_collector()->RecordSlot(code_map, slot, |
- *slot); |
- } |
- } |
- |
- // Trim the optimized code map if entries have been removed. |
- if (new_length < old_length) { |
- holder->TrimOptimizedCodeMap(old_length - new_length); |
- } |
- |
- holder = next_holder; |
- } |
- |
- optimized_code_map_holder_head_ = NULL; |
-} |
- |
- |
void CodeFlusher::EvictCandidate(SharedFunctionInfo* shared_info) { |
// Make sure previous flushing decisions are revisited. |
isolate_->heap()->incremental_marking()->RecordWrites(shared_info); |
@@ -1133,44 +1054,6 @@ void CodeFlusher::EvictCandidate(JSFunction* function) { |
} |
-void CodeFlusher::EvictOptimizedCodeMap(SharedFunctionInfo* code_map_holder) { |
- FixedArray* code_map = |
- FixedArray::cast(code_map_holder->optimized_code_map()); |
- DCHECK(!code_map->get(SharedFunctionInfo::kNextMapIndex)->IsUndefined()); |
- |
- // Make sure previous flushing decisions are revisited. |
- isolate_->heap()->incremental_marking()->RecordWrites(code_map); |
- isolate_->heap()->incremental_marking()->RecordWrites(code_map_holder); |
- |
- if (FLAG_trace_code_flushing) { |
- PrintF("[code-flushing abandons code-map: "); |
- code_map_holder->ShortPrint(); |
- PrintF("]\n"); |
- } |
- |
- SharedFunctionInfo* holder = optimized_code_map_holder_head_; |
- SharedFunctionInfo* next_holder; |
- if (holder == code_map_holder) { |
- next_holder = GetNextCodeMap(code_map_holder); |
- optimized_code_map_holder_head_ = next_holder; |
- ClearNextCodeMap(code_map_holder); |
- } else { |
- while (holder != NULL) { |
- next_holder = GetNextCodeMap(holder); |
- |
- if (next_holder == code_map_holder) { |
- next_holder = GetNextCodeMap(code_map_holder); |
- SetNextCodeMap(holder, next_holder); |
- ClearNextCodeMap(code_map_holder); |
- break; |
- } |
- |
- holder = next_holder; |
- } |
- } |
-} |
- |
- |
void CodeFlusher::EvictJSFunctionCandidates() { |
JSFunction* candidate = jsfunction_candidates_head_; |
JSFunction* next_candidate; |
@@ -1195,18 +1078,6 @@ void CodeFlusher::EvictSharedFunctionInfoCandidates() { |
} |
-void CodeFlusher::EvictOptimizedCodeMaps() { |
- SharedFunctionInfo* holder = optimized_code_map_holder_head_; |
- SharedFunctionInfo* next_holder; |
- while (holder != NULL) { |
- next_holder = GetNextCodeMap(holder); |
- EvictOptimizedCodeMap(holder); |
- holder = next_holder; |
- } |
- DCHECK(optimized_code_map_holder_head_ == NULL); |
-} |
- |
- |
void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) { |
Heap* heap = isolate_->heap(); |
@@ -2234,6 +2105,13 @@ void MarkCompactCollector::AfterMarking() { |
code_flusher_->ProcessCandidates(); |
} |
+ // Process and clear all optimized code maps. |
+ if (!FLAG_flush_optimized_code_cache) { |
+ GCTracer::Scope gc_scope(heap()->tracer(), |
+ GCTracer::Scope::MC_MARK_OPTIMIZED_CODE_MAPS); |
+ ProcessAndClearOptimizedCodeMaps(); |
+ } |
+ |
if (FLAG_track_gc_object_stats) { |
if (FLAG_trace_gc_object_stats) { |
heap()->object_stats_->TraceObjectStats(); |
@@ -2243,6 +2121,72 @@ void MarkCompactCollector::AfterMarking() { |
} |
+void MarkCompactCollector::ProcessAndClearOptimizedCodeMaps() { |
+ SharedFunctionInfo::Iterator iterator(isolate()); |
+ while (SharedFunctionInfo* shared = iterator.Next()) { |
+ if (shared->optimized_code_map()->IsSmi()) continue; |
+ |
+ // Process context-dependent entries in the optimized code map. |
+ FixedArray* code_map = FixedArray::cast(shared->optimized_code_map()); |
+ int new_length = SharedFunctionInfo::kEntriesStart; |
+ int old_length = code_map->length(); |
+ for (int i = SharedFunctionInfo::kEntriesStart; i < old_length; |
+ i += SharedFunctionInfo::kEntryLength) { |
+ // Each entry contains [ context, code, literals, ast-id ] as fields. |
+ STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4); |
+ Context* context = |
+ Context::cast(code_map->get(i + SharedFunctionInfo::kContextOffset)); |
+ HeapObject* code = HeapObject::cast( |
+ code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); |
+ FixedArray* literals = FixedArray::cast( |
+ code_map->get(i + SharedFunctionInfo::kLiteralsOffset)); |
+ Smi* ast_id = |
+ Smi::cast(code_map->get(i + SharedFunctionInfo::kOsrAstIdOffset)); |
+ if (Marking::IsWhite(Marking::MarkBitFrom(context))) continue; |
+ DCHECK(Marking::IsBlack(Marking::MarkBitFrom(context))); |
+ if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue; |
+ DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code))); |
+ if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue; |
+ DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals))); |
+ // Move every slot in the entry and record slots when needed. |
+ code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code); |
+ code_map->set(new_length + SharedFunctionInfo::kContextOffset, context); |
+ code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals); |
+ code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id); |
+ Object** code_slot = code_map->RawFieldOfElementAt( |
+ new_length + SharedFunctionInfo::kCachedCodeOffset); |
+ RecordSlot(code_map, code_slot, *code_slot); |
+ Object** context_slot = code_map->RawFieldOfElementAt( |
+ new_length + SharedFunctionInfo::kContextOffset); |
+ RecordSlot(code_map, context_slot, *context_slot); |
+ Object** literals_slot = code_map->RawFieldOfElementAt( |
+ new_length + SharedFunctionInfo::kLiteralsOffset); |
+ RecordSlot(code_map, literals_slot, *literals_slot); |
+ new_length += SharedFunctionInfo::kEntryLength; |
+ } |
+ |
+ // Process context-independent entry in the optimized code map. |
+ Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex); |
+ if (shared_object->IsCode()) { |
+ Code* shared_code = Code::cast(shared_object); |
+ if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) { |
+ code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex); |
+ } else { |
+ DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code))); |
+ Object** slot = |
+ code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex); |
+ RecordSlot(code_map, slot, *slot); |
+ } |
+ } |
+ |
+ // Trim the optimized code map if entries have been removed. |
+ if (new_length < old_length) { |
+ shared->TrimOptimizedCodeMap(old_length - new_length); |
+ } |
+ } |
+} |
+ |
+ |
void MarkCompactCollector::ClearNonLiveReferences() { |
GCTracer::Scope gc_scope(heap()->tracer(), |
GCTracer::Scope::MC_NONLIVEREFERENCES); |