Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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_