[heap] Introduce LocalHeap class

Instead of directly using the Heap class concurrent threads will use the
LocalHeap class for all heap operations.

Bug: v8:10315
Change-Id: Ie007abb5b914af7f2507c9e790f34baacbcdf588
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2096620
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66663}
This commit is contained in:
Dominik Inführ 2020-03-11 14:35:39 +01:00 committed by Commit Bot
parent 384b94170a
commit 82aaf737df
7 changed files with 201 additions and 0 deletions

View File

@ -2375,6 +2375,8 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/item-parallel-job.h",
"src/heap/local-allocator-inl.h",
"src/heap/local-allocator.h",
"src/heap/local-heap.cc",
"src/heap/local-heap.h",
"src/heap/mark-compact-inl.h",
"src/heap/mark-compact.cc",
"src/heap/mark-compact.h",

View File

@ -40,6 +40,7 @@
#include "src/heap/heap-write-barrier-inl.h"
#include "src/heap/incremental-marking-inl.h"
#include "src/heap/incremental-marking.h"
#include "src/heap/local-heap.h"
#include "src/heap/mark-compact-inl.h"
#include "src/heap/mark-compact.h"
#include "src/heap/memory-measurement.h"
@ -200,6 +201,7 @@ Heap::Heap()
: isolate_(isolate()),
memory_pressure_level_(MemoryPressureLevel::kNone),
global_pretenuring_feedback_(kInitialFeedbackCapacity),
local_heaps_head_(nullptr),
external_string_table_(this) {
// Ensure old_generation_size_ is a multiple of kPageSize.
DCHECK_EQ(0, max_old_generation_size_ & (Page::kPageSize - 1));
@ -3874,6 +3876,40 @@ void Heap::AppendArrayBufferExtension(JSArrayBuffer object,
array_buffer_sweeper_->Append(object, extension);
}
void Heap::AddLocalHeap(LocalHeap* local_heap) {
base::MutexGuard guard(&local_heaps_mutex_);
if (local_heaps_head_) local_heaps_head_->prev_ = local_heap;
local_heap->prev_ = nullptr;
local_heap->next_ = local_heaps_head_;
local_heaps_head_ = local_heap;
}
void Heap::RemoveLocalHeap(LocalHeap* local_heap) {
base::MutexGuard guard(&local_heaps_mutex_);
if (local_heap->next_) local_heap->next_->prev_ = local_heap->prev_;
if (local_heap->prev_)
local_heap->prev_->next_ = local_heap->next_;
else
local_heaps_head_ = local_heap->next_;
}
bool Heap::ContainsLocalHeap(LocalHeap* local_heap) {
base::MutexGuard guard(&local_heaps_mutex_);
LocalHeap* current = local_heaps_head_;
while (current) {
if (current == local_heap) return true;
current = current->next_;
}
return false;
}
bool Heap::ContainsAnyLocalHeap() {
base::MutexGuard guard(&local_heaps_mutex_);
return local_heaps_head_ != nullptr;
}
void Heap::AutomaticallyRestoreInitialHeapLimit(double threshold_percent) {
initial_max_old_generation_size_threshold_ =
initial_max_old_generation_size_ * threshold_percent;

View File

@ -72,6 +72,7 @@ class HeapStats;
class Isolate;
class JSFinalizationRegistry;
class LocalEmbedderHeapTracer;
class LocalHeap;
class MemoryAllocator;
class MemoryMeasurement;
class MemoryReducer;
@ -618,6 +619,11 @@ class Heap {
void AppendArrayBufferExtension(JSArrayBuffer object,
ArrayBufferExtension* extension);
void AddLocalHeap(LocalHeap* local_heap);
void RemoveLocalHeap(LocalHeap* local_heap);
V8_EXPORT_PRIVATE bool ContainsLocalHeap(LocalHeap* local_heap);
V8_EXPORT_PRIVATE bool ContainsAnyLocalHeap();
V8_EXPORT_PRIVATE double MonotonicallyIncreasingTimeInMs();
void RecordStats(HeapStats* stats, bool take_snapshot = false);
@ -2162,6 +2168,9 @@ class Heap {
GCCallbackFlags current_gc_callback_flags_ =
GCCallbackFlags::kNoGCCallbackFlags;
base::Mutex local_heaps_mutex_;
LocalHeap* local_heaps_head_;
bool is_current_gc_forced_ = false;
ExternalStringTable external_string_table_;

54
src/heap/local-heap.cc Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/local-heap.h"
#include "src/heap/heap.h"
namespace v8 {
namespace internal {
LocalHeap::LocalHeap(Heap* heap)
: heap_(heap),
state_(ThreadState::Running),
prev_(nullptr),
next_(nullptr) {
heap_->AddLocalHeap(this);
}
LocalHeap::~LocalHeap() { heap_->RemoveLocalHeap(this); }
void LocalHeap::Park() {
base::MutexGuard guard(&state_mutex_);
CHECK(state_ == ThreadState::Running);
state_ = ThreadState::Parked;
}
void LocalHeap::Unpark() {
base::MutexGuard guard(&state_mutex_);
CHECK(state_ == ThreadState::Parked);
state_ = ThreadState::Running;
}
void LocalHeap::RequestSafepoint() {
safepoint_requested_.store(true, std::memory_order_relaxed);
}
bool LocalHeap::IsSafepointRequested() {
return safepoint_requested_.load(std::memory_order_relaxed);
}
void LocalHeap::Safepoint() {
if (IsSafepointRequested()) {
EnterSafepoint();
}
}
void LocalHeap::ClearSafepointRequested() {
safepoint_requested_.store(false, std::memory_order_relaxed);
}
void LocalHeap::EnterSafepoint() { UNIMPLEMENTED(); }
} // namespace internal
} // namespace v8

62
src/heap/local-heap.h Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_LOCAL_HEAP_H_
#define V8_HEAP_LOCAL_HEAP_H_
#include <atomic>
#include "src/base/platform/condition-variable.h"
#include "src/base/platform/mutex.h"
namespace v8 {
namespace internal {
class Heap;
class LocalHeap {
public:
V8_EXPORT_PRIVATE explicit LocalHeap(Heap* heap);
V8_EXPORT_PRIVATE ~LocalHeap();
// Invoked by main thread to signal this thread that it needs to halt in a
// safepoint.
void RequestSafepoint();
// Frequently invoked by local thread to check whether safepoint was requested
// from the main thread.
void Safepoint();
private:
enum class ThreadState {
// Threads in this state need to be stopped in a safepoint.
Running,
// Thread was parked, which means that the thread is not allowed to access
// or manipulate the heap in any way.
Parked,
// Thread was stopped in a safepoint.
Safepoint
};
void Park();
void Unpark();
bool IsSafepointRequested();
void ClearSafepointRequested();
void EnterSafepoint();
Heap* heap_;
base::Mutex state_mutex_;
base::ConditionVariable state_condvar_;
ThreadState state_;
std::atomic<bool> safepoint_requested_;
LocalHeap* prev_;
LocalHeap* next_;
friend class Heap;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_LOCAL_HEAP_H_

View File

@ -170,6 +170,7 @@ v8_source_set("unittests_sources") {
"heap/heap-controller-unittest.cc",
"heap/heap-unittest.cc",
"heap/item-parallel-job-unittest.cc",
"heap/local-heap-unittest.cc",
"heap/marking-unittest.cc",
"heap/marking-worklist-unittest.cc",
"heap/memory-reducer-unittest.cc",

View File

@ -0,0 +1,37 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/local-heap.h"
#include "src/heap/heap.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
using LocalHeapTest = TestWithIsolate;
TEST_F(LocalHeapTest, Initialize) {
Heap* heap = i_isolate()->heap();
{
LocalHeap lh1(heap);
CHECK(heap->ContainsLocalHeap(&lh1));
LocalHeap lh2(heap);
CHECK(heap->ContainsLocalHeap(&lh2));
{
LocalHeap lh3(heap);
CHECK(heap->ContainsLocalHeap(&lh3));
}
CHECK(heap->ContainsLocalHeap(&lh1));
CHECK(heap->ContainsLocalHeap(&lh2));
}
CHECK(!heap->ContainsAnyLocalHeap());
}
} // namespace internal
} // namespace v8