OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef SRC_TRACING_TRACE_EVENT_H_ | 5 #ifndef SRC_TRACING_TRACE_EVENT_H_ |
6 #define SRC_TRACING_TRACE_EVENT_H_ | 6 #define SRC_TRACING_TRACE_EVENT_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include "base/trace_event/common/trace_event_common.h" | 10 #include "base/trace_event/common/trace_event_common.h" |
11 #include "include/v8-platform.h" | 11 #include "include/v8-platform.h" |
12 #include "src/base/atomicops.h" | 12 #include "src/base/atomicops.h" |
13 #include "src/base/macros.h" | 13 #include "src/base/macros.h" |
14 #include "src/counters.h" | |
15 | 14 |
16 // This header file defines implementation details of how the trace macros in | 15 // This header file defines implementation details of how the trace macros in |
17 // trace_event_common.h collect and store trace events. Anything not | 16 // trace_event_common.h collect and store trace events. Anything not |
18 // implementation-specific should go in trace_macros_common.h instead of here. | 17 // implementation-specific should go in trace_macros_common.h instead of here. |
19 | 18 |
20 | 19 |
21 // The pointer returned from GetCategoryGroupEnabled() points to a | 20 // The pointer returned from GetCategoryGroupEnabled() points to a |
22 // value with zero or more of the following bits. Used in this class only. | 21 // value with zero or more of the following bits. Used in this class only. |
23 // The TRACE_EVENT macros should only use the value as a bool. | 22 // The TRACE_EVENT macros should only use the value as a bool. |
24 // These values must be in sync with macro values in trace_log.h in | 23 // These values must be in sync with macro values in trace_log.h in |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 }; \ | 281 }; \ |
283 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | 282 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ |
284 INTERNAL_TRACE_EVENT_UID(scoped_context)(context.raw_id()); | 283 INTERNAL_TRACE_EVENT_UID(scoped_context)(context.raw_id()); |
285 | 284 |
286 #define TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED() \ | 285 #define TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED() \ |
287 base::NoBarrier_Load(&v8::internal::tracing::kRuntimeCallStatsTracingEnabled) | 286 base::NoBarrier_Load(&v8::internal::tracing::kRuntimeCallStatsTracingEnabled) |
288 | 287 |
289 #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \ | 288 #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \ |
290 INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) | 289 INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) |
291 | 290 |
292 #define TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED(isolate, counter_id) \ | |
293 INTERNAL_TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED(isolate, counter_id) | |
294 | |
295 #define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \ | 291 #define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \ |
296 { \ | 292 { \ |
297 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO( \ | 293 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO( \ |
298 TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats")); \ | 294 TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats")); \ |
299 base::NoBarrier_Store( \ | 295 base::NoBarrier_Store( \ |
300 &v8::internal::tracing::kRuntimeCallStatsTracingEnabled, \ | 296 &v8::internal::tracing::kRuntimeCallStatsTracingEnabled, \ |
301 INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()); \ | 297 INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()); \ |
302 } \ | 298 } \ |
303 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ | 299 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ |
304 v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \ | 300 v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \ |
305 tracer); \ | 301 tracer); \ |
306 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ | 302 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ |
307 INTERNAL_TRACE_EVENT_UID(tracer) \ | 303 INTERNAL_TRACE_EVENT_UID(tracer) \ |
308 .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ | 304 .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ |
309 name); \ | 305 name); \ |
310 } | 306 } |
311 | 307 |
312 #define INTERNAL_TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED(isolate, \ | |
313 counter_id) \ | |
314 v8::internal::tracing::CounterScope INTERNAL_TRACE_EVENT_UID(scope)( \ | |
315 isolate, counter_id); | |
316 | |
317 namespace v8 { | 308 namespace v8 { |
318 namespace internal { | 309 namespace internal { |
| 310 |
| 311 class Isolate; |
| 312 |
319 namespace tracing { | 313 namespace tracing { |
320 | 314 |
321 // Specify these values when the corresponding argument of AddTraceEvent is not | 315 // Specify these values when the corresponding argument of AddTraceEvent is not |
322 // used. | 316 // used. |
323 const int kZeroNumArgs = 0; | 317 const int kZeroNumArgs = 0; |
324 const decltype(nullptr) kGlobalScope = nullptr; | 318 const decltype(nullptr) kGlobalScope = nullptr; |
325 const uint64_t kNoId = 0; | 319 const uint64_t kNoId = 0; |
326 | 320 |
327 extern base::Atomic32 kRuntimeCallStatsTracingEnabled; | 321 extern base::Atomic32 kRuntimeCallStatsTracingEnabled; |
328 | 322 |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 // Do not use directly. | 621 // Do not use directly. |
628 class CallStatsScopedTracer { | 622 class CallStatsScopedTracer { |
629 public: | 623 public: |
630 CallStatsScopedTracer() : p_data_(nullptr) {} | 624 CallStatsScopedTracer() : p_data_(nullptr) {} |
631 ~CallStatsScopedTracer() { | 625 ~CallStatsScopedTracer() { |
632 if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) { | 626 if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) { |
633 AddEndTraceEvent(); | 627 AddEndTraceEvent(); |
634 } | 628 } |
635 } | 629 } |
636 | 630 |
637 void Initialize(Isolate* isolate, const uint8_t* category_group_enabled, | 631 void Initialize(v8::internal::Isolate* isolate, |
638 const char* name); | 632 const uint8_t* category_group_enabled, const char* name); |
639 | 633 |
640 private: | 634 private: |
641 void AddEndTraceEvent(); | 635 void AddEndTraceEvent(); |
642 struct Data { | 636 struct Data { |
643 const uint8_t* category_group_enabled; | 637 const uint8_t* category_group_enabled; |
644 const char* name; | 638 const char* name; |
645 Isolate* isolate; | 639 v8::internal::Isolate* isolate; |
646 }; | 640 }; |
647 bool has_parent_scope_; | 641 bool has_parent_scope_; |
648 Data* p_data_; | 642 Data* p_data_; |
649 Data data_; | 643 Data data_; |
650 }; | 644 }; |
651 | 645 |
652 // TraceEventCallStatsTimer is used to keep track of the stack of currently | |
653 // active timers used for properly measuring the own time of a | |
654 // RuntimeCallCounter. | |
655 class TraceEventCallStatsTimer { | |
656 public: | |
657 TraceEventCallStatsTimer() : counter_(nullptr), parent_(nullptr) {} | |
658 RuntimeCallCounter* counter() { return counter_; } | |
659 base::ElapsedTimer timer() { return timer_; } | |
660 | |
661 private: | |
662 friend class TraceEventStatsTable; | |
663 | |
664 V8_INLINE void Start(RuntimeCallCounter* counter, | |
665 TraceEventCallStatsTimer* parent) { | |
666 counter_ = counter; | |
667 parent_ = parent; | |
668 timer_.Start(); | |
669 } | |
670 | |
671 V8_INLINE TraceEventCallStatsTimer* Stop() { | |
672 base::TimeDelta delta = timer_.Elapsed(); | |
673 timer_.Stop(); | |
674 counter_->count++; | |
675 counter_->time += delta; | |
676 if (parent_ != nullptr) { | |
677 // Adjust parent timer so that it does not include sub timer's time. | |
678 parent_->counter_->time -= delta; | |
679 } | |
680 return parent_; | |
681 } | |
682 | |
683 RuntimeCallCounter* counter_; | |
684 TraceEventCallStatsTimer* parent_; | |
685 base::ElapsedTimer timer_; | |
686 }; | |
687 | |
688 class TraceEventStatsTable { | |
689 public: | |
690 typedef RuntimeCallCounter TraceEventStatsTable::*CounterId; | |
691 | |
692 #define CALL_RUNTIME_COUNTER(name) \ | |
693 RuntimeCallCounter name = RuntimeCallCounter(#name); | |
694 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) | |
695 #undef CALL_RUNTIME_COUNTER | |
696 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ | |
697 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); | |
698 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) | |
699 #undef CALL_RUNTIME_COUNTER | |
700 #define CALL_BUILTIN_COUNTER(name) \ | |
701 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); | |
702 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) | |
703 #undef CALL_BUILTIN_COUNTER | |
704 #define CALL_BUILTIN_COUNTER(name) \ | |
705 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); | |
706 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) | |
707 #undef CALL_BUILTIN_COUNTER | |
708 #define CALL_BUILTIN_COUNTER(name) \ | |
709 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); | |
710 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) | |
711 #undef CALL_BUILTIN_COUNTER | |
712 | |
713 // Starting measuring the time for a function. This will establish the | |
714 // connection to the parent counter for properly calculating the own times. | |
715 static void Enter(Isolate* isolate, TraceEventCallStatsTimer* timer, | |
716 CounterId counter_id); | |
717 | |
718 // Leave a scope for a measured runtime function. This will properly add | |
719 // the time delta to the current_counter and subtract the delta from its | |
720 // parent. | |
721 static void Leave(Isolate* isolate, TraceEventCallStatsTimer* timer); | |
722 | |
723 void Reset(); | |
724 const char* Dump(); | |
725 | |
726 TraceEventStatsTable() { | |
727 Reset(); | |
728 in_use_ = false; | |
729 } | |
730 | |
731 TraceEventCallStatsTimer* current_timer() { return current_timer_; } | |
732 bool InUse() { return in_use_; } | |
733 | |
734 private: | |
735 std::stringstream buffer_; | |
736 std::unique_ptr<char[]> buffer_c_str_; | |
737 size_t len_ = 0; | |
738 // Counter to track recursive time events. | |
739 TraceEventCallStatsTimer* current_timer_ = nullptr; | |
740 bool in_use_; | |
741 }; | |
742 | |
743 class CounterScope { | |
744 public: | |
745 CounterScope(Isolate* isolate, TraceEventStatsTable::CounterId counter_id) | |
746 : isolate_(nullptr) { | |
747 if (V8_UNLIKELY(TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED())) { | |
748 isolate_ = isolate; | |
749 TraceEventStatsTable::Enter(isolate_, &timer_, counter_id); | |
750 } | |
751 } | |
752 ~CounterScope() { | |
753 // A non-nullptr isolate_ means the stats table already entered the scope | |
754 // and started the timer, we need to leave the scope and reset the timer | |
755 // even when we stop tracing, otherwise we have the risk to have a dangling | |
756 // pointer. | |
757 if (V8_UNLIKELY(isolate_ != nullptr)) { | |
758 TraceEventStatsTable::Leave(isolate_, &timer_); | |
759 } | |
760 } | |
761 | |
762 private: | |
763 Isolate* isolate_; | |
764 TraceEventCallStatsTimer timer_; | |
765 }; | |
766 | |
767 } // namespace tracing | 646 } // namespace tracing |
768 } // namespace internal | 647 } // namespace internal |
769 } // namespace v8 | 648 } // namespace v8 |
770 | 649 |
771 #endif // SRC_TRACING_TRACE_EVENT_H_ | 650 #endif // SRC_TRACING_TRACE_EVENT_H_ |
OLD | NEW |