[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:
parent
384b94170a
commit
82aaf737df
2
BUILD.gn
2
BUILD.gn
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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
54
src/heap/local-heap.cc
Normal 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
62
src/heap/local-heap.h
Normal 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_
|
@ -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",
|
||||
|
37
test/unittests/heap/local-heap-unittest.cc
Normal file
37
test/unittests/heap/local-heap-unittest.cc
Normal 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
|
Loading…
Reference in New Issue
Block a user