Index: src/spaces.cc |
diff --git a/src/spaces.cc b/src/spaces.cc |
index 56453503b0880e99bb81bd4c7cc3ef1c9fc7dbe0..9f2cef52c0398702d19bab958723cd4600da7ff9 100644 |
--- a/src/spaces.cc |
+++ b/src/spaces.cc |
@@ -292,7 +292,7 @@ bool MemoryAllocator::Setup(intptr_t capacity, intptr_t capacity_executable) { |
void MemoryAllocator::TearDown() { |
- // Check that spaces were teared down before MemoryAllocator. |
+ // Check that spaces were torn down before MemoryAllocator. |
ASSERT(size_ == 0); |
// TODO(gc) this will be true again when we fix FreeMemory. |
// ASSERT(size_executable_ == 0); |
@@ -301,6 +301,28 @@ void MemoryAllocator::TearDown() { |
} |
+void MemoryAllocator::FreeMemory(VirtualMemory* reservation, |
+ Executability executable) { |
+ // TODO(gc) make code_range part of memory allocator? |
+ ASSERT(reservation->IsReserved()); |
+ size_t size = reservation->size(); |
+ ASSERT(size_ >= size); |
+ size_ -= size; |
+ |
+ isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); |
+ |
+ if (executable == EXECUTABLE) { |
+ ASSERT(size_executable_ >= size); |
+ size_executable_ -= size; |
+ } |
+ // Code which is part of the code-range does not have its own VirtualMemory. |
+ ASSERT(!isolate_->code_range()->contains( |
+ static_cast<Address>(reservation->address()))); |
+ ASSERT(executable == NOT_EXECUTABLE || !isolate_->code_range()->exists()); |
+ reservation->Release(); |
+} |
+ |
+ |
void MemoryAllocator::FreeMemory(Address base, |
size_t size, |
Executability executable) { |
@@ -324,73 +346,33 @@ void MemoryAllocator::FreeMemory(Address base, |
} |
-Address MemoryAllocator::ReserveAlignedMemory(const size_t requested, |
+Address MemoryAllocator::ReserveAlignedMemory(size_t size, |
size_t alignment, |
- size_t* allocated_size) { |
- ASSERT(IsAligned(alignment, OS::AllocateAlignment())); |
- if (size_ + requested > capacity_) return NULL; |
- |
- size_t allocated = RoundUp(requested + alignment, |
- static_cast<intptr_t>(OS::AllocateAlignment())); |
- |
- Address base = reinterpret_cast<Address>( |
- VirtualMemory::ReserveRegion(allocated)); |
- |
- Address end = base + allocated; |
- |
- if (base == 0) return NULL; |
- |
- Address aligned_base = RoundUp(base, alignment); |
- |
- ASSERT(aligned_base + requested <= base + allocated); |
- |
- // The difference between re-aligned base address and base address is |
- // multiple of OS::AllocateAlignment(). |
- if (aligned_base != base) { |
- ASSERT(aligned_base > base); |
- // TODO(gc) check result of operation? |
- VirtualMemory::ReleaseRegion(reinterpret_cast<void*>(base), |
- aligned_base - base); |
- allocated -= (aligned_base - base); |
- base = aligned_base; |
- } |
- |
- ASSERT(base + allocated == end); |
- |
- Address requested_end = base + requested; |
- Address aligned_requested_end = |
- RoundUp(requested_end, OS::AllocateAlignment()); |
- |
- if (aligned_requested_end < end) { |
- // TODO(gc) check result of operation? |
- VirtualMemory::ReleaseRegion(reinterpret_cast<void*>(aligned_requested_end), |
- end - aligned_requested_end); |
- allocated = aligned_requested_end - base; |
- } |
- |
- size_ += allocated; |
- *allocated_size = allocated; |
+ VirtualMemory* controller) { |
+ VirtualMemory reservation(size, alignment); |
+ |
+ if (!reservation.IsReserved()) return NULL; |
+ size_ += reservation.size(); |
+ Address base = RoundUp(static_cast<Address>(reservation.address()), |
+ alignment); |
+ controller->TakeControl(&reservation); |
return base; |
} |
-Address MemoryAllocator::AllocateAlignedMemory(const size_t requested, |
+Address MemoryAllocator::AllocateAlignedMemory(size_t size, |
size_t alignment, |
Executability executable, |
- size_t* allocated_size) { |
- Address base = |
- ReserveAlignedMemory(requested, Page::kPageSize, allocated_size); |
- |
+ VirtualMemory* controller) { |
+ VirtualMemory reservation; |
+ Address base = ReserveAlignedMemory(size, alignment, &reservation); |
if (base == NULL) return NULL; |
- |
- if (!VirtualMemory::CommitRegion(base, |
- *allocated_size, |
- executable == EXECUTABLE)) { |
- VirtualMemory::ReleaseRegion(base, *allocated_size); |
- size_ -= *allocated_size; |
+ if (!reservation.Commit(base, |
+ size, |
+ executable == EXECUTABLE)) { |
return NULL; |
} |
- |
+ controller->TakeControl(&reservation); |
return base; |
} |
@@ -447,6 +429,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, |
chunk->size_ = size; |
chunk->flags_ = 0; |
chunk->set_owner(owner); |
+ chunk->InitializeReservedMemory(); |
chunk->slots_buffer_ = NULL; |
Bitmap::Clear(chunk); |
chunk->initialize_scan_on_scavenge(false); |
@@ -488,6 +471,7 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, |
size_t chunk_size = MemoryChunk::kObjectStartOffset + body_size; |
Heap* heap = isolate_->heap(); |
Address base = NULL; |
+ VirtualMemory reservation; |
if (executable == EXECUTABLE) { |
// Check executable memory limit. |
if (size_executable_ + chunk_size > capacity_executable_) { |
@@ -503,23 +487,24 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, |
base = isolate_->code_range()->AllocateRawMemory(chunk_size, &chunk_size); |
ASSERT(IsAligned(reinterpret_cast<intptr_t>(base), |
MemoryChunk::kAlignment)); |
+ if (base == NULL) return NULL; |
size_ += chunk_size; |
+ // Update executable memory size. |
+ size_executable_ += chunk_size; |
} else { |
base = AllocateAlignedMemory(chunk_size, |
MemoryChunk::kAlignment, |
executable, |
- &chunk_size); |
+ &reservation); |
+ if (base == NULL) return NULL; |
+ // Update executable memory size. |
+ size_executable_ += reservation.size(); |
} |
- |
- if (base == NULL) return NULL; |
- |
- // Update executable memory size. |
- size_executable_ += chunk_size; |
} else { |
base = AllocateAlignedMemory(chunk_size, |
MemoryChunk::kAlignment, |
executable, |
- &chunk_size); |
+ &reservation); |
if (base == NULL) return NULL; |
} |
@@ -536,11 +521,13 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t body_size, |
PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); |
} |
- return MemoryChunk::Initialize(heap, |
- base, |
- chunk_size, |
- executable, |
- owner); |
+ MemoryChunk* result = MemoryChunk::Initialize(heap, |
+ base, |
+ chunk_size, |
+ executable, |
+ owner); |
+ result->set_reserved_memory(&reservation); |
+ return result; |
} |
@@ -571,9 +558,14 @@ void MemoryAllocator::Free(MemoryChunk* chunk) { |
PerformAllocationCallback(space, kAllocationActionFree, chunk->size()); |
} |
- FreeMemory(chunk->address(), |
- chunk->size(), |
- chunk->executable()); |
+ VirtualMemory* reservation = chunk->reserved_memory(); |
+ if (reservation->IsReserved()) { |
+ FreeMemory(reservation, chunk->executable()); |
+ } else { |
+ FreeMemory(chunk->address(), |
+ chunk->size(), |
+ chunk->executable()); |
+ } |
} |
@@ -845,13 +837,10 @@ bool NewSpace::Setup(int reserved_semispace_capacity, |
// this chunk must be a power of two and it must be aligned to its size. |
int initial_semispace_capacity = heap()->InitialSemiSpaceSize(); |
- size_t size = 0; |
+ size_t size = 2 * reserved_semispace_capacity; |
Address base = |
heap()->isolate()->memory_allocator()->ReserveAlignedMemory( |
- 2 * reserved_semispace_capacity, |
- 2 * reserved_semispace_capacity, |
- &size); |
- |
+ size, size, &reservation_); |
if (base == NULL) return false; |
chunk_base_ = base; |
@@ -915,10 +904,10 @@ void NewSpace::TearDown() { |
from_space_.TearDown(); |
LOG(heap()->isolate(), DeleteEvent("InitialChunk", chunk_base_)); |
- heap()->isolate()->memory_allocator()->FreeMemory( |
- chunk_base_, |
- static_cast<size_t>(chunk_size_), |
- NOT_EXECUTABLE); |
+ |
+ ASSERT(reservation_.IsReserved()); |
+ heap()->isolate()->memory_allocator()->FreeMemory(&reservation_, |
+ NOT_EXECUTABLE); |
chunk_base_ = NULL; |
chunk_size_ = 0; |
} |