Index: src/heap/spaces.cc |
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc |
index b1c9557989fd5a12cd0f5e2043572b548c362997..c74b93f52c1672417ffbf9d250ffebee234b8b76 100644 |
--- a/src/heap/spaces.cc |
+++ b/src/heap/spaces.cc |
@@ -80,8 +80,7 @@ CodeRange::CodeRange(Isolate* isolate) |
code_range_(NULL), |
free_list_(0), |
allocation_list_(0), |
- current_allocation_block_index_(0), |
- emergency_block_() {} |
+ current_allocation_block_index_(0) {} |
bool CodeRange::SetUp(size_t requested) { |
@@ -140,7 +139,6 @@ bool CodeRange::SetUp(size_t requested) { |
current_allocation_block_index_ = 0; |
LOG(isolate_, NewEvent("CodeRange", code_range_->address(), requested)); |
- ReserveEmergencyBlock(); |
return true; |
} |
@@ -276,24 +274,6 @@ void CodeRange::ReleaseBlock(const FreeBlock* block) { |
} |
-void CodeRange::ReserveEmergencyBlock() { |
- const size_t requested_size = MemoryAllocator::CodePageAreaSize(); |
- if (emergency_block_.size == 0) { |
- ReserveBlock(requested_size, &emergency_block_); |
- } else { |
- DCHECK(emergency_block_.size >= requested_size); |
- } |
-} |
- |
- |
-void CodeRange::ReleaseEmergencyBlock() { |
- if (emergency_block_.size != 0) { |
- ReleaseBlock(&emergency_block_); |
- emergency_block_.size = 0; |
- } |
-} |
- |
- |
// ----------------------------------------------------------------------------- |
// MemoryAllocator |
// |
@@ -492,6 +472,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size, |
chunk->progress_bar_ = 0; |
chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base)); |
chunk->set_parallel_sweeping(SWEEPING_DONE); |
+ chunk->parallel_compaction_state().SetValue(kCompactingDone); |
chunk->mutex_ = NULL; |
chunk->available_in_small_free_list_ = 0; |
chunk->available_in_medium_free_list_ = 0; |
@@ -974,8 +955,7 @@ PagedSpace::PagedSpace(Heap* heap, AllocationSpace space, |
: Space(heap, space, executable), |
free_list_(this), |
unswept_free_bytes_(0), |
- end_of_unswept_pages_(NULL), |
- emergency_memory_(NULL) { |
+ end_of_unswept_pages_(NULL) { |
area_size_ = MemoryAllocator::PageAreaSize(space); |
accounting_stats_.Clear(); |
@@ -1003,30 +983,38 @@ void PagedSpace::TearDown() { |
} |
+void PagedSpace::MoveOverFreeMemory(PagedSpace* other) { |
+ DCHECK(identity() == other->identity()); |
+ // Destroy the linear allocation space of {other}. This is needed to |
+ // (a) not waste the memory and |
+ // (b) keep the rest of the chunk in an iterable state (filler is needed). |
+ other->EmptyAllocationInfo(); |
+ |
+ // Move over the free list. Concatenate makes sure that the source free list |
+ // gets properly reset after moving over all nodes. |
+ intptr_t freed_bytes = free_list_.Concatenate(other->free_list()); |
+ |
+ // Moved memory is not recorded as allocated memory, but rather increases and |
+ // decreases capacity of the corresponding spaces. Used size and waste size |
+ // are maintained by the receiving space upon allocating and freeing blocks. |
+ other->accounting_stats_.DecreaseCapacity(freed_bytes); |
+ accounting_stats_.IncreaseCapacity(freed_bytes); |
+} |
+ |
+ |
void PagedSpace::MergeCompactionSpace(CompactionSpace* other) { |
// Unmerged fields: |
// area_size_ |
// allocation_info_ |
- // emergency_memory_ |
// end_of_unswept_pages_ |
// unswept_free_bytes_ |
// anchor_ |
- // It only makes sense to merge compatible spaces. |
- DCHECK(identity() == other->identity()); |
- |
- // Destroy the linear allocation space of {other}. This is needed to (a) not |
- // waste the memory and (b) keep the rest of the chunk in an iterable state |
- // (filler is needed). |
- int linear_size = static_cast<int>(other->limit() - other->top()); |
- other->Free(other->top(), linear_size); |
- |
- // Move over the free list. |
- free_list_.Concatenate(other->free_list()); |
+ MoveOverFreeMemory(other); |
// Update and clear accounting statistics. |
accounting_stats_.Merge(other->accounting_stats_); |
- other->accounting_stats_.Clear(); |
+ other->accounting_stats_.Reset(); |
// Move over pages. |
PageIterator it(other); |
@@ -1110,9 +1098,6 @@ bool PagedSpace::Expand() { |
if (!heap()->deserialization_complete()) p->MarkNeverEvacuate(); |
DCHECK(Capacity() <= heap()->MaxOldGenerationSize()); |
- DCHECK(heap()->CommittedOldGenerationMemory() <= |
- heap()->MaxOldGenerationSize() + |
- PagedSpace::MaxEmergencyMemoryAllocated()); |
p->InsertAfter(anchor_.prev_page()); |
@@ -1182,51 +1167,6 @@ void PagedSpace::ReleasePage(Page* page) { |
} |
-intptr_t PagedSpace::MaxEmergencyMemoryAllocated() { |
- // New space and large object space. |
- static const int spaces_without_emergency_memory = 2; |
- static const int spaces_with_emergency_memory = |
- LAST_SPACE - FIRST_SPACE + 1 - spaces_without_emergency_memory; |
- return Page::kPageSize * spaces_with_emergency_memory; |
-} |
- |
- |
-void PagedSpace::CreateEmergencyMemory() { |
- if (identity() == CODE_SPACE) { |
- // Make the emergency block available to the allocator. |
- CodeRange* code_range = heap()->isolate()->code_range(); |
- if (code_range != NULL && code_range->valid()) { |
- code_range->ReleaseEmergencyBlock(); |
- } |
- DCHECK(MemoryAllocator::CodePageAreaSize() == AreaSize()); |
- } |
- emergency_memory_ = heap()->isolate()->memory_allocator()->AllocateChunk( |
- AreaSize(), AreaSize(), executable(), this); |
-} |
- |
- |
-void PagedSpace::FreeEmergencyMemory() { |
- Page* page = static_cast<Page*>(emergency_memory_); |
- DCHECK(page->LiveBytes() == 0); |
- DCHECK(AreaSize() == page->area_size()); |
- DCHECK(!free_list_.ContainsPageFreeListItems(page)); |
- heap()->isolate()->memory_allocator()->Free(page); |
- emergency_memory_ = NULL; |
-} |
- |
- |
-void PagedSpace::UseEmergencyMemory() { |
- // Page::Initialize makes the chunk into a real page and adds it to the |
- // accounting for this space. Unlike PagedSpace::Expand, we don't check |
- // CanExpand first, so we can go over the limits a little here. That's OK, |
- // because we are in the process of compacting which will free up at least as |
- // much memory as it allocates. |
- Page* page = Page::Initialize(heap(), emergency_memory_, executable(), this); |
- page->InsertAfter(anchor_.prev_page()); |
- emergency_memory_ = NULL; |
-} |
- |
- |
#ifdef DEBUG |
void PagedSpace::Print() {} |
#endif |
@@ -2133,9 +2073,10 @@ intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { |
if (category->top() != NULL) { |
// This is safe (not going to deadlock) since Concatenate operations |
// are never performed on the same free lists at the same time in |
- // reverse order. |
- base::LockGuard<base::Mutex> target_lock_guard(mutex()); |
- base::LockGuard<base::Mutex> source_lock_guard(category->mutex()); |
+ // reverse order. Furthermore, we only lock if the PagedSpace containing |
+ // the free list is know to be globally available, i.e., not local. |
+ if (!this->owner()->owner()->is_local()) mutex()->Lock(); |
+ if (!category->owner()->owner()->is_local()) category->mutex()->Lock(); |
DCHECK(category->end_ != NULL); |
free_bytes = category->available(); |
if (end_ == NULL) { |
@@ -2147,6 +2088,8 @@ intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { |
base::NoBarrier_Store(&top_, category->top_); |
available_ += category->available(); |
category->Reset(); |
+ if (!category->owner()->owner()->is_local()) category->mutex()->Unlock(); |
+ if (!this->owner()->owner()->is_local()) mutex()->Unlock(); |
} |
return free_bytes; |
} |
@@ -2254,7 +2197,13 @@ void FreeListCategory::RepairFreeList(Heap* heap) { |
} |
-FreeList::FreeList(PagedSpace* owner) : owner_(owner), heap_(owner->heap()) { |
+FreeList::FreeList(PagedSpace* owner) |
+ : owner_(owner), |
+ heap_(owner->heap()), |
+ small_list_(this), |
+ medium_list_(this), |
+ large_list_(this), |
+ huge_list_(this) { |
Reset(); |
} |