v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
etw-isolate-load-script-data-win.cc
Go to the documentation of this file.
1// Copyright 2024 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
6
7#include <windows.h>
8
9#include <iostream>
10#include <memory>
11#include <string>
12#include <unordered_map>
13#include <unordered_set>
14#include <utility>
15
17#include "include/v8-isolate.h"
20#include "include/v8-script.h"
21#include "src/api/api-inl.h"
23#include "src/base/logging.h"
30#include "src/logging/log.h"
34
35namespace v8 {
36namespace internal {
37namespace ETWJITInterface {
38
40
45 isolate_ = rhs.isolate_;
46 loaded_scripts_ids_ = std::move(rhs.loaded_scripts_ids_);
47 event_id_ = rhs.event_id_.load();
48}
49
50// static
53 isolate_map.Pointer()->emplace(isolate, IsolateLoadScriptData(isolate));
54}
55
56// static
59 isolate_map.Pointer()->erase(isolate);
60}
61
62// static
64 uint32_t options) {
65 ETWTRACEDBG << "UpdateAllIsolates with etw_enabled==" << etw_enabled
66 << " and options==" << options << " acquiring mutex" << std::endl;
68 ETWTRACEDBG << "UpdateAllIsolates Isolate count=="
69 << isolate_map.Pointer()->size() << std::endl;
70 auto monitor = std::make_shared<EtwIsolateCaptureStateMonitor>(
71 isolates_mutex.Pointer(), isolate_map.Pointer()->size());
72 bool capture_state =
74 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor = monitor;
75 std::for_each(
76 isolate_map.Pointer()->begin(), isolate_map.Pointer()->end(),
77 [etw_enabled, weak_monitor, options](auto& pair) {
78 auto& isolate_data = pair.second;
79 if (etw_enabled) {
80 ETWTRACEDBG << "UpdateAllIsolates enqueing enablelog" << std::endl;
81 isolate_data.EnqueueEnableLog(weak_monitor, options);
82 } else {
83 ETWTRACEDBG << "UpdateAllIsolates enqueing disablelog" << std::endl;
84 isolate_data.EnqueueDisableLog();
85 }
86 });
87
88 if (!capture_state) {
89 return;
90 }
91
92 ETWTRACEDBG << "UpdateAllIsolates starting WaitFor" << std::endl;
93 bool timeout = !monitor->WaitFor(kCaptureStateTimeout);
94 ETWTRACEDBG << "UpdateAllIsolates WaitFor "
95 << (timeout ? "timeout" : "completed") << std::endl;
96}
97
98// static
99bool IsolateLoadScriptData::MaybeAddLoadedScript(Isolate* isolate,
100 int script_id) {
102 auto& data = GetData(isolate);
103 if (data.IsScriptLoaded(script_id)) {
104 return false;
105 }
106 data.AddLoadedScript(script_id);
107 return true;
108}
109
110// static
111void IsolateLoadScriptData::EnableLog(
112 Isolate* isolate, size_t event_id,
113 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor,
114 uint32_t options) {
115 {
116 ETWTRACEDBG << "EnableLog called with event_id==" << event_id
117 << " and options==" << options << " taking mutex" << std::endl;
119 auto& data = GetData(isolate);
120 if (event_id > 0 && data.CurrentEventId() != event_id) {
121 // This interrupt was canceled by a newer interrupt.
122 return;
123 }
124
125 // Cause all SourceLoad events to be re-emitted.
126 if (options & kJitCodeEventEnumExisting) {
127 data.RemoveAllLoadedScripts();
128 }
129 }
130
131 ETWTRACEDBG << "Mutex released with event_id==" << event_id << std::endl;
132
133 // This cannot be done while isolate_mutex is locked, as it can call
134 // EventHandler while in the call for all the existing code.
135 EtwIsolateOperations::Instance()->SetEtwCodeEventHandler(isolate, options);
136 isolate->SetETWTracingEnabled(true);
137
138 // Notify waiting thread if a monitor was provided.
139 if (auto monitor = weak_monitor.lock()) {
140 ETWTRACEDBG << "monitor->Notify with event_id==" << event_id << std::endl;
141 monitor->Notify();
142 }
143}
144
145// static
146void IsolateLoadScriptData::EnableLogWithFilterDataOnAllIsolates(
147 const uint8_t* data, size_t size, uint32_t options) {
149
150 std::string etw_filter_payload;
151 etw_filter_payload.assign(data, data + size);
152 auto monitor = std::make_shared<EtwIsolateCaptureStateMonitor>(
153 isolates_mutex.Pointer(), isolate_map.Pointer()->size());
154 bool capture_state =
156 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor = monitor;
157 std::for_each(isolate_map.Pointer()->begin(), isolate_map.Pointer()->end(),
158 [&etw_filter_payload, weak_monitor, options](auto& pair) {
159 auto& isolate_data = pair.second;
160 isolate_data.EnqueueEnableLogWithFilterData(
161 etw_filter_payload, weak_monitor, options);
162 });
163
164 if (!capture_state) {
165 return;
166 }
167
168 bool timeout = !monitor->WaitFor(kCaptureStateTimeout);
169 ETWTRACEDBG << "EnableLogWithFilterDataOnAllIsolates WaitFor "
170 << (timeout ? "timeout" : "completed") << std::endl;
171}
172
173// static
174void IsolateLoadScriptData::DisableLog(Isolate* isolate, size_t event_id) {
175 {
177 auto& data = GetData(isolate);
178 if (event_id > 0 && data.CurrentEventId() != event_id) {
179 // This interrupt was canceled by a newer interrupt.
180 return;
181 }
182 data.RemoveAllLoadedScripts();
183 }
184 EtwIsolateOperations::Instance()->ResetEtwCodeEventHandler(isolate);
185 isolate->SetETWTracingEnabled(false);
186}
187
188// static
189void IsolateLoadScriptData::EnableLogWithFilterData(
190 Isolate* isolate, size_t event_id, const std::string& etw_filter_payload,
191 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor,
192 uint32_t options) {
193 bool filter_did_match = false;
194 DCHECK(!etw_filter_payload.empty());
195
196 {
197 ETWTRACEDBG << "EnableLogWithFilterData called with event_id==" << event_id
198 << " and options==" << options << " taking mutex" << std::endl;
200
201 auto& data = GetData(isolate);
202 if (event_id > 0 && data.CurrentEventId() != event_id) {
203 // This interrupt was canceled by a newer interrupt.
204 return;
205 }
206
207 FilterETWSessionByURLResult filter_etw_session_by_url_result =
208 EtwIsolateOperations::Instance()->RunFilterETWSessionByURLCallback(
209 isolate, etw_filter_payload);
210 filter_did_match = filter_etw_session_by_url_result.enable_etw_tracing;
211 if (filter_did_match) {
212 if (filter_etw_session_by_url_result.trace_interpreter_frames) {
213 isolate->set_etw_trace_interpreted_frames();
214 }
215
216 // Cause all SourceLoad events to be re-emitted.
217 if (options & kJitCodeEventEnumExisting) {
218 data.RemoveAllLoadedScripts();
219 }
220 }
221 }
222
223 if (filter_did_match) {
224 ETWTRACEDBG << "Filter was matched with event_id==" << event_id
225 << std::endl;
226 EtwIsolateOperations::Instance()->SetEtwCodeEventHandler(isolate, options);
227 isolate->SetETWTracingEnabled(true);
228 }
229
230 // Notify waiting thread if a monitor was provided.
231 if (auto monitor = weak_monitor.lock()) {
232 ETWTRACEDBG << "monitor->Notify with event_id==" << event_id << std::endl;
233 monitor->Notify();
234 }
235}
236
237// static
238IsolateLoadScriptData& IsolateLoadScriptData::GetData(Isolate* isolate) {
239 return isolate_map.Pointer()->at(isolate);
240}
241
242void IsolateLoadScriptData::EnqueueEnableLog(
243 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor,
244 uint32_t options) {
245 size_t event_id = event_id_.fetch_add(1);
246 EtwIsolateOperations::Instance()->RequestInterrupt(
247 isolate_,
248 // Executed in the isolate thread.
249 [](v8::Isolate* v8_isolate, void* data) {
250 std::unique_ptr<EnableInterruptData> interrupt_data(
251 reinterpret_cast<EnableInterruptData*>(data));
252 size_t event_id = interrupt_data->event_id;
253 auto weak_monitor = interrupt_data->weak_monitor;
254 uint32_t options = interrupt_data->options;
255 EnableLog(reinterpret_cast<Isolate*>(v8_isolate), event_id,
256 weak_monitor, options);
257 },
258 new EnableInterruptData{event_id + 1, weak_monitor, options});
259}
260
261void IsolateLoadScriptData::EnqueueDisableLog() {
262 size_t event_id = event_id_.fetch_add(1);
263 EtwIsolateOperations::Instance()->RequestInterrupt(
264 isolate_,
265 // Executed in the isolate thread.
266 [](v8::Isolate* v8_isolate, void* data) {
267 DisableLog(reinterpret_cast<Isolate*>(v8_isolate),
268 reinterpret_cast<size_t>(data));
269 },
270 reinterpret_cast<void*>(event_id + 1));
271}
272
273void IsolateLoadScriptData::EnqueueEnableLogWithFilterData(
274 const std::string& etw_filter_payload,
275 std::weak_ptr<EtwIsolateCaptureStateMonitor> weak_monitor,
276 uint32_t options) {
277 size_t event_id = event_id_.fetch_add(1);
278 EtwIsolateOperations::Instance()->RequestInterrupt(
279 isolate_,
280 // Executed in the isolate thread.
281 [](v8::Isolate* v8_isolate, void* data) {
282 std::unique_ptr<EnableWithFilterDataInterruptData> interrupt_data(
283 reinterpret_cast<EnableWithFilterDataInterruptData*>(data));
284 size_t event_id = interrupt_data->event_id;
285 std::string etw_filter_payload = interrupt_data->payload;
286 auto weak_monitor = interrupt_data->weak_monitor;
287 uint32_t options = interrupt_data->options;
288 EnableLogWithFilterData(reinterpret_cast<Isolate*>(v8_isolate),
289 event_id, etw_filter_payload, weak_monitor,
290 options);
291 },
292 new EnableWithFilterDataInterruptData{event_id + 1, etw_filter_payload,
293 weak_monitor, options});
294}
295
296bool IsolateLoadScriptData::IsScriptLoaded(int script_id) const {
297 return loaded_scripts_ids_.find(script_id) != loaded_scripts_ids_.end();
298}
299void IsolateLoadScriptData::AddLoadedScript(int script_id) {
300 loaded_scripts_ids_.insert(script_id);
301}
302void IsolateLoadScriptData::RemoveAllLoadedScripts() {
303 loaded_scripts_ids_.clear();
304}
305
306size_t IsolateLoadScriptData::CurrentEventId() const {
307 return event_id_.load();
308}
309
315
316} // namespace ETWJITInterface
317} // namespace internal
318} // namespace v8
Isolate * isolate_
static constexpr TimeDelta FromSeconds(int64_t seconds)
Definition time.h:81
static void UpdateAllIsolates(bool etw_enabled, uint32_t options)
#define ETWTRACEDBG
#define LAZY_INSTANCE_INITIALIZER
#define LAZY_MUTEX_INITIALIZER
Definition mutex.h:105
base::LazyInstance< IsolateMapType >::type isolate_map
base::LazyInstance< FilterDataType >::type etw_filter_payload_glob
@ kJitCodeEventEnumExisting
#define V8_NOEXCEPT
#define DCHECK(condition)
Definition logging.h:482
typename LazyStaticInstance< T, CreateTrait, InitOnceTrait, DestroyTrait >::type type