GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: debug_utils-inl.h Lines: 75 80 93.8 %
Date: 2022-09-07 04:19:57 Branches: 205 265 77.4 %

Line Branch Exec Source
1
#ifndef SRC_DEBUG_UTILS_INL_H_
2
#define SRC_DEBUG_UTILS_INL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "debug_utils.h"
7
#include "env.h"
8
9
#include <type_traits>
10
11
namespace node {
12
13
struct ToStringHelper {
14
  template <typename T>
15
962
  static std::string Convert(
16
      const T& value,
17
      std::string(T::* to_string)() const = &T::ToString) {
18
962
    return (value.*to_string)();
19
  }
20
  template <typename T,
21
            typename test_for_number = typename std::
22
                enable_if<std::is_arithmetic<T>::value, bool>::type,
23
            typename dummy = bool>
24
52996
  static std::string Convert(const T& value) { return std::to_string(value); }
25
2840
  static std::string Convert(const char* value) {
26
2840
    return value != nullptr ? value : "(null)";
27
  }
28
6121
  static std::string Convert(const std::string& value) { return value; }
29
53
  static std::string Convert(bool value) { return value ? "true" : "false"; }
30
  template <unsigned BASE_BITS,
31
            typename T,
32
            typename = std::enable_if_t<std::is_integral_v<T>>>
33
12
  static std::string BaseConvert(const T& value) {
34
12
    auto v = static_cast<uint64_t>(value);
35
    char ret[3 * sizeof(T)];
36
12
    char* ptr = ret + 3 * sizeof(T) - 1;
37
12
    *ptr = '\0';
38
12
    const char* digits = "0123456789abcdef";
39
6
    do {
40
18
      unsigned digit = v & ((1 << BASE_BITS) - 1);
41
18
      *--ptr =
42
6
          (BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]);
43
18
    } while ((v >>= BASE_BITS) != 0);
44
12
    return ptr;
45
  }
46
  template <unsigned BASE_BITS,
47
            typename T,
48
            typename = std::enable_if_t<!std::is_integral_v<T>>>
49
  static std::string BaseConvert(T value) {
50
    return Convert(std::forward<T>(value));
51
  }
52
};
53
54
template <typename T>
55
64539
std::string ToString(const T& value) {
56
64539
  return ToStringHelper::Convert(value);
57
}
58
59
template <unsigned BASE_BITS, typename T>
60
12
std::string ToBaseString(const T& value) {
61
12
  return ToStringHelper::BaseConvert<BASE_BITS>(value);
62
}
63
64
16501
inline std::string SPrintFImpl(const char* format) {
65
16501
  const char* p = strchr(format, '%');
66
16501
  if (LIKELY(p == nullptr)) return format;
67
1
  CHECK_EQ(p[1], '%');  // Only '%%' allowed when there are no arguments.
68
69
1
  return std::string(format, p + 1) + SPrintFImpl(p + 2);
70
}
71
72
template <typename Arg, typename... Args>
73
71425
std::string COLD_NOINLINE SPrintFImpl(  // NOLINT(runtime/string)
74
    const char* format, Arg&& arg, Args&&... args) {
75
71425
  const char* p = strchr(format, '%');
76
71425
  CHECK_NOT_NULL(p);  // If you hit this, you passed in too many arguments.
77
214275
  std::string ret(format, p);
78
  // Ignore long / size_t modifiers
79
71547
  while (strchr("lz", *++p) != nullptr) {}
80

71425
  switch (*p) {
81
2
    case '%': {
82
      return ret + '%' + SPrintFImpl(p + 1,
83
                                     std::forward<Arg>(arg),
84
2
                                     std::forward<Args>(args)...);
85
    }
86
    default: {
87
      return ret + '%' + SPrintFImpl(p,
88
                                     std::forward<Arg>(arg),
89
                                     std::forward<Args>(args)...);
90
    }
91
71407
    case 'd':
92
    case 'i':
93
    case 'u':
94
    case 's':
95
71407
      ret += ToString(arg);
96
71407
      break;
97
4
    case 'o':
98
4
      ret += ToBaseString<3>(arg);
99
4
      break;
100
4
    case 'x':
101
4
      ret += ToBaseString<4>(arg);
102
4
      break;
103
4
    case 'X':
104
4
      ret += node::ToUpper(ToBaseString<4>(arg));
105
4
      break;
106
4
    case 'p': {
107
      CHECK(std::is_pointer<typename std::remove_reference<Arg>::type>::value);
108
      char out[20];
109
4
      int n = snprintf(out,
110
                       sizeof(out),
111
                       "%p",
112
                       *reinterpret_cast<const void* const*>(&arg));
113
4
      CHECK_GE(n, 0);
114
4
      ret += out;
115
4
      break;
116
    }
117
  }
118
71423
  return ret + SPrintFImpl(p + 1, std::forward<Args>(args)...);
119
}
120
121
template <typename... Args>
122
25763
std::string COLD_NOINLINE SPrintF(  // NOLINT(runtime/string)
123
    const char* format, Args&&... args) {
124
25763
  return SPrintFImpl(format, std::forward<Args>(args)...);
125
}
126
127
template <typename... Args>
128
5083
void COLD_NOINLINE FPrintF(FILE* file, const char* format, Args&&... args) {
129
5083
  FWrite(file, SPrintF(format, std::forward<Args>(args)...));
130
5083
}
131
132
template <typename... Args>
133
inline void FORCE_INLINE Debug(EnabledDebugList* list,
134
                               DebugCategory cat,
135
                               const char* format,
136
                               Args&&... args) {
137




















970465
  if (!UNLIKELY(list->enabled(cat))) return;
138
945
  FPrintF(stderr, format, std::forward<Args>(args)...);
139
}
140
141
inline void FORCE_INLINE Debug(EnabledDebugList* list,
142
                               DebugCategory cat,
143
                               const char* message) {
144



7006
  if (!UNLIKELY(list->enabled(cat))) return;
145
74
  FPrintF(stderr, "%s", message);
146
}
147
148
template <typename... Args>
149
inline void FORCE_INLINE
150
Debug(Environment* env, DebugCategory cat, const char* format, Args&&... args) {
151
81174
  Debug(env->enabled_debug_list(), cat, format, std::forward<Args>(args)...);
152
}
153
154
inline void FORCE_INLINE Debug(Environment* env,
155
                               DebugCategory cat,
156
                               const char* message) {
157
12456
  Debug(env->enabled_debug_list(), cat, message);
158
}
159
160
template <typename... Args>
161
234
inline void Debug(Environment* env,
162
                  DebugCategory cat,
163
                  const std::string& format,
164
                  Args&&... args) {
165
234
  Debug(env->enabled_debug_list(),
166
        cat,
167
        format.c_str(),
168
        std::forward<Args>(args)...);
169
}
170
171
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that
172
// the FORCE_INLINE flag on them doesn't apply to the contents of this function
173
// as well.
174
// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing
175
// this function for speed and it should rather focus on keeping it out of
176
// hot code paths. In particular, we want to keep the string concatenating code
177
// out of the function containing the original `Debug()` call.
178
template <typename... Args>
179
234
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
180
                                               const char* format,
