Commit b01869ca authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

cppgc: Add GCInfo folding

Adds GCInfo folding that delegates GCInfo requests to the
parent-most object if finalizer semantics match.

Folding is disabled for builds that want exact object names
as those names are also managed through GCInfo objects.

Bug: chromium:1056170
Change-Id: I783aad930587853741da533d0b9b56ba160d0596
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2748588
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73339}
parent 2dbdfcdd
......@@ -102,8 +102,10 @@ class MakeGarbageCollectedTraitBase
* \returns the memory to construct an object of type T on.
*/
static void* Allocate(AllocationHandle& handle, size_t size) {
return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(handle,
size);
return SpacePolicy<
typename internal::GCInfoFolding<
T, typename T::ParentMostGarbageCollectedType>::ResultType,
typename SpaceTrait<T>::Space>::Allocate(handle, size);
}
/**
......
......@@ -73,10 +73,11 @@ class GarbageCollectedBase {
* };
* \endcode
*/
template <typename>
template <typename T>
class GarbageCollected : public internal::GarbageCollectedBase {
public:
using IsGarbageCollectedTypeMarker = void;
using ParentMostGarbageCollectedType = T;
protected:
GarbageCollected() = default;
......
......@@ -28,6 +28,34 @@ class V8_EXPORT RegisteredGCInfoIndex final {
const GCInfoIndex index_;
};
// Fold types based on finalizer behavior. Note that finalizer characteristics
// align with trace behavior, i.e., destructors are virtual when trace methods
// are and vice versa.
template <typename T, typename ParentMostGarbageCollectedType>
struct GCInfoFolding {
static constexpr bool kHasVirtualDestructorAtBase =
std::has_virtual_destructor<ParentMostGarbageCollectedType>::value;
static constexpr bool kBothTypesAreTriviallyDestructible =
std::is_trivially_destructible<ParentMostGarbageCollectedType>::value &&
std::is_trivially_destructible<T>::value;
static constexpr bool kHasCustomFinalizerDispatchAtBase =
internal::HasFinalizeGarbageCollectedObject<
ParentMostGarbageCollectedType>::value;
#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
static constexpr bool kWantsDetailedObjectNames = true;
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
static constexpr bool kWantsDetailedObjectNames = false;
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
// Folding would regresses name resolution when deriving names from C++
// class names as it would just folds a name to the base class name.
using ResultType = std::conditional_t<(kHasVirtualDestructorAtBase ||
kBothTypesAreTriviallyDestructible ||
kHasCustomFinalizerDispatchAtBase) &&
!kWantsDetailedObjectNames,
ParentMostGarbageCollectedType, T>;
};
// Trait determines how the garbage collector treats objects wrt. to traversing,
// finalization, and naming.
template <typename T>
......
......@@ -4,6 +4,8 @@
#include "include/cppgc/internal/gc-info.h"
#include <type_traits>
#include "include/cppgc/platform.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h"
......@@ -161,5 +163,110 @@ TEST_F(GCInfoTraitTest, TraitReturnsDifferentIndexForDifferentTypes) {
EXPECT_NE(index1, index2);
}
namespace {
struct Dummy {};
class BaseWithVirtualDestructor
: public GarbageCollected<BaseWithVirtualDestructor> {
public:
virtual ~BaseWithVirtualDestructor() = default;
void Trace(Visitor*) const {}
private:
std::unique_ptr<Dummy> non_trivially_destructible_;
};
class ChildOfBaseWithVirtualDestructor : public BaseWithVirtualDestructor {
public:
~ChildOfBaseWithVirtualDestructor() override = default;
};
static_assert(std::has_virtual_destructor<BaseWithVirtualDestructor>::value,
"Must have virtual destructor.");
static_assert(!std::is_trivially_destructible<BaseWithVirtualDestructor>::value,
"Must not be trivially destructible");
#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(std::is_same<typename internal::GCInfoFolding<
ChildOfBaseWithVirtualDestructor,
ChildOfBaseWithVirtualDestructor::
ParentMostGarbageCollectedType>::ResultType,
ChildOfBaseWithVirtualDestructor>::value,
"No folding to preserve object names");
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(std::is_same<typename internal::GCInfoFolding<
ChildOfBaseWithVirtualDestructor,
ChildOfBaseWithVirtualDestructor::
ParentMostGarbageCollectedType>::ResultType,
BaseWithVirtualDestructor>::value,
"Must fold into base as base has virtual destructor.");
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
class TriviallyDestructibleBase
: public GarbageCollected<TriviallyDestructibleBase> {
public:
virtual void Trace(Visitor*) const {}
};
class ChildOfTriviallyDestructibleBase : public TriviallyDestructibleBase {};
static_assert(!std::has_virtual_destructor<TriviallyDestructibleBase>::value,
"Must not have virtual destructor.");
static_assert(std::is_trivially_destructible<TriviallyDestructibleBase>::value,
"Must be trivially destructible");
#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(std::is_same<typename internal::GCInfoFolding<
ChildOfTriviallyDestructibleBase,
ChildOfTriviallyDestructibleBase::
ParentMostGarbageCollectedType>::ResultType,
ChildOfTriviallyDestructibleBase>::value,
"No folding to preserve object names");
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(std::is_same<typename internal::GCInfoFolding<
ChildOfTriviallyDestructibleBase,
ChildOfTriviallyDestructibleBase::
ParentMostGarbageCollectedType>::ResultType,
TriviallyDestructibleBase>::value,
"Must fold into base as both are trivially destructible.");
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
class TypeWithCustomFinalizationMethodAtBase
: public GarbageCollected<TypeWithCustomFinalizationMethodAtBase> {
public:
void FinalizeGarbageCollectedObject() {}
void Trace(Visitor*) const {}
private:
std::unique_ptr<Dummy> non_trivially_destructible_;
};
class ChildOfTypeWithCustomFinalizationMethodAtBase
: public TypeWithCustomFinalizationMethodAtBase {};
static_assert(
!std::has_virtual_destructor<TypeWithCustomFinalizationMethodAtBase>::value,
"Must not have virtual destructor.");
static_assert(!std::is_trivially_destructible<
TypeWithCustomFinalizationMethodAtBase>::value,
"Must not be trivially destructible");
#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(
std::is_same<typename internal::GCInfoFolding<
ChildOfTypeWithCustomFinalizationMethodAtBase,
ChildOfTypeWithCustomFinalizationMethodAtBase::
ParentMostGarbageCollectedType>::ResultType,
ChildOfTypeWithCustomFinalizationMethodAtBase>::value,
"No folding to preserve object names");
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
static_assert(std::is_same<typename internal::GCInfoFolding<
ChildOfTypeWithCustomFinalizationMethodAtBase,
ChildOfTypeWithCustomFinalizationMethodAtBase::
ParentMostGarbageCollectedType>::ResultType,
TypeWithCustomFinalizationMethodAtBase>::value,
"Must fold into base as base has custom finalizer dispatch.");
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
} // namespace
} // namespace internal
} // namespace cppgc
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