1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 6 #define INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 7 8 #include <cstddef> 9 10 #include "cppgc/name-provider.h" 11 #include "v8config.h" // NOLINT(build/include_directory) 12 13 namespace cppgc { 14 namespace internal { 15 16 #if CPPGC_SUPPORTS_OBJECT_NAMES && defined(__clang__) 17 #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1 18 19 // Provides constexpr c-string storage for a name of fixed |Size| characters. 20 // Automatically appends terminating 0 byte. 21 template <size_t Size> 22 struct NameBuffer { 23 char name[Size + 1]{}; 24 FromCStringNameBuffer25 static constexpr NameBuffer FromCString(const char* str) { 26 NameBuffer result; 27 for (size_t i = 0; i < Size; ++i) result.name[i] = str[i]; 28 result.name[Size] = 0; 29 return result; 30 } 31 }; 32 33 template <typename T> GetTypename()34const char* GetTypename() { 35 static constexpr char kSelfPrefix[] = 36 "const char *cppgc::internal::GetTypename() [T ="; 37 static_assert(__builtin_strncmp(__PRETTY_FUNCTION__, kSelfPrefix, 38 sizeof(kSelfPrefix) - 1) == 0, 39 "The prefix must match"); 40 static constexpr const char* kTypenameStart = 41 __PRETTY_FUNCTION__ + sizeof(kSelfPrefix); 42 static constexpr size_t kTypenameSize = 43 __builtin_strlen(__PRETTY_FUNCTION__) - sizeof(kSelfPrefix) - 1; 44 // NameBuffer is an indirection that is needed to make sure that only a 45 // substring of __PRETTY_FUNCTION__ gets materialized in the binary. 46 static constexpr auto buffer = 47 NameBuffer<kTypenameSize>::FromCString(kTypenameStart); 48 return buffer.name; 49 } 50 51 #else 52 #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 0 53 #endif 54 55 struct HeapObjectName { 56 const char* value; 57 bool name_was_hidden; 58 }; 59 60 class V8_EXPORT NameTraitBase { 61 protected: 62 static HeapObjectName GetNameFromTypeSignature(const char*); 63 }; 64 65 // Trait that specifies how the garbage collector retrieves the name for a 66 // given object. 67 template <typename T> 68 class NameTrait final : public NameTraitBase { 69 public: GetName(const void * obj)70 static HeapObjectName GetName(const void* obj) { 71 return GetNameFor(static_cast<const T*>(obj)); 72 } 73 74 private: GetNameFor(const NameProvider * name_provider)75 static HeapObjectName GetNameFor(const NameProvider* name_provider) { 76 return {name_provider->GetName(), false}; 77 } 78 GetNameFor(...)79 static HeapObjectName GetNameFor(...) { 80 #if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 81 return {GetTypename<T>(), false}; 82 #elif CPPGC_SUPPORTS_OBJECT_NAMES 83 84 #if defined(V8_CC_GNU) 85 #define PRETTY_FUNCTION_VALUE __PRETTY_FUNCTION__ 86 #elif defined(V8_CC_MSVC) 87 #define PRETTY_FUNCTION_VALUE __FUNCSIG__ 88 #else 89 #define PRETTY_FUNCTION_VALUE nullptr 90 #endif 91 92 static const HeapObjectName leaky_name = 93 GetNameFromTypeSignature(PRETTY_FUNCTION_VALUE); 94 return leaky_name; 95 96 #undef PRETTY_FUNCTION_VALUE 97 98 #else // !CPPGC_SUPPORTS_OBJECT_NAMES 99 return {NameProvider::kHiddenName, true}; 100 #endif // !CPPGC_SUPPORTS_OBJECT_NAMES 101 } 102 }; 103 104 using NameCallback = HeapObjectName (*)(const void*); 105 106 } // namespace internal 107 } // namespace cppgc 108 109 #undef CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 110 111 #endif // INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ 112