Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Unified Diff: src/heap/spaces.cc

Issue 1913083002: [heap] Uncommit pooled pages concurrently (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/spaces.h ('k') | test/cctest/heap/test-spaces.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/spaces.cc
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index ff5a704e49aab49b030295a7a3584b6ec5caa9ba..97f16e49135af03dcbf2e4bbddae0c35ec831917 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -6,11 +6,13 @@
#include "src/base/bits.h"
#include "src/base/platform/platform.h"
+#include "src/base/platform/semaphore.h"
#include "src/full-codegen/full-codegen.h"
#include "src/heap/slot-set.h"
#include "src/macro-assembler.h"
#include "src/msan.h"
#include "src/snapshot/snapshot.h"
+#include "src/v8.h"
namespace v8 {
namespace internal {
@@ -303,7 +305,8 @@ MemoryAllocator::MemoryAllocator(Isolate* isolate)
size_(0),
size_executable_(0),
lowest_ever_allocated_(reinterpret_cast<void*>(-1)),
- highest_ever_allocated_(reinterpret_cast<void*>(0)) {}
+ highest_ever_allocated_(reinterpret_cast<void*>(0)),
+ unmapper_(this) {}
bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable,
intptr_t code_range_size) {
@@ -322,10 +325,14 @@ bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable,
void MemoryAllocator::TearDown() {
- for (MemoryChunk* chunk : chunk_pool_) {
+ unmapper()->WaitUntilCompleted();
+
+ MemoryChunk* chunk = nullptr;
+ while ((chunk = unmapper()->TryGetPooledMemoryChunkSafe()) != nullptr) {
FreeMemory(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize,
NOT_EXECUTABLE);
}
+
// Check that spaces were torn down before MemoryAllocator.
DCHECK_EQ(size_.Value(), 0);
// TODO(gc) this will be true again when we fix FreeMemory.
@@ -341,6 +348,55 @@ void MemoryAllocator::TearDown() {
code_range_ = nullptr;
}
+class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public v8::Task {
+ public:
+ explicit UnmapFreeMemoryTask(Unmapper* unmapper) : unmapper_(unmapper) {}
+
+ private:
+ // v8::Task overrides.
+ void Run() override {
+ unmapper_->PerformFreeMemoryOnQueuedChunks();
+ unmapper_->pending_unmapping_tasks_semaphore_.Signal();
+ }
+
+ Unmapper* unmapper_;
+ DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask);
+};
+
+void MemoryAllocator::Unmapper::FreeQueuedChunks() {
+ if (FLAG_concurrent_sweeping) {
+ V8::GetCurrentPlatform()->CallOnBackgroundThread(
+ new UnmapFreeMemoryTask(this), v8::Platform::kShortRunningTask);
+ concurrent_unmapping_tasks_active_++;
+ } else {
+ PerformFreeMemoryOnQueuedChunks();
+ }
+}
+
+bool MemoryAllocator::Unmapper::WaitUntilCompleted() {
+ bool waited = false;
+ while (concurrent_unmapping_tasks_active_ > 0) {
+ pending_unmapping_tasks_semaphore_.Wait();
+ concurrent_unmapping_tasks_active_--;
+ waited = true;
+ }
+ return waited;
+}
+
+void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() {
+ MemoryChunk* chunk = nullptr;
+ // Regular chunks.
+ while ((chunk = GetMemoryChunkSafe<kRegular>()) != nullptr) {
+ bool pooled = chunk->IsFlagSet(MemoryChunk::POOLED);
+ allocator_->PerformFreeMemory(chunk);
+ if (pooled) AddMemoryChunkSafe<kPooled>(chunk);
+ }
+ // Non-regular chunks.
+ while ((chunk = GetMemoryChunkSafe<kNonRegular>()) != nullptr) {
+ allocator_->PerformFreeMemory(chunk);
+ }
+}
+
bool MemoryAllocator::CommitMemory(Address base, size_t size,
Executability executable) {
if (!base::VirtualMemory::CommitRegion(base, size,
@@ -748,28 +804,45 @@ void MemoryAllocator::PerformFreeMemory(MemoryChunk* chunk) {
chunk->ReleaseAllocatedMemory();
base::VirtualMemory* reservation = chunk->reserved_memory();
- if (reservation->IsReserved()) {
- FreeMemory(reservation, chunk->executable());
+ if (chunk->IsFlagSet(MemoryChunk::POOLED)) {
+ UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
} else {
- FreeMemory(chunk->address(), chunk->size(), chunk->executable());
+ if (reservation->IsReserved()) {
+ FreeMemory(reservation, chunk->executable());
+ } else {
+ FreeMemory(chunk->address(), chunk->size(), chunk->executable());
+ }
}
}
-template <MemoryAllocator::AllocationMode mode>
+template <MemoryAllocator::FreeMode mode>
void MemoryAllocator::Free(MemoryChunk* chunk) {
- if (mode == kRegular) {
- PreFreeMemory(chunk);
- PerformFreeMemory(chunk);
- } else {
- DCHECK_EQ(mode, kPooled);
- FreePooled(chunk);
+ switch (mode) {
+ case kFull:
+ PreFreeMemory(chunk);
+ PerformFreeMemory(chunk);
+ break;
+ case kPooledAndQueue:
+ DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize));
+ DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE);
+ chunk->SetFlag(MemoryChunk::POOLED);
+ // Fall through to kPreFreeAndQueue.
+ case kPreFreeAndQueue:
+ PreFreeMemory(chunk);
+ // The chunks added to this queue will be freed by a concurrent thread.
+ unmapper()->AddMemoryChunkSafe(chunk);
+ break;
+ default:
+ UNREACHABLE();
}
}
-template void MemoryAllocator::Free<MemoryAllocator::kRegular>(
+template void MemoryAllocator::Free<MemoryAllocator::kFull>(MemoryChunk* chunk);
+
+template void MemoryAllocator::Free<MemoryAllocator::kPreFreeAndQueue>(
MemoryChunk* chunk);
-template void MemoryAllocator::Free<MemoryAllocator::kPooled>(
+template void MemoryAllocator::Free<MemoryAllocator::kPooledAndQueue>(
MemoryChunk* chunk);
template <typename PageType, MemoryAllocator::AllocationMode mode,
@@ -803,9 +876,9 @@ template NewSpacePage* MemoryAllocator::AllocatePage<
template <typename SpaceType>
MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) {
- if (chunk_pool_.is_empty()) return nullptr;
+ MemoryChunk* chunk = unmapper()->TryGetPooledMemoryChunkSafe();
+ if (chunk == nullptr) return nullptr;
const int size = MemoryChunk::kPageSize;
- MemoryChunk* chunk = chunk_pool_.RemoveLast();
const Address start = reinterpret_cast<Address>(chunk);
const Address area_start = start + MemoryChunk::kObjectStartOffset;
const Address area_end = start + size;
@@ -817,18 +890,6 @@ MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) {
return chunk;
}
-void MemoryAllocator::FreePooled(MemoryChunk* chunk) {
- DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize));
- DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE);
- chunk_pool_.Add(chunk);
- intptr_t chunk_size = static_cast<intptr_t>(chunk->size());
- if (chunk->executable() == EXECUTABLE) {
- size_executable_.Increment(-chunk_size);
- }
- size_.Increment(-chunk_size);
- UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
-}
-
bool MemoryAllocator::CommitBlock(Address start, size_t size,
Executability executable) {
if (!CommitMemory(start, size, executable)) return false;
@@ -971,12 +1032,16 @@ bool MemoryAllocator::CommitExecutableMemory(base::VirtualMemory* vm,
// MemoryChunk implementation
void MemoryChunk::ReleaseAllocatedMemory() {
- delete skip_list_;
- skip_list_ = nullptr;
- delete mutex_;
- mutex_ = nullptr;
- ReleaseOldToNewSlots();
- ReleaseOldToOldSlots();
+ if (skip_list_ != nullptr) {
+ delete skip_list_;
+ skip_list_ = nullptr;
+ }
+ if (mutex_ != nullptr) {
+ delete mutex_;
+ mutex_ = nullptr;
+ }
+ if (old_to_new_slots_ != nullptr) ReleaseOldToNewSlots();
+ if (old_to_old_slots_ != nullptr) ReleaseOldToOldSlots();
}
static SlotSet* AllocateSlotSet(size_t size, Address page_start) {
@@ -1060,7 +1125,7 @@ bool PagedSpace::HasBeenSetUp() { return true; }
void PagedSpace::TearDown() {
PageIterator iterator(this);
while (iterator.has_next()) {
- heap()->memory_allocator()->Free(iterator.next());
+ heap()->memory_allocator()->Free<MemoryAllocator::kFull>(iterator.next());
}
anchor_.set_next_page(&anchor_);
anchor_.set_prev_page(&anchor_);
@@ -1251,7 +1316,7 @@ void PagedSpace::ReleasePage(Page* page) {
}
AccountUncommitted(static_cast<intptr_t>(page->size()));
- heap()->QueueMemoryChunkForFree(page);
+ heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
DCHECK(Capacity() > 0);
accounting_stats_.ShrinkSpace(AreaSize());
@@ -1715,12 +1780,14 @@ bool SemiSpace::Uncommit() {
DCHECK(is_committed());
NewSpacePageIterator it(this);
while (it.has_next()) {
- heap()->memory_allocator()->Free<MemoryAllocator::kPooled>(it.next());
+ heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(
+ it.next());
}
anchor()->set_next_page(anchor());
anchor()->set_prev_page(anchor());
AccountUncommitted(current_capacity_);
committed_ = false;
+ heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
return true;
}
@@ -1798,10 +1865,12 @@ bool SemiSpace::ShrinkTo(int new_capacity) {
new_last_page = last_page->prev_page();
new_last_page->set_next_page(anchor());
anchor()->set_prev_page(new_last_page);
- heap()->memory_allocator()->Free<MemoryAllocator::kPooled>(last_page);
+ heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(
+ last_page);
delta_pages--;
}
AccountUncommitted(static_cast<intptr_t>(delta));
+ heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
}
current_capacity_ = new_capacity;
return true;
@@ -2894,7 +2963,7 @@ void LargeObjectSpace::TearDown() {
ObjectSpace space = static_cast<ObjectSpace>(1 << identity());
heap()->memory_allocator()->PerformAllocationCallback(
space, kAllocationActionFree, page->size());
- heap()->memory_allocator()->Free(page);
+ heap()->memory_allocator()->Free<MemoryAllocator::kFull>(page);
}
SetUp();
}
@@ -3037,7 +3106,7 @@ void LargeObjectSpace::FreeUnmarkedObjects() {
static_cast<uint32_t>(key));
}
- heap()->QueueMemoryChunkForFree(page);
+ heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
}
}
}
« no previous file with comments | « src/heap/spaces.h ('k') | test/cctest/heap/test-spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698