Commit d10f61e1 authored by Omer Katz's avatar Omer Katz Committed by V8 LUCI CQ

cppgc-js, heap: Concurrently push references from v8 to Oilpan

Included in this CL:
(*) Introduce CppMarkingState that V8 should use to push references to
    Oilpan. CppMarkingState allocates its own Worklist::Locals to
    support concurrent updates from V8.
(*) Split Oilpan MarkingWorklist object to form a base class used by
    CppMarkingState.
(*) Remove MarkerFactory and split marking initialization. Marking
    worklists should already be initialized when V8 initializes
    visitors. For incremental marking, this requires splitting
    marking initialization and marking start.
(*) Drive-by: Mark JSObject::IsApiWrapper and
    JSObject::IsDroppableApiWrapper as const.

Bug: v8:12407
Change-Id: I35cc816343da86f69a68306204675720e9b3913f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3293410Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78446}
parent b014d0ba
...@@ -1317,6 +1317,8 @@ filegroup( ...@@ -1317,6 +1317,8 @@ filegroup(
"src/heap/concurrent-marking.h", "src/heap/concurrent-marking.h",
"src/heap/cppgc-js/cpp-heap.cc", "src/heap/cppgc-js/cpp-heap.cc",
"src/heap/cppgc-js/cpp-heap.h", "src/heap/cppgc-js/cpp-heap.h",
"src/heap/cppgc-js/cpp-marking-state.h",
"src/heap/cppgc-js/cpp-marking-state-inl.h",
"src/heap/cppgc-js/cpp-snapshot.cc", "src/heap/cppgc-js/cpp-snapshot.cc",
"src/heap/cppgc-js/cpp-snapshot.h", "src/heap/cppgc-js/cpp-snapshot.h",
"src/heap/cppgc-js/unified-heap-marking-state.h", "src/heap/cppgc-js/unified-heap-marking-state.h",
...@@ -1326,6 +1328,7 @@ filegroup( ...@@ -1326,6 +1328,7 @@ filegroup(
"src/heap/cppgc-js/unified-heap-marking-visitor.h", "src/heap/cppgc-js/unified-heap-marking-visitor.h",
"src/heap/embedder-tracing.cc", "src/heap/embedder-tracing.cc",
"src/heap/embedder-tracing.h", "src/heap/embedder-tracing.h",
"src/heap/embedder-tracing-inl.h",
"src/heap/factory-base.cc", "src/heap/factory-base.cc",
"src/heap/factory-base.h", "src/heap/factory-base.h",
"src/heap/factory-base-inl.h", "src/heap/factory-base-inl.h",
......
...@@ -2931,10 +2931,13 @@ v8_header_set("v8_internal_headers") { ...@@ -2931,10 +2931,13 @@ v8_header_set("v8_internal_headers") {
"src/heap/concurrent-allocator.h", "src/heap/concurrent-allocator.h",
"src/heap/concurrent-marking.h", "src/heap/concurrent-marking.h",
"src/heap/cppgc-js/cpp-heap.h", "src/heap/cppgc-js/cpp-heap.h",
"src/heap/cppgc-js/cpp-marking-state-inl.h",
"src/heap/cppgc-js/cpp-marking-state.h",
"src/heap/cppgc-js/cpp-snapshot.h", "src/heap/cppgc-js/cpp-snapshot.h",
"src/heap/cppgc-js/unified-heap-marking-state.h", "src/heap/cppgc-js/unified-heap-marking-state.h",
"src/heap/cppgc-js/unified-heap-marking-verifier.h", "src/heap/cppgc-js/unified-heap-marking-verifier.h",
"src/heap/cppgc-js/unified-heap-marking-visitor.h", "src/heap/cppgc-js/unified-heap-marking-visitor.h",
"src/heap/embedder-tracing-inl.h",
"src/heap/embedder-tracing.h", "src/heap/embedder-tracing.h",
"src/heap/factory-base-inl.h", "src/heap/factory-base-inl.h",
"src/heap/factory-base.h", "src/heap/factory-base.h",
......
...@@ -451,7 +451,11 @@ void ConcurrentMarking::Run(JobDelegate* delegate, ...@@ -451,7 +451,11 @@ void ConcurrentMarking::Run(JobDelegate* delegate,
int kObjectsUntilInterrupCheck = 1000; int kObjectsUntilInterrupCheck = 1000;
uint8_t task_id = delegate->GetTaskId() + 1; uint8_t task_id = delegate->GetTaskId() + 1;
TaskState* task_state = &task_state_[task_id]; TaskState* task_state = &task_state_[task_id];
MarkingWorklists::Local local_marking_worklists(marking_worklists_); auto* cpp_heap = CppHeap::From(heap_->cpp_heap());
MarkingWorklists::Local local_marking_worklists(
marking_worklists_, cpp_heap
? cpp_heap->CreateCppMarkingState()
: MarkingWorklists::Local::kNoCppMarkingState);
WeakObjects::Local local_weak_objects(weak_objects_); WeakObjects::Local local_weak_objects(weak_objects_);
ConcurrentMarkingVisitor visitor( ConcurrentMarkingVisitor visitor(
task_id, &local_marking_worklists, &local_weak_objects, heap_, task_id, &local_marking_worklists, &local_weak_objects, heap_,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "src/handles/global-handles.h" #include "src/handles/global-handles.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/heap/base/stack.h" #include "src/heap/base/stack.h"
#include "src/heap/cppgc-js/cpp-marking-state.h"
#include "src/heap/cppgc-js/cpp-snapshot.h" #include "src/heap/cppgc-js/cpp-snapshot.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h" #include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/cppgc-js/unified-heap-marking-verifier.h" #include "src/heap/cppgc-js/unified-heap-marking-verifier.h"
...@@ -172,13 +173,17 @@ UnifiedHeapConcurrentMarker::CreateConcurrentMarkingVisitor( ...@@ -172,13 +173,17 @@ UnifiedHeapConcurrentMarker::CreateConcurrentMarkingVisitor(
class UnifiedHeapMarker final : public cppgc::internal::MarkerBase { class UnifiedHeapMarker final : public cppgc::internal::MarkerBase {
public: public:
UnifiedHeapMarker(Key, Heap* v8_heap, cppgc::internal::HeapBase& cpp_heap, UnifiedHeapMarker(Heap* v8_heap, cppgc::internal::HeapBase& cpp_heap,
cppgc::Platform* platform, MarkingConfig config); cppgc::Platform* platform, MarkingConfig config);
~UnifiedHeapMarker() final = default; ~UnifiedHeapMarker() final = default;
void AddObject(void*); void AddObject(void*);
cppgc::internal::MarkingWorklists& GetMarkingWorklists() {
return marking_worklists_;
}
protected: protected:
cppgc::Visitor& visitor() final { return marking_visitor_; } cppgc::Visitor& visitor() final { return marking_visitor_; }
cppgc::internal::ConservativeTracingVisitor& conservative_visitor() final { cppgc::internal::ConservativeTracingVisitor& conservative_visitor() final {
...@@ -194,11 +199,11 @@ class UnifiedHeapMarker final : public cppgc::internal::MarkerBase { ...@@ -194,11 +199,11 @@ class UnifiedHeapMarker final : public cppgc::internal::MarkerBase {
cppgc::internal::ConservativeMarkingVisitor conservative_marking_visitor_; cppgc::internal::ConservativeMarkingVisitor conservative_marking_visitor_;
}; };
UnifiedHeapMarker::UnifiedHeapMarker(Key key, Heap* v8_heap, UnifiedHeapMarker::UnifiedHeapMarker(Heap* v8_heap,
cppgc::internal::HeapBase& heap, cppgc::internal::HeapBase& heap,
cppgc::Platform* platform, cppgc::Platform* platform,
MarkingConfig config) MarkingConfig config)
: cppgc::internal::MarkerBase(key, heap, platform, config), : cppgc::internal::MarkerBase(heap, platform, config),
unified_heap_marking_state_(v8_heap), unified_heap_marking_state_(v8_heap),
marking_visitor_(heap, mutator_marking_state_, marking_visitor_(heap, mutator_marking_state_,
unified_heap_marking_state_), unified_heap_marking_state_),
...@@ -391,17 +396,6 @@ void CppHeap::DetachIsolate() { ...@@ -391,17 +396,6 @@ void CppHeap::DetachIsolate() {
no_gc_scope_++; no_gc_scope_++;
} }
void CppHeap::RegisterV8References(
const std::vector<std::pair<void*, void*> >& embedder_fields) {
DCHECK(marker_);
for (auto& tuple : embedder_fields) {
// First field points to type.
// Second field points to object.
static_cast<UnifiedHeapMarker*>(marker_.get())->AddObject(tuple.second);
}
marking_done_ = false;
}
namespace { namespace {
bool IsMemoryReducingGC(CppHeap::GarbageCollectionFlags flags) { bool IsMemoryReducingGC(CppHeap::GarbageCollectionFlags flags) {
...@@ -417,7 +411,8 @@ bool ShouldReduceMemory(CppHeap::GarbageCollectionFlags flags) { ...@@ -417,7 +411,8 @@ bool ShouldReduceMemory(CppHeap::GarbageCollectionFlags flags) {
} }
} // namespace } // namespace
void CppHeap::TracePrologue(GarbageCollectionFlags gc_flags) {
void CppHeap::InitializeTracing(GarbageCollectionFlags gc_flags) {
CHECK(!sweeper_.IsSweepingInProgress()); CHECK(!sweeper_.IsSweepingInProgress());
#if defined(CPPGC_YOUNG_GENERATION) #if defined(CPPGC_YOUNG_GENERATION)
...@@ -445,10 +440,13 @@ void CppHeap::TracePrologue(GarbageCollectionFlags gc_flags) { ...@@ -445,10 +440,13 @@ void CppHeap::TracePrologue(GarbageCollectionFlags gc_flags) {
compactor_.InitializeIfShouldCompact(marking_config.marking_type, compactor_.InitializeIfShouldCompact(marking_config.marking_type,
marking_config.stack_state); marking_config.stack_state);
} }
marker_ = marker_ = std::make_unique<UnifiedHeapMarker>(
cppgc::internal::MarkerFactory::CreateAndStartMarking<UnifiedHeapMarker>( isolate_ ? isolate()->heap() : nullptr, AsBase(), platform_.get(),
isolate_ ? isolate_->heap() : nullptr, AsBase(), platform_.get(), marking_config);
marking_config); }
void CppHeap::StartTracing() {
marker_->StartMarking();
marking_done_ = false; marking_done_ = false;
} }
...@@ -593,7 +591,10 @@ void CppHeap::CollectGarbageForTesting( ...@@ -593,7 +591,10 @@ void CppHeap::CollectGarbageForTesting(
} else { } else {
// Perform an atomic GC, with starting incremental/concurrent marking and // Perform an atomic GC, with starting incremental/concurrent marking and
// immediately finalizing the garbage collection. // immediately finalizing the garbage collection.
if (!IsMarking()) TracePrologue(GarbageCollectionFlagValues::kForced); if (!IsMarking()) {
InitializeTracing(GarbageCollectionFlagValues::kForced);
StartTracing();
}
EnterFinalPause(stack_state); EnterFinalPause(stack_state);
AdvanceTracing(std::numeric_limits<double>::infinity()); AdvanceTracing(std::numeric_limits<double>::infinity());
TraceEpilogue(); TraceEpilogue();
...@@ -614,7 +615,8 @@ void CppHeap::StartIncrementalGarbageCollectionForTesting() { ...@@ -614,7 +615,8 @@ void CppHeap::StartIncrementalGarbageCollectionForTesting() {
DCHECK_NULL(isolate_); DCHECK_NULL(isolate_);
if (IsMarking()) return; if (IsMarking()) return;
force_incremental_marking_for_testing_ = true; force_incremental_marking_for_testing_ = true;
TracePrologue(GarbageCollectionFlagValues::kForced); InitializeTracing(GarbageCollectionFlagValues::kForced);
StartTracing();
force_incremental_marking_for_testing_ = false; force_incremental_marking_for_testing_ = false;
} }
...@@ -713,5 +715,12 @@ CppHeap::MetricRecorderAdapter* CppHeap::GetMetricRecorder() const { ...@@ -713,5 +715,12 @@ CppHeap::MetricRecorderAdapter* CppHeap::GetMetricRecorder() const {
void CppHeap::FinishSweepingIfRunning() { sweeper_.FinishIfRunning(); } void CppHeap::FinishSweepingIfRunning() { sweeper_.FinishIfRunning(); }
std::unique_ptr<CppMarkingState> CppHeap::CreateCppMarkingState() {
DCHECK(IsMarking());
return std::make_unique<CppMarkingState>(
*this, wrapper_descriptor_,
static_cast<UnifiedHeapMarker*>(marker())->GetMarkingWorklists());
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -25,6 +25,8 @@ class Isolate; ...@@ -25,6 +25,8 @@ class Isolate;
namespace internal { namespace internal {
class CppMarkingState;
// A C++ heap implementation used with V8 to implement unified heap. // A C++ heap implementation used with V8 to implement unified heap.
class V8_EXPORT_PRIVATE CppHeap final class V8_EXPORT_PRIVATE CppHeap final
: public cppgc::internal::HeapBase, : public cppgc::internal::HeapBase,
...@@ -113,9 +115,8 @@ class V8_EXPORT_PRIVATE CppHeap final ...@@ -113,9 +115,8 @@ class V8_EXPORT_PRIVATE CppHeap final
void FinishSweepingIfRunning(); void FinishSweepingIfRunning();
void RegisterV8References( void InitializeTracing(GarbageCollectionFlags);
const std::vector<std::pair<void*, void*>>& embedder_fields); void StartTracing();
void TracePrologue(GarbageCollectionFlags);
bool AdvanceTracing(double max_duration); bool AdvanceTracing(double max_duration);
bool IsTracingDone(); bool IsTracingDone();
void TraceEpilogue(); void TraceEpilogue();
...@@ -134,6 +135,8 @@ class V8_EXPORT_PRIVATE CppHeap final ...@@ -134,6 +135,8 @@ class V8_EXPORT_PRIVATE CppHeap final
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
std::unique_ptr<CppMarkingState> CreateCppMarkingState();
private: private:
void FinalizeIncrementalGarbageCollectionIfNeeded( void FinalizeIncrementalGarbageCollectionIfNeeded(
cppgc::Heap::StackState) final { cppgc::Heap::StackState) final {
......
// Copyright 2021 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_CPPGC_JS_CPP_MARKING_STATE_INL_H_
#define V8_HEAP_CPPGC_JS_CPP_MARKING_STATE_INL_H_
#include "src/heap/cppgc-js/cpp-marking-state.h"
#include "src/heap/embedder-tracing-inl.h"
#include "src/objects/js-objects.h"
namespace v8 {
namespace internal {
void CppMarkingState::MarkAndPush(const JSObject& js_object) {
DCHECK(js_object.IsApiWrapper());
LocalEmbedderHeapTracer::WrapperInfo info;
if (LocalEmbedderHeapTracer::ExtractWrappableInfo(
isolate_, js_object, wrapper_descriptor_, &info)) {
marking_state_.MarkAndPush(
cppgc::internal::HeapObjectHeader::FromObject(info.second));
}
}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_CPPGC_JS_CPP_MARKING_STATE_INL_H_
// Copyright 2021 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_CPPGC_JS_CPP_MARKING_STATE_H_
#define V8_HEAP_CPPGC_JS_CPP_MARKING_STATE_H_
#include "src/heap/cppgc-js/cpp-heap.h"
#include "src/heap/cppgc/marking-state.h"
#include "src/heap/cppgc/marking-worklists.h"
namespace v8 {
namespace internal {
class JSObject;
class CppMarkingState {
public:
CppMarkingState(CppHeap& cpp_heap,
const WrapperDescriptor& wrapper_descriptor,
cppgc::internal::MarkingWorklists& marking_worklists)
: isolate_(reinterpret_cast<Isolate*>(cpp_heap.isolate())),
wrapper_descriptor_(wrapper_descriptor),
marking_state_(cpp_heap.AsBase(), marking_worklists) {}
CppMarkingState(const CppMarkingState&) = delete;
CppMarkingState& operator=(const CppMarkingState&) = delete;
void Publish() { marking_state_.Publish(); }
inline void MarkAndPush(const JSObject& js_object);
bool IsLocalEmpty() {
return marking_state_.marking_worklist().IsLocalEmpty();
}
private:
Isolate* const isolate_;
const WrapperDescriptor& wrapper_descriptor_;
cppgc::internal::MarkingStateBase marking_state_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_CPPGC_JS_CPP_MARKING_STATE_H_
...@@ -13,7 +13,7 @@ namespace v8 { ...@@ -13,7 +13,7 @@ namespace v8 {
namespace internal { namespace internal {
UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase( UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase(
HeapBase& heap, cppgc::internal::MarkingStateBase& marking_state, HeapBase& heap, cppgc::internal::BasicMarkingState& marking_state,
UnifiedHeapMarkingState& unified_heap_marking_state) UnifiedHeapMarkingState& unified_heap_marking_state)
: JSVisitor(cppgc::internal::VisitorFactory::CreateKey()), : JSVisitor(cppgc::internal::VisitorFactory::CreateKey()),
marking_state_(marking_state), marking_state_(marking_state),
......
...@@ -17,7 +17,7 @@ class SourceLocation; ...@@ -17,7 +17,7 @@ class SourceLocation;
namespace internal { namespace internal {
class ConcurrentMarkingState; class ConcurrentMarkingState;
class MarkingStateBase; class BasicMarkingState;
class MutatorMarkingState; class MutatorMarkingState;
} // namespace internal } // namespace internal
} // namespace cppgc } // namespace cppgc
...@@ -33,7 +33,7 @@ using cppgc::internal::MutatorMarkingState; ...@@ -33,7 +33,7 @@ using cppgc::internal::MutatorMarkingState;
class V8_EXPORT_PRIVATE UnifiedHeapMarkingVisitorBase : public JSVisitor { class V8_EXPORT_PRIVATE UnifiedHeapMarkingVisitorBase : public JSVisitor {
public: public:
UnifiedHeapMarkingVisitorBase(HeapBase&, cppgc::internal::MarkingStateBase&, UnifiedHeapMarkingVisitorBase(HeapBase&, cppgc::internal::BasicMarkingState&,
UnifiedHeapMarkingState&); UnifiedHeapMarkingState&);
~UnifiedHeapMarkingVisitorBase() override = default; ~UnifiedHeapMarkingVisitorBase() override = default;
...@@ -51,7 +51,7 @@ class V8_EXPORT_PRIVATE UnifiedHeapMarkingVisitorBase : public JSVisitor { ...@@ -51,7 +51,7 @@ class V8_EXPORT_PRIVATE UnifiedHeapMarkingVisitorBase : public JSVisitor {
// JS handling. // JS handling.
void Visit(const TracedReferenceBase& ref) final; void Visit(const TracedReferenceBase& ref) final;
cppgc::internal::MarkingStateBase& marking_state_; cppgc::internal::BasicMarkingState& marking_state_;
UnifiedHeapMarkingState& unified_heap_marking_state_; UnifiedHeapMarkingState& unified_heap_marking_state_;
}; };
......
...@@ -159,8 +159,8 @@ void Heap::StartGarbageCollection(Config config) { ...@@ -159,8 +159,8 @@ void Heap::StartGarbageCollection(Config config) {
const Marker::MarkingConfig marking_config{ const Marker::MarkingConfig marking_config{
config.collection_type, config.stack_state, config.marking_type, config.collection_type, config.stack_state, config.marking_type,
config.is_forced_gc}; config.is_forced_gc};
marker_ = MarkerFactory::CreateAndStartMarking<Marker>( marker_ = std::make_unique<Marker>(AsBase(), platform_.get(), marking_config);
AsBase(), platform_.get(), marking_config); marker_->StartMarking();
} }
void Heap::FinalizeGarbageCollection(Config::StackState stack_state) { void Heap::FinalizeGarbageCollection(Config::StackState stack_state) {
......
...@@ -86,7 +86,7 @@ static constexpr size_t kDefaultDeadlineCheckInterval = 150u; ...@@ -86,7 +86,7 @@ static constexpr size_t kDefaultDeadlineCheckInterval = 150u;
template <size_t kDeadlineCheckInterval = kDefaultDeadlineCheckInterval, template <size_t kDeadlineCheckInterval = kDefaultDeadlineCheckInterval,
typename WorklistLocal, typename Callback> typename WorklistLocal, typename Callback>
bool DrainWorklistWithBytesAndTimeDeadline(MarkingStateBase& marking_state, bool DrainWorklistWithBytesAndTimeDeadline(BasicMarkingState& marking_state,
size_t marked_bytes_deadline, size_t marked_bytes_deadline,
v8::base::TimeTicks time_deadline, v8::base::TimeTicks time_deadline,
WorklistLocal& worklist_local, WorklistLocal& worklist_local,
...@@ -153,7 +153,7 @@ void MarkerBase::IncrementalMarkingTask::Run() { ...@@ -153,7 +153,7 @@ void MarkerBase::IncrementalMarkingTask::Run() {
} }
} }
MarkerBase::MarkerBase(Key, HeapBase& heap, cppgc::Platform* platform, MarkerBase::MarkerBase(HeapBase& heap, cppgc::Platform* platform,
MarkingConfig config) MarkingConfig config)
: heap_(heap), : heap_(heap),
config_(config), config_(config),
...@@ -624,9 +624,8 @@ void MarkerBase::WaitForConcurrentMarkingForTesting() { ...@@ -624,9 +624,8 @@ void MarkerBase::WaitForConcurrentMarkingForTesting() {
concurrent_marker_->JoinForTesting(); concurrent_marker_->JoinForTesting();
} }
Marker::Marker(Key key, HeapBase& heap, cppgc::Platform* platform, Marker::Marker(HeapBase& heap, cppgc::Platform* platform, MarkingConfig config)
MarkingConfig config) : MarkerBase(heap, platform, config),
: MarkerBase(key, heap, platform, config),
marking_visitor_(heap, mutator_marking_state_), marking_visitor_(heap, mutator_marking_state_),
conservative_marking_visitor_(heap, mutator_marking_state_, conservative_marking_visitor_(heap, mutator_marking_state_,
marking_visitor_) { marking_visitor_) {
......
...@@ -24,12 +24,10 @@ namespace cppgc { ...@@ -24,12 +24,10 @@ namespace cppgc {
namespace internal { namespace internal {
class HeapBase; class HeapBase;
class MarkerFactory;
// Marking algorithm. Example for a valid call sequence creating the marking // Marking algorithm. Example for a valid call sequence creating the marking
// phase: // phase:
// 1. StartMarking() [Called implicitly when creating a Marker using // 1. StartMarking()
// MarkerFactory]
// 2. AdvanceMarkingWithLimits() [Optional, depending on environment.] // 2. AdvanceMarkingWithLimits() [Optional, depending on environment.]
// 3. EnterAtomicPause() // 3. EnterAtomicPause()
// 4. AdvanceMarkingWithLimits() // 4. AdvanceMarkingWithLimits()
...@@ -87,6 +85,10 @@ class V8_EXPORT_PRIVATE MarkerBase { ...@@ -87,6 +85,10 @@ class V8_EXPORT_PRIVATE MarkerBase {
// objects to be marked and merely updates marking states if needed. // objects to be marked and merely updates marking states if needed.
void LeaveAtomicPause(); void LeaveAtomicPause();
// Initialize marking according to the given config. This method will
// trigger incremental/concurrent marking if needed.
void StartMarking();
// Combines: // Combines:
// - EnterAtomicPause() // - EnterAtomicPause()
// - AdvanceMarkingWithLimits() // - AdvanceMarkingWithLimits()
...@@ -141,17 +143,7 @@ class V8_EXPORT_PRIVATE MarkerBase { ...@@ -141,17 +143,7 @@ class V8_EXPORT_PRIVATE MarkerBase {
static constexpr v8::base::TimeDelta kMaximumIncrementalStepDuration = static constexpr v8::base::TimeDelta kMaximumIncrementalStepDuration =
v8::base::TimeDelta::FromMilliseconds(2); v8::base::TimeDelta::FromMilliseconds(2);
class Key { MarkerBase(HeapBase&, cppgc::Platform*, MarkingConfig);
private:
Key() = default;
friend class MarkerFactory;
};
MarkerBase(Key, HeapBase&, cppgc::Platform*, MarkingConfig);
// Initialize marking according to the given config. This method will
// trigger incremental/concurrent marking if needed.
void StartMarking();
virtual cppgc::Visitor& visitor() = 0; virtual cppgc::Visitor& visitor() = 0;
virtual ConservativeTracingVisitor& conservative_visitor() = 0; virtual ConservativeTracingVisitor& conservative_visitor() = 0;
...@@ -195,27 +187,11 @@ class V8_EXPORT_PRIVATE MarkerBase { ...@@ -195,27 +187,11 @@ class V8_EXPORT_PRIVATE MarkerBase {
bool main_marking_disabled_for_testing_{false}; bool main_marking_disabled_for_testing_{false};
bool visited_cross_thread_persistents_in_atomic_pause_{false}; bool visited_cross_thread_persistents_in_atomic_pause_{false};
friend class MarkerFactory;
};
class V8_EXPORT_PRIVATE MarkerFactory {
public:
template <typename T, typename... Args>
static std::unique_ptr<T> CreateAndStartMarking(Args&&... args) {
static_assert(std::is_base_of<MarkerBase, T>::value,
"MarkerFactory can only create subclasses of MarkerBase");
std::unique_ptr<T> marker =
std::make_unique<T>(MarkerBase::Key(), std::forward<Args>(args)...);
marker->StartMarking();
return marker;
}
}; };
class V8_EXPORT_PRIVATE Marker final : public MarkerBase { class V8_EXPORT_PRIVATE Marker final : public MarkerBase {
public: public:
Marker(Key, HeapBase&, cppgc::Platform*, Marker(HeapBase&, cppgc::Platform*, MarkingConfig = MarkingConfig::Default());
MarkingConfig = MarkingConfig::Default());
protected: protected:
cppgc::Visitor& visitor() final { return marking_visitor_; } cppgc::Visitor& visitor() final { return marking_visitor_; }
......
...@@ -23,8 +23,7 @@ namespace internal { ...@@ -23,8 +23,7 @@ namespace internal {
// C++ marking implementation. // C++ marking implementation.
class MarkingStateBase { class MarkingStateBase {
public: public:
inline MarkingStateBase(HeapBase& heap, MarkingWorklists&, inline MarkingStateBase(HeapBase&, MarkingWorklists&);
CompactionWorklists*);
MarkingStateBase(const MarkingStateBase&) = delete; MarkingStateBase(const MarkingStateBase&) = delete;
MarkingStateBase& operator=(const MarkingStateBase&) = delete; MarkingStateBase& operator=(const MarkingStateBase&) = delete;
...@@ -34,6 +33,86 @@ class MarkingStateBase { ...@@ -34,6 +33,86 @@ class MarkingStateBase {
inline void PushMarked(HeapObjectHeader&, TraceDescriptor desc); inline void PushMarked(HeapObjectHeader&, TraceDescriptor desc);
void Publish() { marking_worklist_.Publish(); }
MarkingWorklists::MarkingWorklist::Local& marking_worklist() {
return marking_worklist_;
}
MarkingWorklists::NotFullyConstructedWorklist&
not_fully_constructed_worklist() {
return not_fully_constructed_worklist_;
}
protected:
inline void MarkAndPush(HeapObjectHeader&, TraceDescriptor);
inline bool MarkNoPush(HeapObjectHeader&);
HeapBase& heap_;
MarkingWorklists::MarkingWorklist::Local marking_worklist_;
MarkingWorklists::NotFullyConstructedWorklist&
not_fully_constructed_worklist_;
};
MarkingStateBase::MarkingStateBase(HeapBase& heap,
MarkingWorklists& marking_worklists)
: heap_(heap),
marking_worklist_(marking_worklists.marking_worklist()),
not_fully_constructed_worklist_(
*marking_worklists.not_fully_constructed_worklist()) {}
void MarkingStateBase::MarkAndPush(const void* object, TraceDescriptor desc) {
DCHECK_NOT_NULL(object);
MarkAndPush(
HeapObjectHeader::FromObject(const_cast<void*>(desc.base_object_payload)),
desc);
}
void MarkingStateBase::MarkAndPush(HeapObjectHeader& header,
TraceDescriptor desc) {
DCHECK_NOT_NULL(desc.callback);
if (header.IsInConstruction<AccessMode::kAtomic>()) {
not_fully_constructed_worklist_.Push<AccessMode::kAtomic>(&header);
} else if (MarkNoPush(header)) {
PushMarked(header, desc);
}
}
bool MarkingStateBase::MarkNoPush(HeapObjectHeader& header) {
// A GC should only mark the objects that belong in its heap.
DCHECK_EQ(&heap_, &BasePage::FromPayload(&header)->heap());
// Never mark free space objects. This would e.g. hint to marking a promptly
// freed backing store.
DCHECK(!header.IsFree<AccessMode::kAtomic>());
return header.TryMarkAtomic();
}
void MarkingStateBase::MarkAndPush(HeapObjectHeader& header) {
MarkAndPush(
header,
{header.ObjectStart(),
GlobalGCInfoTable::GCInfoFromIndex(header.GetGCInfoIndex()).trace});
}
void MarkingStateBase::PushMarked(HeapObjectHeader& header,
TraceDescriptor desc) {
DCHECK(header.IsMarked<AccessMode::kAtomic>());
DCHECK(!header.IsInConstruction<AccessMode::kAtomic>());
DCHECK_NOT_NULL(desc.callback);
marking_worklist_.Push(desc);
}
class BasicMarkingState : public MarkingStateBase {
public:
inline BasicMarkingState(HeapBase& heap, MarkingWorklists&,
CompactionWorklists*);
BasicMarkingState(const BasicMarkingState&) = delete;
BasicMarkingState& operator=(const BasicMarkingState&) = delete;
inline void RegisterWeakReferenceIfNeeded(const void*, TraceDescriptor, inline void RegisterWeakReferenceIfNeeded(const void*, TraceDescriptor,
WeakCallback, const void*); WeakCallback, const void*);
inline void RegisterWeakCallback(WeakCallback, const void*); inline void RegisterWeakCallback(WeakCallback, const void*);
...@@ -58,7 +137,7 @@ class MarkingStateBase { ...@@ -58,7 +137,7 @@ class MarkingStateBase {
size_t marked_bytes() const { return marked_bytes_; } size_t marked_bytes() const { return marked_bytes_; }
void Publish() { void Publish() {
marking_worklist_.Publish(); MarkingStateBase::Publish();
previously_not_fully_constructed_worklist_.Publish(); previously_not_fully_constructed_worklist_.Publish();
weak_callback_worklist_.Publish(); weak_callback_worklist_.Publish();
write_barrier_worklist_.Publish(); write_barrier_worklist_.Publish();
...@@ -68,13 +147,6 @@ class MarkingStateBase { ...@@ -68,13 +147,6 @@ class MarkingStateBase {
if (IsCompactionEnabled()) movable_slots_worklist_->Publish(); if (IsCompactionEnabled()) movable_slots_worklist_->Publish();
} }
MarkingWorklists::MarkingWorklist::Local& marking_worklist() {
return marking_worklist_;
}
MarkingWorklists::NotFullyConstructedWorklist&
not_fully_constructed_worklist() {
return not_fully_constructed_worklist_;
}
MarkingWorklists::PreviouslyNotFullyConstructedWorklist::Local& MarkingWorklists::PreviouslyNotFullyConstructedWorklist::Local&
previously_not_fully_constructed_worklist() { previously_not_fully_constructed_worklist() {
return previously_not_fully_constructed_worklist_; return previously_not_fully_constructed_worklist_;
...@@ -121,21 +193,12 @@ class MarkingStateBase { ...@@ -121,21 +193,12 @@ class MarkingStateBase {
void set_in_atomic_pause() { in_atomic_pause_ = true; } void set_in_atomic_pause() { in_atomic_pause_ = true; }
protected: protected:
inline void MarkAndPush(HeapObjectHeader&, TraceDescriptor);
inline bool MarkNoPush(HeapObjectHeader&);
inline void RegisterWeakContainer(HeapObjectHeader&); inline void RegisterWeakContainer(HeapObjectHeader&);
inline bool IsCompactionEnabled() const { inline bool IsCompactionEnabled() const {
return movable_slots_worklist_.get(); return movable_slots_worklist_.get();
} }
HeapBase& heap_;
MarkingWorklists::MarkingWorklist::Local marking_worklist_;
MarkingWorklists::NotFullyConstructedWorklist&
not_fully_constructed_worklist_;
MarkingWorklists::PreviouslyNotFullyConstructedWorklist::Local MarkingWorklists::PreviouslyNotFullyConstructedWorklist::Local
previously_not_fully_constructed_worklist_; previously_not_fully_constructed_worklist_;
MarkingWorklists::WeakCallbackWorklist::Local weak_callback_worklist_; MarkingWorklists::WeakCallbackWorklist::Local weak_callback_worklist_;
...@@ -160,13 +223,10 @@ class MarkingStateBase { ...@@ -160,13 +223,10 @@ class MarkingStateBase {
bool in_atomic_pause_ = false; bool in_atomic_pause_ = false;
}; };
MarkingStateBase::MarkingStateBase(HeapBase& heap, BasicMarkingState::BasicMarkingState(HeapBase& heap,
MarkingWorklists& marking_worklists, MarkingWorklists& marking_worklists,
CompactionWorklists* compaction_worklists) CompactionWorklists* compaction_worklists)
: heap_(heap), : MarkingStateBase(heap, marking_worklists),
marking_worklist_(marking_worklists.marking_worklist()),
not_fully_constructed_worklist_(
*marking_worklists.not_fully_constructed_worklist()),
previously_not_fully_constructed_worklist_( previously_not_fully_constructed_worklist_(
marking_worklists.previously_not_fully_constructed_worklist()), marking_worklists.previously_not_fully_constructed_worklist()),
weak_callback_worklist_(marking_worklists.weak_callback_worklist()), weak_callback_worklist_(marking_worklists.weak_callback_worklist()),
...@@ -187,53 +247,9 @@ MarkingStateBase::MarkingStateBase(HeapBase& heap, ...@@ -187,53 +247,9 @@ MarkingStateBase::MarkingStateBase(HeapBase& heap,
} }
} }
void MarkingStateBase::MarkAndPush(const void* object, TraceDescriptor desc) { void BasicMarkingState::RegisterWeakReferenceIfNeeded(
DCHECK_NOT_NULL(object); const void* object, TraceDescriptor desc, WeakCallback weak_callback,
MarkAndPush( const void* parameter) {
HeapObjectHeader::FromObject(const_cast<void*>(desc.base_object_payload)),
desc);
}
void MarkingStateBase::MarkAndPush(HeapObjectHeader& header,
TraceDescriptor desc) {
DCHECK_NOT_NULL(desc.callback);
if (header.IsInConstruction<AccessMode::kAtomic>()) {
not_fully_constructed_worklist_.Push<AccessMode::kAtomic>(&header);
} else if (MarkNoPush(header)) {
PushMarked(header, desc);
}
}
bool MarkingStateBase::MarkNoPush(HeapObjectHeader& header) {
// A GC should only mark the objects that belong in its heap.
DCHECK_EQ(&heap_, &BasePage::FromPayload(&header)->heap());
// Never mark free space objects. This would e.g. hint to marking a promptly
// freed backing store.
DCHECK(!header.IsFree<AccessMode::kAtomic>());
return header.TryMarkAtomic();
}
void MarkingStateBase::MarkAndPush(HeapObjectHeader& header) {
MarkAndPush(
header,
{header.ObjectStart(),
GlobalGCInfoTable::GCInfoFromIndex(header.GetGCInfoIndex()).trace});
}
void MarkingStateBase::PushMarked(HeapObjectHeader& header,
TraceDescriptor desc) {
DCHECK(header.IsMarked<AccessMode::kAtomic>());
DCHECK(!header.IsInConstruction<AccessMode::kAtomic>());
DCHECK_NOT_NULL(desc.callback);
marking_worklist_.Push(desc);
}
void MarkingStateBase::RegisterWeakReferenceIfNeeded(const void* object,
TraceDescriptor desc,
WeakCallback weak_callback,
const void* parameter) {
// Filter out already marked values. The write barrier for WeakMember // Filter out already marked values. The write barrier for WeakMember
// ensures that any newly set value after this point is kept alive and does // ensures that any newly set value after this point is kept alive and does
// not require the callback. // not require the callback.
...@@ -245,20 +261,20 @@ void MarkingStateBase::RegisterWeakReferenceIfNeeded(const void* object, ...@@ -245,20 +261,20 @@ void MarkingStateBase::RegisterWeakReferenceIfNeeded(const void* object,
RegisterWeakCallback(weak_callback, parameter); RegisterWeakCallback(weak_callback, parameter);
} }
void MarkingStateBase::RegisterWeakCallback(WeakCallback callback, void BasicMarkingState::RegisterWeakCallback(WeakCallback callback,
const void* object) { const void* object) {
DCHECK_NOT_NULL(callback); DCHECK_NOT_NULL(callback);
weak_callback_worklist_.Push({callback, object}); weak_callback_worklist_.Push({callback, object});
} }
void MarkingStateBase::RegisterWeakContainer(HeapObjectHeader& header) { void BasicMarkingState::RegisterWeakContainer(HeapObjectHeader& header) {
weak_containers_worklist_.Push<AccessMode::kAtomic>(&header); weak_containers_worklist_.Push<AccessMode::kAtomic>(&header);
} }
void MarkingStateBase::ProcessWeakContainer(const void* object, void BasicMarkingState::ProcessWeakContainer(const void* object,
TraceDescriptor desc, TraceDescriptor desc,
WeakCallback callback, WeakCallback callback,
const void* data) { const void* data) {
DCHECK_NOT_NULL(object); DCHECK_NOT_NULL(object);
HeapObjectHeader& header = HeapObjectHeader& header =
...@@ -291,9 +307,9 @@ void MarkingStateBase::ProcessWeakContainer(const void* object, ...@@ -291,9 +307,9 @@ void MarkingStateBase::ProcessWeakContainer(const void* object,
} }
} }
void MarkingStateBase::ProcessEphemeron(const void* key, const void* value, void BasicMarkingState::ProcessEphemeron(const void* key, const void* value,
TraceDescriptor value_desc, TraceDescriptor value_desc,
Visitor& visitor) { Visitor& visitor) {
// ProcessEphemeron is not expected to find new ephemerons recursively, which // ProcessEphemeron is not expected to find new ephemerons recursively, which
// would break the main marking loop. // would break the main marking loop.
DCHECK(!in_ephemeron_processing_); DCHECK(!in_ephemeron_processing_);
...@@ -325,7 +341,7 @@ void MarkingStateBase::ProcessEphemeron(const void* key, const void* value, ...@@ -325,7 +341,7 @@ void MarkingStateBase::ProcessEphemeron(const void* key, const void* value,
in_ephemeron_processing_ = false; in_ephemeron_processing_ = false;
} }
void MarkingStateBase::AccountMarkedBytes(const HeapObjectHeader& header) { void BasicMarkingState::AccountMarkedBytes(const HeapObjectHeader& header) {
AccountMarkedBytes( AccountMarkedBytes(
header.IsLargeObject<AccessMode::kAtomic>() header.IsLargeObject<AccessMode::kAtomic>()
? reinterpret_cast<const LargePage*>(BasePage::FromPayload(&header)) ? reinterpret_cast<const LargePage*>(BasePage::FromPayload(&header))
...@@ -333,18 +349,18 @@ void MarkingStateBase::AccountMarkedBytes(const HeapObjectHeader& header) { ...@@ -333,18 +349,18 @@ void MarkingStateBase::AccountMarkedBytes(const HeapObjectHeader& header) {
: header.AllocatedSize<AccessMode::kAtomic>()); : header.AllocatedSize<AccessMode::kAtomic>());
} }
void MarkingStateBase::AccountMarkedBytes(size_t marked_bytes) { void BasicMarkingState::AccountMarkedBytes(size_t marked_bytes) {
marked_bytes_ += marked_bytes; marked_bytes_ += marked_bytes;
} }
class MutatorMarkingState : public MarkingStateBase { class MutatorMarkingState : public BasicMarkingState {
public: public:
MutatorMarkingState(HeapBase& heap, MarkingWorklists& marking_worklists, MutatorMarkingState(HeapBase& heap, MarkingWorklists& marking_worklists,
CompactionWorklists* compaction_worklists) CompactionWorklists* compaction_worklists)
: MarkingStateBase(heap, marking_worklists, compaction_worklists) {} : BasicMarkingState(heap, marking_worklists, compaction_worklists) {}
inline bool MarkNoPush(HeapObjectHeader& header) { inline bool MarkNoPush(HeapObjectHeader& header) {
return MutatorMarkingState::MarkingStateBase::MarkNoPush(header); return MutatorMarkingState::BasicMarkingState::MarkNoPush(header);
} }
inline void ReTraceMarkedWeakContainer(cppgc::Visitor&, HeapObjectHeader&); inline void ReTraceMarkedWeakContainer(cppgc::Visitor&, HeapObjectHeader&);
...@@ -440,11 +456,11 @@ void MutatorMarkingState::RecentlyRetracedWeakContainers::Insert( ...@@ -440,11 +456,11 @@ void MutatorMarkingState::RecentlyRetracedWeakContainers::Insert(
recently_retraced_cache_[last_used_index_] = header; recently_retraced_cache_[last_used_index_] = header;
} }
class ConcurrentMarkingState : public MarkingStateBase { class ConcurrentMarkingState : public BasicMarkingState {
public: public:
ConcurrentMarkingState(HeapBase& heap, MarkingWorklists& marking_worklists, ConcurrentMarkingState(HeapBase& heap, MarkingWorklists& marking_worklists,
CompactionWorklists* compaction_worklists) CompactionWorklists* compaction_worklists)
: MarkingStateBase(heap, marking_worklists, compaction_worklists) {} : BasicMarkingState(heap, marking_worklists, compaction_worklists) {}
~ConcurrentMarkingState() { DCHECK_EQ(last_marked_bytes_, marked_bytes_); } ~ConcurrentMarkingState() { DCHECK_EQ(last_marked_bytes_, marked_bytes_); }
......
...@@ -12,7 +12,7 @@ namespace cppgc { ...@@ -12,7 +12,7 @@ namespace cppgc {
namespace internal { namespace internal {
MarkingVisitorBase::MarkingVisitorBase(HeapBase& heap, MarkingVisitorBase::MarkingVisitorBase(HeapBase& heap,
MarkingStateBase& marking_state) BasicMarkingState& marking_state)
: marking_state_(marking_state) {} : marking_state_(marking_state) {}
void MarkingVisitorBase::Visit(const void* object, TraceDescriptor desc) { void MarkingVisitorBase::Visit(const void* object, TraceDescriptor desc) {
......
...@@ -16,13 +16,13 @@ namespace internal { ...@@ -16,13 +16,13 @@ namespace internal {
class HeapBase; class HeapBase;
class HeapObjectHeader; class HeapObjectHeader;
class Marker; class Marker;
class MarkingStateBase; class BasicMarkingState;
class MutatorMarkingState; class MutatorMarkingState;
class ConcurrentMarkingState; class ConcurrentMarkingState;
class V8_EXPORT_PRIVATE MarkingVisitorBase : public VisitorBase { class V8_EXPORT_PRIVATE MarkingVisitorBase : public VisitorBase {
public: public:
MarkingVisitorBase(HeapBase&, MarkingStateBase&); MarkingVisitorBase(HeapBase&, BasicMarkingState&);
~MarkingVisitorBase() override = default; ~MarkingVisitorBase() override = default;
protected: protected:
...@@ -35,7 +35,7 @@ class V8_EXPORT_PRIVATE MarkingVisitorBase : public VisitorBase { ...@@ -35,7 +35,7 @@ class V8_EXPORT_PRIVATE MarkingVisitorBase : public VisitorBase {
void RegisterWeakCallback(WeakCallback, const void*) final; void RegisterWeakCallback(WeakCallback, const void*) final;
void HandleMovableReference(const void**) final; void HandleMovableReference(const void**) final;
MarkingStateBase& marking_state_; BasicMarkingState& marking_state_;
}; };
class V8_EXPORT_PRIVATE MutatorMarkingVisitor : public MarkingVisitorBase { class V8_EXPORT_PRIVATE MutatorMarkingVisitor : public MarkingVisitorBase {
......
// Copyright 2021 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_EMBEDDER_TRACING_INL_H_
#define V8_HEAP_EMBEDDER_TRACING_INL_H_
#include "src/heap/embedder-tracing.h"
#include "src/objects/embedder-data-slot.h"
#include "src/objects/js-objects-inl.h"
namespace v8 {
namespace internal {
// static
bool LocalEmbedderHeapTracer::ExtractWrappableInfo(
Isolate* isolate, JSObject js_object,
const WrapperDescriptor& wrapper_descriptor, WrapperInfo* info) {
DCHECK(js_object.IsApiWrapper());
if (js_object.GetEmbedderFieldCount() < 2) return false;
if (EmbedderDataSlot(js_object, wrapper_descriptor.wrappable_type_index)
.ToAlignedPointerSafe(isolate, &info->first) &&
info->first &&
EmbedderDataSlot(js_object, wrapper_descriptor.wrappable_instance_index)
.ToAlignedPointerSafe(isolate, &info->second) &&
info->second) {
return (wrapper_descriptor.embedder_id_for_garbage_collected ==
WrapperDescriptor::kUnknownEmbedderId) ||
(*static_cast<uint16_t*>(info->first) ==
wrapper_descriptor.embedder_id_for_garbage_collected);
}
return false;
}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_EMBEDDER_TRACING_INL_H_
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
#include "include/v8-cppgc.h" #include "include/v8-cppgc.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/handles/global-handles.h" #include "src/handles/global-handles.h"
#include "src/heap/embedder-tracing-inl.h"
#include "src/heap/gc-tracer.h" #include "src/heap/gc-tracer.h"
#include "src/objects/embedder-data-slot.h" #include "src/heap/marking-worklist-inl.h"
#include "src/objects/js-objects-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -41,13 +41,18 @@ CppHeap::GarbageCollectionFlags ConvertTraceFlags( ...@@ -41,13 +41,18 @@ CppHeap::GarbageCollectionFlags ConvertTraceFlags(
} }
} // namespace } // namespace
void LocalEmbedderHeapTracer::PrepareForTrace(
EmbedderHeapTracer::TraceFlags flags) {
if (cpp_heap_) cpp_heap()->InitializeTracing(ConvertTraceFlags(flags));
}
void LocalEmbedderHeapTracer::TracePrologue( void LocalEmbedderHeapTracer::TracePrologue(
EmbedderHeapTracer::TraceFlags flags) { EmbedderHeapTracer::TraceFlags flags) {
if (!InUse()) return; if (!InUse()) return;
embedder_worklist_empty_ = false; embedder_worklist_empty_ = false;
if (cpp_heap_) if (cpp_heap_)
cpp_heap()->TracePrologue(ConvertTraceFlags(flags)); cpp_heap()->StartTracing();
else else
remote_tracer_->TracePrologue(flags); remote_tracer_->TracePrologue(flags);
} }
...@@ -113,42 +118,17 @@ void LocalEmbedderHeapTracer::SetEmbedderStackStateForNextFinalization( ...@@ -113,42 +118,17 @@ void LocalEmbedderHeapTracer::SetEmbedderStackStateForNextFinalization(
NotifyEmptyEmbedderStack(); NotifyEmptyEmbedderStack();
} }
namespace {
bool ExtractWrappableInfo(Isolate* isolate, JSObject js_object,
const WrapperDescriptor& wrapper_descriptor,
LocalEmbedderHeapTracer::WrapperInfo* info) {
DCHECK(js_object.IsApiWrapper());
if (js_object.GetEmbedderFieldCount() < 2) return false;
if (EmbedderDataSlot(js_object, wrapper_descriptor.wrappable_type_index)
.ToAlignedPointerSafe(isolate, &info->first) &&
info->first &&
EmbedderDataSlot(js_object, wrapper_descriptor.wrappable_instance_index)
.ToAlignedPointerSafe(isolate, &info->second) &&
info->second) {
return (wrapper_descriptor.embedder_id_for_garbage_collected ==
WrapperDescriptor::kUnknownEmbedderId) ||
(*static_cast<uint16_t*>(info->first) ==
wrapper_descriptor.embedder_id_for_garbage_collected);
}
return false;
}
} // namespace
LocalEmbedderHeapTracer::ProcessingScope::ProcessingScope( LocalEmbedderHeapTracer::ProcessingScope::ProcessingScope(
LocalEmbedderHeapTracer* tracer) LocalEmbedderHeapTracer* tracer)
: tracer_(tracer), wrapper_descriptor_(tracer->wrapper_descriptor()) { : tracer_(tracer), wrapper_descriptor_(tracer->wrapper_descriptor_) {
DCHECK(!tracer_->cpp_heap_);
wrapper_cache_.reserve(kWrapperCacheSize); wrapper_cache_.reserve(kWrapperCacheSize);
} }
LocalEmbedderHeapTracer::ProcessingScope::~ProcessingScope() { LocalEmbedderHeapTracer::ProcessingScope::~ProcessingScope() {
DCHECK(!tracer_->cpp_heap_);
if (!wrapper_cache_.empty()) { if (!wrapper_cache_.empty()) {
if (tracer_->cpp_heap_) tracer_->remote_tracer_->RegisterV8References(std::move(wrapper_cache_));
tracer_->cpp_heap()->RegisterV8References(std::move(wrapper_cache_));
else
tracer_->remote_tracer_->RegisterV8References(std::move(wrapper_cache_));
} }
} }
...@@ -174,11 +154,9 @@ void LocalEmbedderHeapTracer::ProcessingScope::TracePossibleWrapper( ...@@ -174,11 +154,9 @@ void LocalEmbedderHeapTracer::ProcessingScope::TracePossibleWrapper(
} }
void LocalEmbedderHeapTracer::ProcessingScope::FlushWrapperCacheIfFull() { void LocalEmbedderHeapTracer::ProcessingScope::FlushWrapperCacheIfFull() {
DCHECK(!tracer_->cpp_heap_);
if (wrapper_cache_.size() == wrapper_cache_.capacity()) { if (wrapper_cache_.size() == wrapper_cache_.capacity()) {
if (tracer_->cpp_heap_) tracer_->remote_tracer_->RegisterV8References(std::move(wrapper_cache_));
tracer_->cpp_heap()->RegisterV8References(std::move(wrapper_cache_));
else
tracer_->remote_tracer_->RegisterV8References(std::move(wrapper_cache_));
wrapper_cache_.clear(); wrapper_cache_.clear();
wrapper_cache_.reserve(kWrapperCacheSize); wrapper_cache_.reserve(kWrapperCacheSize);
} }
...@@ -213,6 +191,20 @@ void LocalEmbedderHeapTracer::NotifyEmptyEmbedderStack() { ...@@ -213,6 +191,20 @@ void LocalEmbedderHeapTracer::NotifyEmptyEmbedderStack() {
isolate_->global_handles()->NotifyEmptyEmbedderStack(); isolate_->global_handles()->NotifyEmptyEmbedderStack();
} }
void LocalEmbedderHeapTracer::EmbedderWriteBarrier(Heap* heap,
JSObject js_object) {
DCHECK(InUse());
DCHECK(js_object.IsApiWrapper());
if (cpp_heap_) {
DCHECK_NOT_NULL(heap->mark_compact_collector());
heap->mark_compact_collector()->local_marking_worklists()->PushWrapper(
js_object);
return;
}
LocalEmbedderHeapTracer::ProcessingScope scope(this);
scope.TracePossibleWrapper(js_object);
}
bool DefaultEmbedderRootsHandler::IsRoot( bool DefaultEmbedderRootsHandler::IsRoot(
const v8::TracedReference<v8::Value>& handle) { const v8::TracedReference<v8::Value>& handle) {
return !tracer_ || tracer_->IsRootForNonTracingGC(handle); return !tracer_ || tracer_->IsRootForNonTracingGC(handle);
......
...@@ -74,6 +74,10 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -74,6 +74,10 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
WrapperCache wrapper_cache_; WrapperCache wrapper_cache_;
}; };
static V8_INLINE bool ExtractWrappableInfo(Isolate*, JSObject,
const WrapperDescriptor&,
WrapperInfo*);
explicit LocalEmbedderHeapTracer(Isolate* isolate) : isolate_(isolate) {} explicit LocalEmbedderHeapTracer(Isolate* isolate) : isolate_(isolate) {}
~LocalEmbedderHeapTracer() { ~LocalEmbedderHeapTracer() {
...@@ -91,6 +95,7 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -91,6 +95,7 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
void SetRemoteTracer(EmbedderHeapTracer* tracer); void SetRemoteTracer(EmbedderHeapTracer* tracer);
void SetCppHeap(CppHeap* cpp_heap); void SetCppHeap(CppHeap* cpp_heap);
void PrepareForTrace(EmbedderHeapTracer::TraceFlags flags);
void TracePrologue(EmbedderHeapTracer::TraceFlags flags); void TracePrologue(EmbedderHeapTracer::TraceFlags flags);
void TraceEpilogue(); void TraceEpilogue();
void EnterFinalPause(); void EnterFinalPause();
...@@ -149,6 +154,8 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final { ...@@ -149,6 +154,8 @@ class V8_EXPORT_PRIVATE LocalEmbedderHeapTracer final {
return embedder_stack_state_; return embedder_stack_state_;
} }
void EmbedderWriteBarrier(Heap*, JSObject);
private: private:
static constexpr size_t kEmbedderAllocatedThreshold = 128 * KB; static constexpr size_t kEmbedderAllocatedThreshold = 128 * KB;
......
...@@ -52,10 +52,9 @@ void WriteBarrier::MarkingSlowFromInternalFields(Heap* heap, JSObject host) { ...@@ -52,10 +52,9 @@ void WriteBarrier::MarkingSlowFromInternalFields(Heap* heap, JSObject host) {
// We are not checking the mark bits of host here as (a) there's no // We are not checking the mark bits of host here as (a) there's no
// synchronization with the marker and (b) we are writing into a live object // synchronization with the marker and (b) we are writing into a live object
// (independent of the mark bits). // (independent of the mark bits).
if (!heap->local_embedder_heap_tracer()->InUse()) return; auto* local_embedder_heap_tracer = heap->local_embedder_heap_tracer();
LocalEmbedderHeapTracer::ProcessingScope scope( if (!local_embedder_heap_tracer->InUse()) return;
heap->local_embedder_heap_tracer()); local_embedder_heap_tracer->EmbedderWriteBarrier(heap, host);
scope.TracePossibleWrapper(host);
} }
void WriteBarrier::MarkingSlow(Heap* heap, Code host, RelocInfo* reloc_info, void WriteBarrier::MarkingSlow(Heap* heap, Code host, RelocInfo* reloc_info,
......
...@@ -235,6 +235,16 @@ void IncrementalMarking::StartMarking() { ...@@ -235,6 +235,16 @@ void IncrementalMarking::StartMarking() {
is_compacting_ = collector_->StartCompaction( is_compacting_ = collector_->StartCompaction(
MarkCompactCollector::StartCompactionMode::kIncremental); MarkCompactCollector::StartCompactionMode::kIncremental);
auto embedder_flags = heap_->flags_for_embedder_tracer();
{
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_EMBEDDER_PROLOGUE);
// PrepareForTrace should be called before visitor initialization in
// StartMarking. It is only used with CppHeap.
heap_->local_embedder_heap_tracer()->PrepareForTrace(embedder_flags);
}
collector_->StartMarking(); collector_->StartMarking();
SetState(MARKING); SetState(MARKING);
...@@ -261,8 +271,7 @@ void IncrementalMarking::StartMarking() { ...@@ -261,8 +271,7 @@ void IncrementalMarking::StartMarking() {
// marking (including write barriers) is fully set up. // marking (including write barriers) is fully set up.
TRACE_GC(heap()->tracer(), TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_EMBEDDER_PROLOGUE); GCTracer::Scope::MC_INCREMENTAL_EMBEDDER_PROLOGUE);
heap_->local_embedder_heap_tracer()->TracePrologue( heap_->local_embedder_heap_tracer()->TracePrologue(embedder_flags);
heap_->flags_for_embedder_tracer());
} }
heap_->InvokeIncrementalMarkingEpilogueCallbacks(); heap_->InvokeIncrementalMarkingEpilogueCallbacks();
...@@ -533,13 +542,15 @@ StepResult IncrementalMarking::EmbedderStep(double expected_duration_ms, ...@@ -533,13 +542,15 @@ StepResult IncrementalMarking::EmbedderStep(double expected_duration_ms,
LocalEmbedderHeapTracer* local_tracer = heap_->local_embedder_heap_tracer(); LocalEmbedderHeapTracer* local_tracer = heap_->local_embedder_heap_tracer();
const double start = heap_->MonotonicallyIncreasingTimeInMs(); const double start = heap_->MonotonicallyIncreasingTimeInMs();
const double deadline = start + expected_duration_ms; const double deadline = start + expected_duration_ms;
bool empty_worklist; bool empty_worklist = true;
{ if (local_marking_worklists()->PublishWrapper()) {
DCHECK(local_marking_worklists()->IsWrapperEmpty());
} else {
// Cannot directly publish wrapper objects.
LocalEmbedderHeapTracer::ProcessingScope scope(local_tracer); LocalEmbedderHeapTracer::ProcessingScope scope(local_tracer);
HeapObject object; HeapObject object;
size_t cnt = 0; size_t cnt = 0;
empty_worklist = true; while (local_marking_worklists()->PopWrapper(&object)) {
while (local_marking_worklists()->PopEmbedder(&object)) {
scope.TracePossibleWrapper(JSObject::cast(object)); scope.TracePossibleWrapper(JSObject::cast(object));
if (++cnt == kObjectsToProcessBeforeDeadlineCheck) { if (++cnt == kObjectsToProcessBeforeDeadlineCheck) {
if (deadline <= heap_->MonotonicallyIncreasingTimeInMs()) { if (deadline <= heap_->MonotonicallyIncreasingTimeInMs()) {
......
...@@ -572,8 +572,11 @@ void MarkCompactCollector::StartMarking() { ...@@ -572,8 +572,11 @@ void MarkCompactCollector::StartMarking() {
} }
code_flush_mode_ = Heap::GetCodeFlushMode(isolate()); code_flush_mode_ = Heap::GetCodeFlushMode(isolate());
marking_worklists()->CreateContextWorklists(contexts); marking_worklists()->CreateContextWorklists(contexts);
local_marking_worklists_ = auto* cpp_heap = CppHeap::From(heap_->cpp_heap());
std::make_unique<MarkingWorklists::Local>(marking_worklists()); local_marking_worklists_ = std::make_unique<MarkingWorklists::Local>(
marking_worklists(), cpp_heap
? cpp_heap->CreateCppMarkingState()
: MarkingWorklists::Local::kNoCppMarkingState);
local_weak_objects_ = std::make_unique<WeakObjects::Local>(weak_objects()); local_weak_objects_ = std::make_unique<WeakObjects::Local>(weak_objects());
marking_visitor_ = std::make_unique<MarkingVisitor>( marking_visitor_ = std::make_unique<MarkingVisitor>(
marking_state(), local_marking_worklists(), local_weak_objects_.get(), marking_state(), local_marking_worklists(), local_weak_objects_.get(),
...@@ -926,8 +929,11 @@ void MarkCompactCollector::Prepare() { ...@@ -926,8 +929,11 @@ void MarkCompactCollector::Prepare() {
if (!was_marked_incrementally_) { if (!was_marked_incrementally_) {
{ {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_EMBEDDER_PROLOGUE); TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_EMBEDDER_PROLOGUE);
heap_->local_embedder_heap_tracer()->TracePrologue( auto embedder_flags = heap_->flags_for_embedder_tracer();
heap_->flags_for_embedder_tracer()); // PrepareForTrace should be called before visitor initialization in
// StartMarking.
heap_->local_embedder_heap_tracer()->PrepareForTrace(embedder_flags);
heap_->local_embedder_heap_tracer()->TracePrologue(embedder_flags);
} }
StartCompaction(StartCompactionMode::kAtomic); StartCompaction(StartCompactionMode::kAtomic);
StartMarking(); StartMarking();
...@@ -1931,7 +1937,7 @@ bool MarkCompactCollector::ProcessEphemeronsUntilFixpoint() { ...@@ -1931,7 +1937,7 @@ bool MarkCompactCollector::ProcessEphemeronsUntilFixpoint() {
} while (another_ephemeron_iteration_main_thread || } while (another_ephemeron_iteration_main_thread ||
heap()->concurrent_marking()->another_ephemeron_iteration() || heap()->concurrent_marking()->another_ephemeron_iteration() ||
!local_marking_worklists()->IsEmpty() || !local_marking_worklists()->IsEmpty() ||
!local_marking_worklists()->IsEmbedderEmpty() || !local_marking_worklists()->IsWrapperEmpty() ||
!heap()->local_embedder_heap_tracer()->IsRemoteTracingDone()); !heap()->local_embedder_heap_tracer()->IsRemoteTracingDone());
CHECK(local_marking_worklists()->IsEmpty()); CHECK(local_marking_worklists()->IsEmpty());
...@@ -2053,7 +2059,7 @@ void MarkCompactCollector::ProcessEphemeronsLinear() { ...@@ -2053,7 +2059,7 @@ void MarkCompactCollector::ProcessEphemeronsLinear() {
// is necessary. // is necessary.
work_to_do = !local_marking_worklists()->IsEmpty() || work_to_do = !local_marking_worklists()->IsEmpty() ||
!local_marking_worklists()->IsEmbedderEmpty() || !local_marking_worklists()->IsWrapperEmpty() ||
!heap()->local_embedder_heap_tracer()->IsRemoteTracingDone(); !heap()->local_embedder_heap_tracer()->IsRemoteTracingDone();
CHECK(local_weak_objects() CHECK(local_weak_objects()
->discovered_ephemerons_local.IsLocalAndGlobalEmpty()); ->discovered_ephemerons_local.IsLocalAndGlobalEmpty());
...@@ -2074,11 +2080,14 @@ void MarkCompactCollector::ProcessEphemeronsLinear() { ...@@ -2074,11 +2080,14 @@ void MarkCompactCollector::ProcessEphemeronsLinear() {
void MarkCompactCollector::PerformWrapperTracing() { void MarkCompactCollector::PerformWrapperTracing() {
if (heap_->local_embedder_heap_tracer()->InUse()) { if (heap_->local_embedder_heap_tracer()->InUse()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_EMBEDDER_TRACING); TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_EMBEDDER_TRACING);
{ if (local_marking_worklists()->PublishWrapper()) {
DCHECK(local_marking_worklists()->IsWrapperEmpty());
} else {
// Cannot directly publish wrapper objects.
LocalEmbedderHeapTracer::ProcessingScope scope( LocalEmbedderHeapTracer::ProcessingScope scope(
heap_->local_embedder_heap_tracer()); heap_->local_embedder_heap_tracer());
HeapObject object; HeapObject object;
while (local_marking_worklists()->PopEmbedder(&object)) { while (local_marking_worklists()->PopWrapper(&object)) {
scope.TracePossibleWrapper(JSObject::cast(object)); scope.TracePossibleWrapper(JSObject::cast(object));
} }
} }
...@@ -2303,8 +2312,8 @@ void MarkCompactCollector::MarkLiveObjects() { ...@@ -2303,8 +2312,8 @@ void MarkCompactCollector::MarkLiveObjects() {
PerformWrapperTracing(); PerformWrapperTracing();
DrainMarkingWorklist(); DrainMarkingWorklist();
} while (!heap_->local_embedder_heap_tracer()->IsRemoteTracingDone() || } while (!heap_->local_embedder_heap_tracer()->IsRemoteTracingDone() ||
!local_marking_worklists()->IsEmbedderEmpty()); !local_marking_worklists()->IsWrapperEmpty());
DCHECK(local_marking_worklists()->IsEmbedderEmpty()); DCHECK(local_marking_worklists()->IsWrapperEmpty());
DCHECK(local_marking_worklists()->IsEmpty()); DCHECK(local_marking_worklists()->IsEmpty());
} }
...@@ -2347,7 +2356,7 @@ void MarkCompactCollector::MarkLiveObjects() { ...@@ -2347,7 +2356,7 @@ void MarkCompactCollector::MarkLiveObjects() {
{ {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY);
ProcessEphemeronMarking(); ProcessEphemeronMarking();
DCHECK(local_marking_worklists()->IsEmbedderEmpty()); DCHECK(local_marking_worklists()->IsWrapperEmpty());
DCHECK(local_marking_worklists()->IsEmpty()); DCHECK(local_marking_worklists()->IsEmpty());
} }
......
...@@ -268,7 +268,7 @@ int MarkingVisitorBase<ConcreteVisitor, ...@@ -268,7 +268,7 @@ int MarkingVisitorBase<ConcreteVisitor,
if (size && is_embedder_tracing_enabled_) { if (size && is_embedder_tracing_enabled_) {
// Success: The object needs to be processed for embedder references on // Success: The object needs to be processed for embedder references on
// the main thread. // the main thread.
local_marking_worklists_->PushEmbedder(object); local_marking_worklists_->PushWrapper(object);
} }
return size; return size;
} }
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "src/heap/cppgc-js/cpp-marking-state-inl.h"
#include "src/heap/marking-worklist.h" #include "src/heap/marking-worklist.h"
#include "src/objects/js-objects-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -16,7 +18,7 @@ template <typename Callback> ...@@ -16,7 +18,7 @@ template <typename Callback>
void MarkingWorklists::Update(Callback callback) { void MarkingWorklists::Update(Callback callback) {
shared_.Update(callback); shared_.Update(callback);
on_hold_.Update(callback); on_hold_.Update(callback);
embedder_.Update(callback); wrapper_.Update(callback);
other_.Update(callback); other_.Update(callback);
for (auto cw : context_worklists_) { for (auto cw : context_worklists_) {
if (cw.context == kSharedContext || cw.context == kOtherContext) { if (cw.context == kSharedContext || cw.context == kOtherContext) {
...@@ -45,12 +47,17 @@ bool MarkingWorklists::Local::PopOnHold(HeapObject* object) { ...@@ -45,12 +47,17 @@ bool MarkingWorklists::Local::PopOnHold(HeapObject* object) {
return on_hold_.Pop(object); return on_hold_.Pop(object);
} }
void MarkingWorklists::Local::PushEmbedder(HeapObject object) { void MarkingWorklists::Local::PushWrapper(HeapObject object) {
embedder_.Push(object); if (cpp_marking_state_) {
cpp_marking_state_->MarkAndPush(JSObject::cast(object));
} else {
wrapper_.Push(object);
}
} }
bool MarkingWorklists::Local::PopEmbedder(HeapObject* object) { bool MarkingWorklists::Local::PopWrapper(HeapObject* object) {
return embedder_.Pop(object); DCHECK(!cpp_marking_state_);
return wrapper_.Pop(object);
} }
Address MarkingWorklists::Local::SwitchToContext(Address context) { Address MarkingWorklists::Local::SwitchToContext(Address context) {
...@@ -72,6 +79,12 @@ void MarkingWorklists::Local::SwitchToContext( ...@@ -72,6 +79,12 @@ void MarkingWorklists::Local::SwitchToContext(
active_context_ = context; active_context_ = context;
} }
bool MarkingWorklists::Local::PublishWrapper() {
if (!cpp_marking_state_) return false;
cpp_marking_state_->Publish();
return true;
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -5,8 +5,11 @@ ...@@ -5,8 +5,11 @@
#include "src/heap/marking-worklist.h" #include "src/heap/marking-worklist.h"
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <map> #include <map>
#include "src/heap/cppgc-js/cpp-heap.h"
#include "src/heap/cppgc-js/cpp-marking-state.h"
#include "src/heap/marking-worklist-inl.h" #include "src/heap/marking-worklist-inl.h"
#include "src/objects/heap-object-inl.h" #include "src/objects/heap-object-inl.h"
#include "src/objects/heap-object.h" #include "src/objects/heap-object.h"
...@@ -29,7 +32,7 @@ MarkingWorklists::~MarkingWorklists() { ...@@ -29,7 +32,7 @@ MarkingWorklists::~MarkingWorklists() {
void MarkingWorklists::Clear() { void MarkingWorklists::Clear() {
shared_.Clear(); shared_.Clear();
on_hold_.Clear(); on_hold_.Clear();
embedder_.Clear(); wrapper_.Clear();
other_.Clear(); other_.Clear();
for (auto cw : context_worklists_) { for (auto cw : context_worklists_) {
if (cw.context == kSharedContext || cw.context == kOtherContext) { if (cw.context == kSharedContext || cw.context == kOtherContext) {
...@@ -94,13 +97,17 @@ void MarkingWorklists::PrintWorklist(const char* worklist_name, ...@@ -94,13 +97,17 @@ void MarkingWorklists::PrintWorklist(const char* worklist_name,
#endif #endif
} }
const Address MarkingWorklists::Local::kSharedContext; constexpr Address MarkingWorklists::Local::kSharedContext;
const Address MarkingWorklists::Local::kOtherContext; constexpr Address MarkingWorklists::Local::kOtherContext;
constexpr std::nullptr_t MarkingWorklists::Local::kNoCppMarkingState;
MarkingWorklists::Local::Local(MarkingWorklists* global) MarkingWorklists::Local::Local(
MarkingWorklists* global,
std::unique_ptr<CppMarkingState> cpp_marking_state)
: on_hold_(global->on_hold()), : on_hold_(global->on_hold()),
embedder_(global->embedder()), wrapper_(global->wrapper()),
is_per_context_mode_(false) { is_per_context_mode_(false),
cpp_marking_state_(std::move(cpp_marking_state)) {
if (global->context_worklists().empty()) { if (global->context_worklists().empty()) {
MarkingWorklist::Local shared(global->shared()); MarkingWorklist::Local shared(global->shared());
active_ = std::move(shared); active_ = std::move(shared);
...@@ -133,7 +140,7 @@ MarkingWorklists::Local::~Local() { ...@@ -133,7 +140,7 @@ MarkingWorklists::Local::~Local() {
void MarkingWorklists::Local::Publish() { void MarkingWorklists::Local::Publish() {
active_.Publish(); active_.Publish();
on_hold_.Publish(); on_hold_.Publish();
embedder_.Publish(); wrapper_.Publish();
if (is_per_context_mode_) { if (is_per_context_mode_) {
for (auto& cw : worklist_by_context_) { for (auto& cw : worklist_by_context_) {
if (cw.first != active_context_) { if (cw.first != active_context_) {
...@@ -141,6 +148,7 @@ void MarkingWorklists::Local::Publish() { ...@@ -141,6 +148,7 @@ void MarkingWorklists::Local::Publish() {
} }
} }
} }
PublishWrapper();
} }
bool MarkingWorklists::Local::IsEmpty() { bool MarkingWorklists::Local::IsEmpty() {
...@@ -163,8 +171,12 @@ bool MarkingWorklists::Local::IsEmpty() { ...@@ -163,8 +171,12 @@ bool MarkingWorklists::Local::IsEmpty() {
return true; return true;
} }
bool MarkingWorklists::Local::IsEmbedderEmpty() const { bool MarkingWorklists::Local::IsWrapperEmpty() const {
return embedder_.IsLocalEmpty() && embedder_.IsGlobalEmpty(); if (cpp_marking_state_) {
DCHECK(wrapper_.IsLocalAndGlobalEmpty());
return cpp_marking_state_->IsLocalEmpty();
}
return wrapper_.IsLocalAndGlobalEmpty();
} }
void MarkingWorklists::Local::ShareWork() { void MarkingWorklists::Local::ShareWork() {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef V8_HEAP_MARKING_WORKLIST_H_ #ifndef V8_HEAP_MARKING_WORKLIST_H_
#define V8_HEAP_MARKING_WORKLIST_H_ #define V8_HEAP_MARKING_WORKLIST_H_
#include <cstddef>
#include <memory>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
...@@ -15,11 +17,14 @@ ...@@ -15,11 +17,14 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CppMarkingState;
class JSObject;
// The index of the main thread task used by concurrent/parallel GC. // The index of the main thread task used by concurrent/parallel GC.
const int kMainThreadTask = 0; const int kMainThreadTask = 0;
using MarkingWorklist = ::heap::base::Worklist<HeapObject, 64>; using MarkingWorklist = ::heap::base::Worklist<HeapObject, 64>;
using EmbedderTracingWorklist = ::heap::base::Worklist<HeapObject, 16>; using WrapperTracingWorklist = ::heap::base::Worklist<HeapObject, 16>;
// We piggyback on marking to compute object sizes per native context that is // We piggyback on marking to compute object sizes per native context that is
// needed for the new memory measurement API. The algorithm works as follows: // needed for the new memory measurement API. The algorithm works as follows:
...@@ -82,7 +87,7 @@ class V8_EXPORT_PRIVATE MarkingWorklists { ...@@ -82,7 +87,7 @@ class V8_EXPORT_PRIVATE MarkingWorklists {
MarkingWorklist* shared() { return &shared_; } MarkingWorklist* shared() { return &shared_; }
MarkingWorklist* on_hold() { return &on_hold_; } MarkingWorklist* on_hold() { return &on_hold_; }
EmbedderTracingWorklist* embedder() { return &embedder_; } WrapperTracingWorklist* wrapper() { return &wrapper_; }
// A list of (context, worklist) pairs that was set up at the start of // A list of (context, worklist) pairs that was set up at the start of
// marking by CreateContextWorklists. // marking by CreateContextWorklists.
...@@ -115,7 +120,7 @@ class V8_EXPORT_PRIVATE MarkingWorklists { ...@@ -115,7 +120,7 @@ class V8_EXPORT_PRIVATE MarkingWorklists {
// Worklist for objects that potentially require embedder tracing, i.e., // Worklist for objects that potentially require embedder tracing, i.e.,
// these objects need to be handed over to the embedder to find the full // these objects need to be handed over to the embedder to find the full
// transitive closure. // transitive closure.
EmbedderTracingWorklist embedder_; WrapperTracingWorklist wrapper_;
// Per-context worklists. // Per-context worklists.
std::vector<ContextWorklistPair> context_worklists_; std::vector<ContextWorklistPair> context_worklists_;
...@@ -137,10 +142,13 @@ class V8_EXPORT_PRIVATE MarkingWorklists { ...@@ -137,10 +142,13 @@ class V8_EXPORT_PRIVATE MarkingWorklists {
// been moved to active_. // been moved to active_.
class V8_EXPORT_PRIVATE MarkingWorklists::Local { class V8_EXPORT_PRIVATE MarkingWorklists::Local {
public: public:
static const Address kSharedContext = MarkingWorklists::kSharedContext; static constexpr Address kSharedContext = MarkingWorklists::kSharedContext;
static const Address kOtherContext = MarkingWorklists::kOtherContext; static constexpr Address kOtherContext = MarkingWorklists::kOtherContext;
static constexpr std::nullptr_t kNoCppMarkingState = nullptr;
explicit Local(MarkingWorklists* global); Local(
MarkingWorklists* global,
std::unique_ptr<CppMarkingState> cpp_marking_state = kNoCppMarkingState);
~Local(); ~Local();
inline void Push(HeapObject object); inline void Push(HeapObject object);
...@@ -149,12 +157,12 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local { ...@@ -149,12 +157,12 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local {
inline void PushOnHold(HeapObject object); inline void PushOnHold(HeapObject object);
inline bool PopOnHold(HeapObject* object); inline bool PopOnHold(HeapObject* object);
inline void PushEmbedder(HeapObject object); inline void PushWrapper(HeapObject object);
inline bool PopEmbedder(HeapObject* object); inline bool PopWrapper(HeapObject* object);
void Publish(); void Publish();
bool IsEmpty(); bool IsEmpty();
bool IsEmbedderEmpty() const; bool IsWrapperEmpty() const;
// Publishes the local active marking worklist if its global worklist is // Publishes the local active marking worklist if its global worklist is
// empty. In the per-context marking mode it also publishes the shared // empty. In the per-context marking mode it also publishes the shared
// worklist. // worklist.
...@@ -162,6 +170,10 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local { ...@@ -162,6 +170,10 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local {
// Merges the on-hold worklist to the shared worklist. // Merges the on-hold worklist to the shared worklist.
void MergeOnHold(); void MergeOnHold();
// Returns true if wrapper objects could be directly pushed. Otherwise,
// objects need to be processed one by one.
inline bool PublishWrapper();
// Returns the context of the active worklist. // Returns the context of the active worklist.
Address Context() const { return active_context_; } Address Context() const { return active_context_; }
inline Address SwitchToContext(Address context); inline Address SwitchToContext(Address context);
...@@ -174,13 +186,15 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local { ...@@ -174,13 +186,15 @@ class V8_EXPORT_PRIVATE MarkingWorklists::Local {
inline void SwitchToContext(Address context, inline void SwitchToContext(Address context,
MarkingWorklist::Local* worklist); MarkingWorklist::Local* worklist);
MarkingWorklist::Local on_hold_; MarkingWorklist::Local on_hold_;
EmbedderTracingWorklist::Local embedder_; WrapperTracingWorklist::Local wrapper_;
MarkingWorklist::Local active_; MarkingWorklist::Local active_;
Address active_context_; Address active_context_;
MarkingWorklist::Local* active_owner_; MarkingWorklist::Local* active_owner_;
bool is_per_context_mode_; bool is_per_context_mode_;
std::unordered_map<Address, std::unique_ptr<MarkingWorklist::Local>> std::unordered_map<Address, std::unique_ptr<MarkingWorklist::Local>>
worklist_by_context_; worklist_by_context_;
std::unique_ptr<CppMarkingState> cpp_marking_state_;
}; };
} // namespace internal } // namespace internal
......
...@@ -5208,7 +5208,7 @@ Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, ...@@ -5208,7 +5208,7 @@ Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
: Nothing<bool>(); : Nothing<bool>();
} }
bool JSObject::IsApiWrapper() { bool JSObject::IsApiWrapper() const {
// These object types can carry information relevant for embedders. The // These object types can carry information relevant for embedders. The
// *_API_* types are generated through templates which can have embedder // *_API_* types are generated through templates which can have embedder
// fields. The other types have their embedder fields added at compile time. // fields. The other types have their embedder fields added at compile time.
...@@ -5222,7 +5222,7 @@ bool JSObject::IsApiWrapper() { ...@@ -5222,7 +5222,7 @@ bool JSObject::IsApiWrapper() {
InstanceTypeChecker::IsJSApiObject(instance_type); InstanceTypeChecker::IsJSApiObject(instance_type);
} }
bool JSObject::IsDroppableApiWrapper() { bool JSObject::IsDroppableApiWrapper() const {
auto instance_type = map().instance_type(); auto instance_type = map().instance_type();
return InstanceTypeChecker::IsJSApiObject(instance_type) || return InstanceTypeChecker::IsJSApiObject(instance_type) ||
instance_type == JS_SPECIAL_API_OBJECT_TYPE; instance_type == JS_SPECIAL_API_OBJECT_TYPE;
......
...@@ -579,8 +579,8 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> { ...@@ -579,8 +579,8 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> {
// embedder fields as well as the number of embedder fields. // embedder fields as well as the number of embedder fields.
// The |function_has_prototype_slot| parameter is needed only for // The |function_has_prototype_slot| parameter is needed only for
// JSFunction objects. // JSFunction objects.
static int GetHeaderSize(InstanceType instance_type, static V8_EXPORT_PRIVATE int GetHeaderSize(
bool function_has_prototype_slot = false); InstanceType instance_type, bool function_has_prototype_slot = false);
static inline int GetHeaderSize(Map map); static inline int GetHeaderSize(Map map);
static inline int GetEmbedderFieldsStartOffset(Map map); static inline int GetEmbedderFieldsStartOffset(Map map);
...@@ -598,10 +598,10 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> { ...@@ -598,10 +598,10 @@ class JSObject : public TorqueGeneratedJSObject<JSObject, JSReceiver> {
// garbage collection treatment. // garbage collection treatment.
// TODO(mlippautz): Make check exact and replace the pattern match in // TODO(mlippautz): Make check exact and replace the pattern match in
// Heap::TracePossibleWrapper. // Heap::TracePossibleWrapper.
bool IsApiWrapper(); V8_EXPORT_PRIVATE bool IsApiWrapper() const;
// Same as IsApiWrapper() but also allow dropping the wrapper on minor GCs. // Same as IsApiWrapper() but also allow dropping the wrapper on minor GCs.
bool IsDroppableApiWrapper(); bool IsDroppableApiWrapper() const;
// Returns a new map with all transitions dropped from the object's current // Returns a new map with all transitions dropped from the object's current
// map and the ElementsKind set. // map and the ElementsKind set.
......
...@@ -70,8 +70,9 @@ class EphemeronPairTest : public testing::TestWithHeap { ...@@ -70,8 +70,9 @@ class EphemeronPairTest : public testing::TestWithHeap {
} }
void InitializeMarker(HeapBase& heap, cppgc::Platform* platform) { void InitializeMarker(HeapBase& heap, cppgc::Platform* platform) {
marker_ = MarkerFactory::CreateAndStartMarking<Marker>( marker_ = std::make_unique<Marker>(heap, platform,
heap, platform, IncrementalPreciseMarkingConfig); IncrementalPreciseMarkingConfig);
marker_->StartMarking();
} }
Marker* marker() const { return marker_.get(); } Marker* marker() const { return marker_.get(); }
......
...@@ -40,8 +40,8 @@ class MarkerTest : public testing::TestWithHeap { ...@@ -40,8 +40,8 @@ class MarkerTest : public testing::TestWithHeap {
void InitializeMarker(HeapBase& heap, cppgc::Platform* platform, void InitializeMarker(HeapBase& heap, cppgc::Platform* platform,
MarkingConfig config) { MarkingConfig config) {
marker_ = marker_ = std::make_unique<Marker>(heap, platform, config);
MarkerFactory::CreateAndStartMarking<Marker>(heap, platform, config); marker_->StartMarking();
} }
Marker* marker() const { return marker_.get(); } Marker* marker() const { return marker_.get(); }
...@@ -421,8 +421,8 @@ class IncrementalMarkingTest : public testing::TestWithHeap { ...@@ -421,8 +421,8 @@ class IncrementalMarkingTest : public testing::TestWithHeap {
void InitializeMarker(HeapBase& heap, cppgc::Platform* platform, void InitializeMarker(HeapBase& heap, cppgc::Platform* platform,
MarkingConfig config) { MarkingConfig config) {
GetMarkerRef() = GetMarkerRef() = std::make_unique<Marker>(heap, platform, config);
MarkerFactory::CreateAndStartMarking<Marker>(heap, platform, config); GetMarkerRef()->StartMarking();
} }
MarkerBase* marker() const { return Heap::From(GetHeap())->marker(); } MarkerBase* marker() const { return Heap::From(GetHeap())->marker(); }
......
...@@ -23,8 +23,10 @@ namespace { ...@@ -23,8 +23,10 @@ namespace {
class MarkingVisitorTest : public testing::TestWithHeap { class MarkingVisitorTest : public testing::TestWithHeap {
public: public:
MarkingVisitorTest() MarkingVisitorTest()
: marker_(MarkerFactory::CreateAndStartMarking<Marker>( : marker_(std::make_unique<Marker>(*Heap::From(GetHeap()),
*Heap::From(GetHeap()), GetPlatformHandle().get())) {} GetPlatformHandle().get())) {
marker_->StartMarking();
}
~MarkingVisitorTest() override { marker_->ClearAllWorklistsForTesting(); } ~MarkingVisitorTest() override { marker_->ClearAllWorklistsForTesting(); }
Marker* GetMarker() { return marker_.get(); } Marker* GetMarker() { return marker_.get(); }
...@@ -51,7 +53,7 @@ class TestMarkingVisitor : public MutatorMarkingVisitor { ...@@ -51,7 +53,7 @@ class TestMarkingVisitor : public MutatorMarkingVisitor {
marker->MutatorMarkingStateForTesting()) {} marker->MutatorMarkingStateForTesting()) {}
~TestMarkingVisitor() { marking_state_.Publish(); } ~TestMarkingVisitor() { marking_state_.Publish(); }
MarkingStateBase& marking_state() { return marking_state_; } BasicMarkingState& marking_state() { return marking_state_; }
}; };
} // namespace } // namespace
......
...@@ -68,8 +68,9 @@ class V8_NODISCARD CppgcTracingScopesTest : public testing::TestWithHeap { ...@@ -68,8 +68,9 @@ class V8_NODISCARD CppgcTracingScopesTest : public testing::TestWithHeap {
Config config = {Config::CollectionType::kMajor, Config config = {Config::CollectionType::kMajor,
Config::StackState::kNoHeapPointers, Config::StackState::kNoHeapPointers,
Config::MarkingType::kIncremental}; Config::MarkingType::kIncremental};
GetMarkerRef() = MarkerFactory::CreateAndStartMarking<Marker>( GetMarkerRef() = std::make_unique<Marker>(
Heap::From(GetHeap())->AsBase(), GetPlatformHandle().get(), config); Heap::From(GetHeap())->AsBase(), GetPlatformHandle().get(), config);
GetMarkerRef()->StartMarking();
DelegatingTracingControllerImpl::check_expectations = true; DelegatingTracingControllerImpl::check_expectations = true;
} }
......
...@@ -24,8 +24,9 @@ class WeakContainerTest : public testing::TestWithHeap { ...@@ -24,8 +24,9 @@ class WeakContainerTest : public testing::TestWithHeap {
Config config = {Config::CollectionType::kMajor, Config config = {Config::CollectionType::kMajor,
Config::StackState::kNoHeapPointers, Config::StackState::kNoHeapPointers,
Config::MarkingType::kIncremental}; Config::MarkingType::kIncremental};
GetMarkerRef() = MarkerFactory::CreateAndStartMarking<Marker>( GetMarkerRef() = std::make_unique<Marker>(
Heap::From(GetHeap())->AsBase(), GetPlatformHandle().get(), config); Heap::From(GetHeap())->AsBase(), GetPlatformHandle().get(), config);
GetMarkerRef()->StartMarking();
} }
void FinishMarking(Config::StackState stack_state) { void FinishMarking(Config::StackState stack_state) {
......
...@@ -162,10 +162,11 @@ class WriteBarrierTest : public testing::TestWithHeap { ...@@ -162,10 +162,11 @@ class WriteBarrierTest : public testing::TestWithHeap {
public: public:
WriteBarrierTest() : internal_heap_(Heap::From(GetHeap())) { WriteBarrierTest() : internal_heap_(Heap::From(GetHeap())) {
DCHECK_NULL(GetMarkerRef().get()); DCHECK_NULL(GetMarkerRef().get());
GetMarkerRef() = MarkerFactory::CreateAndStartMarking<Marker>( GetMarkerRef() =
*internal_heap_, GetPlatformHandle().get(), std::make_unique<Marker>(*internal_heap_, GetPlatformHandle().get(),
IncrementalMarkingScope::kIncrementalConfig); IncrementalMarkingScope::kIncrementalConfig);
marker_ = GetMarkerRef().get(); marker_ = GetMarkerRef().get();
marker_->StartMarking();
} }
~WriteBarrierTest() override { ~WriteBarrierTest() override {
......
...@@ -45,9 +45,9 @@ TEST_F(MarkingWorklistTest, PushPopEmbedder) { ...@@ -45,9 +45,9 @@ TEST_F(MarkingWorklistTest, PushPopEmbedder) {
MarkingWorklists::Local worklists(&holder); MarkingWorklists::Local worklists(&holder);
HeapObject pushed_object = HeapObject pushed_object =
ReadOnlyRoots(i_isolate()->heap()).undefined_value(); ReadOnlyRoots(i_isolate()->heap()).undefined_value();
worklists.PushEmbedder(pushed_object); worklists.PushWrapper(pushed_object);
HeapObject popped_object; HeapObject popped_object;
EXPECT_TRUE(worklists.PopEmbedder(&popped_object)); EXPECT_TRUE(worklists.PopWrapper(&popped_object));
EXPECT_EQ(popped_object, pushed_object); EXPECT_EQ(popped_object, pushed_object);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment