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

Side by Side Diff: src/spaces.cc

Issue 435003: Patch for allowing several V8 instances in process:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years 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 | Annotate | Revision Log
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 #endif 133 #endif
134 stop_page_ = space->last_page_; 134 stop_page_ = space->last_page_;
135 break; 135 break;
136 } 136 }
137 } 137 }
138 138
139 139
140 // ----------------------------------------------------------------------------- 140 // -----------------------------------------------------------------------------
141 // Page 141 // Page
142 142
143 #ifdef DEBUG
144 Page::RSetState Page::rset_state_ = Page::IN_USE;
145 #endif
146
147 // ----------------------------------------------------------------------------- 143 // -----------------------------------------------------------------------------
148 // CodeRange 144 // CodeRange
149 145
150 List<CodeRange::FreeBlock> CodeRange::free_list_(0); 146 CodeRangeData::CodeRangeData()
151 List<CodeRange::FreeBlock> CodeRange::allocation_list_(0); 147 :free_list_(0), allocation_list_(0), current_allocation_block_index_(0),
152 int CodeRange::current_allocation_block_index_ = 0; 148 code_range_(NULL) {
153 VirtualMemory* CodeRange::code_range_ = NULL; 149 }
154
155 150
156 bool CodeRange::Setup(const size_t requested) { 151 bool CodeRange::Setup(const size_t requested) {
157 ASSERT(code_range_ == NULL); 152 CodeRangeData& data = v8_context()->code_range_data_;
153 ASSERT(data.code_range_ == NULL);
158 154
159 code_range_ = new VirtualMemory(requested); 155 data.code_range_ = new VirtualMemory(requested);
160 CHECK(code_range_ != NULL); 156 CHECK(data.code_range_ != NULL);
161 if (!code_range_->IsReserved()) { 157 if (!data.code_range_->IsReserved()) {
162 delete code_range_; 158 delete data.code_range_;
163 code_range_ = NULL; 159 data.code_range_ = NULL;
164 return false; 160 return false;
165 } 161 }
166 162
167 // We are sure that we have mapped a block of requested addresses. 163 // We are sure that we have mapped a block of requested addresses.
168 ASSERT(code_range_->size() == requested); 164 ASSERT(data.code_range_->size() == requested);
169 LOG(NewEvent("CodeRange", code_range_->address(), requested)); 165 LOG(NewEvent("CodeRange", data.code_range_->address(), requested));
170 allocation_list_.Add(FreeBlock(code_range_->address(), code_range_->size())); 166 data.allocation_list_.Add(
171 current_allocation_block_index_ = 0; 167 CodeRangeData::FreeBlock(
168 data.code_range_->address(),
169 data.code_range_->size()));
170 data.current_allocation_block_index_ = 0;
172 return true; 171 return true;
173 } 172 }
174 173
175 174
176 int CodeRange::CompareFreeBlockAddress(const FreeBlock* left, 175 int CodeRange::CompareFreeBlockAddress(const CodeRangeData::FreeBlock* left,
177 const FreeBlock* right) { 176 const CodeRangeData::FreeBlock* right) {
178 // The entire point of CodeRange is that the difference between two 177 // The entire point of CodeRange is that the difference between two
179 // addresses in the range can be represented as a signed 32-bit int, 178 // addresses in the range can be represented as a signed 32-bit int,
180 // so the cast is semantically correct. 179 // so the cast is semantically correct.
181 return static_cast<int>(left->start - right->start); 180 return static_cast<int>(left->start - right->start);
182 } 181 }
183 182
184 183
185 void CodeRange::GetNextAllocationBlock(size_t requested) { 184 void CodeRange::GetNextAllocationBlock(size_t requested) {
186 for (current_allocation_block_index_++; 185 CodeRangeData& data = v8_context()->code_range_data_;
187 current_allocation_block_index_ < allocation_list_.length(); 186 for (data.current_allocation_block_index_++;
188 current_allocation_block_index_++) { 187 data.current_allocation_block_index_ < data.allocation_list_.length();
189 if (requested <= allocation_list_[current_allocation_block_index_].size) { 188 data.current_allocation_block_index_++) {
189 if (requested <=
190 data.allocation_list_[data.current_allocation_block_index_].size) {
190 return; // Found a large enough allocation block. 191 return; // Found a large enough allocation block.
191 } 192 }
192 } 193 }
193 194
194 // Sort and merge the free blocks on the free list and the allocation list. 195 // Sort and merge the free blocks on the free list and the allocation list.
195 free_list_.AddAll(allocation_list_); 196 data.free_list_.AddAll(data.allocation_list_);
196 allocation_list_.Clear(); 197 data.allocation_list_.Clear();
197 free_list_.Sort(&CompareFreeBlockAddress); 198 data.free_list_.Sort(&CompareFreeBlockAddress);
198 for (int i = 0; i < free_list_.length();) { 199 for (int i = 0; i < data.free_list_.length();) {
199 FreeBlock merged = free_list_[i]; 200 CodeRangeData::FreeBlock merged = data.free_list_[i];
200 i++; 201 i++;
201 // Add adjacent free blocks to the current merged block. 202 // Add adjacent free blocks to the current merged block.
202 while (i < free_list_.length() && 203 while (i < data.free_list_.length() &&
203 free_list_[i].start == merged.start + merged.size) { 204 data.free_list_[i].start == merged.start + merged.size) {
204 merged.size += free_list_[i].size; 205 merged.size += data.free_list_[i].size;
205 i++; 206 i++;
206 } 207 }
207 if (merged.size > 0) { 208 if (merged.size > 0) {
208 allocation_list_.Add(merged); 209 data.allocation_list_.Add(merged);
209 } 210 }
210 } 211 }
211 free_list_.Clear(); 212 data.free_list_.Clear();
212 213
213 for (current_allocation_block_index_ = 0; 214 for (data.current_allocation_block_index_ = 0;
214 current_allocation_block_index_ < allocation_list_.length(); 215 data.current_allocation_block_index_ < data.allocation_list_.length();
215 current_allocation_block_index_++) { 216 data.current_allocation_block_index_++) {
216 if (requested <= allocation_list_[current_allocation_block_index_].size) { 217 if (requested <=
218 data.allocation_list_[data.current_allocation_block_index_].size) {
217 return; // Found a large enough allocation block. 219 return; // Found a large enough allocation block.
218 } 220 }
219 } 221 }
220 222
221 // Code range is full or too fragmented. 223 // Code range is full or too fragmented.
222 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock"); 224 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock");
223 } 225 }
224 226
225 227
226 228
227 void* CodeRange::AllocateRawMemory(const size_t requested, size_t* allocated) { 229 void* CodeRange::AllocateRawMemory(const size_t requested, size_t* allocated) {
228 ASSERT(current_allocation_block_index_ < allocation_list_.length()); 230 CodeRangeData& data = v8_context()->code_range_data_;
229 if (requested > allocation_list_[current_allocation_block_index_].size) { 231 ASSERT(data.current_allocation_block_index_ < data.allocation_list_.length());
232 if (requested >
233 data.allocation_list_[data.current_allocation_block_index_].size) {
230 // Find an allocation block large enough. This function call may 234 // Find an allocation block large enough. This function call may
231 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block. 235 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block.
232 GetNextAllocationBlock(requested); 236 GetNextAllocationBlock(requested);
233 } 237 }
234 // Commit the requested memory at the start of the current allocation block. 238 // Commit the requested memory at the start of the current allocation block.
235 *allocated = RoundUp(requested, Page::kPageSize); 239 *allocated = RoundUp(requested, Page::kPageSize);
236 FreeBlock current = allocation_list_[current_allocation_block_index_]; 240 CodeRangeData::FreeBlock current =
241 data.allocation_list_[data.current_allocation_block_index_];
237 if (*allocated >= current.size - Page::kPageSize) { 242 if (*allocated >= current.size - Page::kPageSize) {
238 // Don't leave a small free block, useless for a large object or chunk. 243 // Don't leave a small free block, useless for a large object or chunk.
239 *allocated = current.size; 244 *allocated = current.size;
240 } 245 }
241 ASSERT(*allocated <= current.size); 246 ASSERT(*allocated <= current.size);
242 if (!code_range_->Commit(current.start, *allocated, true)) { 247 if (!data.code_range_->Commit(current.start, *allocated, true)) {
243 *allocated = 0; 248 *allocated = 0;
244 return NULL; 249 return NULL;
245 } 250 }
246 allocation_list_[current_allocation_block_index_].start += *allocated; 251 data.allocation_list_[data.current_allocation_block_index_].start +=
247 allocation_list_[current_allocation_block_index_].size -= *allocated; 252 *allocated;
253 data.allocation_list_[data.current_allocation_block_index_].size -=
254 *allocated;
248 if (*allocated == current.size) { 255 if (*allocated == current.size) {
249 GetNextAllocationBlock(0); // This block is used up, get the next one. 256 GetNextAllocationBlock(0); // This block is used up, get the next one.
250 } 257 }
251 return current.start; 258 return current.start;
252 } 259 }
253 260
254 261
255 void CodeRange::FreeRawMemory(void* address, size_t length) { 262 void CodeRange::FreeRawMemory(void* address, size_t length) {
256 free_list_.Add(FreeBlock(address, length)); 263 CodeRangeData& data = v8_context()->code_range_data_;
257 code_range_->Uncommit(address, length); 264 data.free_list_.Add(CodeRangeData::FreeBlock(address, length));
265 data.code_range_->Uncommit(address, length);
258 } 266 }
259 267
260 268
261 void CodeRange::TearDown() { 269 void CodeRange::TearDown() {
262 delete code_range_; // Frees all memory in the virtual memory range. 270 CodeRangeData& data = v8_context()->code_range_data_;
263 code_range_ = NULL; 271 delete data.code_range_; // Frees all memory in the virtual memory range.
264 free_list_.Free(); 272 data.code_range_ = NULL;
265 allocation_list_.Free(); 273 data.free_list_.Free();
274 data.allocation_list_.Free();
266 } 275 }
267 276
268 277
269 // ----------------------------------------------------------------------------- 278 // -----------------------------------------------------------------------------
270 // MemoryAllocator 279 // MemoryAllocator
271 // 280 //
272 int MemoryAllocator::capacity_ = 0;
273 int MemoryAllocator::size_ = 0;
274
275 VirtualMemory* MemoryAllocator::initial_chunk_ = NULL;
276 281
277 // 270 is an estimate based on the static default heap size of a pair of 256K 282 // 270 is an estimate based on the static default heap size of a pair of 256K
278 // semispaces and a 64M old generation. 283 // semispaces and a 64M old generation.
279 const int kEstimatedNumberOfChunks = 270; 284 const int kEstimatedNumberOfChunks = 270;
280 List<MemoryAllocator::ChunkInfo> MemoryAllocator::chunks_(
281 kEstimatedNumberOfChunks);
282 List<int> MemoryAllocator::free_chunk_ids_(kEstimatedNumberOfChunks);
283 int MemoryAllocator::max_nof_chunks_ = 0;
284 int MemoryAllocator::top_ = 0;
285 285
286 MemoryAllocatorData::MemoryAllocatorData()
287 :capacity_(0), size_(0), initial_chunk_(NULL),
288 free_chunk_ids_(kEstimatedNumberOfChunks), max_nof_chunks_(0), top_(0) {
289 }
286 290
287 void MemoryAllocator::Push(int free_chunk_id) { 291 void MemoryAllocator::Push(int free_chunk_id) {
288 ASSERT(max_nof_chunks_ > 0); 292 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
289 ASSERT(top_ < max_nof_chunks_); 293 ASSERT(data.max_nof_chunks_ > 0);
290 free_chunk_ids_[top_++] = free_chunk_id; 294 ASSERT(data.top_ < data.max_nof_chunks_);
295 data.free_chunk_ids_[data.top_++] = free_chunk_id;
291 } 296 }
292 297
293 298
294 int MemoryAllocator::Pop() { 299 int MemoryAllocator::Pop() {
295 ASSERT(top_ > 0); 300 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
296 return free_chunk_ids_[--top_]; 301 ASSERT(data.top_ > 0);
302 return data.free_chunk_ids_[--data.top_];
297 } 303 }
298 304
299 305
300 bool MemoryAllocator::Setup(int capacity) { 306 bool MemoryAllocator::Setup(int capacity) {
301 capacity_ = RoundUp(capacity, Page::kPageSize); 307 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
308 data.capacity_ = RoundUp(capacity, Page::kPageSize);
302 309
303 // Over-estimate the size of chunks_ array. It assumes the expansion of old 310 // Over-estimate the size of chunks_ array. It assumes the expansion of old
304 // space is always in the unit of a chunk (kChunkSize) except the last 311 // space is always in the unit of a chunk (kChunkSize) except the last
305 // expansion. 312 // expansion.
306 // 313 //
307 // Due to alignment, allocated space might be one page less than required 314 // Due to alignment, allocated space might be one page less than required
308 // number (kPagesPerChunk) of pages for old spaces. 315 // number (kPagesPerChunk) of pages for old spaces.
309 // 316 //
310 // Reserve two chunk ids for semispaces, one for map space, one for old 317 // Reserve two chunk ids for semispaces, one for map space, one for old
311 // space, and one for code space. 318 // space, and one for code space.
312 max_nof_chunks_ = (capacity_ / (kChunkSize - Page::kPageSize)) + 5; 319 data.max_nof_chunks_ = (data.capacity_ / (kChunkSize - Page::kPageSize)) + 5;
313 if (max_nof_chunks_ > kMaxNofChunks) return false; 320 if (data.max_nof_chunks_ > kMaxNofChunks) return false;
314 321
315 size_ = 0; 322 data.size_ = 0;
316 ChunkInfo info; // uninitialized element. 323 MemoryAllocatorData::ChunkInfo info; // uninitialized element.
317 for (int i = max_nof_chunks_ - 1; i >= 0; i--) { 324 for (int i = data.max_nof_chunks_ - 1; i >= 0; i--) {
318 chunks_.Add(info); 325 data.chunks_.Add(info);
319 free_chunk_ids_.Add(i); 326 data.free_chunk_ids_.Add(i);
320 } 327 }
321 top_ = max_nof_chunks_; 328 data.top_ = data.max_nof_chunks_;
322 return true; 329 return true;
323 } 330 }
324 331
325 332
326 void MemoryAllocator::TearDown() { 333 void MemoryAllocator::TearDown() {
327 for (int i = 0; i < max_nof_chunks_; i++) { 334 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
328 if (chunks_[i].address() != NULL) DeleteChunk(i); 335 for (int i = 0; i < data.max_nof_chunks_; i++) {
336 if (data.chunks_[i].address() != NULL) DeleteChunk(i);
329 } 337 }
330 chunks_.Clear(); 338 data.chunks_.Clear();
331 free_chunk_ids_.Clear(); 339 data.free_chunk_ids_.Clear();
332 340
333 if (initial_chunk_ != NULL) { 341 if (data.initial_chunk_ != NULL) {
334 LOG(DeleteEvent("InitialChunk", initial_chunk_->address())); 342 LOG(DeleteEvent("InitialChunk", data.initial_chunk_->address()));
335 delete initial_chunk_; 343 delete data.initial_chunk_;
336 initial_chunk_ = NULL; 344 data.initial_chunk_ = NULL;
337 } 345 }
338 346
339 ASSERT(top_ == max_nof_chunks_); // all chunks are free 347 ASSERT(data.top_ == data.max_nof_chunks_); // all chunks are free
340 top_ = 0; 348 data.top_ = 0;
341 capacity_ = 0; 349 data.capacity_ = 0;
342 size_ = 0; 350 data.size_ = 0;
343 max_nof_chunks_ = 0; 351 data.max_nof_chunks_ = 0;
344 } 352 }
345 353
346 354
347 void* MemoryAllocator::AllocateRawMemory(const size_t requested, 355 void* MemoryAllocator::AllocateRawMemory(const size_t requested,
348 size_t* allocated, 356 size_t* allocated,
349 Executability executable) { 357 Executability executable) {
350 if (size_ + static_cast<int>(requested) > capacity_) return NULL; 358 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
359 if (data.size_ + static_cast<int>(requested) > data.capacity_) return NULL;
351 void* mem; 360 void* mem;
352 if (executable == EXECUTABLE && CodeRange::exists()) { 361 if (executable == EXECUTABLE && CodeRange::exists()) {
353 mem = CodeRange::AllocateRawMemory(requested, allocated); 362 mem = CodeRange::AllocateRawMemory(requested, allocated);
354 } else { 363 } else {
355 mem = OS::Allocate(requested, allocated, (executable == EXECUTABLE)); 364 mem = OS::Allocate(requested, allocated, (executable == EXECUTABLE));
356 } 365 }
357 int alloced = static_cast<int>(*allocated); 366 int alloced = static_cast<int>(*allocated);
358 size_ += alloced; 367 data.size_ += alloced;
359 Counters::memory_allocated.Increment(alloced); 368 INCREMENT_COUNTER(memory_allocated, alloced);
360 return mem; 369 return mem;
361 } 370 }
362 371
363 372
364 void MemoryAllocator::FreeRawMemory(void* mem, size_t length) { 373 void MemoryAllocator::FreeRawMemory(void* mem, size_t length) {
365 if (CodeRange::contains(static_cast<Address>(mem))) { 374 if (CodeRange::contains(static_cast<Address>(mem))) {
366 CodeRange::FreeRawMemory(mem, length); 375 CodeRange::FreeRawMemory(mem, length);
367 } else { 376 } else {
368 OS::Free(mem, length); 377 OS::Free(mem, length);
369 } 378 }
370 Counters::memory_allocated.Decrement(static_cast<int>(length)); 379 DECREMENT_COUNTER(memory_allocated, static_cast<int>(length));
371 size_ -= static_cast<int>(length); 380 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
372 ASSERT(size_ >= 0); 381 data.size_ -= static_cast<int>(length);
382 ASSERT(data.size_ >= 0);
373 } 383 }
374 384
375 385
376 void* MemoryAllocator::ReserveInitialChunk(const size_t requested) { 386 void* MemoryAllocator::ReserveInitialChunk(const size_t requested) {
377 ASSERT(initial_chunk_ == NULL); 387 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
388 ASSERT(data.initial_chunk_ == NULL);
378 389
379 initial_chunk_ = new VirtualMemory(requested); 390 data.initial_chunk_ = new VirtualMemory(requested);
380 CHECK(initial_chunk_ != NULL); 391 CHECK(data.initial_chunk_ != NULL);
381 if (!initial_chunk_->IsReserved()) { 392 if (!data.initial_chunk_->IsReserved()) {
382 delete initial_chunk_; 393 delete data.initial_chunk_;
383 initial_chunk_ = NULL; 394 data.initial_chunk_ = NULL;
384 return NULL; 395 return NULL;
385 } 396 }
386 397
387 // We are sure that we have mapped a block of requested addresses. 398 // We are sure that we have mapped a block of requested addresses.
388 ASSERT(initial_chunk_->size() == requested); 399 ASSERT(data.initial_chunk_->size() == requested);
389 LOG(NewEvent("InitialChunk", initial_chunk_->address(), requested)); 400 LOG(NewEvent("InitialChunk", data.initial_chunk_->address(), requested));
390 size_ += static_cast<int>(requested); 401 data.size_ += static_cast<int>(requested);
391 return initial_chunk_->address(); 402 return data.initial_chunk_->address();
392 } 403 }
393 404
394 405
395 static int PagesInChunk(Address start, size_t size) { 406 static int PagesInChunk(Address start, size_t size) {
396 // The first page starts on the first page-aligned address from start onward 407 // The first page starts on the first page-aligned address from start onward
397 // and the last page ends on the last page-aligned address before 408 // and the last page ends on the last page-aligned address before
398 // start+size. Page::kPageSize is a power of two so we can divide by 409 // start+size. Page::kPageSize is a power of two so we can divide by
399 // shifting. 410 // shifting.
400 return static_cast<int>((RoundDown(start + size, Page::kPageSize) 411 return static_cast<int>((RoundDown(start + size, Page::kPageSize)
401 - RoundUp(start, Page::kPageSize)) >> Page::kPageSizeBits); 412 - RoundUp(start, Page::kPageSize)) >> Page::kPageSizeBits);
402 } 413 }
403 414
404 415
405 Page* MemoryAllocator::AllocatePages(int requested_pages, int* allocated_pages, 416 Page* MemoryAllocator::AllocatePages(int requested_pages, int* allocated_pages,
406 PagedSpace* owner) { 417 PagedSpace* owner) {
407 if (requested_pages <= 0) return Page::FromAddress(NULL); 418 if (requested_pages <= 0) return Page::FromAddress(NULL);
408 size_t chunk_size = requested_pages * Page::kPageSize; 419 size_t chunk_size = requested_pages * Page::kPageSize;
409 420
421 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
410 // There is not enough space to guarantee the desired number pages can be 422 // There is not enough space to guarantee the desired number pages can be
411 // allocated. 423 // allocated.
412 if (size_ + static_cast<int>(chunk_size) > capacity_) { 424 if (data.size_ + static_cast<int>(chunk_size) > data.capacity_) {
413 // Request as many pages as we can. 425 // Request as many pages as we can.
414 chunk_size = capacity_ - size_; 426 chunk_size = data.capacity_ - data.size_;
415 requested_pages = static_cast<int>(chunk_size >> Page::kPageSizeBits); 427 requested_pages = static_cast<int>(chunk_size >> Page::kPageSizeBits);
416 428
417 if (requested_pages <= 0) return Page::FromAddress(NULL); 429 if (requested_pages <= 0) return Page::FromAddress(NULL);
418 } 430 }
419 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable()); 431 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable());
420 if (chunk == NULL) return Page::FromAddress(NULL); 432 if (chunk == NULL) return Page::FromAddress(NULL);
421 LOG(NewEvent("PagedChunk", chunk, chunk_size)); 433 LOG(NewEvent("PagedChunk", chunk, chunk_size));
422 434
423 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size); 435 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
424 if (*allocated_pages == 0) { 436 if (*allocated_pages == 0) {
425 FreeRawMemory(chunk, chunk_size); 437 FreeRawMemory(chunk, chunk_size);
426 LOG(DeleteEvent("PagedChunk", chunk)); 438 LOG(DeleteEvent("PagedChunk", chunk));
427 return Page::FromAddress(NULL); 439 return Page::FromAddress(NULL);
428 } 440 }
429 441
430 int chunk_id = Pop(); 442 int chunk_id = Pop();
431 chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner); 443 data.chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner);
432 444
433 return InitializePagesInChunk(chunk_id, *allocated_pages, owner); 445 return InitializePagesInChunk(chunk_id, *allocated_pages, owner);
434 } 446 }
435 447
436 448
437 Page* MemoryAllocator::CommitPages(Address start, size_t size, 449 Page* MemoryAllocator::CommitPages(Address start, size_t size,
438 PagedSpace* owner, int* num_pages) { 450 PagedSpace* owner, int* num_pages) {
451 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
439 ASSERT(start != NULL); 452 ASSERT(start != NULL);
440 *num_pages = PagesInChunk(start, size); 453 *num_pages = PagesInChunk(start, size);
441 ASSERT(*num_pages > 0); 454 ASSERT(*num_pages > 0);
442 ASSERT(initial_chunk_ != NULL); 455 ASSERT(data.initial_chunk_ != NULL);
443 ASSERT(InInitialChunk(start)); 456 ASSERT(InInitialChunk(start));
444 ASSERT(InInitialChunk(start + size - 1)); 457 ASSERT(InInitialChunk(start + size - 1));
445 if (!initial_chunk_->Commit(start, size, owner->executable() == EXECUTABLE)) { 458 if (!data.initial_chunk_->Commit(start, size, owner->executable()
459 == EXECUTABLE)) {
446 return Page::FromAddress(NULL); 460 return Page::FromAddress(NULL);
447 } 461 }
448 Counters::memory_allocated.Increment(static_cast<int>(size)); 462 INCREMENT_COUNTER(memory_allocated, static_cast<int>(size));
449 463
450 // So long as we correctly overestimated the number of chunks we should not 464 // So long as we correctly overestimated the number of chunks we should not
451 // run out of chunk ids. 465 // run out of chunk ids.
452 CHECK(!OutOfChunkIds()); 466 CHECK(!OutOfChunkIds());
453 int chunk_id = Pop(); 467 int chunk_id = Pop();
454 chunks_[chunk_id].init(start, size, owner); 468 data.chunks_[chunk_id].init(start, size, owner);
455 return InitializePagesInChunk(chunk_id, *num_pages, owner); 469 return InitializePagesInChunk(chunk_id, *num_pages, owner);
456 } 470 }
457 471
458 472
459 bool MemoryAllocator::CommitBlock(Address start, 473 bool MemoryAllocator::CommitBlock(Address start,
460 size_t size, 474 size_t size,
461 Executability executable) { 475 Executability executable) {
476 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
462 ASSERT(start != NULL); 477 ASSERT(start != NULL);
463 ASSERT(size > 0); 478 ASSERT(size > 0);
464 ASSERT(initial_chunk_ != NULL); 479 ASSERT(data.initial_chunk_ != NULL);
465 ASSERT(InInitialChunk(start)); 480 ASSERT(InInitialChunk(start));
466 ASSERT(InInitialChunk(start + size - 1)); 481 ASSERT(InInitialChunk(start + size - 1));
467 482
468 if (!initial_chunk_->Commit(start, size, executable)) return false; 483 if (!data.initial_chunk_->Commit(start, size, executable)) return false;
469 Counters::memory_allocated.Increment(static_cast<int>(size)); 484 INCREMENT_COUNTER(memory_allocated, static_cast<int>(size));
470 return true; 485 return true;
471 } 486 }
472 487
473 bool MemoryAllocator::UncommitBlock(Address start, size_t size) { 488 bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
489 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
474 ASSERT(start != NULL); 490 ASSERT(start != NULL);
475 ASSERT(size > 0); 491 ASSERT(size > 0);
476 ASSERT(initial_chunk_ != NULL); 492 ASSERT(data.initial_chunk_ != NULL);
477 ASSERT(InInitialChunk(start)); 493 ASSERT(InInitialChunk(start));
478 ASSERT(InInitialChunk(start + size - 1)); 494 ASSERT(InInitialChunk(start + size - 1));
479 495
480 if (!initial_chunk_->Uncommit(start, size)) return false; 496 if (!data.initial_chunk_->Uncommit(start, size)) return false;
481 Counters::memory_allocated.Decrement(static_cast<int>(size)); 497 DECREMENT_COUNTER(memory_allocated, static_cast<int>(size));
482 return true; 498 return true;
483 } 499 }
484 500
485 Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int pages_in_chunk, 501 Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int pages_in_chunk,
486 PagedSpace* owner) { 502 PagedSpace* owner) {
487 ASSERT(IsValidChunk(chunk_id)); 503 ASSERT(IsValidChunk(chunk_id));
488 ASSERT(pages_in_chunk > 0); 504 ASSERT(pages_in_chunk > 0);
489 505
490 Address chunk_start = chunks_[chunk_id].address(); 506 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
507 Address chunk_start = data.chunks_[chunk_id].address();
491 508
492 Address low = RoundUp(chunk_start, Page::kPageSize); 509 Address low = RoundUp(chunk_start, Page::kPageSize);
493 510
494 #ifdef DEBUG 511 #ifdef DEBUG
495 size_t chunk_size = chunks_[chunk_id].size(); 512 size_t chunk_size = data.chunks_[chunk_id].size();
496 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize); 513 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize);
497 ASSERT(pages_in_chunk <= 514 ASSERT(pages_in_chunk <=
498 ((OffsetFrom(high) - OffsetFrom(low)) / Page::kPageSize)); 515 ((OffsetFrom(high) - OffsetFrom(low)) / Page::kPageSize));
499 #endif 516 #endif
500 517
501 Address page_addr = low; 518 Address page_addr = low;
502 for (int i = 0; i < pages_in_chunk; i++) { 519 for (int i = 0; i < pages_in_chunk; i++) {
503 Page* p = Page::FromAddress(page_addr); 520 Page* p = Page::FromAddress(page_addr);
504 p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id; 521 p->opaque_header = OffsetFrom(page_addr + Page::kPageSize) | chunk_id;
505 p->is_normal_page = 1; 522 p->is_normal_page = 1;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 557
541 // Free the current chunk. 558 // Free the current chunk.
542 DeleteChunk(chunk_id); 559 DeleteChunk(chunk_id);
543 } 560 }
544 561
545 return page_to_return; 562 return page_to_return;
546 } 563 }
547 564
548 565
549 void MemoryAllocator::DeleteChunk(int chunk_id) { 566 void MemoryAllocator::DeleteChunk(int chunk_id) {
567 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
550 ASSERT(IsValidChunk(chunk_id)); 568 ASSERT(IsValidChunk(chunk_id));
551 569
552 ChunkInfo& c = chunks_[chunk_id]; 570 MemoryAllocatorData::ChunkInfo& c = data.chunks_[chunk_id];
553 571
554 // We cannot free a chunk contained in the initial chunk because it was not 572 // We cannot free a chunk contained in the initial chunk because it was not
555 // allocated with AllocateRawMemory. Instead we uncommit the virtual 573 // allocated with AllocateRawMemory. Instead we uncommit the virtual
556 // memory. 574 // memory.
557 if (InInitialChunk(c.address())) { 575 if (InInitialChunk(c.address())) {
558 // TODO(1240712): VirtualMemory::Uncommit has a return value which 576 // TODO(1240712): VirtualMemory::Uncommit has a return value which
559 // is ignored here. 577 // is ignored here.
560 initial_chunk_->Uncommit(c.address(), c.size()); 578 data.initial_chunk_->Uncommit(c.address(), c.size());
561 Counters::memory_allocated.Decrement(static_cast<int>(c.size())); 579 DECREMENT_COUNTER(memory_allocated, static_cast<int>(c.size()));
562 } else { 580 } else {
563 LOG(DeleteEvent("PagedChunk", c.address())); 581 LOG(DeleteEvent("PagedChunk", c.address()));
564 FreeRawMemory(c.address(), c.size()); 582 FreeRawMemory(c.address(), c.size());
565 } 583 }
566 c.init(NULL, 0, NULL); 584 c.init(NULL, 0, NULL);
567 Push(chunk_id); 585 Push(chunk_id);
568 } 586 }
569 587
570 588
571 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) { 589 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) {
572 int chunk_id = GetChunkId(p); 590 int chunk_id = GetChunkId(p);
573 ASSERT(IsValidChunk(chunk_id)); 591 ASSERT(IsValidChunk(chunk_id));
574 592
575 Address low = RoundUp(chunks_[chunk_id].address(), Page::kPageSize); 593 Address low = RoundUp(
594 v8_context()->memory_allocator_data_.chunks_[chunk_id].address(),
595 Page::kPageSize);
576 return Page::FromAddress(low); 596 return Page::FromAddress(low);
577 } 597 }
578 598
579 599
580 Page* MemoryAllocator::FindLastPageInSameChunk(Page* p) { 600 Page* MemoryAllocator::FindLastPageInSameChunk(Page* p) {
581 int chunk_id = GetChunkId(p); 601 int chunk_id = GetChunkId(p);
582 ASSERT(IsValidChunk(chunk_id)); 602 ASSERT(IsValidChunk(chunk_id));
583 603
584 Address chunk_start = chunks_[chunk_id].address(); 604 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
585 size_t chunk_size = chunks_[chunk_id].size(); 605 Address chunk_start = data.chunks_[chunk_id].address();
606 size_t chunk_size = data.chunks_[chunk_id].size();
586 607
587 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize); 608 Address high = RoundDown(chunk_start + chunk_size, Page::kPageSize);
588 ASSERT(chunk_start <= p->address() && p->address() < high); 609 ASSERT(chunk_start <= p->address() && p->address() < high);
589 610
590 return Page::FromAddress(high - Page::kPageSize); 611 return Page::FromAddress(high - Page::kPageSize);
591 } 612 }
592 613
593 614
594 #ifdef DEBUG 615 #ifdef DEBUG
595 void MemoryAllocator::ReportStatistics() { 616 void MemoryAllocator::ReportStatistics() {
596 float pct = static_cast<float>(capacity_ - size_) / capacity_; 617 MemoryAllocatorData& data = v8_context()->memory_allocator_data_;
618 float pct = static_cast<float>(data.capacity_ - data.size_) / data.capacity_;
597 PrintF(" capacity: %d, used: %d, available: %%%d\n\n", 619 PrintF(" capacity: %d, used: %d, available: %%%d\n\n",
598 capacity_, size_, static_cast<int>(pct*100)); 620 data.capacity_, data.size_, static_cast<int>(pct*100));
599 } 621 }
600 #endif 622 #endif
601 623
602 624
603 // ----------------------------------------------------------------------------- 625 // -----------------------------------------------------------------------------
604 // PagedSpace implementation 626 // PagedSpace implementation
605 627
606 PagedSpace::PagedSpace(int max_capacity, 628 PagedSpace::PagedSpace(int max_capacity,
607 AllocationSpace id, 629 AllocationSpace id,
608 Executability executable) 630 Executability executable)
(...skipping 2182 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 reinterpret_cast<Object**>(object->address() 2813 reinterpret_cast<Object**>(object->address()
2792 + Page::kObjectAreaSize), 2814 + Page::kObjectAreaSize),
2793 allocation_top); 2815 allocation_top);
2794 PrintF("\n"); 2816 PrintF("\n");
2795 } 2817 }
2796 } 2818 }
2797 } 2819 }
2798 #endif // DEBUG 2820 #endif // DEBUG
2799 2821
2800 } } // namespace v8::internal 2822 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/spaces.h ('k') | src/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698