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