11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <cstddef> 91cb0ef41Sopenharmony_ci#include <cstdint> 101cb0ef41Sopenharmony_ci#include <type_traits> 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "cppgc/name-provider.h" 131cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace cppgc { 161cb0ef41Sopenharmony_cinamespace internal { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#if CPPGC_SUPPORTS_OBJECT_NAMES && defined(__clang__) 191cb0ef41Sopenharmony_ci#define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// Provides constexpr c-string storage for a name of fixed |Size| characters. 221cb0ef41Sopenharmony_ci// Automatically appends terminating 0 byte. 231cb0ef41Sopenharmony_citemplate <size_t Size> 241cb0ef41Sopenharmony_cistruct NameBuffer { 251cb0ef41Sopenharmony_ci char name[Size + 1]{}; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci static constexpr NameBuffer FromCString(const char* str) { 281cb0ef41Sopenharmony_ci NameBuffer result; 291cb0ef41Sopenharmony_ci for (size_t i = 0; i < Size; ++i) result.name[i] = str[i]; 301cb0ef41Sopenharmony_ci result.name[Size] = 0; 311cb0ef41Sopenharmony_ci return result; 321cb0ef41Sopenharmony_ci } 331cb0ef41Sopenharmony_ci}; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_citemplate <typename T> 361cb0ef41Sopenharmony_ciconst char* GetTypename() { 371cb0ef41Sopenharmony_ci static constexpr char kSelfPrefix[] = 381cb0ef41Sopenharmony_ci "const char *cppgc::internal::GetTypename() [T ="; 391cb0ef41Sopenharmony_ci static_assert(__builtin_strncmp(__PRETTY_FUNCTION__, kSelfPrefix, 401cb0ef41Sopenharmony_ci sizeof(kSelfPrefix) - 1) == 0, 411cb0ef41Sopenharmony_ci "The prefix must match"); 421cb0ef41Sopenharmony_ci static constexpr const char* kTypenameStart = 431cb0ef41Sopenharmony_ci __PRETTY_FUNCTION__ + sizeof(kSelfPrefix); 441cb0ef41Sopenharmony_ci static constexpr size_t kTypenameSize = 451cb0ef41Sopenharmony_ci __builtin_strlen(__PRETTY_FUNCTION__) - sizeof(kSelfPrefix) - 1; 461cb0ef41Sopenharmony_ci // NameBuffer is an indirection that is needed to make sure that only a 471cb0ef41Sopenharmony_ci // substring of __PRETTY_FUNCTION__ gets materialized in the binary. 481cb0ef41Sopenharmony_ci static constexpr auto buffer = 491cb0ef41Sopenharmony_ci NameBuffer<kTypenameSize>::FromCString(kTypenameStart); 501cb0ef41Sopenharmony_ci return buffer.name; 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci#else 541cb0ef41Sopenharmony_ci#define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 0 551cb0ef41Sopenharmony_ci#endif 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_cistruct HeapObjectName { 581cb0ef41Sopenharmony_ci const char* value; 591cb0ef41Sopenharmony_ci bool name_was_hidden; 601cb0ef41Sopenharmony_ci}; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_cienum class HeapObjectNameForUnnamedObject : uint8_t { 631cb0ef41Sopenharmony_ci kUseClassNameIfSupported, 641cb0ef41Sopenharmony_ci kUseHiddenName, 651cb0ef41Sopenharmony_ci}; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ciclass V8_EXPORT NameTraitBase { 681cb0ef41Sopenharmony_ci protected: 691cb0ef41Sopenharmony_ci static HeapObjectName GetNameFromTypeSignature(const char*); 701cb0ef41Sopenharmony_ci}; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci// Trait that specifies how the garbage collector retrieves the name for a 731cb0ef41Sopenharmony_ci// given object. 741cb0ef41Sopenharmony_citemplate <typename T> 751cb0ef41Sopenharmony_ciclass NameTrait final : public NameTraitBase { 761cb0ef41Sopenharmony_ci public: 771cb0ef41Sopenharmony_ci static constexpr bool HasNonHiddenName() { 781cb0ef41Sopenharmony_ci#if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 791cb0ef41Sopenharmony_ci return true; 801cb0ef41Sopenharmony_ci#elif CPPGC_SUPPORTS_OBJECT_NAMES 811cb0ef41Sopenharmony_ci return true; 821cb0ef41Sopenharmony_ci#else // !CPPGC_SUPPORTS_OBJECT_NAMES 831cb0ef41Sopenharmony_ci return std::is_base_of<NameProvider, T>::value; 841cb0ef41Sopenharmony_ci#endif // !CPPGC_SUPPORTS_OBJECT_NAMES 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci static HeapObjectName GetName( 881cb0ef41Sopenharmony_ci const void* obj, HeapObjectNameForUnnamedObject name_retrieval_mode) { 891cb0ef41Sopenharmony_ci return GetNameFor(static_cast<const T*>(obj), name_retrieval_mode); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci private: 931cb0ef41Sopenharmony_ci static HeapObjectName GetNameFor(const NameProvider* name_provider, 941cb0ef41Sopenharmony_ci HeapObjectNameForUnnamedObject) { 951cb0ef41Sopenharmony_ci // Objects inheriting from `NameProvider` are not considered unnamed as 961cb0ef41Sopenharmony_ci // users already provided a name for them. 971cb0ef41Sopenharmony_ci return {name_provider->GetHumanReadableName(), false}; 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci static HeapObjectName GetNameFor( 1011cb0ef41Sopenharmony_ci const void*, HeapObjectNameForUnnamedObject name_retrieval_mode) { 1021cb0ef41Sopenharmony_ci if (name_retrieval_mode == HeapObjectNameForUnnamedObject::kUseHiddenName) 1031cb0ef41Sopenharmony_ci return {NameProvider::kHiddenName, true}; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci#if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1061cb0ef41Sopenharmony_ci return {GetTypename<T>(), false}; 1071cb0ef41Sopenharmony_ci#elif CPPGC_SUPPORTS_OBJECT_NAMES 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci#if defined(V8_CC_GNU) 1101cb0ef41Sopenharmony_ci#define PRETTY_FUNCTION_VALUE __PRETTY_FUNCTION__ 1111cb0ef41Sopenharmony_ci#elif defined(V8_CC_MSVC) 1121cb0ef41Sopenharmony_ci#define PRETTY_FUNCTION_VALUE __FUNCSIG__ 1131cb0ef41Sopenharmony_ci#else 1141cb0ef41Sopenharmony_ci#define PRETTY_FUNCTION_VALUE nullptr 1151cb0ef41Sopenharmony_ci#endif 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci static const HeapObjectName leaky_name = 1181cb0ef41Sopenharmony_ci GetNameFromTypeSignature(PRETTY_FUNCTION_VALUE); 1191cb0ef41Sopenharmony_ci return leaky_name; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci#undef PRETTY_FUNCTION_VALUE 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci#else // !CPPGC_SUPPORTS_OBJECT_NAMES 1241cb0ef41Sopenharmony_ci return {NameProvider::kHiddenName, true}; 1251cb0ef41Sopenharmony_ci#endif // !CPPGC_SUPPORTS_OBJECT_NAMES 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci}; 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciusing NameCallback = HeapObjectName (*)(const void*, 1301cb0ef41Sopenharmony_ci HeapObjectNameForUnnamedObject); 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci} // namespace internal 1331cb0ef41Sopenharmony_ci} // namespace cppgc 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci#undef CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci#endif // INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 138