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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 private: \ | 275 private: \ |
277 /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ | 276 /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ |
278 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | 277 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ |
279 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ | 278 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ |
280 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ | 279 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ |
281 uint64_t cid_; \ | 280 uint64_t cid_; \ |
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() \ | |
287 v8::internal::tracing::kRuntimeCallsTracingEnabled | |
288 | |
289 #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \ | |
290 INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) | |
291 | |
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) \ | |
296 { \ | |
297 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO( \ | |
298 TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats")); \ | |
299 v8::internal::tracing::kRuntimeCallsTracingEnabled = \ | |
300 INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ | |
301 ? true \ | |
302 : false; \ | |
303 } \ | |
304 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ | |
305 v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \ | |
306 tracer); \ | |
307 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ | |
308 INTERNAL_TRACE_EVENT_UID(tracer) \ | |
309 .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \ | |
310 name); \ | |
311 } | |
312 | |
313 #define INTERNAL_TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED(isolate, \ | |
314 counter_id) \ | |
315 v8::internal::tracing::CounterScope INTERNAL_TRACE_EVENT_UID(scope)( \ | |
316 isolate, counter_id); | |
317 | |
318 namespace v8 { | 285 namespace v8 { |
319 namespace internal { | 286 namespace internal { |
320 namespace tracing { | 287 namespace tracing { |
321 | 288 |
322 // Specify these values when the corresponding argument of AddTraceEvent is not | 289 // Specify these values when the corresponding argument of AddTraceEvent is not |
323 // used. | 290 // used. |
324 const int kZeroNumArgs = 0; | 291 const int kZeroNumArgs = 0; |
325 const decltype(nullptr) kGlobalScope = nullptr; | 292 const decltype(nullptr) kGlobalScope = nullptr; |
326 const uint64_t kNoId = 0; | 293 const uint64_t kNoId = 0; |
327 | 294 |
328 extern bool kRuntimeCallsTracingEnabled; | |
329 | |
330 class TraceEventHelper { | 295 class TraceEventHelper { |
331 public: | 296 public: |
332 static v8::Platform* GetCurrentPlatform(); | 297 static v8::Platform* GetCurrentPlatform(); |
333 }; | 298 }; |
334 | 299 |
335 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers | 300 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers |
336 // are by default mangled with the Process ID so that they are unlikely to | 301 // are by default mangled with the Process ID so that they are unlikely to |
337 // collide when the same pointer is used on different processes. | 302 // collide when the same pointer is used on different processes. |
338 class TraceID { | 303 class TraceID { |
339 public: | 304 public: |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 static V8_INLINE void Set(const char* category_and_name) { | 583 static V8_INLINE void Set(const char* category_and_name) { |
619 TRACE_EVENT_API_ATOMIC_STORE(g_trace_state[BucketNumber], | 584 TRACE_EVENT_API_ATOMIC_STORE(g_trace_state[BucketNumber], |
620 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( | 585 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( |
621 const_cast<char*>(category_and_name))); | 586 const_cast<char*>(category_and_name))); |
622 } | 587 } |
623 | 588 |
624 private: | 589 private: |
625 const char* previous_state_; | 590 const char* previous_state_; |
626 }; | 591 }; |
627 | 592 |
628 // Do not use directly. | |
629 class CallStatsScopedTracer { | |
630 public: | |
631 CallStatsScopedTracer() : p_data_(nullptr) {} | |
632 ~CallStatsScopedTracer() { | |
633 if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) { | |
634 AddEndTraceEvent(); | |
635 } | |
636 } | |
637 | |
638 void Initialize(Isolate* isolate, const uint8_t* category_group_enabled, | |
639 const char* name); | |
640 | |
641 private: | |
642 void AddEndTraceEvent(); | |
643 struct Data { | |
644 const uint8_t* category_group_enabled; | |
645 const char* name; | |
646 Isolate* isolate; | |
647 }; | |
648 bool has_parent_scope_; | |
649 Data* p_data_; | |
650 Data data_; | |
651 }; | |
652 | |
653 // TraceEventCallStatsTimer is used to keep track of the stack of currently | |
654 // active timers used for properly measuring the own time of a | |
655 // RuntimeCallCounter. | |
656 class TraceEventCallStatsTimer { | |
657 public: | |
658 TraceEventCallStatsTimer() : counter_(nullptr), parent_(nullptr) {} | |
659 RuntimeCallCounter* counter() { return counter_; } | |
660 base::ElapsedTimer timer() { return timer_; } | |
661 | |
662 private: | |
663 friend class TraceEventStatsTable; | |
664 | |
665 V8_INLINE void Start(RuntimeCallCounter* counter, | |
666 TraceEventCallStatsTimer* parent) { | |
667 counter_ = counter; | |
668 parent_ = parent; | |
669 timer_.Start(); | |
670 } | |
671 | |
672 V8_INLINE TraceEventCallStatsTimer* Stop() { | |
673 base::TimeDelta delta = timer_.Elapsed(); | |
674 timer_.Stop(); | |
675 counter_->count++; | |
676 counter_->time += delta; | |
677 if (parent_ != nullptr) { | |
678 // Adjust parent timer so that it does not include sub timer's time. | |
679 parent_->counter_->time -= delta; | |
680 } | |
681 return parent_; | |
682 } | |
683 | |
684 RuntimeCallCounter* counter_; | |
685 TraceEventCallStatsTimer* parent_; | |
686 base::ElapsedTimer timer_; | |
687 }; | |
688 | |
689 class TraceEventStatsTable { | |
690 public: | |
691 typedef RuntimeCallCounter TraceEventStatsTable::*CounterId; | |
692 | |
693 #define CALL_RUNTIME_COUNTER(name) \ | |
694 RuntimeCallCounter name = RuntimeCallCounter(#name); | |
695 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) | |
696 #undef CALL_RUNTIME_COUNTER | |
697 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ | |
698 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); | |
699 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) | |
700 #undef CALL_RUNTIME_COUNTER | |
701 #define CALL_BUILTIN_COUNTER(name) \ | |
702 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); | |
703 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) | |
704 #undef CALL_BUILTIN_COUNTER | |
705 #define CALL_BUILTIN_COUNTER(name) \ | |
706 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); | |
707 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) | |
708 #undef CALL_BUILTIN_COUNTER | |
709 #define CALL_BUILTIN_COUNTER(name) \ | |
710 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); | |
711 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) | |
712 #undef CALL_BUILTIN_COUNTER | |
713 | |
714 // Starting measuring the time for a function. This will establish the | |
715 // connection to the parent counter for properly calculating the own times. | |
716 static void Enter(Isolate* isolate, TraceEventCallStatsTimer* timer, | |
717 CounterId counter_id); | |
718 | |
719 // Leave a scope for a measured runtime function. This will properly add | |
720 // the time delta to the current_counter and subtract the delta from its | |
721 // parent. | |
722 static void Leave(Isolate* isolate, TraceEventCallStatsTimer* timer); | |
723 | |
724 void Reset(); | |
725 const char* Dump(); | |
726 | |
727 TraceEventStatsTable() { | |
728 Reset(); | |
729 in_use_ = false; | |
730 } | |
731 TraceEventCallStatsTimer* current_timer() { return current_timer_; } | |
732 bool InUse() { return in_use_; } | |
733 | |
734 private: | |
735 std::stringstream buffer_; | |
736 // Counter to track recursive time events. | |
737 TraceEventCallStatsTimer* current_timer_ = nullptr; | |
738 bool in_use_; | |
739 }; | |
740 | |
741 class CounterScope { | |
742 public: | |
743 CounterScope(Isolate* isolate, TraceEventStatsTable::CounterId counter_id) | |
744 : isolate_(nullptr) { | |
745 if (V8_UNLIKELY(TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_ENABLED())) { | |
746 isolate_ = isolate; | |
747 TraceEventStatsTable::Enter(isolate_, &timer_, counter_id); | |
748 } | |
749 } | |
750 ~CounterScope() { | |
751 // A non-nullptr isolate_ means the stats table already entered the scope | |
752 // and started the timer, we need to leave the scope and reset the timer | |
753 // even when we stop tracing, otherwise we have the risk to have a dangling | |
754 // pointer. | |
755 if (V8_UNLIKELY(isolate_ != nullptr)) { | |
756 TraceEventStatsTable::Leave(isolate_, &timer_); | |
757 } | |
758 } | |
759 | |
760 private: | |
761 Isolate* isolate_; | |
762 TraceEventCallStatsTimer timer_; | |
763 }; | |
764 | |
765 } // namespace tracing | 593 } // namespace tracing |
766 } // namespace internal | 594 } // namespace internal |
767 } // namespace v8 | 595 } // namespace v8 |
768 | 596 |
769 #endif // SRC_TRACING_TRACE_EVENT_H_ | 597 #endif // SRC_TRACING_TRACE_EVENT_H_ |
OLD | NEW |