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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 | 68 |
69 HeapObjectIterator::HeapObjectIterator(Page* page, | 69 HeapObjectIterator::HeapObjectIterator(Page* page, |
70 HeapObjectCallback size_func) { | 70 HeapObjectCallback size_func) { |
71 Space* owner = page->owner(); | 71 Space* owner = page->owner(); |
72 ASSERT(owner == HEAP->old_pointer_space() || | 72 ASSERT(owner == HEAP->old_pointer_space() || |
73 owner == HEAP->old_data_space() || | 73 owner == HEAP->old_data_space() || |
74 owner == HEAP->map_space() || | 74 owner == HEAP->map_space() || |
75 owner == HEAP->cell_space() || | 75 owner == HEAP->cell_space() || |
76 owner == HEAP->code_space()); | 76 owner == HEAP->code_space()); |
77 Initialize(reinterpret_cast<PagedSpace*>(owner), | 77 Initialize(reinterpret_cast<PagedSpace*>(owner), |
78 page->ObjectAreaStart(), | 78 page->area_start(), |
79 page->ObjectAreaEnd(), | 79 page->area_end(), |
80 kOnePageOnly, | 80 kOnePageOnly, |
81 size_func); | 81 size_func); |
82 ASSERT(page->WasSweptPrecisely()); | 82 ASSERT(page->WasSweptPrecisely()); |
83 } | 83 } |
84 | 84 |
85 | 85 |
86 void HeapObjectIterator::Initialize(PagedSpace* space, | 86 void HeapObjectIterator::Initialize(PagedSpace* space, |
87 Address cur, Address end, | 87 Address cur, Address end, |
88 HeapObjectIterator::PageMode mode, | 88 HeapObjectIterator::PageMode mode, |
89 HeapObjectCallback size_f) { | 89 HeapObjectCallback size_f) { |
(...skipping 11 matching lines...) Expand all Loading... |
101 // We have hit the end of the page and should advance to the next block of | 101 // We have hit the end of the page and should advance to the next block of |
102 // objects. This happens at the end of the page. | 102 // objects. This happens at the end of the page. |
103 bool HeapObjectIterator::AdvanceToNextPage() { | 103 bool HeapObjectIterator::AdvanceToNextPage() { |
104 ASSERT(cur_addr_ == cur_end_); | 104 ASSERT(cur_addr_ == cur_end_); |
105 if (page_mode_ == kOnePageOnly) return false; | 105 if (page_mode_ == kOnePageOnly) return false; |
106 Page* cur_page; | 106 Page* cur_page; |
107 if (cur_addr_ == NULL) { | 107 if (cur_addr_ == NULL) { |
108 cur_page = space_->anchor(); | 108 cur_page = space_->anchor(); |
109 } else { | 109 } else { |
110 cur_page = Page::FromAddress(cur_addr_ - 1); | 110 cur_page = Page::FromAddress(cur_addr_ - 1); |
111 ASSERT(cur_addr_ == cur_page->ObjectAreaEnd()); | 111 ASSERT(cur_addr_ == cur_page->area_end()); |
112 } | 112 } |
113 cur_page = cur_page->next_page(); | 113 cur_page = cur_page->next_page(); |
114 if (cur_page == space_->anchor()) return false; | 114 if (cur_page == space_->anchor()) return false; |
115 cur_addr_ = cur_page->ObjectAreaStart(); | 115 cur_addr_ = cur_page->area_start(); |
116 cur_end_ = cur_page->ObjectAreaEnd(); | 116 cur_end_ = cur_page->area_end(); |
117 ASSERT(cur_page->WasSweptPrecisely()); | 117 ASSERT(cur_page->WasSweptPrecisely()); |
118 return true; | 118 return true; |
119 } | 119 } |
120 | 120 |
121 | 121 |
122 // ----------------------------------------------------------------------------- | 122 // ----------------------------------------------------------------------------- |
123 // CodeRange | 123 // CodeRange |
124 | 124 |
125 | 125 |
126 CodeRange::CodeRange(Isolate* isolate) | 126 CodeRange::CodeRange(Isolate* isolate) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 size_t aligned_requested = RoundUp(requested, MemoryChunk::kAlignment); | 220 size_t aligned_requested = RoundUp(requested, MemoryChunk::kAlignment); |
221 FreeBlock current = allocation_list_[current_allocation_block_index_]; | 221 FreeBlock current = allocation_list_[current_allocation_block_index_]; |
222 if (aligned_requested >= (current.size - Page::kPageSize)) { | 222 if (aligned_requested >= (current.size - Page::kPageSize)) { |
223 // 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. |
224 *allocated = current.size; | 224 *allocated = current.size; |
225 } else { | 225 } else { |
226 *allocated = aligned_requested; | 226 *allocated = aligned_requested; |
227 } | 227 } |
228 ASSERT(*allocated <= current.size); | 228 ASSERT(*allocated <= current.size); |
229 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); | 229 ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); |
230 if (!code_range_->Commit(current.start, *allocated, true)) { | 230 if (!MemoryAllocator::CommitCodePage(code_range_, |
| 231 current.start, |
| 232 *allocated)) { |
231 *allocated = 0; | 233 *allocated = 0; |
232 return NULL; | 234 return NULL; |
233 } | 235 } |
234 allocation_list_[current_allocation_block_index_].start += *allocated; | 236 allocation_list_[current_allocation_block_index_].start += *allocated; |
235 allocation_list_[current_allocation_block_index_].size -= *allocated; | 237 allocation_list_[current_allocation_block_index_].size -= *allocated; |
236 if (*allocated == current.size) { | 238 if (*allocated == current.size) { |
237 GetNextAllocationBlock(0); // This block is used up, get the next one. | 239 GetNextAllocationBlock(0); // This block is used up, get the next one. |
238 } | 240 } |
239 return current.start; | 241 return current.start; |
240 } | 242 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 } | 353 } |
352 | 354 |
353 | 355 |
354 Address MemoryAllocator::AllocateAlignedMemory(size_t size, | 356 Address MemoryAllocator::AllocateAlignedMemory(size_t size, |
355 size_t alignment, | 357 size_t alignment, |
356 Executability executable, | 358 Executability executable, |
357 VirtualMemory* controller) { | 359 VirtualMemory* controller) { |
358 VirtualMemory reservation; | 360 VirtualMemory reservation; |
359 Address base = ReserveAlignedMemory(size, alignment, &reservation); | 361 Address base = ReserveAlignedMemory(size, alignment, &reservation); |
360 if (base == NULL) return NULL; | 362 if (base == NULL) return NULL; |
361 if (!reservation.Commit(base, | 363 |
362 size, | 364 if (executable == EXECUTABLE) { |
363 executable == EXECUTABLE)) { | 365 CommitCodePage(&reservation, base, size); |
364 return NULL; | 366 } else { |
| 367 if (!reservation.Commit(base, |
| 368 size, |
| 369 executable == EXECUTABLE)) { |
| 370 return NULL; |
| 371 } |
365 } | 372 } |
| 373 |
366 controller->TakeControl(&reservation); | 374 controller->TakeControl(&reservation); |
367 return base; | 375 return base; |
368 } | 376 } |
369 | 377 |
370 | 378 |
371 void Page::InitializeAsAnchor(PagedSpace* owner) { | 379 void Page::InitializeAsAnchor(PagedSpace* owner) { |
372 set_owner(owner); | 380 set_owner(owner); |
373 set_prev_page(this); | 381 set_prev_page(this); |
374 set_next_page(this); | 382 set_next_page(this); |
375 } | 383 } |
376 | 384 |
377 | 385 |
378 NewSpacePage* NewSpacePage::Initialize(Heap* heap, | 386 NewSpacePage* NewSpacePage::Initialize(Heap* heap, |
379 Address start, | 387 Address start, |
380 SemiSpace* semi_space) { | 388 SemiSpace* semi_space) { |
| 389 Address area_start = start + NewSpacePage::kObjectStartOffset; |
| 390 Address area_end = start + Page::kPageSize; |
| 391 |
381 MemoryChunk* chunk = MemoryChunk::Initialize(heap, | 392 MemoryChunk* chunk = MemoryChunk::Initialize(heap, |
382 start, | 393 start, |
383 Page::kPageSize, | 394 Page::kPageSize, |
| 395 area_start, |
| 396 area_end, |
384 NOT_EXECUTABLE, | 397 NOT_EXECUTABLE, |
385 semi_space); | 398 semi_space); |
386 chunk->set_next_chunk(NULL); | 399 chunk->set_next_chunk(NULL); |
387 chunk->set_prev_chunk(NULL); | 400 chunk->set_prev_chunk(NULL); |
388 chunk->initialize_scan_on_scavenge(true); | 401 chunk->initialize_scan_on_scavenge(true); |
389 bool in_to_space = (semi_space->id() != kFromSpace); | 402 bool in_to_space = (semi_space->id() != kFromSpace); |
390 chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE | 403 chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE |
391 : MemoryChunk::IN_FROM_SPACE); | 404 : MemoryChunk::IN_FROM_SPACE); |
392 ASSERT(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE | 405 ASSERT(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE |
393 : MemoryChunk::IN_TO_SPACE)); | 406 : MemoryChunk::IN_TO_SPACE)); |
394 NewSpacePage* page = static_cast<NewSpacePage*>(chunk); | 407 NewSpacePage* page = static_cast<NewSpacePage*>(chunk); |
395 heap->incremental_marking()->SetNewSpacePageFlags(page); | 408 heap->incremental_marking()->SetNewSpacePageFlags(page); |
396 return page; | 409 return page; |
397 } | 410 } |
398 | 411 |
399 | 412 |
400 void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) { | 413 void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) { |
401 set_owner(semi_space); | 414 set_owner(semi_space); |
402 set_next_chunk(this); | 415 set_next_chunk(this); |
403 set_prev_chunk(this); | 416 set_prev_chunk(this); |
404 // Flags marks this invalid page as not being in new-space. | 417 // Flags marks this invalid page as not being in new-space. |
405 // All real new-space pages will be in new-space. | 418 // All real new-space pages will be in new-space. |
406 SetFlags(0, ~0); | 419 SetFlags(0, ~0); |
407 } | 420 } |
408 | 421 |
409 | 422 |
410 MemoryChunk* MemoryChunk::Initialize(Heap* heap, | 423 MemoryChunk* MemoryChunk::Initialize(Heap* heap, |
411 Address base, | 424 Address base, |
412 size_t size, | 425 size_t size, |
| 426 Address area_start, |
| 427 Address area_end, |
413 Executability executable, | 428 Executability executable, |
414 Space* owner) { | 429 Space* owner) { |
415 MemoryChunk* chunk = FromAddress(base); | 430 MemoryChunk* chunk = FromAddress(base); |
416 | 431 |
417 ASSERT(base == chunk->address()); | 432 ASSERT(base == chunk->address()); |
418 | 433 |
419 chunk->heap_ = heap; | 434 chunk->heap_ = heap; |
420 chunk->size_ = size; | 435 chunk->size_ = size; |
| 436 chunk->area_start_ = area_start; |
| 437 chunk->area_end_ = area_end; |
421 chunk->flags_ = 0; | 438 chunk->flags_ = 0; |
422 chunk->set_owner(owner); | 439 chunk->set_owner(owner); |
423 chunk->InitializeReservedMemory(); | 440 chunk->InitializeReservedMemory(); |
424 chunk->slots_buffer_ = NULL; | 441 chunk->slots_buffer_ = NULL; |
425 chunk->skip_list_ = NULL; | 442 chunk->skip_list_ = NULL; |
426 chunk->ResetLiveBytes(); | 443 chunk->ResetLiveBytes(); |
427 Bitmap::Clear(chunk); | 444 Bitmap::Clear(chunk); |
428 chunk->initialize_scan_on_scavenge(false); | 445 chunk->initialize_scan_on_scavenge(false); |
429 chunk->SetFlag(WAS_SWEPT_PRECISELY); | 446 chunk->SetFlag(WAS_SWEPT_PRECISELY); |
430 | 447 |
431 ASSERT(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); | 448 ASSERT(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); |
432 ASSERT(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); | 449 ASSERT(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); |
433 | 450 |
434 if (executable == EXECUTABLE) chunk->SetFlag(IS_EXECUTABLE); | 451 if (executable == EXECUTABLE) { |
| 452 chunk->SetFlag(IS_EXECUTABLE); |
| 453 } |
435 | 454 |
436 if (owner == heap->old_data_space()) chunk->SetFlag(CONTAINS_ONLY_DATA); | 455 if (owner == heap->old_data_space()) { |
| 456 chunk->SetFlag(CONTAINS_ONLY_DATA); |
| 457 } |
437 | 458 |
438 return chunk; | 459 return chunk; |
439 } | 460 } |
440 | 461 |
441 | 462 |
442 void MemoryChunk::InsertAfter(MemoryChunk* other) { | 463 void MemoryChunk::InsertAfter(MemoryChunk* other) { |
443 next_chunk_ = other->next_chunk_; | 464 next_chunk_ = other->next_chunk_; |
444 prev_chunk_ = other; | 465 prev_chunk_ = other; |
445 other->next_chunk_->prev_chunk_ = this; | 466 other->next_chunk_->prev_chunk_ = this; |
446 other->next_chunk_ = this; | 467 other->next_chunk_ = this; |
447 } | 468 } |
448 | 469 |
449 | 470 |
450 void MemoryChunk::Unlink() { | 471 void MemoryChunk::Unlink() { |
451 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) { | 472 if (!InNewSpace() && IsFlagSet(SCAN_ON_SCAVENGE)) { |
452 heap_->decrement_scan_on_scavenge_pages(); | 473 heap_->decrement_scan_on_scavenge_pages(); |
453 ClearFlag(SCAN_ON_SCAVENGE); | 474 ClearFlag(SCAN_ON_SCAVENGE); |
454 } | 475 } |
455 next_chunk_->prev_chunk_ = prev_chunk_; | 476 next_chunk_->prev_chunk_ = prev_chunk_; |
456 prev_chunk_->next_chunk_ = next_chunk_; | 477 prev_chunk_->next_chunk_ = next_chunk_; |
457 prev_chunk_ = NULL; | 478 prev_chunk_ = NULL; |
458 next_chunk_ = NULL; | 479 next_chunk_ = NULL; |
459 } | 480 } |
460 | 481 |
461 | 482 |
462 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, | 483 MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, |
463 Executability executable, | 484 Executability executable, |
464 Space* owner) { | 485 Space* owner) { |
465 size_t chunk_size = MemoryChunk::kObjectStartOffset + body_size; | 486 size_t chunk_size; |
466 Heap* heap = isolate_->heap(); | 487 Heap* heap = isolate_->heap(); |
467 Address base = NULL; | 488 Address base = NULL; |
468 VirtualMemory reservation; | 489 VirtualMemory reservation; |
| 490 Address area_start = NULL; |
| 491 Address area_end = NULL; |
469 if (executable == EXECUTABLE) { | 492 if (executable == EXECUTABLE) { |
| 493 chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, |
| 494 OS::CommitPageSize()) + CodePageGuardSize(); |
| 495 |
470 // Check executable memory limit. | 496 // Check executable memory limit. |
471 if (size_executable_ + chunk_size > capacity_executable_) { | 497 if (size_executable_ + chunk_size > capacity_executable_) { |
472 LOG(isolate_, | 498 LOG(isolate_, |
473 StringEvent("MemoryAllocator::AllocateRawMemory", | 499 StringEvent("MemoryAllocator::AllocateRawMemory", |
474 "V8 Executable Allocation capacity exceeded")); | 500 "V8 Executable Allocation capacity exceeded")); |
475 return NULL; | 501 return NULL; |
476 } | 502 } |
477 | 503 |
478 // Allocate executable memory either from code range or from the | 504 // Allocate executable memory either from code range or from the |
479 // OS. | 505 // OS. |
480 if (isolate_->code_range()->exists()) { | 506 if (isolate_->code_range()->exists()) { |
481 base = isolate_->code_range()->AllocateRawMemory(chunk_size, &chunk_size); | 507 base = isolate_->code_range()->AllocateRawMemory(chunk_size, &chunk_size); |
482 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), | 508 ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), |
483 MemoryChunk::kAlignment)); | 509 MemoryChunk::kAlignment)); |
484 if (base == NULL) return NULL; | 510 if (base == NULL) return NULL; |
485 size_ += chunk_size; | 511 size_ += chunk_size; |
486 // Update executable memory size. | 512 // Update executable memory size. |
487 size_executable_ += chunk_size; | 513 size_executable_ += chunk_size; |
488 } else { | 514 } else { |
489 base = AllocateAlignedMemory(chunk_size, | 515 base = AllocateAlignedMemory(chunk_size, |
490 MemoryChunk::kAlignment, | 516 MemoryChunk::kAlignment, |
491 executable, | 517 executable, |
492 &reservation); | 518 &reservation); |
493 if (base == NULL) return NULL; | 519 if (base == NULL) return NULL; |
494 // Update executable memory size. | 520 // Update executable memory size. |
495 size_executable_ += reservation.size(); | 521 size_executable_ += reservation.size(); |
496 } | 522 } |
| 523 |
| 524 #ifdef DEBUG |
| 525 ZapBlock(base, CodePageGuardStartOffset()); |
| 526 ZapBlock(base + CodePageAreaStartOffset(), body_size); |
| 527 #endif |
| 528 area_start = base + CodePageAreaStartOffset(); |
| 529 area_end = area_start + body_size; |
497 } else { | 530 } else { |
| 531 chunk_size = MemoryChunk::kObjectStartOffset + body_size; |
498 base = AllocateAlignedMemory(chunk_size, | 532 base = AllocateAlignedMemory(chunk_size, |
499 MemoryChunk::kAlignment, | 533 MemoryChunk::kAlignment, |
500 executable, | 534 executable, |
501 &reservation); | 535 &reservation); |
502 | 536 |
503 if (base == NULL) return NULL; | 537 if (base == NULL) return NULL; |
| 538 |
| 539 #ifdef DEBUG |
| 540 ZapBlock(base, chunk_size); |
| 541 #endif |
| 542 |
| 543 area_start = base + Page::kObjectStartOffset; |
| 544 area_end = base + chunk_size; |
504 } | 545 } |
505 | 546 |
506 #ifdef DEBUG | |
507 ZapBlock(base, chunk_size); | |
508 #endif | |
509 isolate_->counters()->memory_allocated()-> | 547 isolate_->counters()->memory_allocated()-> |
510 Increment(static_cast<int>(chunk_size)); | 548 Increment(static_cast<int>(chunk_size)); |
511 | 549 |
512 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); | 550 LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size)); |
513 if (owner != NULL) { | 551 if (owner != NULL) { |
514 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); | 552 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); |
515 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); | 553 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); |
516 } | 554 } |
517 | 555 |
518 MemoryChunk* result = MemoryChunk::Initialize(heap, | 556 MemoryChunk* result = MemoryChunk::Initialize(heap, |
519 base, | 557 base, |
520 chunk_size, | 558 chunk_size, |
| 559 area_start, |
| 560 area_end, |
521 executable, | 561 executable, |
522 owner); | 562 owner); |
523 result->set_reserved_memory(&reservation); | 563 result->set_reserved_memory(&reservation); |
524 return result; | 564 return result; |
525 } | 565 } |
526 | 566 |
527 | 567 |
528 Page* MemoryAllocator::AllocatePage(PagedSpace* owner, | 568 Page* MemoryAllocator::AllocatePage(PagedSpace* owner, |
529 Executability executable) { | 569 Executability executable) { |
530 MemoryChunk* chunk = AllocateChunk(Page::kObjectAreaSize, executable, owner); | 570 MemoryChunk* chunk = AllocateChunk(owner->AreaSize(), |
| 571 executable, |
| 572 owner); |
531 | 573 |
532 if (chunk == NULL) return NULL; | 574 if (chunk == NULL) return NULL; |
533 | 575 |
534 return Page::Initialize(isolate_->heap(), chunk, executable, owner); | 576 return Page::Initialize(isolate_->heap(), chunk, executable, owner); |
535 } | 577 } |
536 | 578 |
537 | 579 |
538 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size, | 580 LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size, |
539 Executability executable, | 581 Executability executable, |
540 Space* owner) { | 582 Space* owner) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 #ifdef DEBUG | 683 #ifdef DEBUG |
642 void MemoryAllocator::ReportStatistics() { | 684 void MemoryAllocator::ReportStatistics() { |
643 float pct = static_cast<float>(capacity_ - size_) / capacity_; | 685 float pct = static_cast<float>(capacity_ - size_) / capacity_; |
644 PrintF(" capacity: %" V8_PTR_PREFIX "d" | 686 PrintF(" capacity: %" V8_PTR_PREFIX "d" |
645 ", used: %" V8_PTR_PREFIX "d" | 687 ", used: %" V8_PTR_PREFIX "d" |
646 ", available: %%%d\n\n", | 688 ", available: %%%d\n\n", |
647 capacity_, size_, static_cast<int>(pct*100)); | 689 capacity_, size_, static_cast<int>(pct*100)); |
648 } | 690 } |
649 #endif | 691 #endif |
650 | 692 |
| 693 |
| 694 int MemoryAllocator::CodePageGuardStartOffset() { |
| 695 // We are guarding code pages: the first OS page after the header |
| 696 // will be protected as non-writable. |
| 697 return RoundUp(Page::kObjectStartOffset, OS::CommitPageSize()); |
| 698 } |
| 699 |
| 700 |
| 701 int MemoryAllocator::CodePageGuardSize() { |
| 702 return OS::CommitPageSize(); |
| 703 } |
| 704 |
| 705 |
| 706 int MemoryAllocator::CodePageAreaStartOffset() { |
| 707 // We are guarding code pages: the first OS page after the header |
| 708 // will be protected as non-writable. |
| 709 return CodePageGuardStartOffset() + CodePageGuardSize(); |
| 710 } |
| 711 |
| 712 |
| 713 int MemoryAllocator::CodePageAreaEndOffset() { |
| 714 // We are guarding code pages: the last OS page will be protected as |
| 715 // non-writable. |
| 716 return Page::kPageSize - OS::CommitPageSize(); |
| 717 } |
| 718 |
| 719 |
| 720 bool MemoryAllocator::CommitCodePage(VirtualMemory* vm, |
| 721 Address start, |
| 722 size_t size) { |
| 723 // Commit page header (not executable). |
| 724 if (!vm->Commit(start, |
| 725 CodePageGuardStartOffset(), |
| 726 false)) { |
| 727 return false; |
| 728 } |
| 729 |
| 730 // Create guard page after the header. |
| 731 if (!vm->Guard(start + CodePageGuardStartOffset())) { |
| 732 return false; |
| 733 } |
| 734 |
| 735 // Commit page body (executable). |
| 736 size_t area_size = size - CodePageAreaStartOffset() - CodePageGuardSize(); |
| 737 if (!vm->Commit(start + CodePageAreaStartOffset(), |
| 738 area_size, |
| 739 true)) { |
| 740 return false; |
| 741 } |
| 742 |
| 743 // Create guard page after the allocatable area. |
| 744 if (!vm->Guard(start + CodePageAreaStartOffset() + area_size)) { |
| 745 return false; |
| 746 } |
| 747 |
| 748 return true; |
| 749 } |
| 750 |
| 751 |
651 // ----------------------------------------------------------------------------- | 752 // ----------------------------------------------------------------------------- |
652 // MemoryChunk implementation | 753 // MemoryChunk implementation |
653 | 754 |
654 void MemoryChunk::IncrementLiveBytesFromMutator(Address address, int by) { | 755 void MemoryChunk::IncrementLiveBytesFromMutator(Address address, int by) { |
655 MemoryChunk* chunk = MemoryChunk::FromAddress(address); | 756 MemoryChunk* chunk = MemoryChunk::FromAddress(address); |
656 if (!chunk->InNewSpace() && !static_cast<Page*>(chunk)->WasSwept()) { | 757 if (!chunk->InNewSpace() && !static_cast<Page*>(chunk)->WasSwept()) { |
657 static_cast<PagedSpace*>(chunk->owner())->IncrementUnsweptFreeBytes(-by); | 758 static_cast<PagedSpace*>(chunk->owner())->IncrementUnsweptFreeBytes(-by); |
658 } | 759 } |
659 chunk->IncrementLiveBytes(by); | 760 chunk->IncrementLiveBytes(by); |
660 } | 761 } |
661 | 762 |
662 // ----------------------------------------------------------------------------- | 763 // ----------------------------------------------------------------------------- |
663 // PagedSpace implementation | 764 // PagedSpace implementation |
664 | 765 |
665 PagedSpace::PagedSpace(Heap* heap, | 766 PagedSpace::PagedSpace(Heap* heap, |
666 intptr_t max_capacity, | 767 intptr_t max_capacity, |
667 AllocationSpace id, | 768 AllocationSpace id, |
668 Executability executable) | 769 Executability executable) |
669 : Space(heap, id, executable), | 770 : Space(heap, id, executable), |
670 free_list_(this), | 771 free_list_(this), |
671 was_swept_conservatively_(false), | 772 was_swept_conservatively_(false), |
672 first_unswept_page_(Page::FromAddress(NULL)), | 773 first_unswept_page_(Page::FromAddress(NULL)), |
673 unswept_free_bytes_(0) { | 774 unswept_free_bytes_(0) { |
| 775 if (id == CODE_SPACE) { |
| 776 area_size_ = heap->isolate()->memory_allocator()-> |
| 777 CodePageAreaSize(); |
| 778 } else { |
| 779 area_size_ = Page::kPageSize - Page::kObjectStartOffset; |
| 780 } |
674 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) | 781 max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) |
675 * Page::kObjectAreaSize; | 782 * AreaSize(); |
676 accounting_stats_.Clear(); | 783 accounting_stats_.Clear(); |
677 | 784 |
678 allocation_info_.top = NULL; | 785 allocation_info_.top = NULL; |
679 allocation_info_.limit = NULL; | 786 allocation_info_.limit = NULL; |
680 | 787 |
681 anchor_.InitializeAsAnchor(this); | 788 anchor_.InitializeAsAnchor(this); |
682 } | 789 } |
683 | 790 |
684 | 791 |
685 bool PagedSpace::SetUp() { | 792 bool PagedSpace::SetUp() { |
(...skipping 29 matching lines...) Expand all Loading... |
715 Address cur = obj->address(); | 822 Address cur = obj->address(); |
716 Address next = cur + obj->Size(); | 823 Address next = cur + obj->Size(); |
717 if ((cur <= addr) && (addr < next)) return obj; | 824 if ((cur <= addr) && (addr < next)) return obj; |
718 } | 825 } |
719 | 826 |
720 UNREACHABLE(); | 827 UNREACHABLE(); |
721 return Failure::Exception(); | 828 return Failure::Exception(); |
722 } | 829 } |
723 | 830 |
724 bool PagedSpace::CanExpand() { | 831 bool PagedSpace::CanExpand() { |
725 ASSERT(max_capacity_ % Page::kObjectAreaSize == 0); | 832 ASSERT(max_capacity_ % AreaSize() == 0); |
726 ASSERT(Capacity() % Page::kObjectAreaSize == 0); | 833 ASSERT(Capacity() % AreaSize() == 0); |
727 | 834 |
728 if (Capacity() == max_capacity_) return false; | 835 if (Capacity() == max_capacity_) return false; |
729 | 836 |
730 ASSERT(Capacity() < max_capacity_); | 837 ASSERT(Capacity() < max_capacity_); |
731 | 838 |
732 // Are we going to exceed capacity for this space? | 839 // Are we going to exceed capacity for this space? |
733 if ((Capacity() + Page::kPageSize) > max_capacity_) return false; | 840 if ((Capacity() + Page::kPageSize) > max_capacity_) return false; |
734 | 841 |
735 return true; | 842 return true; |
736 } | 843 } |
(...skipping 19 matching lines...) Expand all Loading... |
756 while (it.has_next()) { | 863 while (it.has_next()) { |
757 it.next(); | 864 it.next(); |
758 count++; | 865 count++; |
759 } | 866 } |
760 return count; | 867 return count; |
761 } | 868 } |
762 | 869 |
763 | 870 |
764 void PagedSpace::ReleasePage(Page* page) { | 871 void PagedSpace::ReleasePage(Page* page) { |
765 ASSERT(page->LiveBytes() == 0); | 872 ASSERT(page->LiveBytes() == 0); |
| 873 ASSERT(AreaSize() == page->area_size()); |
766 | 874 |
767 // Adjust list of unswept pages if the page is the head of the list. | 875 // Adjust list of unswept pages if the page is the head of the list. |
768 if (first_unswept_page_ == page) { | 876 if (first_unswept_page_ == page) { |
769 first_unswept_page_ = page->next_page(); | 877 first_unswept_page_ = page->next_page(); |
770 if (first_unswept_page_ == anchor()) { | 878 if (first_unswept_page_ == anchor()) { |
771 first_unswept_page_ = Page::FromAddress(NULL); | 879 first_unswept_page_ = Page::FromAddress(NULL); |
772 } | 880 } |
773 } | 881 } |
774 | 882 |
775 if (page->WasSwept()) { | 883 if (page->WasSwept()) { |
776 intptr_t size = free_list_.EvictFreeListItems(page); | 884 intptr_t size = free_list_.EvictFreeListItems(page); |
777 accounting_stats_.AllocateBytes(size); | 885 accounting_stats_.AllocateBytes(size); |
778 ASSERT_EQ(Page::kObjectAreaSize, static_cast<int>(size)); | 886 ASSERT_EQ(AreaSize(), static_cast<int>(size)); |
779 } else { | 887 } else { |
780 DecreaseUnsweptFreeBytes(page); | 888 DecreaseUnsweptFreeBytes(page); |
781 } | 889 } |
782 | 890 |
783 if (Page::FromAllocationTop(allocation_info_.top) == page) { | 891 if (Page::FromAllocationTop(allocation_info_.top) == page) { |
784 allocation_info_.top = allocation_info_.limit = NULL; | 892 allocation_info_.top = allocation_info_.limit = NULL; |
785 } | 893 } |
786 | 894 |
787 page->Unlink(); | 895 page->Unlink(); |
788 if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { | 896 if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { |
789 heap()->isolate()->memory_allocator()->Free(page); | 897 heap()->isolate()->memory_allocator()->Free(page); |
790 } else { | 898 } else { |
791 heap()->QueueMemoryChunkForFree(page); | 899 heap()->QueueMemoryChunkForFree(page); |
792 } | 900 } |
793 | 901 |
794 ASSERT(Capacity() > 0); | 902 ASSERT(Capacity() > 0); |
795 ASSERT(Capacity() % Page::kObjectAreaSize == 0); | 903 ASSERT(Capacity() % AreaSize() == 0); |
796 accounting_stats_.ShrinkSpace(Page::kObjectAreaSize); | 904 accounting_stats_.ShrinkSpace(AreaSize()); |
797 } | 905 } |
798 | 906 |
799 | 907 |
800 void PagedSpace::ReleaseAllUnusedPages() { | 908 void PagedSpace::ReleaseAllUnusedPages() { |
801 PageIterator it(this); | 909 PageIterator it(this); |
802 while (it.has_next()) { | 910 while (it.has_next()) { |
803 Page* page = it.next(); | 911 Page* page = it.next(); |
804 if (!page->WasSwept()) { | 912 if (!page->WasSwept()) { |
805 if (page->LiveBytes() == 0) ReleasePage(page); | 913 if (page->LiveBytes() == 0) ReleasePage(page); |
806 } else { | 914 } else { |
807 HeapObject* obj = HeapObject::FromAddress(page->body()); | 915 HeapObject* obj = HeapObject::FromAddress(page->area_start()); |
808 if (obj->IsFreeSpace() && | 916 if (obj->IsFreeSpace() && |
809 FreeSpace::cast(obj)->size() == Page::kObjectAreaSize) { | 917 FreeSpace::cast(obj)->size() == AreaSize()) { |
810 // Sometimes we allocate memory from free list but don't | 918 // Sometimes we allocate memory from free list but don't |
811 // immediately initialize it (e.g. see PagedSpace::ReserveSpace | 919 // immediately initialize it (e.g. see PagedSpace::ReserveSpace |
812 // called from Heap::ReserveSpace that can cause GC before | 920 // called from Heap::ReserveSpace that can cause GC before |
813 // reserved space is actually initialized). | 921 // reserved space is actually initialized). |
814 // Thus we can't simply assume that obj represents a valid | 922 // Thus we can't simply assume that obj represents a valid |
815 // node still owned by a free list | 923 // node still owned by a free list |
816 // Instead we should verify that the page is fully covered | 924 // Instead we should verify that the page is fully covered |
817 // by free list items. | 925 // by free list items. |
818 FreeList::SizeStats sizes; | 926 FreeList::SizeStats sizes; |
819 free_list_.CountFreeListItems(page, &sizes); | 927 free_list_.CountFreeListItems(page, &sizes); |
820 if (sizes.Total() == Page::kObjectAreaSize) { | 928 if (sizes.Total() == AreaSize()) { |
821 ReleasePage(page); | 929 ReleasePage(page); |
822 } | 930 } |
823 } | 931 } |
824 } | 932 } |
825 } | 933 } |
826 heap()->FreeQueuedChunks(); | 934 heap()->FreeQueuedChunks(); |
827 } | 935 } |
828 | 936 |
829 | 937 |
830 #ifdef DEBUG | 938 #ifdef DEBUG |
(...skipping 10 matching lines...) Expand all Loading... |
841 (allocation_info_.top == allocation_info_.limit); | 949 (allocation_info_.top == allocation_info_.limit); |
842 PageIterator page_iterator(this); | 950 PageIterator page_iterator(this); |
843 while (page_iterator.has_next()) { | 951 while (page_iterator.has_next()) { |
844 Page* page = page_iterator.next(); | 952 Page* page = page_iterator.next(); |
845 ASSERT(page->owner() == this); | 953 ASSERT(page->owner() == this); |
846 if (page == Page::FromAllocationTop(allocation_info_.top)) { | 954 if (page == Page::FromAllocationTop(allocation_info_.top)) { |
847 allocation_pointer_found_in_space = true; | 955 allocation_pointer_found_in_space = true; |
848 } | 956 } |
849 ASSERT(page->WasSweptPrecisely()); | 957 ASSERT(page->WasSweptPrecisely()); |
850 HeapObjectIterator it(page, NULL); | 958 HeapObjectIterator it(page, NULL); |
851 Address end_of_previous_object = page->ObjectAreaStart(); | 959 Address end_of_previous_object = page->area_start(); |
852 Address top = page->ObjectAreaEnd(); | 960 Address top = page->area_end(); |
853 int black_size = 0; | 961 int black_size = 0; |
854 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | 962 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { |
855 ASSERT(end_of_previous_object <= object->address()); | 963 ASSERT(end_of_previous_object <= object->address()); |
856 | 964 |
857 // The first word should be a map, and we expect all map pointers to | 965 // The first word should be a map, and we expect all map pointers to |
858 // be in map space. | 966 // be in map space. |
859 Map* map = object->map(); | 967 Map* map = object->map(); |
860 ASSERT(map->IsMap()); | 968 ASSERT(map->IsMap()); |
861 ASSERT(heap()->map_space()->Contains(map)); | 969 ASSERT(heap()->map_space()->Contains(map)); |
862 | 970 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 // TODO(gc): Change the limit on new-space allocation to prevent this | 1162 // TODO(gc): Change the limit on new-space allocation to prevent this |
1055 // from happening (all such allocations should go directly to LOSpace). | 1163 // from happening (all such allocations should go directly to LOSpace). |
1056 return false; | 1164 return false; |
1057 } | 1165 } |
1058 if (!to_space_.AdvancePage()) { | 1166 if (!to_space_.AdvancePage()) { |
1059 // Failed to get a new page in to-space. | 1167 // Failed to get a new page in to-space. |
1060 return false; | 1168 return false; |
1061 } | 1169 } |
1062 | 1170 |
1063 // Clear remainder of current page. | 1171 // Clear remainder of current page. |
1064 Address limit = NewSpacePage::FromLimit(top)->body_limit(); | 1172 Address limit = NewSpacePage::FromLimit(top)->area_end(); |
1065 if (heap()->gc_state() == Heap::SCAVENGE) { | 1173 if (heap()->gc_state() == Heap::SCAVENGE) { |
1066 heap()->promotion_queue()->SetNewLimit(limit); | 1174 heap()->promotion_queue()->SetNewLimit(limit); |
1067 heap()->promotion_queue()->ActivateGuardIfOnTheSamePage(); | 1175 heap()->promotion_queue()->ActivateGuardIfOnTheSamePage(); |
1068 } | 1176 } |
1069 | 1177 |
1070 int remaining_in_page = static_cast<int>(limit - top); | 1178 int remaining_in_page = static_cast<int>(limit - top); |
1071 heap()->CreateFillerObjectAt(top, remaining_in_page); | 1179 heap()->CreateFillerObjectAt(top, remaining_in_page); |
1072 pages_used_++; | 1180 pages_used_++; |
1073 UpdateAllocationInfo(); | 1181 UpdateAllocationInfo(); |
1074 | 1182 |
(...skipping 29 matching lines...) Expand all Loading... |
1104 | 1212 |
1105 #ifdef DEBUG | 1213 #ifdef DEBUG |
1106 // We do not use the SemiSpaceIterator because verification doesn't assume | 1214 // We do not use the SemiSpaceIterator because verification doesn't assume |
1107 // that it works (it depends on the invariants we are checking). | 1215 // that it works (it depends on the invariants we are checking). |
1108 void NewSpace::Verify() { | 1216 void NewSpace::Verify() { |
1109 // The allocation pointer should be in the space or at the very end. | 1217 // The allocation pointer should be in the space or at the very end. |
1110 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1218 ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
1111 | 1219 |
1112 // There should be objects packed in from the low address up to the | 1220 // There should be objects packed in from the low address up to the |
1113 // allocation pointer. | 1221 // allocation pointer. |
1114 Address current = to_space_.first_page()->body(); | 1222 Address current = to_space_.first_page()->area_start(); |
1115 CHECK_EQ(current, to_space_.space_start()); | 1223 CHECK_EQ(current, to_space_.space_start()); |
1116 | 1224 |
1117 while (current != top()) { | 1225 while (current != top()) { |
1118 if (!NewSpacePage::IsAtEnd(current)) { | 1226 if (!NewSpacePage::IsAtEnd(current)) { |
1119 // The allocation pointer should not be in the middle of an object. | 1227 // The allocation pointer should not be in the middle of an object. |
1120 CHECK(!NewSpacePage::FromLimit(current)->ContainsLimit(top()) || | 1228 CHECK(!NewSpacePage::FromLimit(current)->ContainsLimit(top()) || |
1121 current < top()); | 1229 current < top()); |
1122 | 1230 |
1123 HeapObject* object = HeapObject::FromAddress(current); | 1231 HeapObject* object = HeapObject::FromAddress(current); |
1124 | 1232 |
(...skipping 14 matching lines...) Expand all Loading... |
1139 VerifyPointersVisitor visitor; | 1247 VerifyPointersVisitor visitor; |
1140 int size = object->Size(); | 1248 int size = object->Size(); |
1141 object->IterateBody(map->instance_type(), size, &visitor); | 1249 object->IterateBody(map->instance_type(), size, &visitor); |
1142 | 1250 |
1143 current += size; | 1251 current += size; |
1144 } else { | 1252 } else { |
1145 // At end of page, switch to next page. | 1253 // At end of page, switch to next page. |
1146 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); | 1254 NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); |
1147 // Next page should be valid. | 1255 // Next page should be valid. |
1148 CHECK(!page->is_anchor()); | 1256 CHECK(!page->is_anchor()); |
1149 current = page->body(); | 1257 current = page->area_start(); |
1150 } | 1258 } |
1151 } | 1259 } |
1152 | 1260 |
1153 // Check semi-spaces. | 1261 // Check semi-spaces. |
1154 ASSERT_EQ(from_space_.id(), kFromSpace); | 1262 ASSERT_EQ(from_space_.id(), kFromSpace); |
1155 ASSERT_EQ(to_space_.id(), kToSpace); | 1263 ASSERT_EQ(to_space_.id(), kToSpace); |
1156 from_space_.Verify(); | 1264 from_space_.Verify(); |
1157 to_space_.Verify(); | 1265 to_space_.Verify(); |
1158 } | 1266 } |
1159 #endif | 1267 #endif |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1925 sum += free_space->Size(); | 2033 sum += free_space->Size(); |
1926 } | 2034 } |
1927 n = n->next(); | 2035 n = n->next(); |
1928 } | 2036 } |
1929 return sum; | 2037 return sum; |
1930 } | 2038 } |
1931 | 2039 |
1932 | 2040 |
1933 void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { | 2041 void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { |
1934 sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); | 2042 sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); |
1935 if (sizes->huge_size_ < Page::kObjectAreaSize) { | 2043 if (sizes->huge_size_ < p->area_size()) { |
1936 sizes->small_size_ = CountFreeListItemsInList(small_list_, p); | 2044 sizes->small_size_ = CountFreeListItemsInList(small_list_, p); |
1937 sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); | 2045 sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); |
1938 sizes->large_size_ = CountFreeListItemsInList(large_list_, p); | 2046 sizes->large_size_ = CountFreeListItemsInList(large_list_, p); |
1939 } else { | 2047 } else { |
1940 sizes->small_size_ = 0; | 2048 sizes->small_size_ = 0; |
1941 sizes->medium_size_ = 0; | 2049 sizes->medium_size_ = 0; |
1942 sizes->large_size_ = 0; | 2050 sizes->large_size_ = 0; |
1943 } | 2051 } |
1944 } | 2052 } |
1945 | 2053 |
1946 | 2054 |
1947 static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { | 2055 static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { |
1948 intptr_t sum = 0; | 2056 intptr_t sum = 0; |
1949 while (*n != NULL) { | 2057 while (*n != NULL) { |
1950 if (Page::FromAddress((*n)->address()) == p) { | 2058 if (Page::FromAddress((*n)->address()) == p) { |
1951 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); | 2059 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); |
1952 sum += free_space->Size(); | 2060 sum += free_space->Size(); |
1953 *n = (*n)->next(); | 2061 *n = (*n)->next(); |
1954 } else { | 2062 } else { |
1955 n = (*n)->next_address(); | 2063 n = (*n)->next_address(); |
1956 } | 2064 } |
1957 } | 2065 } |
1958 return sum; | 2066 return sum; |
1959 } | 2067 } |
1960 | 2068 |
1961 | 2069 |
1962 intptr_t FreeList::EvictFreeListItems(Page* p) { | 2070 intptr_t FreeList::EvictFreeListItems(Page* p) { |
1963 intptr_t sum = EvictFreeListItemsInList(&huge_list_, p); | 2071 intptr_t sum = EvictFreeListItemsInList(&huge_list_, p); |
1964 | 2072 |
1965 if (sum < Page::kObjectAreaSize) { | 2073 if (sum < p->area_size()) { |
1966 sum += EvictFreeListItemsInList(&small_list_, p) + | 2074 sum += EvictFreeListItemsInList(&small_list_, p) + |
1967 EvictFreeListItemsInList(&medium_list_, p) + | 2075 EvictFreeListItemsInList(&medium_list_, p) + |
1968 EvictFreeListItemsInList(&large_list_, p); | 2076 EvictFreeListItemsInList(&large_list_, p); |
1969 } | 2077 } |
1970 | 2078 |
1971 available_ -= static_cast<int>(sum); | 2079 available_ -= static_cast<int>(sum); |
1972 | 2080 |
1973 return sum; | 2081 return sum; |
1974 } | 2082 } |
1975 | 2083 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 } | 2185 } |
2078 first_unswept_page_ = Page::FromAddress(NULL); | 2186 first_unswept_page_ = Page::FromAddress(NULL); |
2079 unswept_free_bytes_ = 0; | 2187 unswept_free_bytes_ = 0; |
2080 | 2188 |
2081 // Clear the free list before a full GC---it will be rebuilt afterward. | 2189 // Clear the free list before a full GC---it will be rebuilt afterward. |
2082 free_list_.Reset(); | 2190 free_list_.Reset(); |
2083 } | 2191 } |
2084 | 2192 |
2085 | 2193 |
2086 bool PagedSpace::ReserveSpace(int size_in_bytes) { | 2194 bool PagedSpace::ReserveSpace(int size_in_bytes) { |
2087 ASSERT(size_in_bytes <= Page::kMaxHeapObjectSize); | 2195 ASSERT(size_in_bytes <= AreaSize()); |
2088 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); | 2196 ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); |
2089 Address current_top = allocation_info_.top; | 2197 Address current_top = allocation_info_.top; |
2090 Address new_top = current_top + size_in_bytes; | 2198 Address new_top = current_top + size_in_bytes; |
2091 if (new_top <= allocation_info_.limit) return true; | 2199 if (new_top <= allocation_info_.limit) return true; |
2092 | 2200 |
2093 HeapObject* new_area = free_list_.Allocate(size_in_bytes); | 2201 HeapObject* new_area = free_list_.Allocate(size_in_bytes); |
2094 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); | 2202 if (new_area == NULL) new_area = SlowAllocateRaw(size_in_bytes); |
2095 if (new_area == NULL) return false; | 2203 if (new_area == NULL) return false; |
2096 | 2204 |
2097 int old_linear_size = static_cast<int>(limit() - top()); | 2205 int old_linear_size = static_cast<int>(limit() - top()); |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2457 return Failure::RetryAfterGC(identity()); | 2565 return Failure::RetryAfterGC(identity()); |
2458 } | 2566 } |
2459 | 2567 |
2460 if (Size() + object_size > max_capacity_) { | 2568 if (Size() + object_size > max_capacity_) { |
2461 return Failure::RetryAfterGC(identity()); | 2569 return Failure::RetryAfterGC(identity()); |
2462 } | 2570 } |
2463 | 2571 |
2464 LargePage* page = heap()->isolate()->memory_allocator()-> | 2572 LargePage* page = heap()->isolate()->memory_allocator()-> |
2465 AllocateLargePage(object_size, executable, this); | 2573 AllocateLargePage(object_size, executable, this); |
2466 if (page == NULL) return Failure::RetryAfterGC(identity()); | 2574 if (page == NULL) return Failure::RetryAfterGC(identity()); |
2467 ASSERT(page->body_size() >= object_size); | 2575 ASSERT(page->area_size() >= object_size); |
2468 | 2576 |
2469 size_ += static_cast<int>(page->size()); | 2577 size_ += static_cast<int>(page->size()); |
2470 objects_size_ += object_size; | 2578 objects_size_ += object_size; |
2471 page_count_++; | 2579 page_count_++; |
2472 page->set_next_page(first_page_); | 2580 page->set_next_page(first_page_); |
2473 first_page_ = page; | 2581 first_page_ = page; |
2474 | 2582 |
2475 HeapObject* object = page->GetObject(); | 2583 HeapObject* object = page->GetObject(); |
2476 | 2584 |
2477 #ifdef DEBUG | 2585 #ifdef DEBUG |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2573 // We do not assume that the large object iterator works, because it depends | 2681 // We do not assume that the large object iterator works, because it depends |
2574 // on the invariants we are checking during verification. | 2682 // on the invariants we are checking during verification. |
2575 void LargeObjectSpace::Verify() { | 2683 void LargeObjectSpace::Verify() { |
2576 for (LargePage* chunk = first_page_; | 2684 for (LargePage* chunk = first_page_; |
2577 chunk != NULL; | 2685 chunk != NULL; |
2578 chunk = chunk->next_page()) { | 2686 chunk = chunk->next_page()) { |
2579 // Each chunk contains an object that starts at the large object page's | 2687 // Each chunk contains an object that starts at the large object page's |
2580 // object area start. | 2688 // object area start. |
2581 HeapObject* object = chunk->GetObject(); | 2689 HeapObject* object = chunk->GetObject(); |
2582 Page* page = Page::FromAddress(object->address()); | 2690 Page* page = Page::FromAddress(object->address()); |
2583 ASSERT(object->address() == page->ObjectAreaStart()); | 2691 ASSERT(object->address() == page->area_start()); |
2584 | 2692 |
2585 // The first word should be a map, and we expect all map pointers to be | 2693 // The first word should be a map, and we expect all map pointers to be |
2586 // in map space. | 2694 // in map space. |
2587 Map* map = object->map(); | 2695 Map* map = object->map(); |
2588 ASSERT(map->IsMap()); | 2696 ASSERT(map->IsMap()); |
2589 ASSERT(heap()->map_space()->Contains(map)); | 2697 ASSERT(heap()->map_space()->Contains(map)); |
2590 | 2698 |
2591 // We have only code, sequential strings, external strings | 2699 // We have only code, sequential strings, external strings |
2592 // (sequential strings that have been morphed into external | 2700 // (sequential strings that have been morphed into external |
2593 // strings), fixed arrays, and byte arrays in large object space. | 2701 // strings), fixed arrays, and byte arrays in large object space. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2674 object->ShortPrint(); | 2782 object->ShortPrint(); |
2675 PrintF("\n"); | 2783 PrintF("\n"); |
2676 } | 2784 } |
2677 printf(" --------------------------------------\n"); | 2785 printf(" --------------------------------------\n"); |
2678 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 2786 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
2679 } | 2787 } |
2680 | 2788 |
2681 #endif // DEBUG | 2789 #endif // DEBUG |
2682 | 2790 |
2683 } } // namespace v8::internal | 2791 } } // namespace v8::internal |
OLD | NEW |