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 bool memory_available = true; | |
1010 bool spaces_need_memory = true; | |
1011 FreeSpace* node = nullptr; | |
1012 int index = 0; | |
1013 CompactionSpace* current_space = nullptr; | |
1014 // Iterate over spaces and memory as long as we have memory and there are | |
1015 // spaces in need of some. | |
1016 while (memory_available && spaces_need_memory) { | |
1017 spaces_need_memory = false; | |
1018 // Round-robin over all spaces. | |
1019 for (int i = 0; i < num; i++) { | |
1020 current_space = other[index]->Get(identity()); | |
1021 if (current_space->free_list()->available() < limit) { | |
1022 // Space has not reached its limit. Try to get some memory. | |
1023 spaces_need_memory = true; | |
1024 node = TryRemoveMemory(limit - current_space->free_list()->available()); | |
1025 if (node != nullptr) { | |
1026 CHECK(current_space->identity() == identity()); | |
1027 current_space->AddMemory(node->address(), node->size()); | |
1028 } else { | |
1029 memory_available = false; | |
1030 break; | |
1031 } | |
1032 } | |
1033 } | |
1034 } | |
1035 } | |
1036 | |
1037 | |
985 void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { | 1038 void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { |
986 DCHECK(identity() == other->identity()); | 1039 DCHECK(identity() == other->identity()); |
987 // Destroy the linear allocation space of {other}. This is needed to | 1040 // Destroy the linear allocation space of {other}. This is needed to |
988 // (a) not waste the memory and | 1041 // (a) not waste the memory and |
989 // (b) keep the rest of the chunk in an iterable state (filler is needed). | 1042 // (b) keep the rest of the chunk in an iterable state (filler is needed). |
990 other->EmptyAllocationInfo(); | 1043 other->EmptyAllocationInfo(); |
991 | 1044 |
992 // Move over the free list. Concatenate makes sure that the source free list | 1045 // Move over the free list. Concatenate makes sure that the source free list |
993 // gets properly reset after moving over all nodes. | 1046 // gets properly reset after moving over all nodes. |
994 intptr_t added = free_list_.Concatenate(other->free_list()); | 1047 intptr_t added = free_list_.Concatenate(other->free_list()); |
995 | 1048 |
996 // Moved memory is not recorded as allocated memory, but rather increases and | 1049 // Moved memory is not recorded as allocated memory, but rather increases and |
997 // decreases capacity of the corresponding spaces. Used size and waste size | 1050 // decreases capacity of the corresponding spaces. |
998 // are maintained by the receiving space upon allocating and freeing blocks. | |
999 other->accounting_stats_.DecreaseCapacity(added); | 1051 other->accounting_stats_.DecreaseCapacity(added); |
1000 accounting_stats_.IncreaseCapacity(added); | 1052 accounting_stats_.IncreaseCapacity(added); |
1001 } | 1053 } |
1002 | 1054 |
1003 | 1055 |
1004 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { | 1056 void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
1005 // Unmerged fields: | 1057 // Unmerged fields: |
1006 // area_size_ | 1058 // area_size_ |
1007 // allocation_info_ | |
1008 // end_of_unswept_pages_ | |
1009 // unswept_free_bytes_ | |
1010 // anchor_ | 1059 // anchor_ |
1011 | 1060 |
1012 MoveOverFreeMemory(other); | 1061 MoveOverFreeMemory(other); |
1013 | 1062 |
1014 // Update and clear accounting statistics. | 1063 // Update and clear accounting statistics. |
1015 accounting_stats_.Merge(other->accounting_stats_); | 1064 accounting_stats_.Merge(other->accounting_stats_); |
1016 other->accounting_stats_.Reset(); | 1065 other->accounting_stats_.Clear(); |
1066 | |
1067 // The linear allocation area of {other} should be destroyed now. | |
1068 DCHECK(other->top() == nullptr); | |
1069 DCHECK(other->limit() == nullptr); | |
1070 | |
1071 DCHECK(other->end_of_unswept_pages_ == nullptr); | |
1017 | 1072 |
1018 AccountCommitted(other->CommittedMemory()); | 1073 AccountCommitted(other->CommittedMemory()); |
1019 | 1074 |
1020 // Move over pages. | 1075 // Move over pages. |
1021 PageIterator it(other); | 1076 PageIterator it(other); |
1022 Page* p = nullptr; | 1077 Page* p = nullptr; |
1023 while (it.has_next()) { | 1078 while (it.has_next()) { |
1024 p = it.next(); | 1079 p = it.next(); |
1025 p->Unlink(); | 1080 p->Unlink(); |
1026 p->set_owner(this); | 1081 p->set_owner(this); |
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2385 page = Page::FromAddress(node->address()); | 2440 page = Page::FromAddress(node->address()); |
2386 page->add_available_in_large_free_list(-(*node_size)); | 2441 page->add_available_in_large_free_list(-(*node_size)); |
2387 } | 2442 } |
2388 } | 2443 } |
2389 | 2444 |
2390 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2445 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2391 return node; | 2446 return node; |
2392 } | 2447 } |
2393 | 2448 |
2394 | 2449 |
2450 FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) { | |
2451 base::LockGuard<base::Mutex> guard(&mutex_); | |
2452 FreeSpace* node = nullptr; | |
2453 int node_size = 0; | |
2454 // Try to find a node that fits exactly. | |
2455 node = FindNodeFor(static_cast<int>(hint_size_in_bytes), &node_size); | |
2456 // If no node could be found get as much memory as possible. | |
2457 if (node == nullptr) node = FindNodeIn(kHuge, &node_size); | |
2458 if (node == nullptr) node = FindNodeIn(kLarge, &node_size); | |
2459 if (node == nullptr) node = FindNodeIn(kMedium, &node_size); | |
Michael Lippautz
2015/10/09 12:20:13
Remove medium and small lists?
| |
2460 if (node == nullptr) node = FindNodeIn(kSmall, &node_size); | |
2461 if (node != nullptr) { | |
2462 // Give back left overs that were not required by {size_in_bytes}. | |
2463 intptr_t aligned_size = RoundUp(hint_size_in_bytes, kPointerSize); | |
2464 intptr_t left_over = node_size - aligned_size; | |
2465 if (left_over > 0) { | |
2466 Free(node->address() + aligned_size, static_cast<int>(left_over)); | |
2467 node->set_size(static_cast<int>(aligned_size)); | |
2468 } | |
2469 } | |
2470 return node; | |
2471 } | |
2472 | |
2473 | |
2395 // Allocation on the old space free list. If it succeeds then a new linear | 2474 // 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 | 2475 // 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 | 2476 // the allocation fails then NULL is returned, and the caller can perform a GC |
2398 // or allocate a new page before retrying. | 2477 // or allocate a new page before retrying. |
2399 HeapObject* FreeList::Allocate(int size_in_bytes) { | 2478 HeapObject* FreeList::Allocate(int size_in_bytes) { |
2400 DCHECK(0 < size_in_bytes); | 2479 DCHECK(0 < size_in_bytes); |
2401 DCHECK(size_in_bytes <= kMaxBlockSize); | 2480 DCHECK(size_in_bytes <= kMaxBlockSize); |
2402 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | 2481 DCHECK(IsAligned(size_in_bytes, kPointerSize)); |
2403 // Don't free list allocate if there is linear space available. | 2482 // Don't free list allocate if there is linear space available. |
2404 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); | 2483 DCHECK(owner_->limit() - owner_->top() < size_in_bytes); |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3158 object->ShortPrint(); | 3237 object->ShortPrint(); |
3159 PrintF("\n"); | 3238 PrintF("\n"); |
3160 } | 3239 } |
3161 printf(" --------------------------------------\n"); | 3240 printf(" --------------------------------------\n"); |
3162 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3241 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3163 } | 3242 } |
3164 | 3243 |
3165 #endif // DEBUG | 3244 #endif // DEBUG |
3166 } // namespace internal | 3245 } // namespace internal |
3167 } // namespace v8 | 3246 } // namespace v8 |
OLD | NEW |