Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 #ifdef DEBUG | 94 #ifdef DEBUG |
| 95 class VerifyMarkingVisitor: public ObjectVisitor { | 95 class VerifyMarkingVisitor: public ObjectVisitor { |
| 96 public: | 96 public: |
| 97 void VisitPointers(Object** start, Object** end) { | 97 void VisitPointers(Object** start, Object** end) { |
| 98 for (Object** current = start; current < end; current++) { | 98 for (Object** current = start; current < end; current++) { |
| 99 if ((*current)->IsHeapObject()) { | 99 if ((*current)->IsHeapObject()) { |
| 100 HeapObject* object = HeapObject::cast(*current); | 100 HeapObject* object = HeapObject::cast(*current); |
| 101 ASSERT(Marking::IsMarked(object)); | 101 ASSERT(MarkCompactCollector::IsMarked(object)); |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 } | 104 } |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 | 107 |
| 108 static void VerifyMarking(Address bottom, Address top) { | 108 static void VerifyMarking(Address bottom, Address top) { |
| 109 VerifyMarkingVisitor visitor; | 109 VerifyMarkingVisitor visitor; |
| 110 HeapObject* object; | 110 HeapObject* object; |
| 111 Address next_object_must_be_here_or_later = bottom; | 111 Address next_object_must_be_here_or_later = bottom; |
| 112 | 112 |
| 113 for (Address current = bottom; | 113 for (Address current = bottom; |
| 114 current < top; | 114 current < top; |
| 115 current += kPointerSize) { | 115 current += kPointerSize) { |
| 116 object = HeapObject::FromAddress(current); | 116 object = HeapObject::FromAddress(current); |
| 117 if (Marking::IsMarked(object)) { | 117 if (MarkCompactCollector::IsMarked(object)) { |
| 118 ASSERT(current >= next_object_must_be_here_or_later); | 118 ASSERT(current >= next_object_must_be_here_or_later); |
| 119 object->Iterate(&visitor); | 119 object->Iterate(&visitor); |
| 120 next_object_must_be_here_or_later = current + object->Size(); | 120 next_object_must_be_here_or_later = current + object->Size(); |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 } | 123 } |
| 124 | 124 |
| 125 | 125 |
| 126 static void VerifyMarking(Page* p) { | 126 static void VerifyMarking(Page* p) { |
| 127 VerifyMarking(p->ObjectAreaStart(), p->ObjectAreaEnd()); | 127 VerifyMarking(p->ObjectAreaStart(), p->ObjectAreaEnd()); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 ClearMarkbits(Heap::map_space()); | 231 ClearMarkbits(Heap::map_space()); |
| 232 ClearMarkbits(Heap::old_pointer_space()); | 232 ClearMarkbits(Heap::old_pointer_space()); |
| 233 ClearMarkbits(Heap::old_data_space()); | 233 ClearMarkbits(Heap::old_data_space()); |
| 234 ClearMarkbits(Heap::cell_space()); | 234 ClearMarkbits(Heap::cell_space()); |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 void Marking::TransferMark(Address old_start, Address new_start) { | 238 void Marking::TransferMark(Address old_start, Address new_start) { |
| 239 if (old_start == new_start) return; | 239 if (old_start == new_start) return; |
| 240 | 240 |
| 241 MarkBit new_mark_bit = Marking::MarkBitFrom(new_start); | |
| 242 | |
| 241 if (!IncrementalMarking::IsStopped()) { | 243 if (!IncrementalMarking::IsStopped()) { |
| 242 if (IncrementalMarking::IsBlack(HeapObject::FromAddress(old_start))) { | 244 MarkBit old_mark_bit = Marking::MarkBitFrom(old_start); |
| 243 IncrementalMarking::MarkBlack(HeapObject::FromAddress(new_start)); | 245 if (IncrementalMarking::IsBlack(old_mark_bit)) { |
| 244 ClearMark(old_start); | 246 IncrementalMarking::MarkBlack(old_mark_bit); |
|
Vyacheslav Egorov (Chromium)
2011/03/21 17:16:30
new_mark_bit
Erik Corry
2011/03/21 20:48:53
Good catch.
| |
| 245 } else if (IncrementalMarking::IsGrey(HeapObject::FromAddress(old_start))) { | 247 old_mark_bit.Clear(); |
| 246 ClearMark(old_start + kPointerSize); | 248 } else if (IncrementalMarking::IsGrey(old_mark_bit)) { |
| 247 IncrementalMarking::WhiteToGrey(HeapObject::FromAddress(new_start)); | 249 old_mark_bit.Next().Clear(); |
| 250 IncrementalMarking::WhiteToGrey(HeapObject::FromAddress(new_start), | |
| 251 new_mark_bit); | |
| 248 IncrementalMarking::RestartIfNotMarking(); | 252 IncrementalMarking::RestartIfNotMarking(); |
| 249 // TODO(gc): if we shift huge array in the loop we might end up pushing | 253 // TODO(gc): if we shift huge array in the loop we might end up pushing |
| 250 // to much to marking stack. maybe we should check one or two elements | 254 // to much to marking stack. maybe we should check one or two elements |
| 251 // on top of it to see whether they are equal to old_start. | 255 // on top of it to see whether they are equal to old_start. |
| 252 } | 256 } |
| 253 } else { | 257 } else { |
| 254 if (Heap::InNewSpace(old_start) || !IsMarked(old_start)) { | 258 ASSERT(IncrementalMarking::IsStopped()); |
| 259 if (Heap::InNewSpace(old_start)) { | |
| 255 return; | 260 return; |
| 261 } else { | |
| 262 MarkBit old_mark_bit = Marking::MarkBitFrom(old_start); | |
| 263 if (!old_mark_bit.Get()) { | |
| 264 return; | |
| 265 } | |
| 256 } | 266 } |
| 257 SetMark(new_start); | 267 new_mark_bit.Set(); |
| 258 } | 268 } |
| 259 } | 269 } |
| 260 | 270 |
| 261 | 271 |
| 262 void MarkCompactCollector::Prepare(GCTracer* tracer) { | 272 void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| 263 FLAG_flush_code = false; | 273 FLAG_flush_code = false; |
| 264 FLAG_always_compact = false; | 274 FLAG_always_compact = false; |
| 265 FLAG_never_compact = true; | 275 FLAG_never_compact = true; |
| 266 | 276 |
| 267 // Disable collection of maps if incremental marking is enabled. | 277 // Disable collection of maps if incremental marking is enabled. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 295 } | 305 } |
| 296 #endif | 306 #endif |
| 297 | 307 |
| 298 PagedSpaces spaces; | 308 PagedSpaces spaces; |
| 299 for (PagedSpace* space = spaces.next(); | 309 for (PagedSpace* space = spaces.next(); |
| 300 space != NULL; space = spaces.next()) { | 310 space != NULL; space = spaces.next()) { |
| 301 space->PrepareForMarkCompact(compacting_collection_); | 311 space->PrepareForMarkCompact(compacting_collection_); |
| 302 } | 312 } |
| 303 | 313 |
| 304 if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { | 314 if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { |
| 305 Address new_space_top = Heap::new_space()->top(); | |
| 306 Address new_space_bottom = Heap::new_space()->bottom(); | 315 Address new_space_bottom = Heap::new_space()->bottom(); |
| 316 uintptr_t new_space_size = | |
| 317 RoundUp(Heap::new_space()->top() - new_space_bottom, 32 * kPointerSize); | |
| 307 | 318 |
| 308 Marking::ClearRange(new_space_bottom, | 319 Marking::ClearRange(new_space_bottom, new_space_size); |
| 309 static_cast<int>(new_space_top - new_space_bottom)); | |
| 310 | 320 |
| 311 ClearMarkbits(); | 321 ClearMarkbits(); |
| 312 #ifdef DEBUG | 322 #ifdef DEBUG |
| 313 VerifyMarkbitsAreClean(); | 323 VerifyMarkbitsAreClean(); |
| 314 #endif | 324 #endif |
| 315 } | 325 } |
| 316 | 326 |
| 317 #ifdef DEBUG | 327 #ifdef DEBUG |
| 318 live_bytes_ = 0; | 328 live_bytes_ = 0; |
| 319 live_young_objects_size_ = 0; | 329 live_young_objects_size_ = 0; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile); | 434 Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile); |
| 425 | 435 |
| 426 JSFunction* candidate = jsfunction_candidates_head_; | 436 JSFunction* candidate = jsfunction_candidates_head_; |
| 427 JSFunction* next_candidate; | 437 JSFunction* next_candidate; |
| 428 while (candidate != NULL) { | 438 while (candidate != NULL) { |
| 429 next_candidate = GetNextCandidate(candidate); | 439 next_candidate = GetNextCandidate(candidate); |
| 430 | 440 |
| 431 SharedFunctionInfo* shared = candidate->unchecked_shared(); | 441 SharedFunctionInfo* shared = candidate->unchecked_shared(); |
| 432 | 442 |
| 433 Code* code = shared->unchecked_code(); | 443 Code* code = shared->unchecked_code(); |
| 434 if (!Marking::IsMarked(code->address())) { | 444 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 445 if (!code_mark.Get()) { | |
| 435 shared->set_code(lazy_compile); | 446 shared->set_code(lazy_compile); |
| 436 candidate->set_code(lazy_compile); | 447 candidate->set_code(lazy_compile); |
| 437 } else { | 448 } else { |
| 438 candidate->set_code(shared->unchecked_code()); | 449 candidate->set_code(shared->unchecked_code()); |
| 439 } | 450 } |
| 440 | 451 |
| 441 candidate = next_candidate; | 452 candidate = next_candidate; |
| 442 } | 453 } |
| 443 | 454 |
| 444 jsfunction_candidates_head_ = NULL; | 455 jsfunction_candidates_head_ = NULL; |
| 445 } | 456 } |
| 446 | 457 |
| 447 | 458 |
| 448 static void ProcessSharedFunctionInfoCandidates() { | 459 static void ProcessSharedFunctionInfoCandidates() { |
| 449 Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile); | 460 Code* lazy_compile = Builtins::builtin(Builtins::LazyCompile); |
| 450 | 461 |
| 451 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 462 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
| 452 SharedFunctionInfo* next_candidate; | 463 SharedFunctionInfo* next_candidate; |
| 453 while (candidate != NULL) { | 464 while (candidate != NULL) { |
| 454 next_candidate = GetNextCandidate(candidate); | 465 next_candidate = GetNextCandidate(candidate); |
| 455 SetNextCandidate(candidate, NULL); | 466 SetNextCandidate(candidate, NULL); |
| 456 | 467 |
| 457 Code* code = candidate->unchecked_code(); | 468 Code* code = candidate->unchecked_code(); |
| 458 if (!Marking::IsMarked(code->address())) { | 469 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 470 if (!code_mark.Get()) { | |
| 459 candidate->set_code(lazy_compile); | 471 candidate->set_code(lazy_compile); |
| 460 } | 472 } |
| 461 | 473 |
| 462 candidate = next_candidate; | 474 candidate = next_candidate; |
| 463 } | 475 } |
| 464 | 476 |
| 465 shared_function_info_candidates_head_ = NULL; | 477 shared_function_info_candidates_head_ = NULL; |
| 466 } | 478 } |
| 467 | 479 |
| 468 | 480 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 643 } | 655 } |
| 644 | 656 |
| 645 static inline void VisitCodeTarget(RelocInfo* rinfo) { | 657 static inline void VisitCodeTarget(RelocInfo* rinfo) { |
| 646 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 658 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 647 Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 659 Code* code = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 648 if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) { | 660 if (FLAG_cleanup_ics_at_gc && code->is_inline_cache_stub()) { |
| 649 IC::Clear(rinfo->pc()); | 661 IC::Clear(rinfo->pc()); |
| 650 // Please note targets for cleared inline cached do not have to be | 662 // Please note targets for cleared inline cached do not have to be |
| 651 // marked since they are contained in Heap::non_monomorphic_cache(). | 663 // marked since they are contained in Heap::non_monomorphic_cache(). |
| 652 } else { | 664 } else { |
| 653 MarkCompactCollector::MarkObject(code); | 665 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 666 MarkCompactCollector::MarkObject(code, code_mark); | |
| 654 } | 667 } |
| 655 } | 668 } |
| 656 | 669 |
| 657 static void VisitGlobalPropertyCell(RelocInfo* rinfo) { | 670 static void VisitGlobalPropertyCell(RelocInfo* rinfo) { |
| 658 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); | 671 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); |
| 659 Object* cell = rinfo->target_cell(); | 672 Object* cell = rinfo->target_cell(); |
| 660 Object* old_cell = cell; | 673 Object* old_cell = cell; |
| 661 VisitPointer(&cell); | 674 VisitPointer(&cell); |
| 662 if (cell != old_cell) { | 675 if (cell != old_cell) { |
| 663 rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell), | 676 rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell), |
| 664 NULL); | 677 NULL); |
| 665 } | 678 } |
| 666 } | 679 } |
| 667 | 680 |
| 668 static inline void VisitDebugTarget(RelocInfo* rinfo) { | 681 static inline void VisitDebugTarget(RelocInfo* rinfo) { |
| 669 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 682 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 670 rinfo->IsPatchedReturnSequence()) || | 683 rinfo->IsPatchedReturnSequence()) || |
| 671 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 684 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 672 rinfo->IsPatchedDebugBreakSlotSequence())); | 685 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 673 HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 686 HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 674 MarkCompactCollector::MarkObject(code); | 687 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 688 MarkCompactCollector::MarkObject(code, code_mark); | |
| 675 } | 689 } |
| 676 | 690 |
| 677 // Mark object pointed to by p. | 691 // Mark object pointed to by p. |
| 678 INLINE(static void MarkObjectByPointer(Object** p)) { | 692 INLINE(static void MarkObjectByPointer(Object** p)) { |
| 679 if (!(*p)->IsHeapObject()) return; | 693 if (!(*p)->IsHeapObject()) return; |
| 680 HeapObject* object = ShortCircuitConsString(p); | 694 HeapObject* object = ShortCircuitConsString(p); |
| 681 MarkCompactCollector::MarkObject(object); | 695 MarkBit mark = Marking::MarkBitFrom(object); |
| 696 MarkCompactCollector::MarkObject(object, mark); | |
| 682 } | 697 } |
| 683 | 698 |
| 684 // Visit an unmarked object. | 699 // Visit an unmarked object. |
| 685 static inline void VisitUnmarkedObject(HeapObject* obj) { | 700 static inline void VisitUnmarkedObject(HeapObject* obj) { |
| 686 #ifdef DEBUG | 701 #ifdef DEBUG |
| 687 ASSERT(Heap::Contains(obj)); | 702 ASSERT(Heap::Contains(obj)); |
| 688 ASSERT(!Marking::IsMarked(obj->address())); | 703 ASSERT(!MarkCompactCollector::IsMarked(obj)); |
| 689 #endif | 704 #endif |
| 690 Map* map = obj->map(); | 705 Map* map = obj->map(); |
| 691 MarkCompactCollector::SetMark(obj); | 706 MarkBit mark = Marking::MarkBitFrom(obj); |
| 707 MarkCompactCollector::SetMark(obj, mark); | |
| 692 // Mark the map pointer and the body. | 708 // Mark the map pointer and the body. |
| 693 MarkCompactCollector::MarkObject(map); | 709 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 710 MarkCompactCollector::MarkObject(map, map_mark); | |
| 694 IterateBody(map, obj); | 711 IterateBody(map, obj); |
| 695 } | 712 } |
| 696 | 713 |
| 697 // Visit all unmarked objects pointed to by [start, end). | 714 // Visit all unmarked objects pointed to by [start, end). |
| 698 // Returns false if the operation fails (lack of stack space). | 715 // Returns false if the operation fails (lack of stack space). |
| 699 static inline bool VisitUnmarkedObjects(Object** start, Object** end) { | 716 static inline bool VisitUnmarkedObjects(Object** start, Object** end) { |
| 700 // Return false is we are close to the stack limit. | 717 // Return false is we are close to the stack limit. |
| 701 StackLimitCheck check; | 718 StackLimitCheck check; |
| 702 if (check.HasOverflowed()) return false; | 719 if (check.HasOverflowed()) return false; |
| 703 | 720 |
| 704 // Visit the unmarked objects. | 721 // Visit the unmarked objects. |
| 705 for (Object** p = start; p < end; p++) { | 722 for (Object** p = start; p < end; p++) { |
| 706 if (!(*p)->IsHeapObject()) continue; | 723 Object* o = *p; |
| 707 HeapObject* obj = HeapObject::cast(*p); | 724 if (!o->IsHeapObject()) continue; |
| 708 if (Marking::IsMarked(obj)) continue; | 725 HeapObject* obj = HeapObject::cast(o); |
| 726 MarkBit mark = Marking::MarkBitFrom(obj); | |
| 727 if (mark.Get()) continue; | |
| 709 VisitUnmarkedObject(obj); | 728 VisitUnmarkedObject(obj); |
| 710 } | 729 } |
| 711 return true; | 730 return true; |
| 712 } | 731 } |
| 713 | 732 |
| 714 static inline void VisitExternalReference(Address* p) { } | 733 static inline void VisitExternalReference(Address* p) { } |
| 715 static inline void VisitRuntimeEntry(RelocInfo* rinfo) { } | 734 static inline void VisitRuntimeEntry(RelocInfo* rinfo) { } |
| 716 | 735 |
| 717 private: | 736 private: |
| 718 class DataObjectVisitor { | 737 class DataObjectVisitor { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 759 inline static bool IsCompiled(SharedFunctionInfo* function) { | 778 inline static bool IsCompiled(SharedFunctionInfo* function) { |
| 760 return | 779 return |
| 761 function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile); | 780 function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile); |
| 762 } | 781 } |
| 763 | 782 |
| 764 inline static bool IsFlushable(JSFunction* function) { | 783 inline static bool IsFlushable(JSFunction* function) { |
| 765 SharedFunctionInfo* shared_info = function->unchecked_shared(); | 784 SharedFunctionInfo* shared_info = function->unchecked_shared(); |
| 766 | 785 |
| 767 // Code is either on stack, in compilation cache or referenced | 786 // Code is either on stack, in compilation cache or referenced |
| 768 // by optimized version of function. | 787 // by optimized version of function. |
| 769 if (Marking::IsMarked(function->unchecked_code())) { | 788 MarkBit code_mark = Marking::MarkBitFrom(function->unchecked_code()); |
| 789 if (code_mark.Get()) { | |
| 770 shared_info->set_code_age(0); | 790 shared_info->set_code_age(0); |
| 771 return false; | 791 return false; |
| 772 } | 792 } |
| 773 | 793 |
| 774 // We do not flush code for optimized functions. | 794 // We do not flush code for optimized functions. |
| 775 if (function->code() != shared_info->unchecked_code()) { | 795 if (function->code() != shared_info->unchecked_code()) { |
| 776 return false; | 796 return false; |
| 777 } | 797 } |
| 778 | 798 |
| 779 return IsFlushable(shared_info); | 799 return IsFlushable(shared_info); |
| 780 } | 800 } |
| 781 | 801 |
| 782 inline static bool IsFlushable(SharedFunctionInfo* shared_info) { | 802 inline static bool IsFlushable(SharedFunctionInfo* shared_info) { |
| 783 // Code is either on stack, in compilation cache or referenced | 803 // Code is either on stack, in compilation cache or referenced |
| 784 // by optimized version of function. | 804 // by optimized version of function. |
| 785 if (Marking::IsMarked(shared_info->unchecked_code())) { | 805 MarkBit code_mark = Marking::MarkBitFrom(shared_info->unchecked_code()); |
| 806 if (code_mark.Get()) { | |
| 786 shared_info->set_code_age(0); | 807 shared_info->set_code_age(0); |
| 787 return false; | 808 return false; |
| 788 } | 809 } |
| 789 | 810 |
| 790 // The function must be compiled and have the source code available, | 811 // The function must be compiled and have the source code available, |
| 791 // to be able to recompile it in case we need the function again. | 812 // to be able to recompile it in case we need the function again. |
| 792 if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) { | 813 if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) { |
| 793 return false; | 814 return false; |
| 794 } | 815 } |
| 795 | 816 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 909 | 930 |
| 910 static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { | 931 static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { |
| 911 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); | 932 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); |
| 912 // The function must have a valid context and not be a builtin. | 933 // The function must have a valid context and not be a builtin. |
| 913 bool flush_code_candidate = false; | 934 bool flush_code_candidate = false; |
| 914 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { | 935 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { |
| 915 flush_code_candidate = FlushCodeForFunction(jsfunction); | 936 flush_code_candidate = FlushCodeForFunction(jsfunction); |
| 916 } | 937 } |
| 917 | 938 |
| 918 if (!flush_code_candidate) { | 939 if (!flush_code_candidate) { |
| 919 MarkCompactCollector::MarkObject( | 940 Code* code = jsfunction->unchecked_shared()->unchecked_code(); |
| 920 jsfunction->unchecked_shared()->unchecked_code()); | 941 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 942 MarkCompactCollector::MarkObject(code, code_mark); | |
| 921 | 943 |
| 922 if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) { | 944 if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) { |
| 923 // For optimized functions we should retain both non-optimized version | 945 // For optimized functions we should retain both non-optimized version |
| 924 // of it's code and non-optimized version of all inlined functions. | 946 // of it's code and non-optimized version of all inlined functions. |
| 925 // This is required to support bailing out from inlined code. | 947 // This is required to support bailing out from inlined code. |
| 926 DeoptimizationInputData* data = | 948 DeoptimizationInputData* data = |
| 927 reinterpret_cast<DeoptimizationInputData*>( | 949 reinterpret_cast<DeoptimizationInputData*>( |
| 928 jsfunction->unchecked_code()->unchecked_deoptimization_data()); | 950 jsfunction->unchecked_code()->unchecked_deoptimization_data()); |
| 929 | 951 |
| 930 FixedArray* literals = data->UncheckedLiteralArray(); | 952 FixedArray* literals = data->UncheckedLiteralArray(); |
| 931 | 953 |
| 932 for (int i = 0, count = data->InlinedFunctionCount()->value(); | 954 for (int i = 0, count = data->InlinedFunctionCount()->value(); |
| 933 i < count; | 955 i < count; |
| 934 i++) { | 956 i++) { |
| 935 JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i)); | 957 JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i)); |
| 936 MarkCompactCollector::MarkObject( | 958 Code* inlined_code = inlined->unchecked_shared()->unchecked_code(); |
|
Vyacheslav Egorov (Chromium)
2011/03/21 17:16:30
I think we will need to kill all unchecked_* gette
Erik Corry
2011/03/21 20:48:53
Done.
| |
| 937 inlined->unchecked_shared()->unchecked_code()); | 959 MarkBit inlined_code_mark = Marking::MarkBitFrom(inlined_code); |
| 960 MarkCompactCollector::MarkObject(inlined_code, inlined_code_mark); | |
| 938 } | 961 } |
| 939 } | 962 } |
| 940 } | 963 } |
| 941 | 964 |
| 942 VisitJSFunctionFields(map, | 965 VisitJSFunctionFields(map, |
| 943 reinterpret_cast<JSFunction*>(object), | 966 reinterpret_cast<JSFunction*>(object), |
| 944 flush_code_candidate); | 967 flush_code_candidate); |
| 945 } | 968 } |
| 946 | 969 |
| 947 | 970 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 963 SLOT_ADDR(object, JSFunction::kCodeEntryOffset)); | 986 SLOT_ADDR(object, JSFunction::kCodeEntryOffset)); |
| 964 | 987 |
| 965 if (!flush_code_candidate) { | 988 if (!flush_code_candidate) { |
| 966 VisitCodeEntry(object->address() + JSFunction::kCodeEntryOffset); | 989 VisitCodeEntry(object->address() + JSFunction::kCodeEntryOffset); |
| 967 } else { | 990 } else { |
| 968 // Don't visit code object. | 991 // Don't visit code object. |
| 969 | 992 |
| 970 // Visit shared function info to avoid double checking of it's | 993 // Visit shared function info to avoid double checking of it's |
| 971 // flushability. | 994 // flushability. |
| 972 SharedFunctionInfo* shared_info = object->unchecked_shared(); | 995 SharedFunctionInfo* shared_info = object->unchecked_shared(); |
| 973 if (!Marking::IsMarked(shared_info)) { | 996 MarkBit shared_info_mark = Marking::MarkBitFrom(shared_info); |
| 997 if (!shared_info_mark.Get()) { | |
| 974 Map* shared_info_map = shared_info->map(); | 998 Map* shared_info_map = shared_info->map(); |
| 975 MarkCompactCollector::SetMark(shared_info); | 999 MarkBit shared_info_map_mark = Marking::MarkBitFrom(shared_info_map); |
| 976 MarkCompactCollector::MarkObject(shared_info_map); | 1000 MarkCompactCollector::SetMark(shared_info, shared_info_mark); |
| 1001 MarkCompactCollector::MarkObject(shared_info_map, shared_info_map_mark); | |
| 977 VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map, | 1002 VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map, |
| 978 shared_info, | 1003 shared_info, |
| 979 true); | 1004 true); |
| 980 } | 1005 } |
| 981 } | 1006 } |
| 982 | 1007 |
| 983 VisitPointers(SLOT_ADDR(object, | 1008 VisitPointers(SLOT_ADDR(object, |
| 984 JSFunction::kCodeEntryOffset + kPointerSize), | 1009 JSFunction::kCodeEntryOffset + kPointerSize), |
| 985 SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset)); | 1010 SLOT_ADDR(object, JSFunction::kNonWeakFieldsEndOffset)); |
| 986 | 1011 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1033 void VisitDebugTarget(RelocInfo* rinfo) { | 1058 void VisitDebugTarget(RelocInfo* rinfo) { |
| 1034 StaticMarkingVisitor::VisitDebugTarget(rinfo); | 1059 StaticMarkingVisitor::VisitDebugTarget(rinfo); |
| 1035 } | 1060 } |
| 1036 }; | 1061 }; |
| 1037 | 1062 |
| 1038 | 1063 |
| 1039 class CodeMarkingVisitor : public ThreadVisitor { | 1064 class CodeMarkingVisitor : public ThreadVisitor { |
| 1040 public: | 1065 public: |
| 1041 void VisitThread(ThreadLocalTop* top) { | 1066 void VisitThread(ThreadLocalTop* top) { |
| 1042 for (StackFrameIterator it(top); !it.done(); it.Advance()) { | 1067 for (StackFrameIterator it(top); !it.done(); it.Advance()) { |
| 1043 MarkCompactCollector::MarkObject(it.frame()->unchecked_code()); | 1068 Code* code = it.frame()->unchecked_code(); |
| 1069 MarkBit code_bit = Marking::MarkBitFrom(code); | |
| 1070 MarkCompactCollector::MarkObject(it.frame()->unchecked_code(), code_bit); | |
| 1044 } | 1071 } |
| 1045 } | 1072 } |
| 1046 }; | 1073 }; |
| 1047 | 1074 |
| 1048 | 1075 |
| 1049 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { | 1076 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { |
| 1050 public: | 1077 public: |
| 1051 void VisitPointers(Object** start, Object** end) { | 1078 void VisitPointers(Object** start, Object** end) { |
| 1052 for (Object** p = start; p < end; p++) VisitPointer(p); | 1079 for (Object** p = start; p < end; p++) VisitPointer(p); |
| 1053 } | 1080 } |
| 1054 | 1081 |
| 1055 void VisitPointer(Object** slot) { | 1082 void VisitPointer(Object** slot) { |
| 1056 Object* obj = *slot; | 1083 Object* obj = *slot; |
| 1057 if (obj->IsSharedFunctionInfo()) { | 1084 if (obj->IsSharedFunctionInfo()) { |
| 1058 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); | 1085 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); |
| 1059 MarkCompactCollector::MarkObject(shared->unchecked_code()); | 1086 MarkBit shared_mark = Marking::MarkBitFrom(shared); |
| 1060 MarkCompactCollector::MarkObject(shared); | 1087 MarkBit code_mark = Marking::MarkBitFrom(shared->unchecked_code()); |
| 1088 MarkCompactCollector::MarkObject(shared->unchecked_code(), code_mark); | |
| 1089 MarkCompactCollector::MarkObject(shared, shared_mark); | |
| 1061 } | 1090 } |
| 1062 } | 1091 } |
| 1063 }; | 1092 }; |
| 1064 | 1093 |
| 1065 | 1094 |
| 1066 void MarkCompactCollector::PrepareForCodeFlushing() { | 1095 void MarkCompactCollector::PrepareForCodeFlushing() { |
| 1067 if (!FLAG_flush_code) { | 1096 if (!FLAG_flush_code) { |
| 1068 StaticMarkingVisitor::EnableCodeFlushing(false); | 1097 StaticMarkingVisitor::EnableCodeFlushing(false); |
| 1069 return; | 1098 return; |
| 1070 } | 1099 } |
| 1071 | 1100 |
| 1072 #ifdef ENABLE_DEBUGGER_SUPPORT | 1101 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1073 if (Debug::IsLoaded() || Debug::has_break_points()) { | 1102 if (Debug::IsLoaded() || Debug::has_break_points()) { |
| 1074 StaticMarkingVisitor::EnableCodeFlushing(false); | 1103 StaticMarkingVisitor::EnableCodeFlushing(false); |
| 1075 return; | 1104 return; |
| 1076 } | 1105 } |
| 1077 #endif | 1106 #endif |
| 1078 StaticMarkingVisitor::EnableCodeFlushing(true); | 1107 StaticMarkingVisitor::EnableCodeFlushing(true); |
| 1079 | 1108 |
| 1080 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray | 1109 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray |
| 1081 // relies on it being marked before any other descriptor array. | 1110 // relies on it being marked before any other descriptor array. |
| 1082 MarkObject(Heap::raw_unchecked_empty_descriptor_array()); | 1111 HeapObject* descriptor_array = Heap::raw_unchecked_empty_descriptor_array(); |
| 1112 MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array); | |
| 1113 MarkObject(descriptor_array, descriptor_array_mark); | |
| 1083 | 1114 |
| 1084 // Make sure we are not referencing the code from the stack. | 1115 // Make sure we are not referencing the code from the stack. |
| 1085 for (StackFrameIterator it; !it.done(); it.Advance()) { | 1116 for (StackFrameIterator it; !it.done(); it.Advance()) { |
| 1086 MarkObject(it.frame()->unchecked_code()); | 1117 Code* code = it.frame()->unchecked_code(); |
| 1118 MarkBit code_mark = Marking::MarkBitFrom(code); | |
| 1119 MarkObject(code, code_mark); | |
| 1087 } | 1120 } |
| 1088 | 1121 |
| 1089 // Iterate the archived stacks in all threads to check if | 1122 // Iterate the archived stacks in all threads to check if |
| 1090 // the code is referenced. | 1123 // the code is referenced. |
| 1091 CodeMarkingVisitor code_marking_visitor; | 1124 CodeMarkingVisitor code_marking_visitor; |
| 1092 ThreadManager::IterateArchivedThreads(&code_marking_visitor); | 1125 ThreadManager::IterateArchivedThreads(&code_marking_visitor); |
| 1093 | 1126 |
| 1094 SharedFunctionInfoMarkingVisitor visitor; | 1127 SharedFunctionInfoMarkingVisitor visitor; |
| 1095 CompilationCache::IterateFunctions(&visitor); | 1128 CompilationCache::IterateFunctions(&visitor); |
| 1096 HandleScopeImplementer::Iterate(&visitor); | 1129 HandleScopeImplementer::Iterate(&visitor); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1109 void VisitPointers(Object** start, Object** end) { | 1142 void VisitPointers(Object** start, Object** end) { |
| 1110 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 1143 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 1111 } | 1144 } |
| 1112 | 1145 |
| 1113 private: | 1146 private: |
| 1114 void MarkObjectByPointer(Object** p) { | 1147 void MarkObjectByPointer(Object** p) { |
| 1115 if (!(*p)->IsHeapObject()) return; | 1148 if (!(*p)->IsHeapObject()) return; |
| 1116 | 1149 |
| 1117 // Replace flat cons strings in place. | 1150 // Replace flat cons strings in place. |
| 1118 HeapObject* object = ShortCircuitConsString(p); | 1151 HeapObject* object = ShortCircuitConsString(p); |
| 1119 if (Marking::IsMarked(object)) return; | 1152 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 1153 if (mark_bit.Get()) return; | |
| 1120 | 1154 |
| 1121 Map* map = object->map(); | 1155 Map* map = object->map(); |
| 1122 // Mark the object. | 1156 // Mark the object. |
| 1123 MarkCompactCollector::SetMark(object); | 1157 MarkCompactCollector::SetMark(object, mark_bit); |
| 1124 | 1158 |
| 1125 // Mark the map pointer and body, and push them on the marking stack. | 1159 // Mark the map pointer and body, and push them on the marking stack. |
| 1126 MarkCompactCollector::MarkObject(map); | 1160 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1161 MarkCompactCollector::MarkObject(map, map_mark); | |
| 1127 StaticMarkingVisitor::IterateBody(map, object); | 1162 StaticMarkingVisitor::IterateBody(map, object); |
| 1128 | 1163 |
| 1129 // Mark all the objects reachable from the map and body. May leave | 1164 // Mark all the objects reachable from the map and body. May leave |
| 1130 // overflowed objects in the heap. | 1165 // overflowed objects in the heap. |
| 1131 MarkCompactCollector::EmptyMarkingStack(); | 1166 MarkCompactCollector::EmptyMarkingStack(); |
| 1132 } | 1167 } |
| 1133 }; | 1168 }; |
| 1134 | 1169 |
| 1135 | 1170 |
| 1136 // Helper class for pruning the symbol table. | 1171 // Helper class for pruning the symbol table. |
| 1137 class SymbolTableCleaner : public ObjectVisitor { | 1172 class SymbolTableCleaner : public ObjectVisitor { |
| 1138 public: | 1173 public: |
| 1139 SymbolTableCleaner() : pointers_removed_(0) { } | 1174 SymbolTableCleaner() : pointers_removed_(0) { } |
| 1140 | 1175 |
| 1141 virtual void VisitPointers(Object** start, Object** end) { | 1176 virtual void VisitPointers(Object** start, Object** end) { |
| 1142 // Visit all HeapObject pointers in [start, end). | 1177 // Visit all HeapObject pointers in [start, end). |
| 1143 for (Object** p = start; p < end; p++) { | 1178 for (Object** p = start; p < end; p++) { |
| 1144 if ((*p)->IsHeapObject() && | 1179 Object* o = *p; |
| 1145 !Marking::IsMarked(HeapObject::cast(*p))) { | 1180 if (o->IsHeapObject() && |
| 1181 !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) { | |
| 1146 // Check if the symbol being pruned is an external symbol. We need to | 1182 // Check if the symbol being pruned is an external symbol. We need to |
| 1147 // delete the associated external data as this symbol is going away. | 1183 // delete the associated external data as this symbol is going away. |
| 1148 | 1184 |
| 1149 // Since no objects have yet been moved we can safely access the map of | 1185 // Since no objects have yet been moved we can safely access the map of |
| 1150 // the object. | 1186 // the object. |
| 1151 if ((*p)->IsExternalString()) { | 1187 if (o->IsExternalString()) { |
| 1152 Heap::FinalizeExternalString(String::cast(*p)); | 1188 Heap::FinalizeExternalString(String::cast(o)); |
| 1153 } | 1189 } |
| 1154 // Set the entry to null_value (as deleted). | 1190 // Set the entry to null_value (as deleted). |
| 1155 *p = Heap::raw_unchecked_null_value(); | 1191 *p = Heap::raw_unchecked_null_value(); |
| 1156 pointers_removed_++; | 1192 pointers_removed_++; |
| 1157 } | 1193 } |
| 1158 } | 1194 } |
| 1159 } | 1195 } |
| 1160 | 1196 |
| 1161 int PointersRemoved() { | 1197 int PointersRemoved() { |
| 1162 return pointers_removed_; | 1198 return pointers_removed_; |
| 1163 } | 1199 } |
| 1164 private: | 1200 private: |
| 1165 int pointers_removed_; | 1201 int pointers_removed_; |
| 1166 }; | 1202 }; |
| 1167 | 1203 |
| 1168 | 1204 |
| 1169 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects | 1205 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects |
| 1170 // are retained. | 1206 // are retained. |
| 1171 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { | 1207 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { |
| 1172 public: | 1208 public: |
| 1173 virtual Object* RetainAs(Object* object) { | 1209 virtual Object* RetainAs(Object* object) { |
| 1174 if (Marking::IsMarked(HeapObject::cast(object))) { | 1210 if (Marking::MarkBitFrom(HeapObject::cast(object)).Get()) { |
| 1175 return object; | 1211 return object; |
| 1176 } else { | 1212 } else { |
| 1177 return NULL; | 1213 return NULL; |
| 1178 } | 1214 } |
| 1179 } | 1215 } |
| 1180 }; | 1216 }; |
| 1181 | 1217 |
| 1182 | 1218 |
| 1183 void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) { | 1219 void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) { |
| 1184 ASSERT(Marking::IsMarked(object)); | 1220 ASSERT(IsMarked(object)); |
| 1185 ASSERT(Heap::Contains(object)); | 1221 ASSERT(Heap::Contains(object)); |
| 1186 if (object->IsMap()) { | 1222 if (object->IsMap()) { |
| 1187 Map* map = Map::cast(object); | 1223 Map* map = Map::cast(object); |
| 1188 if (FLAG_cleanup_caches_in_maps_at_gc) { | 1224 if (FLAG_cleanup_caches_in_maps_at_gc) { |
| 1189 map->ClearCodeCache(); | 1225 map->ClearCodeCache(); |
| 1190 } | 1226 } |
| 1191 if (FLAG_collect_maps && | 1227 if (FLAG_collect_maps && |
| 1192 map->instance_type() >= FIRST_JS_OBJECT_TYPE && | 1228 map->instance_type() >= FIRST_JS_OBJECT_TYPE && |
| 1193 map->instance_type() <= JS_FUNCTION_TYPE) { | 1229 map->instance_type() <= JS_FUNCTION_TYPE) { |
| 1194 MarkMapContents(map); | 1230 MarkMapContents(map); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1212 Map::kPointerFieldsBeginOffset); | 1248 Map::kPointerFieldsBeginOffset); |
| 1213 | 1249 |
| 1214 Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset); | 1250 Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset); |
| 1215 | 1251 |
| 1216 StaticMarkingVisitor::VisitPointers(start_slot, end_slot); | 1252 StaticMarkingVisitor::VisitPointers(start_slot, end_slot); |
| 1217 } | 1253 } |
| 1218 | 1254 |
| 1219 | 1255 |
| 1220 void MarkCompactCollector::MarkDescriptorArray( | 1256 void MarkCompactCollector::MarkDescriptorArray( |
| 1221 DescriptorArray* descriptors) { | 1257 DescriptorArray* descriptors) { |
| 1222 if (Marking::IsMarked(descriptors)) return; | 1258 MarkBit descriptors_mark = Marking::MarkBitFrom(descriptors); |
| 1259 if (descriptors_mark.Get()) return; | |
| 1223 // Empty descriptor array is marked as a root before any maps are marked. | 1260 // Empty descriptor array is marked as a root before any maps are marked. |
| 1224 ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array()); | 1261 ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array()); |
| 1225 SetMark(descriptors); | 1262 SetMark(descriptors, descriptors_mark); |
| 1226 | 1263 |
| 1227 FixedArray* contents = reinterpret_cast<FixedArray*>( | 1264 FixedArray* contents = reinterpret_cast<FixedArray*>( |
| 1228 descriptors->get(DescriptorArray::kContentArrayIndex)); | 1265 descriptors->get(DescriptorArray::kContentArrayIndex)); |
| 1229 ASSERT(contents->IsHeapObject()); | 1266 ASSERT(contents->IsHeapObject()); |
| 1230 ASSERT(!Marking::IsMarked(contents)); | 1267 ASSERT(!IsMarked(contents)); |
| 1231 ASSERT(contents->IsFixedArray()); | 1268 ASSERT(contents->IsFixedArray()); |
| 1232 ASSERT(contents->length() >= 2); | 1269 ASSERT(contents->length() >= 2); |
| 1233 SetMark(contents); | 1270 MarkBit contents_mark = Marking::MarkBitFrom(contents); |
| 1271 SetMark(contents, contents_mark); | |
| 1234 // Contents contains (value, details) pairs. If the details say that | 1272 // Contents contains (value, details) pairs. If the details say that |
| 1235 // the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION, or | 1273 // the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION, or |
| 1236 // NULL_DESCRIPTOR, we don't mark the value as live. Only for | 1274 // NULL_DESCRIPTOR, we don't mark the value as live. Only for |
| 1237 // MAP_TRANSITION and CONSTANT_TRANSITION is the value an Object* (a | 1275 // MAP_TRANSITION and CONSTANT_TRANSITION is the value an Object* (a |
| 1238 // Map*). | 1276 // Map*). |
| 1239 for (int i = 0; i < contents->length(); i += 2) { | 1277 for (int i = 0; i < contents->length(); i += 2) { |
| 1240 // If the pair (value, details) at index i, i+1 is not | 1278 // If the pair (value, details) at index i, i+1 is not |
| 1241 // a transition or null descriptor, mark the value. | 1279 // a transition or null descriptor, mark the value. |
| 1242 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 1280 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 1243 if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) { | 1281 if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) { |
| 1244 HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i)); | 1282 HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i)); |
| 1245 if (object->IsHeapObject() && !Marking::IsMarked(object)) { | 1283 if (object->IsHeapObject()) { |
| 1246 SetMark(object); | 1284 MarkBit mark = Marking::MarkBitFrom(HeapObject::cast(object)); |
| 1247 marking_stack.Push(object); | 1285 if (!mark.Get()) { |
| 1286 SetMark(HeapObject::cast(object), mark); | |
| 1287 marking_stack.Push(object); | |
| 1288 } | |
| 1248 } | 1289 } |
| 1249 } | 1290 } |
| 1250 } | 1291 } |
| 1251 // The DescriptorArray descriptors contains a pointer to its contents array, | 1292 // The DescriptorArray descriptors contains a pointer to its contents array, |
| 1252 // but the contents array is already marked. | 1293 // but the contents array is already marked. |
| 1253 marking_stack.Push(descriptors); | 1294 marking_stack.Push(descriptors); |
| 1254 } | 1295 } |
| 1255 | 1296 |
| 1256 | 1297 |
| 1257 void MarkCompactCollector::CreateBackPointers() { | 1298 void MarkCompactCollector::CreateBackPointers() { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1284 template<class T> | 1325 template<class T> |
| 1285 static void ScanOverflowedObjects(T* it) { | 1326 static void ScanOverflowedObjects(T* it) { |
| 1286 #if 0 | 1327 #if 0 |
| 1287 // The caller should ensure that the marking stack is initially not full, | 1328 // The caller should ensure that the marking stack is initially not full, |
| 1288 // so that we don't waste effort pointlessly scanning for objects. | 1329 // so that we don't waste effort pointlessly scanning for objects. |
| 1289 ASSERT(!marking_stack.is_full()); | 1330 ASSERT(!marking_stack.is_full()); |
| 1290 | 1331 |
| 1291 for (HeapObject* object = it->next(); object != NULL; object = it->next()) { | 1332 for (HeapObject* object = it->next(); object != NULL; object = it->next()) { |
| 1292 if (object->IsOverflowed()) { | 1333 if (object->IsOverflowed()) { |
| 1293 object->ClearOverflow(); | 1334 object->ClearOverflow(); |
| 1294 ASSERT(Marking::IsMarked(object)); | 1335 ASSERT(MarkCompactCollector::IsMarked(object)); |
| 1295 ASSERT(Heap::Contains(object)); | 1336 ASSERT(Heap::Contains(object)); |
| 1296 marking_stack.Push(object); | 1337 marking_stack.Push(object); |
| 1297 if (marking_stack.is_full()) return; | 1338 if (marking_stack.is_full()) return; |
| 1298 } | 1339 } |
| 1299 } | 1340 } |
| 1300 #endif | 1341 #endif |
| 1301 UNREACHABLE(); | 1342 UNREACHABLE(); |
| 1302 } | 1343 } |
| 1303 | 1344 |
| 1304 | 1345 |
| 1305 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 1346 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 1306 return (*p)->IsHeapObject() && | 1347 Object* o = *p; |
| 1307 !Marking::IsMarked(HeapObject::cast(*p)); | 1348 if (!o->IsHeapObject()) return false; |
| 1349 HeapObject* heap_object = HeapObject::cast(o); | |
| 1350 MarkBit mark = Marking::MarkBitFrom(heap_object); | |
| 1351 return !mark.Get(); | |
| 1308 } | 1352 } |
| 1309 | 1353 |
| 1310 | 1354 |
| 1311 void MarkCompactCollector::MarkSymbolTable() { | 1355 void MarkCompactCollector::MarkSymbolTable() { |
| 1312 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); | 1356 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); |
| 1313 // Mark the symbol table itself. | 1357 // Mark the symbol table itself. |
| 1314 SetMark(symbol_table); | 1358 MarkBit symbol_table_mark = Marking::MarkBitFrom(symbol_table); |
| 1359 SetMark(symbol_table, symbol_table_mark); | |
| 1315 // Explicitly mark the prefix. | 1360 // Explicitly mark the prefix. |
| 1316 MarkingVisitor marker; | 1361 MarkingVisitor marker; |
| 1317 symbol_table->IteratePrefix(&marker); | 1362 symbol_table->IteratePrefix(&marker); |
| 1318 ProcessMarkingStack(); | 1363 ProcessMarkingStack(); |
| 1319 } | 1364 } |
| 1320 | 1365 |
| 1321 | 1366 |
| 1322 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 1367 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
| 1323 // Mark the heap roots including global variables, stack variables, | 1368 // Mark the heap roots including global variables, stack variables, |
| 1324 // etc., and all objects reachable from them. | 1369 // etc., and all objects reachable from them. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1339 List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups(); | 1384 List<ObjectGroup*>* object_groups = GlobalHandles::ObjectGroups(); |
| 1340 | 1385 |
| 1341 for (int i = 0; i < object_groups->length(); i++) { | 1386 for (int i = 0; i < object_groups->length(); i++) { |
| 1342 ObjectGroup* entry = object_groups->at(i); | 1387 ObjectGroup* entry = object_groups->at(i); |
| 1343 if (entry == NULL) continue; | 1388 if (entry == NULL) continue; |
| 1344 | 1389 |
| 1345 List<Object**>& objects = entry->objects_; | 1390 List<Object**>& objects = entry->objects_; |
| 1346 bool group_marked = false; | 1391 bool group_marked = false; |
| 1347 for (int j = 0; j < objects.length(); j++) { | 1392 for (int j = 0; j < objects.length(); j++) { |
| 1348 Object* object = *objects[j]; | 1393 Object* object = *objects[j]; |
| 1349 if (object->IsHeapObject() | 1394 if (object->IsHeapObject()) { |
| 1350 && Marking::IsMarked(HeapObject::cast(object))) { | 1395 HeapObject* heap_object = HeapObject::cast(object); |
| 1351 group_marked = true; | 1396 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| 1352 break; | 1397 if (mark.Get()) { |
| 1398 group_marked = true; | |
| 1399 break; | |
| 1400 } | |
| 1353 } | 1401 } |
| 1354 } | 1402 } |
| 1355 | 1403 |
| 1356 if (!group_marked) continue; | 1404 if (!group_marked) continue; |
| 1357 | 1405 |
| 1358 // An object in the group is marked, so mark as gray all white heap | 1406 // An object in the group is marked, so mark as grey all white heap |
| 1359 // objects in the group. | 1407 // objects in the group. |
| 1360 for (int j = 0; j < objects.length(); ++j) { | 1408 for (int j = 0; j < objects.length(); ++j) { |
| 1361 if ((*objects[j])->IsHeapObject()) { | 1409 Object* object = *objects[j]; |
| 1362 MarkObject(HeapObject::cast(*objects[j])); | 1410 if (object->IsHeapObject()) { |
| 1411 HeapObject* heap_object = HeapObject::cast(object); | |
| 1412 MarkBit mark = Marking::MarkBitFrom(heap_object); | |
| 1413 MarkObject(heap_object, mark); | |
| 1363 } | 1414 } |
| 1364 } | 1415 } |
| 1365 // Once the entire group has been colored gray, set the object group | 1416 // Once the entire group has been colored grey, set the object group |
| 1366 // to NULL so it won't be processed again. | 1417 // to NULL so it won't be processed again. |
| 1367 delete object_groups->at(i); | 1418 delete object_groups->at(i); |
| 1368 object_groups->at(i) = NULL; | 1419 object_groups->at(i) = NULL; |
| 1369 } | 1420 } |
| 1370 } | 1421 } |
| 1371 | 1422 |
| 1372 | 1423 |
| 1373 // Mark all objects reachable from the objects on the marking stack. | 1424 // Mark all objects reachable from the objects on the marking stack. |
| 1374 // Before: the marking stack contains zero or more heap object pointers. | 1425 // Before: the marking stack contains zero or more heap object pointers. |
| 1375 // After: the marking stack is empty, and all objects reachable from the | 1426 // After: the marking stack is empty, and all objects reachable from the |
| 1376 // marking stack have been marked, or are overflowed in the heap. | 1427 // marking stack have been marked, or are overflowed in the heap. |
| 1377 void MarkCompactCollector::EmptyMarkingStack() { | 1428 void MarkCompactCollector::EmptyMarkingStack() { |
| 1378 while (!marking_stack.is_empty()) { | 1429 while (!marking_stack.is_empty()) { |
| 1379 HeapObject* object = marking_stack.Pop(); | 1430 HeapObject* object = marking_stack.Pop(); |
| 1380 ASSERT(object->IsHeapObject()); | 1431 ASSERT(object->IsHeapObject()); |
| 1381 ASSERT(Heap::Contains(object)); | 1432 ASSERT(Heap::Contains(object)); |
| 1382 ASSERT(Marking::IsMarked(object)); | 1433 ASSERT(IsMarked(object)); |
| 1383 ASSERT(!object->IsOverflowed()); | 1434 ASSERT(!object->IsOverflowed()); |
| 1384 | 1435 |
| 1385 // Because the object is marked, we have to recover the original map | |
| 1386 // pointer and use it to mark the object's body. | |
| 1387 Map* map = object->map(); | 1436 Map* map = object->map(); |
| 1388 MarkObject(map); | 1437 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1438 MarkObject(map, map_mark); | |
| 1389 | 1439 |
| 1390 StaticMarkingVisitor::IterateBody(map, object); | 1440 StaticMarkingVisitor::IterateBody(map, object); |
| 1391 } | 1441 } |
| 1392 } | 1442 } |
| 1393 | 1443 |
| 1394 | 1444 |
| 1395 // Sweep the heap for overflowed objects, clear their overflow bits, and | 1445 // Sweep the heap for overflowed objects, clear their overflow bits, and |
| 1396 // push them on the marking stack. Stop early if the marking stack fills | 1446 // push them on the marking stack. Stop early if the marking stack fills |
| 1397 // before sweeping completes. If sweeping completes, there are no remaining | 1447 // before sweeping completes. If sweeping completes, there are no remaining |
| 1398 // overflowed objects in the heap so the overflow flag on the markings stack | 1448 // overflowed objects in the heap so the overflow flag on the markings stack |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1576 // dropping the back pointers temporarily stored in the prototype field. | 1626 // dropping the back pointers temporarily stored in the prototype field. |
| 1577 // Setting the prototype field requires following the linked list of | 1627 // Setting the prototype field requires following the linked list of |
| 1578 // back pointers, reversing them all at once. This allows us to find | 1628 // back pointers, reversing them all at once. This allows us to find |
| 1579 // those maps with map transitions that need to be nulled, and only | 1629 // those maps with map transitions that need to be nulled, and only |
| 1580 // scan the descriptor arrays of those maps, not all maps. | 1630 // scan the descriptor arrays of those maps, not all maps. |
| 1581 // All of these actions are carried out only on maps of JSObjects | 1631 // All of these actions are carried out only on maps of JSObjects |
| 1582 // and related subtypes. | 1632 // and related subtypes. |
| 1583 for (HeapObject* obj = map_iterator.Next(); | 1633 for (HeapObject* obj = map_iterator.Next(); |
| 1584 obj != NULL; obj = map_iterator.Next()) { | 1634 obj != NULL; obj = map_iterator.Next()) { |
| 1585 Map* map = reinterpret_cast<Map*>(obj); | 1635 Map* map = reinterpret_cast<Map*>(obj); |
| 1586 if (!Marking::IsMarked(map) && map->IsFreeSpace()) continue; | 1636 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1637 if (!map_mark.Get() && map->IsFreeSpace()) continue; | |
| 1587 | 1638 |
| 1588 ASSERT(SafeIsMap(map)); | 1639 ASSERT(SafeIsMap(map)); |
| 1589 // Only JSObject and subtypes have map transitions and back pointers. | 1640 // Only JSObject and subtypes have map transitions and back pointers. |
| 1590 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; | 1641 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; |
| 1591 if (map->instance_type() > JS_FUNCTION_TYPE) continue; | 1642 if (map->instance_type() > JS_FUNCTION_TYPE) continue; |
| 1592 | 1643 |
| 1593 if (Marking::IsMarked(map) && | 1644 if (map_mark.Get() && |
| 1594 map->attached_to_shared_function_info()) { | 1645 map->attached_to_shared_function_info()) { |
| 1595 // This map is used for inobject slack tracking and has been detached | 1646 // This map is used for inobject slack tracking and has been detached |
| 1596 // from SharedFunctionInfo during the mark phase. | 1647 // from SharedFunctionInfo during the mark phase. |
| 1597 // Since it survived the GC, reattach it now. | 1648 // Since it survived the GC, reattach it now. |
| 1598 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); | 1649 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); |
| 1599 } | 1650 } |
| 1600 | 1651 |
| 1601 // Follow the chain of back pointers to find the prototype. | 1652 // Follow the chain of back pointers to find the prototype. |
| 1602 Map* current = map; | 1653 Map* current = map; |
| 1603 while (SafeIsMap(current)) { | 1654 while (SafeIsMap(current)) { |
| 1604 current = reinterpret_cast<Map*>(current->prototype()); | 1655 current = reinterpret_cast<Map*>(current->prototype()); |
| 1605 ASSERT(current->IsHeapObject()); | 1656 ASSERT(current->IsHeapObject()); |
| 1606 } | 1657 } |
| 1607 Object* real_prototype = current; | 1658 Object* real_prototype = current; |
| 1608 | 1659 |
| 1609 // Follow back pointers, setting them to prototype, | 1660 // Follow back pointers, setting them to prototype, |
| 1610 // clearing map transitions when necessary. | 1661 // clearing map transitions when necessary. |
| 1611 current = map; | 1662 bool on_dead_path = !map_mark.Get(); |
| 1612 bool on_dead_path = !Marking::IsMarked(current); | |
| 1613 Object* next; | 1663 Object* next; |
| 1614 while (SafeIsMap(current)) { | 1664 while (SafeIsMap(current)) { |
| 1615 next = current->prototype(); | 1665 next = current->prototype(); |
| 1616 // There should never be a dead map above a live map. | 1666 // There should never be a dead map above a live map. |
| 1617 ASSERT(on_dead_path || Marking::IsMarked(current)); | 1667 MarkBit current_mark = Marking::MarkBitFrom(current); |
| 1668 ASSERT(on_dead_path || current_mark.Get()); | |
| 1618 | 1669 |
| 1619 // A live map above a dead map indicates a dead transition. | 1670 // A live map above a dead map indicates a dead transition. |
| 1620 // This test will always be false on the first iteration. | 1671 // This test will always be false on the first iteration. |
| 1621 if (on_dead_path && Marking::IsMarked(current)) { | 1672 if (on_dead_path && current_mark.Get()) { |
| 1622 on_dead_path = false; | 1673 on_dead_path = false; |
| 1623 current->ClearNonLiveTransitions(real_prototype); | 1674 current->ClearNonLiveTransitions(real_prototype); |
| 1624 } | 1675 } |
| 1625 *HeapObject::RawField(current, Map::kPrototypeOffset) = | 1676 *HeapObject::RawField(current, Map::kPrototypeOffset) = |
| 1626 real_prototype; | 1677 real_prototype; |
| 1627 current = reinterpret_cast<Map*>(next); | 1678 current = reinterpret_cast<Map*>(next); |
| 1628 } | 1679 } |
| 1629 } | 1680 } |
| 1630 } | 1681 } |
| 1631 | 1682 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1786 space->ResetAllocationInfo(); | 1837 space->ResetAllocationInfo(); |
| 1787 | 1838 |
| 1788 int size = 0; | 1839 int size = 0; |
| 1789 int survivors_size = 0; | 1840 int survivors_size = 0; |
| 1790 | 1841 |
| 1791 // First pass: traverse all objects in inactive semispace, remove marks, | 1842 // First pass: traverse all objects in inactive semispace, remove marks, |
| 1792 // migrate live objects and write forwarding addresses. | 1843 // migrate live objects and write forwarding addresses. |
| 1793 for (Address current = from_bottom; current < from_top; current += size) { | 1844 for (Address current = from_bottom; current < from_top; current += size) { |
| 1794 HeapObject* object = HeapObject::FromAddress(current); | 1845 HeapObject* object = HeapObject::FromAddress(current); |
| 1795 | 1846 |
| 1796 if (Marking::IsMarked(object)) { | 1847 |
| 1797 Marking::ClearMark(object); | 1848 MarkBit mark_bit = Marking::MarkBitFromNewSpace(object); |
| 1849 if (mark_bit.Get()) { | |
| 1850 mark_bit.Clear(); | |
| 1798 MarkCompactCollector::tracer()->decrement_marked_count(); | 1851 MarkCompactCollector::tracer()->decrement_marked_count(); |
| 1799 | 1852 |
| 1800 size = object->Size(); | 1853 size = object->Size(); |
| 1801 survivors_size += size; | 1854 survivors_size += size; |
| 1802 | 1855 |
| 1803 // Aggressively promote young survivors to the old space. | 1856 // Aggressively promote young survivors to the old space. |
| 1804 if (TryPromoteObject(object, size)) { | 1857 if (TryPromoteObject(object, size)) { |
| 1805 continue; | 1858 continue; |
| 1806 } | 1859 } |
| 1807 | 1860 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2212 | 2265 |
| 2213 // Sweeps a space conservatively. After this has been done the larger free | 2266 // Sweeps a space conservatively. After this has been done the larger free |
| 2214 // spaces have been put on the free list and the smaller ones have been | 2267 // spaces have been put on the free list and the smaller ones have been |
| 2215 // ignored and left untouched. A free space is always either ignored or put | 2268 // ignored and left untouched. A free space is always either ignored or put |
| 2216 // on the free list, never split up into two parts. This is important | 2269 // on the free list, never split up into two parts. This is important |
| 2217 // because it means that any FreeSpace maps left actually describe a region of | 2270 // because it means that any FreeSpace maps left actually describe a region of |
| 2218 // memory that can be ignored when scanning. Dead objects other than free | 2271 // memory that can be ignored when scanning. Dead objects other than free |
| 2219 // spaces will not contain the free space map. | 2272 // spaces will not contain the free space map. |
| 2220 static void SweepConservatively(PagedSpace* space, | 2273 static void SweepConservatively(PagedSpace* space, |
| 2221 Page* p) { | 2274 Page* p) { |
| 2222 Page::MarkbitsBitmap* markbits = p->markbits(); | 2275 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2223 Page::MarkbitsBitmap::CellType* cells = markbits->cells(); | |
| 2224 | 2276 |
| 2225 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2277 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2226 | 2278 |
| 2227 // This is the start of the 32 word block that we are currently looking at. | 2279 // This is the start of the 32 word block that we are currently looking at. |
| 2228 Address block_address = p->ObjectAreaStart(); | 2280 Address block_address = p->ObjectAreaStart(); |
| 2229 | 2281 |
| 2230 int last_cell_index = | 2282 int last_cell_index = |
| 2231 Page::MarkbitsBitmap::IndexToCell( | 2283 Page::MarkbitsBitmap::IndexToCell( |
| 2232 Page::MarkbitsBitmap::CellAlignIndex( | 2284 Page::MarkbitsBitmap::CellAlignIndex( |
| 2233 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2285 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2295 } | 2347 } |
| 2296 } | 2348 } |
| 2297 | 2349 |
| 2298 | 2350 |
| 2299 // Sweep a space precisely. After this has been done the space can | 2351 // Sweep a space precisely. After this has been done the space can |
| 2300 // be iterated precisely, hitting only the live objects. Code space | 2352 // be iterated precisely, hitting only the live objects. Code space |
| 2301 // is always swept precisely because we want to be able to iterate | 2353 // is always swept precisely because we want to be able to iterate |
| 2302 // over it. Map space is swept precisely, because it is not compacted. | 2354 // over it. Map space is swept precisely, because it is not compacted. |
| 2303 static void SweepPrecisely(PagedSpace* space, | 2355 static void SweepPrecisely(PagedSpace* space, |
| 2304 Page* p) { | 2356 Page* p) { |
| 2305 Page::MarkbitsBitmap* markbits = p->markbits(); | 2357 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2306 Page::MarkbitsBitmap::CellType* cells = markbits->cells(); | |
| 2307 | 2358 |
| 2308 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2359 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2309 | 2360 |
| 2310 int last_cell_index = | 2361 int last_cell_index = |
| 2311 Page::MarkbitsBitmap::IndexToCell( | 2362 Page::MarkbitsBitmap::IndexToCell( |
| 2312 Page::MarkbitsBitmap::CellAlignIndex( | 2363 Page::MarkbitsBitmap::CellAlignIndex( |
| 2313 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2364 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2314 | 2365 |
| 2315 int cell_index = Page::kFirstUsedCell; | 2366 int cell_index = Page::kFirstUsedCell; |
| 2316 Address free_start = p->ObjectAreaStart(); | 2367 Address free_start = p->ObjectAreaStart(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2476 } | 2527 } |
| 2477 | 2528 |
| 2478 | 2529 |
| 2479 void MarkCompactCollector::Initialize() { | 2530 void MarkCompactCollector::Initialize() { |
| 2480 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 2531 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
| 2481 StaticMarkingVisitor::Initialize(); | 2532 StaticMarkingVisitor::Initialize(); |
| 2482 } | 2533 } |
| 2483 | 2534 |
| 2484 | 2535 |
| 2485 } } // namespace v8::internal | 2536 } } // namespace v8::internal |
| OLD | NEW |