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