Skip to content

Commit 5127c70

Browse files
joyeecheungMylesBorins
authored andcommitted
src: refactor debug category parsing
Move the debug category parsing into a new EnabledDebugList class, so that it can be reused outside of Environment. PR-URL: #31884 Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 2388a40 commit 5127c70

7 files changed

+168
-93
lines changed

src/debug_utils-inl.h

+74
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

66
#include "debug_utils.h"
7+
#include "env.h"
78

89
#include <type_traits>
910

@@ -90,6 +91,79 @@ void COLD_NOINLINE FPrintF(FILE* file, const char* format, Args&&... args) {
9091
FWrite(file, SPrintF(format, std::forward<Args>(args)...));
9192
}
9293

94+
template <typename... Args>
95+
inline void FORCE_INLINE Debug(EnabledDebugList* list,
96+
DebugCategory cat,
97+
const char* format,
98+
Args&&... args) {
99+
if (!UNLIKELY(list->enabled(cat))) return;
100+
FPrintF(stderr, format, std::forward<Args>(args)...);
101+
}
102+
103+
inline void FORCE_INLINE Debug(EnabledDebugList* list,
104+
DebugCategory cat,
105+
const char* message) {
106+
if (!UNLIKELY(list->enabled(cat))) return;
107+
FPrintF(stderr, "%s", message);
108+
}
109+
110+
template <typename... Args>
111+
inline void FORCE_INLINE
112+
Debug(Environment* env, DebugCategory cat, const char* format, Args&&... args) {
113+
Debug(env->enabled_debug_list(), cat, format, std::forward<Args>(args)...);
114+
}
115+
116+
inline void FORCE_INLINE Debug(Environment* env,
117+
DebugCategory cat,
118+
const char* message) {
119+
Debug(env->enabled_debug_list(), cat, message);
120+
}
121+
122+
template <typename... Args>
123+
inline void Debug(Environment* env,
124+
DebugCategory cat,
125+
const std::string& format,
126+
Args&&... args) {
127+
Debug(env->enabled_debug_list(),
128+
cat,
129+
format.c_str(),
130+
std::forward<Args>(args)...);
131+
}
132+
133+
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that
134+
// the FORCE_INLINE flag on them doesn't apply to the contents of this function
135+
// as well.
136+
// We apply COLD_NOINLINE to tell the compiler that it's not worth optimizing
137+
// this function for speed and it should rather focus on keeping it out of
138+
// hot code paths. In particular, we want to keep the string concatenating code
139+
// out of the function containing the original `Debug()` call.
140+
template <typename... Args>
141+
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
142+
const char* format,
143+
Args&&... args) {
144+
Debug(async_wrap->env(),
145+
static_cast<DebugCategory>(async_wrap->provider_type()),
146+
async_wrap->diagnostic_name() + " " + format + "\n",
147+
std::forward<Args>(args)...);
148+
}
149+
150+
template <typename... Args>
151+
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
152+
const char* format,
153+
Args&&... args) {
154+
DCHECK_NOT_NULL(async_wrap);
155+
DebugCategory cat = static_cast<DebugCategory>(async_wrap->provider_type());
156+
if (!UNLIKELY(async_wrap->env()->enabled_debug_list()->enabled(cat))) return;
157+
UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...);
158+
}
159+
160+
template <typename... Args>
161+
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
162+
const std::string& format,
163+
Args&&... args) {
164+
Debug(async_wrap, format.c_str(), std::forward<Args>(args)...);
165+
}
166+
93167
} // namespace node
94168

95169
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

src/debug_utils.cc

+29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "debug_utils-inl.h" // NOLINT(build/include)
22
#include "env-inl.h"
3+
#include "node_internals.h"
34

45
#ifdef __POSIX__
56
#if defined(__linux__)
@@ -54,6 +55,34 @@
5455

