/src/node/deps/v8/include/cppgc/internal/name-trait.h
Line  | Count  | Source  | 
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 <cstdint>  | 
10  |  | #include <type_traits>  | 
11  |  |  | 
12  |  | #include "cppgc/name-provider.h"  | 
13  |  | #include "v8config.h"  // NOLINT(build/include_directory)  | 
14  |  |  | 
15  |  | namespace cppgc { | 
16  |  | namespace internal { | 
17  |  |  | 
18  |  | #if CPPGC_SUPPORTS_OBJECT_NAMES && defined(__clang__)  | 
19  |  | #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1  | 
20  |  |  | 
21  |  | // Provides constexpr c-string storage for a name of fixed |Size| characters.  | 
22  |  | // Automatically appends terminating 0 byte.  | 
23  |  | template <size_t Size>  | 
24  |  | struct NameBuffer { | 
25  |  |   char name[Size + 1]{}; | 
26  |  |  | 
27  |  |   static constexpr NameBuffer FromCString(const char* str) { | 
28  |  |     NameBuffer result;  | 
29  |  |     for (size_t i = 0; i < Size; ++i) result.name[i] = str[i];  | 
30  |  |     result.name[Size] = 0;  | 
31  |  |     return result;  | 
32  |  |   }  | 
33  |  | };  | 
34  |  |  | 
35  |  | template <typename T>  | 
36  |  | const char* GetTypename() { | 
37  |  |   static constexpr char kSelfPrefix[] =  | 
38  |  |       "const char *cppgc::internal::GetTypename() [T =";  | 
39  |  |   static_assert(__builtin_strncmp(__PRETTY_FUNCTION__, kSelfPrefix,  | 
40  |  |                                   sizeof(kSelfPrefix) - 1) == 0,  | 
41  |  |                 "The prefix must match");  | 
42  |  |   static constexpr const char* kTypenameStart =  | 
43  |  |       __PRETTY_FUNCTION__ + sizeof(kSelfPrefix);  | 
44  |  |   static constexpr size_t kTypenameSize =  | 
45  |  |       __builtin_strlen(__PRETTY_FUNCTION__) - sizeof(kSelfPrefix) - 1;  | 
46  |  |   // NameBuffer is an indirection that is needed to make sure that only a  | 
47  |  |   // substring of __PRETTY_FUNCTION__ gets materialized in the binary.  | 
48  |  |   static constexpr auto buffer =  | 
49  |  |       NameBuffer<kTypenameSize>::FromCString(kTypenameStart);  | 
50  |  |   return buffer.name;  | 
51  |  | }  | 
52  |  |  | 
53  |  | #else  | 
54  |  | #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 0  | 
55  |  | #endif  | 
56  |  |  | 
57  |  | struct HeapObjectName { | 
58  |  |   const char* value;  | 
59  |  |   bool name_was_hidden;  | 
60  |  | };  | 
61  |  |  | 
62  |  | enum class HeapObjectNameForUnnamedObject : uint8_t { | 
63  |  |   kUseClassNameIfSupported,  | 
64  |  |   kUseHiddenName,  | 
65  |  | };  | 
66  |  |  | 
67  |  | class V8_EXPORT NameTraitBase { | 
68  |  |  protected:  | 
69  |  |   static HeapObjectName GetNameFromTypeSignature(const char*);  | 
70  |  | };  | 
71  |  |  | 
72  |  | // Trait that specifies how the garbage collector retrieves the name for a  | 
73  |  | // given object.  | 
74  |  | template <typename T>  | 
75  |  | class NameTrait final : public NameTraitBase { | 
76  |  |  public:  | 
77  | 0  |   static constexpr bool HasNonHiddenName() { | 
78  | 0  | #if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME  | 
79  | 0  |     return true;  | 
80  | 0  | #elif CPPGC_SUPPORTS_OBJECT_NAMES  | 
81  | 0  |     return true;  | 
82  | 0  | #else   // !CPPGC_SUPPORTS_OBJECT_NAMES  | 
83  | 0  |     return std::is_base_of_v<NameProvider, T>;  | 
84  | 0  | #endif  // !CPPGC_SUPPORTS_OBJECT_NAMES  | 
85  | 0  |   }  | 
86  |  |  | 
87  |  |   static HeapObjectName GetName(  | 
88  | 0  |       const void* obj, HeapObjectNameForUnnamedObject name_retrieval_mode) { | 
89  | 0  |     return GetNameFor(static_cast<const T*>(obj), name_retrieval_mode);  | 
90  | 0  |   } Unexecuted instantiation: cppgc::internal::NameTrait<v8::Object::Wrappable>::GetName(void const*, cppgc::internal::HeapObjectNameForUnnamedObject) Unexecuted instantiation: cppgc::internal::NameTrait<node::contextify::ContextifyContext>::GetName(void const*, cppgc::internal::HeapObjectNameForUnnamedObject) Unexecuted instantiation: cppgc::internal::NameTrait<node::contextify::ContextifyScript>::GetName(void const*, cppgc::internal::HeapObjectNameForUnnamedObject)  | 
91  |  |  | 
92  |  |  private:  | 
93  |  |   static HeapObjectName GetNameFor(const NameProvider* name_provider,  | 
94  | 0  |                                    HeapObjectNameForUnnamedObject) { | 
95  |  |     // Objects inheriting from `NameProvider` are not considered unnamed as  | 
96  |  |     // users already provided a name for them.  | 
97  | 0  |     return {name_provider->GetHumanReadableName(), false}; | 
98  | 0  |   } Unexecuted instantiation: cppgc::internal::NameTrait<v8::Object::Wrappable>::GetNameFor(cppgc::NameProvider const*, cppgc::internal::HeapObjectNameForUnnamedObject) Unexecuted instantiation: cppgc::internal::NameTrait<node::contextify::ContextifyContext>::GetNameFor(cppgc::NameProvider const*, cppgc::internal::HeapObjectNameForUnnamedObject) Unexecuted instantiation: cppgc::internal::NameTrait<node::contextify::ContextifyScript>::GetNameFor(cppgc::NameProvider const*, cppgc::internal::HeapObjectNameForUnnamedObject)  | 
99  |  |  | 
100  |  |   static HeapObjectName GetNameFor(  | 
101  |  |       const void*, HeapObjectNameForUnnamedObject name_retrieval_mode) { | 
102  |  |     if (name_retrieval_mode == HeapObjectNameForUnnamedObject::kUseHiddenName)  | 
103  |  |       return {NameProvider::kHiddenName, true}; | 
104  |  |  | 
105  |  | #if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME  | 
106  |  |     return {GetTypename<T>(), false}; | 
107  |  | #elif CPPGC_SUPPORTS_OBJECT_NAMES  | 
108  |  |  | 
109  |  | #if defined(V8_CC_GNU)  | 
110  |  | #define PRETTY_FUNCTION_VALUE __PRETTY_FUNCTION__  | 
111  |  | #elif defined(V8_CC_MSVC)  | 
112  |  | #define PRETTY_FUNCTION_VALUE __FUNCSIG__  | 
113  |  | #else  | 
114  |  | #define PRETTY_FUNCTION_VALUE nullptr  | 
115  |  | #endif  | 
116  |  |  | 
117  |  |     static const HeapObjectName leaky_name =  | 
118  |  |         GetNameFromTypeSignature(PRETTY_FUNCTION_VALUE);  | 
119  |  |     return leaky_name;  | 
120  |  |  | 
121  |  | #undef PRETTY_FUNCTION_VALUE  | 
122  |  |  | 
123  |  | #else   // !CPPGC_SUPPORTS_OBJECT_NAMES  | 
124  |  |     // We wanted to use a class name but were unable to provide one due to  | 
125  |  |     // compiler limitations or build configuration. As such, return the hidden  | 
126  |  |     // name with name_was_hidden=false, which will cause this object to be  | 
127  |  |     // visible in the snapshot.  | 
128  |  |     return {NameProvider::kHiddenName, false}; | 
129  |  | #endif  // !CPPGC_SUPPORTS_OBJECT_NAMES  | 
130  |  |   }  | 
131  |  | };  | 
132  |  |  | 
133  |  | using NameCallback = HeapObjectName (*)(const void*,  | 
134  |  |                                         HeapObjectNameForUnnamedObject);  | 
135  |  |  | 
136  |  | }  // namespace internal  | 
137  |  | }  // namespace cppgc  | 
138  |  |  | 
139  |  | #undef CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME  | 
140  |  |  | 
141  |  | #endif  // INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_  |