cppgc: First round of API docs

Bug: chromium:1056170
Change-Id: Idbbab7af430e3bc2791eba630b331a75a67e35a9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2142262
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@{#67112}
This commit is contained in:
Michael Lippautz 2020-04-14 14:02:39 +02:00 committed by Commit Bot
parent bb9f0c2b2f
commit 2e61c41c4b
3 changed files with 161 additions and 48 deletions

View File

@ -41,30 +41,53 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal {
} // namespace internal } // namespace internal
// Users with custom allocation needs (e.g. overriding size) should override /**
// MakeGarbageCollectedTrait (see below) and inherit their trait from * Base trait that provides utilities for advancers users that have custom
// MakeGarbageCollectedTraitBase to get access to low-level primitives. * allocation needs (e.g., overriding size). It's expected that users override
* MakeGarbageCollectedTrait (see below) and inherit from
* MakeGarbageCollectedTraitBase and make use of the low-level primitives
* offered to allocate and construct an object.
*/
template <typename T> template <typename T>
class MakeGarbageCollectedTraitBase class MakeGarbageCollectedTraitBase
: private internal::MakeGarbageCollectedTraitInternal { : private internal::MakeGarbageCollectedTraitInternal {
protected: protected:
// Allocates an object of |size| bytes on |heap|. /**
// * Allocates memory for an object of type T.
// TODO(mlippautz): Allow specifying arena for specific embedder uses. *
* \param heap The heap to allocate this object on.
* \param size The size that should be reserved for the object.
* \returns the memory to construct an object of type T on.
*/
static void* Allocate(Heap* heap, size_t size) { static void* Allocate(Heap* heap, size_t size) {
// TODO(chromium:1056170): Allow specifying arena for specific embedder
// uses.
return internal::MakeGarbageCollectedTraitInternal::Allocate( return internal::MakeGarbageCollectedTraitInternal::Allocate(
heap, size, internal::GCInfoTrait<T>::Index()); heap, size, internal::GCInfoTrait<T>::Index());
} }
// Marks an object as being fully constructed, resulting in precise handling /**
// by the garbage collector. * Marks an object as fully constructed, resulting in precise handling by the
* garbage collector.
*
* \param payload The base pointer the object is allocated at.
*/
static void MarkObjectAsFullyConstructed(const void* payload) { static void MarkObjectAsFullyConstructed(const void* payload) {
// internal::MarkObjectAsFullyConstructed(payload);
internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed( internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
payload); payload);
} }
}; };
/**
* Default trait class that specifies how to construct an object of type T.
* Advanced users may override how an object is constructed using the utilities
* that are provided through MakeGarbageCollectedTraitBase.
*
* Any trait overriding construction must
* - allocate through MakeGarbageCollectedTraitBase<T>::Allocate;
* - mark the object as fully constructed using
* MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed;
*/
template <typename T> template <typename T>
class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> { class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
public: public:
@ -83,8 +106,14 @@ class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
} }
}; };
// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage /**
// collected type. * Constructs a managed object of type T where T transitively inherits from
* GarbageCollected.
*
* \param args List of arguments with which an instance of T will be
* constructed.
* \returns an instance of type T.
*/
template <typename T, typename... Args> template <typename T, typename... Args>
T* MakeGarbageCollected(Heap* heap, Args&&... args) { T* MakeGarbageCollected(Heap* heap, Args&&... args) {
return MakeGarbageCollectedTrait<T>::Call(heap, std::forward<Args>(args)...); return MakeGarbageCollectedTrait<T>::Call(heap, std::forward<Args>(args)...);

View File

@ -38,6 +38,41 @@ class GarbageCollectedBase {
} // namespace internal } // namespace internal
/**
* Base class for managed objects. Only descendent types of GarbageCollected can
* be constructed using MakeGarbageCollected. Must be inherited from as
* left-most base class.
*
* Types inheriting from GarbageCollected must provide a method of
* signature `void Trace(cppgc::Visitor*)` that dispatchs all managed pointers
* to the visitor and delegates to garbage-collected base classes. The method
* must be virtual if the type is not directly a child of GarbageCollected and
* marked as final.
*
* \code
* // Example using final class.
* class FinalType final : public GarbageCollected<FinalType> {
* public:
* void Trace(cppgc::Visitor* visitor) {
* // Dispatch using visitor->Trace(...);
* }
* };
*
* // Example using non-final base class.
* class NonFinalBase : public GarbageCollected<NonFinalBase> {
* public:
* virtual void Trace(cppgc::Visitor*) {}
* };
*
* class FinalChild final : public NonFinalBase {
* public:
* void Trace(cppgc::Visitor* visitor) final {
* // Dispatch using visitor->Trace(...);
* NonFinalBase::Trace(visitor);
* }
* };
* \endcode
*/
template <typename> template <typename>
class GarbageCollected : public internal::GarbageCollectedBase { class GarbageCollected : public internal::GarbageCollectedBase {
public: public:
@ -47,6 +82,24 @@ class GarbageCollected : public internal::GarbageCollectedBase {
GarbageCollected() = default; GarbageCollected() = default;
}; };
/**
* Base class for managed mixin objects. Such objects cannot be constructed
* directly but must be mixed into the inheritance hierarchy of a
* GarbageCollected object.
*
* Types inheriting from GarbageCollectedMixin must override a virtual method of
* signature `void Trace(cppgc::Visitor*)` that dispatchs all managed pointers
* to the visitor and delegates to base classes.
*
* \code
* class Mixin : public GarbageCollectedMixin {
* public:
* void Trace(cppgc::Visitor* visitor) override {
* // Dispatch using visitor->Trace(...);
* }
* };
* \endcode
*/
class GarbageCollectedMixin : public internal::GarbageCollectedBase { class GarbageCollectedMixin : public internal::GarbageCollectedBase {
public: public:
using IsGarbageCollectedMixinTypeMarker = void; using IsGarbageCollectedMixinTypeMarker = void;
@ -54,14 +107,18 @@ class GarbageCollectedMixin : public internal::GarbageCollectedBase {
// Sentinel used to mark not-fully-constructed mixins. // Sentinel used to mark not-fully-constructed mixins.
static constexpr void* kNotFullyConstructedObject = nullptr; static constexpr void* kNotFullyConstructedObject = nullptr;
virtual void Trace(cppgc::Visitor*) {}
// Provide default implementation that indicate that the vtable is not yet // Provide default implementation that indicate that the vtable is not yet
// set up properly. This is used to to get GCInfo objects for mixins so that // set up properly. This is used to to get GCInfo objects for mixins so that
// these objects can be processed later on. // these objects can be processed later on.
virtual TraceDescriptor GetTraceDescriptor() const { virtual TraceDescriptor GetTraceDescriptor() const {
return {kNotFullyConstructedObject, nullptr}; return {kNotFullyConstructedObject, nullptr};
} }
/**
* This Trace method must be overriden by objects inheriting from
* GarbageCollectedMixin.
*/
virtual void Trace(cppgc::Visitor*) {}
}; };
namespace internal { namespace internal {
@ -70,12 +127,32 @@ class __thisIsHereToForceASemicolonAfterThisMacro {};
} // namespace internal } // namespace internal
// The USING_GARBAGE_COLLECTED_MIXIN macro defines all methods and markers /**
// needed for handling mixins. HasUsingGarbageCollectedMixinMacro is used * Macro defines all methods and markers needed for handling mixins. Must be
// by the clang GC plugin to check for proper usages of the * used on the type that is inheriting from GarbageCollected *and*
// USING_GARBAGE_COLLECTED_MIXIN macro. * GarbageCollectedMixin.
*
* \code
* class Mixin : public GarbageCollectedMixin {
* public:
* void Trace(cppgc::Visitor* visitor) override {
* // Dispatch using visitor->Trace(...);
* }
* };
*
* class Foo : public GarbageCollected<Foo>, public Mixin {
* USING_GARBAGE_COLLECTED_MIXIN();
* public:
* void Trace(cppgc::Visitor* visitor) override {
* // Dispatch using visitor->Trace(...);
* Mixin::Trace(visitor);
* }
* };
* \endcode
*/
#define USING_GARBAGE_COLLECTED_MIXIN() \ #define USING_GARBAGE_COLLECTED_MIXIN() \
public: \ public: \
/* Marker is used by clang to check for proper usages of the macro. */ \
typedef int HasUsingGarbageCollectedMixinMacro; \ typedef int HasUsingGarbageCollectedMixinMacro; \
\ \
TraceDescriptor GetTraceDescriptor() const override { \ TraceDescriptor GetTraceDescriptor() const override { \
@ -91,23 +168,23 @@ class __thisIsHereToForceASemicolonAfterThisMacro {};
private: \ private: \
friend class internal::__thisIsHereToForceASemicolonAfterThisMacro friend class internal::__thisIsHereToForceASemicolonAfterThisMacro
// Merge two or more Mixins into one: /**
// * Merge two or more Mixins into one.
// class A : public GarbageCollectedMixin {}; *
// class B : public GarbageCollectedMixin {}; * \code
// class C : public A, public B { * class A : public GarbageCollectedMixin {};
// // C::GetTraceDescriptor is now ambiguous because there are two * class B : public GarbageCollectedMixin {};
// // candidates: A::GetTraceDescriptor and B::GetTraceDescriptor. Ditto for * class C : public A, public B {
// // other functions. * MERGE_GARBAGE_COLLECTED_MIXINS();
// * public:
// MERGE_GARBAGE_COLLECTED_MIXINS(); * };
// // The macro defines C::GetTraceDescriptor, similar to * \endcode
// // GarbageCollectedMixin, so that they are no longer ambiguous. */
// // USING_GARBAGE_COLLECTED_MIXIN() overrides them later and provides the
// // implementations.
// };
#define MERGE_GARBAGE_COLLECTED_MIXINS() \ #define MERGE_GARBAGE_COLLECTED_MIXINS() \
public: \ public: \
/* When using multiple mixins the methods become */ \
/* ambigous. Providing additional implementations */ \
/* disambiguate them again. */ \
TraceDescriptor GetTraceDescriptor() const override { \ TraceDescriptor GetTraceDescriptor() const override { \
return {kNotFullyConstructedObject, nullptr}; \ return {kNotFullyConstructedObject, nullptr}; \
} \ } \

View File

@ -37,8 +37,9 @@ class BasicMember : private CheckingPolicy {
template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag, template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
typename OtherCheckingPolicy, typename OtherCheckingPolicy,
typename = std::enable_if_t<std::is_base_of<T, U>::value>> typename = std::enable_if_t<std::is_base_of<T, U>::value>>
BasicMember(const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy, BasicMember( // NOLINT
OtherCheckingPolicy>& other) const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>& other)
: BasicMember(other.Get()) {} : BasicMember(other.Get()) {}
BasicMember& operator=(const BasicMember& other) { BasicMember& operator=(const BasicMember& other) {
@ -78,7 +79,7 @@ class BasicMember : private CheckingPolicy {
} }
explicit operator bool() const { return Get(); } explicit operator bool() const { return Get(); }
operator T*() const { return Get(); } operator T*() const { return Get(); } // NOLINT
T* operator->() const { return Get(); } T* operator->() const { return Get(); }
T& operator*() const { return *Get(); } T& operator*() const { return *Get(); }
@ -146,27 +147,33 @@ struct IsWeak<
} // namespace internal } // namespace internal
// Members are used in classes to contain strong pointers to other garbage /**
// collected objects. All Member fields of a class must be traced in the class' * Members are used in classes to contain strong pointers to other garbage
// trace method. * collected objects. All Member fields of a class must be traced in the class'
* trace method.
*/
template <typename T> template <typename T>
using Member = internal::BasicMember<T, internal::StrongMemberTag, using Member = internal::BasicMember<T, internal::StrongMemberTag,
internal::DijkstraWriteBarrierPolicy>; internal::DijkstraWriteBarrierPolicy>;
// WeakMember is similar to Member in that it is used to point to other garbage /**
// collected objects. However instead of creating a strong pointer to the * WeakMember is similar to Member in that it is used to point to other garbage
// object, the WeakMember creates a weak pointer, which does not keep the * collected objects. However instead of creating a strong pointer to the
// pointee alive. Hence if all pointers to to a heap allocated object are weak * object, the WeakMember creates a weak pointer, which does not keep the
// the object will be garbage collected. At the time of GC the weak pointers * pointee alive. Hence if all pointers to to a heap allocated object are weak
// will automatically be set to null. * the object will be garbage collected. At the time of GC the weak pointers
* will automatically be set to null.
*/
template <typename T> template <typename T>
using WeakMember = internal::BasicMember<T, internal::WeakMemberTag, using WeakMember = internal::BasicMember<T, internal::WeakMemberTag,
internal::DijkstraWriteBarrierPolicy>; internal::DijkstraWriteBarrierPolicy>;
// UntracedMember is a pointer to an on-heap object that is not traced for some /**
// reason. Do not use this unless you know what you are doing. Keeping raw * UntracedMember is a pointer to an on-heap object that is not traced for some
// pointers to on-heap objects is prohibited unless used from stack. Pointee * reason. Do not use this unless you know what you are doing. Keeping raw
// must be kept alive through other means. * pointers to on-heap objects is prohibited unless used from stack. Pointee
* must be kept alive through other means.
*/
template <typename T> template <typename T>
using UntracedMember = internal::BasicMember<T, internal::UntracedMemberTag, using UntracedMember = internal::BasicMember<T, internal::UntracedMemberTag,
internal::NoWriteBarrierPolicy>; internal::NoWriteBarrierPolicy>;