diff options
author | isaacs <i@izs.me> | 2012-02-27 13:43:31 -0800 |
---|---|---|
committer | isaacs <i@izs.me> | 2012-02-27 13:43:31 -0800 |
commit | 2e24ded6d23c58c97d3559bbfb37872b3981bc55 (patch) | |
tree | 94734cc8855253dda8314a09ddd24f8c6473ec5a /deps/v8/src/spaces.cc | |
parent | fde26002f176b4da87cc60bdb1b59b1d45c6a901 (diff) | |
download | node-new-2e24ded6d23c58c97d3559bbfb37872b3981bc55.tar.gz |
Upgrade v8 to 3.9.11
Diffstat (limited to 'deps/v8/src/spaces.cc')
-rw-r--r-- | deps/v8/src/spaces.cc | 178 |
1 files changed, 143 insertions, 35 deletions
diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 05c5876fdf..1fbad551af 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -75,8 +75,8 @@ HeapObjectIterator::HeapObjectIterator(Page* page, owner == HEAP->cell_space() || owner == HEAP->code_space()); Initialize(reinterpret_cast<PagedSpace*>(owner), - page->ObjectAreaStart(), - page->ObjectAreaEnd(), + page->area_start(), + page->area_end(), kOnePageOnly, size_func); ASSERT(page->WasSweptPrecisely()); @@ -108,12 +108,12 @@ bool HeapObjectIterator::AdvanceToNextPage() { cur_page = space_->anchor(); } else { cur_page = Page::FromAddress(cur_addr_ - 1); - ASSERT(cur_addr_ == cur_page->ObjectAreaEnd()); + ASSERT(cur_addr_ == cur_page->area_end()); } cur_page = cur_page->next_page(); if (cur_page == space_->anchor()) return false; - cur_addr_ = cur_page->ObjectAreaStart(); - cur_end_ = cur_page->ObjectAreaEnd(); + cur_addr_ = cur_page->area_start(); + cur_end_ = cur_page->area_end(); ASSERT(cur_page->WasSweptPrecisely()); return true; } @@ -227,7 +227,9 @@ Address CodeRange::AllocateRawMemory(const size_t requested, } ASSERT(*allocated <= current.size); ASSERT(IsAddressAligned(current.start, MemoryChunk::kAlignment)); - if (!code_range_->Commit(current.start, *allocated, true)) { + if (!MemoryAllocator::CommitCodePage(code_range_, + current.start, + *allocated)) { *allocated = 0; return NULL; } @@ -358,11 +360,17 @@ Address MemoryAllocator::AllocateAlignedMemory(size_t size, VirtualMemory reservation; Address base = ReserveAlignedMemory(size, alignment, &reservation); if (base == NULL) return NULL; - if (!reservation.Commit(base, - size, - executable == EXECUTABLE)) { - return NULL; + + if (executable == EXECUTABLE) { + CommitCodePage(&reservation, base, size); + } else { + if (!reservation.Commit(base, + size, + executable == EXECUTABLE)) { + return NULL; + } } + controller->TakeControl(&reservation); return base; } @@ -378,9 +386,14 @@ void Page::InitializeAsAnchor(PagedSpace* owner) { NewSpacePage* NewSpacePage::Initialize(Heap* heap, Address start, SemiSpace* semi_space) { + Address area_start = start + NewSpacePage::kObjectStartOffset; + Address area_end = start + Page::kPageSize; + MemoryChunk* chunk = MemoryChunk::Initialize(heap, start, Page::kPageSize, + area_start, + area_end, NOT_EXECUTABLE, semi_space); chunk->set_next_chunk(NULL); @@ -410,6 +423,8 @@ void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) { MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size, + Address area_start, + Address area_end, Executability executable, Space* owner) { MemoryChunk* chunk = FromAddress(base); @@ -418,6 +433,8 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, chunk->heap_ = heap; chunk->size_ = size; + chunk->area_start_ = area_start; + chunk->area_end_ = area_end; chunk->flags_ = 0; chunk->set_owner(owner); chunk->InitializeReservedMemory(); @@ -431,9 +448,13 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, ASSERT(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); ASSERT(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); - if (executable == EXECUTABLE) chunk->SetFlag(IS_EXECUTABLE); + if (executable == EXECUTABLE) { + chunk->SetFlag(IS_EXECUTABLE); + } - if (owner == heap->old_data_space()) chunk->SetFlag(CONTAINS_ONLY_DATA); + if (owner == heap->old_data_space()) { + chunk->SetFlag(CONTAINS_ONLY_DATA); + } return chunk; } @@ -462,11 +483,16 @@ void MemoryChunk::Unlink() { MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, Executability executable, Space* owner) { - size_t chunk_size = MemoryChunk::kObjectStartOffset + body_size; + size_t chunk_size; Heap* heap = isolate_->heap(); Address base = NULL; VirtualMemory reservation; + Address area_start = NULL; + Address area_end = NULL; if (executable == EXECUTABLE) { + chunk_size = RoundUp(CodePageAreaStartOffset() + body_size, + OS::CommitPageSize()) + CodePageGuardSize(); + // Check executable memory limit. if (size_executable_ + chunk_size > capacity_executable_) { LOG(isolate_, @@ -494,18 +520,30 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, // Update executable memory size. size_executable_ += reservation.size(); } + +#ifdef DEBUG + ZapBlock(base, CodePageGuardStartOffset()); + ZapBlock(base + CodePageAreaStartOffset(), body_size); +#endif + area_start = base + CodePageAreaStartOffset(); + area_end = area_start + body_size; } else { + chunk_size = MemoryChunk::kObjectStartOffset + body_size; base = AllocateAlignedMemory(chunk_size, MemoryChunk::kAlignment, executable, &reservation); if (base == NULL) return NULL; - } #ifdef DEBUG - ZapBlock(base, chunk_size); + ZapBlock(base, chunk_size); #endif + + area_start = base + Page::kObjectStartOffset; + area_end = base + chunk_size; + } + isolate_->counters()->memory_allocated()-> Increment(static_cast<int>(chunk_size)); @@ -518,6 +556,8 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, MemoryChunk* result = MemoryChunk::Initialize(heap, base, chunk_size, + area_start, + area_end, executable, owner); result->set_reserved_memory(&reservation); @@ -527,7 +567,9 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, Page* MemoryAllocator::AllocatePage(PagedSpace* owner, Executability executable) { - MemoryChunk* chunk = AllocateChunk(Page::kObjectAreaSize, executable, owner); + MemoryChunk* chunk = AllocateChunk(owner->AreaSize(), + executable, + owner); if (chunk == NULL) return NULL; @@ -648,6 +690,65 @@ void MemoryAllocator::ReportStatistics() { } #endif + +int MemoryAllocator::CodePageGuardStartOffset() { + // We are guarding code pages: the first OS page after the header + // will be protected as non-writable. + return RoundUp(Page::kObjectStartOffset, OS::CommitPageSize()); +} + + +int MemoryAllocator::CodePageGuardSize() { + return static_cast<int>(OS::CommitPageSize()); +} + + +int MemoryAllocator::CodePageAreaStartOffset() { + // We are guarding code pages: the first OS page after the header + // will be protected as non-writable. + return CodePageGuardStartOffset() + CodePageGuardSize(); +} + + +int MemoryAllocator::CodePageAreaEndOffset() { + // We are guarding code pages: the last OS page will be protected as + // non-writable. + return Page::kPageSize - static_cast<int>(OS::CommitPageSize()); +} + + +bool MemoryAllocator::CommitCodePage(VirtualMemory* vm, + Address start, + size_t size) { + // Commit page header (not executable). + if (!vm->Commit(start, + CodePageGuardStartOffset(), + false)) { + return false; + } + + // Create guard page after the header. + if (!vm->Guard(start + CodePageGuardStartOffset())) { + return false; + } + + // Commit page body (executable). + size_t area_size = size - CodePageAreaStartOffset() - CodePageGuardSize(); + if (!vm->Commit(start + CodePageAreaStartOffset(), + area_size, + true)) { + return false; + } + + // Create guard page after the allocatable area. + if (!vm->Guard(start + CodePageAreaStartOffset() + area_size)) { + return false; + } + + return true; +} + + // ----------------------------------------------------------------------------- // MemoryChunk implementation @@ -671,8 +772,14 @@ PagedSpace::PagedSpace(Heap* heap, was_swept_conservatively_(false), first_unswept_page_(Page::FromAddress(NULL)), unswept_free_bytes_(0) { + if (id == CODE_SPACE) { + area_size_ = heap->isolate()->memory_allocator()-> + CodePageAreaSize(); + } else { + area_size_ = Page::kPageSize - Page::kObjectStartOffset; + } max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) - * Page::kObjectAreaSize; + * AreaSize(); accounting_stats_.Clear(); allocation_info_.top = NULL; @@ -722,8 +829,8 @@ MaybeObject* PagedSpace::FindObject(Address addr) { } bool PagedSpace::CanExpand() { - ASSERT(max_capacity_ % Page::kObjectAreaSize == 0); - ASSERT(Capacity() % Page::kObjectAreaSize == 0); + ASSERT(max_capacity_ % AreaSize() == 0); + ASSERT(Capacity() % AreaSize() == 0); if (Capacity() == max_capacity_) return false; @@ -763,6 +870,7 @@ int PagedSpace::CountTotalPages() { void PagedSpace::ReleasePage(Page* page) { ASSERT(page->LiveBytes() == 0); + ASSERT(AreaSize() == page->area_size()); // Adjust list of unswept pages if the page is the head of the list. if (first_unswept_page_ == page) { @@ -775,7 +883,7 @@ void PagedSpace::ReleasePage(Page* page) { if (page->WasSwept()) { intptr_t size = free_list_.EvictFreeListItems(page); accounting_stats_.AllocateBytes(size); - ASSERT_EQ(Page::kObjectAreaSize, static_cast<int>(size)); + ASSERT_EQ(AreaSize(), static_cast<int>(size)); } else { DecreaseUnsweptFreeBytes(page); } @@ -792,8 +900,8 @@ void PagedSpace::ReleasePage(Page* page) { } ASSERT(Capacity() > 0); - ASSERT(Capacity() % Page::kObjectAreaSize == 0); - accounting_stats_.ShrinkSpace(Page::kObjectAreaSize); + ASSERT(Capacity() % AreaSize() == 0); + accounting_stats_.ShrinkSpace(AreaSize()); } @@ -804,9 +912,9 @@ void PagedSpace::ReleaseAllUnusedPages() { if (!page->WasSwept()) { if (page->LiveBytes() == 0) ReleasePage(page); } else { - HeapObject* obj = HeapObject::FromAddress(page->body()); + HeapObject* obj = HeapObject::FromAddress(page->area_start()); if (obj->IsFreeSpace() && - FreeSpace::cast(obj)->size() == Page::kObjectAreaSize) { + FreeSpace::cast(obj)->size() == AreaSize()) { // Sometimes we allocate memory from free list but don't // immediately initialize it (e.g. see PagedSpace::ReserveSpace // called from Heap::ReserveSpace that can cause GC before @@ -817,7 +925,7 @@ void PagedSpace::ReleaseAllUnusedPages() { // by free list items. FreeList::SizeStats sizes; free_list_.CountFreeListItems(page, &sizes); - if (sizes.Total() == Page::kObjectAreaSize) { + if (sizes.Total() == AreaSize()) { ReleasePage(page); } } @@ -848,8 +956,8 @@ void PagedSpace::Verify(ObjectVisitor* visitor) { } ASSERT(page->WasSweptPrecisely()); HeapObjectIterator it(page, NULL); - Address end_of_previous_object = page->ObjectAreaStart(); - Address top = page->ObjectAreaEnd(); + Address end_of_previous_object = page->area_start(); + Address top = page->area_end(); int black_size = 0; for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { ASSERT(end_of_previous_object <= object->address()); @@ -1061,7 +1169,7 @@ bool NewSpace::AddFreshPage() { } // Clear remainder of current page. - Address limit = NewSpacePage::FromLimit(top)->body_limit(); + Address limit = NewSpacePage::FromLimit(top)->area_end(); if (heap()->gc_state() == Heap::SCAVENGE) { heap()->promotion_queue()->SetNewLimit(limit); heap()->promotion_queue()->ActivateGuardIfOnTheSamePage(); @@ -1111,7 +1219,7 @@ void NewSpace::Verify() { // There should be objects packed in from the low address up to the // allocation pointer. - Address current = to_space_.first_page()->body(); + Address current = to_space_.first_page()->area_start(); CHECK_EQ(current, to_space_.space_start()); while (current != top()) { @@ -1146,7 +1254,7 @@ void NewSpace::Verify() { NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page(); // Next page should be valid. CHECK(!page->is_anchor()); - current = page->body(); + current = page->area_start(); } } @@ -1932,7 +2040,7 @@ static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); - if (sizes->huge_size_ < Page::kObjectAreaSize) { + if (sizes->huge_size_ < p->area_size()) { sizes->small_size_ = CountFreeListItemsInList(small_list_, p); sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); sizes->large_size_ = CountFreeListItemsInList(large_list_, p); @@ -1962,7 +2070,7 @@ static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { intptr_t FreeList::EvictFreeListItems(Page* p) { intptr_t sum = EvictFreeListItemsInList(&huge_list_, p); - if (sum < Page::kObjectAreaSize) { + if (sum < p->area_size()) { sum += EvictFreeListItemsInList(&small_list_, p) + EvictFreeListItemsInList(&medium_list_, p) + EvictFreeListItemsInList(&large_list_, p); @@ -2084,7 +2192,7 @@ void PagedSpace::PrepareForMarkCompact() { bool PagedSpace::ReserveSpace(int size_in_bytes) { - ASSERT(size_in_bytes <= Page::kMaxHeapObjectSize); + ASSERT(size_in_bytes <= AreaSize()); ASSERT(size_in_bytes == RoundSizeDownToObjectAlignment(size_in_bytes)); Address current_top = allocation_info_.top; Address new_top = current_top + size_in_bytes; @@ -2464,7 +2572,7 @@ MaybeObject* LargeObjectSpace::AllocateRaw(int object_size, LargePage* page = heap()->isolate()->memory_allocator()-> AllocateLargePage(object_size, executable, this); if (page == NULL) return Failure::RetryAfterGC(identity()); - ASSERT(page->body_size() >= object_size); + ASSERT(page->area_size() >= object_size); size_ += static_cast<int>(page->size()); objects_size_ += object_size; @@ -2580,7 +2688,7 @@ void LargeObjectSpace::Verify() { // object area start. HeapObject* object = chunk->GetObject(); Page* page = Page::FromAddress(object->address()); - ASSERT(object->address() == page->ObjectAreaStart()); + ASSERT(object->address() == page->area_start()); // The first word should be a map, and we expect all map pointers to be // in map space. |