| 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 2979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2990 if (page == NULL) return AllocationResult::Retry(identity()); | 2990 if (page == NULL) return AllocationResult::Retry(identity()); |
| 2991 DCHECK(page->area_size() >= object_size); | 2991 DCHECK(page->area_size() >= object_size); |
| 2992 | 2992 |
| 2993 size_ += static_cast<int>(page->size()); | 2993 size_ += static_cast<int>(page->size()); |
| 2994 AccountCommitted(static_cast<intptr_t>(page->size())); | 2994 AccountCommitted(static_cast<intptr_t>(page->size())); |
| 2995 objects_size_ += object_size; | 2995 objects_size_ += object_size; |
| 2996 page_count_++; | 2996 page_count_++; |
| 2997 page->set_next_page(first_page_); | 2997 page->set_next_page(first_page_); |
| 2998 first_page_ = page; | 2998 first_page_ = page; |
| 2999 | 2999 |
| 3000 // Register all MemoryChunk::kAlignment-aligned chunks covered by | 3000 InsertChunkMapEntries(page); |
| 3001 // this large page in the chunk map. | |
| 3002 uintptr_t base = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment; | |
| 3003 uintptr_t limit = base + (page->size() - 1) / MemoryChunk::kAlignment; | |
| 3004 for (uintptr_t key = base; key <= limit; key++) { | |
| 3005 HashMap::Entry* entry = chunk_map_.LookupOrInsert( | |
| 3006 reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); | |
| 3007 DCHECK(entry != NULL); | |
| 3008 entry->value = page; | |
| 3009 } | |
| 3010 | 3001 |
| 3011 HeapObject* object = page->GetObject(); | 3002 HeapObject* object = page->GetObject(); |
| 3012 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size); | 3003 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), object_size); |
| 3013 | 3004 |
| 3014 if (Heap::ShouldZapGarbage()) { | 3005 if (Heap::ShouldZapGarbage()) { |
| 3015 // Make the object consistent so the heap can be verified in OldSpaceStep. | 3006 // Make the object consistent so the heap can be verified in OldSpaceStep. |
| 3016 // We only need to do this in debug builds or if verify_heap is on. | 3007 // We only need to do this in debug builds or if verify_heap is on. |
| 3017 reinterpret_cast<Object**>(object->address())[0] = | 3008 reinterpret_cast<Object**>(object->address())[0] = |
| 3018 heap()->fixed_array_map(); | 3009 heap()->fixed_array_map(); |
| 3019 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); | 3010 reinterpret_cast<Object**>(object->address())[1] = Smi::FromInt(0); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3065 HeapObject* object = current->GetObject(); | 3056 HeapObject* object = current->GetObject(); |
| 3066 MarkBit mark_bit = Marking::MarkBitFrom(object); | 3057 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 3067 DCHECK(Marking::IsBlack(mark_bit)); | 3058 DCHECK(Marking::IsBlack(mark_bit)); |
| 3068 Marking::BlackToWhite(mark_bit); | 3059 Marking::BlackToWhite(mark_bit); |
| 3069 Page::FromAddress(object->address())->ResetProgressBar(); | 3060 Page::FromAddress(object->address())->ResetProgressBar(); |
| 3070 Page::FromAddress(object->address())->ResetLiveBytes(); | 3061 Page::FromAddress(object->address())->ResetLiveBytes(); |
| 3071 current = current->next_page(); | 3062 current = current->next_page(); |
| 3072 } | 3063 } |
| 3073 } | 3064 } |
| 3074 | 3065 |
| 3066 void LargeObjectSpace::InsertChunkMapEntries(LargePage* page) { |
| 3067 // Register all MemoryChunk::kAlignment-aligned chunks covered by |
| 3068 // this large page in the chunk map. |
| 3069 uintptr_t start = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment; |
| 3070 uintptr_t limit = start + (page->size() - 1) / MemoryChunk::kAlignment; |
| 3071 for (uintptr_t key = start; key <= limit; key++) { |
| 3072 HashMap::Entry* entry = chunk_map_.InsertNew(reinterpret_cast<void*>(key), |
| 3073 static_cast<uint32_t>(key)); |
| 3074 DCHECK(entry != NULL); |
| 3075 entry->value = page; |
| 3076 } |
| 3077 } |
| 3078 |
| 3079 void LargeObjectSpace::RemoveChunkMapEntries(LargePage* page) { |
| 3080 RemoveChunkMapEntries(page, page->address()); |
| 3081 } |
| 3082 |
| 3083 void LargeObjectSpace::RemoveChunkMapEntries(LargePage* page, |
| 3084 Address free_start) { |
| 3085 uintptr_t start = RoundUp(reinterpret_cast<uintptr_t>(free_start), |
| 3086 MemoryChunk::kAlignment) / |
| 3087 MemoryChunk::kAlignment; |
| 3088 uintptr_t limit = start + (page->size() - 1) / MemoryChunk::kAlignment; |
| 3089 for (uintptr_t key = start; key <= limit; key++) { |
| 3090 chunk_map_.Remove(reinterpret_cast<void*>(key), static_cast<uint32_t>(key)); |
| 3091 } |
| 3092 } |
| 3093 |
| 3075 void LargeObjectSpace::FreeUnmarkedObjects() { | 3094 void LargeObjectSpace::FreeUnmarkedObjects() { |
| 3076 LargePage* previous = NULL; | 3095 LargePage* previous = NULL; |
| 3077 LargePage* current = first_page_; | 3096 LargePage* current = first_page_; |
| 3078 while (current != NULL) { | 3097 while (current != NULL) { |
| 3079 HeapObject* object = current->GetObject(); | 3098 HeapObject* object = current->GetObject(); |
| 3080 MarkBit mark_bit = Marking::MarkBitFrom(object); | 3099 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 3081 DCHECK(!Marking::IsGrey(mark_bit)); | 3100 DCHECK(!Marking::IsGrey(mark_bit)); |
| 3082 if (Marking::IsBlack(mark_bit)) { | 3101 if (Marking::IsBlack(mark_bit)) { |
| 3083 Address free_start; | 3102 Address free_start; |
| 3084 if ((free_start = current->GetAddressToShrink()) != 0) { | 3103 if ((free_start = current->GetAddressToShrink()) != 0) { |
| 3085 // TODO(hpayer): Perform partial free concurrently. | 3104 // TODO(hpayer): Perform partial free concurrently. |
| 3086 heap()->memory_allocator()->PartialFreeMemory(current, free_start); | 3105 heap()->memory_allocator()->PartialFreeMemory(current, free_start); |
| 3106 RemoveChunkMapEntries(current, free_start); |
| 3087 } | 3107 } |
| 3088 previous = current; | 3108 previous = current; |
| 3089 current = current->next_page(); | 3109 current = current->next_page(); |
| 3090 } else { | 3110 } else { |
| 3091 LargePage* page = current; | 3111 LargePage* page = current; |
| 3092 // Cut the chunk out from the chunk list. | 3112 // Cut the chunk out from the chunk list. |
| 3093 current = current->next_page(); | 3113 current = current->next_page(); |
| 3094 if (previous == NULL) { | 3114 if (previous == NULL) { |
| 3095 first_page_ = current; | 3115 first_page_ = current; |
| 3096 } else { | 3116 } else { |
| 3097 previous->set_next_page(current); | 3117 previous->set_next_page(current); |
| 3098 } | 3118 } |
| 3099 | 3119 |
| 3100 // Free the chunk. | 3120 // Free the chunk. |
| 3101 size_ -= static_cast<int>(page->size()); | 3121 size_ -= static_cast<int>(page->size()); |
| 3102 AccountUncommitted(static_cast<intptr_t>(page->size())); | 3122 AccountUncommitted(static_cast<intptr_t>(page->size())); |
| 3103 objects_size_ -= object->Size(); | 3123 objects_size_ -= object->Size(); |
| 3104 page_count_--; | 3124 page_count_--; |
| 3105 | 3125 |
| 3106 // Remove entries belonging to this page. | 3126 RemoveChunkMapEntries(page); |
| 3107 // Use variable alignment to help pass length check (<= 80 characters) | |
| 3108 // of single line in tools/presubmit.py. | |
| 3109 const intptr_t alignment = MemoryChunk::kAlignment; | |
| 3110 uintptr_t base = reinterpret_cast<uintptr_t>(page) / alignment; | |
| 3111 uintptr_t limit = base + (page->size() - 1) / alignment; | |
| 3112 for (uintptr_t key = base; key <= limit; key++) { | |
| 3113 chunk_map_.Remove(reinterpret_cast<void*>(key), | |
| 3114 static_cast<uint32_t>(key)); | |
| 3115 } | |
| 3116 | |
| 3117 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); | 3127 heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page); |
| 3118 } | 3128 } |
| 3119 } | 3129 } |
| 3120 } | 3130 } |
| 3121 | 3131 |
| 3122 | 3132 |
| 3123 bool LargeObjectSpace::Contains(HeapObject* object) { | 3133 bool LargeObjectSpace::Contains(HeapObject* object) { |
| 3124 Address address = object->address(); | 3134 Address address = object->address(); |
| 3125 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 3135 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
| 3126 | 3136 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3240 object->ShortPrint(); | 3250 object->ShortPrint(); |
| 3241 PrintF("\n"); | 3251 PrintF("\n"); |
| 3242 } | 3252 } |
| 3243 printf(" --------------------------------------\n"); | 3253 printf(" --------------------------------------\n"); |
| 3244 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3254 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3245 } | 3255 } |
| 3246 | 3256 |
| 3247 #endif // DEBUG | 3257 #endif // DEBUG |
| 3248 } // namespace internal | 3258 } // namespace internal |
| 3249 } // namespace v8 | 3259 } // namespace v8 |
| OLD | NEW |