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/+/3094007 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@{#76291}
This commit is contained in:
parent
a91547b7e0
commit
479bfdb11b
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user