Commit 479bfdb1 authored by Michael Lippautz's avatar Michael Lippautz Committed by V8 LUCI CQ

cppgc: Optimize GCInfo setup

In Blink's version of Oilpan, GCInfo objects would reside in .bss and
a table would translate between an index and the .bss address. Upon
retrieving a GCInfoIndex, the slow path merely passes a .bss pointer
to a slow path setup method to create the table mapping.

In cppgc, we set up GCInfo entries directly in the table. This is
slightly faster for actually using GCInfo objects as there's no
indirection between table and .bss, and it also saves one pointer (the
indirection) per type that is set up. The downside of this approach is
that individual components of a GCInfo objects, that are all
type-dependent, need to be passed to the conditional setup method.
Since GCInfo indices must be retrieved on each allocation, this
pollutes the fast path with additional instructions.

However, GCInfo components are actually known at compile-time for many
objects. In such cases, we can use a compile-time static dispatch to
encode the known parameters in different functions. This saves around
40KiB of memory on ChromePublic.apk and also creates a more compact
fast path for allocation.

Bug: chromium:1238884, chromium:1056170
Change-Id: Iedd809a8baefcc02f131d2b2c77d341b0abe43bb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3094007Reviewed-by: 's avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76291}
parent a91547b7
......@@ -207,7 +207,7 @@ struct PostConstructionCallbackTrait {
* \returns an instance of type T.
*/
template <typename T, typename... Args>
T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
T* object =
MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
PostConstructionCallbackTrait<T>::Call(object);
......@@ -225,8 +225,9 @@ T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
* \returns an instance of type T.
*/
template <typename T, typename... Args>
T* MakeGarbageCollected(AllocationHandle& handle,
AdditionalBytes additional_bytes, Args&&... args) {
V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
AdditionalBytes additional_bytes,
Args&&... args) {
T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
std::forward<Args>(args)...);
PostConstructionCallbackTrait<T>::Call(object);
......
......@@ -76,6 +76,8 @@ struct FinalizerTrait {
}
public:
static constexpr bool HasFinalizer() { return kCallback; }
// The callback used to finalize an object of type T.
static constexpr FinalizationCallback kCallback =
kNonTrivialFinalizer ? Finalize : nullptr;
......
......@@ -19,11 +19,93 @@ namespace internal {
using GCInfoIndex = uint16_t;
// Acquires a new GC info object and returns the index. In addition, also
// updates `registered_index` atomically.
V8_EXPORT GCInfoIndex
EnsureGCInfoIndex(std::atomic<GCInfoIndex>& registered_index,
FinalizationCallback, TraceCallback, NameCallback, bool);
struct V8_EXPORT EnsureGCInfoIndexTrait final {
// Acquires a new GC info object and returns the index. In addition, also
// updates `registered_index` atomically.
template <typename T>
V8_INLINE static GCInfoIndex EnsureIndex(
std::atomic<GCInfoIndex>& registered_index) {
return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
}
private:
template <typename T, bool = std::is_polymorphic<T>::value,
bool = FinalizerTrait<T>::HasFinalizer(),
bool = NameTrait<T>::HasNonHiddenName()>
struct EnsureGCInfoIndexTraitDispatch;
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback,
FinalizationCallback,
NameCallback);
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback,
FinalizationCallback);
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback, NameCallback);
static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback);
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
FinalizationCallback,
TraceCallback,
NameCallback);
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback,
FinalizationCallback);
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback,
NameCallback);
static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
TraceCallback);
};
#define DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function) \
template <typename T> \
struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch< \
T, is_polymorphic, has_finalizer, has_non_hidden_name> { \
V8_INLINE GCInfoIndex \
operator()(std::atomic<GCInfoIndex>& registered_index) { \
return function; \
} \
};
// --------------------------------------------------------------------- //
// DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function)
// --------------------------------------------------------------------- //
DISPATCH(true, true, true, //
EnsureGCInfoIndexPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
FinalizerTrait<T>::kCallback, //
NameTrait<T>::GetName)) //
DISPATCH(true, true, false, //
EnsureGCInfoIndexPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
FinalizerTrait<T>::kCallback)) //
DISPATCH(true, false, true, //
EnsureGCInfoIndexPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
NameTrait<T>::GetName)) //
DISPATCH(true, false, false, //
EnsureGCInfoIndexPolymorphic(registered_index, //
TraceTrait<T>::Trace)) //
DISPATCH(false, true, true, //
EnsureGCInfoIndexNonPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
FinalizerTrait<T>::kCallback, //
NameTrait<T>::GetName)) //
DISPATCH(false, true, false, //
EnsureGCInfoIndexNonPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
FinalizerTrait<T>::kCallback)) //
DISPATCH(false, false, true, //
EnsureGCInfoIndexNonPolymorphic(registered_index, //
TraceTrait<T>::Trace, //
NameTrait<T>::GetName)) //
DISPATCH(false, false, false, //
EnsureGCInfoIndexNonPolymorphic(registered_index, //
TraceTrait<T>::Trace)) //
#undef DISPATCH
// Fold types based on finalizer behavior. Note that finalizer characteristics
// align with trace behavior, i.e., destructors are virtual when trace methods
......@@ -57,16 +139,13 @@ struct GCInfoFolding {
// finalization, and naming.
template <typename T>
struct GCInfoTrait final {
static GCInfoIndex Index() {
V8_INLINE static GCInfoIndex Index() {
static_assert(sizeof(T), "T must be fully defined");
static std::atomic<GCInfoIndex>
registered_index; // Uses zero initialization.
const GCInfoIndex index = registered_index.load(std::memory_order_acquire);
return index ? index
: EnsureGCInfoIndex(
registered_index, FinalizerTrait<T>::kCallback,
TraceTrait<T>::Trace, NameTrait<T>::GetName,
std::is_polymorphic<T>::value);
: EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
}
};
......
......@@ -6,6 +6,7 @@
#define INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_
#include <cstddef>
#include <type_traits>
#include "cppgc/name-provider.h"
#include "v8config.h" // NOLINT(build/include_directory)
......@@ -67,6 +68,16 @@ class V8_EXPORT NameTraitBase {
template <typename T>
class NameTrait final : public NameTraitBase {
public:
static constexpr bool HasNonHiddenName() {
#if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME
return true;
#elif CPPGC_SUPPORTS_OBJECT_NAMES
return true;
#else // !CPPGC_SUPPORTS_OBJECT_NAMES
return std::is_base_of<NameProvider, T>::value;
#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
}
static HeapObjectName GetName(const void* obj) {
return GetNameFor(static_cast<const T*>(obj));
}
......
......@@ -3,19 +3,87 @@
// found in the LICENSE file.
#include "include/cppgc/internal/gc-info.h"
#include "include/cppgc/internal/name-trait.h"
#include "include/v8config.h"
#include "src/heap/cppgc/gc-info-table.h"
namespace cppgc {
namespace internal {
GCInfoIndex EnsureGCInfoIndex(std::atomic<GCInfoIndex>& registered_index,
FinalizationCallback finalization_callback,
TraceCallback trace_callback,
NameCallback name_callback, bool has_v_table) {
namespace {
HeapObjectName GetHiddenName(const void*) {
return {NameProvider::kHiddenName, true};
}
} // namespace
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback,
FinalizationCallback finalization_callback, NameCallback name_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index,
{finalization_callback, trace_callback, name_callback, has_v_table});
{finalization_callback, trace_callback, name_callback, true});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback,
FinalizationCallback finalization_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index,
{finalization_callback, trace_callback, GetHiddenName, true});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback,
NameCallback name_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index, {nullptr, trace_callback, name_callback, true});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index, {nullptr, trace_callback, GetHiddenName, true});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexNonPolymorphic(
std::atomic<GCInfoIndex>& registered_index,
FinalizationCallback finalization_callback, TraceCallback trace_callback,
NameCallback name_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index,
{finalization_callback, trace_callback, name_callback, false});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexNonPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback,
FinalizationCallback finalization_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index,
{finalization_callback, trace_callback, GetHiddenName, false});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexNonPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback,
NameCallback name_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index, {nullptr, trace_callback, name_callback, false});
}
// static
GCInfoIndex EnsureGCInfoIndexTrait::EnsureGCInfoIndexNonPolymorphic(
std::atomic<GCInfoIndex>& registered_index, TraceCallback trace_callback) {
return GlobalGCInfoTable::GetMutable().RegisterNewGCInfo(
registered_index, {nullptr, trace_callback, GetHiddenName, false});
}
} // namespace internal
......
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