| 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/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| 10 #include "src/heap/slot-set.h" | 11 #include "src/heap/slot-set.h" |
| 11 #include "src/macro-assembler.h" | 12 #include "src/macro-assembler.h" |
| 12 #include "src/msan.h" | 13 #include "src/msan.h" |
| 13 #include "src/snapshot/snapshot.h" | 14 #include "src/snapshot/snapshot.h" |
| 15 #include "src/v8.h" |
| 14 | 16 |
| 15 namespace v8 { | 17 namespace v8 { |
| 16 namespace internal { | 18 namespace internal { |
| 17 | 19 |
| 18 | 20 |
| 19 // ---------------------------------------------------------------------------- | 21 // ---------------------------------------------------------------------------- |
| 20 // HeapObjectIterator | 22 // HeapObjectIterator |
| 21 | 23 |
| 22 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { | 24 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) { |
| 23 // You can't actually iterate over the anchor page. It is not a real page, | 25 // You can't actually iterate over the anchor page. It is not a real page, |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 // | 298 // |
| 297 | 299 |
| 298 MemoryAllocator::MemoryAllocator(Isolate* isolate) | 300 MemoryAllocator::MemoryAllocator(Isolate* isolate) |
| 299 : isolate_(isolate), | 301 : isolate_(isolate), |
| 300 code_range_(nullptr), | 302 code_range_(nullptr), |
| 301 capacity_(0), | 303 capacity_(0), |
| 302 capacity_executable_(0), | 304 capacity_executable_(0), |
| 303 size_(0), | 305 size_(0), |
| 304 size_executable_(0), | 306 size_executable_(0), |
| 305 lowest_ever_allocated_(reinterpret_cast<void*>(-1)), | 307 lowest_ever_allocated_(reinterpret_cast<void*>(-1)), |
| 306 highest_ever_allocated_(reinterpret_cast<void*>(0)) {} | 308 highest_ever_allocated_(reinterpret_cast<void*>(0)), |
| 309 unmapper_(this) {} |
| 307 | 310 |
| 308 bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable, | 311 bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable, |
| 309 intptr_t code_range_size) { | 312 intptr_t code_range_size) { |
| 310 capacity_ = RoundUp(capacity, Page::kPageSize); | 313 capacity_ = RoundUp(capacity, Page::kPageSize); |
| 311 capacity_executable_ = RoundUp(capacity_executable, Page::kPageSize); | 314 capacity_executable_ = RoundUp(capacity_executable, Page::kPageSize); |
| 312 DCHECK_GE(capacity_, capacity_executable_); | 315 DCHECK_GE(capacity_, capacity_executable_); |
| 313 | 316 |
| 314 size_ = 0; | 317 size_ = 0; |
| 315 size_executable_ = 0; | 318 size_executable_ = 0; |
| 316 | 319 |
| 317 code_range_ = new CodeRange(isolate_); | 320 code_range_ = new CodeRange(isolate_); |
| 318 if (!code_range_->SetUp(static_cast<size_t>(code_range_size))) return false; | 321 if (!code_range_->SetUp(static_cast<size_t>(code_range_size))) return false; |
| 319 | 322 |
| 320 return true; | 323 return true; |
| 321 } | 324 } |
| 322 | 325 |
| 323 | 326 |
| 324 void MemoryAllocator::TearDown() { | 327 void MemoryAllocator::TearDown() { |
| 325 for (MemoryChunk* chunk : chunk_pool_) { | 328 unmapper()->WaitUntilCompleted(); |
| 329 |
| 330 MemoryChunk* chunk = nullptr; |
| 331 while ((chunk = unmapper()->TryGetPooledMemoryChunkSafe()) != nullptr) { |
| 326 FreeMemory(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize, | 332 FreeMemory(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize, |
| 327 NOT_EXECUTABLE); | 333 NOT_EXECUTABLE); |
| 328 } | 334 } |
| 335 |
| 329 // Check that spaces were torn down before MemoryAllocator. | 336 // Check that spaces were torn down before MemoryAllocator. |
| 330 DCHECK_EQ(size_.Value(), 0); | 337 DCHECK_EQ(size_.Value(), 0); |
| 331 // TODO(gc) this will be true again when we fix FreeMemory. | 338 // TODO(gc) this will be true again when we fix FreeMemory. |
| 332 // DCHECK(size_executable_ == 0); | 339 // DCHECK(size_executable_ == 0); |
| 333 capacity_ = 0; | 340 capacity_ = 0; |
| 334 capacity_executable_ = 0; | 341 capacity_executable_ = 0; |
| 335 | 342 |
| 336 if (last_chunk_.IsReserved()) { | 343 if (last_chunk_.IsReserved()) { |
| 337 last_chunk_.Release(); | 344 last_chunk_.Release(); |
| 338 } | 345 } |
| 339 | 346 |
| 340 delete code_range_; | 347 delete code_range_; |
| 341 code_range_ = nullptr; | 348 code_range_ = nullptr; |
| 342 } | 349 } |
| 343 | 350 |
| 351 class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public v8::Task { |
| 352 public: |
| 353 explicit UnmapFreeMemoryTask(Unmapper* unmapper) : unmapper_(unmapper) {} |
| 354 |
| 355 private: |
| 356 // v8::Task overrides. |
| 357 void Run() override { |
| 358 unmapper_->PerformFreeMemoryOnQueuedChunks(); |
| 359 unmapper_->pending_unmapping_tasks_semaphore_.Signal(); |
| 360 } |
| 361 |
| 362 Unmapper* unmapper_; |
| 363 DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask); |
| 364 }; |
| 365 |
| 366 void MemoryAllocator::Unmapper::FreeQueuedChunks() { |
| 367 if (FLAG_concurrent_sweeping) { |
| 368 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 369 new UnmapFreeMemoryTask(this), v8::Platform::kShortRunningTask); |
| 370 concurrent_unmapping_tasks_active_++; |
| 371 } else { |
| 372 PerformFreeMemoryOnQueuedChunks(); |
| 373 } |
| 374 } |
| 375 |
| 376 bool MemoryAllocator::Unmapper::WaitUntilCompleted() { |
| 377 bool waited = false; |
| 378 while (concurrent_unmapping_tasks_active_ > 0) { |
| 379 pending_unmapping_tasks_semaphore_.Wait(); |
| 380 concurrent_unmapping_tasks_active_--; |
| 381 waited = true; |
| 382 } |
| 383 return waited; |
| 384 } |
| 385 |
| 386 void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() { |
| 387 MemoryChunk* chunk = nullptr; |
| 388 // Regular chunks. |
| 389 while ((chunk = GetMemoryChunkSafe<kRegular>()) != nullptr) { |
| 390 bool pooled = chunk->IsFlagSet(MemoryChunk::POOLED); |
| 391 allocator_->PerformFreeMemory(chunk); |
| 392 if (pooled) AddMemoryChunkSafe<kPooled>(chunk); |
| 393 } |
| 394 // Non-regular chunks. |
| 395 while ((chunk = GetMemoryChunkSafe<kNonRegular>()) != nullptr) { |
| 396 allocator_->PerformFreeMemory(chunk); |
| 397 } |
| 398 } |
| 399 |
| 344 bool MemoryAllocator::CommitMemory(Address base, size_t size, | 400 bool MemoryAllocator::CommitMemory(Address base, size_t size, |
| 345 Executability executable) { | 401 Executability executable) { |
| 346 if (!base::VirtualMemory::CommitRegion(base, size, | 402 if (!base::VirtualMemory::CommitRegion(base, size, |
| 347 executable == EXECUTABLE)) { | 403 executable == EXECUTABLE)) { |
| 348 return false; | 404 return false; |
| 349 } | 405 } |
| 350 UpdateAllocatedSpaceLimits(base, base + size); | 406 UpdateAllocatedSpaceLimits(base, base + size); |
| 351 return true; | 407 return true; |
| 352 } | 408 } |
| 353 | 409 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 | 797 |
| 742 chunk->SetFlag(MemoryChunk::PRE_FREED); | 798 chunk->SetFlag(MemoryChunk::PRE_FREED); |
| 743 } | 799 } |
| 744 | 800 |
| 745 | 801 |
| 746 void MemoryAllocator::PerformFreeMemory(MemoryChunk* chunk) { | 802 void MemoryAllocator::PerformFreeMemory(MemoryChunk* chunk) { |
| 747 DCHECK(chunk->IsFlagSet(MemoryChunk::PRE_FREED)); | 803 DCHECK(chunk->IsFlagSet(MemoryChunk::PRE_FREED)); |
| 748 chunk->ReleaseAllocatedMemory(); | 804 chunk->ReleaseAllocatedMemory(); |
| 749 | 805 |
| 750 base::VirtualMemory* reservation = chunk->reserved_memory(); | 806 base::VirtualMemory* reservation = chunk->reserved_memory(); |
| 751 if (reservation->IsReserved()) { | 807 if (chunk->IsFlagSet(MemoryChunk::POOLED)) { |
| 752 FreeMemory(reservation, chunk->executable()); | 808 UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize); |
| 753 } else { | 809 } else { |
| 754 FreeMemory(chunk->address(), chunk->size(), chunk->executable()); | 810 if (reservation->IsReserved()) { |
| 811 FreeMemory(reservation, chunk->executable()); |
| 812 } else { |
| 813 FreeMemory(chunk->address(), chunk->size(), chunk->executable()); |
| 814 } |
| 755 } | 815 } |
| 756 } | 816 } |
| 757 | 817 |
| 758 template <MemoryAllocator::AllocationMode mode> | 818 template <MemoryAllocator::FreeMode mode> |
| 759 void MemoryAllocator::Free(MemoryChunk* chunk) { | 819 void MemoryAllocator::Free(MemoryChunk* chunk) { |
| 760 if (mode == kRegular) { | 820 switch (mode) { |
| 761 PreFreeMemory(chunk); | 821 case kFull: |
| 762 PerformFreeMemory(chunk); | 822 PreFreeMemory(chunk); |
| 763 } else { | 823 PerformFreeMemory(chunk); |
| 764 DCHECK_EQ(mode, kPooled); | 824 break; |
| 765 FreePooled(chunk); | 825 case kPooledAndQueue: |
| 826 DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize)); |
| 827 DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE); |
| 828 chunk->SetFlag(MemoryChunk::POOLED); |
| 829 // Fall through to kPreFreeAndQueue. |
| 830 case kPreFreeAndQueue: |
| 831 PreFreeMemory(chunk); |
| 832 // The chunks added to this queue will be freed by a concurrent thread. |
| 833 unmapper()->AddMemoryChunkSafe(chunk); |
| 834 break; |
| 835 default: |
| 836 UNREACHABLE(); |
| 766 } | 837 } |
| 767 } | 838 } |
| 768 | 839 |
| 769 template void MemoryAllocator::Free<MemoryAllocator::kRegular>( | 840 template void MemoryAllocator::Free<MemoryAllocator::kFull>(MemoryChunk* chunk); |
| 841 |
| 842 template void MemoryAllocator::Free<MemoryAllocator::kPreFreeAndQueue>( |
| 770 MemoryChunk* chunk); | 843 MemoryChunk* chunk); |
| 771 | 844 |
| 772 template void MemoryAllocator::Free<MemoryAllocator::kPooled>( | 845 template void MemoryAllocator::Free<MemoryAllocator::kPooledAndQueue>( |
| 773 MemoryChunk* chunk); | 846 MemoryChunk* chunk); |
| 774 | 847 |
| 775 template <typename PageType, MemoryAllocator::AllocationMode mode, | 848 template <typename PageType, MemoryAllocator::AllocationMode mode, |
| 776 typename SpaceType> | 849 typename SpaceType> |
| 777 PageType* MemoryAllocator::AllocatePage(intptr_t size, SpaceType* owner, | 850 PageType* MemoryAllocator::AllocatePage(intptr_t size, SpaceType* owner, |
| 778 Executability executable) { | 851 Executability executable) { |
| 779 MemoryChunk* chunk = nullptr; | 852 MemoryChunk* chunk = nullptr; |
| 780 if (mode == kPooled) { | 853 if (mode == kPooled) { |
| 781 DCHECK_EQ(size, static_cast<intptr_t>(MemoryChunk::kAllocatableMemory)); | 854 DCHECK_EQ(size, static_cast<intptr_t>(MemoryChunk::kAllocatableMemory)); |
| 782 DCHECK_EQ(executable, NOT_EXECUTABLE); | 855 DCHECK_EQ(executable, NOT_EXECUTABLE); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 796 template LargePage* | 869 template LargePage* |
| 797 MemoryAllocator::AllocatePage<LargePage, MemoryAllocator::kRegular, Space>( | 870 MemoryAllocator::AllocatePage<LargePage, MemoryAllocator::kRegular, Space>( |
| 798 intptr_t, Space*, Executability); | 871 intptr_t, Space*, Executability); |
| 799 | 872 |
| 800 template NewSpacePage* MemoryAllocator::AllocatePage< | 873 template NewSpacePage* MemoryAllocator::AllocatePage< |
| 801 NewSpacePage, MemoryAllocator::kPooled, SemiSpace>(intptr_t, SemiSpace*, | 874 NewSpacePage, MemoryAllocator::kPooled, SemiSpace>(intptr_t, SemiSpace*, |
| 802 Executability); | 875 Executability); |
| 803 | 876 |
| 804 template <typename SpaceType> | 877 template <typename SpaceType> |
| 805 MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) { | 878 MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) { |
| 806 if (chunk_pool_.is_empty()) return nullptr; | 879 MemoryChunk* chunk = unmapper()->TryGetPooledMemoryChunkSafe(); |
| 880 if (chunk == nullptr) return nullptr; |
| 807 const int size = MemoryChunk::kPageSize; | 881 const int size = MemoryChunk::kPageSize; |
| 808 MemoryChunk* chunk = chunk_pool_.RemoveLast(); | |
| 809 const Address start = reinterpret_cast<Address>(chunk); | 882 const Address start = reinterpret_cast<Address>(chunk); |
| 810 const Address area_start = start + MemoryChunk::kObjectStartOffset; | 883 const Address area_start = start + MemoryChunk::kObjectStartOffset; |
| 811 const Address area_end = start + size; | 884 const Address area_end = start + size; |
| 812 CommitBlock(reinterpret_cast<Address>(chunk), size, NOT_EXECUTABLE); | 885 CommitBlock(reinterpret_cast<Address>(chunk), size, NOT_EXECUTABLE); |
| 813 base::VirtualMemory reservation(start, size); | 886 base::VirtualMemory reservation(start, size); |
| 814 MemoryChunk::Initialize(isolate_->heap(), start, size, area_start, area_end, | 887 MemoryChunk::Initialize(isolate_->heap(), start, size, area_start, area_end, |
| 815 NOT_EXECUTABLE, owner, &reservation); | 888 NOT_EXECUTABLE, owner, &reservation); |
| 816 size_.Increment(size); | 889 size_.Increment(size); |
| 817 return chunk; | 890 return chunk; |
| 818 } | 891 } |
| 819 | 892 |
| 820 void MemoryAllocator::FreePooled(MemoryChunk* chunk) { | |
| 821 DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize)); | |
| 822 DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE); | |
| 823 chunk_pool_.Add(chunk); | |
| 824 intptr_t chunk_size = static_cast<intptr_t>(chunk->size()); | |
| 825 if (chunk->executable() == EXECUTABLE) { | |
| 826 size_executable_.Increment(-chunk_size); | |
| 827 } | |
| 828 size_.Increment(-chunk_size); | |
| 829 UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize); | |
| 830 } | |
| 831 | |
| 832 bool MemoryAllocator::CommitBlock(Address start, size_t size, | 893 bool MemoryAllocator::CommitBlock(Address start, size_t size, |
| 833 Executability executable) { | 894 Executability executable) { |
| 834 if (!CommitMemory(start, size, executable)) return false; | 895 if (!CommitMemory(start, size, executable)) return false; |
| 835 | 896 |
| 836 if (Heap::ShouldZapGarbage()) { | 897 if (Heap::ShouldZapGarbage()) { |
| 837 ZapBlock(start, size); | 898 ZapBlock(start, size); |
| 838 } | 899 } |
| 839 | 900 |
| 840 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); | 901 isolate_->counters()->memory_allocated()->Increment(static_cast<int>(size)); |
| 841 return true; | 902 return true; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 vm->Uncommit(header, header_size); | 1025 vm->Uncommit(header, header_size); |
| 965 } | 1026 } |
| 966 return false; | 1027 return false; |
| 967 } | 1028 } |
| 968 | 1029 |
| 969 | 1030 |
| 970 // ----------------------------------------------------------------------------- | 1031 // ----------------------------------------------------------------------------- |
| 971 // MemoryChunk implementation | 1032 // MemoryChunk implementation |
| 972 | 1033 |
| 973 void MemoryChunk::ReleaseAllocatedMemory() { | 1034 void MemoryChunk::ReleaseAllocatedMemory() { |
| 974 delete skip_list_; | 1035 if (skip_list_ != nullptr) { |
| 975 skip_list_ = nullptr; | 1036 delete skip_list_; |
| 976 delete mutex_; | 1037 skip_list_ = nullptr; |
| 977 mutex_ = nullptr; | 1038 } |
| 978 ReleaseOldToNewSlots(); | 1039 if (mutex_ != nullptr) { |
| 979 ReleaseOldToOldSlots(); | 1040 delete mutex_; |
| 1041 mutex_ = nullptr; |
| 1042 } |
| 1043 if (old_to_new_slots_ != nullptr) ReleaseOldToNewSlots(); |
| 1044 if (old_to_old_slots_ != nullptr) ReleaseOldToOldSlots(); |
| 980 } | 1045 } |
| 981 | 1046 |
| 982 static SlotSet* AllocateSlotSet(size_t size, Address page_start) { | 1047 static SlotSet* AllocateSlotSet(size_t size, Address page_start) { |
| 983 size_t pages = (size + Page::kPageSize - 1) / Page::kPageSize; | 1048 size_t pages = (size + Page::kPageSize - 1) / Page::kPageSize; |
| 984 DCHECK(pages > 0); | 1049 DCHECK(pages > 0); |
| 985 SlotSet* slot_set = new SlotSet[pages]; | 1050 SlotSet* slot_set = new SlotSet[pages]; |
| 986 for (size_t i = 0; i < pages; i++) { | 1051 for (size_t i = 0; i < pages; i++) { |
| 987 slot_set[i].SetPageStart(page_start + i * Page::kPageSize); | 1052 slot_set[i].SetPageStart(page_start + i * Page::kPageSize); |
| 988 } | 1053 } |
| 989 return slot_set; | 1054 return slot_set; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 | 1118 |
| 1054 bool PagedSpace::SetUp() { return true; } | 1119 bool PagedSpace::SetUp() { return true; } |
| 1055 | 1120 |
| 1056 | 1121 |
| 1057 bool PagedSpace::HasBeenSetUp() { return true; } | 1122 bool PagedSpace::HasBeenSetUp() { return true; } |
| 1058 | 1123 |
| 1059 | 1124 |
| 1060 void PagedSpace::TearDown() { | 1125 void PagedSpace::TearDown() { |
| 1061 PageIterator iterator(this); | 1126 PageIterator iterator(this); |
| 1062 while (iterator.has_next()) { | 1127 while (iterator.has_next()) { |
| 1063 heap()->memory_allocator()->Free(iterator.next()); | 1128 heap()->memory_allocator()->Free<MemoryAllocator::kFull>(iterator.next()); |
| 1064 } | 1129 } |
| 1065 anchor_.set_next_page(&anchor_); | 1130 anchor_.set_next_page(&anchor_); |
| 1066 anchor_.set_prev_page(&anchor_); | 1131 anchor_.set_prev_page(&anchor_); |
| 1067 accounting_stats_.Clear(); | 1132 accounting_stats_.Clear(); |
| 1068 } | 1133 } |
| 1069 | 1134 |
| 1070 void PagedSpace::RefillFreeList() { | 1135 void PagedSpace::RefillFreeList() { |
| 1071 // Any PagedSpace might invoke RefillFreeList. We filter all but our old | 1136 // Any PagedSpace might invoke RefillFreeList. We filter all but our old |
| 1072 // generation spaces out. | 1137 // generation spaces out. |
| 1073 if (identity() != OLD_SPACE && identity() != CODE_SPACE && | 1138 if (identity() != OLD_SPACE && identity() != CODE_SPACE && |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 allocation_info_.Reset(nullptr, nullptr); | 1309 allocation_info_.Reset(nullptr, nullptr); |
| 1245 } | 1310 } |
| 1246 | 1311 |
| 1247 // If page is still in a list, unlink it from that list. | 1312 // If page is still in a list, unlink it from that list. |
| 1248 if (page->next_chunk() != NULL) { | 1313 if (page->next_chunk() != NULL) { |
| 1249 DCHECK(page->prev_chunk() != NULL); | 1314 DCHECK(page->prev_chunk() != NULL); |
| 1250 page->Unlink(); | 1315 page->Unlink(); |
| 1251 } | 1316 } |
| 1252 | 1317 |
| 1253 AccountUncommitted(static_cast<intptr_t>(page->size())); | 1318 AccountUncommitted(static_cast<intptr_t>(page->size())); |
| 1254 heap()->QueueMemoryChunkForFree(page); | 1319 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); |
| 1255 | 1320 |
| 1256 DCHECK(Capacity() > 0); | 1321 DCHECK(Capacity() > 0); |
| 1257 accounting_stats_.ShrinkSpace(AreaSize()); | 1322 accounting_stats_.ShrinkSpace(AreaSize()); |
| 1258 } | 1323 } |
| 1259 | 1324 |
| 1260 #ifdef DEBUG | 1325 #ifdef DEBUG |
| 1261 void PagedSpace::Print() {} | 1326 void PagedSpace::Print() {} |
| 1262 #endif | 1327 #endif |
| 1263 | 1328 |
| 1264 #ifdef VERIFY_HEAP | 1329 #ifdef VERIFY_HEAP |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 } | 1773 } |
| 1709 committed_ = true; | 1774 committed_ = true; |
| 1710 return true; | 1775 return true; |
| 1711 } | 1776 } |
| 1712 | 1777 |
| 1713 | 1778 |
| 1714 bool SemiSpace::Uncommit() { | 1779 bool SemiSpace::Uncommit() { |
| 1715 DCHECK(is_committed()); | 1780 DCHECK(is_committed()); |
| 1716 NewSpacePageIterator it(this); | 1781 NewSpacePageIterator it(this); |
| 1717 while (it.has_next()) { | 1782 while (it.has_next()) { |
| 1718 heap()->memory_allocator()->Free<MemoryAllocator::kPooled>(it.next()); | 1783 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( |
| 1784 it.next()); |
| 1719 } | 1785 } |
| 1720 anchor()->set_next_page(anchor()); | 1786 anchor()->set_next_page(anchor()); |
| 1721 anchor()->set_prev_page(anchor()); | 1787 anchor()->set_prev_page(anchor()); |
| 1722 AccountUncommitted(current_capacity_); | 1788 AccountUncommitted(current_capacity_); |
| 1723 committed_ = false; | 1789 committed_ = false; |
| 1790 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); |
| 1724 return true; | 1791 return true; |
| 1725 } | 1792 } |
| 1726 | 1793 |
| 1727 | 1794 |
| 1728 size_t SemiSpace::CommittedPhysicalMemory() { | 1795 size_t SemiSpace::CommittedPhysicalMemory() { |
| 1729 if (!is_committed()) return 0; | 1796 if (!is_committed()) return 0; |
| 1730 size_t size = 0; | 1797 size_t size = 0; |
| 1731 NewSpacePageIterator it(this); | 1798 NewSpacePageIterator it(this); |
| 1732 while (it.has_next()) { | 1799 while (it.has_next()) { |
| 1733 size += it.next()->CommittedPhysicalMemory(); | 1800 size += it.next()->CommittedPhysicalMemory(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 const int delta = current_capacity_ - new_capacity; | 1858 const int delta = current_capacity_ - new_capacity; |
| 1792 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); | 1859 DCHECK(IsAligned(delta, base::OS::AllocateAlignment())); |
| 1793 int delta_pages = delta / NewSpacePage::kPageSize; | 1860 int delta_pages = delta / NewSpacePage::kPageSize; |
| 1794 NewSpacePage* new_last_page; | 1861 NewSpacePage* new_last_page; |
| 1795 NewSpacePage* last_page; | 1862 NewSpacePage* last_page; |
| 1796 while (delta_pages > 0) { | 1863 while (delta_pages > 0) { |
| 1797 last_page = anchor()->prev_page(); | 1864 last_page = anchor()->prev_page(); |
| 1798 new_last_page = last_page->prev_page(); | 1865 new_last_page = last_page->prev_page(); |
| 1799 new_last_page->set_next_page(anchor()); | 1866 new_last_page->set_next_page(anchor()); |
| 1800 anchor()->set_prev_page(new_last_page); | 1867 anchor()->set_prev_page(new_last_page); |
| 1801 heap()->memory_allocator()->Free<MemoryAllocator::kPooled>(last_page); | 1868 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( |
| 1869 last_page); |
| 1802 delta_pages--; | 1870 delta_pages--; |
| 1803 } | 1871 } |
| 1804 AccountUncommitted(static_cast<intptr_t>(delta)); | 1872 AccountUncommitted(static_cast<intptr_t>(delta)); |
| 1873 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); |
| 1805 } | 1874 } |
| 1806 current_capacity_ = new_capacity; | 1875 current_capacity_ = new_capacity; |
| 1807 return true; | 1876 return true; |
| 1808 } | 1877 } |
| 1809 | 1878 |
| 1810 void SemiSpace::FixPagesFlags(intptr_t flags, intptr_t mask) { | 1879 void SemiSpace::FixPagesFlags(intptr_t flags, intptr_t mask) { |
| 1811 anchor_.set_owner(this); | 1880 anchor_.set_owner(this); |
| 1812 // Fixup back-pointers to anchor. Address of anchor changes when we swap. | 1881 // Fixup back-pointers to anchor. Address of anchor changes when we swap. |
| 1813 anchor_.prev_page()->set_next_page(&anchor_); | 1882 anchor_.prev_page()->set_next_page(&anchor_); |
| 1814 anchor_.next_page()->set_prev_page(&anchor_); | 1883 anchor_.next_page()->set_prev_page(&anchor_); |
| (...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2887 | 2956 |
| 2888 void LargeObjectSpace::TearDown() { | 2957 void LargeObjectSpace::TearDown() { |
| 2889 while (first_page_ != NULL) { | 2958 while (first_page_ != NULL) { |
| 2890 LargePage* page = first_page_; | 2959 LargePage* page = first_page_; |
| 2891 first_page_ = first_page_->next_page(); | 2960 first_page_ = first_page_->next_page(); |
| 2892 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", page->address())); | 2961 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", page->address())); |
| 2893 | 2962 |
| 2894 ObjectSpace space = static_cast<ObjectSpace>(1 << identity()); | 2963 ObjectSpace space = static_cast<ObjectSpace>(1 << identity()); |
| 2895 heap()->memory_allocator()->PerformAllocationCallback( | 2964 heap()->memory_allocator()->PerformAllocationCallback( |
| 2896 space, kAllocationActionFree, page->size()); | 2965 space, kAllocationActionFree, page->size()); |
| 2897 heap()->memory_allocator()->Free(page); | 2966 heap()->memory_allocator()->Free<MemoryAllocator::kFull>(page); |
| 2898 } | 2967 } |
| 2899 SetUp(); | 2968 SetUp(); |
| 2900 } | 2969 } |
| 2901 | 2970 |
| 2902 | 2971 |
| 2903 AllocationResult LargeObjectSpace::AllocateRaw(int object_size, | 2972 AllocationResult LargeObjectSpace::AllocateRaw(int object_size, |
| 2904 Executability executable) { | 2973 Executability executable) { |
| 2905 // Check if we want to force a GC before growing the old space further. | 2974 // Check if we want to force a GC before growing the old space further. |
| 2906 // If so, fail the allocation. | 2975 // If so, fail the allocation. |
| 2907 if (!heap()->CanExpandOldGeneration(object_size)) { | 2976 if (!heap()->CanExpandOldGeneration(object_size)) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3030 // Use variable alignment to help pass length check (<= 80 characters) | 3099 // Use variable alignment to help pass length check (<= 80 characters) |
| 3031 // of single line in tools/presubmit.py. | 3100 // of single line in tools/presubmit.py. |
| 3032 const intptr_t alignment = MemoryChunk::kAlignment; | 3101 const intptr_t alignment = MemoryChunk::kAlignment; |
| 3033 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment; | 3102 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment; |
| 3034 uintptr_t limit = base + (page->size() - 1) / alignment; | 3103 uintptr_t limit = base + (page->size() - 1) / alignment; |
| 3035 for (uintptr_t key = base; key <= limit; key++) { | 3104 for (uintptr_t key = base; key <= limit; key++) { |
| 3036 chunk_map_.Remove(reinterpret_cast<void*>(key), | 3105 chunk_map_.Remove(reinterpret_cast<void*>(key), |
| 3037 static_cast<uint32_t>(key)); | 3106 static_cast<uint32_t>(key)); |
| 3038 } | 3107 } |
| 3039 | 3108 |
| 3040 heap()->QueueMemoryChunkForFree(page); | 3109 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); |
| 3041 } | 3110 } |
| 3042 } | 3111 } |
| 3043 } | 3112 } |
| 3044 | 3113 |
| 3045 | 3114 |
| 3046 bool LargeObjectSpace::Contains(HeapObject* object) { | 3115 bool LargeObjectSpace::Contains(HeapObject* object) { |
| 3047 Address address = object->address(); | 3116 Address address = object->address(); |
| 3048 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 3117 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
| 3049 | 3118 |
| 3050 bool owned = (chunk->owner() == this); | 3119 bool owned = (chunk->owner() == this); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3161 object->ShortPrint(); | 3230 object->ShortPrint(); |
| 3162 PrintF("\n"); | 3231 PrintF("\n"); |
| 3163 } | 3232 } |
| 3164 printf(" --------------------------------------\n"); | 3233 printf(" --------------------------------------\n"); |
| 3165 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3234 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3166 } | 3235 } |
| 3167 | 3236 |
| 3168 #endif // DEBUG | 3237 #endif // DEBUG |
| 3169 } // namespace internal | 3238 } // namespace internal |
| 3170 } // namespace v8 | 3239 } // namespace v8 |
| OLD | NEW |