| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 MarkLiveObjects(); | 79 MarkLiveObjects(); |
| 80 | 80 |
| 81 if (FLAG_collect_maps) ClearNonLiveTransitions(); | 81 if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| 82 | 82 |
| 83 SweepLargeObjectSpace(); | 83 SweepLargeObjectSpace(); |
| 84 | 84 |
| 85 if (IsCompacting()) { | 85 if (IsCompacting()) { |
| 86 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT); | 86 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT); |
| 87 EncodeForwardingAddresses(); | 87 EncodeForwardingAddresses(); |
| 88 | 88 |
| 89 heap_->MarkMapPointersAsEncoded(true); | 89 heap()->MarkMapPointersAsEncoded(true); |
| 90 UpdatePointers(); | 90 UpdatePointers(); |
| 91 heap_->MarkMapPointersAsEncoded(false); | 91 heap()->MarkMapPointersAsEncoded(false); |
| 92 heap_->isolate()->pc_to_code_cache()->Flush(); | 92 heap()->isolate()->pc_to_code_cache()->Flush(); |
| 93 | 93 |
| 94 RelocateObjects(); | 94 RelocateObjects(); |
| 95 } else { | 95 } else { |
| 96 SweepSpaces(); | 96 SweepSpaces(); |
| 97 heap_->isolate()->pc_to_code_cache()->Flush(); | 97 heap()->isolate()->pc_to_code_cache()->Flush(); |
| 98 } | 98 } |
| 99 | 99 |
| 100 Finish(); | 100 Finish(); |
| 101 | 101 |
| 102 // Save the count of marked objects remaining after the collection and | 102 // Save the count of marked objects remaining after the collection and |
| 103 // null out the GC tracer. | 103 // null out the GC tracer. |
| 104 previous_marked_count_ = tracer_->marked_count(); | 104 previous_marked_count_ = tracer_->marked_count(); |
| 105 ASSERT(previous_marked_count_ == 0); | 105 ASSERT(previous_marked_count_ == 0); |
| 106 tracer_ = NULL; | 106 tracer_ = NULL; |
| 107 } | 107 } |
| 108 | 108 |
| 109 | 109 |
| 110 void MarkCompactCollector::Prepare(GCTracer* tracer) { | 110 void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| 111 // Rather than passing the tracer around we stash it in a static member | 111 // Rather than passing the tracer around we stash it in a static member |
| 112 // variable. | 112 // variable. |
| 113 tracer_ = tracer; | 113 tracer_ = tracer; |
| 114 | 114 |
| 115 #ifdef DEBUG | 115 #ifdef DEBUG |
| 116 ASSERT(state_ == IDLE); | 116 ASSERT(state_ == IDLE); |
| 117 state_ = PREPARE_GC; | 117 state_ = PREPARE_GC; |
| 118 #endif | 118 #endif |
| 119 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 119 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 120 | 120 |
| 121 compacting_collection_ = | 121 compacting_collection_ = |
| 122 FLAG_always_compact || force_compaction_ || compact_on_next_gc_; | 122 FLAG_always_compact || force_compaction_ || compact_on_next_gc_; |
| 123 compact_on_next_gc_ = false; | 123 compact_on_next_gc_ = false; |
| 124 | 124 |
| 125 if (FLAG_never_compact) compacting_collection_ = false; | 125 if (FLAG_never_compact) compacting_collection_ = false; |
| 126 if (!HEAP->map_space()->MapPointersEncodable()) | 126 if (!heap()->map_space()->MapPointersEncodable()) |
| 127 compacting_collection_ = false; | 127 compacting_collection_ = false; |
| 128 if (FLAG_collect_maps) CreateBackPointers(); | 128 if (FLAG_collect_maps) CreateBackPointers(); |
| 129 #ifdef ENABLE_GDB_JIT_INTERFACE | 129 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 130 if (FLAG_gdbjit) { | 130 if (FLAG_gdbjit) { |
| 131 // If GDBJIT interface is active disable compaction. | 131 // If GDBJIT interface is active disable compaction. |
| 132 compacting_collection_ = false; | 132 compacting_collection_ = false; |
| 133 } | 133 } |
| 134 #endif | 134 #endif |
| 135 | 135 |
| 136 PagedSpaces spaces; | 136 PagedSpaces spaces; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 154 | 154 |
| 155 void MarkCompactCollector::Finish() { | 155 void MarkCompactCollector::Finish() { |
| 156 #ifdef DEBUG | 156 #ifdef DEBUG |
| 157 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 157 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| 158 state_ = IDLE; | 158 state_ = IDLE; |
| 159 #endif | 159 #endif |
| 160 // The stub cache is not traversed during GC; clear the cache to | 160 // The stub cache is not traversed during GC; clear the cache to |
| 161 // force lazy re-initialization of it. This must be done after the | 161 // force lazy re-initialization of it. This must be done after the |
| 162 // GC, because it relies on the new address of certain old space | 162 // GC, because it relies on the new address of certain old space |
| 163 // objects (empty string, illegal builtin). | 163 // objects (empty string, illegal builtin). |
| 164 heap_->isolate()->stub_cache()->Clear(); | 164 heap()->isolate()->stub_cache()->Clear(); |
| 165 | 165 |
| 166 heap_->external_string_table_.CleanUp(); | 166 heap()->external_string_table_.CleanUp(); |
| 167 | 167 |
| 168 // If we've just compacted old space there's no reason to check the | 168 // If we've just compacted old space there's no reason to check the |
| 169 // fragmentation limit. Just return. | 169 // fragmentation limit. Just return. |
| 170 if (HasCompacted()) return; | 170 if (HasCompacted()) return; |
| 171 | 171 |
| 172 // We compact the old generation on the next GC if it has gotten too | 172 // We compact the old generation on the next GC if it has gotten too |
| 173 // fragmented (ie, we could recover an expected amount of space by | 173 // fragmented (ie, we could recover an expected amount of space by |
| 174 // reclaiming the waste and free list blocks). | 174 // reclaiming the waste and free list blocks). |
| 175 static const int kFragmentationLimit = 15; // Percent. | 175 static const int kFragmentationLimit = 15; // Percent. |
| 176 static const int kFragmentationAllowed = 1 * MB; // Absolute. | 176 static const int kFragmentationAllowed = 1 * MB; // Absolute. |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { | 449 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { |
| 450 // Mark all objects pointed to in [start, end). | 450 // Mark all objects pointed to in [start, end). |
| 451 const int kMinRangeForMarkingRecursion = 64; | 451 const int kMinRangeForMarkingRecursion = 64; |
| 452 if (end - start >= kMinRangeForMarkingRecursion) { | 452 if (end - start >= kMinRangeForMarkingRecursion) { |
| 453 if (VisitUnmarkedObjects(heap, start, end)) return; | 453 if (VisitUnmarkedObjects(heap, start, end)) return; |
| 454 // We are close to a stack overflow, so just mark the objects. | 454 // We are close to a stack overflow, so just mark the objects. |
| 455 } | 455 } |
| 456 for (Object** p = start; p < end; p++) MarkObjectByPointer(heap, p); | 456 for (Object** p = start; p < end; p++) MarkObjectByPointer(heap, p); |
| 457 } | 457 } |
| 458 | 458 |
| 459 static inline void VisitCodeTarget(RelocInfo* rinfo) { | 459 static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { |
| 460 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 460 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 461 Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 461 Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 462 if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) { | 462 if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) { |
| 463 IC::Clear(rinfo->pc()); | 463 IC::Clear(rinfo->pc()); |
| 464 // Please note targets for cleared inline cached do not have to be | 464 // Please note targets for cleared inline cached do not have to be |
| 465 // marked since they are contained in HEAP->non_monomorphic_cache(). | 465 // marked since they are contained in HEAP->non_monomorphic_cache(). |
| 466 } else { | 466 } else { |
| 467 code->heap()->mark_compact_collector()->MarkObject(code); | 467 heap->mark_compact_collector()->MarkObject(code); |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 | 470 |
| 471 static void VisitGlobalPropertyCell(RelocInfo* rinfo) { | 471 static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) { |
| 472 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); | 472 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); |
| 473 Object* cell = rinfo->target_cell(); | 473 Object* cell = rinfo->target_cell(); |
| 474 Object* old_cell = cell; | 474 Object* old_cell = cell; |
| 475 VisitPointer(reinterpret_cast<JSGlobalPropertyCell*>(cell)->heap(), &cell); | 475 VisitPointer(heap, &cell); |
| 476 if (cell != old_cell) { | 476 if (cell != old_cell) { |
| 477 rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell)); | 477 rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell)); |
| 478 } | 478 } |
| 479 } | 479 } |
| 480 | 480 |
| 481 static inline void VisitDebugTarget(RelocInfo* rinfo) { | 481 static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) { |
| 482 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 482 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 483 rinfo->IsPatchedReturnSequence()) || | 483 rinfo->IsPatchedReturnSequence()) || |
| 484 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 484 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 485 rinfo->IsPatchedDebugBreakSlotSequence())); | 485 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 486 HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 486 HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 487 reinterpret_cast<Code*>(code)->heap()->mark_compact_collector()-> | 487 heap->mark_compact_collector()->MarkObject(code); |
| 488 MarkObject(code); | |
| 489 } | 488 } |
| 490 | 489 |
| 491 // Mark object pointed to by p. | 490 // Mark object pointed to by p. |
| 492 INLINE(static void MarkObjectByPointer(Heap* heap, Object** p)) { | 491 INLINE(static void MarkObjectByPointer(Heap* heap, Object** p)) { |
| 493 if (!(*p)->IsHeapObject()) return; | 492 if (!(*p)->IsHeapObject()) return; |
| 494 HeapObject* object = ShortCircuitConsString(p); | 493 HeapObject* object = ShortCircuitConsString(p); |
| 495 if (!object->IsMarked()) { | 494 if (!object->IsMarked()) { |
| 496 heap->mark_compact_collector()->MarkUnmarkedObject(object); | 495 heap->mark_compact_collector()->MarkUnmarkedObject(object); |
| 497 } | 496 } |
| 498 } | 497 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( | 557 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( |
| 559 map->heap()); | 558 map->heap()); |
| 560 } | 559 } |
| 561 | 560 |
| 562 // Code flushing support. | 561 // Code flushing support. |
| 563 | 562 |
| 564 // How many collections newly compiled code object will survive before being | 563 // How many collections newly compiled code object will survive before being |
| 565 // flushed. | 564 // flushed. |
| 566 static const int kCodeAgeThreshold = 5; | 565 static const int kCodeAgeThreshold = 5; |
| 567 | 566 |
| 568 inline static bool HasSourceCode(SharedFunctionInfo* info) { | 567 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { |
| 569 Object* undefined = HEAP->raw_unchecked_undefined_value(); | 568 Object* undefined = heap->raw_unchecked_undefined_value(); |
| 570 return (info->script() != undefined) && | 569 return (info->script() != undefined) && |
| 571 (reinterpret_cast<Script*>(info->script())->source() != undefined); | 570 (reinterpret_cast<Script*>(info->script())->source() != undefined); |
| 572 } | 571 } |
| 573 | 572 |
| 574 | 573 |
| 575 inline static bool IsCompiled(JSFunction* function) { | 574 inline static bool IsCompiled(JSFunction* function) { |
| 576 return function->unchecked_code() != | 575 return function->unchecked_code() != |
| 577 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); | 576 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); |
| 578 } | 577 } |
| 579 | 578 |
| 580 inline static bool IsCompiled(SharedFunctionInfo* function) { | 579 inline static bool IsCompiled(SharedFunctionInfo* function) { |
| 581 return function->unchecked_code() != | 580 return function->unchecked_code() != |
| 582 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); | 581 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); |
| 583 } | 582 } |
| 584 | 583 |
| 585 inline static bool IsFlushable(JSFunction* function) { | 584 inline static bool IsFlushable(Heap* heap, JSFunction* function) { |
| 586 SharedFunctionInfo* shared_info = function->unchecked_shared(); | 585 SharedFunctionInfo* shared_info = function->unchecked_shared(); |
| 587 | 586 |
| 588 // Code is either on stack, in compilation cache or referenced | 587 // Code is either on stack, in compilation cache or referenced |
| 589 // by optimized version of function. | 588 // by optimized version of function. |
| 590 if (function->unchecked_code()->IsMarked()) { | 589 if (function->unchecked_code()->IsMarked()) { |
| 591 shared_info->set_code_age(0); | 590 shared_info->set_code_age(0); |
| 592 return false; | 591 return false; |
| 593 } | 592 } |
| 594 | 593 |
| 595 // We do not flush code for optimized functions. | 594 // We do not flush code for optimized functions. |
| 596 if (function->code() != shared_info->unchecked_code()) { | 595 if (function->code() != shared_info->unchecked_code()) { |
| 597 return false; | 596 return false; |
| 598 } | 597 } |
| 599 | 598 |
| 600 return IsFlushable(shared_info); | 599 return IsFlushable(heap, shared_info); |
| 601 } | 600 } |
| 602 | 601 |
| 603 inline static bool IsFlushable(SharedFunctionInfo* shared_info) { | 602 inline static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info) { |
| 604 // Code is either on stack, in compilation cache or referenced | 603 // Code is either on stack, in compilation cache or referenced |
| 605 // by optimized version of function. | 604 // by optimized version of function. |
| 606 if (shared_info->unchecked_code()->IsMarked()) { | 605 if (shared_info->unchecked_code()->IsMarked()) { |
| 607 shared_info->set_code_age(0); | 606 shared_info->set_code_age(0); |
| 608 return false; | 607 return false; |
| 609 } | 608 } |
| 610 | 609 |
| 611 // The function must be compiled and have the source code available, | 610 // The function must be compiled and have the source code available, |
| 612 // to be able to recompile it in case we need the function again. | 611 // to be able to recompile it in case we need the function again. |
| 613 if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) { | 612 if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) { |
| 614 return false; | 613 return false; |
| 615 } | 614 } |
| 616 | 615 |
| 617 // We never flush code for Api functions. | 616 // We never flush code for Api functions. |
| 618 Object* function_data = shared_info->function_data(); | 617 Object* function_data = shared_info->function_data(); |
| 619 if (function_data->IsHeapObject() && | 618 if (function_data->IsHeapObject() && |
| 620 (SafeMap(function_data)->instance_type() == | 619 (SafeMap(function_data)->instance_type() == |
| 621 FUNCTION_TEMPLATE_INFO_TYPE)) { | 620 FUNCTION_TEMPLATE_INFO_TYPE)) { |
| 622 return false; | 621 return false; |
| 623 } | 622 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 635 if (shared_info->code_age() < kCodeAgeThreshold) { | 634 if (shared_info->code_age() < kCodeAgeThreshold) { |
| 636 shared_info->set_code_age(shared_info->code_age() + 1); | 635 shared_info->set_code_age(shared_info->code_age() + 1); |
| 637 return false; | 636 return false; |
| 638 } | 637 } |
| 639 | 638 |
| 640 return true; | 639 return true; |
| 641 } | 640 } |
| 642 | 641 |
| 643 | 642 |
| 644 static bool FlushCodeForFunction(Heap* heap, JSFunction* function) { | 643 static bool FlushCodeForFunction(Heap* heap, JSFunction* function) { |
| 645 if (!IsFlushable(function)) return false; | 644 if (!IsFlushable(heap, function)) return false; |
| 646 | 645 |
| 647 // This function's code looks flushable. But we have to postpone the | 646 // This function's code looks flushable. But we have to postpone the |
| 648 // decision until we see all functions that point to the same | 647 // decision until we see all functions that point to the same |
| 649 // SharedFunctionInfo because some of them might be optimized. | 648 // SharedFunctionInfo because some of them might be optimized. |
| 650 // That would make the nonoptimized version of the code nonflushable, | 649 // That would make the nonoptimized version of the code nonflushable, |
| 651 // because it is required for bailing out from optimized code. | 650 // because it is required for bailing out from optimized code. |
| 652 heap->mark_compact_collector()->code_flusher()->AddCandidate(function); | 651 heap->mark_compact_collector()->code_flusher()->AddCandidate(function); |
| 653 return true; | 652 return true; |
| 654 } | 653 } |
| 655 | 654 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 | 711 |
| 713 | 712 |
| 714 static void VisitSharedFunctionInfoAndFlushCodeGeneric( | 713 static void VisitSharedFunctionInfoAndFlushCodeGeneric( |
| 715 Map* map, HeapObject* object, bool known_flush_code_candidate) { | 714 Map* map, HeapObject* object, bool known_flush_code_candidate) { |
| 716 Heap* heap = map->heap(); | 715 Heap* heap = map->heap(); |
| 717 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object); | 716 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object); |
| 718 | 717 |
| 719 if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap(); | 718 if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap(); |
| 720 | 719 |
| 721 if (!known_flush_code_candidate) { | 720 if (!known_flush_code_candidate) { |
| 722 known_flush_code_candidate = IsFlushable(shared); | 721 known_flush_code_candidate = IsFlushable(heap, shared); |
| 723 if (known_flush_code_candidate) { | 722 if (known_flush_code_candidate) { |
| 724 heap->mark_compact_collector()->code_flusher()->AddCandidate(shared); | 723 heap->mark_compact_collector()->code_flusher()->AddCandidate(shared); |
| 725 } | 724 } |
| 726 } | 725 } |
| 727 | 726 |
| 728 VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate); | 727 VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate); |
| 729 } | 728 } |
| 730 | 729 |
| 731 | 730 |
| 732 static void VisitCodeEntry(Heap* heap, Address entry_address) { | 731 static void VisitCodeEntry(Heap* heap, Address entry_address) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 explicit MarkingVisitor(Heap* heap) : heap_(heap) { } | 861 explicit MarkingVisitor(Heap* heap) : heap_(heap) { } |
| 863 | 862 |
| 864 void VisitPointer(Object** p) { | 863 void VisitPointer(Object** p) { |
| 865 StaticMarkingVisitor::VisitPointer(heap_, p); | 864 StaticMarkingVisitor::VisitPointer(heap_, p); |
| 866 } | 865 } |
| 867 | 866 |
| 868 void VisitPointers(Object** start, Object** end) { | 867 void VisitPointers(Object** start, Object** end) { |
| 869 StaticMarkingVisitor::VisitPointers(heap_, start, end); | 868 StaticMarkingVisitor::VisitPointers(heap_, start, end); |
| 870 } | 869 } |
| 871 | 870 |
| 872 void VisitCodeTarget(RelocInfo* rinfo) { | 871 void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { |
| 873 StaticMarkingVisitor::VisitCodeTarget(rinfo); | 872 StaticMarkingVisitor::VisitCodeTarget(heap, rinfo); |
| 874 } | 873 } |
| 875 | 874 |
| 876 void VisitGlobalPropertyCell(RelocInfo* rinfo) { | 875 void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) { |
| 877 StaticMarkingVisitor::VisitGlobalPropertyCell(rinfo); | 876 StaticMarkingVisitor::VisitGlobalPropertyCell(heap, rinfo); |
| 878 } | 877 } |
| 879 | 878 |
| 880 void VisitDebugTarget(RelocInfo* rinfo) { | 879 void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) { |
| 881 StaticMarkingVisitor::VisitDebugTarget(rinfo); | 880 StaticMarkingVisitor::VisitDebugTarget(heap, rinfo); |
| 882 } | 881 } |
| 883 | 882 |
| 884 private: | 883 private: |
| 885 Heap* heap_; | 884 Heap* heap_; |
| 886 }; | 885 }; |
| 887 | 886 |
| 888 | 887 |
| 889 class CodeMarkingVisitor : public ThreadVisitor { | 888 class CodeMarkingVisitor : public ThreadVisitor { |
| 890 public: | 889 public: |
| 891 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 890 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
| (...skipping 27 matching lines...) Expand all Loading... |
| 919 collector_->MarkObject(shared); | 918 collector_->MarkObject(shared); |
| 920 } | 919 } |
| 921 } | 920 } |
| 922 | 921 |
| 923 private: | 922 private: |
| 924 MarkCompactCollector* collector_; | 923 MarkCompactCollector* collector_; |
| 925 }; | 924 }; |
| 926 | 925 |
| 927 | 926 |
| 928 void MarkCompactCollector::PrepareForCodeFlushing() { | 927 void MarkCompactCollector::PrepareForCodeFlushing() { |
| 929 ASSERT(heap_ == Isolate::Current()->heap()); | 928 ASSERT(heap() == Isolate::Current()->heap()); |
| 930 | 929 |
| 931 if (!FLAG_flush_code) { | 930 if (!FLAG_flush_code) { |
| 932 EnableCodeFlushing(false); | 931 EnableCodeFlushing(false); |
| 933 return; | 932 return; |
| 934 } | 933 } |
| 935 | 934 |
| 936 #ifdef ENABLE_DEBUGGER_SUPPORT | 935 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 937 if (heap_->isolate()->debug()->IsLoaded() || | 936 if (heap()->isolate()->debug()->IsLoaded() || |
| 938 heap_->isolate()->debug()->has_break_points()) { | 937 heap()->isolate()->debug()->has_break_points()) { |
| 939 EnableCodeFlushing(false); | 938 EnableCodeFlushing(false); |
| 940 return; | 939 return; |
| 941 } | 940 } |
| 942 #endif | 941 #endif |
| 943 EnableCodeFlushing(true); | 942 EnableCodeFlushing(true); |
| 944 | 943 |
| 945 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray | 944 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray |
| 946 // relies on it being marked before any other descriptor array. | 945 // relies on it being marked before any other descriptor array. |
| 947 MarkObject(heap_->raw_unchecked_empty_descriptor_array()); | 946 MarkObject(heap()->raw_unchecked_empty_descriptor_array()); |
| 948 | 947 |
| 949 // Make sure we are not referencing the code from the stack. | 948 // Make sure we are not referencing the code from the stack. |
| 950 ASSERT(this == heap_->mark_compact_collector()); | 949 ASSERT(this == heap()->mark_compact_collector()); |
| 951 for (StackFrameIterator it; !it.done(); it.Advance()) { | 950 for (StackFrameIterator it; !it.done(); it.Advance()) { |
| 952 MarkObject(it.frame()->unchecked_code()); | 951 MarkObject(it.frame()->unchecked_code()); |
| 953 } | 952 } |
| 954 | 953 |
| 955 // Iterate the archived stacks in all threads to check if | 954 // Iterate the archived stacks in all threads to check if |
| 956 // the code is referenced. | 955 // the code is referenced. |
| 957 CodeMarkingVisitor code_marking_visitor(this); | 956 CodeMarkingVisitor code_marking_visitor(this); |
| 958 heap_->isolate()->thread_manager()->IterateArchivedThreads( | 957 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
| 959 &code_marking_visitor); | 958 &code_marking_visitor); |
| 960 | 959 |
| 961 SharedFunctionInfoMarkingVisitor visitor(this); | 960 SharedFunctionInfoMarkingVisitor visitor(this); |
| 962 heap_->isolate()->compilation_cache()->IterateFunctions(&visitor); | 961 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); |
| 963 heap_->isolate()->handle_scope_implementer()->Iterate(&visitor); | 962 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); |
| 964 | 963 |
| 965 ProcessMarkingStack(); | 964 ProcessMarkingStack(); |
| 966 } | 965 } |
| 967 | 966 |
| 968 | 967 |
| 969 // Visitor class for marking heap roots. | 968 // Visitor class for marking heap roots. |
| 970 class RootMarkingVisitor : public ObjectVisitor { | 969 class RootMarkingVisitor : public ObjectVisitor { |
| 971 public: | 970 public: |
| 972 explicit RootMarkingVisitor(Heap* heap) | 971 explicit RootMarkingVisitor(Heap* heap) |
| 973 : collector_(heap->mark_compact_collector()) { } | 972 : collector_(heap->mark_compact_collector()) { } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1001 collector_->EmptyMarkingStack(); | 1000 collector_->EmptyMarkingStack(); |
| 1002 } | 1001 } |
| 1003 | 1002 |
| 1004 MarkCompactCollector* collector_; | 1003 MarkCompactCollector* collector_; |
| 1005 }; | 1004 }; |
| 1006 | 1005 |
| 1007 | 1006 |
| 1008 // Helper class for pruning the symbol table. | 1007 // Helper class for pruning the symbol table. |
| 1009 class SymbolTableCleaner : public ObjectVisitor { | 1008 class SymbolTableCleaner : public ObjectVisitor { |
| 1010 public: | 1009 public: |
| 1011 SymbolTableCleaner() : pointers_removed_(0) { } | 1010 explicit SymbolTableCleaner(Heap* heap) |
| 1011 : heap_(heap), pointers_removed_(0) { } |
| 1012 | 1012 |
| 1013 virtual void VisitPointers(Object** start, Object** end) { | 1013 virtual void VisitPointers(Object** start, Object** end) { |
| 1014 // Visit all HeapObject pointers in [start, end). | 1014 // Visit all HeapObject pointers in [start, end). |
| 1015 for (Object** p = start; p < end; p++) { | 1015 for (Object** p = start; p < end; p++) { |
| 1016 if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) { | 1016 if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) { |
| 1017 // Check if the symbol being pruned is an external symbol. We need to | 1017 // Check if the symbol being pruned is an external symbol. We need to |
| 1018 // delete the associated external data as this symbol is going away. | 1018 // delete the associated external data as this symbol is going away. |
| 1019 | 1019 |
| 1020 // Since no objects have yet been moved we can safely access the map of | 1020 // Since no objects have yet been moved we can safely access the map of |
| 1021 // the object. | 1021 // the object. |
| 1022 if ((*p)->IsExternalString()) { | 1022 if ((*p)->IsExternalString()) { |
| 1023 HEAP->FinalizeExternalString(String::cast(*p)); | 1023 heap_->FinalizeExternalString(String::cast(*p)); |
| 1024 } | 1024 } |
| 1025 // Set the entry to null_value (as deleted). | 1025 // Set the entry to null_value (as deleted). |
| 1026 *p = HEAP->raw_unchecked_null_value(); | 1026 *p = heap_->raw_unchecked_null_value(); |
| 1027 pointers_removed_++; | 1027 pointers_removed_++; |
| 1028 } | 1028 } |
| 1029 } | 1029 } |
| 1030 } | 1030 } |
| 1031 | 1031 |
| 1032 int PointersRemoved() { | 1032 int PointersRemoved() { |
| 1033 return pointers_removed_; | 1033 return pointers_removed_; |
| 1034 } | 1034 } |
| 1035 private: | 1035 private: |
| 1036 Heap* heap_; |
| 1036 int pointers_removed_; | 1037 int pointers_removed_; |
| 1037 }; | 1038 }; |
| 1038 | 1039 |
| 1039 | 1040 |
| 1040 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects | 1041 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects |
| 1041 // are retained. | 1042 // are retained. |
| 1042 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { | 1043 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { |
| 1043 public: | 1044 public: |
| 1044 virtual Object* RetainAs(Object* object) { | 1045 virtual Object* RetainAs(Object* object) { |
| 1045 MapWord first_word = HeapObject::cast(object)->map_word(); | 1046 MapWord first_word = HeapObject::cast(object)->map_word(); |
| 1046 if (first_word.IsMarked()) { | 1047 if (first_word.IsMarked()) { |
| 1047 return object; | 1048 return object; |
| 1048 } else { | 1049 } else { |
| 1049 return NULL; | 1050 return NULL; |
| 1050 } | 1051 } |
| 1051 } | 1052 } |
| 1052 }; | 1053 }; |
| 1053 | 1054 |
| 1054 | 1055 |
| 1055 void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) { | 1056 void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) { |
| 1056 ASSERT(!object->IsMarked()); | 1057 ASSERT(!object->IsMarked()); |
| 1057 ASSERT(HEAP->Contains(object)); | 1058 ASSERT(HEAP->Contains(object)); |
| 1058 if (object->IsMap()) { | 1059 if (object->IsMap()) { |
| 1059 Map* map = Map::cast(object); | 1060 Map* map = Map::cast(object); |
| 1060 if (FLAG_cleanup_caches_in_maps_at_gc) { | 1061 if (FLAG_cleanup_caches_in_maps_at_gc) { |
| 1061 map->ClearCodeCache(heap_); | 1062 map->ClearCodeCache(heap()); |
| 1062 } | 1063 } |
| 1063 SetMark(map); | 1064 SetMark(map); |
| 1064 if (FLAG_collect_maps && | 1065 if (FLAG_collect_maps && |
| 1065 map->instance_type() >= FIRST_JS_OBJECT_TYPE && | 1066 map->instance_type() >= FIRST_JS_OBJECT_TYPE && |
| 1066 map->instance_type() <= JS_FUNCTION_TYPE) { | 1067 map->instance_type() <= JS_FUNCTION_TYPE) { |
| 1067 MarkMapContents(map); | 1068 MarkMapContents(map); |
| 1068 } else { | 1069 } else { |
| 1069 marking_stack_.Push(map); | 1070 marking_stack_.Push(map); |
| 1070 } | 1071 } |
| 1071 } else { | 1072 } else { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 } | 1123 } |
| 1123 } | 1124 } |
| 1124 } | 1125 } |
| 1125 // The DescriptorArray descriptors contains a pointer to its contents array, | 1126 // The DescriptorArray descriptors contains a pointer to its contents array, |
| 1126 // but the contents array is already marked. | 1127 // but the contents array is already marked. |
| 1127 marking_stack_.Push(descriptors); | 1128 marking_stack_.Push(descriptors); |
| 1128 } | 1129 } |
| 1129 | 1130 |
| 1130 | 1131 |
| 1131 void MarkCompactCollector::CreateBackPointers() { | 1132 void MarkCompactCollector::CreateBackPointers() { |
| 1132 HeapObjectIterator iterator(HEAP->map_space()); | 1133 HeapObjectIterator iterator(heap()->map_space()); |
| 1133 for (HeapObject* next_object = iterator.next(); | 1134 for (HeapObject* next_object = iterator.next(); |
| 1134 next_object != NULL; next_object = iterator.next()) { | 1135 next_object != NULL; next_object = iterator.next()) { |
| 1135 if (next_object->IsMap()) { // Could also be ByteArray on free list. | 1136 if (next_object->IsMap()) { // Could also be ByteArray on free list. |
| 1136 Map* map = Map::cast(next_object); | 1137 Map* map = Map::cast(next_object); |
| 1137 if (map->instance_type() >= FIRST_JS_OBJECT_TYPE && | 1138 if (map->instance_type() >= FIRST_JS_OBJECT_TYPE && |
| 1138 map->instance_type() <= JS_FUNCTION_TYPE) { | 1139 map->instance_type() <= JS_FUNCTION_TYPE) { |
| 1139 map->CreateBackPointers(); | 1140 map->CreateBackPointers(); |
| 1140 } else { | 1141 } else { |
| 1141 ASSERT(map->instance_descriptors() == HEAP->empty_descriptor_array()); | 1142 ASSERT(map->instance_descriptors() == heap()->empty_descriptor_array()); |
| 1142 } | 1143 } |
| 1143 } | 1144 } |
| 1144 } | 1145 } |
| 1145 } | 1146 } |
| 1146 | 1147 |
| 1147 | 1148 |
| 1148 static int OverflowObjectSize(HeapObject* obj) { | 1149 static int OverflowObjectSize(HeapObject* obj) { |
| 1149 // Recover the normal map pointer, it might be marked as live and | 1150 // Recover the normal map pointer, it might be marked as live and |
| 1150 // overflowed. | 1151 // overflowed. |
| 1151 MapWord map_word = obj->map_word(); | 1152 MapWord map_word = obj->map_word(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1179 } | 1180 } |
| 1180 }; | 1181 }; |
| 1181 | 1182 |
| 1182 | 1183 |
| 1183 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 1184 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 1184 return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked(); | 1185 return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked(); |
| 1185 } | 1186 } |
| 1186 | 1187 |
| 1187 | 1188 |
| 1188 void MarkCompactCollector::MarkSymbolTable() { | 1189 void MarkCompactCollector::MarkSymbolTable() { |
| 1189 SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table(); | 1190 SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table(); |
| 1190 // Mark the symbol table itself. | 1191 // Mark the symbol table itself. |
| 1191 SetMark(symbol_table); | 1192 SetMark(symbol_table); |
| 1192 // Explicitly mark the prefix. | 1193 // Explicitly mark the prefix. |
| 1193 MarkingVisitor marker(heap_); | 1194 MarkingVisitor marker(heap()); |
| 1194 symbol_table->IteratePrefix(&marker); | 1195 symbol_table->IteratePrefix(&marker); |
| 1195 ProcessMarkingStack(); | 1196 ProcessMarkingStack(); |
| 1196 } | 1197 } |
| 1197 | 1198 |
| 1198 | 1199 |
| 1199 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 1200 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
| 1200 // Mark the heap roots including global variables, stack variables, | 1201 // Mark the heap roots including global variables, stack variables, |
| 1201 // etc., and all objects reachable from them. | 1202 // etc., and all objects reachable from them. |
| 1202 HEAP->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); | 1203 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); |
| 1203 | 1204 |
| 1204 // Handle the symbol table specially. | 1205 // Handle the symbol table specially. |
| 1205 MarkSymbolTable(); | 1206 MarkSymbolTable(); |
| 1206 | 1207 |
| 1207 // There may be overflowed objects in the heap. Visit them now. | 1208 // There may be overflowed objects in the heap. Visit them now. |
| 1208 while (marking_stack_.overflowed()) { | 1209 while (marking_stack_.overflowed()) { |
| 1209 RefillMarkingStack(); | 1210 RefillMarkingStack(); |
| 1210 EmptyMarkingStack(); | 1211 EmptyMarkingStack(); |
| 1211 } | 1212 } |
| 1212 } | 1213 } |
| 1213 | 1214 |
| 1214 | 1215 |
| 1215 void MarkCompactCollector::MarkObjectGroups() { | 1216 void MarkCompactCollector::MarkObjectGroups() { |
| 1216 List<ObjectGroup*>* object_groups = | 1217 List<ObjectGroup*>* object_groups = |
| 1217 heap_->isolate()->global_handles()->object_groups(); | 1218 heap()->isolate()->global_handles()->object_groups(); |
| 1218 | 1219 |
| 1219 for (int i = 0; i < object_groups->length(); i++) { | 1220 for (int i = 0; i < object_groups->length(); i++) { |
| 1220 ObjectGroup* entry = object_groups->at(i); | 1221 ObjectGroup* entry = object_groups->at(i); |
| 1221 if (entry == NULL) continue; | 1222 if (entry == NULL) continue; |
| 1222 | 1223 |
| 1223 List<Object**>& objects = entry->objects_; | 1224 List<Object**>& objects = entry->objects_; |
| 1224 bool group_marked = false; | 1225 bool group_marked = false; |
| 1225 for (int j = 0; j < objects.length(); j++) { | 1226 for (int j = 0; j < objects.length(); j++) { |
| 1226 Object* object = *objects[j]; | 1227 Object* object = *objects[j]; |
| 1227 if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) { | 1228 if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1243 // Once the entire group has been colored gray, set the object group | 1244 // Once the entire group has been colored gray, set the object group |
| 1244 // to NULL so it won't be processed again. | 1245 // to NULL so it won't be processed again. |
| 1245 delete entry; | 1246 delete entry; |
| 1246 object_groups->at(i) = NULL; | 1247 object_groups->at(i) = NULL; |
| 1247 } | 1248 } |
| 1248 } | 1249 } |
| 1249 | 1250 |
| 1250 | 1251 |
| 1251 void MarkCompactCollector::MarkImplicitRefGroups() { | 1252 void MarkCompactCollector::MarkImplicitRefGroups() { |
| 1252 List<ImplicitRefGroup*>* ref_groups = | 1253 List<ImplicitRefGroup*>* ref_groups = |
| 1253 heap_->isolate()->global_handles()->implicit_ref_groups(); | 1254 heap()->isolate()->global_handles()->implicit_ref_groups(); |
| 1254 | 1255 |
| 1255 for (int i = 0; i < ref_groups->length(); i++) { | 1256 for (int i = 0; i < ref_groups->length(); i++) { |
| 1256 ImplicitRefGroup* entry = ref_groups->at(i); | 1257 ImplicitRefGroup* entry = ref_groups->at(i); |
| 1257 if (entry == NULL) continue; | 1258 if (entry == NULL) continue; |
| 1258 | 1259 |
| 1259 if (!entry->parent_->IsMarked()) continue; | 1260 if (!entry->parent_->IsMarked()) continue; |
| 1260 | 1261 |
| 1261 List<Object**>& children = entry->children_; | 1262 List<Object**>& children = entry->children_; |
| 1262 // A parent object is marked, so mark as gray all child white heap | 1263 // A parent object is marked, so mark as gray all child white heap |
| 1263 // objects. | 1264 // objects. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1276 | 1277 |
| 1277 | 1278 |
| 1278 // Mark all objects reachable from the objects on the marking stack. | 1279 // Mark all objects reachable from the objects on the marking stack. |
| 1279 // Before: the marking stack contains zero or more heap object pointers. | 1280 // Before: the marking stack contains zero or more heap object pointers. |
| 1280 // After: the marking stack is empty, and all objects reachable from the | 1281 // After: the marking stack is empty, and all objects reachable from the |
| 1281 // marking stack have been marked, or are overflowed in the heap. | 1282 // marking stack have been marked, or are overflowed in the heap. |
| 1282 void MarkCompactCollector::EmptyMarkingStack() { | 1283 void MarkCompactCollector::EmptyMarkingStack() { |
| 1283 while (!marking_stack_.is_empty()) { | 1284 while (!marking_stack_.is_empty()) { |
| 1284 HeapObject* object = marking_stack_.Pop(); | 1285 HeapObject* object = marking_stack_.Pop(); |
| 1285 ASSERT(object->IsHeapObject()); | 1286 ASSERT(object->IsHeapObject()); |
| 1286 ASSERT(heap_->Contains(object)); | 1287 ASSERT(heap()->Contains(object)); |
| 1287 ASSERT(object->IsMarked()); | 1288 ASSERT(object->IsMarked()); |
| 1288 ASSERT(!object->IsOverflowed()); | 1289 ASSERT(!object->IsOverflowed()); |
| 1289 | 1290 |
| 1290 // Because the object is marked, we have to recover the original map | 1291 // Because the object is marked, we have to recover the original map |
| 1291 // pointer and use it to mark the object's body. | 1292 // pointer and use it to mark the object's body. |
| 1292 MapWord map_word = object->map_word(); | 1293 MapWord map_word = object->map_word(); |
| 1293 map_word.ClearMark(); | 1294 map_word.ClearMark(); |
| 1294 Map* map = map_word.ToMap(); | 1295 Map* map = map_word.ToMap(); |
| 1295 MarkObject(map); | 1296 MarkObject(map); |
| 1296 | 1297 |
| 1297 StaticMarkingVisitor::IterateBody(map, object); | 1298 StaticMarkingVisitor::IterateBody(map, object); |
| 1298 } | 1299 } |
| 1299 } | 1300 } |
| 1300 | 1301 |
| 1301 | 1302 |
| 1302 // Sweep the heap for overflowed objects, clear their overflow bits, and | 1303 // Sweep the heap for overflowed objects, clear their overflow bits, and |
| 1303 // push them on the marking stack. Stop early if the marking stack fills | 1304 // push them on the marking stack. Stop early if the marking stack fills |
| 1304 // before sweeping completes. If sweeping completes, there are no remaining | 1305 // before sweeping completes. If sweeping completes, there are no remaining |
| 1305 // overflowed objects in the heap so the overflow flag on the markings stack | 1306 // overflowed objects in the heap so the overflow flag on the markings stack |
| 1306 // is cleared. | 1307 // is cleared. |
| 1307 void MarkCompactCollector::RefillMarkingStack() { | 1308 void MarkCompactCollector::RefillMarkingStack() { |
| 1308 ASSERT(marking_stack_.overflowed()); | 1309 ASSERT(marking_stack_.overflowed()); |
| 1309 | 1310 |
| 1310 SemiSpaceIterator new_it(HEAP->new_space(), &OverflowObjectSize); | 1311 SemiSpaceIterator new_it(heap()->new_space(), &OverflowObjectSize); |
| 1311 OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it); | 1312 OverflowedObjectsScanner::ScanOverflowedObjects(this, &new_it); |
| 1312 if (marking_stack_.is_full()) return; | 1313 if (marking_stack_.is_full()) return; |
| 1313 | 1314 |
| 1314 HeapObjectIterator old_pointer_it(HEAP->old_pointer_space(), | 1315 HeapObjectIterator old_pointer_it(heap()->old_pointer_space(), |
| 1315 &OverflowObjectSize); | 1316 &OverflowObjectSize); |
| 1316 OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_pointer_it); | 1317 OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_pointer_it); |
| 1317 if (marking_stack_.is_full()) return; | 1318 if (marking_stack_.is_full()) return; |
| 1318 | 1319 |
| 1319 HeapObjectIterator old_data_it(HEAP->old_data_space(), &OverflowObjectSize); | 1320 HeapObjectIterator old_data_it(heap()->old_data_space(), &OverflowObjectSize); |
| 1320 OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_data_it); | 1321 OverflowedObjectsScanner::ScanOverflowedObjects(this, &old_data_it); |
| 1321 if (marking_stack_.is_full()) return; | 1322 if (marking_stack_.is_full()) return; |
| 1322 | 1323 |
| 1323 HeapObjectIterator code_it(HEAP->code_space(), &OverflowObjectSize); | 1324 HeapObjectIterator code_it(heap()->code_space(), &OverflowObjectSize); |
| 1324 OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it); | 1325 OverflowedObjectsScanner::ScanOverflowedObjects(this, &code_it); |
| 1325 if (marking_stack_.is_full()) return; | 1326 if (marking_stack_.is_full()) return; |
| 1326 | 1327 |
| 1327 HeapObjectIterator map_it(HEAP->map_space(), &OverflowObjectSize); | 1328 HeapObjectIterator map_it(heap()->map_space(), &OverflowObjectSize); |
| 1328 OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it); | 1329 OverflowedObjectsScanner::ScanOverflowedObjects(this, &map_it); |
| 1329 if (marking_stack_.is_full()) return; | 1330 if (marking_stack_.is_full()) return; |
| 1330 | 1331 |
| 1331 HeapObjectIterator cell_it(HEAP->cell_space(), &OverflowObjectSize); | 1332 HeapObjectIterator cell_it(heap()->cell_space(), &OverflowObjectSize); |
| 1332 OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it); | 1333 OverflowedObjectsScanner::ScanOverflowedObjects(this, &cell_it); |
| 1333 if (marking_stack_.is_full()) return; | 1334 if (marking_stack_.is_full()) return; |
| 1334 | 1335 |
| 1335 LargeObjectIterator lo_it(HEAP->lo_space(), &OverflowObjectSize); | 1336 LargeObjectIterator lo_it(heap()->lo_space(), &OverflowObjectSize); |
| 1336 OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it); | 1337 OverflowedObjectsScanner::ScanOverflowedObjects(this, &lo_it); |
| 1337 if (marking_stack_.is_full()) return; | 1338 if (marking_stack_.is_full()) return; |
| 1338 | 1339 |
| 1339 marking_stack_.clear_overflowed(); | 1340 marking_stack_.clear_overflowed(); |
| 1340 } | 1341 } |
| 1341 | 1342 |
| 1342 | 1343 |
| 1343 // Mark all objects reachable (transitively) from objects on the marking | 1344 // Mark all objects reachable (transitively) from objects on the marking |
| 1344 // stack. Before: the marking stack contains zero or more heap object | 1345 // stack. Before: the marking stack contains zero or more heap object |
| 1345 // pointers. After: the marking stack is empty and there are no overflowed | 1346 // pointers. After: the marking stack is empty and there are no overflowed |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1363 ProcessMarkingStack(); | 1364 ProcessMarkingStack(); |
| 1364 } | 1365 } |
| 1365 } | 1366 } |
| 1366 | 1367 |
| 1367 | 1368 |
| 1368 void MarkCompactCollector::MarkLiveObjects() { | 1369 void MarkCompactCollector::MarkLiveObjects() { |
| 1369 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK); | 1370 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_MARK); |
| 1370 // The recursive GC marker detects when it is nearing stack overflow, | 1371 // The recursive GC marker detects when it is nearing stack overflow, |
| 1371 // and switches to a different marking system. JS interrupts interfere | 1372 // and switches to a different marking system. JS interrupts interfere |
| 1372 // with the C stack limit check. | 1373 // with the C stack limit check. |
| 1373 PostponeInterruptsScope postpone(heap_->isolate()); | 1374 PostponeInterruptsScope postpone(heap()->isolate()); |
| 1374 | 1375 |
| 1375 #ifdef DEBUG | 1376 #ifdef DEBUG |
| 1376 ASSERT(state_ == PREPARE_GC); | 1377 ASSERT(state_ == PREPARE_GC); |
| 1377 state_ = MARK_LIVE_OBJECTS; | 1378 state_ = MARK_LIVE_OBJECTS; |
| 1378 #endif | 1379 #endif |
| 1379 // The to space contains live objects, the from space is used as a marking | 1380 // The to space contains live objects, the from space is used as a marking |
| 1380 // stack. | 1381 // stack. |
| 1381 marking_stack_.Initialize(heap_->new_space()->FromSpaceLow(), | 1382 marking_stack_.Initialize(heap()->new_space()->FromSpaceLow(), |
| 1382 heap_->new_space()->FromSpaceHigh()); | 1383 heap()->new_space()->FromSpaceHigh()); |
| 1383 | 1384 |
| 1384 ASSERT(!marking_stack_.overflowed()); | 1385 ASSERT(!marking_stack_.overflowed()); |
| 1385 | 1386 |
| 1386 PrepareForCodeFlushing(); | 1387 PrepareForCodeFlushing(); |
| 1387 | 1388 |
| 1388 RootMarkingVisitor root_visitor(heap_); | 1389 RootMarkingVisitor root_visitor(heap()); |
| 1389 MarkRoots(&root_visitor); | 1390 MarkRoots(&root_visitor); |
| 1390 | 1391 |
| 1391 // The objects reachable from the roots are marked, yet unreachable | 1392 // The objects reachable from the roots are marked, yet unreachable |
| 1392 // objects are unmarked. Mark objects reachable due to host | 1393 // objects are unmarked. Mark objects reachable due to host |
| 1393 // application specific logic. | 1394 // application specific logic. |
| 1394 ProcessExternalMarking(); | 1395 ProcessExternalMarking(); |
| 1395 | 1396 |
| 1396 // The objects reachable from the roots or object groups are marked, | 1397 // The objects reachable from the roots or object groups are marked, |
| 1397 // yet unreachable objects are unmarked. Mark objects reachable | 1398 // yet unreachable objects are unmarked. Mark objects reachable |
| 1398 // only from weak global handles. | 1399 // only from weak global handles. |
| 1399 // | 1400 // |
| 1400 // First we identify nonlive weak handles and mark them as pending | 1401 // First we identify nonlive weak handles and mark them as pending |
| 1401 // destruction. | 1402 // destruction. |
| 1402 heap_->isolate()->global_handles()->IdentifyWeakHandles( | 1403 heap()->isolate()->global_handles()->IdentifyWeakHandles( |
| 1403 &IsUnmarkedHeapObject); | 1404 &IsUnmarkedHeapObject); |
| 1404 // Then we mark the objects and process the transitive closure. | 1405 // Then we mark the objects and process the transitive closure. |
| 1405 heap_->isolate()->global_handles()->IterateWeakRoots(&root_visitor); | 1406 heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor); |
| 1406 while (marking_stack_.overflowed()) { | 1407 while (marking_stack_.overflowed()) { |
| 1407 RefillMarkingStack(); | 1408 RefillMarkingStack(); |
| 1408 EmptyMarkingStack(); | 1409 EmptyMarkingStack(); |
| 1409 } | 1410 } |
| 1410 | 1411 |
| 1411 // Repeat host application specific marking to mark unmarked objects | 1412 // Repeat host application specific marking to mark unmarked objects |
| 1412 // reachable from the weak roots. | 1413 // reachable from the weak roots. |
| 1413 ProcessExternalMarking(); | 1414 ProcessExternalMarking(); |
| 1414 | 1415 |
| 1415 // Prune the symbol table removing all symbols only pointed to by the | 1416 // Prune the symbol table removing all symbols only pointed to by the |
| 1416 // symbol table. Cannot use symbol_table() here because the symbol | 1417 // symbol table. Cannot use symbol_table() here because the symbol |
| 1417 // table is marked. | 1418 // table is marked. |
| 1418 SymbolTable* symbol_table = heap_->raw_unchecked_symbol_table(); | 1419 SymbolTable* symbol_table = heap()->raw_unchecked_symbol_table(); |
| 1419 SymbolTableCleaner v; | 1420 SymbolTableCleaner v(heap()); |
| 1420 symbol_table->IterateElements(&v); | 1421 symbol_table->IterateElements(&v); |
| 1421 symbol_table->ElementsRemoved(v.PointersRemoved()); | 1422 symbol_table->ElementsRemoved(v.PointersRemoved()); |
| 1422 heap_->external_string_table_.Iterate(&v); | 1423 heap()->external_string_table_.Iterate(&v); |
| 1423 heap_->external_string_table_.CleanUp(); | 1424 heap()->external_string_table_.CleanUp(); |
| 1424 | 1425 |
| 1425 // Process the weak references. | 1426 // Process the weak references. |
| 1426 MarkCompactWeakObjectRetainer mark_compact_object_retainer; | 1427 MarkCompactWeakObjectRetainer mark_compact_object_retainer; |
| 1427 heap_->ProcessWeakReferences(&mark_compact_object_retainer); | 1428 heap()->ProcessWeakReferences(&mark_compact_object_retainer); |
| 1428 | 1429 |
| 1429 // Remove object groups after marking phase. | 1430 // Remove object groups after marking phase. |
| 1430 heap_->isolate()->global_handles()->RemoveObjectGroups(); | 1431 heap()->isolate()->global_handles()->RemoveObjectGroups(); |
| 1431 heap_->isolate()->global_handles()->RemoveImplicitRefGroups(); | 1432 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); |
| 1432 | 1433 |
| 1433 // Flush code from collected candidates. | 1434 // Flush code from collected candidates. |
| 1434 if (is_code_flushing_enabled()) { | 1435 if (is_code_flushing_enabled()) { |
| 1435 code_flusher_->ProcessCandidates(); | 1436 code_flusher_->ProcessCandidates(); |
| 1436 } | 1437 } |
| 1437 | 1438 |
| 1438 // Clean up dead objects from the runtime profiler. | 1439 // Clean up dead objects from the runtime profiler. |
| 1439 heap_->isolate()->runtime_profiler()->RemoveDeadSamples(); | 1440 heap()->isolate()->runtime_profiler()->RemoveDeadSamples(); |
| 1440 } | 1441 } |
| 1441 | 1442 |
| 1442 | 1443 |
| 1443 #ifdef DEBUG | 1444 #ifdef DEBUG |
| 1444 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { | 1445 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { |
| 1445 live_bytes_ += obj->Size(); | 1446 live_bytes_ += obj->Size(); |
| 1446 if (HEAP->new_space()->Contains(obj)) { | 1447 if (heap()->new_space()->Contains(obj)) { |
| 1447 live_young_objects_size_ += obj->Size(); | 1448 live_young_objects_size_ += obj->Size(); |
| 1448 } else if (HEAP->map_space()->Contains(obj)) { | 1449 } else if (heap()->map_space()->Contains(obj)) { |
| 1449 ASSERT(obj->IsMap()); | 1450 ASSERT(obj->IsMap()); |
| 1450 live_map_objects_size_ += obj->Size(); | 1451 live_map_objects_size_ += obj->Size(); |
| 1451 } else if (HEAP->cell_space()->Contains(obj)) { | 1452 } else if (heap()->cell_space()->Contains(obj)) { |
| 1452 ASSERT(obj->IsJSGlobalPropertyCell()); | 1453 ASSERT(obj->IsJSGlobalPropertyCell()); |
| 1453 live_cell_objects_size_ += obj->Size(); | 1454 live_cell_objects_size_ += obj->Size(); |
| 1454 } else if (HEAP->old_pointer_space()->Contains(obj)) { | 1455 } else if (heap()->old_pointer_space()->Contains(obj)) { |
| 1455 live_old_pointer_objects_size_ += obj->Size(); | 1456 live_old_pointer_objects_size_ += obj->Size(); |
| 1456 } else if (HEAP->old_data_space()->Contains(obj)) { | 1457 } else if (heap()->old_data_space()->Contains(obj)) { |
| 1457 live_old_data_objects_size_ += obj->Size(); | 1458 live_old_data_objects_size_ += obj->Size(); |
| 1458 } else if (HEAP->code_space()->Contains(obj)) { | 1459 } else if (heap()->code_space()->Contains(obj)) { |
| 1459 live_code_objects_size_ += obj->Size(); | 1460 live_code_objects_size_ += obj->Size(); |
| 1460 } else if (HEAP->lo_space()->Contains(obj)) { | 1461 } else if (heap()->lo_space()->Contains(obj)) { |
| 1461 live_lo_objects_size_ += obj->Size(); | 1462 live_lo_objects_size_ += obj->Size(); |
| 1462 } else { | 1463 } else { |
| 1463 UNREACHABLE(); | 1464 UNREACHABLE(); |
| 1464 } | 1465 } |
| 1465 } | 1466 } |
| 1466 #endif // DEBUG | 1467 #endif // DEBUG |
| 1467 | 1468 |
| 1468 | 1469 |
| 1469 void MarkCompactCollector::SweepLargeObjectSpace() { | 1470 void MarkCompactCollector::SweepLargeObjectSpace() { |
| 1470 #ifdef DEBUG | 1471 #ifdef DEBUG |
| 1471 ASSERT(state_ == MARK_LIVE_OBJECTS); | 1472 ASSERT(state_ == MARK_LIVE_OBJECTS); |
| 1472 state_ = | 1473 state_ = |
| 1473 compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES; | 1474 compacting_collection_ ? ENCODE_FORWARDING_ADDRESSES : SWEEP_SPACES; |
| 1474 #endif | 1475 #endif |
| 1475 // Deallocate unmarked objects and clear marked bits for marked objects. | 1476 // Deallocate unmarked objects and clear marked bits for marked objects. |
| 1476 HEAP->lo_space()->FreeUnmarkedObjects(); | 1477 heap()->lo_space()->FreeUnmarkedObjects(); |
| 1477 } | 1478 } |
| 1478 | 1479 |
| 1479 | 1480 |
| 1480 // Safe to use during marking phase only. | 1481 // Safe to use during marking phase only. |
| 1481 bool MarkCompactCollector::SafeIsMap(HeapObject* object) { | 1482 bool MarkCompactCollector::SafeIsMap(HeapObject* object) { |
| 1482 MapWord metamap = object->map_word(); | 1483 MapWord metamap = object->map_word(); |
| 1483 metamap.ClearMark(); | 1484 metamap.ClearMark(); |
| 1484 return metamap.ToMap()->instance_type() == MAP_TYPE; | 1485 return metamap.ToMap()->instance_type() == MAP_TYPE; |
| 1485 } | 1486 } |
| 1486 | 1487 |
| 1487 | 1488 |
| 1488 void MarkCompactCollector::ClearNonLiveTransitions() { | 1489 void MarkCompactCollector::ClearNonLiveTransitions() { |
| 1489 HeapObjectIterator map_iterator(HEAP->map_space(), &SizeOfMarkedObject); | 1490 HeapObjectIterator map_iterator(heap() ->map_space(), &SizeOfMarkedObject); |
| 1490 // Iterate over the map space, setting map transitions that go from | 1491 // Iterate over the map space, setting map transitions that go from |
| 1491 // a marked map to an unmarked map to null transitions. At the same time, | 1492 // a marked map to an unmarked map to null transitions. At the same time, |
| 1492 // set all the prototype fields of maps back to their original value, | 1493 // set all the prototype fields of maps back to their original value, |
| 1493 // dropping the back pointers temporarily stored in the prototype field. | 1494 // dropping the back pointers temporarily stored in the prototype field. |
| 1494 // Setting the prototype field requires following the linked list of | 1495 // Setting the prototype field requires following the linked list of |
| 1495 // back pointers, reversing them all at once. This allows us to find | 1496 // back pointers, reversing them all at once. This allows us to find |
| 1496 // those maps with map transitions that need to be nulled, and only | 1497 // those maps with map transitions that need to be nulled, and only |
| 1497 // scan the descriptor arrays of those maps, not all maps. | 1498 // scan the descriptor arrays of those maps, not all maps. |
| 1498 // All of these actions are carried out only on maps of JSObjects | 1499 // All of these actions are carried out only on maps of JSObjects |
| 1499 // and related subtypes. | 1500 // and related subtypes. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1529 Object* next; | 1530 Object* next; |
| 1530 while (SafeIsMap(current)) { | 1531 while (SafeIsMap(current)) { |
| 1531 next = current->prototype(); | 1532 next = current->prototype(); |
| 1532 // There should never be a dead map above a live map. | 1533 // There should never be a dead map above a live map. |
| 1533 ASSERT(on_dead_path || current->IsMarked()); | 1534 ASSERT(on_dead_path || current->IsMarked()); |
| 1534 | 1535 |
| 1535 // A live map above a dead map indicates a dead transition. | 1536 // A live map above a dead map indicates a dead transition. |
| 1536 // This test will always be false on the first iteration. | 1537 // This test will always be false on the first iteration. |
| 1537 if (on_dead_path && current->IsMarked()) { | 1538 if (on_dead_path && current->IsMarked()) { |
| 1538 on_dead_path = false; | 1539 on_dead_path = false; |
| 1539 current->ClearNonLiveTransitions(heap_, real_prototype); | 1540 current->ClearNonLiveTransitions(heap(), real_prototype); |
| 1540 } | 1541 } |
| 1541 *HeapObject::RawField(current, Map::kPrototypeOffset) = | 1542 *HeapObject::RawField(current, Map::kPrototypeOffset) = |
| 1542 real_prototype; | 1543 real_prototype; |
| 1543 current = reinterpret_cast<Map*>(next); | 1544 current = reinterpret_cast<Map*>(next); |
| 1544 } | 1545 } |
| 1545 } | 1546 } |
| 1546 } | 1547 } |
| 1547 | 1548 |
| 1548 // ------------------------------------------------------------------------- | 1549 // ------------------------------------------------------------------------- |
| 1549 // Phase 2: Encode forwarding addresses. | 1550 // Phase 2: Encode forwarding addresses. |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 } | 1765 } |
| 1765 | 1766 |
| 1766 | 1767 |
| 1767 // Functions to encode the forwarding pointers in each compactable space. | 1768 // Functions to encode the forwarding pointers in each compactable space. |
| 1768 void MarkCompactCollector::EncodeForwardingAddressesInNewSpace() { | 1769 void MarkCompactCollector::EncodeForwardingAddressesInNewSpace() { |
| 1769 int ignored; | 1770 int ignored; |
| 1770 EncodeForwardingAddressesInRange<MCAllocateFromNewSpace, | 1771 EncodeForwardingAddressesInRange<MCAllocateFromNewSpace, |
| 1771 EncodeForwardingAddressInNewSpace, | 1772 EncodeForwardingAddressInNewSpace, |
| 1772 IgnoreNonLiveObject>( | 1773 IgnoreNonLiveObject>( |
| 1773 this, | 1774 this, |
| 1774 heap_->new_space()->bottom(), | 1775 heap()->new_space()->bottom(), |
| 1775 heap_->new_space()->top(), | 1776 heap()->new_space()->top(), |
| 1776 &ignored); | 1777 &ignored); |
| 1777 } | 1778 } |
| 1778 | 1779 |
| 1779 | 1780 |
| 1780 template<MarkCompactCollector::AllocationFunction Alloc, | 1781 template<MarkCompactCollector::AllocationFunction Alloc, |
| 1781 MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive> | 1782 MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive> |
| 1782 void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace( | 1783 void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace( |
| 1783 PagedSpace* space) { | 1784 PagedSpace* space) { |
| 1784 PageIterator it(space, PageIterator::PAGES_IN_USE); | 1785 PageIterator it(space, PageIterator::PAGES_IN_USE); |
| 1785 while (it.has_next()) { | 1786 while (it.has_next()) { |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 space->SetTop(new_allocation_top); | 2188 space->SetTop(new_allocation_top); |
| 2188 } | 2189 } |
| 2189 } | 2190 } |
| 2190 | 2191 |
| 2191 | 2192 |
| 2192 void MarkCompactCollector::EncodeForwardingAddresses() { | 2193 void MarkCompactCollector::EncodeForwardingAddresses() { |
| 2193 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 2194 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
| 2194 // Objects in the active semispace of the young generation may be | 2195 // Objects in the active semispace of the young generation may be |
| 2195 // relocated to the inactive semispace (if not promoted). Set the | 2196 // relocated to the inactive semispace (if not promoted). Set the |
| 2196 // relocation info to the beginning of the inactive semispace. | 2197 // relocation info to the beginning of the inactive semispace. |
| 2197 heap_->new_space()->MCResetRelocationInfo(); | 2198 heap()->new_space()->MCResetRelocationInfo(); |
| 2198 | 2199 |
| 2199 // Compute the forwarding pointers in each space. | 2200 // Compute the forwarding pointers in each space. |
| 2200 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, | 2201 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, |
| 2201 ReportDeleteIfNeeded>( | 2202 ReportDeleteIfNeeded>( |
| 2202 heap_->old_pointer_space()); | 2203 heap()->old_pointer_space()); |
| 2203 | 2204 |
| 2204 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace, | 2205 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace, |
| 2205 IgnoreNonLiveObject>( | 2206 IgnoreNonLiveObject>( |
| 2206 heap_->old_data_space()); | 2207 heap()->old_data_space()); |
| 2207 | 2208 |
| 2208 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace, | 2209 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace, |
| 2209 ReportDeleteIfNeeded>( | 2210 ReportDeleteIfNeeded>( |
| 2210 heap_->code_space()); | 2211 heap()->code_space()); |
| 2211 | 2212 |
| 2212 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace, | 2213 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace, |
| 2213 IgnoreNonLiveObject>( | 2214 IgnoreNonLiveObject>( |
| 2214 heap_->cell_space()); | 2215 heap()->cell_space()); |
| 2215 | 2216 |
| 2216 | 2217 |
| 2217 // Compute new space next to last after the old and code spaces have been | 2218 // Compute new space next to last after the old and code spaces have been |
| 2218 // compacted. Objects in new space can be promoted to old or code space. | 2219 // compacted. Objects in new space can be promoted to old or code space. |
| 2219 EncodeForwardingAddressesInNewSpace(); | 2220 EncodeForwardingAddressesInNewSpace(); |
| 2220 | 2221 |
| 2221 // Compute map space last because computing forwarding addresses | 2222 // Compute map space last because computing forwarding addresses |
| 2222 // overwrites non-live objects. Objects in the other spaces rely on | 2223 // overwrites non-live objects. Objects in the other spaces rely on |
| 2223 // non-live map pointers to get the sizes of non-live objects. | 2224 // non-live map pointers to get the sizes of non-live objects. |
| 2224 EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace, | 2225 EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace, |
| 2225 IgnoreNonLiveObject>( | 2226 IgnoreNonLiveObject>( |
| 2226 heap_->map_space()); | 2227 heap()->map_space()); |
| 2227 | 2228 |
| 2228 // Write relocation info to the top page, so we can use it later. This is | 2229 // Write relocation info to the top page, so we can use it later. This is |
| 2229 // done after promoting objects from the new space so we get the correct | 2230 // done after promoting objects from the new space so we get the correct |
| 2230 // allocation top. | 2231 // allocation top. |
| 2231 heap_->old_pointer_space()->MCWriteRelocationInfoToPage(); | 2232 heap()->old_pointer_space()->MCWriteRelocationInfoToPage(); |
| 2232 heap_->old_data_space()->MCWriteRelocationInfoToPage(); | 2233 heap()->old_data_space()->MCWriteRelocationInfoToPage(); |
| 2233 heap_->code_space()->MCWriteRelocationInfoToPage(); | 2234 heap()->code_space()->MCWriteRelocationInfoToPage(); |
| 2234 heap_->map_space()->MCWriteRelocationInfoToPage(); | 2235 heap()->map_space()->MCWriteRelocationInfoToPage(); |
| 2235 heap_->cell_space()->MCWriteRelocationInfoToPage(); | 2236 heap()->cell_space()->MCWriteRelocationInfoToPage(); |
| 2236 } | 2237 } |
| 2237 | 2238 |
| 2238 | 2239 |
| 2239 class MapIterator : public HeapObjectIterator { | 2240 class MapIterator : public HeapObjectIterator { |
| 2240 public: | 2241 public: |
| 2241 MapIterator() : HeapObjectIterator(HEAP->map_space(), &SizeCallback) { } | 2242 explicit MapIterator(Heap* heap) |
| 2243 : HeapObjectIterator(heap->map_space(), &SizeCallback) { } |
| 2242 | 2244 |
| 2243 explicit MapIterator(Address start) | 2245 MapIterator(Heap* heap, Address start) |
| 2244 : HeapObjectIterator(HEAP->map_space(), start, &SizeCallback) { } | 2246 : HeapObjectIterator(heap->map_space(), start, &SizeCallback) { } |
| 2245 | 2247 |
| 2246 private: | 2248 private: |
| 2247 static int SizeCallback(HeapObject* unused) { | 2249 static int SizeCallback(HeapObject* unused) { |
| 2248 USE(unused); | 2250 USE(unused); |
| 2249 return Map::kSize; | 2251 return Map::kSize; |
| 2250 } | 2252 } |
| 2251 }; | 2253 }; |
| 2252 | 2254 |
| 2253 | 2255 |
| 2254 class MapCompact { | 2256 class MapCompact { |
| 2255 public: | 2257 public: |
| 2256 explicit MapCompact(Heap* heap, int live_maps) | 2258 explicit MapCompact(Heap* heap, int live_maps) |
| 2257 : heap_(heap), | 2259 : heap_(heap), |
| 2258 live_maps_(live_maps), | 2260 live_maps_(live_maps), |
| 2259 to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)), | 2261 to_evacuate_start_(heap->map_space()->TopAfterCompaction(live_maps)), |
| 2260 map_to_evacuate_it_(to_evacuate_start_), | 2262 vacant_map_it_(heap), |
| 2263 map_to_evacuate_it_(heap, to_evacuate_start_), |
| 2261 first_map_to_evacuate_( | 2264 first_map_to_evacuate_( |
| 2262 reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) { | 2265 reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) { |
| 2263 } | 2266 } |
| 2264 | 2267 |
| 2265 void CompactMaps() { | 2268 void CompactMaps() { |
| 2266 // As we know the number of maps to evacuate beforehand, | 2269 // As we know the number of maps to evacuate beforehand, |
| 2267 // we stop then there is no more vacant maps. | 2270 // we stop then there is no more vacant maps. |
| 2268 for (Map* next_vacant_map = NextVacantMap(); | 2271 for (Map* next_vacant_map = NextVacantMap(); |
| 2269 next_vacant_map; | 2272 next_vacant_map; |
| 2270 next_vacant_map = NextVacantMap()) { | 2273 next_vacant_map = NextVacantMap()) { |
| 2271 EvacuateMap(next_vacant_map, NextMapToEvacuate()); | 2274 EvacuateMap(next_vacant_map, NextMapToEvacuate()); |
| 2272 } | 2275 } |
| 2273 | 2276 |
| 2274 #ifdef DEBUG | 2277 #ifdef DEBUG |
| 2275 CheckNoMapsToEvacuate(); | 2278 CheckNoMapsToEvacuate(); |
| 2276 #endif | 2279 #endif |
| 2277 } | 2280 } |
| 2278 | 2281 |
| 2279 void UpdateMapPointersInRoots() { | 2282 void UpdateMapPointersInRoots() { |
| 2280 MapUpdatingVisitor map_updating_visitor; | 2283 MapUpdatingVisitor map_updating_visitor; |
| 2281 heap_->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG); | 2284 heap()->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG); |
| 2282 heap_->isolate()->global_handles()->IterateWeakRoots(&map_updating_visitor); | 2285 heap()->isolate()->global_handles()->IterateWeakRoots( |
| 2286 &map_updating_visitor); |
| 2283 LiveObjectList::IterateElements(&map_updating_visitor); | 2287 LiveObjectList::IterateElements(&map_updating_visitor); |
| 2284 } | 2288 } |
| 2285 | 2289 |
| 2286 void UpdateMapPointersInPagedSpace(PagedSpace* space) { | 2290 void UpdateMapPointersInPagedSpace(PagedSpace* space) { |
| 2287 ASSERT(space != heap_->map_space()); | 2291 ASSERT(space != heap()->map_space()); |
| 2288 | 2292 |
| 2289 PageIterator it(space, PageIterator::PAGES_IN_USE); | 2293 PageIterator it(space, PageIterator::PAGES_IN_USE); |
| 2290 while (it.has_next()) { | 2294 while (it.has_next()) { |
| 2291 Page* p = it.next(); | 2295 Page* p = it.next(); |
| 2292 UpdateMapPointersInRange(heap_, p->ObjectAreaStart(), p->AllocationTop()); | 2296 UpdateMapPointersInRange(heap(), |
| 2297 p->ObjectAreaStart(), |
| 2298 p->AllocationTop()); |
| 2293 } | 2299 } |
| 2294 } | 2300 } |
| 2295 | 2301 |
| 2296 void UpdateMapPointersInNewSpace() { | 2302 void UpdateMapPointersInNewSpace() { |
| 2297 NewSpace* space = heap_->new_space(); | 2303 NewSpace* space = heap()->new_space(); |
| 2298 UpdateMapPointersInRange(heap_, space->bottom(), space->top()); | 2304 UpdateMapPointersInRange(heap(), space->bottom(), space->top()); |
| 2299 } | 2305 } |
| 2300 | 2306 |
| 2301 void UpdateMapPointersInLargeObjectSpace() { | 2307 void UpdateMapPointersInLargeObjectSpace() { |
| 2302 LargeObjectIterator it(heap_->lo_space()); | 2308 LargeObjectIterator it(heap()->lo_space()); |
| 2303 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) | 2309 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) |
| 2304 UpdateMapPointersInObject(heap_, obj); | 2310 UpdateMapPointersInObject(heap(), obj); |
| 2305 } | 2311 } |
| 2306 | 2312 |
| 2307 void Finish() { | 2313 void Finish() { |
| 2308 heap_->map_space()->FinishCompaction(to_evacuate_start_, live_maps_); | 2314 heap()->map_space()->FinishCompaction(to_evacuate_start_, live_maps_); |
| 2309 } | 2315 } |
| 2310 | 2316 |
| 2317 inline Heap* heap() const { return heap_; } |
| 2318 |
| 2311 private: | 2319 private: |
| 2312 Heap* heap_; | 2320 Heap* heap_; |
| 2313 int live_maps_; | 2321 int live_maps_; |
| 2314 Address to_evacuate_start_; | 2322 Address to_evacuate_start_; |
| 2315 MapIterator vacant_map_it_; | 2323 MapIterator vacant_map_it_; |
| 2316 MapIterator map_to_evacuate_it_; | 2324 MapIterator map_to_evacuate_it_; |
| 2317 Map* first_map_to_evacuate_; | 2325 Map* first_map_to_evacuate_; |
| 2318 | 2326 |
| 2319 // Helper class for updating map pointers in HeapObjects. | 2327 // Helper class for updating map pointers in HeapObjects. |
| 2320 class MapUpdatingVisitor: public ObjectVisitor { | 2328 class MapUpdatingVisitor: public ObjectVisitor { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2450 void MarkCompactCollector::SweepSpaces() { | 2458 void MarkCompactCollector::SweepSpaces() { |
| 2451 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); | 2459 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); |
| 2452 | 2460 |
| 2453 ASSERT(state_ == SWEEP_SPACES); | 2461 ASSERT(state_ == SWEEP_SPACES); |
| 2454 ASSERT(!IsCompacting()); | 2462 ASSERT(!IsCompacting()); |
| 2455 // Noncompacting collections simply sweep the spaces to clear the mark | 2463 // Noncompacting collections simply sweep the spaces to clear the mark |
| 2456 // bits and free the nonlive blocks (for old and map spaces). We sweep | 2464 // bits and free the nonlive blocks (for old and map spaces). We sweep |
| 2457 // the map space last because freeing non-live maps overwrites them and | 2465 // the map space last because freeing non-live maps overwrites them and |
| 2458 // the other spaces rely on possibly non-live maps to get the sizes for | 2466 // the other spaces rely on possibly non-live maps to get the sizes for |
| 2459 // non-live objects. | 2467 // non-live objects. |
| 2460 SweepSpace(heap_, heap_->old_pointer_space()); | 2468 SweepSpace(heap(), heap()->old_pointer_space()); |
| 2461 SweepSpace(heap_, heap_->old_data_space()); | 2469 SweepSpace(heap(), heap()->old_data_space()); |
| 2462 SweepSpace(heap_, heap_->code_space()); | 2470 SweepSpace(heap(), heap()->code_space()); |
| 2463 SweepSpace(heap_, heap_->cell_space()); | 2471 SweepSpace(heap(), heap()->cell_space()); |
| 2464 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); | 2472 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); |
| 2465 SweepNewSpace(heap_, heap_->new_space()); | 2473 SweepNewSpace(heap(), heap()->new_space()); |
| 2466 } | 2474 } |
| 2467 SweepSpace(heap_, heap_->map_space()); | 2475 SweepSpace(heap(), heap()->map_space()); |
| 2468 | 2476 |
| 2469 heap_->IterateDirtyRegions(heap_->map_space(), | 2477 heap()->IterateDirtyRegions(heap()->map_space(), |
| 2470 &heap_->IteratePointersInDirtyMapsRegion, | 2478 &heap()->IteratePointersInDirtyMapsRegion, |
| 2471 &UpdatePointerToNewGen, | 2479 &UpdatePointerToNewGen, |
| 2472 heap_->WATERMARK_SHOULD_BE_VALID); | 2480 heap()->WATERMARK_SHOULD_BE_VALID); |
| 2473 | 2481 |
| 2474 intptr_t live_maps_size = heap_->map_space()->Size(); | 2482 intptr_t live_maps_size = heap()->map_space()->Size(); |
| 2475 int live_maps = static_cast<int>(live_maps_size / Map::kSize); | 2483 int live_maps = static_cast<int>(live_maps_size / Map::kSize); |
| 2476 ASSERT(live_map_objects_size_ == live_maps_size); | 2484 ASSERT(live_map_objects_size_ == live_maps_size); |
| 2477 | 2485 |
| 2478 if (heap_->map_space()->NeedsCompaction(live_maps)) { | 2486 if (heap()->map_space()->NeedsCompaction(live_maps)) { |
| 2479 MapCompact map_compact(heap_, live_maps); | 2487 MapCompact map_compact(heap(), live_maps); |
| 2480 | 2488 |
| 2481 map_compact.CompactMaps(); | 2489 map_compact.CompactMaps(); |
| 2482 map_compact.UpdateMapPointersInRoots(); | 2490 map_compact.UpdateMapPointersInRoots(); |
| 2483 | 2491 |
| 2484 PagedSpaces spaces; | 2492 PagedSpaces spaces; |
| 2485 for (PagedSpace* space = spaces.next(); | 2493 for (PagedSpace* space = spaces.next(); |
| 2486 space != NULL; space = spaces.next()) { | 2494 space != NULL; space = spaces.next()) { |
| 2487 if (space == heap_->map_space()) continue; | 2495 if (space == heap()->map_space()) continue; |
| 2488 map_compact.UpdateMapPointersInPagedSpace(space); | 2496 map_compact.UpdateMapPointersInPagedSpace(space); |
| 2489 } | 2497 } |
| 2490 map_compact.UpdateMapPointersInNewSpace(); | 2498 map_compact.UpdateMapPointersInNewSpace(); |
| 2491 map_compact.UpdateMapPointersInLargeObjectSpace(); | 2499 map_compact.UpdateMapPointersInLargeObjectSpace(); |
| 2492 | 2500 |
| 2493 map_compact.Finish(); | 2501 map_compact.Finish(); |
| 2494 } | 2502 } |
| 2495 } | 2503 } |
| 2496 | 2504 |
| 2497 | 2505 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2573 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 2581 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 2574 rinfo->IsPatchedReturnSequence()) || | 2582 rinfo->IsPatchedReturnSequence()) || |
| 2575 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 2583 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 2576 rinfo->IsPatchedDebugBreakSlotSequence())); | 2584 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 2577 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 2585 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 2578 VisitPointer(&target); | 2586 VisitPointer(&target); |
| 2579 rinfo->set_call_address( | 2587 rinfo->set_call_address( |
| 2580 reinterpret_cast<Code*>(target)->instruction_start()); | 2588 reinterpret_cast<Code*>(target)->instruction_start()); |
| 2581 } | 2589 } |
| 2582 | 2590 |
| 2591 inline Heap* heap() const { return heap_; } |
| 2592 |
| 2583 private: | 2593 private: |
| 2584 void UpdatePointer(Object** p) { | 2594 void UpdatePointer(Object** p) { |
| 2585 if (!(*p)->IsHeapObject()) return; | 2595 if (!(*p)->IsHeapObject()) return; |
| 2586 | 2596 |
| 2587 HeapObject* obj = HeapObject::cast(*p); | 2597 HeapObject* obj = HeapObject::cast(*p); |
| 2588 Address old_addr = obj->address(); | 2598 Address old_addr = obj->address(); |
| 2589 Address new_addr; | 2599 Address new_addr; |
| 2590 ASSERT(!heap_->InFromSpace(obj)); | 2600 ASSERT(!heap()->InFromSpace(obj)); |
| 2591 | 2601 |
| 2592 if (heap_->new_space()->Contains(obj)) { | 2602 if (heap()->new_space()->Contains(obj)) { |
| 2593 Address forwarding_pointer_addr = | 2603 Address forwarding_pointer_addr = |
| 2594 heap_->new_space()->FromSpaceLow() + | 2604 heap()->new_space()->FromSpaceLow() + |
| 2595 heap_->new_space()->ToSpaceOffsetForAddress(old_addr); | 2605 heap()->new_space()->ToSpaceOffsetForAddress(old_addr); |
| 2596 new_addr = Memory::Address_at(forwarding_pointer_addr); | 2606 new_addr = Memory::Address_at(forwarding_pointer_addr); |
| 2597 | 2607 |
| 2598 #ifdef DEBUG | 2608 #ifdef DEBUG |
| 2599 ASSERT(heap_->old_pointer_space()->Contains(new_addr) || | 2609 ASSERT(heap()->old_pointer_space()->Contains(new_addr) || |
| 2600 heap_->old_data_space()->Contains(new_addr) || | 2610 heap()->old_data_space()->Contains(new_addr) || |
| 2601 heap_->new_space()->FromSpaceContains(new_addr) || | 2611 heap()->new_space()->FromSpaceContains(new_addr) || |
| 2602 heap_->lo_space()->Contains(HeapObject::FromAddress(new_addr))); | 2612 heap()->lo_space()->Contains(HeapObject::FromAddress(new_addr))); |
| 2603 | 2613 |
| 2604 if (heap_->new_space()->FromSpaceContains(new_addr)) { | 2614 if (heap()->new_space()->FromSpaceContains(new_addr)) { |
| 2605 ASSERT(heap_->new_space()->FromSpaceOffsetForAddress(new_addr) <= | 2615 ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <= |
| 2606 heap_->new_space()->ToSpaceOffsetForAddress(old_addr)); | 2616 heap()->new_space()->ToSpaceOffsetForAddress(old_addr)); |
| 2607 } | 2617 } |
| 2608 #endif | 2618 #endif |
| 2609 | 2619 |
| 2610 } else if (heap_->lo_space()->Contains(obj)) { | 2620 } else if (heap()->lo_space()->Contains(obj)) { |
| 2611 // Don't move objects in the large object space. | 2621 // Don't move objects in the large object space. |
| 2612 return; | 2622 return; |
| 2613 | 2623 |
| 2614 } else { | 2624 } else { |
| 2615 #ifdef DEBUG | 2625 #ifdef DEBUG |
| 2616 PagedSpaces spaces; | 2626 PagedSpaces spaces; |
| 2617 PagedSpace* original_space = spaces.next(); | 2627 PagedSpace* original_space = spaces.next(); |
| 2618 while (original_space != NULL) { | 2628 while (original_space != NULL) { |
| 2619 if (original_space->Contains(obj)) break; | 2629 if (original_space->Contains(obj)) break; |
| 2620 original_space = spaces.next(); | 2630 original_space = spaces.next(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2639 | 2649 |
| 2640 Heap* heap_; | 2650 Heap* heap_; |
| 2641 }; | 2651 }; |
| 2642 | 2652 |
| 2643 | 2653 |
| 2644 void MarkCompactCollector::UpdatePointers() { | 2654 void MarkCompactCollector::UpdatePointers() { |
| 2645 #ifdef DEBUG | 2655 #ifdef DEBUG |
| 2646 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 2656 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
| 2647 state_ = UPDATE_POINTERS; | 2657 state_ = UPDATE_POINTERS; |
| 2648 #endif | 2658 #endif |
| 2649 UpdatingVisitor updating_visitor(heap_); | 2659 UpdatingVisitor updating_visitor(heap()); |
| 2650 heap_->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( | 2660 heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( |
| 2651 &updating_visitor); | 2661 &updating_visitor); |
| 2652 heap_->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); | 2662 heap()->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); |
| 2653 heap_->isolate()->global_handles()->IterateWeakRoots(&updating_visitor); | 2663 heap()->isolate()->global_handles()->IterateWeakRoots(&updating_visitor); |
| 2654 | 2664 |
| 2655 // Update the pointer to the head of the weak list of global contexts. | 2665 // Update the pointer to the head of the weak list of global contexts. |
| 2656 updating_visitor.VisitPointer(&heap_->global_contexts_list_); | 2666 updating_visitor.VisitPointer(&heap()->global_contexts_list_); |
| 2657 | 2667 |
| 2658 LiveObjectList::IterateElements(&updating_visitor); | 2668 LiveObjectList::IterateElements(&updating_visitor); |
| 2659 | 2669 |
| 2660 int live_maps_size = IterateLiveObjects( | 2670 int live_maps_size = IterateLiveObjects( |
| 2661 heap_->map_space(), &MarkCompactCollector::UpdatePointersInOldObject); | 2671 heap()->map_space(), &MarkCompactCollector::UpdatePointersInOldObject); |
| 2662 int live_pointer_olds_size = IterateLiveObjects( | 2672 int live_pointer_olds_size = IterateLiveObjects( |
| 2663 heap_->old_pointer_space(), | 2673 heap()->old_pointer_space(), |
| 2664 &MarkCompactCollector::UpdatePointersInOldObject); | 2674 &MarkCompactCollector::UpdatePointersInOldObject); |
| 2665 int live_data_olds_size = IterateLiveObjects( | 2675 int live_data_olds_size = IterateLiveObjects( |
| 2666 heap_->old_data_space(), | 2676 heap()->old_data_space(), |
| 2667 &MarkCompactCollector::UpdatePointersInOldObject); | 2677 &MarkCompactCollector::UpdatePointersInOldObject); |
| 2668 int live_codes_size = IterateLiveObjects( | 2678 int live_codes_size = IterateLiveObjects( |
| 2669 heap_->code_space(), &MarkCompactCollector::UpdatePointersInOldObject); | 2679 heap()->code_space(), &MarkCompactCollector::UpdatePointersInOldObject); |
| 2670 int live_cells_size = IterateLiveObjects( | 2680 int live_cells_size = IterateLiveObjects( |
| 2671 heap_->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject); | 2681 heap()->cell_space(), &MarkCompactCollector::UpdatePointersInOldObject); |
| 2672 int live_news_size = IterateLiveObjects( | 2682 int live_news_size = IterateLiveObjects( |
| 2673 heap_->new_space(), &MarkCompactCollector::UpdatePointersInNewObject); | 2683 heap()->new_space(), &MarkCompactCollector::UpdatePointersInNewObject); |
| 2674 | 2684 |
| 2675 // Large objects do not move, the map word can be updated directly. | 2685 // Large objects do not move, the map word can be updated directly. |
| 2676 LargeObjectIterator it(heap_->lo_space()); | 2686 LargeObjectIterator it(heap()->lo_space()); |
| 2677 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { | 2687 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) { |
| 2678 UpdatePointersInNewObject(obj); | 2688 UpdatePointersInNewObject(obj); |
| 2679 } | 2689 } |
| 2680 | 2690 |
| 2681 USE(live_maps_size); | 2691 USE(live_maps_size); |
| 2682 USE(live_pointer_olds_size); | 2692 USE(live_pointer_olds_size); |
| 2683 USE(live_data_olds_size); | 2693 USE(live_data_olds_size); |
| 2684 USE(live_codes_size); | 2694 USE(live_codes_size); |
| 2685 USE(live_cells_size); | 2695 USE(live_cells_size); |
| 2686 USE(live_news_size); | 2696 USE(live_news_size); |
| 2687 ASSERT(live_maps_size == live_map_objects_size_); | 2697 ASSERT(live_maps_size == live_map_objects_size_); |
| 2688 ASSERT(live_data_olds_size == live_old_data_objects_size_); | 2698 ASSERT(live_data_olds_size == live_old_data_objects_size_); |
| 2689 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); | 2699 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); |
| 2690 ASSERT(live_codes_size == live_code_objects_size_); | 2700 ASSERT(live_codes_size == live_code_objects_size_); |
| 2691 ASSERT(live_cells_size == live_cell_objects_size_); | 2701 ASSERT(live_cells_size == live_cell_objects_size_); |
| 2692 ASSERT(live_news_size == live_young_objects_size_); | 2702 ASSERT(live_news_size == live_young_objects_size_); |
| 2693 } | 2703 } |
| 2694 | 2704 |
| 2695 | 2705 |
| 2696 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { | 2706 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { |
| 2697 // Keep old map pointers | 2707 // Keep old map pointers |
| 2698 Map* old_map = obj->map(); | 2708 Map* old_map = obj->map(); |
| 2699 ASSERT(old_map->IsHeapObject()); | 2709 ASSERT(old_map->IsHeapObject()); |
| 2700 | 2710 |
| 2701 Address forwarded = GetForwardingAddressInOldSpace(old_map); | 2711 Address forwarded = GetForwardingAddressInOldSpace(old_map); |
| 2702 | 2712 |
| 2703 ASSERT(heap_->map_space()->Contains(old_map)); | 2713 ASSERT(heap()->map_space()->Contains(old_map)); |
| 2704 ASSERT(heap_->map_space()->Contains(forwarded)); | 2714 ASSERT(heap()->map_space()->Contains(forwarded)); |
| 2705 #ifdef DEBUG | 2715 #ifdef DEBUG |
| 2706 if (FLAG_gc_verbose) { | 2716 if (FLAG_gc_verbose) { |
| 2707 PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(), | 2717 PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(), |
| 2708 forwarded); | 2718 forwarded); |
| 2709 } | 2719 } |
| 2710 #endif | 2720 #endif |
| 2711 // Update the map pointer. | 2721 // Update the map pointer. |
| 2712 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded))); | 2722 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded))); |
| 2713 | 2723 |
| 2714 // We have to compute the object size relying on the old map because | 2724 // We have to compute the object size relying on the old map because |
| 2715 // map objects are not relocated yet. | 2725 // map objects are not relocated yet. |
| 2716 int obj_size = obj->SizeFromMap(old_map); | 2726 int obj_size = obj->SizeFromMap(old_map); |
| 2717 | 2727 |
| 2718 // Update pointers in the object body. | 2728 // Update pointers in the object body. |
| 2719 UpdatingVisitor updating_visitor(heap_); | 2729 UpdatingVisitor updating_visitor(heap()); |
| 2720 obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor); | 2730 obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor); |
| 2721 return obj_size; | 2731 return obj_size; |
| 2722 } | 2732 } |
| 2723 | 2733 |
| 2724 | 2734 |
| 2725 int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) { | 2735 int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) { |
| 2726 // Decode the map pointer. | 2736 // Decode the map pointer. |
| 2727 MapWord encoding = obj->map_word(); | 2737 MapWord encoding = obj->map_word(); |
| 2728 Address map_addr = encoding.DecodeMapAddress(heap_->map_space()); | 2738 Address map_addr = encoding.DecodeMapAddress(heap()->map_space()); |
| 2729 ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr))); | 2739 ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr))); |
| 2730 | 2740 |
| 2731 // At this point, the first word of map_addr is also encoded, cannot | 2741 // At this point, the first word of map_addr is also encoded, cannot |
| 2732 // cast it to Map* using Map::cast. | 2742 // cast it to Map* using Map::cast. |
| 2733 Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)); | 2743 Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)); |
| 2734 int obj_size = obj->SizeFromMap(map); | 2744 int obj_size = obj->SizeFromMap(map); |
| 2735 InstanceType type = map->instance_type(); | 2745 InstanceType type = map->instance_type(); |
| 2736 | 2746 |
| 2737 // Update map pointer. | 2747 // Update map pointer. |
| 2738 Address new_map_addr = GetForwardingAddressInOldSpace(map); | 2748 Address new_map_addr = GetForwardingAddressInOldSpace(map); |
| 2739 int offset = encoding.DecodeOffset(); | 2749 int offset = encoding.DecodeOffset(); |
| 2740 obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset)); | 2750 obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset)); |
| 2741 | 2751 |
| 2742 #ifdef DEBUG | 2752 #ifdef DEBUG |
| 2743 if (FLAG_gc_verbose) { | 2753 if (FLAG_gc_verbose) { |
| 2744 PrintF("update %p : %p -> %p\n", obj->address(), | 2754 PrintF("update %p : %p -> %p\n", obj->address(), |
| 2745 map_addr, new_map_addr); | 2755 map_addr, new_map_addr); |
| 2746 } | 2756 } |
| 2747 #endif | 2757 #endif |
| 2748 | 2758 |
| 2749 // Update pointers in the object body. | 2759 // Update pointers in the object body. |
| 2750 UpdatingVisitor updating_visitor(heap_); | 2760 UpdatingVisitor updating_visitor(heap()); |
| 2751 obj->IterateBody(type, obj_size, &updating_visitor); | 2761 obj->IterateBody(type, obj_size, &updating_visitor); |
| 2752 return obj_size; | 2762 return obj_size; |
| 2753 } | 2763 } |
| 2754 | 2764 |
| 2755 | 2765 |
| 2756 Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) { | 2766 Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) { |
| 2757 // Object should either in old or map space. | 2767 // Object should either in old or map space. |
| 2758 MapWord encoding = obj->map_word(); | 2768 MapWord encoding = obj->map_word(); |
| 2759 | 2769 |
| 2760 // Offset to the first live object's forwarding address. | 2770 // Offset to the first live object's forwarding address. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2797 // Phase 4: Relocate objects | 2807 // Phase 4: Relocate objects |
| 2798 | 2808 |
| 2799 void MarkCompactCollector::RelocateObjects() { | 2809 void MarkCompactCollector::RelocateObjects() { |
| 2800 #ifdef DEBUG | 2810 #ifdef DEBUG |
| 2801 ASSERT(state_ == UPDATE_POINTERS); | 2811 ASSERT(state_ == UPDATE_POINTERS); |
| 2802 state_ = RELOCATE_OBJECTS; | 2812 state_ = RELOCATE_OBJECTS; |
| 2803 #endif | 2813 #endif |
| 2804 // Relocates objects, always relocate map objects first. Relocating | 2814 // Relocates objects, always relocate map objects first. Relocating |
| 2805 // objects in other space relies on map objects to get object size. | 2815 // objects in other space relies on map objects to get object size. |
| 2806 int live_maps_size = IterateLiveObjects( | 2816 int live_maps_size = IterateLiveObjects( |
| 2807 heap_->map_space(), &MarkCompactCollector::RelocateMapObject); | 2817 heap()->map_space(), &MarkCompactCollector::RelocateMapObject); |
| 2808 int live_pointer_olds_size = IterateLiveObjects( | 2818 int live_pointer_olds_size = IterateLiveObjects( |
| 2809 heap_->old_pointer_space(), | 2819 heap()->old_pointer_space(), |
| 2810 &MarkCompactCollector::RelocateOldPointerObject); | 2820 &MarkCompactCollector::RelocateOldPointerObject); |
| 2811 int live_data_olds_size = IterateLiveObjects( | 2821 int live_data_olds_size = IterateLiveObjects( |
| 2812 heap_->old_data_space(), &MarkCompactCollector::RelocateOldDataObject); | 2822 heap()->old_data_space(), &MarkCompactCollector::RelocateOldDataObject); |
| 2813 int live_codes_size = IterateLiveObjects( | 2823 int live_codes_size = IterateLiveObjects( |
| 2814 heap_->code_space(), &MarkCompactCollector::RelocateCodeObject); | 2824 heap()->code_space(), &MarkCompactCollector::RelocateCodeObject); |
| 2815 int live_cells_size = IterateLiveObjects( | 2825 int live_cells_size = IterateLiveObjects( |
| 2816 heap_->cell_space(), &MarkCompactCollector::RelocateCellObject); | 2826 heap()->cell_space(), &MarkCompactCollector::RelocateCellObject); |
| 2817 int live_news_size = IterateLiveObjects( | 2827 int live_news_size = IterateLiveObjects( |
| 2818 heap_->new_space(), &MarkCompactCollector::RelocateNewObject); | 2828 heap()->new_space(), &MarkCompactCollector::RelocateNewObject); |
| 2819 | 2829 |
| 2820 USE(live_maps_size); | 2830 USE(live_maps_size); |
| 2821 USE(live_pointer_olds_size); | 2831 USE(live_pointer_olds_size); |
| 2822 USE(live_data_olds_size); | 2832 USE(live_data_olds_size); |
| 2823 USE(live_codes_size); | 2833 USE(live_codes_size); |
| 2824 USE(live_cells_size); | 2834 USE(live_cells_size); |
| 2825 USE(live_news_size); | 2835 USE(live_news_size); |
| 2826 ASSERT(live_maps_size == live_map_objects_size_); | 2836 ASSERT(live_maps_size == live_map_objects_size_); |
| 2827 ASSERT(live_data_olds_size == live_old_data_objects_size_); | 2837 ASSERT(live_data_olds_size == live_old_data_objects_size_); |
| 2828 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); | 2838 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); |
| 2829 ASSERT(live_codes_size == live_code_objects_size_); | 2839 ASSERT(live_codes_size == live_code_objects_size_); |
| 2830 ASSERT(live_cells_size == live_cell_objects_size_); | 2840 ASSERT(live_cells_size == live_cell_objects_size_); |
| 2831 ASSERT(live_news_size == live_young_objects_size_); | 2841 ASSERT(live_news_size == live_young_objects_size_); |
| 2832 | 2842 |
| 2833 // Flip from and to spaces | 2843 // Flip from and to spaces |
| 2834 heap_->new_space()->Flip(); | 2844 heap()->new_space()->Flip(); |
| 2835 | 2845 |
| 2836 heap_->new_space()->MCCommitRelocationInfo(); | 2846 heap()->new_space()->MCCommitRelocationInfo(); |
| 2837 | 2847 |
| 2838 // Set age_mark to bottom in to space | 2848 // Set age_mark to bottom in to space |
| 2839 Address mark = heap_->new_space()->bottom(); | 2849 Address mark = heap()->new_space()->bottom(); |
| 2840 heap_->new_space()->set_age_mark(mark); | 2850 heap()->new_space()->set_age_mark(mark); |
| 2841 | 2851 |
| 2842 PagedSpaces spaces; | 2852 PagedSpaces spaces; |
| 2843 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) | 2853 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) |
| 2844 space->MCCommitRelocationInfo(); | 2854 space->MCCommitRelocationInfo(); |
| 2845 | 2855 |
| 2846 heap_->CheckNewSpaceExpansionCriteria(); | 2856 heap()->CheckNewSpaceExpansionCriteria(); |
| 2847 heap_->IncrementYoungSurvivorsCounter(live_news_size); | 2857 heap()->IncrementYoungSurvivorsCounter(live_news_size); |
| 2848 } | 2858 } |
| 2849 | 2859 |
| 2850 | 2860 |
| 2851 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { | 2861 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { |
| 2852 // Recover map pointer. | 2862 // Recover map pointer. |
| 2853 MapWord encoding = obj->map_word(); | 2863 MapWord encoding = obj->map_word(); |
| 2854 Address map_addr = encoding.DecodeMapAddress(heap_->map_space()); | 2864 Address map_addr = encoding.DecodeMapAddress(heap()->map_space()); |
| 2855 ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr))); | 2865 ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr))); |
| 2856 | 2866 |
| 2857 // Get forwarding address before resetting map pointer | 2867 // Get forwarding address before resetting map pointer |
| 2858 Address new_addr = GetForwardingAddressInOldSpace(obj); | 2868 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 2859 | 2869 |
| 2860 // Reset map pointer. The meta map object may not be copied yet so | 2870 // Reset map pointer. The meta map object may not be copied yet so |
| 2861 // Map::cast does not yet work. | 2871 // Map::cast does not yet work. |
| 2862 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); | 2872 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); |
| 2863 | 2873 |
| 2864 Address old_addr = obj->address(); | 2874 Address old_addr = obj->address(); |
| 2865 | 2875 |
| 2866 if (new_addr != old_addr) { | 2876 if (new_addr != old_addr) { |
| 2867 // Move contents. | 2877 // Move contents. |
| 2868 heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr, | 2878 heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr, |
| 2869 old_addr, | 2879 old_addr, |
| 2870 Map::kSize); | 2880 Map::kSize); |
| 2871 } | 2881 } |
| 2872 | 2882 |
| 2873 #ifdef DEBUG | 2883 #ifdef DEBUG |
| 2874 if (FLAG_gc_verbose) { | 2884 if (FLAG_gc_verbose) { |
| 2875 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 2885 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
| 2876 } | 2886 } |
| 2877 #endif | 2887 #endif |
| 2878 | 2888 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2904 #endif | 2914 #endif |
| 2905 | 2915 |
| 2906 return obj_size; | 2916 return obj_size; |
| 2907 } | 2917 } |
| 2908 | 2918 |
| 2909 | 2919 |
| 2910 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, | 2920 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, |
| 2911 PagedSpace* space) { | 2921 PagedSpace* space) { |
| 2912 // Recover map pointer. | 2922 // Recover map pointer. |
| 2913 MapWord encoding = obj->map_word(); | 2923 MapWord encoding = obj->map_word(); |
| 2914 Address map_addr = encoding.DecodeMapAddress(heap_->map_space()); | 2924 Address map_addr = encoding.DecodeMapAddress(heap()->map_space()); |
| 2915 ASSERT(heap_->map_space()->Contains(map_addr)); | 2925 ASSERT(heap()->map_space()->Contains(map_addr)); |
| 2916 | 2926 |
| 2917 // Get forwarding address before resetting map pointer. | 2927 // Get forwarding address before resetting map pointer. |
| 2918 Address new_addr = GetForwardingAddressInOldSpace(obj); | 2928 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 2919 | 2929 |
| 2920 // Reset the map pointer. | 2930 // Reset the map pointer. |
| 2921 int obj_size = RestoreMap(obj, space, new_addr, map_addr); | 2931 int obj_size = RestoreMap(obj, space, new_addr, map_addr); |
| 2922 | 2932 |
| 2923 Address old_addr = obj->address(); | 2933 Address old_addr = obj->address(); |
| 2924 | 2934 |
| 2925 if (new_addr != old_addr) { | 2935 if (new_addr != old_addr) { |
| 2926 // Move contents. | 2936 // Move contents. |
| 2927 if (space == heap_->old_data_space()) { | 2937 if (space == heap()->old_data_space()) { |
| 2928 heap_->MoveBlock(new_addr, old_addr, obj_size); | 2938 heap()->MoveBlock(new_addr, old_addr, obj_size); |
| 2929 } else { | 2939 } else { |
| 2930 heap_->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr, | 2940 heap()->MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr, |
| 2931 old_addr, | 2941 old_addr, |
| 2932 obj_size); | 2942 obj_size); |
| 2933 } | 2943 } |
| 2934 } | 2944 } |
| 2935 | 2945 |
| 2936 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); | 2946 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
| 2937 | 2947 |
| 2938 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 2948 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
| 2939 if (copied_to->IsSharedFunctionInfo()) { | 2949 if (copied_to->IsSharedFunctionInfo()) { |
| 2940 PROFILE(heap_->isolate(), | 2950 PROFILE(heap()->isolate(), |
| 2941 SharedFunctionInfoMoveEvent(old_addr, new_addr)); | 2951 SharedFunctionInfoMoveEvent(old_addr, new_addr)); |
| 2942 } | 2952 } |
| 2943 HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr)); | 2953 HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr)); |
| 2944 | 2954 |
| 2945 return obj_size; | 2955 return obj_size; |
| 2946 } | 2956 } |
| 2947 | 2957 |
| 2948 | 2958 |
| 2949 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { | 2959 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { |
| 2950 return RelocateOldNonCodeObject(obj, heap_->old_pointer_space()); | 2960 return RelocateOldNonCodeObject(obj, heap()->old_pointer_space()); |
| 2951 } | 2961 } |
| 2952 | 2962 |
| 2953 | 2963 |
| 2954 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { | 2964 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { |
| 2955 return RelocateOldNonCodeObject(obj, heap_->old_data_space()); | 2965 return RelocateOldNonCodeObject(obj, heap()->old_data_space()); |
| 2956 } | 2966 } |
| 2957 | 2967 |
| 2958 | 2968 |
| 2959 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) { | 2969 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) { |
| 2960 return RelocateOldNonCodeObject(obj, heap_->cell_space()); | 2970 return RelocateOldNonCodeObject(obj, heap()->cell_space()); |
| 2961 } | 2971 } |
| 2962 | 2972 |
| 2963 | 2973 |
| 2964 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { | 2974 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { |
| 2965 // Recover map pointer. | 2975 // Recover map pointer. |
| 2966 MapWord encoding = obj->map_word(); | 2976 MapWord encoding = obj->map_word(); |
| 2967 Address map_addr = encoding.DecodeMapAddress(heap_->map_space()); | 2977 Address map_addr = encoding.DecodeMapAddress(heap()->map_space()); |
| 2968 ASSERT(heap_->map_space()->Contains(HeapObject::FromAddress(map_addr))); | 2978 ASSERT(heap()->map_space()->Contains(HeapObject::FromAddress(map_addr))); |
| 2969 | 2979 |
| 2970 // Get forwarding address before resetting map pointer | 2980 // Get forwarding address before resetting map pointer |
| 2971 Address new_addr = GetForwardingAddressInOldSpace(obj); | 2981 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 2972 | 2982 |
| 2973 // Reset the map pointer. | 2983 // Reset the map pointer. |
| 2974 int obj_size = RestoreMap(obj, heap_->code_space(), new_addr, map_addr); | 2984 int obj_size = RestoreMap(obj, heap()->code_space(), new_addr, map_addr); |
| 2975 | 2985 |
| 2976 Address old_addr = obj->address(); | 2986 Address old_addr = obj->address(); |
| 2977 | 2987 |
| 2978 if (new_addr != old_addr) { | 2988 if (new_addr != old_addr) { |
| 2979 // Move contents. | 2989 // Move contents. |
| 2980 heap_->MoveBlock(new_addr, old_addr, obj_size); | 2990 heap()->MoveBlock(new_addr, old_addr, obj_size); |
| 2981 } | 2991 } |
| 2982 | 2992 |
| 2983 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 2993 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
| 2984 if (copied_to->IsCode()) { | 2994 if (copied_to->IsCode()) { |
| 2985 // May also update inline cache target. | 2995 // May also update inline cache target. |
| 2986 Code::cast(copied_to)->Relocate(new_addr - old_addr); | 2996 Code::cast(copied_to)->Relocate(new_addr - old_addr); |
| 2987 // Notify the logger that compiled code has moved. | 2997 // Notify the logger that compiled code has moved. |
| 2988 PROFILE(heap_->isolate(), CodeMoveEvent(old_addr, new_addr)); | 2998 PROFILE(heap()->isolate(), CodeMoveEvent(old_addr, new_addr)); |
| 2989 } | 2999 } |
| 2990 HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr)); | 3000 HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr)); |
| 2991 | 3001 |
| 2992 return obj_size; | 3002 return obj_size; |
| 2993 } | 3003 } |
| 2994 | 3004 |
| 2995 | 3005 |
| 2996 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { | 3006 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { |
| 2997 int obj_size = obj->Size(); | 3007 int obj_size = obj->Size(); |
| 2998 | 3008 |
| 2999 // Get forwarding address | 3009 // Get forwarding address |
| 3000 Address old_addr = obj->address(); | 3010 Address old_addr = obj->address(); |
| 3001 int offset = heap_->new_space()->ToSpaceOffsetForAddress(old_addr); | 3011 int offset = heap()->new_space()->ToSpaceOffsetForAddress(old_addr); |
| 3002 | 3012 |
| 3003 Address new_addr = | 3013 Address new_addr = |
| 3004 Memory::Address_at(heap_->new_space()->FromSpaceLow() + offset); | 3014 Memory::Address_at(heap()->new_space()->FromSpaceLow() + offset); |
| 3005 | 3015 |
| 3006 #ifdef DEBUG | 3016 #ifdef DEBUG |
| 3007 if (heap_->new_space()->FromSpaceContains(new_addr)) { | 3017 if (heap()->new_space()->FromSpaceContains(new_addr)) { |
| 3008 ASSERT(heap_->new_space()->FromSpaceOffsetForAddress(new_addr) <= | 3018 ASSERT(heap()->new_space()->FromSpaceOffsetForAddress(new_addr) <= |
| 3009 heap_->new_space()->ToSpaceOffsetForAddress(old_addr)); | 3019 heap()->new_space()->ToSpaceOffsetForAddress(old_addr)); |
| 3010 } else { | 3020 } else { |
| 3011 ASSERT(heap_->TargetSpace(obj) == heap_->old_pointer_space() || | 3021 ASSERT(heap()->TargetSpace(obj) == heap()->old_pointer_space() || |
| 3012 heap_->TargetSpace(obj) == heap_->old_data_space()); | 3022 heap()->TargetSpace(obj) == heap()->old_data_space()); |
| 3013 } | 3023 } |
| 3014 #endif | 3024 #endif |
| 3015 | 3025 |
| 3016 // New and old addresses cannot overlap. | 3026 // New and old addresses cannot overlap. |
| 3017 if (heap_->InNewSpace(HeapObject::FromAddress(new_addr))) { | 3027 if (heap()->InNewSpace(HeapObject::FromAddress(new_addr))) { |
| 3018 heap_->CopyBlock(new_addr, old_addr, obj_size); | 3028 heap()->CopyBlock(new_addr, old_addr, obj_size); |
| 3019 } else { | 3029 } else { |
| 3020 heap_->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr, | 3030 heap()->CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr, |
| 3021 old_addr, | 3031 old_addr, |
| 3022 obj_size); | 3032 obj_size); |
| 3023 } | 3033 } |
| 3024 | 3034 |
| 3025 #ifdef DEBUG | 3035 #ifdef DEBUG |
| 3026 if (FLAG_gc_verbose) { | 3036 if (FLAG_gc_verbose) { |
| 3027 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 3037 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
| 3028 } | 3038 } |
| 3029 #endif | 3039 #endif |
| 3030 | 3040 |
| 3031 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 3041 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
| 3032 if (copied_to->IsSharedFunctionInfo()) { | 3042 if (copied_to->IsSharedFunctionInfo()) { |
| 3033 PROFILE(heap_->isolate(), | 3043 PROFILE(heap()->isolate(), |
| 3034 SharedFunctionInfoMoveEvent(old_addr, new_addr)); | 3044 SharedFunctionInfoMoveEvent(old_addr, new_addr)); |
| 3035 } | 3045 } |
| 3036 HEAP_PROFILE(heap_, ObjectMoveEvent(old_addr, new_addr)); | 3046 HEAP_PROFILE(heap(), ObjectMoveEvent(old_addr, new_addr)); |
| 3037 | 3047 |
| 3038 return obj_size; | 3048 return obj_size; |
| 3039 } | 3049 } |
| 3040 | 3050 |
| 3041 | 3051 |
| 3042 void MarkCompactCollector::EnableCodeFlushing(bool enable) { | 3052 void MarkCompactCollector::EnableCodeFlushing(bool enable) { |
| 3043 if (enable) { | 3053 if (enable) { |
| 3044 if (code_flusher_ != NULL) return; | 3054 if (code_flusher_ != NULL) return; |
| 3045 code_flusher_ = new CodeFlusher(heap_->isolate()); | 3055 code_flusher_ = new CodeFlusher(heap()->isolate()); |
| 3046 } else { | 3056 } else { |
| 3047 if (code_flusher_ == NULL) return; | 3057 if (code_flusher_ == NULL) return; |
| 3048 delete code_flusher_; | 3058 delete code_flusher_; |
| 3049 code_flusher_ = NULL; | 3059 code_flusher_ = NULL; |
| 3050 } | 3060 } |
| 3051 } | 3061 } |
| 3052 | 3062 |
| 3053 | 3063 |
| 3054 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj, | 3064 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj, |
| 3055 Isolate* isolate) { | 3065 Isolate* isolate) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3073 } | 3083 } |
| 3074 | 3084 |
| 3075 | 3085 |
| 3076 void MarkCompactCollector::Initialize() { | 3086 void MarkCompactCollector::Initialize() { |
| 3077 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 3087 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
| 3078 StaticMarkingVisitor::Initialize(); | 3088 StaticMarkingVisitor::Initialize(); |
| 3079 } | 3089 } |
| 3080 | 3090 |
| 3081 | 3091 |
| 3082 } } // namespace v8::internal | 3092 } } // namespace v8::internal |
| OLD | NEW |