api: Add JSVisitor and JSMember reference
- Adds JSVisitor that is used for unified heap marking. - Adds JSMember as supported reference type that also encapsulates a write barrier in future. JSMember is a replacement for TracedReference which can be deprecated with EmbedderHeapTracer once the library is used to handle unified heap collections. The dispatch for v8::JSMember on cppgc::Visitor is provided through a specialization of TraceTrait. Bug: chromium:1056170 Change-Id: I60d976ae66db3e5fa2e690a21627bdcb8c6871af Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284488 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Anton Bikineev <bikineev@chromium.org> Reviewed-by: Omer Katz <omerkatz@chromium.org> Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/master@{#68716}
This commit is contained in:
parent
bc793ae8e5
commit
3a50eae048
2
BUILD.gn
2
BUILD.gn
@ -1837,6 +1837,7 @@ v8_header_set("v8_headers") {
|
||||
public_configs = [ ":v8_header_features" ]
|
||||
|
||||
sources = [
|
||||
"include/v8-cppgc.h",
|
||||
"include/v8-fast-api-calls.h",
|
||||
"include/v8-internal.h",
|
||||
"include/v8.h",
|
||||
@ -2173,6 +2174,7 @@ v8_source_set("v8_base_without_compiler") {
|
||||
### gcmole(all) ###
|
||||
"$target_gen_dir/builtins-generated/bytecodes-builtins-list.h",
|
||||
"include/cppgc/common.h",
|
||||
"include/v8-cppgc.h",
|
||||
"include/v8-fast-api-calls.h",
|
||||
"include/v8-inspector-protocol.h",
|
||||
"include/v8-inspector.h",
|
||||
|
@ -2,4 +2,5 @@ include_rules = [
|
||||
# v8-inspector-protocol.h depends on generated files under include/inspector.
|
||||
"+inspector",
|
||||
"+cppgc/common.h",
|
||||
"+cppgc/visitor.h",
|
||||
]
|
||||
|
@ -21,6 +21,8 @@ template <typename T, typename WeaknessPolicy, typename LocationPolicy,
|
||||
class BasicPersistent;
|
||||
class ConservativeTracingVisitor;
|
||||
class VisitorBase;
|
||||
class VisitorFactory;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
using WeakCallback = void (*)(const LivenessBroker&, const void*);
|
||||
@ -44,6 +46,14 @@ using WeakCallback = void (*)(const LivenessBroker&, const void*);
|
||||
*/
|
||||
class Visitor {
|
||||
public:
|
||||
class Key {
|
||||
private:
|
||||
Key() = default;
|
||||
friend class internal::VisitorFactory;
|
||||
};
|
||||
|
||||
explicit Visitor(Key) {}
|
||||
|
||||
virtual ~Visitor() = default;
|
||||
|
||||
/**
|
||||
@ -147,8 +157,6 @@ class Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
Visitor() = default;
|
||||
|
||||
template <typename Persistent,
|
||||
std::enable_if_t<Persistent::IsStrongPersistent::value>* = nullptr>
|
||||
void TraceRoot(const Persistent& p, const SourceLocation& loc) {
|
||||
@ -193,11 +201,11 @@ class Visitor {
|
||||
V8_EXPORT void CheckObjectNotInConstruction(const void* address);
|
||||
#endif // V8_ENABLE_CHECKS
|
||||
|
||||
friend class internal::VisitorBase;
|
||||
template <typename T, typename WeaknessPolicy, typename LocationPolicy,
|
||||
typename CheckingPolicy>
|
||||
friend class internal::BasicPersistent;
|
||||
friend class internal::ConservativeTracingVisitor;
|
||||
friend class internal::VisitorBase;
|
||||
};
|
||||
|
||||
} // namespace cppgc
|
||||
|
78
include/v8-cppgc.h
Normal file
78
include/v8-cppgc.h
Normal file
@ -0,0 +1,78 @@
|
||||
// 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 INCLUDE_V8_CPPGC_H_
|
||||
#define INCLUDE_V8_CPPGC_H_
|
||||
|
||||
#include "cppgc/visitor.h"
|
||||
#include "v8.h" // NOLINT(build/include_directory)
|
||||
|
||||
namespace v8 {
|
||||
|
||||
template <typename T>
|
||||
class JSMember;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// TODO(chromium:1056170): Provide implementation based on global handles.
|
||||
class JSMemberBase {
|
||||
private:
|
||||
JSMemberBase() = default;
|
||||
|
||||
template <typename T>
|
||||
friend class v8::JSMember;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* A traced handle without destructor that clears the handle. The handle may
|
||||
* only be used in GarbageCollected objects and must be processed in a Trace()
|
||||
* method.
|
||||
*
|
||||
* TODO(chromium:1056170): Implementation.
|
||||
*/
|
||||
template <typename T>
|
||||
class JSMember : public internal::JSMemberBase {
|
||||
static_assert(std::is_base_of<v8::Value, T>::value,
|
||||
"JSMember only supports references to v8::Value");
|
||||
|
||||
public:
|
||||
JSMember() = default;
|
||||
|
||||
// Heterogeneous construction.
|
||||
template <typename U,
|
||||
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
|
||||
JSMember(const JSMember<U>& other) {} // NOLINT
|
||||
};
|
||||
|
||||
class JSVisitor : public cppgc::Visitor {
|
||||
public:
|
||||
explicit JSVisitor(cppgc::Visitor::Key key) : cppgc::Visitor(key) {}
|
||||
|
||||
template <typename T>
|
||||
void Trace(const JSMember<T>& ref) {
|
||||
Visit(ref);
|
||||
}
|
||||
|
||||
protected:
|
||||
using cppgc::Visitor::Visit;
|
||||
|
||||
virtual void Visit(const internal::JSMemberBase& ref) {}
|
||||
};
|
||||
|
||||
} // namespace v8
|
||||
|
||||
namespace cppgc {
|
||||
|
||||
template <typename T>
|
||||
struct TraceTrait<v8::JSMember<T>> {
|
||||
static void Trace(Visitor* visitor, const v8::JSMember<T>* self) {
|
||||
static_cast<v8::JSVisitor*>(visitor)->Trace(*self);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cppgc
|
||||
|
||||
#endif // INCLUDE_V8_CPPGC_H_
|
@ -16,11 +16,16 @@ class HeapBase;
|
||||
class HeapObjectHeader;
|
||||
class PageBackend;
|
||||
|
||||
class VisitorFactory {
|
||||
public:
|
||||
static constexpr Visitor::Key CreateKey() { return {}; }
|
||||
};
|
||||
|
||||
// Base visitor that is allowed to create a public cppgc::Visitor object and
|
||||
// use its internals.
|
||||
class VisitorBase : public cppgc::Visitor {
|
||||
public:
|
||||
VisitorBase() = default;
|
||||
VisitorBase() : cppgc::Visitor(VisitorFactory::CreateKey()) {}
|
||||
~VisitorBase() override = default;
|
||||
|
||||
VisitorBase(const VisitorBase&) = delete;
|
||||
|
@ -241,6 +241,7 @@ 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",
|
||||
|
53
test/unittests/heap/js-visitor-unittest.cc
Normal file
53
test/unittests/heap/js-visitor-unittest.cc
Normal file
@ -0,0 +1,53 @@
|
||||
// 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
|
Loading…
Reference in New Issue
Block a user