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/full-codegen/full-codegen.h" | 9 #include "src/full-codegen/full-codegen.h" |
| 10 #include "src/heap/slots-buffer.h" | 10 #include "src/heap/slots-buffer.h" |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 975 PageIterator iterator(this); | 975 PageIterator iterator(this); |
| 976 while (iterator.has_next()) { | 976 while (iterator.has_next()) { |
| 977 heap()->isolate()->memory_allocator()->Free(iterator.next()); | 977 heap()->isolate()->memory_allocator()->Free(iterator.next()); |
| 978 } | 978 } |
| 979 anchor_.set_next_page(&anchor_); | 979 anchor_.set_next_page(&anchor_); |
| 980 anchor_.set_prev_page(&anchor_); | 980 anchor_.set_prev_page(&anchor_); |
| 981 accounting_stats_.Clear(); | 981 accounting_stats_.Clear(); |
| 982 } | 982 } |
| 983 | 983 |
| 984 | 984 |
| 985 void PagedSpace::AddMemory(Address start, intptr_t size) { | |
| 986 accounting_stats_.ExpandSpace(static_cast<int>(size)); | |
| 987 Free(start, static_cast<int>(size)); | |
| 988 } | |
| 989 | |
| 990 | |
| 991 FreeSpace* PagedSpace::TryRemoveMemory(intptr_t size_in_bytes) { | |
| 992 FreeSpace* space = free_list()->TryRemoveMemory(size_in_bytes); | |
| 993 if (space != nullptr) { | |
| 994 accounting_stats_.DecreaseCapacity(space->size()); | |
| 995 } | |
| 996 return space; | |
| 997 } | |
| 998 | |
| 999 | |
| 1000 void PagedSpace::DivideUponCompactionSpaces(CompactionSpaceCollection** other, | |
| 1001 int num, intptr_t limit) { | |
| 1002 DCHECK_GT(num, 0); | |
| 1003 DCHECK(other != nullptr); | |
| 1004 | |
| 1005 if (limit == 0) limit = std::numeric_limits<intptr_t>::max(); | |
| 1006 | |
| 1007 EmptyAllocationInfo(); | |
| 1008 | |
| 1009 int index = 0; | |
| 1010 FreeSpace* node = nullptr; | |
| 1011 // We evenly distribute existing memory among compaction spaces, i.e., while | |
| 1012 // iterating over them in round-robin fashion, we check whether they have | |
| 1013 // reached the {limit} of available bytes and try to add some memory if not. | |
| 1014 for (CompactionSpace* space = other[index]->Get(identity()); | |
|
ulan
2015/10/09 11:48:48
Let's simplify the "for" statement so that the cor
Michael Lippautz
2015/10/09 12:20:13
Done, rewrote the loop.
The intention is summariz
| |
| 1015 (space->free_list()->available() < limit) && | |
| 1016 ((node = TryRemoveMemory(limit - space->free_list()->available())) != | |
| 1017 nullptr); | |
| 1018 space = other[++index % num]->Get(identity())) { | |
| 1019 CHECK(space->identity() == identity()); | |
| 1020 space->AddMemory(node->address(), node->size()); | |
| 1021 } | |
| 1022 } | |
| 1023 | |
| 1024 | |
| 985 void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { | 1025 void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { |
| 986 DCHECK(identity() == other->identity()); | 1026 DCHECK(identity() == other->identity()); |
| 987 // Destroy the linear allocation space of {other}. This is needed to | 1027 // Destroy the linear allocation space of {other}. This is needed to |
| 988 // (a) not waste the memory and | 1028 // (a) not waste the memory and |
| 989 // (b) keep the rest of the chunk in an iterable state (filler is needed). | 1029 // (b) keep the rest of the chunk in an iterable state (filler is needed). |
| 990 other->EmptyAllocationInfo(); | 1030 other->EmptyAllocationInfo(); |
| 991 | 1031 |
| 992 // Move over the free list. Concatenate makes sure that the source free list | 1032 // Move over the free list. Concatenate makes sure that the source free list |
| 993 // gets properly reset after moving over all nodes. | 1033 // gets properly reset after moving over all nodes. |
| 994 intptr_t added = free_list_.Concatenate(other->free_list()); | 1034 intptr_t added = free_list_.Concatenate(other->free_list()); |
| 995 | 1035 |
| 996 // Moved memory is not recorded as allocated memory, but rather increases and | 1036 // Moved memory is not recorded as allocated memory, but rather increases and |
| 997 // decreases capacity of the corresponding spaces. Used size and waste size | 1037 // decreases capacity of the corresponding spaces. |
| 998 // are maintained by the receiving space upon allocating and freeing blocks. | |
| 999 other->accounting_stats_.DecreaseCapacity(added); | 1038 other->accounting_stats_.DecreaseCapacity(added); |
| 1000 accounting_stats_.IncreaseCapacity(added); | 1039 accounting_stats_.IncreaseCapacity(added); |
| 1001 } | 1040 } |
| 1002 | 1041 |
| 1003 | 1042 |
| 1004 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { | 1043 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
| 1005 // Unmerged fields: | 1044 // Unmerged fields: |
| 1006 // area_size_ | 1045 // area_size_ |
| 1007 // allocation_info_ | |
| 1008 // end_of_unswept_pages_ | |
| 1009 // unswept_free_bytes_ | |
| 1010 // anchor_ | 1046 // anchor_ |
| 1011 | 1047 |
| 1012 MoveOverFreeMemory(other); | 1048 MoveOverFreeMemory(other); |
| 1013 | 1049 |
| 1014 // Update and clear accounting statistics. | 1050 // Update and clear accounting statistics. |
| 1015 accounting_stats_.Merge(other->accounting_stats_); | 1051 accounting_stats_.Merge(other->accounting_stats_); |
| 1016 other->accounting_stats_.Reset(); | 1052 other->accounting_stats_.Clear(); |
| 1053 | |
| 1054 // The linear allocation area of {other} should be destroyed now. | |
| 1055 DCHECK(other->top() == nullptr); | |
| 1056 DCHECK(other->limit() == nullptr); | |
| 1057 | |
| 1058 DCHECK(other->end_of_unswept_pages_ == nullptr); | |
| 1017 | 1059 |
| 1018 AccountCommitted(other->CommittedMemory()); | 1060 AccountCommitted(other->CommittedMemory()); |
| 1019 | 1061 |
| 1020 // Move over pages. | 1062 // Move over pages. |
| 1021 PageIterator it(other); | 1063 PageIterator it(other); |
| 1022 Page* p = nullptr; | 1064 Page* p = nullptr; |
| 1023 while (it.has_next()) { | 1065 while (it.has_next()) { |
| 1024 p = it.next(); | 1066 p = it.next(); |
| 1025 p->Unlink(); | 1067 p->Unlink(); |
| 1026 p->set_owner(this); | 1068 p->set_owner(this); |
| (...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2385 page = Page::FromAddress(node->address()); | 2427 page = Page::FromAddress(node->address()); |
| 2386 page->add_available_in_large_free_list(-(*node_size)); | 2428 page->add_available_in_large_free_list(-(*node_size)); |
| 2387 } | 2429 } |
| 2388 } | 2430 } |
| 2389 | 2431 |
| 2390 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2432 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
| 2391 return node; | 2433 return node; |
| 2392 } | 2434 } |
| 2393 | 2435 |
| 2394 | 2436 |
| 2437 FreeSpace* FreeList::TryRemoveMemory(intptr_t size_in_bytes) { | |
|
ulan
2015/10/09 11:48:48
Could you please comment the postconditions of thi
Michael Lippautz
2015/10/09 12:20:13
Done. I added a high-level description to the .h f
| |
| 2438 base::LockGuard<base::Mutex> guard(&mutex_); | |
| 2439 FreeSpace* node = nullptr; | |
| 2440 int node_size = 0; | |
| 2441 // Try to find a node that fits exactly. | |
| 2442 node = FindNodeFor(static_cast<int>(size_in_bytes), &node_size); | |
| 2443 // If no node could be found get as much memory as possible. | |
| 2444 if (node == nullptr) node = FindNodeIn(kHuge, &node_size); | |
| 2445 if (node == nullptr) node = FindNodeIn(kLarge, &node_size); | |
| 2446 if (node == nullptr) node = FindNodeIn(kMedium, &node_size); | |
| 2447 if (node == nullptr) node = FindNodeIn(kSmall, &node_size); | |
| 2448 if (node != nullptr) { | |
| 2449 // Give back left overs that were not required by {size_in_bytes}. | |
|
Michael Lippautz
2015/10/09 11:08:59
This could potentially increase fragmentation, but
| |
| 2450 intptr_t aligned_size = RoundUp(size_in_bytes, kPointerSize); | |
| 2451 intptr_t left_over = node_size - aligned_size; | |
| 2452 if (left_over > 0) { | |
| 2453 Free(node->address() + aligned_size, static_cast<int>(left_over)); | |
| 2454 node->set_size(static_cast<int>(aligned_size)); | |
| 2455 } | |
| 2456 } | |
| 2457 return node; | |
| 2458 } | |
| 2459 | |
| 2460 | |
| 2395 // Allocation on the old space free list. If it succeeds then a new linear | 2461 // Allocation on the old space free list. If it succeeds then a new linear |
| 2396 // allocation space has been set up with the top and limit of the space. If | 2462 // allocation space has been set up with the top and limit of the space. If |
| 2397 // the allocation fails then NULL is returned, and the caller can perform a GC | 2463 // the allocation fails then NULL is returned, and the caller can perform a GC |
| 2398 // or allocate a new page before retrying. | 2464 // or allocate a new page before retrying. |
| 2399 HeapObject* FreeList::Allocate(int size_in_bytes) { | 2465 HeapObject* FreeList::Allocate(int size_in_bytes) { |
| 2400 DCHECK(0 < size_in_bytes); | 2466 DCHECK(0 < size_in_bytes); |
| 2401 DCHECK(size_in_bytes <= kMaxBlockSize); | 2467 DCHECK(size_in_bytes <= kMaxBlockSize); |
| 2402 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | 2468 DCHECK(IsAligned(size_in_bytes, kPointerSize)); |
| 2403 // Don't free list allocate if there is linear space available. | 2469 // Don't free list allocate if there is linear space available. |
| 2404 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); | 2470 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3158 object->ShortPrint(); | 3224 object->ShortPrint(); |
| 3159 PrintF("\n"); | 3225 PrintF("\n"); |
| 3160 } | 3226 } |
| 3161 printf(" --------------------------------------\n"); | 3227 printf(" --------------------------------------\n"); |
| 3162 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3228 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3163 } | 3229 } |
| 3164 | 3230 |
| 3165 #endif // DEBUG | 3231 #endif // DEBUG |
| 3166 } // namespace internal | 3232 } // namespace internal |
| 3167 } // namespace v8 | 3233 } // namespace v8 |
| OLD | NEW |