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

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

Issue 742733002: Reserve code range block for evacuation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix test/cctest/test-spaces.cc Created 6 years, 1 month 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/test-spaces.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/v8.h" 5 #include "src/v8.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.h" 9 #include "src/full-codegen.h"
10 #include "src/heap/mark-compact.h" 10 #include "src/heap/mark-compact.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 86
87 // ----------------------------------------------------------------------------- 87 // -----------------------------------------------------------------------------
88 // CodeRange 88 // CodeRange
89 89
90 90
91 CodeRange::CodeRange(Isolate* isolate) 91 CodeRange::CodeRange(Isolate* isolate)
92 : isolate_(isolate), 92 : isolate_(isolate),
93 code_range_(NULL), 93 code_range_(NULL),
94 free_list_(0), 94 free_list_(0),
95 allocation_list_(0), 95 allocation_list_(0),
96 current_allocation_block_index_(0) {} 96 current_allocation_block_index_(0),
97 emergency_block_() {}
97 98
98 99
99 bool CodeRange::SetUp(size_t requested) { 100 bool CodeRange::SetUp(size_t requested) {
100 DCHECK(code_range_ == NULL); 101 DCHECK(code_range_ == NULL);
101 102
102 if (requested == 0) { 103 if (requested == 0) {
103 // When a target requires the code range feature, we put all code objects 104 // When a target requires the code range feature, we put all code objects
104 // in a kMaximalCodeRangeSize range of virtual address space, so that 105 // in a kMaximalCodeRangeSize range of virtual address space, so that
105 // they can call each other with near calls. 106 // they can call each other with near calls.
106 if (kRequiresCodeRange) { 107 if (kRequiresCodeRange) {
(...skipping 30 matching lines...) Expand all
137 return false; 138 return false;
138 } 139 }
139 base += kReservedCodeRangePages * base::OS::CommitPageSize(); 140 base += kReservedCodeRangePages * base::OS::CommitPageSize();
140 } 141 }
141 Address aligned_base = RoundUp(base, MemoryChunk::kAlignment); 142 Address aligned_base = RoundUp(base, MemoryChunk::kAlignment);
142 size_t size = code_range_->size() - (aligned_base - base); 143 size_t size = code_range_->size() - (aligned_base - base);
143 allocation_list_.Add(FreeBlock(aligned_base, size)); 144 allocation_list_.Add(FreeBlock(aligned_base, size));
144 current_allocation_block_index_ = 0; 145 current_allocation_block_index_ = 0;
145 146
146 LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested)); 147 LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested));
148 ReserveEmergencyBlock();
147 return true; 149 return true;
148 } 150 }
149 151
150 152
151 int CodeRange::CompareFreeBlockAddress(const FreeBlock* left, 153 int CodeRange::CompareFreeBlockAddress(const FreeBlock* left,
152 const FreeBlock* right) { 154 const FreeBlock* right) {
153 // The entire point of CodeRange is that the difference between two 155 // The entire point of CodeRange is that the difference between two
154 // addresses in the range can be represented as a signed 32-bit int, 156 // addresses in the range can be represented as a signed 32-bit int,
155 // so the cast is semantically correct. 157 // so the cast is semantically correct.
156 return static_cast<int>(left->start - right->start); 158 return static_cast<int>(left->start - right->start);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 current_allocation_block_index_ = 0; 197 current_allocation_block_index_ = 0;
196 // Code range is full or too fragmented. 198 // Code range is full or too fragmented.
197 return false; 199 return false;
198 } 200 }
199 201
200 202
201 Address CodeRange::AllocateRawMemory(const size_t requested_size, 203 Address CodeRange::AllocateRawMemory(const size_t requested_size,
202 const size_t commit_size, 204 const size_t commit_size,
203 size_t* allocated) { 205 size_t* allocated) {
204 DCHECK(commit_size <= requested_size); 206 DCHECK(commit_size <= requested_size);
205 DCHECK(allocation_list_.length() == 0 || 207 FreeBlock current;
206 current_allocation_block_index_ < allocation_list_.length()); 208 if (!ReserveBlock(requested_size, &current)) {
207 if (allocation_list_.length() == 0 || 209 *allocated = 0;
208 requested_size > allocation_list_[current_allocation_block_index_].size) { 210 return NULL;
209 // Find an allocation block large enough.
210 if (!GetNextAllocationBlock(requested_size)) return NULL;
211 } 211 }
212 // Commit the requested memory at the start of the current allocation block. 212 *allocated = current.size;
213 size_t aligned_requested = RoundUp(requested_size, MemoryChunk::kAlignment);
214 FreeBlock current = allocation_list_[current_allocation_block_index_];
215 if (aligned_requested >= (current.size - Page::kPageSize)) {
216 // Don't leave a small free block, useless for a large object or chunk.
217 *allocated = current.size;
218 } else {
219 *allocated = aligned_requested;
220 }
221 DCHECK(*allocated <= current.size); 213 DCHECK(*allocated <= current.size);
222 DCHECK(IsAddressAligned(current.start, MemoryChunk::kAlignment)); 214 DCHECK(IsAddressAligned(current.start, MemoryChunk::kAlignment));
223 if (!isolate_->memory_allocator()->CommitExecutableMemory( 215 if (!isolate_->memory_allocator()->CommitExecutableMemory(
224 code_range_, current.start, commit_size, *allocated)) { 216 code_range_, current.start, commit_size, *allocated)) {
225 *allocated = 0; 217 *allocated = 0;
218 ReleaseBlock(&current);
226 return NULL; 219 return NULL;
227 } 220 }
228 allocation_list_[current_allocation_block_index_].start += *allocated;
229 allocation_list_[current_allocation_block_index_].size -= *allocated;
230 if (*allocated == current.size) {
231 // This block is used up, get the next one.
232 GetNextAllocationBlock(0);
233 }
234 return current.start; 221 return current.start;
235 } 222 }
236 223
237 224
238 bool CodeRange::CommitRawMemory(Address start, size_t length) { 225 bool CodeRange::CommitRawMemory(Address start, size_t length) {
239 return isolate_->memory_allocator()->CommitMemory(start, length, EXECUTABLE); 226 return isolate_->memory_allocator()->CommitMemory(start, length, EXECUTABLE);
240 } 227 }
241 228
242 229
243 bool CodeRange::UncommitRawMemory(Address start, size_t length) { 230 bool CodeRange::UncommitRawMemory(Address start, size_t length) {
244 return code_range_->Uncommit(start, length); 231 return code_range_->Uncommit(start, length);
245 } 232 }
246 233
247 234
248 void CodeRange::FreeRawMemory(Address address, size_t length) { 235 void CodeRange::FreeRawMemory(Address address, size_t length) {
249 DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment)); 236 DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment));
250 free_list_.Add(FreeBlock(address, length)); 237 free_list_.Add(FreeBlock(address, length));
251 code_range_->Uncommit(address, length); 238 code_range_->Uncommit(address, length);
252 } 239 }
253 240
254 241
255 void CodeRange::TearDown() { 242 void CodeRange::TearDown() {
256 delete code_range_; // Frees all memory in the virtual memory range. 243 delete code_range_; // Frees all memory in the virtual memory range.
257 code_range_ = NULL; 244 code_range_ = NULL;
258 free_list_.Free(); 245 free_list_.Free();
259 allocation_list_.Free(); 246 allocation_list_.Free();
260 } 247 }
261 248
262 249
250 bool CodeRange::ReserveBlock(const size_t requested_size, FreeBlock* block) {
251 DCHECK(allocation_list_.length() == 0 ||
252 current_allocation_block_index_ < allocation_list_.length());
253 if (allocation_list_.length() == 0 ||
254 requested_size > allocation_list_[current_allocation_block_index_].size) {
255 // Find an allocation block large enough.
256 if (!GetNextAllocationBlock(requested_size)) return false;
257 }
258 // Commit the requested memory at the start of the current allocation block.
259 size_t aligned_requested = RoundUp(requested_size, MemoryChunk::kAlignment);
260 *block = allocation_list_[current_allocation_block_index_];
261 // Don't leave a small free block, useless for a large object or chunk.
262 if (aligned_requested < (block->size - Page::kPageSize)) {
263 block->size = aligned_requested;
264 }
265 DCHECK(IsAddressAligned(block->start, MemoryChunk::kAlignment));
266 allocation_list_[current_allocation_block_index_].start += block->size;
267 allocation_list_[current_allocation_block_index_].size -= block->size;
268 return true;
269 }
270
271
272 void CodeRange::ReleaseBlock(const FreeBlock* block) { free_list_.Add(*block); }
273
274
275 void CodeRange::ReserveEmergencyBlock() {
276 const size_t requested_size = MemoryAllocator::CodePageAreaSize();
277 if (emergency_block_.size == 0) {
278 ReserveBlock(requested_size, &emergency_block_);
279 } else {
280 DCHECK(emergency_block_.size >= requested_size);
281 }
282 }
283
284
285 void CodeRange::ReleaseEmergencyBlock() {
286 if (emergency_block_.size != 0) {
287 ReleaseBlock(&emergency_block_);
288 emergency_block_.size = 0;
289 }
290 }
291
292
263 // ----------------------------------------------------------------------------- 293 // -----------------------------------------------------------------------------
264 // MemoryAllocator 294 // MemoryAllocator
265 // 295 //
266 296
267 MemoryAllocator::MemoryAllocator(Isolate* isolate) 297 MemoryAllocator::MemoryAllocator(Isolate* isolate)
268 : isolate_(isolate), 298 : isolate_(isolate),
269 capacity_(0), 299 capacity_(0),
270 capacity_executable_(0), 300 capacity_executable_(0),
271 size_(0), 301 size_(0),
272 size_executable_(0), 302 size_executable_(0),
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 } else { 1129 } else {
1100 heap()->QueueMemoryChunkForFree(page); 1130 heap()->QueueMemoryChunkForFree(page);
1101 } 1131 }
1102 1132
1103 DCHECK(Capacity() > 0); 1133 DCHECK(Capacity() > 0);
1104 accounting_stats_.ShrinkSpace(AreaSize()); 1134 accounting_stats_.ShrinkSpace(AreaSize());
1105 } 1135 }
1106 1136
1107 1137
1108 void PagedSpace::CreateEmergencyMemory() { 1138 void PagedSpace::CreateEmergencyMemory() {
1139 if (identity() == CODE_SPACE) {
1140 // Make the emergency block available to the allocator.
1141 CodeRange* code_range = heap()->isolate()->code_range();
1142 if (code_range != NULL && code_range->valid()) {
1143 code_range->ReleaseEmergencyBlock();
1144 }
1145 DCHECK(MemoryAllocator::CodePageAreaSize() == AreaSize());
1146 }
1109 emergency_memory_ = heap()->isolate()->memory_allocator()->AllocateChunk( 1147 emergency_memory_ = heap()->isolate()->memory_allocator()->AllocateChunk(
1110 AreaSize(), AreaSize(), executable(), this); 1148 AreaSize(), AreaSize(), executable(), this);
1111 } 1149 }
1112 1150
1113 1151
1114 void PagedSpace::FreeEmergencyMemory() { 1152 void PagedSpace::FreeEmergencyMemory() {
1115 Page* page = static_cast<Page*>(emergency_memory_); 1153 Page* page = static_cast<Page*>(emergency_memory_);
1116 DCHECK(page->LiveBytes() == 0); 1154 DCHECK(page->LiveBytes() == 0);
1117 DCHECK(AreaSize() == page->area_size()); 1155 DCHECK(AreaSize() == page->area_size());
1118 DCHECK(!free_list_.ContainsPageFreeListItems(page)); 1156 DCHECK(!free_list_.ContainsPageFreeListItems(page));
(...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after
3166 object->ShortPrint(); 3204 object->ShortPrint();
3167 PrintF("\n"); 3205 PrintF("\n");
3168 } 3206 }
3169 printf(" --------------------------------------\n"); 3207 printf(" --------------------------------------\n");
3170 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3208 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3171 } 3209 }
3172 3210
3173 #endif // DEBUG 3211 #endif // DEBUG
3174 } 3212 }
3175 } // namespace v8::internal 3213 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap/spaces.h ('k') | test/cctest/test-spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698