5556
namespace node {
5657

58+
void EnabledDebugList::Parse(Environment* env) {
59+
std::string cats;
60+
credentials::SafeGetenv("NODE_DEBUG_NATIVE", &cats, env);
61+
Parse(cats, true);
62+
}
63+
64+
void EnabledDebugList::Parse(const std::string& cats, bool enabled) {
65+
std::string debug_categories = cats;
66+
while (!debug_categories.empty()) {
67+
std::string::size_type comma_pos = debug_categories.find(',');
68+
std::string wanted = ToLower(debug_categories.substr(0, comma_pos));
69+
70+
#define V(name) \
71+
{ \
72+
static const std::string available_category = ToLower(#name); \
73+
if (available_category.find(wanted) != std::string::npos) \
74+
set_enabled(DebugCategory::name, enabled); \
75+
}
76+
77+
DEBUG_CATEGORY_NAMES(V)
78+
#undef V
79+
80+
if (comma_pos == std::string::npos) break;
81+
// Use everything after the `,` as the list for the next iteration.
82+
debug_categories = debug_categories.substr(comma_pos + 1);
83+
}
84+
}
85+
5786
#ifdef __POSIX__
5887
#if HAVE_EXECINFO_H
5988
class PosixSymbolDebuggingContext final : public NativeSymbolDebuggingContext {

src/debug_utils.h

+58-32
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

66
#include "async_wrap.h"
7-
#include "env.h"
87

98
#include <sstream>
109
#include <string>
@@ -21,6 +20,7 @@
2120
#endif
2221

2322
namespace node {
23+
class Environment;
2424

2525
template <typename T>
2626
inline std::string ToString(const T& value);
@@ -36,31 +36,71 @@ template <typename... Args>
3636
inline void FPrintF(FILE* file, const char* format, Args&&... args);
3737
void FWrite(FILE* file, const std::string& str);
3838

39+
// Listing the AsyncWrap provider types first enables us to cast directly
40+
// from a provider type to a debug category.
41+
#define DEBUG_CATEGORY_NAMES(V) \
42+
NODE_ASYNC_PROVIDER_TYPES(V) \
43+
V(INSPECTOR_SERVER) \
44+
V(INSPECTOR_PROFILER) \
45+
V(WASI)
46+
47+
enum class DebugCategory {
48+
#define V(name) name,
49+
DEBUG_CATEGORY_NAMES(V)
50+
#undef V
51+
CATEGORY_COUNT
52+
};
53+
54+
class EnabledDebugList {
55+
public:
56+
bool enabled(DebugCategory category) const {
57+
DCHECK_GE(static_cast<int>(category), 0);
58+
DCHECK_LT(static_cast<int>(category),
59+
static_cast<int>(DebugCategory::CATEGORY_COUNT));
60+
return enabled_[static_cast<int>(category)];
61+
}
62+
63+
// Uses NODE_DEBUG_NATIVE to initialize the categories. When env is not a
64+
// nullptr, the environment variables set in the Environment are used.
65+
// Otherwise the system environment variables are used.
66+
void Parse(Environment* env);
67+
68+
private:
69+
// Set all categories matching cats to the value of enabled.
70+
void Parse(const std::string& cats, bool enabled);
71+
void set_enabled(DebugCategory category, bool enabled) {
72+
DCHECK_GE(static_cast<int>(category), 0);
73+
DCHECK_LT(static_cast<int>(category),
74+
static_cast<int>(DebugCategory::CATEGORY_COUNT));
75+
enabled_[static_cast<int>(category)] = true;
76+
}
77+
78+
bool enabled_[static_cast<int>(DebugCategory::CATEGORY_COUNT)] = {false};
79+
};
80+
3981
template <typename... Args>
40-
inline void FORCE_INLINE Debug(Environment* env,
82+
inline void FORCE_INLINE Debug(EnabledDebugList* list,
4183
DebugCategory cat,
4284
const char* format,
43-
Args&&... args) {
44-
if (!UNLIKELY(env->debug_enabled(cat)))
45-
return;
46-
FPrintF(stderr, format, std::forward<Args>(args)...);
47-
}
85+
Args&&... args);
86+
87+
inline void FORCE_INLINE Debug(EnabledDebugList* list,
88+
DebugCategory cat,
89+
const char* message);
90+
91+
template <typename... Args>
92+
inline void FORCE_INLINE
93+
Debug(Environment* env, DebugCategory cat, const char* format, Args&&... args);
4894

4995
inline void FORCE_INLINE Debug(Environment* env,
5096
DebugCategory cat,
51-
const char* message) {
52-
if (!UNLIKELY(env->debug_enabled(cat)))
53-
return;
54-
FPrintF(stderr, "%s", message);
55-
}
97+
const char* message);
5698

5799
template <typename... Args>
58100
inline void Debug(Environment* env,
59101
DebugCategory cat,
60102
const std::string& format,
61-
Args&&... args) {
62-
Debug(env, cat, format.c_str(), std::forward<Args>(args)...);
63-
}
103+
Args&&... args);
64104

65105
// Used internally by the 'real' Debug(AsyncWrap*, ...) functions below, so that
66106
// the FORCE_INLINE flag on them doesn't apply to the contents of this function
@@ -72,31 +112,17 @@ inline void Debug(Environment* env,
72112
template <typename... Args>
73113
void COLD_NOINLINE UnconditionalAsyncWrapDebug(AsyncWrap* async_wrap,
74114
const char* format,
75-
Args&&... args) {
76-
Debug(async_wrap->env(),
77-
static_cast<DebugCategory>(async_wrap->provider_type()),
78-
async_wrap->diagnostic_name() + " " + format + "\n",
79-
std::forward<Args>(args)...);
80-
}
115+
Args&&... args);
81116

82117
template <typename... Args>
83118
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
84119
const char* format,
85-
Args&&... args) {
86-
DCHECK_NOT_NULL(async_wrap);
87-
DebugCategory cat =
88-
static_cast<DebugCategory>(async_wrap->provider_type());
89-
if (!UNLIKELY(async_wrap->env()->debug_enabled(cat)))
90-
return;
91-
UnconditionalAsyncWrapDebug(async_wrap, format, std::forward<Args>(args)...);
92-
}
120+
Args&&... args);
93121

