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 // 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 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 if (!heap()->CanExpandOldGeneration(size)) return false; | 1222 if (!heap()->CanExpandOldGeneration(size)) return false; | 
| 1223 | 1223 | 
| 1224 Page* p = heap()->memory_allocator()->AllocatePage(size, this, executable()); | 1224 Page* p = heap()->memory_allocator()->AllocatePage(size, this, executable()); | 
| 1225 if (p == nullptr) return false; | 1225 if (p == nullptr) return false; | 
| 1226 | 1226 | 
| 1227 AccountCommitted(static_cast<intptr_t>(p->size())); | 1227 AccountCommitted(static_cast<intptr_t>(p->size())); | 
| 1228 | 1228 | 
| 1229 // Pages created during bootstrapping may contain immortal immovable objects. | 1229 // Pages created during bootstrapping may contain immortal immovable objects. | 
| 1230 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); | 1230 if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); | 
| 1231 | 1231 | 
| 1232 // When incremental marking was activated, old space pages are allocated | |
| 1233 // black. | |
| 1234 if (heap()->incremental_marking()->black_allocation() && | |
| 1235 identity() == OLD_SPACE) { | |
| 1236 p->markbits()->SetAllBits(); | |
| 1237 p->SetFlag(Page::BLACK_PAGE); | |
| 1238 if (FLAG_trace_incremental_marking) { | |
| 1239 PrintIsolate(heap()->isolate(), "Added black page %p\n", | |
| 1240 static_cast<void*>(p)); | |
| 1241 } | |
| 1242 } | |
| 1243 | |
| 1244 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); | 1232 DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); | 
| 1245 | 1233 | 
| 1246 p->InsertAfter(anchor_.prev_page()); | 1234 p->InsertAfter(anchor_.prev_page()); | 
| 1247 | 1235 | 
| 1248 return true; | 1236 return true; | 
| 1249 } | 1237 } | 
| 1250 | 1238 | 
| 1251 | 1239 | 
| 1252 int PagedSpace::CountTotalPages() { | 1240 int PagedSpace::CountTotalPages() { | 
| 1253 int count = 0; | 1241 int count = 0; | 
| 1254 for (Page* page : *this) { | 1242 for (Page* page : *this) { | 
| 1255 count++; | 1243 count++; | 
| 1256 USE(page); | 1244 USE(page); | 
| 1257 } | 1245 } | 
| 1258 return count; | 1246 return count; | 
| 1259 } | 1247 } | 
| 1260 | 1248 | 
| 1261 | 1249 | 
| 1262 void PagedSpace::ResetFreeListStatistics() { | 1250 void PagedSpace::ResetFreeListStatistics() { | 
| 1263 for (Page* page : *this) { | 1251 for (Page* page : *this) { | 
| 1264 page->ResetFreeListStatistics(); | 1252 page->ResetFreeListStatistics(); | 
| 1265 } | 1253 } | 
| 1266 } | 1254 } | 
| 1267 | 1255 | 
| 1256 void PagedSpace::SetAllocationInfo(Address top, Address limit) { | |
| 1257 SetTopAndLimit(top, limit); | |
| 1258 if (top != nullptr && top != limit && | |
| 1259 heap()->incremental_marking()->black_allocation()) { | |
| 1260 Page* page = Page::FromAddress(top); | |
| 1261 page->markbits()->SetRange(page->AddressToMarkbitIndex(top), | |
| 1262 page->AddressToMarkbitIndex(limit)); | |
| 1263 page->IncrementLiveBytes(static_cast<int>(limit - top)); | |
| 1264 } | |
| 1265 } | |
| 1266 | |
| 1267 // Empty space allocation info, returning unused area to free list. | |
| 1268 void PagedSpace::EmptyAllocationInfo() { | |
| 1269 // Mark the old linear allocation area with a free space map so it can be | |
| 1270 // skipped when scanning the heap. | |
| 1271 Address current_top = top(); | |
| 1272 Address current_limit = limit(); | |
| 1273 if (current_top == nullptr) { | |
| 1274 DCHECK(current_limit == nullptr); | |
| 1275 return; | |
| 1276 } | |
| 1277 int old_linear_size = static_cast<int>(current_limit - current_top); | |
| 1278 Free(current_top, old_linear_size); | |
| 
 
ulan
2016/07/19 13:23:32
Let's move it after clearing the range, so that we
 
Hannes Payer (out of office)
2016/07/19 14:42:53
Done.
 
 | |
| 1279 SetTopAndLimit(NULL, NULL); | |
| 1280 if (current_top != current_limit && | |
| 1281 heap()->incremental_marking()->black_allocation()) { | |
| 1282 Page* page = Page::FromAddress(current_top); | |
| 1283 page->markbits()->ClearRange(page->AddressToMarkbitIndex(current_top), | |
| 1284 page->AddressToMarkbitIndex(current_limit)); | |
| 1285 page->IncrementLiveBytes(static_cast<int>(current_top - current_limit)); | |
| 
 
ulan
2016/07/19 13:23:32
To avoid large unsigned to int conversions, let's
 
Hannes Payer (out of office)
2016/07/19 14:42:53
Done.
Good idea. I do that in the follow-up CL th
 
 | |
| 1286 } | |
| 1287 } | |
| 1268 | 1288 | 
| 1269 void PagedSpace::IncreaseCapacity(int size) { | 1289 void PagedSpace::IncreaseCapacity(int size) { | 
| 1270 accounting_stats_.ExpandSpace(size); | 1290 accounting_stats_.ExpandSpace(size); | 
| 1271 } | 1291 } | 
| 1272 | 1292 | 
| 1273 void PagedSpace::ReleasePage(Page* page) { | 1293 void PagedSpace::ReleasePage(Page* page) { | 
| 1274 DCHECK_EQ(page->LiveBytes(), 0); | 1294 DCHECK_EQ(page->LiveBytes(), 0); | 
| 1275 DCHECK_EQ(AreaSize(), page->area_size()); | 1295 DCHECK_EQ(AreaSize(), page->area_size()); | 
| 1276 DCHECK_EQ(page->owner(), this); | 1296 DCHECK_EQ(page->owner(), this); | 
| 1277 | 1297 | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1324 | 1344 | 
| 1325 // Perform space-specific object verification. | 1345 // Perform space-specific object verification. | 
| 1326 VerifyObject(object); | 1346 VerifyObject(object); | 
| 1327 | 1347 | 
| 1328 // The object itself should look OK. | 1348 // The object itself should look OK. | 
| 1329 object->ObjectVerify(); | 1349 object->ObjectVerify(); | 
| 1330 | 1350 | 
| 1331 // All the interior pointers should be contained in the heap. | 1351 // All the interior pointers should be contained in the heap. | 
| 1332 int size = object->Size(); | 1352 int size = object->Size(); | 
| 1333 object->IterateBody(map->instance_type(), size, visitor); | 1353 object->IterateBody(map->instance_type(), size, visitor); | 
| 1334 if (!page->IsFlagSet(Page::BLACK_PAGE) && | 1354 if (Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) { | 
| 1335 Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) { | |
| 1336 black_size += size; | 1355 black_size += size; | 
| 1337 } | 1356 } | 
| 1338 | 1357 | 
| 1339 CHECK(object->address() + size <= top); | 1358 CHECK(object->address() + size <= top); | 
| 1340 end_of_previous_object = object->address() + size; | 1359 end_of_previous_object = object->address() + size; | 
| 1341 } | 1360 } | 
| 1342 CHECK_LE(black_size, page->LiveBytes()); | 1361 CHECK_LE(black_size, page->LiveBytes()); | 
| 1343 } | 1362 } | 
| 1344 CHECK(allocation_pointer_found_in_space); | 1363 CHECK(allocation_pointer_found_in_space); | 
| 1345 } | 1364 } | 
| (...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2422 DCHECK(0 < size_in_bytes); | 2441 DCHECK(0 < size_in_bytes); | 
| 2423 DCHECK(size_in_bytes <= kMaxBlockSize); | 2442 DCHECK(size_in_bytes <= kMaxBlockSize); | 
| 2424 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | 2443 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | 
| 2425 // Don't free list allocate if there is linear space available. | 2444 // Don't free list allocate if there is linear space available. | 
| 2426 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); | 2445 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); | 
| 2427 | 2446 | 
| 2428 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); | 2447 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); | 
| 2429 // Mark the old linear allocation area with a free space map so it can be | 2448 // Mark the old linear allocation area with a free space map so it can be | 
| 2430 // skipped when scanning the heap. This also puts it back in the free list | 2449 // skipped when scanning the heap. This also puts it back in the free list | 
| 2431 // if it is big enough. | 2450 // if it is big enough. | 
| 2432 owner_->Free(owner_->top(), old_linear_size); | 2451 owner_->EmptyAllocationInfo(); | 
| 2433 owner_->SetTopAndLimit(nullptr, nullptr); | |
| 2434 | 2452 | 
| 2435 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - | 2453 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - | 
| 2436 old_linear_size); | 2454 old_linear_size); | 
| 2437 | 2455 | 
| 2438 int new_node_size = 0; | 2456 int new_node_size = 0; | 
| 2439 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); | 2457 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); | 
| 2440 if (new_node == nullptr) return nullptr; | 2458 if (new_node == nullptr) return nullptr; | 
| 2441 | 2459 | 
| 2442 int bytes_left = new_node_size - size_in_bytes; | 2460 int bytes_left = new_node_size - size_in_bytes; | 
| 2443 DCHECK(bytes_left >= 0); | 2461 DCHECK(bytes_left >= 0); | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2457 const int kThreshold = IncrementalMarking::kAllocatedThreshold; | 2475 const int kThreshold = IncrementalMarking::kAllocatedThreshold; | 
| 2458 | 2476 | 
| 2459 // Memory in the linear allocation area is counted as allocated. We may free | 2477 // Memory in the linear allocation area is counted as allocated. We may free | 
| 2460 // a little of this again immediately - see below. | 2478 // a little of this again immediately - see below. | 
| 2461 owner_->Allocate(new_node_size); | 2479 owner_->Allocate(new_node_size); | 
| 2462 | 2480 | 
| 2463 if (owner_->heap()->inline_allocation_disabled()) { | 2481 if (owner_->heap()->inline_allocation_disabled()) { | 
| 2464 // Keep the linear allocation area empty if requested to do so, just | 2482 // Keep the linear allocation area empty if requested to do so, just | 
| 2465 // return area back to the free list instead. | 2483 // return area back to the free list instead. | 
| 2466 owner_->Free(new_node->address() + size_in_bytes, bytes_left); | 2484 owner_->Free(new_node->address() + size_in_bytes, bytes_left); | 
| 2467 owner_->SetTopAndLimit(new_node->address() + size_in_bytes, | 2485 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, | 
| 2468 new_node->address() + size_in_bytes); | 2486 new_node->address() + size_in_bytes); | 
| 2469 } else if (bytes_left > kThreshold && | 2487 } else if (bytes_left > kThreshold && | 
| 2470 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && | 2488 owner_->heap()->incremental_marking()->IsMarkingIncomplete() && | 
| 2471 FLAG_incremental_marking) { | 2489 FLAG_incremental_marking) { | 
| 2472 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); | 2490 int linear_size = owner_->RoundSizeDownToObjectAlignment(kThreshold); | 
| 2473 // We don't want to give too large linear areas to the allocator while | 2491 // We don't want to give too large linear areas to the allocator while | 
| 2474 // incremental marking is going on, because we won't check again whether | 2492 // incremental marking is going on, because we won't check again whether | 
| 2475 // we want to do another increment until the linear area is used up. | 2493 // we want to do another increment until the linear area is used up. | 
| 2476 owner_->Free(new_node->address() + size_in_bytes + linear_size, | 2494 owner_->Free(new_node->address() + size_in_bytes + linear_size, | 
| 2477 new_node_size - size_in_bytes - linear_size); | 2495 new_node_size - size_in_bytes - linear_size); | 
| 2478 owner_->SetTopAndLimit(new_node->address() + size_in_bytes, | 2496 owner_->SetAllocationInfo( | 
| 2479 new_node->address() + size_in_bytes + linear_size); | 2497 new_node->address() + size_in_bytes, | 
| 2498 new_node->address() + size_in_bytes + linear_size); | |
| 2480 } else { | 2499 } else { | 
| 2481 DCHECK(bytes_left >= 0); | 2500 DCHECK(bytes_left >= 0); | 
| 2482 // Normally we give the rest of the node to the allocator as its new | 2501 // Normally we give the rest of the node to the allocator as its new | 
| 2483 // linear allocation area. | 2502 // linear allocation area. | 
| 2484 owner_->SetTopAndLimit(new_node->address() + size_in_bytes, | 2503 owner_->SetAllocationInfo(new_node->address() + size_in_bytes, | 
| 2485 new_node->address() + new_node_size); | 2504 new_node->address() + new_node_size); | 
| 2486 } | 2505 } | 
| 2487 | 2506 | 
| 2488 owner_->AllocationStep(new_node->address(), size_in_bytes); | 2507 owner_->AllocationStep(new_node->address(), size_in_bytes); | 
| 2489 | 2508 | 
| 2490 return new_node; | 2509 return new_node; | 
| 2491 } | 2510 } | 
| 2492 | 2511 | 
| 2493 intptr_t FreeList::EvictFreeListItems(Page* page) { | 2512 intptr_t FreeList::EvictFreeListItems(Page* page) { | 
| 2494 intptr_t sum = 0; | 2513 intptr_t sum = 0; | 
| 2495 page->ForAllFreeListCategories( | 2514 page->ForAllFreeListCategories( | 
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2865 if (Heap::ShouldZapGarbage()) { | 2884 if (Heap::ShouldZapGarbage()) { | 
| 2866 // Make the object consistent so the heap can be verified in OldSpaceStep. | 2885 // Make the object consistent so the heap can be verified in OldSpaceStep. | 
| 2867 // We only need to do this in debug builds or if verify_heap is on. | 2886 // We only need to do this in debug builds or if verify_heap is on. | 
| 2868 reinterpret_cast<Object**>(object->address())[0] = | 2887 reinterpret_cast<Object**>(object->address())[0] = | 
| 2869 heap()->fixed_array_map(); | 2888 heap()->fixed_array_map(); | 
| 2870 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); | 2889 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); | 
| 2871 } | 2890 } | 
| 2872 | 2891 | 
| 2873 heap()->incremental_marking()->OldSpaceStep(object_size); | 2892 heap()->incremental_marking()->OldSpaceStep(object_size); | 
| 2874 AllocationStep(object->address(), object_size); | 2893 AllocationStep(object->address(), object_size); | 
| 2894 | |
| 2895 if (heap()->incremental_marking()->black_allocation()) { | |
| 2896 Marking::MarkBlack(ObjectMarking::MarkBitFrom(object)); | |
| 2897 MemoryChunk::IncrementLiveBytesFromGC(object, object_size); | |
| 2898 } | |
| 2875 return object; | 2899 return object; | 
| 2876 } | 2900 } | 
| 2877 | 2901 | 
| 2878 | 2902 | 
| 2879 size_t LargeObjectSpace::CommittedPhysicalMemory() { | 2903 size_t LargeObjectSpace::CommittedPhysicalMemory() { | 
| 2880 // On a platform that provides lazy committing of memory, we over-account | 2904 // On a platform that provides lazy committing of memory, we over-account | 
| 2881 // the actually committed memory. There is no easy way right now to support | 2905 // the actually committed memory. There is no easy way right now to support | 
| 2882 // precise accounting of committed memory in large object space. | 2906 // precise accounting of committed memory in large object space. | 
| 2883 return CommittedMemory(); | 2907 return CommittedMemory(); | 
| 2884 } | 2908 } | 
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3098 object->ShortPrint(); | 3122 object->ShortPrint(); | 
| 3099 PrintF("\n"); | 3123 PrintF("\n"); | 
| 3100 } | 3124 } | 
| 3101 printf(" --------------------------------------\n"); | 3125 printf(" --------------------------------------\n"); | 
| 3102 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3126 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 
| 3103 } | 3127 } | 
| 3104 | 3128 | 
| 3105 #endif // DEBUG | 3129 #endif // DEBUG | 
| 3106 } // namespace internal | 3130 } // namespace internal | 
| 3107 } // namespace v8 | 3131 } // namespace v8 | 
| OLD | NEW |