GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_v8_platform-inl.h Lines: 66 68 97.1 %
Date: 2022-12-31 04:22:30 Branches: 17 28 60.7 %

Line Branch Exec Source
1
#ifndef SRC_NODE_V8_PLATFORM_INL_H_
2
#define SRC_NODE_V8_PLATFORM_INL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include <memory>
7
8
#include "env-inl.h"
9
#include "node.h"
10
#include "node_metadata.h"
11
#include "node_platform.h"
12
#include "node_options.h"
13
#include "tracing/node_trace_writer.h"
14
#include "tracing/trace_event.h"
15
#include "tracing/traced_value.h"
16
#include "util.h"
17
18
namespace node {
19
20
// Ensures that __metadata trace events are only emitted
21
// when tracing is enabled.
22
class NodeTraceStateObserver
23
    : public v8::TracingController::TraceStateObserver {
24
 public:
25
90
  inline void OnTraceEnabled() override {
26
180
    std::string title = GetProcessTitle("");
27
90
    if (!title.empty()) {
28
      // Only emit the metadata event if the title can be retrieved
29
      // successfully. Ignore it otherwise.
30

270
      TRACE_EVENT_METADATA1(
31
          "__metadata", "process_name", "name", TRACE_STR_COPY(title.c_str()));
32
    }
33

270
    TRACE_EVENT_METADATA1("__metadata",
34
                          "version",
35
                          "node",
36
                          per_process::metadata.versions.node.c_str());
37

270
    TRACE_EVENT_METADATA1(
38
        "__metadata", "thread_name", "name", "JavaScriptMainThread");
39
40
180
    auto trace_process = tracing::TracedValue::Create();
41
90
    trace_process->BeginDictionary("versions");
42
43
#define V(key)                                                                 \
44
  trace_process->SetString(#key, per_process::metadata.versions.key.c_str());
45
46
90
    NODE_VERSIONS_KEYS(V)
47
#undef V
48
49
90
    trace_process->EndDictionary();
50
51
90
    trace_process->SetString("arch", per_process::metadata.arch.c_str());
52
90
    trace_process->SetString("platform",
53
                             per_process::metadata.platform.c_str());
54
55
90
    trace_process->BeginDictionary("release");
56
90
    trace_process->SetString("name",
57
                             per_process::metadata.release.name.c_str());
58
#if NODE_VERSION_IS_LTS
59
    trace_process->SetString("lts", per_process::metadata.release.lts.c_str());
60
#endif
61
90
    trace_process->EndDictionary();
62

270
    TRACE_EVENT_METADATA1(
63
        "__metadata", "node", "process", std::move(trace_process));
64
65
    // This only runs the first time tracing is enabled
66
90
    controller_->RemoveTraceStateObserver(this);
67
90
  }
68
69
  inline void OnTraceDisabled() override {
70
    // Do nothing here. This should never be called because the
71
    // observer removes itself when OnTraceEnabled() is called.
72
    UNREACHABLE();
73
  }
74
75
5724
  explicit NodeTraceStateObserver(v8::TracingController* controller)
76
5724
      : controller_(controller) {}
77
22896
  ~NodeTraceStateObserver() override = default;
78
79
 private:
80
  v8::TracingController* controller_;
81
};
82
83
struct V8Platform {
84
  bool initialized_ = false;
85
86
#if NODE_USE_V8_PLATFORM
87
5724
  inline void Initialize(int thread_pool_size) {
88
5724
    CHECK(!initialized_);
89
5724
    initialized_ = true;
90
5724
    tracing_agent_ = std::make_unique<tracing::Agent>();
91
5724
    node::tracing::TraceEventHelper::SetAgent(tracing_agent_.get());
92
    node::tracing::TracingController* controller =
93
5724
        tracing_agent_->GetTracingController();
94
    trace_state_observer_ =
95
5724
        std::make_unique<NodeTraceStateObserver>(controller);
96
5724
    controller->AddTraceStateObserver(trace_state_observer_.get());
97
5724
    tracing_file_writer_ = tracing_agent_->DefaultHandle();
98
    // Only start the tracing agent if we enabled any tracing categories.
99
5724
    if (!per_process::cli_options->trace_event_categories.empty()) {
100
86
      StartTracingAgent();
101
    }
102
    // Tracing must be initialized before platform threads are created.
103
5724
    platform_ = new NodePlatform(thread_pool_size, controller);
104
5724
    v8::V8::InitializePlatform(platform_);
105
5724
  }
106
  // Make sure V8Platform don not call into Libuv threadpool,
107
  // see DefaultProcessExitHandlerInternal in environment.cc
108
5717
  inline void Dispose() {
109
5717
    if (!initialized_)
110
2
      return;
111
5715
    initialized_ = false;
112
5715
    node::tracing::TraceEventHelper::SetAgent(nullptr);
113
5715
    StopTracingAgent();
114
5715
    platform_->Shutdown();
115
5715
    delete platform_;
116
5715
    platform_ = nullptr;
117
    // Destroy tracing after the platform (and platform threads) have been
118
    // stopped.
119
5715
    tracing_agent_.reset(nullptr);
120
    // The observer remove itself in OnTraceEnabled
121
5715
    trace_state_observer_.reset(nullptr);
122
  }
123
124
  inline void DrainVMTasks(v8::Isolate* isolate) {
125
    platform_->DrainTasks(isolate);
126
  }
127
128
106
  inline void StartTracingAgent() {
129
    // Attach a new NodeTraceWriter only if this function hasn't been called
130
    // before.
131
106
    if (tracing_file_writer_.IsDefaultHandle()) {
132
      std::vector<std::string> categories =
133
88
          SplitString(per_process::cli_options->trace_event_categories, ',');
134
135
264
      tracing_file_writer_ = tracing_agent_->AddClient(
136
176
          std::set<std::string>(std::make_move_iterator(categories.begin()),
137
                                std::make_move_iterator(categories.end())),
138
176
          std::unique_ptr<tracing::AsyncTraceWriter>(
139
              new tracing::NodeTraceWriter(
140
88
                  per_process::cli_options->trace_event_file_pattern)),
141
88
          tracing::Agent::kUseDefaultCategories);
142
    }
143
106
  }
144
145
5715
  inline void StopTracingAgent() { tracing_file_writer_.reset(); }
146
147
12521
  inline tracing::AgentWriterHandle* GetTracingAgentWriter() {
148
12521
    return &tracing_file_writer_;
149
  }
150
151
11460
  inline NodePlatform* Platform() { return platform_; }
152
153
  std::unique_ptr<NodeTraceStateObserver> trace_state_observer_;
154
  std::unique_ptr<tracing::Agent> tracing_agent_;
155
  tracing::AgentWriterHandle tracing_file_writer_;
156
  NodePlatform* platform_;
157
#else   // !NODE_USE_V8_PLATFORM
158
  inline void Initialize(int thread_pool_size) {}
159
  inline void Dispose() {}
160
  inline void DrainVMTasks(v8::Isolate* isolate) {}
161
  inline void StartTracingAgent() {
162
    if (!per_process::cli_options->trace_event_categories.empty()) {
163
      fprintf(stderr,
164
              "Node compiled with NODE_USE_V8_PLATFORM=0, "
165
              "so event tracing is not available.\n");
166
    }
167
  }
168
  inline void StopTracingAgent() {}
169
170
  inline tracing::AgentWriterHandle* GetTracingAgentWriter() { return nullptr; }
171
172
  inline NodePlatform* Platform() { return nullptr; }
173
#endif  // !NODE_USE_V8_PLATFORM
174
};
175
176
namespace per_process {
177
extern struct V8Platform v8_platform;
178
}
179
180
20
inline void StartTracingAgent() {
181
20
  return per_process::v8_platform.StartTracingAgent();
182
}
183
184
12521
inline tracing::AgentWriterHandle* GetTracingAgentWriter() {
185
12521
  return per_process::v8_platform.GetTracingAgentWriter();
186
}
187
188
605
inline void DisposePlatform() {
189
605
  per_process::v8_platform.Dispose();
190
605
}
191
192
}  // namespace node
193
194
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
195
196
#endif  // SRC_NODE_V8_PLATFORM_INL_H_