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 <utility> | 7 #include <utility> |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 while ((p = collector->sweeper().GetSweptPageSafe(this)) != nullptr) { | 1219 while ((p = collector->sweeper().GetSweptPageSafe(this)) != nullptr) { |
1220 // Only during compaction pages can actually change ownership. This is | 1220 // Only during compaction pages can actually change ownership. This is |
1221 // safe because there exists no other competing action on the page links | 1221 // safe because there exists no other competing action on the page links |
1222 // during compaction. | 1222 // during compaction. |
1223 if (is_local() && (p->owner() != this)) { | 1223 if (is_local() && (p->owner() != this)) { |
1224 base::LockGuard<base::Mutex> guard( | 1224 base::LockGuard<base::Mutex> guard( |
1225 reinterpret_cast<PagedSpace*>(p->owner())->mutex()); | 1225 reinterpret_cast<PagedSpace*>(p->owner())->mutex()); |
1226 p->Unlink(); | 1226 p->Unlink(); |
1227 p->set_owner(this); | 1227 p->set_owner(this); |
1228 p->InsertAfter(anchor_.prev_page()); | 1228 p->InsertAfter(anchor_.prev_page()); |
| 1229 } else { |
| 1230 CHECK_EQ(this, p->owner()); |
| 1231 // Regular refill on main thread. |
| 1232 if (p->available_in_free_list() < kPageReuseThreshold) { |
| 1233 // Relink categories with only little memory left previous to anchor. |
| 1234 p->Unlink(); |
| 1235 p->InsertAfter(anchor()->prev_page()); |
| 1236 } |
1229 } | 1237 } |
1230 added += RelinkFreeListCategories(p); | 1238 added += RelinkFreeListCategories(p); |
1231 added += p->wasted_memory(); | 1239 added += p->wasted_memory(); |
1232 if (is_local() && (added > kCompactionMemoryWanted)) break; | 1240 if (is_local() && (added > kCompactionMemoryWanted)) break; |
1233 } | 1241 } |
1234 } | 1242 } |
1235 accounting_stats_.IncreaseCapacity(added); | 1243 accounting_stats_.IncreaseCapacity(added); |
1236 } | 1244 } |
1237 | 1245 |
1238 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { | 1246 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1299 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 1307 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
1300 Address cur = obj->address(); | 1308 Address cur = obj->address(); |
1301 Address next = cur + obj->Size(); | 1309 Address next = cur + obj->Size(); |
1302 if ((cur <= addr) && (addr < next)) return obj; | 1310 if ((cur <= addr) && (addr < next)) return obj; |
1303 } | 1311 } |
1304 | 1312 |
1305 UNREACHABLE(); | 1313 UNREACHABLE(); |
1306 return Smi::kZero; | 1314 return Smi::kZero; |
1307 } | 1315 } |
1308 | 1316 |
| 1317 Page* PagedSpace::RemovePageSafe() { |
| 1318 base::LockGuard<base::Mutex> guard(mutex()); |
| 1319 |
| 1320 if (anchor()->next_page() == anchor() || |
| 1321 anchor()->next_page()->available_in_free_list() < kPageReuseThreshold) |
| 1322 return nullptr; |
| 1323 |
| 1324 Page* page = anchor()->next_page(); |
| 1325 AccountUncommitted(page->size()); |
| 1326 accounting_stats_.DeallocateBytes(page->LiveBytesFromFreeList()); |
| 1327 accounting_stats_.DecreaseCapacity(page->size()); |
| 1328 page->Unlink(); |
| 1329 UnlinkFreeListCategories(page); |
| 1330 return page; |
| 1331 } |
| 1332 |
| 1333 void PagedSpace::AddPage(Page* page) { |
| 1334 AccountCommitted(page->size()); |
| 1335 accounting_stats_.IncreaseCapacity(page->size()); |
| 1336 accounting_stats_.AllocateBytes(page->LiveBytesFromFreeList()); |
| 1337 page->set_owner(this); |
| 1338 RelinkFreeListCategories(page); |
| 1339 page->InsertAfter(anchor()->prev_page()); |
| 1340 } |
| 1341 |
1309 void PagedSpace::ShrinkImmortalImmovablePages() { | 1342 void PagedSpace::ShrinkImmortalImmovablePages() { |
1310 DCHECK(!heap()->deserialization_complete()); | 1343 DCHECK(!heap()->deserialization_complete()); |
1311 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 1344 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
1312 EmptyAllocationInfo(); | 1345 EmptyAllocationInfo(); |
1313 ResetFreeList(); | 1346 ResetFreeList(); |
1314 | 1347 |
1315 for (Page* page : *this) { | 1348 for (Page* page : *this) { |
1316 DCHECK(page->IsFlagSet(Page::NEVER_EVACUATE)); | 1349 DCHECK(page->IsFlagSet(Page::NEVER_EVACUATE)); |
1317 size_t unused = page->ShrinkToHighWaterMark(); | 1350 size_t unused = page->ShrinkToHighWaterMark(); |
1318 accounting_stats_.DecreaseCapacity(static_cast<intptr_t>(unused)); | 1351 accounting_stats_.DecreaseCapacity(static_cast<intptr_t>(unused)); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 | 1472 |
1440 #ifdef DEBUG | 1473 #ifdef DEBUG |
1441 void PagedSpace::Print() {} | 1474 void PagedSpace::Print() {} |
1442 #endif | 1475 #endif |
1443 | 1476 |
1444 #ifdef VERIFY_HEAP | 1477 #ifdef VERIFY_HEAP |
1445 void PagedSpace::Verify(ObjectVisitor* visitor) { | 1478 void PagedSpace::Verify(ObjectVisitor* visitor) { |
1446 bool allocation_pointer_found_in_space = | 1479 bool allocation_pointer_found_in_space = |
1447 (allocation_info_.top() == allocation_info_.limit()); | 1480 (allocation_info_.top() == allocation_info_.limit()); |
1448 for (Page* page : *this) { | 1481 for (Page* page : *this) { |
| 1482 if (page->IsFlagSet(Page::CANNOT_BE_VERIFIED)) continue; |
1449 CHECK(page->owner() == this); | 1483 CHECK(page->owner() == this); |
1450 if (page == Page::FromAllocationAreaAddress(allocation_info_.top())) { | 1484 if (page == Page::FromAllocationAreaAddress(allocation_info_.top())) { |
1451 allocation_pointer_found_in_space = true; | 1485 allocation_pointer_found_in_space = true; |
1452 } | 1486 } |
1453 CHECK(page->SweepingDone()); | 1487 CHECK(page->SweepingDone()); |
1454 HeapObjectIterator it(page); | 1488 HeapObjectIterator it(page); |
1455 Address end_of_previous_object = page->area_start(); | 1489 Address end_of_previous_object = page->area_start(); |
1456 Address top = page->area_end(); | 1490 Address top = page->area_end(); |
1457 int black_size = 0; | 1491 int black_size = 0; |
1458 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | 1492 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 // allocation pointer. | 1874 // allocation pointer. |
1841 Address current = to_space_.first_page()->area_start(); | 1875 Address current = to_space_.first_page()->area_start(); |
1842 CHECK_EQ(current, to_space_.space_start()); | 1876 CHECK_EQ(current, to_space_.space_start()); |
1843 | 1877 |
1844 while (current != top()) { | 1878 while (current != top()) { |
1845 if (!Page::IsAlignedToPageSize(current)) { | 1879 if (!Page::IsAlignedToPageSize(current)) { |
1846 // The allocation pointer should not be in the middle of an object. | 1880 // The allocation pointer should not be in the middle of an object. |
1847 CHECK(!Page::FromAllocationAreaAddress(current)->ContainsLimit(top()) || | 1881 CHECK(!Page::FromAllocationAreaAddress(current)->ContainsLimit(top()) || |
1848 current < top()); | 1882 current < top()); |
1849 | 1883 |
| 1884 if (Page::FromAddress(current)->IsFlagSet(Page::CANNOT_BE_VERIFIED)) { |
| 1885 Page* page = Page::FromAddress(current); |
| 1886 if (page->next_page()->is_anchor()) { |
| 1887 current = top(); |
| 1888 } else { |
| 1889 current = Page::FromAddress(current)->area_end(); |
| 1890 } |
| 1891 continue; |
| 1892 } |
| 1893 |
1850 HeapObject* object = HeapObject::FromAddress(current); | 1894 HeapObject* object = HeapObject::FromAddress(current); |
1851 | 1895 |
1852 // The first word should be a map, and we expect all map pointers to | 1896 // The first word should be a map, and we expect all map pointers to |
1853 // be in map space. | 1897 // be in map space. |
1854 Map* map = object->map(); | 1898 Map* map = object->map(); |
1855 CHECK(map->IsMap()); | 1899 CHECK(map->IsMap()); |
1856 CHECK(heap()->map_space()->Contains(map)); | 1900 CHECK(heap()->map_space()->Contains(map)); |
1857 | 1901 |
1858 // The object should not be code or a map. | 1902 // The object should not be code or a map. |
1859 CHECK(!object->IsMap()); | 1903 CHECK(!object->IsMap()); |
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2828 return free_list_.Allocate(size_in_bytes); | 2872 return free_list_.Allocate(size_in_bytes); |
2829 } | 2873 } |
2830 return nullptr; | 2874 return nullptr; |
2831 } | 2875 } |
2832 | 2876 |
2833 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { | 2877 HeapObject* PagedSpace::SlowAllocateRaw(int size_in_bytes) { |
2834 DCHECK_GE(size_in_bytes, 0); | 2878 DCHECK_GE(size_in_bytes, 0); |
2835 const int kMaxPagesToSweep = 1; | 2879 const int kMaxPagesToSweep = 1; |
2836 | 2880 |
2837 // Allocation in this space has failed. | 2881 // Allocation in this space has failed. |
2838 | |
2839 MarkCompactCollector* collector = heap()->mark_compact_collector(); | 2882 MarkCompactCollector* collector = heap()->mark_compact_collector(); |
2840 // Sweeping is still in progress. | 2883 // Sweeping is still in progress. |
2841 if (collector->sweeping_in_progress()) { | 2884 if (collector->sweeping_in_progress()) { |
2842 // First try to refill the free-list, concurrent sweeper threads | 2885 // First try to refill the free-list, concurrent sweeper threads |
2843 // may have freed some objects in the meantime. | 2886 // may have freed some objects in the meantime. |
2844 RefillFreeList(); | 2887 RefillFreeList(); |
2845 | 2888 |
2846 // Retry the free list allocation. | 2889 // Retry the free list allocation. |
2847 HeapObject* object = | 2890 HeapObject* object = |
2848 free_list_.Allocate(static_cast<size_t>(size_in_bytes)); | 2891 free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2849 if (object != NULL) return object; | 2892 if (object != NULL) return object; |
2850 | 2893 |
2851 // If sweeping is still in progress try to sweep pages on the main thread. | 2894 // If sweeping is still in progress try to sweep pages on the main thread. |
2852 int max_freed = collector->sweeper().ParallelSweepSpace( | 2895 int max_freed = collector->sweeper().ParallelSweepSpace( |
2853 identity(), size_in_bytes, kMaxPagesToSweep); | 2896 identity(), size_in_bytes, kMaxPagesToSweep); |
2854 RefillFreeList(); | 2897 RefillFreeList(); |
2855 if (max_freed >= size_in_bytes) { | 2898 if (max_freed >= size_in_bytes) { |
2856 object = free_list_.Allocate(static_cast<size_t>(size_in_bytes)); | 2899 object = free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2857 if (object != nullptr) return object; | 2900 if (object != nullptr) return object; |
2858 } | 2901 } |
| 2902 } else if (is_local()) { |
| 2903 // Sweeping not in progress and we are on a {CompactionSpace}. |
| 2904 Page* page = heap()->old_space()->RemovePageSafe(); |
| 2905 if (page != nullptr) { |
| 2906 PrintF("Reusing page: available free list memory: %" PRIuS "\n", |
| 2907 page->available_in_free_list()); |
| 2908 AddPage(page); |
| 2909 HeapObject* object = |
| 2910 free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
| 2911 if (object != nullptr) return object; |
| 2912 } |
2859 } | 2913 } |
2860 | 2914 |
2861 if (heap()->ShouldExpandOldGenerationOnAllocationFailure() && Expand()) { | 2915 if (heap()->ShouldExpandOldGenerationOnAllocationFailure() && Expand()) { |
2862 DCHECK((CountTotalPages() > 1) || | 2916 DCHECK((CountTotalPages() > 1) || |
2863 (static_cast<size_t>(size_in_bytes) <= free_list_.Available())); | 2917 (static_cast<size_t>(size_in_bytes) <= free_list_.Available())); |
2864 return free_list_.Allocate(static_cast<size_t>(size_in_bytes)); | 2918 return free_list_.Allocate(static_cast<size_t>(size_in_bytes)); |
2865 } | 2919 } |
2866 | 2920 |
2867 // If sweeper threads are active, wait for them at that point and steal | 2921 // If sweeper threads are active, wait for them at that point and steal |
2868 // elements form their free-lists. Allocation may still fail their which | 2922 // elements form their free-lists. Allocation may still fail their which |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3247 object->ShortPrint(); | 3301 object->ShortPrint(); |
3248 PrintF("\n"); | 3302 PrintF("\n"); |
3249 } | 3303 } |
3250 printf(" --------------------------------------\n"); | 3304 printf(" --------------------------------------\n"); |
3251 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3305 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3252 } | 3306 } |
3253 | 3307 |
3254 #endif // DEBUG | 3308 #endif // DEBUG |
3255 } // namespace internal | 3309 } // namespace internal |
3256 } // namespace v8 | 3310 } // namespace v8 |
OLD | NEW |