/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_ |