Commit 9a11ada5 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

heap: Add atomic unified-heap support

Adds support for main-thread handling of JSMember during the
atomic pause.

Follow-ups for later:
- Copy/Move/Heterogenous assignment
- Write barrier
- Atomic handling for concurrent processing.

Bug: chromium:1056170
Change-Id: Ia9ac4599ca85cf7cc2d67066e89485744d7d56b6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2289781
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68813}
parent b212db2d
......@@ -2486,6 +2486,9 @@ v8_source_set("v8_base_without_compiler") {
"src/heap/concurrent-marking.h",
"src/heap/cppgc-js/cpp-heap.cc",
"src/heap/cppgc-js/cpp-heap.h",
"src/heap/cppgc-js/unified-heap-marking-state.h",
"src/heap/cppgc-js/unified-heap-marking-visitor.cc",
"src/heap/cppgc-js/unified-heap-marking-visitor.h",
"src/heap/embedder-tracing.cc",
"src/heap/embedder-tracing.h",
"src/heap/factory-base.cc",
......
......@@ -6,24 +6,56 @@
#define INCLUDE_V8_CPPGC_H_
#include "cppgc/visitor.h"
#include "v8-internal.h" // NOLINT(build/include_directory)
#include "v8.h" // NOLINT(build/include_directory)
namespace v8 {
class Isolate;
template <typename T>
class JSMember;
namespace internal {
class JSMemberBaseExtractor;
// TODO(chromium:1056170): Provide implementation based on global handles.
class JSMemberBase {
public:
/**
* Returns true if the reference is empty, i.e., has not been assigned
* object.
*/
bool IsEmpty() const { return val_ == kNullAddress; }
/**
* Clears the reference. IsEmpty() will return true after this call.
*/
V8_INLINE void Reset();
private:
static internal::Address New(v8::Isolate* isolate, internal::Address* object,
internal::Address* slot);
static void Delete(internal::Address* slot);
JSMemberBase() = default;
JSMemberBase(v8::Isolate* isolate, internal::Address* object)
: val_(New(isolate, object, &this->val_)) {}
internal::Address val_ = kNullAddress;
template <typename T>
friend class v8::JSMember;
friend class v8::internal::JSMemberBaseExtractor;
};
void JSMemberBase::Reset() {
if (IsEmpty()) return;
Delete(reinterpret_cast<internal::Address*>(val_));
val_ = kNullAddress;
}
} // namespace internal
/**
......@@ -41,7 +73,13 @@ class JSMember : public internal::JSMemberBase {
public:
JSMember() = default;
template <typename U,
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
JSMember(Isolate* isolate, Local<U> that)
: internal::JSMemberBase(isolate, that.val_) {}
// Heterogeneous construction.
// TODO(chromium:1056170): Implementation.
template <typename U,
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
JSMember(const JSMember<U>& other) {} // NOLINT
......@@ -53,6 +91,7 @@ class JSVisitor : public cppgc::Visitor {
template <typename T>
void Trace(const JSMember<T>& ref) {
if (ref.IsEmpty()) return;
Visit(ref);
}
......
......@@ -11,6 +11,7 @@
#include <utility> // For move
#include <vector>
#include "include/v8-cppgc.h"
#include "include/v8-fast-api-calls.h"
#include "include/v8-profiler.h"
#include "include/v8-util.h"
......@@ -986,6 +987,32 @@ i::Address* V8::GlobalizeTracedReference(i::Isolate* isolate, i::Address* obj,
return result.location();
}
// static
i::Address i::JSMemberBase::New(v8::Isolate* isolate, i::Address* object,
i::Address* slot) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, JSMemberBase, New);
#ifdef DEBUG
Utils::ApiCheck((object != nullptr), "i::JSMemberBase::New",
"the object must be not null");
Utils::ApiCheck((slot != nullptr), "i::JSMemberBase::New",
"the address slot must be not null");
#endif
i::Handle<i::Object> result = i_isolate->global_handles()->CreateTraced(
*object, slot, false /* no destructor */);
#ifdef VERIFY_HEAP
if (i::FLAG_verify_heap) {
i::Object(*object).ObjectVerify(i_isolate);
}
#endif // VERIFY_HEAP
return reinterpret_cast<i::Address>(result.location());
}
// static
void i::JSMemberBase::Delete(i::Address* slot) {
i::GlobalHandles::DestroyTraced(slot);
}
i::Address* V8::CopyGlobalReference(i::Address* from) {
i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(from);
return result.location();
......
......@@ -9,7 +9,11 @@
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/time.h"
#include "src/execution/isolate.h"
#include "src/flags/flags.h"
#include "src/heap/base/stack.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/cppgc-js/unified-heap-marking-visitor.h"
#include "src/heap/cppgc/gc-info-table.h"
#include "src/heap/cppgc/heap-base.h"
#include "src/heap/cppgc/heap-object-header.h"
......@@ -59,9 +63,11 @@ class CppgcPlatformAdapter final : public cppgc::Platform {
v8::Isolate* isolate_;
};
class UnifiedHeapMarker : public cppgc::internal::MarkerBase {
class UnifiedHeapMarker final : public cppgc::internal::MarkerBase {
public:
explicit UnifiedHeapMarker(cppgc::internal::HeapBase& heap);
explicit UnifiedHeapMarker(Heap& v8_heap, cppgc::internal::HeapBase& heap);
~UnifiedHeapMarker() final = default;
void AddObject(void*);
......@@ -70,19 +76,22 @@ class UnifiedHeapMarker : public cppgc::internal::MarkerBase {
cppgc::internal::ConservativeTracingVisitor& conservative_visitor() final {
return conservative_marking_visitor_;
}
heap::base::StackVisitor& stack_visitor() final {
::heap::base::StackVisitor& stack_visitor() final {
return conservative_marking_visitor_;
}
private:
// TODO(chromium:1056170): Implement unified heap specific marking visitors.
cppgc::internal::MarkingVisitor marking_visitor_;
UnifiedHeapMarkingState unified_heap_mutator_marking_state_;
UnifiedHeapMarkingVisitor marking_visitor_;
cppgc::internal::ConservativeMarkingVisitor conservative_marking_visitor_;
};
UnifiedHeapMarker::UnifiedHeapMarker(cppgc::internal::HeapBase& heap)
UnifiedHeapMarker::UnifiedHeapMarker(Heap& v8_heap,
cppgc::internal::HeapBase& heap)
: cppgc::internal::MarkerBase(heap),
marking_visitor_(heap, mutator_marking_state_),
unified_heap_mutator_marking_state_(v8_heap),
marking_visitor_(heap, mutator_marking_state_,
unified_heap_mutator_marking_state_),
conservative_marking_visitor_(heap, mutator_marking_state_,
marking_visitor_) {}
......@@ -95,7 +104,8 @@ void UnifiedHeapMarker::AddObject(void* object) {
CppHeap::CppHeap(v8::Isolate* isolate, size_t custom_spaces)
: cppgc::internal::HeapBase(std::make_shared<CppgcPlatformAdapter>(isolate),
custom_spaces) {
custom_spaces),
isolate_(*reinterpret_cast<Isolate*>(isolate)) {
CHECK(!FLAG_incremental_marking_wrappers);
}
......@@ -111,7 +121,7 @@ void CppHeap::RegisterV8References(
}
void CppHeap::TracePrologue(TraceFlags flags) {
marker_.reset(new UnifiedHeapMarker(AsBase()));
marker_.reset(new UnifiedHeapMarker(*isolate_.heap(), AsBase()));
const UnifiedHeapMarker::MarkingConfig marking_config{
UnifiedHeapMarker::MarkingConfig::CollectionType::kMajor,
cppgc::Heap::StackState::kNoHeapPointers,
......
......@@ -33,6 +33,7 @@ class V8_EXPORT_PRIVATE CppHeap final : public cppgc::internal::HeapBase,
void EnterFinalPause(EmbedderStackState stack_state) final;
private:
Isolate& isolate_;
bool marking_done_ = false;
};
......
// 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_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_H_
#define V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_H_
#include "include/v8-cppgc.h"
#include "src/heap/heap.h"
namespace v8 {
class JSMemberBase;
namespace internal {
class JSMemberBaseExtractor {
public:
static Address* ObjectReference(const JSMemberBase& ref) {
return reinterpret_cast<Address*>(ref.val_);
}
};
class UnifiedHeapMarkingState {
public:
explicit UnifiedHeapMarkingState(Heap& heap) : heap_(heap) {}
UnifiedHeapMarkingState(const UnifiedHeapMarkingState&) = delete;
UnifiedHeapMarkingState& operator=(const UnifiedHeapMarkingState&) = delete;
inline void MarkAndPush(const JSMemberBase&);
private:
Heap& heap_;
};
void UnifiedHeapMarkingState::MarkAndPush(const JSMemberBase& ref) {
heap_.RegisterExternallyReferencedObject(
JSMemberBaseExtractor::ObjectReference(ref));
}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_H_
// 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/cppgc-js/unified-heap-marking-visitor.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/cppgc/heap.h"
#include "src/heap/cppgc/marking-state.h"
#include "src/heap/cppgc/visitor.h"
namespace v8 {
namespace internal {
UnifiedHeapMarkingVisitor::UnifiedHeapMarkingVisitor(
HeapBase& heap, MarkingState& marking_state,
UnifiedHeapMarkingState& unified_heap_marking_state)
: JSVisitor(cppgc::internal::VisitorFactory::CreateKey()),
marking_state_(marking_state),
unified_heap_marking_state_(unified_heap_marking_state) {}
void UnifiedHeapMarkingVisitor::Visit(const void* object,
TraceDescriptor desc) {
marking_state_.MarkAndPush(object, desc);
}
void UnifiedHeapMarkingVisitor::VisitWeak(const void* object,
TraceDescriptor desc,
WeakCallback weak_callback,
const void* weak_member) {
marking_state_.RegisterWeakReferenceIfNeeded(object, desc, weak_callback,
weak_member);
}
void UnifiedHeapMarkingVisitor::VisitRoot(const void* object,
TraceDescriptor desc) {
Visit(object, desc);
}
void UnifiedHeapMarkingVisitor::VisitWeakRoot(const void* object,
TraceDescriptor desc,
WeakCallback weak_callback,
const void* weak_root) {
marking_state_.InvokeWeakRootsCallbackIfNeeded(object, desc, weak_callback,
weak_root);
}
void UnifiedHeapMarkingVisitor::RegisterWeakCallback(WeakCallback callback,
const void* object) {
marking_state_.RegisterWeakCallback(callback, object);
}
void UnifiedHeapMarkingVisitor::Visit(const internal::JSMemberBase& ref) {
unified_heap_marking_state_.MarkAndPush(ref);
}
} // namespace internal
} // namespace v8
// 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_CPPGC_JS_UNIFIED_HEAP_MARKING_VISITOR_H_
#define V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_VISITOR_H_
#include "include/cppgc/trace-trait.h"
#include "include/v8-cppgc.h"
#include "src/base/macros.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/cppgc/marking-visitor.h"
namespace cppgc {
namespace internal {
class MarkingState;
} // namespace internal
} // namespace cppgc
namespace v8 {
namespace internal {
using cppgc::TraceDescriptor;
using cppgc::WeakCallback;
using cppgc::internal::HeapBase;
using cppgc::internal::MarkingState;
class V8_EXPORT_PRIVATE UnifiedHeapMarkingVisitor : public JSVisitor {
public:
UnifiedHeapMarkingVisitor(HeapBase&, MarkingState&, UnifiedHeapMarkingState&);
~UnifiedHeapMarkingVisitor() override = default;
private:
// C++ handling.
void Visit(const void*, TraceDescriptor) final;
void VisitWeak(const void*, TraceDescriptor, WeakCallback, const void*) final;
void VisitRoot(const void*, TraceDescriptor) final;
void VisitWeakRoot(const void*, TraceDescriptor, WeakCallback,
const void*) final;
void RegisterWeakCallback(WeakCallback, const void*) final;
// JS handling.
void Visit(const internal::JSMemberBase& ref) final;
MarkingState& marking_state_;
UnifiedHeapMarkingState& unified_heap_marking_state_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_VISITOR_H_
......@@ -746,6 +746,7 @@ class RuntimeCallTimer final {
V(Int8Array_New) \
V(Isolate_DateTimeConfigurationChangeNotification) \
V(Isolate_LocaleConfigurationChangeNotification) \
V(JSMemberBase_New) \
V(JSON_Parse) \
V(JSON_Stringify) \
V(Map_AsArray) \
......
......@@ -241,7 +241,6 @@ v8_source_set("unittests_sources") {
"heap/heap-unittest.cc",
"heap/heap-utils.h",
"heap/item-parallel-job-unittest.cc",
"heap/js-visitor-unittest.cc",
"heap/list-unittest.cc",
"heap/local-heap-unittest.cc",
"heap/marking-unittest.cc",
......
// 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 "include/cppgc/type-traits.h"
#include "include/v8-cppgc.h"
#include "include/v8.h"
#include "src/heap/cppgc/visitor.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
namespace {
class TestingVisitor : public JSVisitor {
public:
TestingVisitor() : JSVisitor(cppgc::internal::VisitorFactory::CreateKey()) {}
size_t found() const { return found_; }
void ExpectReference(const void* expected) { expected_ = expected; }
cppgc::Visitor& AsBaseVisitor() { return *this; }
protected:
void Visit(const JSMemberBase& ref) final {
if (&ref == expected_) {
found_++;
}
}
private:
size_t found_ = 0;
const void* expected_ = nullptr;
};
} // namespace
TEST(JSVisitorTest, DispatchJSMember) {
TestingVisitor visitor;
JSMember<v8::Value> js_value;
visitor.ExpectReference(&js_value);
visitor.AsBaseVisitor().Trace(js_value);
EXPECT_EQ(1u, visitor.found());
JSMember<v8::Function> js_function;
visitor.ExpectReference(&js_function);
visitor.AsBaseVisitor().Trace(js_function);
EXPECT_EQ(2u, visitor.found());
}
} // namespace internal
} // namespace v8
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