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

Side by Side Diff: src/spaces.cc

Issue 11566011: Use MemoryChunk-based allocation for deoptimization entry code (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « src/spaces.h ('k') | test/cctest/test-alloc.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 // 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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 if (requested <= allocation_list_[current_allocation_block_index_].size) { 200 if (requested <= allocation_list_[current_allocation_block_index_].size) {
201 return; // Found a large enough allocation block. 201 return; // Found a large enough allocation block.
202 } 202 }
203 } 203 }
204 204
205 // Code range is full or too fragmented. 205 // Code range is full or too fragmented.
206 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock"); 206 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock");
207 } 207 }
208 208
209 209
210
211 Address CodeRange::AllocateRawMemory(const size_t requested, 210 Address CodeRange::AllocateRawMemory(const size_t requested,
212 size_t* allocated) { 211 size_t* allocated,
212 size_t initial_commit_size) {
213 ASSERT(initial_commit_size <= requested);
213 ASSERT(current_allocation_block_index_ < allocation_list_.length()); 214 ASSERT(current_allocation_block_index_ < allocation_list_.length());
214 if (requested > allocation_list_[current_allocation_block_index_].size) { 215 if (requested > allocation_list_[current_allocation_block_index_].size) {
215 // Find an allocation block large enough. This function call may 216 // Find an allocation block large enough. This function call may
216 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block. 217 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block.
217 GetNextAllocationBlock(requested); 218 GetNextAllocationBlock(requested);
218 } 219 }
219 // Commit the requested memory at the start of the current allocation block. 220 // Commit the requested memory at the start of the current allocation block.
220 size_t aligned_requested = RoundUp(requested, MemoryChunk::kAlignment); 221 size_t aligned_requested = RoundUp(requested, MemoryChunk::kAlignment);
221 FreeBlock current = allocation_list_[current_allocation_block_index_]; 222 FreeBlock current = allocation_list_[current_allocation_block_index_];
222 if (aligned_requested >= (current.size - Page::kPageSize)) { 223 if (aligned_requested >= (current.size - Page::kPageSize)) {
223 // Don't leave a small free block, useless for a large object or chunk. 224 // Don't leave a small free block, useless for a large object or chunk.
224 *allocated = current.size; 225 *allocated = current.size;
225 } else { 226 } else {
226 *allocated = aligned_requested; 227 *allocated = aligned_requested;
227 } 228 }
228 ASSERT(*allocated <= current.size); 229 ASSERT(*allocated <= current.size);
229 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); 230 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment));
230 if (!MemoryAllocator::CommitCodePage(code_range_, 231 if (!MemoryAllocator::CommitCodePage(code_range_,
231 current.start, 232 current.start,
232 *allocated)) { 233 initial_commit_size)) {
233 *allocated = 0; 234 *allocated = 0;
234 return NULL; 235 return NULL;
235 } 236 }
236 allocation_list_[current_allocation_block_index_].start += *allocated; 237 allocation_list_[current_allocation_block_index_].start += *allocated;
237 allocation_list_[current_allocation_block_index_].size -= *allocated; 238 allocation_list_[current_allocation_block_index_].size -= *allocated;
238 if (*allocated == current.size) { 239 if (*allocated == current.size) {
239 GetNextAllocationBlock(0); // This block is used up, get the next one. 240 GetNextAllocationBlock(0); // This block is used up, get the next one.
240 } 241 }
241 return current.start; 242 return current.start;
242 } 243 }
243 244
244 245
246 bool CodeRange::RecommitRawMemory(Address start, size_t size) {
danno 2013/01/16 14:48:54 If you make the changes in MemoryChunk to support
haitao.feng 2013/01/17 05:34:01 Done.
247 ASSERT(reinterpret_cast<int64_t>(start) % MemoryChunk::kAlignment ==
248 MemoryAllocator::CodePageAreaStartOffset());
249
250 // Recommit page body (executable).
251 if (!code_range_->Commit(start, size, true)) return false;
252 // Append a guard page.
253 if (!code_range_->Guard(start + size)) return false;
danno 2013/01/16 14:48:54 Guard pages are managed by the MemoryChunk (not he
haitao.feng 2013/01/17 05:34:01 Done.
254
255 return true;
256 }
257
258
245 void CodeRange::FreeRawMemory(Address address, size_t length) { 259 void CodeRange::FreeRawMemory(Address address, size_t length) {
246 ASSERT(IsAddressAligned(address, MemoryChunk::kAlignment)); 260 ASSERT(IsAddressAligned(address, MemoryChunk::kAlignment));
247 free_list_.Add(FreeBlock(address, length)); 261 free_list_.Add(FreeBlock(address, length));
248 code_range_->Uncommit(address, length); 262 code_range_->Uncommit(address, length);
249 } 263 }
250 264
251 265
252 void CodeRange::TearDown() { 266 void CodeRange::TearDown() {
253 delete code_range_; // Frees all memory in the virtual memory range. 267 delete code_range_; // Frees all memory in the virtual memory range.
254 code_range_ = NULL; 268 code_range_ = NULL;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 353 }
340 354
341 355
342 Address MemoryAllocator::ReserveAlignedMemory(size_t size, 356 Address MemoryAllocator::ReserveAlignedMemory(size_t size,
343 size_t alignment, 357 size_t alignment,
344 VirtualMemory* controller) { 358 VirtualMemory* controller) {
345 VirtualMemory reservation(size, alignment); 359 VirtualMemory reservation(size, alignment);
346 360
347 if (!reservation.IsReserved()) return NULL; 361 if (!reservation.IsReserved()) return NULL;
348 size_ += reservation.size(); 362 size_ += reservation.size();
349 Address base = RoundUp(static_cast<Address>(reservation.address()), 363 Address base = static_cast<Address>(reservation.address());
350 alignment);
351 controller->TakeControl(&reservation); 364 controller->TakeControl(&reservation);
352 return base; 365 return base;
353 } 366 }
354 367
355 368
356 Address MemoryAllocator::AllocateAlignedMemory(size_t size, 369 Address MemoryAllocator::AllocateAlignedMemory(size_t size,
357 size_t alignment, 370 size_t alignment,
371 size_t initial_commit_size,
358 Executability executable, 372 Executability executable,
359 VirtualMemory* controller) { 373 VirtualMemory* controller) {
374 ASSERT(initial_commit_size <= size);
360 VirtualMemory reservation; 375 VirtualMemory reservation;
361 Address base = ReserveAlignedMemory(size, alignment, &reservation); 376 Address base = ReserveAlignedMemory(size, alignment, &reservation);
362 if (base == NULL) return NULL; 377 if (base == NULL) return NULL;
363 378
364 if (executable == EXECUTABLE) { 379 if (executable == EXECUTABLE) {
365 if (!CommitCodePage(&reservation, base, size)) { 380 if (!CommitCodePage(&reservation, base, initial_commit_size)) {
danno 2013/01/16 14:48:54 CommitCodePage should take both size and initial_c
haitao.feng 2013/01/17 05:34:01 Done.
366 base = NULL; 381 base = NULL;
367 } 382 }
368 } else { 383 } else {
369 if (!reservation.Commit(base, size, false)) { 384 if (!reservation.Commit(base, initial_commit_size, false)) {
370 base = NULL; 385 base = NULL;
371 } 386 }
372 } 387 }
373 388
374 if (base == NULL) { 389 if (base == NULL) {
375 // Failed to commit the body. Release the mapping and any partially 390 // Failed to commit the body. Release the mapping and any partially
376 // commited regions inside it. 391 // commited regions inside it.
377 reservation.Release(); 392 reservation.Release();
378 return NULL; 393 return NULL;
379 } 394 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 } 478 }
464 479
465 if (owner == heap->old_data_space()) { 480 if (owner == heap->old_data_space()) {
466 chunk->SetFlag(CONTAINS_ONLY_DATA); 481 chunk->SetFlag(CONTAINS_ONLY_DATA);
467 } 482 }
468 483
469 return chunk; 484 return chunk;
470 } 485 }
471 486
472 487
488 bool MemoryChunk::RecommitBody(size_t body_size, Executability executable) {
danno 2013/01/16 14:48:54 I think I'd prefer that the MemoryChunk remembered
haitao.feng 2013/01/17 05:34:01 I am using area_end_ - area_start_ to remember "co
489 ASSERT(area_start_ + body_size <= area_end_);
490 if (reservation_.IsReserved()) {
491 if (executable == EXECUTABLE) {
492 // Recommit page body (executable).
493 if (!reservation_.Commit(area_start_, body_size, true)) return false;
494 // Append a guard page.
495 if (!reservation_.Guard(area_start_ + body_size)) return false;
danno 2013/01/16 14:48:54 As mentioned above, the guard page should always b
haitao.feng 2013/01/17 05:34:01 Done.
496 } else {
497 if (!reservation_.Commit(area_start_, body_size, false)) return false;
498 }
499 } else {
500 ASSERT(heap_->isolate()->code_range()->exists() &&
501 (executable == EXECUTABLE));
502 // Recommit page body (executable).
503 if (!heap_->isolate()->code_range()->RecommitRawMemory(area_start_,
danno 2013/01/16 14:48:54 If you change this method to be called "CommitBody
haitao.feng 2013/01/17 05:34:01 Done.
504 body_size)) {
505 return false;
506 }
507 }
508
509 if (Heap::ShouldZapGarbage()) {
danno 2013/01/16 14:48:54 Just zap the delta of uncommitted pages.
haitao.feng 2013/01/17 05:34:01 Done.
510 heap_->isolate()->memory_allocator()->ZapBlock(area_start_, body_size);
511 }
512
513 return true;
514 }
515
516
473 void MemoryChunk::InsertAfter(MemoryChunk* other) { 517 void MemoryChunk::InsertAfter(MemoryChunk* other) {
474 next_chunk_ = other->next_chunk_; 518 next_chunk_ = other->next_chunk_;
475 prev_chunk_ = other; 519 prev_chunk_ = other;
476 other->next_chunk_->prev_chunk_ = this; 520 other->next_chunk_->prev_chunk_ = this;
477 other->next_chunk_ = this; 521 other->next_chunk_ = this;
478 } 522 }
479 523
480 524
481 void MemoryChunk::Unlink() { 525 void MemoryChunk::Unlink() {
482 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) { 526 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) {
483 heap_->decrement_scan_on_scavenge_pages(); 527 heap_->decrement_scan_on_scavenge_pages();
484 ClearFlag(SCAN_ON_SCAVENGE); 528 ClearFlag(SCAN_ON_SCAVENGE);
485 } 529 }
486 next_chunk_->prev_chunk_ = prev_chunk_; 530 next_chunk_->prev_chunk_ = prev_chunk_;
487 prev_chunk_->next_chunk_ = next_chunk_; 531 prev_chunk_->next_chunk_ = next_chunk_;
488 prev_chunk_ = NULL; 532 prev_chunk_ = NULL;
489 next_chunk_ = NULL; 533 next_chunk_ = NULL;
490 } 534 }
491 535
492 536
493 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, 537 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size,
538 intptr_t commit_size,
494 Executability executable, 539 Executability executable,
495 Space* owner) { 540 Space* owner) {
496 size_t chunk_size; 541 ASSERT(commit_size <= body_size);
542
543 size_t chunk_size, initial_commit_size;
danno 2013/01/16 14:48:54 nit: declare initial_commit_size in the scope that
497 Heap* heap = isolate_->heap(); 544 Heap* heap = isolate_->heap();
498 Address base = NULL; 545 Address base = NULL;
499 VirtualMemory reservation; 546 VirtualMemory reservation;
500 Address area_start = NULL; 547 Address area_start = NULL;
501 Address area_end = NULL; 548 Address area_end = NULL;
502 549
503 if (executable == EXECUTABLE) { 550 if (executable == EXECUTABLE) {
504 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, 551 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size,
505 OS::CommitPageSize()) + CodePageGuardSize(); 552 OS::CommitPageSize()) + CodePageGuardSize();
506 553
507 // Check executable memory limit. 554 // Check executable memory limit.
508 if (size_executable_ + chunk_size > capacity_executable_) { 555 if (size_executable_ + chunk_size > capacity_executable_) {
509 LOG(isolate_, 556 LOG(isolate_,
510 StringEvent("MemoryAllocator::AllocateRawMemory", 557 StringEvent("MemoryAllocator::AllocateRawMemory",
511 "V8 Executable Allocation capacity exceeded")); 558 "V8 Executable Allocation capacity exceeded"));
512 return NULL; 559 return NULL;
513 } 560 }
514 561
562 initial_commit_size = RoundUp(CodePageAreaStartOffset() + commit_size,
danno 2013/01/16 14:48:54 I don't think you need to round this up if you mak
danno 2013/01/16 14:48:54 As noted above: size_t initial_commit_size = ...
haitao.feng 2013/01/17 05:34:01 Done.
haitao.feng 2013/01/17 05:34:01 Done.
563 OS::CommitPageSize()) + CodePageGuardSize();
564
515 // Allocate executable memory either from code range or from the 565 // Allocate executable memory either from code range or from the
516 // OS. 566 // OS.
517 if (isolate_->code_range()->exists()) { 567 if (isolate_->code_range()->exists()) {
518 base = isolate_->code_range()->AllocateRawMemory(chunk_size, &chunk_size); 568 base = isolate_->code_range()->AllocateRawMemory(chunk_size,
569 &chunk_size,
570 initial_commit_size);
519 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), 571 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base),
520 MemoryChunk::kAlignment)); 572 MemoryChunk::kAlignment));
521 if (base == NULL) return NULL; 573 if (base == NULL) return NULL;
522 size_ += chunk_size; 574 size_ += chunk_size;
523 // Update executable memory size. 575 // Update executable memory size.
524 size_executable_ += chunk_size; 576 size_executable_ += chunk_size;
525 } else { 577 } else {
526 base = AllocateAlignedMemory(chunk_size, 578 base = AllocateAlignedMemory(chunk_size,
527 MemoryChunk::kAlignment, 579 MemoryChunk::kAlignment,
580 initial_commit_size,
528 executable, 581 executable,
529 &reservation); 582 &reservation);
530 if (base == NULL) return NULL; 583 if (base == NULL) return NULL;
531 // Update executable memory size. 584 // Update executable memory size.
532 size_executable_ += reservation.size(); 585 size_executable_ += reservation.size();
533 } 586 }
534 587
535 if (Heap::ShouldZapGarbage()) { 588 if (Heap::ShouldZapGarbage()) {
536 ZapBlock(base, CodePageGuardStartOffset()); 589 ZapBlock(base, CodePageGuardStartOffset());
537 ZapBlock(base + CodePageAreaStartOffset(), body_size); 590 ZapBlock(base + CodePageAreaStartOffset(), commit_size);
538 } 591 }
539 592
540 area_start = base + CodePageAreaStartOffset(); 593 area_start = base + CodePageAreaStartOffset();
541 area_end = area_start + body_size; 594 area_end = area_start + body_size;
542 } else { 595 } else {
543 chunk_size = MemoryChunk::kObjectStartOffset + body_size; 596 chunk_size = MemoryChunk::kObjectStartOffset + body_size;
597 initial_commit_size = MemoryChunk::kObjectStartOffset + commit_size;
danno 2013/01/16 14:48:54 As noted above: size_t initial_commit_size = ...
haitao.feng 2013/01/17 05:34:01 Done.
544 base = AllocateAlignedMemory(chunk_size, 598 base = AllocateAlignedMemory(chunk_size,
545 MemoryChunk::kAlignment, 599 MemoryChunk::kAlignment,
600 initial_commit_size,
546 executable, 601 executable,
547 &reservation); 602 &reservation);
548 603
549 if (base == NULL) return NULL; 604 if (base == NULL) return NULL;
550 605
551 if (Heap::ShouldZapGarbage()) { 606 if (Heap::ShouldZapGarbage()) {
552 ZapBlock(base, chunk_size); 607 ZapBlock(base, commit_size);
553 } 608 }
554 609
555 area_start = base + Page::kObjectStartOffset; 610 area_start = base + Page::kObjectStartOffset;
556 area_end = base + chunk_size; 611 area_end = base + chunk_size;
557 } 612 }
558 613
559 isolate_->counters()->memory_allocated()-> 614 isolate_->counters()->memory_allocated()->
560 Increment(static_cast<int>(chunk_size)); 615 Increment(static_cast<int>(chunk_size));
561 616
562 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); 617 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size));
(...skipping 10 matching lines...) Expand all
573 executable, 628 executable,
574 owner); 629 owner);
575 result->set_reserved_memory(&reservation); 630 result->set_reserved_memory(&reservation);
576 return result; 631 return result;
577 } 632 }
578 633
579 634
580 Page* MemoryAllocator::AllocatePage(intptr_t size, 635 Page* MemoryAllocator::AllocatePage(intptr_t size,
581 PagedSpace* owner, 636 PagedSpace* owner,
582 Executability executable) { 637 Executability executable) {
583 MemoryChunk* chunk = AllocateChunk(size, executable, owner); 638 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner);
584 639
585 if (chunk == NULL) return NULL; 640 if (chunk == NULL) return NULL;
586 641
587 return Page::Initialize(isolate_->heap(), chunk, executable, owner); 642 return Page::Initialize(isolate_->heap(), chunk, executable, owner);
588 } 643 }
589 644
590 645
591 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size, 646 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size,
592 Space* owner, 647 Space* owner,
593 Executability executable) { 648 Executability executable) {
594 MemoryChunk* chunk = AllocateChunk(object_size, executable, owner); 649 MemoryChunk* chunk = AllocateChunk(object_size,
650 object_size,
651 executable,
652 owner);
595 if (chunk == NULL) return NULL; 653 if (chunk == NULL) return NULL;
596 return LargePage::Initialize(isolate_->heap(), chunk); 654 return LargePage::Initialize(isolate_->heap(), chunk);
597 } 655 }
598 656
599 657
600 void MemoryAllocator::Free(MemoryChunk* chunk) { 658 void MemoryAllocator::Free(MemoryChunk* chunk) {
601 LOG(isolate_, DeleteEvent("MemoryChunk", chunk)); 659 LOG(isolate_, DeleteEvent("MemoryChunk", chunk));
602 if (chunk->owner() != NULL) { 660 if (chunk->owner() != NULL) {
603 ObjectSpace space = 661 ObjectSpace space =
604 static_cast<ObjectSpace>(1 << chunk->owner()->identity()); 662 static_cast<ObjectSpace>(1 << chunk->owner()->identity());
(...skipping 2381 matching lines...) Expand 10 before | Expand all | Expand 10 after
2986 object->ShortPrint(); 3044 object->ShortPrint();
2987 PrintF("\n"); 3045 PrintF("\n");
2988 } 3046 }
2989 printf(" --------------------------------------\n"); 3047 printf(" --------------------------------------\n");
2990 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3048 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
2991 } 3049 }
2992 3050
2993 #endif // DEBUG 3051 #endif // DEBUG
2994 3052
2995 } } // namespace v8::internal 3053 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/spaces.h ('k') | test/cctest/test-alloc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698