• 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 
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()34 const 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