Chromium Code Reviews| Index: src/mark-compact.cc |
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc |
| index 5c91dbfc10f9aef6653085632866c3184eacad57..928c4d2cc45fbbcfddded4051bde5525dedef3dd 100644 |
| --- a/src/mark-compact.cc |
| +++ b/src/mark-compact.cc |
| @@ -73,7 +73,8 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT |
| migration_slots_buffer_(NULL), |
| heap_(NULL), |
| code_flusher_(NULL), |
| - encountered_weak_maps_(NULL) { } |
| + encountered_weak_maps_(NULL), |
| + code_to_deoptimize_(NULL) { } |
| #ifdef VERIFY_HEAP |
| @@ -485,6 +486,15 @@ void MarkCompactCollector::VerifyMarkbitsAreClean() { |
| } |
| +// Return true if the given code is deoptimized or will be deoptimized. |
| +static bool WillBeDeoptimized(Code* code) { |
| + // The gc_metadata field is used as a linked list of code to deopt. |
|
ulan
2013/07/22 09:23:08
Maybe assert that code->gc_metadata() is optimized
titzer
2013/07/23 12:41:00
I've had to rework this function because I was not
|
| + // != 0 implies the code is in the list, undefined means at the end. |
| + return code->gc_metadata() != Smi::FromInt(0) |
| + || code->marked_for_deoptimization(); |
| +} |
| + |
| + |
| void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() { |
| HeapObjectIterator code_iterator(heap()->code_space()); |
| for (HeapObject* obj = code_iterator.Next(); |
| @@ -492,7 +502,7 @@ void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() { |
| obj = code_iterator.Next()) { |
| Code* code = Code::cast(obj); |
| if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; |
| - if (code->marked_for_deoptimization()) continue; |
| + if (WillBeDeoptimized(code)) continue; |
| code->VerifyEmbeddedMapsDependency(); |
| } |
| } |
| @@ -945,14 +955,6 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| } |
| -class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter { |
| - public: |
| - virtual bool TakeFunction(JSFunction* function) { |
| - return function->code()->marked_for_deoptimization(); |
| - } |
| -}; |
| - |
| - |
| void MarkCompactCollector::Finish() { |
| #ifdef DEBUG |
| ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| @@ -964,8 +966,22 @@ void MarkCompactCollector::Finish() { |
| // objects (empty string, illegal builtin). |
| isolate()->stub_cache()->Clear(); |
| - DeoptimizeMarkedCodeFilter filter; |
| - Deoptimizer::DeoptimizeAllFunctionsWith(isolate(), &filter); |
| + if (code_to_deoptimize_ != Smi::FromInt(0)) { |
| + // Convert the linked list of Code objects into a ZoneList. |
| + Zone zone(isolate()); |
| + ZoneList<Code*> codes(4, &zone); |
| + |
| + Object *list = code_to_deoptimize_; |
| + while (list->IsCode()) { |
| + Code *code = Code::cast(list); |
| + list = code->gc_metadata(); |
| + codes.Add(code, &zone); |
| + code->set_gc_metadata(Smi::FromInt(0)); |
| + } |
| + code_to_deoptimize_ = Smi::FromInt(0); |
| + |
| + Deoptimizer::DeoptimizeCodeList(isolate(), &codes); |
| + } |
| } |
| @@ -2610,8 +2626,21 @@ void MarkCompactCollector::ClearAndDeoptimizeDependentCode(Map* map) { |
| // and ClearAndDeoptimizeDependentCode shouldn't be called. |
| ASSERT(entries->is_code_at(i)); |
| Code* code = entries->code_at(i); |
| - if (IsMarked(code) && !code->marked_for_deoptimization()) { |
| - code->set_marked_for_deoptimization(true); |
| + |
| + if (IsMarked(code) && !WillBeDeoptimized(code)) { |
| + // Insert the code into the code_to_deoptimize linked list. |
| + Object* next; |
| + if (code_to_deoptimize_ == Smi::FromInt(0)) { |
| + // First entry; undefined indicates the end of the list. |
| + next = isolate()->heap()->undefined_value(); |
| + } else { |
| + // Link the rest of the list off this code object. |
| + next = code_to_deoptimize_; |
| + } |
| + Object** slot = HeapObject::RawField(code, Code::kGCMetadataOffset); |
| + code->set_gc_metadata(next); |
| + RecordSlot(slot, slot, next); // Don't forget about the update. |
| + code_to_deoptimize_ = code; // This code is the new head of the list. |
| } |
| entries->clear_at(i); |
| } |
| @@ -2632,7 +2661,7 @@ void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { |
| Object* obj = entries->object_at(i); |
| ASSERT(obj->IsCode() || IsMarked(obj)); |
| if (IsMarked(obj) && |
| - (!obj->IsCode() || !Code::cast(obj)->marked_for_deoptimization())) { |
| + (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { |
| if (new_number_of_entries + group_number_of_entries != i) { |
| entries->set_object_at( |
| new_number_of_entries + group_number_of_entries, obj); |
| @@ -3449,8 +3478,9 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| } |
| } |
| - // Update pointer from the native contexts list. |
| + // Update the heads of the native contexts list the code to deoptimize list. |
| updating_visitor.VisitPointer(heap_->native_contexts_list_address()); |
| + updating_visitor.VisitPointer(&code_to_deoptimize_); |
| heap_->string_table()->Iterate(&updating_visitor); |