v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-call-stats.h
Go to the documentation of this file.
1// Copyright 2021 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
5#ifndef V8_LOGGING_RUNTIME_CALL_STATS_H_
6#define V8_LOGGING_RUNTIME_CALL_STATS_H_
7
8#include <optional>
9
10#include "src/base/macros.h"
11
12#ifdef V8_RUNTIME_CALL_STATS
13
21#include "src/runtime/runtime.h"
24
25#endif // V8_RUNTIME_CALL_STATS
26
27namespace v8 {
28namespace internal {
29
30#ifdef V8_RUNTIME_CALL_STATS
31
32class RuntimeCallCounter final {
33 public:
34 RuntimeCallCounter() : RuntimeCallCounter(nullptr) {}
35 explicit RuntimeCallCounter(const char* name)
36 : name_(name), count_(0), time_(0) {}
37 V8_NOINLINE void Reset();
38 V8_NOINLINE void Dump(v8::tracing::TracedValue* value);
39 void Add(RuntimeCallCounter* other);
40
41 const char* name() const { return name_; }
42 int64_t count() const { return count_; }
43 base::TimeDelta time() const {
44 return base::TimeDelta::FromMicroseconds(time_);
45 }
46 void Increment() { count_++; }
47 void Add(base::TimeDelta delta) { time_ += delta.InMicroseconds(); }
48
49 private:
50 friend class RuntimeCallStats;
51
52 const char* name_;
53 int64_t count_;
54 // Stored as int64_t so that its initialization can be deferred.
55 int64_t time_;
56};
57
58// RuntimeCallTimer is used to keep track of the stack of currently active
59// timers used for properly measuring the own time of a RuntimeCallCounter.
60class RuntimeCallTimer final {
61 public:
62 RuntimeCallCounter* counter() { return counter_; }
63 void set_counter(RuntimeCallCounter* counter) { counter_ = counter; }
64 RuntimeCallTimer* parent() const { return parent_.Value(); }
65 void set_parent(RuntimeCallTimer* timer) { parent_.SetValue(timer); }
66 const char* name() const { return counter_->name(); }
67
68 inline bool IsStarted() const { return start_ticks_ != base::TimeTicks(); }
69
70 inline void Start(RuntimeCallCounter* counter, RuntimeCallTimer* parent) {
71 DCHECK(!IsStarted());
72 counter_ = counter;
73 parent_.SetValue(parent);
74 if (TracingFlags::runtime_stats.load(std::memory_order_relaxed) ==
76 return;
77 }
78 base::TimeTicks now = RuntimeCallTimer::Now();
79 if (parent) parent->Pause(now);
80 Resume(now);
81 DCHECK(IsStarted());
82 }
83
84 void Snapshot();
85
86 inline RuntimeCallTimer* Stop() {
87 if (!IsStarted()) return parent();
88 base::TimeTicks now = RuntimeCallTimer::Now();
89 Pause(now);
90 counter_->Increment();
91 CommitTimeToCounter();
92
93 RuntimeCallTimer* parent_timer = parent();
94 if (parent_timer) {
95 parent_timer->Resume(now);
96 }
97 return parent_timer;
98 }
99
100 // Make the time source configurable for testing purposes.
101 V8_EXPORT_PRIVATE static base::TimeTicks (*Now)();
102
103 // Helper to switch over to CPU time.
104 static base::TimeTicks NowCPUTime();
105
106 private:
107 inline void Pause(base::TimeTicks now) {
108 DCHECK(IsStarted());
109 elapsed_ += (now - start_ticks_);
110 start_ticks_ = base::TimeTicks();
111 }
112
113 inline void Resume(base::TimeTicks now) {
114 DCHECK(!IsStarted());
115 start_ticks_ = now;
116 }
117
118 inline void CommitTimeToCounter() {
119 counter_->Add(elapsed_);
120 elapsed_ = base::TimeDelta();
121 }
122
123 RuntimeCallCounter* counter_ = nullptr;
124 base::AtomicValue<RuntimeCallTimer*> parent_;
125 base::TimeTicks start_ticks_;
126 base::TimeDelta elapsed_;
127};
128
129#define FOR_EACH_GC_COUNTER(V) \
130 TRACER_SCOPES(V) \
131 TRACER_BACKGROUND_SCOPES(V)
132
133#define FOR_EACH_API_COUNTER(V) \
134 V(AccessorPair_New) \
135 V(ArrayBuffer_Cast) \
136 V(ArrayBuffer_Detach) \
137 V(ArrayBuffer_MaybeNew) \
138 V(ArrayBuffer_New) \
139 V(ArrayBuffer_NewBackingStore) \
140 V(ArrayBuffer_BackingStore_Reallocate) \
141 V(Array_CloneElementAt) \
142 V(Array_Iterate) \
143 V(Array_New) \
144 V(BigInt64Array_New) \
145 V(BigInt_NewFromWords) \
146 V(BigIntObject_BigIntValue) \
147 V(BigIntObject_New) \
148 V(BigUint64Array_New) \
149 V(BooleanObject_BooleanValue) \
150 V(BooleanObject_New) \
151 V(Context_DeepFreeze) \
152 V(Context_New) \
153 V(Context_NewRemoteContext) \
154 V(DataView_New) \
155 V(Date_New) \
156 V(Date_Parse) \
157 V(Debug_Call) \
158 V(debug_GetPrivateMembers) \
159 V(DictionaryTemplate_New) \
160 V(DictionaryTemplate_NewInstance) \
161 V(Error_New) \
162 V(Exception_CaptureStackTrace) \
163 V(External_New) \
164 V(Float16Array_New) \
165 V(Float32Array_New) \
166 V(Float64Array_New) \
167 V(Function_Call) \
168 V(Function_New) \
169 V(Function_FunctionProtoToString) \
170 V(Function_NewInstance) \
171 V(FunctionTemplate_GetFunction) \
172 V(FunctionTemplate_New) \
173 V(FunctionTemplate_NewRemoteInstance) \
174 V(FunctionTemplate_NewWithCache) \
175 V(FunctionTemplate_NewWithFastHandler) \
176 V(Int16Array_New) \
177 V(Int32Array_New) \
178 V(Int8Array_New) \
179 V(Isolate_DateTimeConfigurationChangeNotification) \
180 V(Isolate_LocaleConfigurationChangeNotification) \
181 V(JSON_Parse) \
182 V(JSON_Stringify) \
183 V(Map_AsArray) \
184 V(Map_Clear) \
185 V(Map_Delete) \
186 V(Map_Get) \
187 V(Map_Has) \
188 V(Map_New) \
189 V(Map_Set) \
190 V(Message_GetEndColumn) \
191 V(Message_GetLineNumber) \
192 V(Message_GetSourceLine) \
193 V(Message_GetStartColumn) \
194 V(Module_Evaluate) \
195 V(Module_InstantiateModule) \
196 V(Module_SetSyntheticModuleExport) \
197 V(NumberObject_New) \
198 V(NumberObject_NumberValue) \
199 V(Object_CallAsConstructor) \
200 V(Object_CallAsFunction) \
201 V(Object_CreateDataProperty) \
202 V(Object_DefineOwnProperty) \
203 V(Object_DefineProperty) \
204 V(Object_Delete) \
205 V(Object_DeleteProperty) \
206 V(Object_ForceSet) \
207 V(Object_Get) \
208 V(Object_GetOwnPropertyDescriptor) \
209 V(Object_GetOwnPropertyNames) \
210 V(Object_GetPropertyAttributes) \
211 V(Object_GetPropertyNames) \
212 V(Object_GetRealNamedProperty) \
213 V(Object_GetRealNamedPropertyAttributes) \
214 V(Object_GetRealNamedPropertyAttributesInPrototypeChain) \
215 V(Object_GetRealNamedPropertyInPrototypeChain) \
216 V(Object_Has) \
217 V(Object_HasOwnProperty) \
218 V(Object_HasRealIndexedProperty) \
219 V(Object_HasRealNamedCallbackProperty) \
220 V(Object_HasRealNamedProperty) \
221 V(Object_IsCodeLike) \
222 V(Object_New) \
223 V(Object_ObjectProtoToString) \
224 V(Object_Set) \
225 V(Object_SetAccessor) \
226 V(Object_SetIntegrityLevel) \
227 V(Object_SetPrivate) \
228 V(Object_SetPrototype) \
229 V(ObjectTemplate_New) \
230 V(ObjectTemplate_NewInstance) \
231 V(Object_ToArrayIndex) \
232 V(Object_ToBigInt) \
233 V(Object_ToDetailString) \
234 V(Object_ToInt32) \
235 V(Object_ToInteger) \
236 V(Object_ToNumber) \
237 V(Object_ToNumeric) \
238 V(Object_ToObject) \
239 V(Object_ToPrimitive) \
240 V(Object_ToString) \
241 V(Object_ToUint32) \
242 V(Persistent_New) \
243 V(Private_New) \
244 V(Promise_Catch) \
245 V(Promise_Chain) \
246 V(Promise_HasRejectHandler) \
247 V(Promise_Resolver_New) \
248 V(Promise_Resolver_Reject) \
249 V(Promise_Resolver_Resolve) \
250 V(Promise_Result) \
251 V(Promise_Status) \
252 V(Promise_Then) \
253 V(Proxy_New) \
254 V(RangeError_New) \
255 V(ReferenceError_New) \
256 V(RegExp_Exec) \
257 V(RegExp_New) \
258 V(ScriptCompiler_Compile) \
259 V(ScriptCompiler_CompileFunction) \
260 V(ScriptCompiler_CompileUnbound) \
261 V(Script_Run) \
262 V(Set_Add) \
263 V(Set_AsArray) \
264 V(Set_Clear) \
265 V(Set_Delete) \
266 V(Set_Has) \
267 V(Set_New) \
268 V(SharedArrayBuffer_New) \
269 V(SharedArrayBuffer_NewBackingStore) \
270 V(String_Concat) \
271 V(String_NewExternalOneByte) \
272 V(String_NewExternalTwoByte) \
273 V(String_NewFromOneByte) \
274 V(String_NewFromTwoByte) \
275 V(String_NewFromUtf8) \
276 V(String_NewFromUtf8Literal) \
277 V(StringObject_New) \
278 V(StringObject_StringValue) \
279 V(String_Write) \
280 V(String_WriteUtf8) \
281 V(Symbol_New) \
282 V(SymbolObject_New) \
283 V(SymbolObject_SymbolValue) \
284 V(SyntaxError_New) \
285 V(TracedGlobal_New) \
286 V(TryCatch_StackTrace) \
287 V(TypeError_New) \
288 V(Uint16Array_New) \
289 V(Uint32Array_New) \
290 V(Uint8Array_New) \
291 V(Uint8ClampedArray_New) \
292 V(UnboundModuleScript_GetSourceMappingURL) \
293 V(UnboundModuleScript_GetSourceURL) \
294 V(UnboundScript_GetColumnNumber) \
295 V(UnboundScript_GetId) \
296 V(UnboundScript_GetLineNumber) \
297 V(UnboundScript_GetName) \
298 V(UnboundScript_GetSourceMappingURL) \
299 V(UnboundScript_GetSourceURL) \
300 V(ValueDeserializer_ReadHeader) \
301 V(ValueDeserializer_ReadValue) \
302 V(ValueSerializer_WriteValue) \
303 V(Value_Equals) \
304 V(Value_InstanceOf) \
305 V(Value_Int32Value) \
306 V(Value_IntegerValue) \
307 V(Value_NumberValue) \
308 V(Value_TypeOf) \
309 V(Value_Uint32Value) \
310 V(WasmCompileError_New) \
311 V(WasmLinkError_New) \
312 V(WasmSuspendError_New) \
313 V(WasmRuntimeError_New) \
314 V(WeakMap_Delete) \
315 V(WeakMap_Get) \
316 V(WeakMap_New) \
317 V(WeakMap_Set)
318
319#define ADD_THREAD_SPECIFIC_COUNTER(V, Prefix, Suffix) \
320 V(Prefix##Suffix) \
321 V(Prefix##Background##Suffix)
322
323#define FOR_EACH_THREAD_SPECIFIC_COUNTER(V) \
324 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Analyse) \
325 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Eval) \
326 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Function) \
327 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Ignition) \
328 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, IgnitionFinalization) \
329 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, RewriteReturnResult) \
330 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, ScopeAnalysis) \
331 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, Script) \
332 ADD_THREAD_SPECIFIC_COUNTER(V, Compile, CompileTask) \
333 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateFPRegisters) \
334 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateSimd128Registers) \
335 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AllocateGeneralRegisters) \
336 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssembleCode) \
337 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, AssignSpillSlots) \
338 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BitcastElision) \
339 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRangeBundles) \
340 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BuildLiveRanges) \
341 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, BytecodeGraphBuilder) \
342 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, CommitAssignment) \
343 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ConnectRanges) \
344 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, DecideSpillingMode) \
345 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, EarlyGraphTrimming) \
346 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, EarlyOptimization) \
347 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, EscapeAnalysis) \
348 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, FinalizeCode) \
349 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, FrameElision) \
350 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, GenericLowering) \
351 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, Inlining) \
352 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, JSWasmInlining) \
353 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, JSWasmLowering) \
354 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, JumpThreading) \
355 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, LoadElimination) \
356 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, LocateSpillSlots) \
357 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, LoopExitElimination) \
358 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, LoopPeeling) \
359 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PairingOptimization) \
360 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, MeetRegisterConstraints) \
361 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, MemoryOptimization) \
362 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, OptimizeMoves) \
363 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PopulateReferenceMaps) \
364 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PrintGraph) \
365 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, PrintTurboshaftGraph) \
366 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolveControlFlow) \
367 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ResolvePhis) \
368 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
369 ScheduledEffectControlLinearization) \
370 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, ScheduledMachineLowering) \
371 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, Scheduling) \
372 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, SelectInstructions) \
373 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, SimplifiedLowering) \
374 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, SimplifyLoops) \
375 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TraceScheduleAndVerify) \
376 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftBlockInstrumentation) \
377 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftBuildGraph) \
378 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
379 TurboshaftCodeEliminationAndSimplification) \
380 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftCsaBranchElimination) \
381 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmInJSInlining) \
382 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
383 TurboshaftCsaEarlyMachineOptimization) \
384 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftCsaLateEscapeAnalysis) \
385 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftCsaLoadElimination) \
386 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftCsaOptimize) \
387 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftDebugFeatureLowering) \
388 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
389 TurboshaftDecompressionOptimization) \
390 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftGrowableStacks) \
391 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftInstructionSelection) \
392 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftInt64Lowering) \
393 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftLateOptimization) \
394 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftLoopPeeling) \
395 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftLoopUnrolling) \
396 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftMachineLowering) \
397 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftMaglevGraphBuilding) \
398 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, \
399 TurboshaftSimplificationAndNormalization) \
400 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftOptimize) \
401 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftProfileApplication) \
402 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftSpecialRPOScheduling) \
403 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftStoreStoreElimination) \
404 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftTagUntagLowering) \
405 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftTypeAssertions) \
406 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftTypedOptimizations) \
407 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmDeadCodeElimination) \
408 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmGCOptimize) \
409 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmOptimize) \
410 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmDebugMemoryLowering) \
411 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmLowering) \
412 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmRevec) \
413 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TurboshaftWasmSimd) \
414 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TypeAssertions) \
415 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, TypedLowering) \
416 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, Typer) \
417 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, Untyper) \
418 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, VerifyGraph) \
419 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmBaseOptimization) \
420 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmGCLowering) \
421 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmGCOptimization) \
422 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmInlining) \
423 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmLoopPeeling) \
424 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmLoopUnrolling) \
425 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmOptimization) \
426 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmJSLowering) \
427 ADD_THREAD_SPECIFIC_COUNTER(V, Optimize, WasmTyping) \
428 \
429 ADD_THREAD_SPECIFIC_COUNTER(V, Parse, ArrowFunctionLiteral) \
430 ADD_THREAD_SPECIFIC_COUNTER(V, Parse, FunctionLiteral) \
431 ADD_THREAD_SPECIFIC_COUNTER(V, Parse, Program) \
432 ADD_THREAD_SPECIFIC_COUNTER(V, PreParse, ArrowFunctionLiteral) \
433 ADD_THREAD_SPECIFIC_COUNTER(V, PreParse, WithVariableResolution)
434
435#define FOR_EACH_MANUAL_COUNTER(V) \
436 V(AccessorGetterCallback) \
437 V(AccessorSetterCallback) \
438 V(ArrayLengthGetter) \
439 V(ArrayLengthSetter) \
440 V(BoundFunctionLengthGetter) \
441 V(BoundFunctionNameGetter) \
442 V(CodeGenerationFromStringsCallbacks) \
443 V(CompileBackgroundBaseline) \
444 V(CompileBackgroundBaselinePreVisit) \
445 V(CompileBackgroundBaselineVisit) \
446 V(CompileBackgroundBaselineBuild) \
447 V(CompileBaseline) \
448 V(CompileBaselineFinalization) \
449 V(CompileBaselinePreVisit) \
450 V(CompileBaselineVisit) \
451 V(CompileBaselineBuild) \
452 V(CompileCollectSourcePositions) \
453 V(CompileDeserialize) \
454 V(CompileEnqueueOnDispatcher) \
455 V(CompileFinalizeBackgroundCompileTask) \
456 V(CompileFinishNowOnDispatcher) \
457 V(CompileGetFromOptimizedCodeMap) \
458 V(CompilePublishBackgroundFinalization) \
459 V(CompileSerialize) \
460 V(CompileWaitForDispatcher) \
461 V(ConfigureInstance) \
462 V(CreateApiFunction) \
463 V(Debugger) \
464 V(DebuggerCallback) \
465 V(DeoptimizeCode) \
466 V(DeserializeContext) \
467 V(DeserializeIsolate) \
468 V(FinalizationRegistryCleanupFromTask) \
469 V(FunctionCallback) \
470 V(FunctionLengthGetter) \
471 V(FunctionPrototypeGetter) \
472 V(FunctionPrototypeSetter) \
473 V(GCEpilogueCallback) \
474 V(GCPrologueCallback) \
475 V(GC_Custom_AllAvailableGarbage) \
476 V(GC_Custom_IncrementalMarkingObserver) \
477 V(GC_Custom_SlowAllocateRaw) \
478 V(Genesis) \
479 V(GetCompatibleReceiver) \
480 V(GetMoreDataCallback) \
481 V(IndexedDefinerCallback) \
482 V(IndexedDeleterCallback) \
483 V(IndexedDescriptorCallback) \
484 V(IndexedEnumeratorCallback) \
485 V(IndexedGetterCallback) \
486 V(IndexedQueryCallback) \
487 V(IndexedSetterCallback) \
488 V(InstantiateFunction) \
489 V(InstantiateObject) \
490 V(Invoke) \
491 V(InvokeApiFunction) \
492 V(InvokeApiInterruptCallbacks) \
493 V(IsCompatibleReceiver) \
494 V(IsCompatibleReceiverMap) \
495 V(IsTemplateFor) \
496 V(JS_Execution) \
497 V(Map_SetPrototype) \
498 V(Map_TransitionToAccessorProperty) \
499 V(Map_TransitionToDataProperty) \
500 V(MessageListenerCallback) \
501 V(NamedDefinerCallback) \
502 V(NamedDeleterCallback) \
503 V(NamedDescriptorCallback) \
504 V(NamedEnumeratorCallback) \
505 V(NamedGetterCallback) \
506 V(NamedQueryCallback) \
507 V(NamedSetterCallback) \
508 V(ObjectVerify) \
509 V(Object_DeleteProperty) \
510 V(OptimizeBackgroundMaglev) \
511 V(OptimizeBackgroundTurbofan) \
512 V(OptimizeCode) \
513 V(OptimizeConcurrentFinalize) \
514 V(OptimizeConcurrentFinalizeMaglev) \
515 V(OptimizeConcurrentPrepare) \
516 V(OptimizeFinalizePipelineJob) \
517 V(OptimizeHeapBrokerInitialization) \
518 V(OptimizeNonConcurrent) \
519 V(OptimizeNonConcurrentMaglev) \
520 V(OptimizeRevectorizer) \
521 V(OptimizeSerialization) \
522 V(OptimizeSerializeMetadata) \
523 V(ParseEval) \
524 V(ParseFunction) \
525 V(PropertyCallback) \
526 V(PrototypeMap_TransitionToAccessorProperty) \
527 V(PrototypeMap_TransitionToDataProperty) \
528 V(PrototypeObject_DeleteProperty) \
529 V(ReconfigureToDataProperty) \
530 V(SnapshotDecompress) \
531 V(StringLengthGetter) \
532 V(TestCounter1) \
533 V(TestCounter2) \
534 V(TestCounter3) \
535 V(UpdateProtector) \
536 V(WrappedFunctionLengthGetter) \
537 V(WrappedFunctionNameGetter)
538
539#define FOR_EACH_HANDLER_COUNTER(V) \
540 V(KeyedLoadIC_KeyedLoadSloppyArgumentsStub) \
541 V(KeyedLoadIC_LoadElementDH) \
542 V(KeyedLoadIC_LoadIndexedInterceptorStub) \
543 V(KeyedLoadIC_LoadIndexedStringDH) \
544 V(KeyedLoadIC_SlowStub) \
545 V(KeyedStoreIC_ElementsTransitionAndStoreStub) \
546 V(KeyedStoreIC_KeyedStoreSloppyArgumentsStub) \
547 V(KeyedStoreIC_SlowStub) \
548 V(KeyedStoreIC_StoreElementStub) \
549 V(KeyedStoreIC_StoreFastElementStub) \
550 V(LoadGlobalIC_LoadScriptContextField) \
551 V(LoadGlobalIC_SlowStub) \
552 V(LoadIC_FunctionPrototypeStub) \
553 V(LoadIC_HandlerCacheHit_Accessor) \
554 V(LoadIC_LoadAccessorDH) \
555 V(LoadIC_LoadAccessorFromPrototypeDH) \
556 V(LoadIC_LoadApiGetterFromPrototypeDH) \
557 V(LoadIC_LoadCallback) \
558 V(LoadIC_LoadConstantDH) \
559 V(LoadIC_LoadConstantFromPrototypeDH) \
560 V(LoadIC_LoadFieldDH) \
561 V(LoadIC_LoadFieldFromPrototypeDH) \
562 V(LoadIC_LoadGlobalDH) \
563 V(LoadIC_LoadGlobalFromPrototypeDH) \
564 V(LoadIC_LoadIntegerIndexedExoticDH) \
565 V(LoadIC_LoadInterceptorDH) \
566 V(LoadIC_LoadInterceptorFromPrototypeDH) \
567 V(LoadIC_LoadNativeDataPropertyDH) \
568 V(LoadIC_LoadNativeDataPropertyFromPrototypeDH) \
569 V(LoadIC_LoadNonexistentDH) \
570 V(LoadIC_LoadNonMaskingInterceptorDH) \
571 V(LoadIC_LoadNormalDH) \
572 V(LoadIC_LoadNormalFromPrototypeDH) \
573 V(LoadIC_NonReceiver) \
574 V(LoadIC_SlowStub) \
575 V(LoadIC_StringLength) \
576 V(LoadIC_StringWrapperLength) \
577 V(StoreGlobalIC_SlowStub) \
578 V(StoreGlobalIC_StoreScriptContextField) \
579 V(StoreIC_HandlerCacheHit_Accessor) \
580 V(StoreIC_NonReceiver) \
581 V(StoreIC_SlowStub) \
582 V(StoreIC_StoreAccessorDH) \
583 V(StoreIC_StoreAccessorOnPrototypeDH) \
584 V(StoreIC_StoreApiSetterOnPrototypeDH) \
585 V(StoreIC_StoreFieldDH) \
586 V(StoreIC_StoreGlobalDH) \
587 V(StoreIC_StoreGlobalTransitionDH) \
588 V(StoreIC_StoreInterceptorStub) \
589 V(StoreIC_StoreNativeDataPropertyDH) \
590 V(StoreIC_StoreNativeDataPropertyOnPrototypeDH) \
591 V(StoreIC_StoreNormalDH) \
592 V(StoreIC_StoreTransitionDH) \
593 V(StoreInArrayLiteralIC_SlowStub)
594
595enum class RuntimeCallCounterId {
596#define CALL_RUNTIME_COUNTER(name) kGC_##name,
597 FOR_EACH_GC_COUNTER(CALL_RUNTIME_COUNTER)
598#undef CALL_RUNTIME_COUNTER
599#define CALL_RUNTIME_COUNTER(name) k##name,
600 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)
601#undef CALL_RUNTIME_COUNTER
602#define CALL_RUNTIME_COUNTER(name, nargs, ressize) kRuntime_##name,
603 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)
604#undef CALL_RUNTIME_COUNTER
605#define CALL_BUILTIN_COUNTER(name, Argc) kBuiltin_##name,
606 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)
607#undef CALL_BUILTIN_COUNTER
608#define CALL_BUILTIN_COUNTER(name) kAPI_##name,
609 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER)
610#undef CALL_BUILTIN_COUNTER
611#define CALL_BUILTIN_COUNTER(name) kHandler_##name,
612 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)
613#undef CALL_BUILTIN_COUNTER
614#define THREAD_SPECIFIC_COUNTER(name) k##name,
615 FOR_EACH_THREAD_SPECIFIC_COUNTER(
616 THREAD_SPECIFIC_COUNTER)
617#undef THREAD_SPECIFIC_COUNTER
618 kNumberOfCounters,
619};
620
621class RuntimeCallStats final {
622 public:
624
625 // If kExact is chosen the counter will be use as given. With kThreadSpecific,
626 // if the RuntimeCallStats was created for a worker thread, then the
627 // background specific version of the counter will be used instead.
628 enum CounterMode { kExact, kThreadSpecific };
629
630 explicit V8_EXPORT_PRIVATE RuntimeCallStats(ThreadType thread_type);
631
632 // Starting measuring the time for a function. This will establish the
633 // connection to the parent counter for properly calculating the own times.
634 V8_EXPORT_PRIVATE void Enter(RuntimeCallTimer* timer,
635 RuntimeCallCounterId counter_id);
636
637 // Leave a scope for a measured runtime function. This will properly add
638 // the time delta to the current_counter and subtract the delta from its
639 // parent.
640 V8_EXPORT_PRIVATE void Leave(RuntimeCallTimer* timer);
641
642 // Set counter id for the innermost measurement. It can be used to refine
643 // event kind when a runtime entry counter is too generic.
644 V8_EXPORT_PRIVATE void CorrectCurrentCounterId(
645 RuntimeCallCounterId counter_id, CounterMode mode = kExact);
646
647 V8_EXPORT_PRIVATE void Reset();
648 // Add all entries from another stats object.
649 void Add(RuntimeCallStats* other);
650 V8_EXPORT_PRIVATE void Print(std::ostream& os);
652 V8_NOINLINE void Dump(v8::tracing::TracedValue* value);
653
654 ThreadId thread_id() const { return thread_id_; }
655 RuntimeCallTimer* current_timer() { return current_timer_.Value(); }
656 RuntimeCallCounter* current_counter() { return current_counter_.Value(); }
657 bool InUse() { return in_use_; }
658 bool IsCalledOnTheSameThread();
659
660 V8_EXPORT_PRIVATE bool IsBackgroundThreadSpecificVariant(
661 RuntimeCallCounterId id);
662 V8_EXPORT_PRIVATE bool HasThreadSpecificCounterVariants(
663 RuntimeCallCounterId id);
664
665 // This should only be called for counters with a dual Background variant. If
666 // on the main thread, this just returns the counter. If on a worker thread,
667 // it returns Background variant of the counter.
668 RuntimeCallCounterId CounterIdForThread(RuntimeCallCounterId id) {
669 DCHECK(HasThreadSpecificCounterVariants(id));
670 // All thread specific counters are laid out with the main thread variant
671 // first followed by the background variant.
672 int idInt = static_cast<int>(id);
673 return thread_type_ == kWorkerThread
674 ? static_cast<RuntimeCallCounterId>(idInt + 1)
675 : id;
676 }
677
678 bool IsCounterAppropriateForThread(RuntimeCallCounterId id) {
679 // TODO(delphick): We should add background-only counters and ensure that
680 // all counters (not just the thread-specific variants) are only invoked on
681 // the correct thread.
682 if (!HasThreadSpecificCounterVariants(id)) return true;
683 return IsBackgroundThreadSpecificVariant(id) ==
684 (thread_type_ == kWorkerThread);
685 }
686
687 static const int kNumberOfCounters =
688 static_cast<int>(RuntimeCallCounterId::kNumberOfCounters);
689 RuntimeCallCounter* GetCounter(RuntimeCallCounterId counter_id) {
690 return &counters_[static_cast<int>(counter_id)];
691 }
692 RuntimeCallCounter* GetCounter(int counter_id) {
693 return &counters_[counter_id];
694 }
695
696 private:
697 // Top of a stack of active timers.
698 base::AtomicValue<RuntimeCallTimer*> current_timer_;
699 // Active counter object associated with current timer.
700 base::AtomicValue<RuntimeCallCounter*> current_counter_;
701 // Used to track nested tracing scopes.
702 bool in_use_;
703 ThreadType thread_type_;
704 ThreadId thread_id_;
705 RuntimeCallCounter counters_[kNumberOfCounters];
706};
707
708class WorkerThreadRuntimeCallStats final {
709 public:
710 WorkerThreadRuntimeCallStats();
711 ~WorkerThreadRuntimeCallStats();
712
713 // Returns the TLS key associated with this WorkerThreadRuntimeCallStats.
715
716 // Returns a new worker thread runtime call stats table managed by this
717 // WorkerThreadRuntimeCallStats.
718 RuntimeCallStats* NewTable();
719
720 // Adds the counters from the worker thread tables to |main_call_stats|.
721 void AddToMainTable(RuntimeCallStats* main_call_stats);
722
723 private:
724 base::Mutex mutex_;
725 std::vector<std::unique_ptr<RuntimeCallStats>> tables_;
726 std::optional<base::Thread::LocalStorageKey> tls_key_;
727 // Since this is for creating worker thread runtime-call stats, record the
728 // main thread ID to ensure we never create a worker RCS table for the main
729 // thread.
730 ThreadId isolate_thread_id_;
731};
732
733// Creating a WorkerThreadRuntimeCallStatsScope will provide a thread-local
734// runtime call stats table, and will dump the table to an immediate trace event
735// when it is destroyed.
736class V8_EXPORT_PRIVATE V8_NODISCARD WorkerThreadRuntimeCallStatsScope final {
737 public:
738 WorkerThreadRuntimeCallStatsScope() = default;
739 explicit WorkerThreadRuntimeCallStatsScope(
740 WorkerThreadRuntimeCallStats* off_thread_stats);
741 ~WorkerThreadRuntimeCallStatsScope();
742
743 WorkerThreadRuntimeCallStatsScope(WorkerThreadRuntimeCallStatsScope&&) =
744 delete;
745 WorkerThreadRuntimeCallStatsScope(const WorkerThreadRuntimeCallStatsScope&) =
746 delete;
747
748 RuntimeCallStats* Get() const { return table_; }
749
750 private:
751 RuntimeCallStats* table_ = nullptr;
752};
753
754#define CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats, counter_id) \
755 do { \
756 if (V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled()) && \
757 runtime_call_stats) { \
758 runtime_call_stats->CorrectCurrentCounterId(counter_id); \
759 } \
760 } while (false)
761
762#define TRACE_HANDLER_STATS(isolate, counter_name) \
763 CHANGE_CURRENT_RUNTIME_COUNTER( \
764 isolate->counters()->runtime_call_stats(), \
765 RuntimeCallCounterId::kHandler_##counter_name)
766
767// A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the
768// the time of C++ scope.
769class V8_NODISCARD RuntimeCallTimerScope {
770 public:
771 inline RuntimeCallTimerScope(Isolate* isolate,
772 RuntimeCallCounterId counter_id);
773 inline RuntimeCallTimerScope(LocalIsolate* isolate,
774 RuntimeCallCounterId counter_id,
775 RuntimeCallStats::CounterMode mode =
776 RuntimeCallStats::CounterMode::kExact);
777 inline RuntimeCallTimerScope(RuntimeCallStats* stats,
778 RuntimeCallCounterId counter_id,
779 RuntimeCallStats::CounterMode mode =
780 RuntimeCallStats::CounterMode::kExact) {
781 if (V8_LIKELY(!TracingFlags::is_runtime_stats_enabled() ||
782 stats == nullptr)) {
783 return;
784 }
785 stats_ = stats;
786 if (mode == RuntimeCallStats::CounterMode::kThreadSpecific) {
787 counter_id = stats->CounterIdForThread(counter_id);
788 }
789
790 DCHECK(stats->IsCounterAppropriateForThread(counter_id));
791 stats_->Enter(&timer_, counter_id);
792 }
793
794 inline ~RuntimeCallTimerScope() {
795 if (V8_UNLIKELY(stats_ != nullptr)) {
796 stats_->Leave(&timer_);
797 }
798 }
799
800 RuntimeCallTimerScope(const RuntimeCallTimerScope&) = delete;
801 RuntimeCallTimerScope& operator=(const RuntimeCallTimerScope&) = delete;
802
803 private:
804 RuntimeCallStats* stats_ = nullptr;
805 RuntimeCallTimer timer_;
806};
807
808#else // RUNTIME_CALL_STATS
809
810#define TRACE_HANDLER_STATS(...)
811#define CHANGE_CURRENT_RUNTIME_COUNTER(...)
812
813// Create dummy types to limit code changes
815
821
823 public:
826 RuntimeCallStats* Get() const { return nullptr; }
827};
828
829#endif // RUNTIME_CALL_STATS
830
831} // namespace internal
832} // namespace v8
833
834#endif // V8_LOGGING_RUNTIME_CALL_STATS_H_
#define BUILTIN_LIST_C(V)
const char * name
Definition builtins.cc:39
int32_t LocalStorageKey
Definition platform.h:541
V8_EXPORT_PRIVATE RuntimeCallStats(ThreadType thread_type)
WorkerThreadRuntimeCallStatsScope(WorkerThreadRuntimeCallStats *off_thread_stats)
base::Mutex & mutex_
size_t count_
Definition sweeper.cc:55
uint32_t count
TimeRecord time
const char * name_
base::ElapsedTimer timer_
Counters * counters_
void Add(RWDigits Z, Digits X, Digits Y)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
void Print(Tagged< Object > obj)
Definition objects.h:774
SourcePositionTable *const table_
Definition pipeline.cc:227
BytecodeSequenceNode * parent_
#define FOR_EACH_INTRINSIC(F)
Definition runtime.h:884
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660
#define V8_NOINLINE
Definition v8config.h:586
#define V8_NODISCARD
Definition v8config.h:693