| OLD | NEW |
| 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 if (requested <= allocation_list_[current_allocation_block_index_].size) { | 199 if (requested <= allocation_list_[current_allocation_block_index_].size) { |
| 200 return; // Found a large enough allocation block. | 200 return; // Found a large enough allocation block. |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 // Code range is full or too fragmented. | 204 // Code range is full or too fragmented. |
| 205 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock"); | 205 V8::FatalProcessOutOfMemory("CodeRange::GetNextAllocationBlock"); |
| 206 } | 206 } |
| 207 | 207 |
| 208 | 208 |
| 209 | 209 Address CodeRange::AllocateRawMemory(const size_t requested_size, |
| 210 Address CodeRange::AllocateRawMemory(const size_t requested, | 210 const size_t commit_size, |
| 211 size_t* allocated) { | 211 size_t* allocated) { |
| 212 ASSERT(commit_size <= requested_size); |
| 212 ASSERT(current_allocation_block_index_ < allocation_list_.length()); | 213 ASSERT(current_allocation_block_index_ < allocation_list_.length()); |
| 213 if (requested > allocation_list_[current_allocation_block_index_].size) { | 214 if (requested_size > allocation_list_[current_allocation_block_index_].size) { |
| 214 // Find an allocation block large enough. This function call may | 215 // Find an allocation block large enough. This function call may |
| 215 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block. | 216 // call V8::FatalProcessOutOfMemory if it cannot find a large enough block. |
| 216 GetNextAllocationBlock(requested); | 217 GetNextAllocationBlock(requested_size); |
| 217 } | 218 } |
| 218 // Commit the requested memory at the start of the current allocation block. | 219 // Commit the requested memory at the start of the current allocation block. |
| 219 size_t aligned_requested = RoundUp(requested, MemoryChunk::kAlignment); | 220 size_t aligned_requested = RoundUp(requested_size, MemoryChunk::kAlignment); |
| 220 FreeBlock current = allocation_list_[current_allocation_block_index_]; | 221 FreeBlock current = allocation_list_[current_allocation_block_index_]; |
| 221 if (aligned_requested >= (current.size - Page::kPageSize)) { | 222 if (aligned_requested >= (current.size - Page::kPageSize)) { |
| 222 // Don't leave a small free block, useless for a large object or chunk. | 223 // Don't leave a small free block, useless for a large object or chunk. |
| 223 *allocated = current.size; | 224 *allocated = current.size; |
| 224 } else { | 225 } else { |
| 225 *allocated = aligned_requested; | 226 *allocated = aligned_requested; |
| 226 } | 227 } |
| 227 ASSERT(*allocated <= current.size); | 228 ASSERT(*allocated <= current.size); |
| 228 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); | 229 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); |
| 229 if (!MemoryAllocator::CommitCodePage(code_range_, | 230 if (!MemoryAllocator::CommitExecutableMemory(code_range_, |
| 230 current.start, | 231 current.start, |
| 231 *allocated)) { | 232 commit_size, |
| 233 *allocated)) { |
| 232 *allocated = 0; | 234 *allocated = 0; |
| 233 return NULL; | 235 return NULL; |
| 234 } | 236 } |
| 235 allocation_list_[current_allocation_block_index_].start += *allocated; | 237 allocation_list_[current_allocation_block_index_].start += *allocated; |
| 236 allocation_list_[current_allocation_block_index_].size -= *allocated; | 238 allocation_list_[current_allocation_block_index_].size -= *allocated; |
| 237 if (*allocated == current.size) { | 239 if (*allocated == current.size) { |
| 238 GetNextAllocationBlock(0); // This block is used up, get the next one. | 240 GetNextAllocationBlock(0); // This block is used up, get the next one. |
| 239 } | 241 } |
| 240 return current.start; | 242 return current.start; |
| 241 } | 243 } |
| 242 | 244 |
| 243 | 245 |
| 246 bool CodeRange::CommitRawMemory(Address start, size_t length) { |
| 247 return code_range_->Commit(start, length, true); |
| 248 } |
| 249 |
| 250 |
| 251 bool CodeRange::UncommitRawMemory(Address start, size_t length) { |
| 252 return code_range_->Uncommit(start, length); |
| 253 } |
| 254 |
| 255 |
| 244 void CodeRange::FreeRawMemory(Address address, size_t length) { | 256 void CodeRange::FreeRawMemory(Address address, size_t length) { |
| 245 ASSERT(IsAddressAligned(address, MemoryChunk::kAlignment)); | 257 ASSERT(IsAddressAligned(address, MemoryChunk::kAlignment)); |
| 246 free_list_.Add(FreeBlock(address, length)); | 258 free_list_.Add(FreeBlock(address, length)); |
| 247 code_range_->Uncommit(address, length); | 259 code_range_->Uncommit(address, length); |
| 248 } | 260 } |
| 249 | 261 |
| 250 | 262 |
| 251 void CodeRange::TearDown() { | 263 void CodeRange::TearDown() { |
| 252 delete code_range_; // Frees all memory in the virtual memory range. | 264 delete code_range_; // Frees all memory in the virtual memory range. |
| 253 code_range_ = NULL; | 265 code_range_ = NULL; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 357 |
| 346 if (!reservation.IsReserved()) return NULL; | 358 if (!reservation.IsReserved()) return NULL; |
| 347 size_ += reservation.size(); | 359 size_ += reservation.size(); |
| 348 Address base = RoundUp(static_cast<Address>(reservation.address()), | 360 Address base = RoundUp(static_cast<Address>(reservation.address()), |
| 349 alignment); | 361 alignment); |
| 350 controller->TakeControl(&reservation); | 362 controller->TakeControl(&reservation); |
| 351 return base; | 363 return base; |
| 352 } | 364 } |
| 353 | 365 |
| 354 | 366 |
| 355 Address MemoryAllocator::AllocateAlignedMemory(size_t size, | 367 Address MemoryAllocator::AllocateAlignedMemory(size_t reserve_size, |
| 368 size_t commit_size, |
| 356 size_t alignment, | 369 size_t alignment, |
| 357 Executability executable, | 370 Executability executable, |
| 358 VirtualMemory* controller) { | 371 VirtualMemory* controller) { |
| 372 ASSERT(commit_size <= reserve_size); |
| 359 VirtualMemory reservation; | 373 VirtualMemory reservation; |
| 360 Address base = ReserveAlignedMemory(size, alignment, &reservation); | 374 Address base = ReserveAlignedMemory(reserve_size, alignment, &reservation); |
| 361 if (base == NULL) return NULL; | 375 if (base == NULL) return NULL; |
| 362 | 376 |
| 363 if (executable == EXECUTABLE) { | 377 if (executable == EXECUTABLE) { |
| 364 if (!CommitCodePage(&reservation, base, size)) { | 378 if (!CommitExecutableMemory(&reservation, |
| 379 base, |
| 380 commit_size, |
| 381 reserve_size)) { |
| 365 base = NULL; | 382 base = NULL; |
| 366 } | 383 } |
| 367 } else { | 384 } else { |
| 368 if (!reservation.Commit(base, size, false)) { | 385 if (!reservation.Commit(base, commit_size, false)) { |
| 369 base = NULL; | 386 base = NULL; |
| 370 } | 387 } |
| 371 } | 388 } |
| 372 | 389 |
| 373 if (base == NULL) { | 390 if (base == NULL) { |
| 374 // Failed to commit the body. Release the mapping and any partially | 391 // Failed to commit the body. Release the mapping and any partially |
| 375 // commited regions inside it. | 392 // commited regions inside it. |
| 376 reservation.Release(); | 393 reservation.Release(); |
| 377 return NULL; | 394 return NULL; |
| 378 } | 395 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 } | 479 } |
| 463 | 480 |
| 464 if (owner == heap->old_data_space()) { | 481 if (owner == heap->old_data_space()) { |
| 465 chunk->SetFlag(CONTAINS_ONLY_DATA); | 482 chunk->SetFlag(CONTAINS_ONLY_DATA); |
| 466 } | 483 } |
| 467 | 484 |
| 468 return chunk; | 485 return chunk; |
| 469 } | 486 } |
| 470 | 487 |
| 471 | 488 |
| 489 // Commit MemoryChunk area to the requested size. |
| 490 bool MemoryChunk::CommitArea(size_t requested) { |
| 491 size_t guard_size = IsFlagSet(IS_EXECUTABLE) ? |
| 492 MemoryAllocator::CodePageGuardSize() : 0; |
| 493 size_t header_size = area_start() - address() - guard_size; |
| 494 size_t commit_size = RoundUp(header_size + requested, OS::CommitPageSize()); |
| 495 size_t committed_size = RoundUp(header_size + (area_end() - area_start()), |
| 496 OS::CommitPageSize()); |
| 497 |
| 498 if (commit_size > committed_size) { |
| 499 // Commit size should be less or equal than the reserved size. |
| 500 ASSERT(commit_size <= size() - 2 * guard_size); |
| 501 // Append the committed area. |
| 502 Address start = address() + committed_size + guard_size; |
| 503 size_t length = commit_size - committed_size; |
| 504 if (reservation_.IsReserved()) { |
| 505 if (!reservation_.Commit(start, length, IsFlagSet(IS_EXECUTABLE))) { |
| 506 return false; |
| 507 } |
| 508 } else { |
| 509 CodeRange* code_range = heap_->isolate()->code_range(); |
| 510 ASSERT(code_range->exists() && IsFlagSet(IS_EXECUTABLE)); |
| 511 if (!code_range->CommitRawMemory(start, length)) return false; |
| 512 } |
| 513 |
| 514 if (Heap::ShouldZapGarbage()) { |
| 515 heap_->isolate()->memory_allocator()->ZapBlock(start, length); |
| 516 } |
| 517 } else if (commit_size < committed_size) { |
| 518 ASSERT(commit_size > 0); |
| 519 // Shrink the committed area. |
| 520 size_t length = committed_size - commit_size; |
| 521 Address start = address() + committed_size + guard_size - length; |
| 522 if (reservation_.IsReserved()) { |
| 523 if (!reservation_.Uncommit(start, length)) return false; |
| 524 } else { |
| 525 CodeRange* code_range = heap_->isolate()->code_range(); |
| 526 ASSERT(code_range->exists() && IsFlagSet(IS_EXECUTABLE)); |
| 527 if (!code_range->UncommitRawMemory(start, length)) return false; |
| 528 } |
| 529 } |
| 530 |
| 531 area_end_ = area_start_ + requested; |
| 532 return true; |
| 533 } |
| 534 |
| 535 |
| 472 void MemoryChunk::InsertAfter(MemoryChunk* other) { | 536 void MemoryChunk::InsertAfter(MemoryChunk* other) { |
| 473 next_chunk_ = other->next_chunk_; | 537 next_chunk_ = other->next_chunk_; |
| 474 prev_chunk_ = other; | 538 prev_chunk_ = other; |
| 475 other->next_chunk_->prev_chunk_ = this; | 539 other->next_chunk_->prev_chunk_ = this; |
| 476 other->next_chunk_ = this; | 540 other->next_chunk_ = this; |
| 477 } | 541 } |
| 478 | 542 |
| 479 | 543 |
| 480 void MemoryChunk::Unlink() { | 544 void MemoryChunk::Unlink() { |
| 481 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) { | 545 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) { |
| 482 heap_->decrement_scan_on_scavenge_pages(); | 546 heap_->decrement_scan_on_scavenge_pages(); |
| 483 ClearFlag(SCAN_ON_SCAVENGE); | 547 ClearFlag(SCAN_ON_SCAVENGE); |
| 484 } | 548 } |
| 485 next_chunk_->prev_chunk_ = prev_chunk_; | 549 next_chunk_->prev_chunk_ = prev_chunk_; |
| 486 prev_chunk_->next_chunk_ = next_chunk_; | 550 prev_chunk_->next_chunk_ = next_chunk_; |
| 487 prev_chunk_ = NULL; | 551 prev_chunk_ = NULL; |
| 488 next_chunk_ = NULL; | 552 next_chunk_ = NULL; |
| 489 } | 553 } |
| 490 | 554 |
| 491 | 555 |
| 492 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, | 556 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t reserve_area_size, |
| 557 intptr_t commit_area_size, |
| 493 Executability executable, | 558 Executability executable, |
| 494 Space* owner) { | 559 Space* owner) { |
| 560 ASSERT(commit_area_size <= reserve_area_size); |
| 561 |
| 495 size_t chunk_size; | 562 size_t chunk_size; |
| 496 Heap* heap = isolate_->heap(); | 563 Heap* heap = isolate_->heap(); |
| 497 Address base = NULL; | 564 Address base = NULL; |
| 498 VirtualMemory reservation; | 565 VirtualMemory reservation; |
| 499 Address area_start = NULL; | 566 Address area_start = NULL; |
| 500 Address area_end = NULL; | 567 Address area_end = NULL; |
| 501 | 568 |
| 569 // |
| 570 // MemoryChunk layout: |
| 571 // |
| 572 // Executable |
| 573 // +----------------------------+<- base aligned with MemoryChunk::kAlignment |
| 574 // | Header | |
| 575 // +----------------------------+<- base + CodePageGuardStartOffset |
| 576 // | Guard | |
| 577 // +----------------------------+<- area_start_ |
| 578 // | Area | |
| 579 // +----------------------------+<- area_end_ (area_start + commit_area_size) |
| 580 // | Committed but not used | |
| 581 // +----------------------------+<- aligned at OS page boundary |
| 582 // | Reserved but not committed | |
| 583 // +----------------------------+<- aligned at OS page boundary |
| 584 // | Guard | |
| 585 // +----------------------------+<- base + chunk_size |
| 586 // |
| 587 // Non-executable |
| 588 // +----------------------------+<- base aligned with MemoryChunk::kAlignment |
| 589 // | Header | |
| 590 // +----------------------------+<- area_start_ (base + kObjectStartOffset) |
| 591 // | Area | |
| 592 // +----------------------------+<- area_end_ (area_start + commit_area_size) |
| 593 // | Committed but not used | |
| 594 // +----------------------------+<- aligned at OS page boundary |
| 595 // | Reserved but not committed | |
| 596 // +----------------------------+<- base + chunk_size |
| 597 // |
| 598 |
| 502 if (executable == EXECUTABLE) { | 599 if (executable == EXECUTABLE) { |
| 503 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, | 600 chunk_size = RoundUp(CodePageAreaStartOffset() + reserve_area_size, |
| 504 OS::CommitPageSize()) + CodePageGuardSize(); | 601 OS::CommitPageSize()) + CodePageGuardSize(); |
| 505 | 602 |
| 506 // Check executable memory limit. | 603 // Check executable memory limit. |
| 507 if (size_executable_ + chunk_size > capacity_executable_) { | 604 if (size_executable_ + chunk_size > capacity_executable_) { |
| 508 LOG(isolate_, | 605 LOG(isolate_, |
| 509 StringEvent("MemoryAllocator::AllocateRawMemory", | 606 StringEvent("MemoryAllocator::AllocateRawMemory", |
| 510 "V8 Executable Allocation capacity exceeded")); | 607 "V8 Executable Allocation capacity exceeded")); |
| 511 return NULL; | 608 return NULL; |
| 512 } | 609 } |
| 513 | 610 |
| 611 // Size of header (not executable) plus area (executable). |
| 612 size_t commit_size = RoundUp(CodePageGuardStartOffset() + commit_area_size, |
| 613 OS::CommitPageSize()); |
| 514 // Allocate executable memory either from code range or from the | 614 // Allocate executable memory either from code range or from the |
| 515 // OS. | 615 // OS. |
| 516 if (isolate_->code_range()->exists()) { | 616 if (isolate_->code_range()->exists()) { |
| 517 base = isolate_->code_range()->AllocateRawMemory(chunk_size, &chunk_size); | 617 base = isolate_->code_range()->AllocateRawMemory(chunk_size, |
| 618 commit_size, |
| 619 &chunk_size); |
| 518 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), | 620 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), |
| 519 MemoryChunk::kAlignment)); | 621 MemoryChunk::kAlignment)); |
| 520 if (base == NULL) return NULL; | 622 if (base == NULL) return NULL; |
| 521 size_ += chunk_size; | 623 size_ += chunk_size; |
| 522 // Update executable memory size. | 624 // Update executable memory size. |
| 523 size_executable_ += chunk_size; | 625 size_executable_ += chunk_size; |
| 524 } else { | 626 } else { |
| 525 base = AllocateAlignedMemory(chunk_size, | 627 base = AllocateAlignedMemory(chunk_size, |
| 628 commit_size, |
| 526 MemoryChunk::kAlignment, | 629 MemoryChunk::kAlignment, |
| 527 executable, | 630 executable, |
| 528 &reservation); | 631 &reservation); |
| 529 if (base == NULL) return NULL; | 632 if (base == NULL) return NULL; |
| 530 // Update executable memory size. | 633 // Update executable memory size. |
| 531 size_executable_ += reservation.size(); | 634 size_executable_ += reservation.size(); |
| 532 } | 635 } |
| 533 | 636 |
| 534 if (Heap::ShouldZapGarbage()) { | 637 if (Heap::ShouldZapGarbage()) { |
| 535 ZapBlock(base, CodePageGuardStartOffset()); | 638 ZapBlock(base, CodePageGuardStartOffset()); |
| 536 ZapBlock(base + CodePageAreaStartOffset(), body_size); | 639 ZapBlock(base + CodePageAreaStartOffset(), commit_area_size); |
| 537 } | 640 } |
| 538 | 641 |
| 539 area_start = base + CodePageAreaStartOffset(); | 642 area_start = base + CodePageAreaStartOffset(); |
| 540 area_end = area_start + body_size; | 643 area_end = area_start + commit_area_size; |
| 541 } else { | 644 } else { |
| 542 chunk_size = MemoryChunk::kObjectStartOffset + body_size; | 645 chunk_size = RoundUp(MemoryChunk::kObjectStartOffset + reserve_area_size, |
| 646 OS::CommitPageSize()); |
| 647 size_t commit_size = RoundUp(MemoryChunk::kObjectStartOffset + |
| 648 commit_area_size, OS::CommitPageSize()); |
| 543 base = AllocateAlignedMemory(chunk_size, | 649 base = AllocateAlignedMemory(chunk_size, |
| 650 commit_size, |
| 544 MemoryChunk::kAlignment, | 651 MemoryChunk::kAlignment, |
| 545 executable, | 652 executable, |
| 546 &reservation); | 653 &reservation); |
| 547 | 654 |
| 548 if (base == NULL) return NULL; | 655 if (base == NULL) return NULL; |
| 549 | 656 |
| 550 if (Heap::ShouldZapGarbage()) { | 657 if (Heap::ShouldZapGarbage()) { |
| 551 ZapBlock(base, chunk_size); | 658 ZapBlock(base, Page::kObjectStartOffset + commit_area_size); |
| 552 } | 659 } |
| 553 | 660 |
| 554 area_start = base + Page::kObjectStartOffset; | 661 area_start = base + Page::kObjectStartOffset; |
| 555 area_end = base + chunk_size; | 662 area_end = area_start + commit_area_size; |
| 556 } | 663 } |
| 557 | 664 |
| 665 // Use chunk_size for statistics and callbacks because we assume that they |
| 666 // treat reserved but not-yet committed memory regions of chunks as allocated. |
| 558 isolate_->counters()->memory_allocated()-> | 667 isolate_->counters()->memory_allocated()-> |
| 559 Increment(static_cast<int>(chunk_size)); | 668 Increment(static_cast<int>(chunk_size)); |
| 560 | 669 |
| 561 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); | 670 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); |
| 562 if (owner != NULL) { | 671 if (owner != NULL) { |
| 563 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); | 672 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); |
| 564 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); | 673 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); |
| 565 } | 674 } |
| 566 | 675 |
| 567 MemoryChunk* result = MemoryChunk::Initialize(heap, | 676 MemoryChunk* result = MemoryChunk::Initialize(heap, |
| 568 base, | 677 base, |
| 569 chunk_size, | 678 chunk_size, |
| 570 area_start, | 679 area_start, |
| 571 area_end, | 680 area_end, |
| 572 executable, | 681 executable, |
| 573 owner); | 682 owner); |
| 574 result->set_reserved_memory(&reservation); | 683 result->set_reserved_memory(&reservation); |
| 575 return result; | 684 return result; |
| 576 } | 685 } |
| 577 | 686 |
| 578 | 687 |
| 579 Page* MemoryAllocator::AllocatePage(intptr_t size, | 688 Page* MemoryAllocator::AllocatePage(intptr_t size, |
| 580 PagedSpace* owner, | 689 PagedSpace* owner, |
| 581 Executability executable) { | 690 Executability executable) { |
| 582 MemoryChunk* chunk = AllocateChunk(size, executable, owner); | 691 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner); |
| 583 | 692 |
| 584 if (chunk == NULL) return NULL; | 693 if (chunk == NULL) return NULL; |
| 585 | 694 |
| 586 return Page::Initialize(isolate_->heap(), chunk, executable, owner); | 695 return Page::Initialize(isolate_->heap(), chunk, executable, owner); |
| 587 } | 696 } |
| 588 | 697 |
| 589 | 698 |
| 590 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size, | 699 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size, |
| 591 Space* owner, | 700 Space* owner, |
| 592 Executability executable) { | 701 Executability executable) { |
| 593 MemoryChunk* chunk = AllocateChunk(object_size, executable, owner); | 702 MemoryChunk* chunk = AllocateChunk(object_size, |
| 703 object_size, |
| 704 executable, |
| 705 owner); |
| 594 if (chunk == NULL) return NULL; | 706 if (chunk == NULL) return NULL; |
| 595 return LargePage::Initialize(isolate_->heap(), chunk); | 707 return LargePage::Initialize(isolate_->heap(), chunk); |
| 596 } | 708 } |
| 597 | 709 |
| 598 | 710 |
| 599 void MemoryAllocator::Free(MemoryChunk* chunk) { | 711 void MemoryAllocator::Free(MemoryChunk* chunk) { |
| 600 LOG(isolate_, DeleteEvent("MemoryChunk", chunk)); | 712 LOG(isolate_, DeleteEvent("MemoryChunk", chunk)); |
| 601 if (chunk->owner() != NULL) { | 713 if (chunk->owner() != NULL) { |
| 602 ObjectSpace space = | 714 ObjectSpace space = |
| 603 static_cast<ObjectSpace>(1 << chunk->owner()->identity()); | 715 static_cast<ObjectSpace>(1 << chunk->owner()->identity()); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 } | 837 } |
| 726 | 838 |
| 727 | 839 |
| 728 int MemoryAllocator::CodePageAreaEndOffset() { | 840 int MemoryAllocator::CodePageAreaEndOffset() { |
| 729 // We are guarding code pages: the last OS page will be protected as | 841 // We are guarding code pages: the last OS page will be protected as |
| 730 // non-writable. | 842 // non-writable. |
| 731 return Page::kPageSize - static_cast<int>(OS::CommitPageSize()); | 843 return Page::kPageSize - static_cast<int>(OS::CommitPageSize()); |
| 732 } | 844 } |
| 733 | 845 |
| 734 | 846 |
| 735 bool MemoryAllocator::CommitCodePage(VirtualMemory* vm, | 847 bool MemoryAllocator::CommitExecutableMemory(VirtualMemory* vm, |
| 736 Address start, | 848 Address start, |
| 737 size_t size) { | 849 size_t commit_size, |
| 850 size_t reserved_size) { |
| 738 // Commit page header (not executable). | 851 // Commit page header (not executable). |
| 739 if (!vm->Commit(start, | 852 if (!vm->Commit(start, |
| 740 CodePageGuardStartOffset(), | 853 CodePageGuardStartOffset(), |
| 741 false)) { | 854 false)) { |
| 742 return false; | 855 return false; |
| 743 } | 856 } |
| 744 | 857 |
| 745 // Create guard page after the header. | 858 // Create guard page after the header. |
| 746 if (!vm->Guard(start + CodePageGuardStartOffset())) { | 859 if (!vm->Guard(start + CodePageGuardStartOffset())) { |
| 747 return false; | 860 return false; |
| 748 } | 861 } |
| 749 | 862 |
| 750 // Commit page body (executable). | 863 // Commit page body (executable). |
| 751 size_t area_size = size - CodePageAreaStartOffset() - CodePageGuardSize(); | |
| 752 if (!vm->Commit(start + CodePageAreaStartOffset(), | 864 if (!vm->Commit(start + CodePageAreaStartOffset(), |
| 753 area_size, | 865 commit_size - CodePageGuardStartOffset(), |
| 754 true)) { | 866 true)) { |
| 755 return false; | 867 return false; |
| 756 } | 868 } |
| 757 | 869 |
| 758 // Create guard page after the allocatable area. | 870 // Create guard page before the end. |
| 759 if (!vm->Guard(start + CodePageAreaStartOffset() + area_size)) { | 871 if (!vm->Guard(start + reserved_size - CodePageGuardSize())) { |
| 760 return false; | 872 return false; |
| 761 } | 873 } |
| 762 | 874 |
| 763 return true; | 875 return true; |
| 764 } | 876 } |
| 765 | 877 |
| 766 | 878 |
| 767 // ----------------------------------------------------------------------------- | 879 // ----------------------------------------------------------------------------- |
| 768 // MemoryChunk implementation | 880 // MemoryChunk implementation |
| 769 | 881 |
| (...skipping 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2985 object->ShortPrint(); | 3097 object->ShortPrint(); |
| 2986 PrintF("\n"); | 3098 PrintF("\n"); |
| 2987 } | 3099 } |
| 2988 printf(" --------------------------------------\n"); | 3100 printf(" --------------------------------------\n"); |
| 2989 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3101 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 2990 } | 3102 } |
| 2991 | 3103 |
| 2992 #endif // DEBUG | 3104 #endif // DEBUG |
| 2993 | 3105 |
| 2994 } } // namespace v8::internal | 3106 } } // namespace v8::internal |
| OLD | NEW |