From 0d7380da55fff4187f1315cdbb002e739b132d20 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Fri, 2 Dec 2011 14:08:12 +0000 Subject: [PATCH] Let store buffer start out small for a 1Mbyte saving in boot memory use (2Mbyte on x64). Review URL: http://codereview.chromium.org/8776032 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10143 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap.cc | 2 +- src/platform-posix.cc | 5 +++ src/platform-win32.cc | 5 +++ src/platform.h | 4 +++ src/store-buffer.cc | 53 +++++++++++++++++++++++--------- src/store-buffer.h | 4 ++- test/cctest/test-mark-compact.cc | 2 +- 7 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/heap.cc b/src/heap.cc index 3f36d8b390..6039dc686a 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -1012,7 +1012,7 @@ void StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) { // Store Buffer overflowed while scanning promoted objects. These are not // in any particular page, though they are likely to be clustered by the // allocation routines. - store_buffer_->HandleFullness(); + store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize); } else { // Store Buffer overflowed while scanning a particular old space page for // pointers to new space. diff --git a/src/platform-posix.cc b/src/platform-posix.cc index cccf0acb37..a59d0bbdc3 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -70,6 +70,11 @@ intptr_t OS::MaxVirtualMemory() { } +intptr_t OS::CommitPageSize() { + return 4096; +} + + #ifndef __CYGWIN__ // Get rid of writable permission on code allocations. void OS::ProtectCode(void* address, const size_t size) { diff --git a/src/platform-win32.cc b/src/platform-win32.cc index 8771c43679..822f360642 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -889,6 +889,11 @@ void OS::Free(void* address, const size_t size) { } +intptr_t OS::CommitPageSize() { + return 4096; +} + + void OS::ProtectCode(void* address, const size_t size) { DWORD old_protect; VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect); diff --git a/src/platform.h b/src/platform.h index f84b6b17a5..127f788f9d 100644 --- a/src/platform.h +++ b/src/platform.h @@ -172,6 +172,10 @@ class OS { bool is_executable); static void Free(void* address, const size_t size); + // This is the granularity at which the ProtectCode(...) call can set page + // permissions. + static intptr_t CommitPageSize(); + // Mark code segments non-writable. static void ProtectCode(void* address, const size_t size); diff --git a/src/store-buffer.cc b/src/store-buffer.cc index 7c8b5f2077..1569305308 100644 --- a/src/store-buffer.cc +++ b/src/store-buffer.cc @@ -41,6 +41,7 @@ StoreBuffer::StoreBuffer(Heap* heap) old_start_(NULL), old_limit_(NULL), old_top_(NULL), + old_reserved_limit_(NULL), old_buffer_is_sorted_(false), old_buffer_is_filtered_(false), during_gc_(false), @@ -59,10 +60,25 @@ void StoreBuffer::Setup() { reinterpret_cast(virtual_memory_->address()); start_ = reinterpret_cast(RoundUp(start_as_int, kStoreBufferSize * 2)); - limit_ = start_ + (kStoreBufferSize / sizeof(*start_)); + limit_ = start_ + (kStoreBufferSize / kPointerSize); - old_top_ = old_start_ = new Address[kOldStoreBufferLength]; - old_limit_ = old_start_ + kOldStoreBufferLength; + old_virtual_memory_ = + new VirtualMemory(kOldStoreBufferLength * kPointerSize); + old_top_ = old_start_ = + reinterpret_cast(old_virtual_memory_->address()); + // Don't know the alignment requirements of the OS, but it is certainly not + // less than 0xfff. + ASSERT((reinterpret_cast(old_start_) & 0xfff) == 0); + int initial_length = OS::CommitPageSize() / kPointerSize; + ASSERT(initial_length > 0); + ASSERT(initial_length <= kOldStoreBufferLength); + old_limit_ = old_start_ + initial_length; + old_reserved_limit_ = old_start_ + kOldStoreBufferLength; + + CHECK(old_virtual_memory_->Commit( + reinterpret_cast(old_start_), + (old_limit_ - old_start_) * kPointerSize, + false)); ASSERT(reinterpret_cast
(start_) >= virtual_memory_->address()); ASSERT(reinterpret_cast
(limit_) >= virtual_memory_->address()); @@ -76,9 +92,9 @@ void StoreBuffer::Setup() { ASSERT((reinterpret_cast(limit_ - 1) & kStoreBufferOverflowBit) == 0); - virtual_memory_->Commit(reinterpret_cast
(start_), - kStoreBufferSize, - false); // Not executable. + CHECK(virtual_memory_->Commit(reinterpret_cast
(start_), + kStoreBufferSize, + false)); // Not executable. heap_->public_set_store_buffer_top(start_); hash_map_1_ = new uintptr_t[kHashMapLength]; @@ -90,10 +106,10 @@ void StoreBuffer::Setup() { void StoreBuffer::TearDown() { delete virtual_memory_; + delete old_virtual_memory_; delete[] hash_map_1_; delete[] hash_map_2_; - delete[] old_start_; - old_start_ = old_top_ = old_limit_ = NULL; + old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL; start_ = limit_ = NULL; heap_->public_set_store_buffer_top(start_); } @@ -150,7 +166,18 @@ void StoreBuffer::Uniq() { } -void StoreBuffer::HandleFullness() { +void StoreBuffer::EnsureSpace(intptr_t space_needed) { + while (old_limit_ - old_top_ < space_needed && + old_limit_ < old_reserved_limit_) { + size_t grow = old_limit_ - old_start_; // Double size. + CHECK(old_virtual_memory_->Commit(reinterpret_cast(old_limit_), + grow * kPointerSize, + false)); + old_limit_ += grow; + } + + if (old_limit_ - old_top_ >= space_needed) return; + if (old_buffer_is_filtered_) return; ASSERT(may_move_store_buffer_entries_); Compact(); @@ -645,9 +672,7 @@ void StoreBuffer::Compact() { // the worst case (compaction doesn't eliminate any pointers). ASSERT(top <= limit_); heap_->public_set_store_buffer_top(start_); - if (top - start_ > old_limit_ - old_top_) { - HandleFullness(); - } + EnsureSpace(top - start_); ASSERT(may_move_store_buffer_entries_); // Goes through the addresses in the store buffer attempting to remove // duplicates. In the interest of speed this is a lossy operation. Some @@ -688,9 +713,7 @@ void StoreBuffer::Compact() { void StoreBuffer::CheckForFullBuffer() { - if (old_limit_ - old_top_ < kStoreBufferSize * 2) { - HandleFullness(); - } + EnsureSpace(kStoreBufferSize * 2); } } } // namespace v8::internal diff --git a/src/store-buffer.h b/src/store-buffer.h index e5e50aeb7a..ab2593808f 100644 --- a/src/store-buffer.h +++ b/src/store-buffer.h @@ -109,7 +109,7 @@ class StoreBuffer { // been promoted. Rebuilds the store buffer completely if it overflowed. void SortUniq(); - void HandleFullness(); + void EnsureSpace(intptr_t space_needed); void Verify(); bool PrepareForIteration(); @@ -134,6 +134,8 @@ class StoreBuffer { Address* old_start_; Address* old_limit_; Address* old_top_; + Address* old_reserved_limit_; + VirtualMemory* old_virtual_memory_; bool old_buffer_is_sorted_; bool old_buffer_is_filtered_; diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index 51409c29b2..05abaf0b52 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -528,7 +528,7 @@ TEST(BootUpMemoryUse) { if (initial_memory >= 0) { InitializeVM(); intptr_t booted_memory = MemoryInUse(); - CHECK_LE(booted_memory - initial_memory, 20 * 1024 * 1024); + CHECK_LE(booted_memory - initial_memory, 18 * 1024 * 1024); } }