File: name-trait.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (141 lines) | stat: -rw-r--r-- 4,437 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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 <cstdint>
#include <type_traits>

#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;
};

enum class HeapObjectNameForUnnamedObject : uint8_t {
  kUseClassNameIfSupported,
  kUseHiddenName,
};

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 constexpr bool HasNonHiddenName() {
#if CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME
    return true;
#elif CPPGC_SUPPORTS_OBJECT_NAMES
    return true;
#else   // !CPPGC_SUPPORTS_OBJECT_NAMES
    return std::is_base_of_v<NameProvider, T>;
#endif  // !CPPGC_SUPPORTS_OBJECT_NAMES
  }

  static HeapObjectName GetName(
      const void* obj, HeapObjectNameForUnnamedObject name_retrieval_mode) {
    return GetNameFor(static_cast<const T*>(obj), name_retrieval_mode);
  }

 private:
  static HeapObjectName GetNameFor(const NameProvider* name_provider,
                                   HeapObjectNameForUnnamedObject) {
    // Objects inheriting from `NameProvider` are not considered unnamed as
    // users already provided a name for them.
    return {name_provider->GetHumanReadableName(), false};
  }

  static HeapObjectName GetNameFor(
      const void*, HeapObjectNameForUnnamedObject name_retrieval_mode) {
    if (name_retrieval_mode == HeapObjectNameForUnnamedObject::kUseHiddenName)
      return {NameProvider::kHiddenName, true};

#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
    // We wanted to use a class name but were unable to provide one due to
    // compiler limitations or build configuration. As such, return the hidden
    // name with name_was_hidden=false, which will cause this object to be
    // visible in the snapshot.
    return {NameProvider::kHiddenName, false};
#endif  // !CPPGC_SUPPORTS_OBJECT_NAMES
  }
};

using NameCallback = HeapObjectName (*)(const void*,
                                        HeapObjectNameForUnnamedObject);

}  // namespace internal
}  // namespace cppgc

#undef CPPGC_SUPPORTS_COMPILE_TIME_TYPENAME

#endif  // INCLUDE_CPPGC_INTERNAL_NAME_TRAIT_H_