181
                                               Args&&... args) {
182
618
  Debug(async_wrap->env(),
183
234
        static_cast<DebugCategory>(async_wrap->provider_type()),
184
234
        async_wrap->diagnostic_name() + " " + format + "\n",
185
        std::forward<Args>(args)...);
186
}
187
188
template <typename... Args>
189
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
190
                               const char* format,
191
                               Args&&... args) {
192
  DCHECK_NOT_NULL(async_wrap);
193
1295939
  DebugCategory cat = static_cast<DebugCategory>(async_wrap->provider_type());
194




































2591878
  if (!UNLIKELY(async_wrap->env()->enabled_debug_list()->enabled(cat))) return;
195
117
  UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...);
196
}
197
198
template <typename... Args>
199
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
200
                               const std::string& format,
201
                               Args&&... args) {
202
  Debug(async_wrap, format.c_str(), std::forward<Args>(args)...);
203
}
204
205
namespace per_process {
206
207
template <typename... Args>
208
inline void FORCE_INLINE Debug(DebugCategory cat,
209
                               const char* format,
210
                               Args&&... args) {
211
889212
  Debug(&enabled_debug_list, cat, format, std::forward<Args>(args)...);
212
}
213
214
inline void FORCE_INLINE Debug(DebugCategory cat, const char* message) {
215
12
  Debug(&enabled_debug_list, cat, message);
216
}
217
218
}  // namespace per_process
219
}  // namespace node
220
221
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
222
223
#endif  // SRC_DEBUG_UTILS_INL_H_