OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/heap/spaces.h" | 5 #include "src/heap/spaces.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/base/platform/semaphore.h" | 9 #include "src/base/platform/semaphore.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 chunk->typed_old_to_old_slots_ = nullptr; | 493 chunk->typed_old_to_old_slots_ = nullptr; |
494 chunk->skip_list_ = nullptr; | 494 chunk->skip_list_ = nullptr; |
495 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; | 495 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; |
496 chunk->progress_bar_ = 0; | 496 chunk->progress_bar_ = 0; |
497 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); | 497 chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); |
498 chunk->concurrent_sweeping_state().SetValue(kSweepingDone); | 498 chunk->concurrent_sweeping_state().SetValue(kSweepingDone); |
499 chunk->mutex_ = new base::Mutex(); | 499 chunk->mutex_ = new base::Mutex(); |
500 chunk->available_in_free_list_ = 0; | 500 chunk->available_in_free_list_ = 0; |
501 chunk->wasted_memory_ = 0; | 501 chunk->wasted_memory_ = 0; |
502 chunk->ResetLiveBytes(); | 502 chunk->ResetLiveBytes(); |
503 Bitmap::Clear(chunk); | 503 chunk->ClearLiveness(); |
504 chunk->set_next_chunk(nullptr); | 504 chunk->set_next_chunk(nullptr); |
505 chunk->set_prev_chunk(nullptr); | 505 chunk->set_prev_chunk(nullptr); |
506 chunk->local_tracker_ = nullptr; | 506 chunk->local_tracker_ = nullptr; |
507 | 507 |
508 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); | 508 DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); |
509 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); | 509 DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); |
510 | 510 |
511 if (executable == EXECUTABLE) { | 511 if (executable == EXECUTABLE) { |
512 chunk->SetFlag(IS_EXECUTABLE); | 512 chunk->SetFlag(IS_EXECUTABLE); |
513 } | 513 } |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 DCHECK_NULL(local_tracker_); | 1053 DCHECK_NULL(local_tracker_); |
1054 local_tracker_ = new LocalArrayBufferTracker(heap()); | 1054 local_tracker_ = new LocalArrayBufferTracker(heap()); |
1055 } | 1055 } |
1056 | 1056 |
1057 void MemoryChunk::ReleaseLocalTracker() { | 1057 void MemoryChunk::ReleaseLocalTracker() { |
1058 DCHECK_NOT_NULL(local_tracker_); | 1058 DCHECK_NOT_NULL(local_tracker_); |
1059 delete local_tracker_; | 1059 delete local_tracker_; |
1060 local_tracker_ = nullptr; | 1060 local_tracker_ = nullptr; |
1061 } | 1061 } |
1062 | 1062 |
| 1063 void MemoryChunk::ClearLiveness() { |
| 1064 markbits()->Clear(); |
| 1065 ResetLiveBytes(); |
| 1066 } |
| 1067 |
1063 // ----------------------------------------------------------------------------- | 1068 // ----------------------------------------------------------------------------- |
1064 // PagedSpace implementation | 1069 // PagedSpace implementation |
1065 | 1070 |
1066 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::NEW_SPACE) == | 1071 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::NEW_SPACE) == |
1067 ObjectSpace::kObjectSpaceNewSpace); | 1072 ObjectSpace::kObjectSpaceNewSpace); |
1068 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::OLD_SPACE) == | 1073 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::OLD_SPACE) == |
1069 ObjectSpace::kObjectSpaceOldSpace); | 1074 ObjectSpace::kObjectSpaceOldSpace); |
1070 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::CODE_SPACE) == | 1075 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::CODE_SPACE) == |
1071 ObjectSpace::kObjectSpaceCodeSpace); | 1076 ObjectSpace::kObjectSpaceCodeSpace); |
1072 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::MAP_SPACE) == | 1077 STATIC_ASSERT(static_cast<ObjectSpace>(1 << AllocationSpace::MAP_SPACE) == |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 | 1226 |
1222 AccountCommitted(static_cast<intptr_t>(p->size())); | 1227 AccountCommitted(static_cast<intptr_t>(p->size())); |
1223 | 1228 |
1224 // Pages created during bootstrapping may contain immortal immovable objects. | 1229 // Pages created during bootstrapping may contain immortal immovable objects. |
1225 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); | 1230 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); |
1226 | 1231 |
1227 // When incremental marking was activated, old space pages are allocated | 1232 // When incremental marking was activated, old space pages are allocated |
1228 // black. | 1233 // black. |
1229 if (heap()->incremental_marking()->black_allocation() && | 1234 if (heap()->incremental_marking()->black_allocation() && |
1230 identity() == OLD_SPACE) { | 1235 identity() == OLD_SPACE) { |
1231 Bitmap::SetAllBits(p); | 1236 p->markbits()->SetAllBits(); |
1232 p->SetFlag(Page::BLACK_PAGE); | 1237 p->SetFlag(Page::BLACK_PAGE); |
1233 if (FLAG_trace_incremental_marking) { | 1238 if (FLAG_trace_incremental_marking) { |
1234 PrintIsolate(heap()->isolate(), "Added black page %p\n", | 1239 PrintIsolate(heap()->isolate(), "Added black page %p\n", |
1235 static_cast<void*>(p)); | 1240 static_cast<void*>(p)); |
1236 } | 1241 } |
1237 } | 1242 } |
1238 | 1243 |
1239 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); | 1244 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); |
1240 | 1245 |
1241 p->InsertAfter(anchor_.prev_page()); | 1246 p->InsertAfter(anchor_.prev_page()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 // Perform space-specific object verification. | 1325 // Perform space-specific object verification. |
1321 VerifyObject(object); | 1326 VerifyObject(object); |
1322 | 1327 |
1323 // The object itself should look OK. | 1328 // The object itself should look OK. |
1324 object->ObjectVerify(); | 1329 object->ObjectVerify(); |
1325 | 1330 |
1326 // All the interior pointers should be contained in the heap. | 1331 // All the interior pointers should be contained in the heap. |
1327 int size = object->Size(); | 1332 int size = object->Size(); |
1328 object->IterateBody(map->instance_type(), size, visitor); | 1333 object->IterateBody(map->instance_type(), size, visitor); |
1329 if (!page->IsFlagSet(Page::BLACK_PAGE) && | 1334 if (!page->IsFlagSet(Page::BLACK_PAGE) && |
1330 Marking::IsBlack(Marking::MarkBitFrom(object))) { | 1335 Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) { |
1331 black_size += size; | 1336 black_size += size; |
1332 } | 1337 } |
1333 | 1338 |
1334 CHECK(object->address() + size <= top); | 1339 CHECK(object->address() + size <= top); |
1335 end_of_previous_object = object->address() + size; | 1340 end_of_previous_object = object->address() + size; |
1336 } | 1341 } |
1337 CHECK_LE(black_size, page->LiveBytes()); | 1342 CHECK_LE(black_size, page->LiveBytes()); |
1338 } | 1343 } |
1339 CHECK(allocation_pointer_found_in_space); | 1344 CHECK(allocation_pointer_found_in_space); |
1340 } | 1345 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1455 } | 1460 } |
1456 } | 1461 } |
1457 while (actual_pages < expected_pages) { | 1462 while (actual_pages < expected_pages) { |
1458 actual_pages++; | 1463 actual_pages++; |
1459 current_page = | 1464 current_page = |
1460 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( | 1465 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
1461 Page::kAllocatableMemory, this, executable()); | 1466 Page::kAllocatableMemory, this, executable()); |
1462 if (current_page == nullptr) return false; | 1467 if (current_page == nullptr) return false; |
1463 DCHECK_NOT_NULL(current_page); | 1468 DCHECK_NOT_NULL(current_page); |
1464 current_page->InsertAfter(anchor()); | 1469 current_page->InsertAfter(anchor()); |
1465 Bitmap::Clear(current_page); | 1470 current_page->ClearLiveness(); |
1466 current_page->SetFlags(anchor()->prev_page()->GetFlags(), | 1471 current_page->SetFlags(anchor()->prev_page()->GetFlags(), |
1467 Page::kCopyAllFlags); | 1472 Page::kCopyAllFlags); |
1468 heap()->CreateFillerObjectAt(current_page->area_start(), | 1473 heap()->CreateFillerObjectAt(current_page->area_start(), |
1469 current_page->area_size(), | 1474 current_page->area_size(), |
1470 ClearRecordedSlots::kNo); | 1475 ClearRecordedSlots::kNo); |
1471 } | 1476 } |
1472 } | 1477 } |
1473 return true; | 1478 return true; |
1474 } | 1479 } |
1475 | 1480 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1528 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
1524 } | 1529 } |
1525 | 1530 |
1526 | 1531 |
1527 void NewSpace::ResetAllocationInfo() { | 1532 void NewSpace::ResetAllocationInfo() { |
1528 Address old_top = allocation_info_.top(); | 1533 Address old_top = allocation_info_.top(); |
1529 to_space_.Reset(); | 1534 to_space_.Reset(); |
1530 UpdateAllocationInfo(); | 1535 UpdateAllocationInfo(); |
1531 // Clear all mark-bits in the to-space. | 1536 // Clear all mark-bits in the to-space. |
1532 for (Page* p : to_space_) { | 1537 for (Page* p : to_space_) { |
1533 Bitmap::Clear(p); | 1538 p->ClearLiveness(); |
1534 } | 1539 } |
1535 InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0); | 1540 InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0); |
1536 } | 1541 } |
1537 | 1542 |
1538 | 1543 |
1539 void NewSpace::UpdateInlineAllocationLimit(int size_in_bytes) { | 1544 void NewSpace::UpdateInlineAllocationLimit(int size_in_bytes) { |
1540 if (heap()->inline_allocation_disabled()) { | 1545 if (heap()->inline_allocation_disabled()) { |
1541 // Lowest limit when linear allocation was disabled. | 1546 // Lowest limit when linear allocation was disabled. |
1542 Address high = to_space_.page_high(); | 1547 Address high = to_space_.page_high(); |
1543 Address new_top = allocation_info_.top() + size_in_bytes; | 1548 Address new_top = allocation_info_.top() + size_in_bytes; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 DCHECK_NE(last_page, anchor()); | 1826 DCHECK_NE(last_page, anchor()); |
1822 for (int pages_added = 0; pages_added < delta_pages; pages_added++) { | 1827 for (int pages_added = 0; pages_added < delta_pages; pages_added++) { |
1823 Page* new_page = | 1828 Page* new_page = |
1824 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( | 1829 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
1825 Page::kAllocatableMemory, this, executable()); | 1830 Page::kAllocatableMemory, this, executable()); |
1826 if (new_page == nullptr) { | 1831 if (new_page == nullptr) { |
1827 RewindPages(last_page, pages_added); | 1832 RewindPages(last_page, pages_added); |
1828 return false; | 1833 return false; |
1829 } | 1834 } |
1830 new_page->InsertAfter(last_page); | 1835 new_page->InsertAfter(last_page); |
1831 Bitmap::Clear(new_page); | 1836 new_page->ClearLiveness(); |
1832 // Duplicate the flags that was set on the old page. | 1837 // Duplicate the flags that was set on the old page. |
1833 new_page->SetFlags(last_page->GetFlags(), Page::kCopyOnFlipFlagsMask); | 1838 new_page->SetFlags(last_page->GetFlags(), Page::kCopyOnFlipFlagsMask); |
1834 last_page = new_page; | 1839 last_page = new_page; |
1835 } | 1840 } |
1836 AccountCommitted(static_cast<intptr_t>(delta)); | 1841 AccountCommitted(static_cast<intptr_t>(delta)); |
1837 current_capacity_ = new_capacity; | 1842 current_capacity_ = new_capacity; |
1838 return true; | 1843 return true; |
1839 } | 1844 } |
1840 | 1845 |
1841 void SemiSpace::RewindPages(Page* start, int num_pages) { | 1846 void SemiSpace::RewindPages(Page* start, int num_pages) { |
(...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2902 } | 2907 } |
2903 } | 2908 } |
2904 return NULL; | 2909 return NULL; |
2905 } | 2910 } |
2906 | 2911 |
2907 | 2912 |
2908 void LargeObjectSpace::ClearMarkingStateOfLiveObjects() { | 2913 void LargeObjectSpace::ClearMarkingStateOfLiveObjects() { |
2909 LargePage* current = first_page_; | 2914 LargePage* current = first_page_; |
2910 while (current != NULL) { | 2915 while (current != NULL) { |
2911 HeapObject* object = current->GetObject(); | 2916 HeapObject* object = current->GetObject(); |
2912 MarkBit mark_bit = Marking::MarkBitFrom(object); | 2917 MarkBit mark_bit = ObjectMarking::MarkBitFrom(object); |
2913 DCHECK(Marking::IsBlack(mark_bit)); | 2918 DCHECK(Marking::IsBlack(mark_bit)); |
2914 Marking::BlackToWhite(mark_bit); | 2919 Marking::BlackToWhite(mark_bit); |
2915 Page::FromAddress(object->address())->ResetProgressBar(); | 2920 Page::FromAddress(object->address())->ResetProgressBar(); |
2916 Page::FromAddress(object->address())->ResetLiveBytes(); | 2921 Page::FromAddress(object->address())->ResetLiveBytes(); |
2917 current = current->next_page(); | 2922 current = current->next_page(); |
2918 } | 2923 } |
2919 } | 2924 } |
2920 | 2925 |
2921 void LargeObjectSpace::InsertChunkMapEntries(LargePage* page) { | 2926 void LargeObjectSpace::InsertChunkMapEntries(LargePage* page) { |
2922 // Register all MemoryChunk::kAlignment-aligned chunks covered by | 2927 // Register all MemoryChunk::kAlignment-aligned chunks covered by |
(...skipping 23 matching lines...) Expand all Loading... |
2946 for (uintptr_t key = start; key <= limit; key++) { | 2951 for (uintptr_t key = start; key <= limit; key++) { |
2947 chunk_map_.Remove(reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); | 2952 chunk_map_.Remove(reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); |
2948 } | 2953 } |
2949 } | 2954 } |
2950 | 2955 |
2951 void LargeObjectSpace::FreeUnmarkedObjects() { | 2956 void LargeObjectSpace::FreeUnmarkedObjects() { |
2952 LargePage* previous = NULL; | 2957 LargePage* previous = NULL; |
2953 LargePage* current = first_page_; | 2958 LargePage* current = first_page_; |
2954 while (current != NULL) { | 2959 while (current != NULL) { |
2955 HeapObject* object = current->GetObject(); | 2960 HeapObject* object = current->GetObject(); |
2956 MarkBit mark_bit = Marking::MarkBitFrom(object); | 2961 MarkBit mark_bit = ObjectMarking::MarkBitFrom(object); |
2957 DCHECK(!Marking::IsGrey(mark_bit)); | 2962 DCHECK(!Marking::IsGrey(mark_bit)); |
2958 if (Marking::IsBlack(mark_bit)) { | 2963 if (Marking::IsBlack(mark_bit)) { |
2959 Address free_start; | 2964 Address free_start; |
2960 if ((free_start = current->GetAddressToShrink()) != 0) { | 2965 if ((free_start = current->GetAddressToShrink()) != 0) { |
2961 // TODO(hpayer): Perform partial free concurrently. | 2966 // TODO(hpayer): Perform partial free concurrently. |
2962 current->ClearOutOfLiveRangeSlots(free_start); | 2967 current->ClearOutOfLiveRangeSlots(free_start); |
2963 RemoveChunkMapEntries(current, free_start); | 2968 RemoveChunkMapEntries(current, free_start); |
2964 heap()->memory_allocator()->PartialFreeMemory(current, free_start); | 2969 heap()->memory_allocator()->PartialFreeMemory(current, free_start); |
2965 } | 2970 } |
2966 previous = current; | 2971 previous = current; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 | 3083 |
3079 void Page::Print() { | 3084 void Page::Print() { |
3080 // Make a best-effort to print the objects in the page. | 3085 // Make a best-effort to print the objects in the page. |
3081 PrintF("Page@%p in %s\n", static_cast<void*>(this->address()), | 3086 PrintF("Page@%p in %s\n", static_cast<void*>(this->address()), |
3082 AllocationSpaceName(this->owner()->identity())); | 3087 AllocationSpaceName(this->owner()->identity())); |
3083 printf(" --------------------------------------\n"); | 3088 printf(" --------------------------------------\n"); |
3084 HeapObjectIterator objects(this); | 3089 HeapObjectIterator objects(this); |
3085 unsigned mark_size = 0; | 3090 unsigned mark_size = 0; |
3086 for (HeapObject* object = objects.Next(); object != NULL; | 3091 for (HeapObject* object = objects.Next(); object != NULL; |
3087 object = objects.Next()) { | 3092 object = objects.Next()) { |
3088 bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)); | 3093 bool is_marked = Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(object)); |
3089 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little. | 3094 PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little. |
3090 if (is_marked) { | 3095 if (is_marked) { |
3091 mark_size += object->Size(); | 3096 mark_size += object->Size(); |
3092 } | 3097 } |
3093 object->ShortPrint(); | 3098 object->ShortPrint(); |
3094 PrintF("\n"); | 3099 PrintF("\n"); |
3095 } | 3100 } |
3096 printf(" --------------------------------------\n"); | 3101 printf(" --------------------------------------\n"); |
3097 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3102 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3098 } | 3103 } |
3099 | 3104 |
3100 #endif // DEBUG | 3105 #endif // DEBUG |
3101 } // namespace internal | 3106 } // namespace internal |
3102 } // namespace v8 | 3107 } // namespace v8 |
OLD | NEW |