| 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 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 } | 730 } |
| 731 } | 731 } |
| 732 | 732 |
| 733 | 733 |
| 734 static inline HeapObject* ShortCircuitConsString(Object** p) { | 734 static inline HeapObject* ShortCircuitConsString(Object** p) { |
| 735 // Optimization: If the heap object pointed to by p is a non-symbol | 735 // Optimization: If the heap object pointed to by p is a non-symbol |
| 736 // cons string whose right substring is HEAP->empty_string, update | 736 // cons string whose right substring is HEAP->empty_string, update |
| 737 // it in place to its left substring. Return the updated value. | 737 // it in place to its left substring. Return the updated value. |
| 738 // | 738 // |
| 739 // Here we assume that if we change *p, we replace it with a heap object | 739 // Here we assume that if we change *p, we replace it with a heap object |
| 740 // (ie, the left substring of a cons string is always a heap object). | 740 // (i.e., the left substring of a cons string is always a heap object). |
| 741 // | 741 // |
| 742 // The check performed is: | 742 // The check performed is: |
| 743 // object->IsConsString() && !object->IsSymbol() && | 743 // object->IsConsString() && !object->IsSymbol() && |
| 744 // (ConsString::cast(object)->second() == HEAP->empty_string()) | 744 // (ConsString::cast(object)->second() == HEAP->empty_string()) |
| 745 // except the maps for the object and its possible substrings might be | 745 // except the maps for the object and its possible substrings might be |
| 746 // marked. | 746 // marked. |
| 747 HeapObject* object = HeapObject::cast(*p); | 747 HeapObject* object = HeapObject::cast(*p); |
| 748 if (!FLAG_clever_optimizations) return object; | 748 if (!FLAG_clever_optimizations) return object; |
| 749 Map* map = object->map(); | 749 Map* map = object->map(); |
| 750 InstanceType type = map->instance_type(); | 750 InstanceType type = map->instance_type(); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 // If we did not use the code for kRegExpCodeThreshold mark sweep GCs | 1189 // If we did not use the code for kRegExpCodeThreshold mark sweep GCs |
| 1190 // we flush the code. | 1190 // we flush the code. |
| 1191 static void VisitRegExpAndFlushCode(Map* map, HeapObject* object) { | 1191 static void VisitRegExpAndFlushCode(Map* map, HeapObject* object) { |
| 1192 Heap* heap = map->GetHeap(); | 1192 Heap* heap = map->GetHeap(); |
| 1193 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1193 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1194 if (!collector->is_code_flushing_enabled()) { | 1194 if (!collector->is_code_flushing_enabled()) { |
| 1195 VisitJSRegExpFields(map, object); | 1195 VisitJSRegExpFields(map, object); |
| 1196 return; | 1196 return; |
| 1197 } | 1197 } |
| 1198 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); | 1198 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); |
| 1199 // Flush code or set age on both ascii and two byte code. | 1199 // Flush code or set age on both ASCII and two byte code. |
| 1200 UpdateRegExpCodeAgeAndFlush(heap, re, true); | 1200 UpdateRegExpCodeAgeAndFlush(heap, re, true); |
| 1201 UpdateRegExpCodeAgeAndFlush(heap, re, false); | 1201 UpdateRegExpCodeAgeAndFlush(heap, re, false); |
| 1202 // Visit the fields of the RegExp, including the updated FixedArray. | 1202 // Visit the fields of the RegExp, including the updated FixedArray. |
| 1203 VisitJSRegExpFields(map, object); | 1203 VisitJSRegExpFields(map, object); |
| 1204 } | 1204 } |
| 1205 | 1205 |
| 1206 | 1206 |
| 1207 static void VisitSharedFunctionInfoAndFlushCode(Map* map, | 1207 static void VisitSharedFunctionInfoAndFlushCode(Map* map, |
| 1208 HeapObject* object) { | 1208 HeapObject* object) { |
| 1209 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); | 1209 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); |
| (...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2880 cell_index++, object_address += 32 * kPointerSize) { | 2880 cell_index++, object_address += 32 * kPointerSize) { |
| 2881 ASSERT((unsigned)cell_index == | 2881 ASSERT((unsigned)cell_index == |
| 2882 Bitmap::IndexToCell( | 2882 Bitmap::IndexToCell( |
| 2883 Bitmap::CellAlignIndex( | 2883 Bitmap::CellAlignIndex( |
| 2884 p->AddressToMarkbitIndex(object_address)))); | 2884 p->AddressToMarkbitIndex(object_address)))); |
| 2885 int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets); | 2885 int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets); |
| 2886 int live_index = 0; | 2886 int live_index = 0; |
| 2887 for ( ; live_objects != 0; live_objects--) { | 2887 for ( ; live_objects != 0; live_objects--) { |
| 2888 Address free_end = object_address + offsets[live_index++] * kPointerSize; | 2888 Address free_end = object_address + offsets[live_index++] * kPointerSize; |
| 2889 if (free_end != free_start) { | 2889 if (free_end != free_start) { |
| 2890 space->Free(free_start, static_cast<int>(free_end - free_start)); | 2890 space->AddToFreeLists(free_start, |
| 2891 static_cast<int>(free_end - free_start)); |
| 2891 } | 2892 } |
| 2892 HeapObject* live_object = HeapObject::FromAddress(free_end); | 2893 HeapObject* live_object = HeapObject::FromAddress(free_end); |
| 2893 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | 2894 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); |
| 2894 Map* map = live_object->map(); | 2895 Map* map = live_object->map(); |
| 2895 int size = live_object->SizeFromMap(map); | 2896 int size = live_object->SizeFromMap(map); |
| 2896 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { | 2897 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { |
| 2897 live_object->IterateBody(map->instance_type(), size, v); | 2898 live_object->IterateBody(map->instance_type(), size, v); |
| 2898 } | 2899 } |
| 2899 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { | 2900 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { |
| 2900 int new_region_start = | 2901 int new_region_start = |
| 2901 SkipList::RegionNumber(free_end); | 2902 SkipList::RegionNumber(free_end); |
| 2902 int new_region_end = | 2903 int new_region_end = |
| 2903 SkipList::RegionNumber(free_end + size - kPointerSize); | 2904 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 2904 if (new_region_start != curr_region || | 2905 if (new_region_start != curr_region || |
| 2905 new_region_end != curr_region) { | 2906 new_region_end != curr_region) { |
| 2906 skip_list->AddObject(free_end, size); | 2907 skip_list->AddObject(free_end, size); |
| 2907 curr_region = new_region_end; | 2908 curr_region = new_region_end; |
| 2908 } | 2909 } |
| 2909 } | 2910 } |
| 2910 free_start = free_end + size; | 2911 free_start = free_end + size; |
| 2911 } | 2912 } |
| 2912 // Clear marking bits for current cell. | 2913 // Clear marking bits for current cell. |
| 2913 cells[cell_index] = 0; | 2914 cells[cell_index] = 0; |
| 2914 } | 2915 } |
| 2915 if (free_start != p->ObjectAreaEnd()) { | 2916 if (free_start != p->ObjectAreaEnd()) { |
| 2916 space->Free(free_start, static_cast<int>(p->ObjectAreaEnd() - free_start)); | 2917 space->AddToFreeLists(free_start, |
| 2918 static_cast<int>(p->ObjectAreaEnd() - free_start)); |
| 2917 } | 2919 } |
| 2918 p->ResetLiveBytes(); | 2920 p->ResetLiveBytes(); |
| 2919 } | 2921 } |
| 2920 | 2922 |
| 2921 | 2923 |
| 2922 static bool SetMarkBitsUnderInvalidatedCode(Code* code, bool value) { | 2924 static bool SetMarkBitsUnderInvalidatedCode(Code* code, bool value) { |
| 2923 Page* p = Page::FromAddress(code->address()); | 2925 Page* p = Page::FromAddress(code->address()); |
| 2924 | 2926 |
| 2925 if (p->IsEvacuationCandidate() || | 2927 if (p->IsEvacuationCandidate() || |
| 2926 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { | 2928 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3199 VerifyEvacuation(heap_); | 3201 VerifyEvacuation(heap_); |
| 3200 } | 3202 } |
| 3201 #endif | 3203 #endif |
| 3202 | 3204 |
| 3203 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); | 3205 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
| 3204 ASSERT(migration_slots_buffer_ == NULL); | 3206 ASSERT(migration_slots_buffer_ == NULL); |
| 3205 for (int i = 0; i < npages; i++) { | 3207 for (int i = 0; i < npages; i++) { |
| 3206 Page* p = evacuation_candidates_[i]; | 3208 Page* p = evacuation_candidates_[i]; |
| 3207 if (!p->IsEvacuationCandidate()) continue; | 3209 if (!p->IsEvacuationCandidate()) continue; |
| 3208 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3210 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3209 space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); | 3211 space->AddToFreeLists(p->ObjectAreaStart(), |
| 3212 p->ObjectAreaEnd() - p->ObjectAreaStart()); |
| 3210 p->set_scan_on_scavenge(false); | 3213 p->set_scan_on_scavenge(false); |
| 3211 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); | 3214 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); |
| 3212 p->ClearEvacuationCandidate(); | 3215 p->ClearEvacuationCandidate(); |
| 3213 } | 3216 } |
| 3214 evacuation_candidates_.Rewind(0); | 3217 evacuation_candidates_.Rewind(0); |
| 3215 compacting_ = false; | 3218 compacting_ = false; |
| 3216 } | 3219 } |
| 3217 | 3220 |
| 3218 | 3221 |
| 3219 static const int kStartTableEntriesPerLine = 5; | 3222 static const int kStartTableEntriesPerLine = 5; |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3516 Address block_address = p->ObjectAreaStart(); | 3519 Address block_address = p->ObjectAreaStart(); |
| 3517 | 3520 |
| 3518 // Skip over all the dead objects at the start of the page and mark them free. | 3521 // Skip over all the dead objects at the start of the page and mark them free. |
| 3519 for (cell_index = Page::kFirstUsedCell; | 3522 for (cell_index = Page::kFirstUsedCell; |
| 3520 cell_index < last_cell_index; | 3523 cell_index < last_cell_index; |
| 3521 cell_index++, block_address += 32 * kPointerSize) { | 3524 cell_index++, block_address += 32 * kPointerSize) { |
| 3522 if (cells[cell_index] != 0) break; | 3525 if (cells[cell_index] != 0) break; |
| 3523 } | 3526 } |
| 3524 size_t size = block_address - p->ObjectAreaStart(); | 3527 size_t size = block_address - p->ObjectAreaStart(); |
| 3525 if (cell_index == last_cell_index) { | 3528 if (cell_index == last_cell_index) { |
| 3526 freed_bytes += static_cast<int>(space->Free(p->ObjectAreaStart(), | 3529 freed_bytes += static_cast<int>(space->AddToFreeLists( |
| 3527 static_cast<int>(size))); | 3530 p->ObjectAreaStart(), static_cast<int>(size))); |
| 3528 ASSERT_EQ(0, p->LiveBytes()); | 3531 ASSERT_EQ(0, p->LiveBytes()); |
| 3529 return freed_bytes; | 3532 return freed_bytes; |
| 3530 } | 3533 } |
| 3531 // Grow the size of the start-of-page free space a little to get up to the | 3534 // Grow the size of the start-of-page free space a little to get up to the |
| 3532 // first live object. | 3535 // first live object. |
| 3533 Address free_end = StartOfLiveObject(block_address, cells[cell_index]); | 3536 Address free_end = StartOfLiveObject(block_address, cells[cell_index]); |
| 3534 // Free the first free space. | 3537 // Free the first free space. |
| 3535 size = free_end - p->ObjectAreaStart(); | 3538 size = free_end - p->ObjectAreaStart(); |
| 3536 freed_bytes += space->Free(p->ObjectAreaStart(), | 3539 freed_bytes += space->AddToFreeLists(p->ObjectAreaStart(), |
| 3537 static_cast<int>(size)); | 3540 static_cast<int>(size)); |
| 3538 // The start of the current free area is represented in undigested form by | 3541 // The start of the current free area is represented in undigested form by |
| 3539 // the address of the last 32-word section that contained a live object and | 3542 // the address of the last 32-word section that contained a live object and |
| 3540 // the marking bitmap for that cell, which describes where the live object | 3543 // the marking bitmap for that cell, which describes where the live object |
| 3541 // started. Unless we find a large free space in the bitmap we will not | 3544 // started. Unless we find a large free space in the bitmap we will not |
| 3542 // digest this pair into a real address. We start the iteration here at the | 3545 // digest this pair into a real address. We start the iteration here at the |
| 3543 // first word in the marking bit map that indicates a live object. | 3546 // first word in the marking bit map that indicates a live object. |
| 3544 Address free_start = block_address; | 3547 Address free_start = block_address; |
| 3545 uint32_t free_start_cell = cells[cell_index]; | 3548 uint32_t free_start_cell = cells[cell_index]; |
| 3546 | 3549 |
| 3547 for ( ; | 3550 for ( ; |
| 3548 cell_index < last_cell_index; | 3551 cell_index < last_cell_index; |
| 3549 cell_index++, block_address += 32 * kPointerSize) { | 3552 cell_index++, block_address += 32 * kPointerSize) { |
| 3550 ASSERT((unsigned)cell_index == | 3553 ASSERT((unsigned)cell_index == |
| 3551 Bitmap::IndexToCell( | 3554 Bitmap::IndexToCell( |
| 3552 Bitmap::CellAlignIndex( | 3555 Bitmap::CellAlignIndex( |
| 3553 p->AddressToMarkbitIndex(block_address)))); | 3556 p->AddressToMarkbitIndex(block_address)))); |
| 3554 uint32_t cell = cells[cell_index]; | 3557 uint32_t cell = cells[cell_index]; |
| 3555 if (cell != 0) { | 3558 if (cell != 0) { |
| 3556 // We have a live object. Check approximately whether it is more than 32 | 3559 // We have a live object. Check approximately whether it is more than 32 |
| 3557 // words since the last live object. | 3560 // words since the last live object. |
| 3558 if (block_address - free_start > 32 * kPointerSize) { | 3561 if (block_address - free_start > 32 * kPointerSize) { |
| 3559 free_start = DigestFreeStart(free_start, free_start_cell); | 3562 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3560 if (block_address - free_start > 32 * kPointerSize) { | 3563 if (block_address - free_start > 32 * kPointerSize) { |
| 3561 // Now that we know the exact start of the free space it still looks | 3564 // Now that we know the exact start of the free space it still looks |
| 3562 // like we have a large enough free space to be worth bothering with. | 3565 // like we have a large enough free space to be worth bothering with. |
| 3563 // so now we need to find the start of the first live object at the | 3566 // so now we need to find the start of the first live object at the |
| 3564 // end of the free space. | 3567 // end of the free space. |
| 3565 free_end = StartOfLiveObject(block_address, cell); | 3568 free_end = StartOfLiveObject(block_address, cell); |
| 3566 freed_bytes += space->Free(free_start, | 3569 freed_bytes += space->AddToFreeLists( |
| 3567 static_cast<int>(free_end - free_start)); | 3570 free_start, static_cast<int>(free_end - free_start)); |
| 3568 } | 3571 } |
| 3569 } | 3572 } |
| 3570 // Update our undigested record of where the current free area started. | 3573 // Update our undigested record of where the current free area started. |
| 3571 free_start = block_address; | 3574 free_start = block_address; |
| 3572 free_start_cell = cell; | 3575 free_start_cell = cell; |
| 3573 // Clear marking bits for current cell. | 3576 // Clear marking bits for current cell. |
| 3574 cells[cell_index] = 0; | 3577 cells[cell_index] = 0; |
| 3575 } | 3578 } |
| 3576 } | 3579 } |
| 3577 | 3580 |
| 3578 // Handle the free space at the end of the page. | 3581 // Handle the free space at the end of the page. |
| 3579 if (block_address - free_start > 32 * kPointerSize) { | 3582 if (block_address - free_start > 32 * kPointerSize) { |
| 3580 free_start = DigestFreeStart(free_start, free_start_cell); | 3583 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3581 freed_bytes += space->Free(free_start, | 3584 freed_bytes += space->AddToFreeLists( |
| 3582 static_cast<int>(block_address - free_start)); | 3585 free_start, static_cast<int>(block_address - free_start)); |
| 3583 } | 3586 } |
| 3584 | 3587 |
| 3585 p->ResetLiveBytes(); | 3588 p->ResetLiveBytes(); |
| 3586 return freed_bytes; | 3589 return freed_bytes; |
| 3587 } | 3590 } |
| 3588 | 3591 |
| 3589 | 3592 |
| 3590 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { | 3593 void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { |
| 3591 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || | 3594 space->set_was_swept_conservatively(sweeper == CONSERVATIVE || |
| 3592 sweeper == LAZY_CONSERVATIVE); | 3595 sweeper == LAZY_CONSERVATIVE); |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3903 while (buffer != NULL) { | 3906 while (buffer != NULL) { |
| 3904 SlotsBuffer* next_buffer = buffer->next(); | 3907 SlotsBuffer* next_buffer = buffer->next(); |
| 3905 DeallocateBuffer(buffer); | 3908 DeallocateBuffer(buffer); |
| 3906 buffer = next_buffer; | 3909 buffer = next_buffer; |
| 3907 } | 3910 } |
| 3908 *buffer_address = NULL; | 3911 *buffer_address = NULL; |
| 3909 } | 3912 } |
| 3910 | 3913 |
| 3911 | 3914 |
| 3912 } } // namespace v8::internal | 3915 } } // namespace v8::internal |
| OLD | NEW |