| // Copyright 2020 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ |
| #define INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ |
| |
| #include <cstddef> |
| |
| #include "cppgc/name-provider.h" |
| #include "v8config.h" // NOLINT(build/include_directory) |
| |
| namespace cppgc { |
| namespace internal { |
| |
| #if CPPGC_SUPPORTS_OBJECT_NAMES && defined(__clang__) |
| #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 1 |
| |
| // Provides constexpr c-string storage for a name of fixed |Size| characters. |
| // Automatically appends terminating 0 byte. |
| template <size_t Size> |
| struct NameBuffer { |
| char name[Size + 1]{}; |
| |
| static constexpr NameBuffer FromCString(const char* str) { |
| NameBuffer result; |
| for (size_t i = 0; i < Size; ++i) result.name[i] = str[i]; |
| result.name[Size] = 0; |
| return result; |
| } |
| }; |
| |
| template <typename T> |
| const char* GetTypename() { |
| static constexpr char kSelfPrefix[] = |
| "const char *cppgc::internal::GetTypename() [T ="; |
| static_assert(__builtin_strncmp(__PRETTY_FUNCTION__, kSelfPrefix, |
| sizeof(kSelfPrefix) - 1) == 0, |
| "The prefix must match"); |
| static constexpr const char* kTypenameStart = |
| __PRETTY_FUNCTION__ + sizeof(kSelfPrefix); |
| static constexpr size_t kTypenameSize = |
| __builtin_strlen(__PRETTY_FUNCTION__) - sizeof(kSelfPrefix) - 1; |
| // NameBuffer is an indirection that is needed to make sure that only a |
| // substring of __PRETTY_FUNCTION__ gets materialized in the binary. |
| static constexpr auto buffer = |
| NameBuffer<kTypenameSize>::FromCString(kTypenameStart); |
| return buffer.name; |
| } |
| |
| #else |
| #define CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME 0 |
| #endif |
| |
| struct HeapObjectName { |
| const char* value; |
| bool name_was_hidden; |
| }; |
| |
| class V8_EXPORT NameTraitBase { |
| protected: |
| static HeapObjectName GetNameFromTypeSignature(const char*); |
| }; |
| |
| // Trait that specifies how the garbage collector retrieves the name for a |
| // given object. |
| template <typename T> |
| class NameTrait final : public NameTraitBase { |
| public: |
| static HeapObjectName GetName(const void* obj) { |
| return GetNameFor(static_cast<const T*>(obj)); |
| } |
| |
| private: |
| static HeapObjectName GetNameFor(const NameProvider* name_provider) { |
| return {name_provider->GetName(), false}; |
| } |
| |
| static HeapObjectName GetNameFor(...) { |
| #if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME |
| return {GetTypename<T>(), false}; |
| #elif CPPGC_SUPPORTS_OBJECT_NAMES |
| |
| #if defined(V8_CC_GNU) |
| #define PRETTY_FUNCTION_VALUE __PRETTY_FUNCTION__ |
| #elif defined(V8_CC_MSVC) |
| #define PRETTY_FUNCTION_VALUE __FUNCSIG__ |
| #else |
| #define PRETTY_FUNCTION_VALUE nullptr |
| #endif |
| |
| static const HeapObjectName leaky_name = |
| GetNameFromTypeSignature(PRETTY_FUNCTION_VALUE); |
| return leaky_name; |
| |
| #undef PRETTY_FUNCTION_VALUE |
| |
| #else // !CPPGC_SUPPORTS_OBJECT_NAMES |
| return {NameProvider::kHiddenName, true}; |
| #endif // !CPPGC_SUPPORTS_OBJECT_NAMES |
| } |
| }; |
| |
| using NameCallback = HeapObjectName (*)(const void*); |
| |
| } // namespace internal |
| } // namespace cppgc |
| |
| #undef CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME |
| |
| #endif // INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_ |