Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(872)

Side by Side Diff: src/heap/spaces.cc

Issue 2106933003: Revert of [heap] Reland uncommit unused large object page memory. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/spaces.h ('k') | test/cctest/heap/test-heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 CodeRange* code_range = heap_->memory_allocator()->code_range(); 563 CodeRange* code_range = heap_->memory_allocator()->code_range();
564 DCHECK(code_range->valid() && IsFlagSet(IS_EXECUTABLE)); 564 DCHECK(code_range->valid() && IsFlagSet(IS_EXECUTABLE));
565 if (!code_range->UncommitRawMemory(start, length)) return false; 565 if (!code_range->UncommitRawMemory(start, length)) return false;
566 } 566 }
567 } 567 }
568 568
569 area_end_ = area_start_ + requested; 569 area_end_ = area_start_ + requested;
570 return true; 570 return true;
571 } 571 }
572 572
573 size_t MemoryChunk::CommittedPhysicalMemory() {
574 if (!base::VirtualMemory::HasLazyCommits() || owner()->identity() == LO_SPACE)
575 return size();
576 return high_water_mark_.Value();
577 }
578 573
579 void MemoryChunk::InsertAfter(MemoryChunk* other) { 574 void MemoryChunk::InsertAfter(MemoryChunk* other) {
580 MemoryChunk* other_next = other->next_chunk(); 575 MemoryChunk* other_next = other->next_chunk();
581 576
582 set_next_chunk(other_next); 577 set_next_chunk(other_next);
583 set_prev_chunk(other); 578 set_prev_chunk(other);
584 other_next->set_prev_chunk(this); 579 other_next->set_prev_chunk(this);
585 other->set_next_chunk(this); 580 other->set_next_chunk(this);
586 } 581 }
587 582
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end, 730 return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
736 executable, owner, &reservation); 731 executable, owner, &reservation);
737 } 732 }
738 733
739 734
740 void Page::ResetFreeListStatistics() { 735 void Page::ResetFreeListStatistics() {
741 wasted_memory_ = 0; 736 wasted_memory_ = 0;
742 available_in_free_list_ = 0; 737 available_in_free_list_ = 0;
743 } 738 }
744 739
745 void MemoryAllocator::PartialFreeMemory(MemoryChunk* chunk,
746 Address start_free) {
747 // We do not allow partial shrink for code.
748 DCHECK(chunk->executable() == NOT_EXECUTABLE);
749
750 intptr_t size;
751 base::VirtualMemory* reservation = chunk->reserved_memory();
752 DCHECK(reservation->IsReserved());
753 size = static_cast<intptr_t>(reservation->size());
754
755 size_t to_free_size = size - (start_free - chunk->address());
756
757 DCHECK(size_.Value() >= static_cast<intptr_t>(to_free_size));
758 size_.Increment(-static_cast<intptr_t>(to_free_size));
759 isolate_->counters()->memory_allocated()->Decrement(
760 static_cast<int>(to_free_size));
761 chunk->set_size(size - to_free_size);
762
763 reservation->ReleasePartial(start_free);
764 }
765
766 void MemoryAllocator::PreFreeMemory(MemoryChunk* chunk) { 740 void MemoryAllocator::PreFreeMemory(MemoryChunk* chunk) {
767 DCHECK(!chunk->IsFlagSet(MemoryChunk::PRE_FREED)); 741 DCHECK(!chunk->IsFlagSet(MemoryChunk::PRE_FREED));
768 LOG(isolate_, DeleteEvent("MemoryChunk", chunk)); 742 LOG(isolate_, DeleteEvent("MemoryChunk", chunk));
769 743
770 isolate_->heap()->RememberUnmappedPage(reinterpret_cast<Address>(chunk), 744 isolate_->heap()->RememberUnmappedPage(reinterpret_cast<Address>(chunk),
771 chunk->IsEvacuationCandidate()); 745 chunk->IsEvacuationCandidate());
772 746
773 intptr_t size; 747 intptr_t size;
774 base::VirtualMemory* reservation = chunk->reserved_memory(); 748 base::VirtualMemory* reservation = chunk->reserved_memory();
775 if (reservation->IsReserved()) { 749 if (reservation->IsReserved()) {
(...skipping 2151 matching lines...) Expand 10 before | Expand all | Expand 10 after
2927 #endif 2901 #endif
2928 } 2902 }
2929 2903
2930 // ----------------------------------------------------------------------------- 2904 // -----------------------------------------------------------------------------
2931 // MapSpace implementation 2905 // MapSpace implementation
2932 2906
2933 #ifdef VERIFY_HEAP 2907 #ifdef VERIFY_HEAP
2934 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); } 2908 void MapSpace::VerifyObject(HeapObject* object) { CHECK(object->IsMap()); }
2935 #endif 2909 #endif
2936 2910
2937 Address LargePage::GetAddressToShrink() {
2938 HeapObject* object = GetObject();
2939 if (executable() == EXECUTABLE) {
2940 return 0;
2941 }
2942 size_t used_size = RoundUp((object->address() - address()) + object->Size(),
2943 base::OS::CommitPageSize());
2944 if (used_size < CommittedPhysicalMemory()) {
2945 return address() + used_size;
2946 }
2947 return 0;
2948 }
2949
2950 void LargePage::ClearOutOfLiveRangeSlots(Address free_start) {
2951 if (old_to_new_slots() != nullptr) {
2952 old_to_new_slots()->RemoveRange(
2953 static_cast<int>(free_start - address()),
2954 static_cast<int>(free_start + size() - address()));
2955 }
2956 if (old_to_old_slots() != nullptr) {
2957 old_to_old_slots()->RemoveRange(
2958 static_cast<int>(free_start - address()),
2959 static_cast<int>(free_start + size() - address()));
2960 }
2961 }
2962 2911
2963 // ----------------------------------------------------------------------------- 2912 // -----------------------------------------------------------------------------
2964 // LargeObjectIterator 2913 // LargeObjectIterator
2965 2914
2966 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { 2915 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) {
2967 current_ = space->first_page_; 2916 current_ = space->first_page_;
2968 } 2917 }
2969 2918
2970 2919
2971 HeapObject* LargeObjectIterator::Next() { 2920 HeapObject* LargeObjectIterator::Next() {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3025 if (page == NULL) return AllocationResult::Retry(identity()); 2974 if (page == NULL) return AllocationResult::Retry(identity());
3026 DCHECK(page->area_size() >= object_size); 2975 DCHECK(page->area_size() >= object_size);
3027 2976
3028 size_ += static_cast<int>(page->size()); 2977 size_ += static_cast<int>(page->size());
3029 AccountCommitted(static_cast<intptr_t>(page->size())); 2978 AccountCommitted(static_cast<intptr_t>(page->size()));
3030 objects_size_ += object_size; 2979 objects_size_ += object_size;
3031 page_count_++; 2980 page_count_++;
3032 page->set_next_page(first_page_); 2981 page->set_next_page(first_page_);
3033 first_page_ = page; 2982 first_page_ = page;
3034 2983
3035 InsertChunkMapEntries(page); 2984 // Register all MemoryChunk::kAlignment-aligned chunks covered by
2985 // this large page in the chunk map.
2986 uintptr_t base = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment;
2987 uintptr_t limit = base + (page->size() - 1) / MemoryChunk::kAlignment;
2988 for (uintptr_t key = base; key <= limit; key++) {
2989 base::HashMap::Entry* entry = chunk_map_.LookupOrInsert(
2990 reinterpret_cast<void*>(key), static_cast<uint32_t>(key));
2991 DCHECK(entry != NULL);
2992 entry->value = page;
2993 }
3036 2994
3037 HeapObject* object = page->GetObject(); 2995 HeapObject* object = page->GetObject();
3038 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size); 2996 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size);
3039 2997
3040 if (Heap::ShouldZapGarbage()) { 2998 if (Heap::ShouldZapGarbage()) {
3041 // Make the object consistent so the heap can be verified in OldSpaceStep. 2999 // Make the object consistent so the heap can be verified in OldSpaceStep.
3042 // We only need to do this in debug builds or if verify_heap is on. 3000 // We only need to do this in debug builds or if verify_heap is on.
3043 reinterpret_cast<Object**>(object->address())[0] = 3001 reinterpret_cast<Object**>(object->address())[0] =
3044 heap()->fixed_array_map(); 3002 heap()->fixed_array_map();
3045 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); 3003 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3091 HeapObject* object = current->GetObject(); 3049 HeapObject* object = current->GetObject();
3092 MarkBit mark_bit = Marking::MarkBitFrom(object); 3050 MarkBit mark_bit = Marking::MarkBitFrom(object);
3093 DCHECK(Marking::IsBlack(mark_bit)); 3051 DCHECK(Marking::IsBlack(mark_bit));
3094 Marking::BlackToWhite(mark_bit); 3052 Marking::BlackToWhite(mark_bit);
3095 Page::FromAddress(object->address())->ResetProgressBar(); 3053 Page::FromAddress(object->address())->ResetProgressBar();
3096 Page::FromAddress(object->address())->ResetLiveBytes(); 3054 Page::FromAddress(object->address())->ResetLiveBytes();
3097 current = current->next_page(); 3055 current = current->next_page();
3098 } 3056 }
3099 } 3057 }
3100 3058
3101 void LargeObjectSpace::InsertChunkMapEntries(LargePage* page) {
3102 // Register all MemoryChunk::kAlignment-aligned chunks covered by
3103 // this large page in the chunk map.
3104 uintptr_t start = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment;
3105 uintptr_t limit = start + (page->size() - 1) / MemoryChunk::kAlignment;
3106 for (uintptr_t key = start; key <= limit; key++) {
3107 base::HashMap::Entry* entry = chunk_map_.InsertNew(
3108 reinterpret_cast<void*>(key), static_cast<uint32_t>(key));
3109 DCHECK(entry != NULL);
3110 entry->value = page;
3111 }
3112 }
3113
3114 void LargeObjectSpace::RemoveChunkMapEntries(LargePage* page) {
3115 RemoveChunkMapEntries(page, page->address());
3116 }
3117
3118 void LargeObjectSpace::RemoveChunkMapEntries(LargePage* page,
3119 Address free_start) {
3120 uintptr_t start = RoundUp(reinterpret_cast<uintptr_t>(free_start),
3121 MemoryChunk::kAlignment) /
3122 MemoryChunk::kAlignment;
3123 uintptr_t limit = start + (page->size() - 1) / MemoryChunk::kAlignment;
3124 for (uintptr_t key = start; key <= limit; key++) {
3125 chunk_map_.Remove(reinterpret_cast<void*>(key), static_cast<uint32_t>(key));
3126 }
3127 }
3128 3059
3129 void LargeObjectSpace::FreeUnmarkedObjects() { 3060 void LargeObjectSpace::FreeUnmarkedObjects() {
3130 LargePage* previous = NULL; 3061 LargePage* previous = NULL;
3131 LargePage* current = first_page_; 3062 LargePage* current = first_page_;
3132 while (current != NULL) { 3063 while (current != NULL) {
3133 HeapObject* object = current->GetObject(); 3064 HeapObject* object = current->GetObject();
3134 MarkBit mark_bit = Marking::MarkBitFrom(object); 3065 MarkBit mark_bit = Marking::MarkBitFrom(object);
3135 DCHECK(!Marking::IsGrey(mark_bit)); 3066 DCHECK(!Marking::IsGrey(mark_bit));
3136 if (Marking::IsBlack(mark_bit)) { 3067 if (Marking::IsBlack(mark_bit)) {
3137 Address free_start;
3138 if ((free_start = current->GetAddressToShrink()) != 0) {
3139 // TODO(hpayer): Perform partial free concurrently.
3140 current->ClearOutOfLiveRangeSlots(free_start);
3141 RemoveChunkMapEntries(current, free_start);
3142 heap()->memory_allocator()->PartialFreeMemory(current, free_start);
3143 }
3144 previous = current; 3068 previous = current;
3145 current = current->next_page(); 3069 current = current->next_page();
3146 } else { 3070 } else {
3147 LargePage* page = current; 3071 LargePage* page = current;
3148 // Cut the chunk out from the chunk list. 3072 // Cut the chunk out from the chunk list.
3149 current = current->next_page(); 3073 current = current->next_page();
3150 if (previous == NULL) { 3074 if (previous == NULL) {
3151 first_page_ = current; 3075 first_page_ = current;
3152 } else { 3076 } else {
3153 previous->set_next_page(current); 3077 previous->set_next_page(current);
3154 } 3078 }
3155 3079
3156 // Free the chunk. 3080 // Free the chunk.
3157 size_ -= static_cast<int>(page->size()); 3081 size_ -= static_cast<int>(page->size());
3158 AccountUncommitted(static_cast<intptr_t>(page->size())); 3082 AccountUncommitted(static_cast<intptr_t>(page->size()));
3159 objects_size_ -= object->Size(); 3083 objects_size_ -= object->Size();
3160 page_count_--; 3084 page_count_--;
3161 3085
3162 RemoveChunkMapEntries(page); 3086 // Remove entries belonging to this page.
3087 // Use variable alignment to help pass length check (<= 80 characters)
3088 // of single line in tools/presubmit.py.
3089 const intptr_t alignment = MemoryChunk::kAlignment;
3090 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment;
3091 uintptr_t limit = base + (page->size() - 1) / alignment;
3092 for (uintptr_t key = base; key <= limit; key++) {
3093 chunk_map_.Remove(reinterpret_cast<void*>(key),
3094 static_cast<uint32_t>(key));
3095 }
3096
3163 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); 3097 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
3164 } 3098 }
3165 } 3099 }
3166 } 3100 }
3167 3101
3168 3102
3169 bool LargeObjectSpace::Contains(HeapObject* object) { 3103 bool LargeObjectSpace::Contains(HeapObject* object) {
3170 Address address = object->address(); 3104 Address address = object->address();
3171 MemoryChunk* chunk = MemoryChunk::FromAddress(address); 3105 MemoryChunk* chunk = MemoryChunk::FromAddress(address);
3172 3106
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 object->ShortPrint(); 3220 object->ShortPrint();
3287 PrintF("\n"); 3221 PrintF("\n");
3288 } 3222 }
3289 printf(" --------------------------------------\n"); 3223 printf(" --------------------------------------\n");
3290 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3224 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3291 } 3225 }
3292 3226
3293 #endif // DEBUG 3227 #endif // DEBUG
3294 } // namespace internal 3228 } // namespace internal
3295 } // namespace v8 3229 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/spaces.h ('k') | test/cctest/heap/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698