Index: src/heap/spaces.cc |
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc |
index c4219df48b7dbbac8a29e1d1d7e3728b16415397..af56ccc2bc64e9baf49d66286345d9bd69ed4268 100644 |
--- a/src/heap/spaces.cc |
+++ b/src/heap/spaces.cc |
@@ -333,6 +333,10 @@ void MemoryAllocator::TearDown() { |
capacity_ = 0; |
capacity_executable_ = 0; |
+ if (last_chunk_.IsReserved()) { |
+ last_chunk_.Release(); |
+ } |
+ |
delete code_range_; |
code_range_ = nullptr; |
} |
@@ -680,6 +684,23 @@ MemoryChunk* MemoryAllocator::AllocateChunk(intptr_t reserve_area_size, |
PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); |
} |
+ // We cannot use the last chunk in the address space because we would |
+ // overflow when comparing top and limit if this chunk is used for a |
+ // linear allocation area. |
+ if ((reinterpret_cast<uintptr_t>(base) + chunk_size) == 0u) { |
+ CHECK(!last_chunk_.IsReserved()); |
+ last_chunk_.TakeControl(&reservation); |
+ UncommitBlock(reinterpret_cast<Address>(last_chunk_.address()), |
+ last_chunk_.size()); |
+ size_.Increment(-static_cast<intptr_t>(chunk_size)); |
+ if (executable == EXECUTABLE) { |
+ size_executable_.Increment(-static_cast<intptr_t>(chunk_size)); |
+ } |
+ CHECK(last_chunk_.IsReserved()); |
+ return AllocateChunk(reserve_area_size, commit_area_size, executable, |
+ owner); |
+ } |
+ |
return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end, |
executable, owner, &reservation); |
} |