94122
template <typename... Args>
95123
inline void FORCE_INLINE Debug(AsyncWrap* async_wrap,
96124
const std::string& format,
97-
Args&&... args) {
98-
Debug(async_wrap, format.c_str(), std::forward<Args>(args)...);
99-
}
125+
Args&&... args);
100126

101127
// Debug helper for inspecting the currently running `node` executable.
102128
class NativeSymbolDebuggingContext {

src/env-inl.h

-14
Original file line numberDiff line numberDiff line change
@@ -606,20 +606,6 @@ inline void Environment::set_http2_state(
606606
http2_state_ = std::move(buffer);
607607
}
608608

609-
bool Environment::debug_enabled(DebugCategory category) const {
610-
DCHECK_GE(static_cast<int>(category), 0);
611-
DCHECK_LT(static_cast<int>(category),
612-
static_cast<int>(DebugCategory::CATEGORY_COUNT));
613-
return debug_enabled_[static_cast<int>(category)];
614-
}
615-
616-
void Environment::set_debug_enabled(DebugCategory category, bool enabled) {
617-
DCHECK_GE(static_cast<int>(category), 0);
618-
DCHECK_LT(static_cast<int>(category),
619-
static_cast<int>(DebugCategory::CATEGORY_COUNT));
620-
debug_enabled_[static_cast<int>(category)] = enabled;
621-
}
622-
623609
inline AliasedFloat64Array* Environment::fs_stats_field_array() {
624610
return &fs_stats_field_array_;
625611
}

src/env.cc

+2-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "env.h"
22

33
#include "async_wrap.h"
4+
#include "debug_utils-inl.h"
45
#include "memory_tracker-inl.h"
56
#include "node_buffer.h"
67
#include "node_context_data.h"
@@ -315,6 +316,7 @@ Environment::Environment(IsolateData* isolate_data,
315316
Context::Scope context_scope(context);
316317

317318
set_env_vars(per_process::system_environment);
319+
enabled_debug_list_.Parse(this);
318320

319321
// We create new copies of the per-Environment option sets, so that it is
320322
// easier to modify them after Environment creation. The defaults are
@@ -375,10 +377,6 @@ Environment::Environment(IsolateData* isolate_data,
375377
// By default, always abort when --abort-on-uncaught-exception was passed.
376378
should_abort_on_uncaught_toggle_[0] = 1;
377379

378-
std::string debug_cats;
379-
credentials::SafeGetenv("NODE_DEBUG_NATIVE", &debug_cats, this);
380-
set_debug_categories(debug_cats, true);
381-
382380
if (options_->no_force_async_hooks_checks) {
383381
async_hooks_.no_force_checks();
384382
}
@@ -867,29 +865,6 @@ Local<Value> Environment::GetNow() {
867865
return Number::New(isolate(), static_cast<double>(now));
868866
}
869867

870-
void Environment::set_debug_categories(const std::string& cats, bool enabled) {
871-
std::string debug_categories = cats;
872-
while (!debug_categories.empty()) {
873-
std::string::size_type comma_pos = debug_categories.find(',');
874-
std::string wanted = ToLower(debug_categories.substr(0, comma_pos));
875-
876-
#define V(name) \
877-
{ \
878-
static const std::string available_category = ToLower(#name); \
879-
if (available_category.find(wanted) != std::string::npos) \
880-
set_debug_enabled(DebugCategory::name, enabled); \
881-
}
882-
883-
DEBUG_CATEGORY_NAMES(V)
884-
#undef V
885-
886-
if (comma_pos == std::string::npos)
887-
break;
888-
// Use everything after the `,` as the list for the next iteration.
889-
debug_categories = debug_categories.substr(comma_pos + 1);
890-
}
891-
}
892-
893868
void CollectExceptionInfo(Environment* env,
894869
Local<Object> obj,
895870
int errorno,

src/env.h

+4-20
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "inspector_agent.h"
3030
#include "inspector_profiler.h"
3131
#endif
32+
#include "debug_utils.h"
3233
#include "handle_wrap.h"
3334
#include "node.h"
3435
#include "node_binding.h"
@@ -550,20 +551,7 @@ struct ContextInfo {
550551
bool is_default = false;
551552
};
552553

553-
// Listing the AsyncWrap provider types first enables us to cast directly
554-
// from a provider type to a debug category.
555-
#define DEBUG_CATEGORY_NAMES(V) \
556-
NODE_ASYNC_PROVIDER_TYPES(V) \
557-
V(INSPECTOR_SERVER) \
558-
V(INSPECTOR_PROFILER) \
559-
V(WASI)
560-
561-
enum class DebugCategory {
562-
#define V(name) name,
563-
DEBUG_CATEGORY_NAMES(V)
564-
#undef V
565-
CATEGORY_COUNT
566-
};
554+
class EnabledDebugList;
567555

568556
// A unique-pointer-ish object that is compatible with the JS engine's
569557
// ArrayBuffer::Allocator.
@@ -1024,9 +1012,7 @@ class Environment : public MemoryRetainer {
10241012
inline http2::Http2State* http2_state() const;
10251013
inline void set_http2_state(std::unique_ptr<http2::Http2State> state);
10261014

1027-
inline bool debug_enabled(DebugCategory category) const;
1028-
inline void set_debug_enabled(DebugCategory category, bool enabled);
1029-
void set_debug_categories(const std::string& cats, bool enabled);
1015+
EnabledDebugList* enabled_debug_list() { return &enabled_debug_list_; }
10301016

10311017
inline AliasedFloat64Array* fs_stats_field_array();
10321018
inline AliasedBigUint64Array* fs_stats_field_bigint_array();
@@ -1382,9 +1368,7 @@ class Environment : public MemoryRetainer {
13821368
bool http_parser_buffer_in_use_ = false;
13831369
std::unique_ptr<http2::Http2State> http2_state_;
13841370

1385-
bool debug_enabled_[static_cast<int>(DebugCategory::CATEGORY_COUNT)] = {
1386-
false};
1387-
1371+
EnabledDebugList enabled_debug_list_;
13881372
AliasedFloat64Array fs_stats_field_array_;
13891373
AliasedBigUint64Array fs_stats_field_bigint_array_;
13901374

0 commit comments

Comments
 (0)