| Index: src/mark-compact.cc
|
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
|
| index 95f673c2a4d5fd406589bc8f9cbc4ced989c6e9b..911e73b12a5224f861171beb3b7de56255ca2b37 100644
|
| --- a/src/mark-compact.cc
|
| +++ b/src/mark-compact.cc
|
| @@ -73,8 +73,8 @@ MarkCompactCollector::MarkCompactCollector() : // NOLINT
|
| migration_slots_buffer_(NULL),
|
| heap_(NULL),
|
| code_flusher_(NULL),
|
| - encountered_weak_collections_(NULL) { }
|
| -
|
| + encountered_weak_collections_(NULL),
|
| + code_to_deoptimize_(NULL) { }
|
|
|
| #ifdef VERIFY_HEAP
|
| class VerifyMarkingVisitor: public ObjectVisitor {
|
| @@ -492,7 +492,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 +945,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 +956,23 @@ 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->code_to_deoptimize_link();
|
| + codes.Add(code, &zone);
|
| + // Destroy the link and don't ever try to deoptimize this code again.
|
| + code->set_code_to_deoptimize_link(Smi::FromInt(0));
|
| + }
|
| + code_to_deoptimize_ = Smi::FromInt(0);
|
| +
|
| + Deoptimizer::DeoptimizeCodeList(isolate(), &codes);
|
| + }
|
| }
|
|
|
|
|
| @@ -2396,7 +2403,6 @@ void MarkCompactCollector::AfterMarking() {
|
| string_table->ElementsRemoved(v.PointersRemoved());
|
| heap()->external_string_table_.Iterate(&v);
|
| heap()->external_string_table_.CleanUp();
|
| - heap()->error_object_list_.RemoveUnmarked(heap());
|
|
|
| // Process the weak references.
|
| MarkCompactWeakObjectRetainer mark_compact_object_retainer;
|
| @@ -2611,8 +2617,17 @@ 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 = code_to_deoptimize_;
|
| + if (next != Smi::FromInt(0)) {
|
| + // Record the slot so that it is updated.
|
| + Object** slot = code->code_to_deoptimize_link_slot();
|
| + RecordSlot(slot, slot, next);
|
| + }
|
| + code->set_code_to_deoptimize_link(next);
|
| + code_to_deoptimize_ = code;
|
| }
|
| entries->clear_at(i);
|
| }
|
| @@ -2633,7 +2648,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);
|
| @@ -2723,7 +2738,12 @@ void MarkCompactCollector::MigrateObject(Address dst,
|
| int size,
|
| AllocationSpace dest) {
|
| HEAP_PROFILE(heap(), ObjectMoveEvent(src, dst));
|
| - if (dest == OLD_POINTER_SPACE || dest == LO_SPACE) {
|
| + // TODO(hpayer): Replace that check with an assert.
|
| + CHECK(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize);
|
| + if (dest == OLD_POINTER_SPACE) {
|
| + // TODO(hpayer): Replace this check with an assert.
|
| + HeapObject* heap_object = HeapObject::FromAddress(src);
|
| + CHECK(heap_->TargetSpace(heap_object) == heap_->old_pointer_space());
|
| Address src_slot = src;
|
| Address dst_slot = dst;
|
| ASSERT(IsAligned(size, kPointerSize));
|
| @@ -2769,6 +2789,13 @@ void MarkCompactCollector::MigrateObject(Address dst,
|
| Code::cast(HeapObject::FromAddress(dst))->Relocate(dst - src);
|
| } else {
|
| ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE);
|
| + // Objects in old data space can just be moved by compaction to a different
|
| + // page in old data space.
|
| + // TODO(hpayer): Replace the following check with an assert.
|
| + CHECK(!heap_->old_data_space()->Contains(src) ||
|
| + (heap_->old_data_space()->Contains(dst) &&
|
| + heap_->TargetSpace(HeapObject::FromAddress(src)) ==
|
| + heap_->old_data_space()));
|
| heap()->MoveBlock(dst, src, size);
|
| }
|
| Memory::Address_at(src) = dst;
|
| @@ -2895,37 +2922,24 @@ static String* UpdateReferenceInExternalStringTableEntry(Heap* heap,
|
|
|
| bool MarkCompactCollector::TryPromoteObject(HeapObject* object,
|
| int object_size) {
|
| - Object* result;
|
| + // TODO(hpayer): Replace that check with an assert.
|
| + CHECK(object_size <= Page::kMaxNonCodeHeapObjectSize);
|
|
|
| - if (object_size > Page::kMaxNonCodeHeapObjectSize) {
|
| - MaybeObject* maybe_result =
|
| - heap()->lo_space()->AllocateRaw(object_size, NOT_EXECUTABLE);
|
| - if (maybe_result->ToObject(&result)) {
|
| - HeapObject* target = HeapObject::cast(result);
|
| - MigrateObject(target->address(),
|
| - object->address(),
|
| - object_size,
|
| - LO_SPACE);
|
| - heap()->mark_compact_collector()->tracer()->
|
| - increment_promoted_objects_size(object_size);
|
| - return true;
|
| - }
|
| - } else {
|
| - OldSpace* target_space = heap()->TargetSpace(object);
|
| -
|
| - ASSERT(target_space == heap()->old_pointer_space() ||
|
| - target_space == heap()->old_data_space());
|
| - MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
|
| - if (maybe_result->ToObject(&result)) {
|
| - HeapObject* target = HeapObject::cast(result);
|
| - MigrateObject(target->address(),
|
| - object->address(),
|
| - object_size,
|
| - target_space->identity());
|
| - heap()->mark_compact_collector()->tracer()->
|
| - increment_promoted_objects_size(object_size);
|
| - return true;
|
| - }
|
| + OldSpace* target_space = heap()->TargetSpace(object);
|
| +
|
| + ASSERT(target_space == heap()->old_pointer_space() ||
|
| + target_space == heap()->old_data_space());
|
| + Object* result;
|
| + MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
|
| + if (maybe_result->ToObject(&result)) {
|
| + HeapObject* target = HeapObject::cast(result);
|
| + MigrateObject(target->address(),
|
| + object->address(),
|
| + object_size,
|
| + target_space->identity());
|
| + heap()->mark_compact_collector()->tracer()->
|
| + increment_promoted_objects_size(object_size);
|
| + return true;
|
| }
|
|
|
| return false;
|
| @@ -3271,6 +3285,16 @@ void MarkCompactCollector::InvalidateCode(Code* code) {
|
| }
|
|
|
|
|
| +// Return true if the given code is deoptimized or will be deoptimized.
|
| +bool MarkCompactCollector::WillBeDeoptimized(Code* code) {
|
| + // We assume the code_to_deoptimize_link is initialized to undefined.
|
| + // If it is 0, or refers to another Code object, then this code
|
| + // is already linked, or was already linked into the list.
|
| + return code->code_to_deoptimize_link() != heap()->undefined_value()
|
| + || code->marked_for_deoptimization();
|
| +}
|
| +
|
| +
|
| bool MarkCompactCollector::MarkInvalidatedCode() {
|
| bool code_marked = false;
|
|
|
| @@ -3454,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);
|
|
|
| @@ -3463,9 +3488,6 @@ void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
|
| heap_->UpdateReferencesInExternalStringTable(
|
| &UpdateReferenceInExternalStringTableEntry);
|
|
|
| - // Update pointers in the new error object list.
|
| - heap_->error_object_list()->UpdateReferences();
|
| -
|
| if (!FLAG_watch_ic_patching) {
|
| // Update JSFunction pointers from the runtime profiler.
|
| heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact(
|
|
|