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
This commit is contained in:
parent
c0e7884752
commit
0d7380da55
@ -1012,7 +1012,7 @@ void StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) {
|
|||||||
// Store Buffer overflowed while scanning promoted objects. These are not
|
// Store Buffer overflowed while scanning promoted objects. These are not
|
||||||
// in any particular page, though they are likely to be clustered by the
|
// in any particular page, though they are likely to be clustered by the
|
||||||
// allocation routines.
|
// allocation routines.
|
||||||
store_buffer_->HandleFullness();
|
store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize);
|
||||||
} else {
|
} else {
|
||||||
// Store Buffer overflowed while scanning a particular old space page for
|
// Store Buffer overflowed while scanning a particular old space page for
|
||||||
// pointers to new space.
|
// pointers to new space.
|
||||||
|
@ -70,6 +70,11 @@ intptr_t OS::MaxVirtualMemory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
intptr_t OS::CommitPageSize() {
|
||||||
|
return 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
// Get rid of writable permission on code allocations.
|
// Get rid of writable permission on code allocations.
|
||||||
void OS::ProtectCode(void* address, const size_t size) {
|
void OS::ProtectCode(void* address, const size_t size) {
|
||||||
|
@ -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) {
|
void OS::ProtectCode(void* address, const size_t size) {
|
||||||
DWORD old_protect;
|
DWORD old_protect;
|
||||||
VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
|
VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
|
||||||
|
@ -172,6 +172,10 @@ class OS {
|
|||||||
bool is_executable);
|
bool is_executable);
|
||||||
static void Free(void* address, const size_t size);
|
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.
|
// Mark code segments non-writable.
|
||||||
static void ProtectCode(void* address, const size_t size);
|
static void ProtectCode(void* address, const size_t size);
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ StoreBuffer::StoreBuffer(Heap* heap)
|
|||||||
old_start_(NULL),
|
old_start_(NULL),
|
||||||
old_limit_(NULL),
|
old_limit_(NULL),
|
||||||
old_top_(NULL),
|
old_top_(NULL),
|
||||||
|
old_reserved_limit_(NULL),
|
||||||
old_buffer_is_sorted_(false),
|
old_buffer_is_sorted_(false),
|
||||||
old_buffer_is_filtered_(false),
|
old_buffer_is_filtered_(false),
|
||||||
during_gc_(false),
|
during_gc_(false),
|
||||||
@ -59,10 +60,25 @@ void StoreBuffer::Setup() {
|
|||||||
reinterpret_cast<uintptr_t>(virtual_memory_->address());
|
reinterpret_cast<uintptr_t>(virtual_memory_->address());
|
||||||
start_ =
|
start_ =
|
||||||
reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
|
reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
|
||||||
limit_ = start_ + (kStoreBufferSize / sizeof(*start_));
|
limit_ = start_ + (kStoreBufferSize / kPointerSize);
|
||||||
|
|
||||||
old_top_ = old_start_ = new Address[kOldStoreBufferLength];
|
old_virtual_memory_ =
|
||||||
old_limit_ = old_start_ + kOldStoreBufferLength;
|
new VirtualMemory(kOldStoreBufferLength * kPointerSize);
|
||||||
|
old_top_ = old_start_ =
|
||||||
|
reinterpret_cast<Address*>(old_virtual_memory_->address());
|
||||||
|
// Don't know the alignment requirements of the OS, but it is certainly not
|
||||||
|
// less than 0xfff.
|
||||||
|
ASSERT((reinterpret_cast<uintptr_t>(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<void*>(old_start_),
|
||||||
|
(old_limit_ - old_start_) * kPointerSize,
|
||||||
|
false));
|
||||||
|
|
||||||
ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address());
|
ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address());
|
||||||
ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address());
|
ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address());
|
||||||
@ -76,9 +92,9 @@ void StoreBuffer::Setup() {
|
|||||||
ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) ==
|
ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) ==
|
||||||
0);
|
0);
|
||||||
|
|
||||||
virtual_memory_->Commit(reinterpret_cast<Address>(start_),
|
CHECK(virtual_memory_->Commit(reinterpret_cast<Address>(start_),
|
||||||
kStoreBufferSize,
|
kStoreBufferSize,
|
||||||
false); // Not executable.
|
false)); // Not executable.
|
||||||
heap_->public_set_store_buffer_top(start_);
|
heap_->public_set_store_buffer_top(start_);
|
||||||
|
|
||||||
hash_map_1_ = new uintptr_t[kHashMapLength];
|
hash_map_1_ = new uintptr_t[kHashMapLength];
|
||||||
@ -90,10 +106,10 @@ void StoreBuffer::Setup() {
|
|||||||
|
|
||||||
void StoreBuffer::TearDown() {
|
void StoreBuffer::TearDown() {
|
||||||
delete virtual_memory_;
|
delete virtual_memory_;
|
||||||
|
delete old_virtual_memory_;
|
||||||
delete[] hash_map_1_;
|
delete[] hash_map_1_;
|
||||||
delete[] hash_map_2_;
|
delete[] hash_map_2_;
|
||||||
delete[] old_start_;
|
old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
|
||||||
old_start_ = old_top_ = old_limit_ = NULL;
|
|
||||||
start_ = limit_ = NULL;
|
start_ = limit_ = NULL;
|
||||||
heap_->public_set_store_buffer_top(start_);
|
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<void*>(old_limit_),
|
||||||
|
grow * kPointerSize,
|
||||||
|
false));
|
||||||
|
old_limit_ += grow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_limit_ - old_top_ >= space_needed) return;
|
||||||
|
|
||||||
if (old_buffer_is_filtered_) return;
|
if (old_buffer_is_filtered_) return;
|
||||||
ASSERT(may_move_store_buffer_entries_);
|
ASSERT(may_move_store_buffer_entries_);
|
||||||
Compact();
|
Compact();
|
||||||
@ -645,9 +672,7 @@ void StoreBuffer::Compact() {
|
|||||||
// the worst case (compaction doesn't eliminate any pointers).
|
// the worst case (compaction doesn't eliminate any pointers).
|
||||||
ASSERT(top <= limit_);
|
ASSERT(top <= limit_);
|
||||||
heap_->public_set_store_buffer_top(start_);
|
heap_->public_set_store_buffer_top(start_);
|
||||||
if (top - start_ > old_limit_ - old_top_) {
|
EnsureSpace(top - start_);
|
||||||
HandleFullness();
|
|
||||||
}
|
|
||||||
ASSERT(may_move_store_buffer_entries_);
|
ASSERT(may_move_store_buffer_entries_);
|
||||||
// Goes through the addresses in the store buffer attempting to remove
|
// Goes through the addresses in the store buffer attempting to remove
|
||||||
// duplicates. In the interest of speed this is a lossy operation. Some
|
// duplicates. In the interest of speed this is a lossy operation. Some
|
||||||
@ -688,9 +713,7 @@ void StoreBuffer::Compact() {
|
|||||||
|
|
||||||
|
|
||||||
void StoreBuffer::CheckForFullBuffer() {
|
void StoreBuffer::CheckForFullBuffer() {
|
||||||
if (old_limit_ - old_top_ < kStoreBufferSize * 2) {
|
EnsureSpace(kStoreBufferSize * 2);
|
||||||
HandleFullness();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -109,7 +109,7 @@ class StoreBuffer {
|
|||||||
// been promoted. Rebuilds the store buffer completely if it overflowed.
|
// been promoted. Rebuilds the store buffer completely if it overflowed.
|
||||||
void SortUniq();
|
void SortUniq();
|
||||||
|
|
||||||
void HandleFullness();
|
void EnsureSpace(intptr_t space_needed);
|
||||||
void Verify();
|
void Verify();
|
||||||
|
|
||||||
bool PrepareForIteration();
|
bool PrepareForIteration();
|
||||||
@ -134,6 +134,8 @@ class StoreBuffer {
|
|||||||
Address* old_start_;
|
Address* old_start_;
|
||||||
Address* old_limit_;
|
Address* old_limit_;
|
||||||
Address* old_top_;
|
Address* old_top_;
|
||||||
|
Address* old_reserved_limit_;
|
||||||
|
VirtualMemory* old_virtual_memory_;
|
||||||
|
|
||||||
bool old_buffer_is_sorted_;
|
bool old_buffer_is_sorted_;
|
||||||
bool old_buffer_is_filtered_;
|
bool old_buffer_is_filtered_;
|
||||||
|
@ -528,7 +528,7 @@ TEST(BootUpMemoryUse) {
|
|||||||
if (initial_memory >= 0) {
|
if (initial_memory >= 0) {
|
||||||
InitializeVM();
|
InitializeVM();
|
||||||
intptr_t booted_memory = MemoryInUse();
|
intptr_t booted_memory = MemoryInUse();
|
||||||
CHECK_LE(booted_memory - initial_memory, 20 * 1024 * 1024);
|
CHECK_LE(booted_memory - initial_memory, 18 * 1024 * 1024);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user