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" |
14 | 15 |
15 // This header file defines implementation details of how the trace macros in | 16 // This header file defines implementation details of how the trace macros in |
16 // trace_event_common.h collect and store trace events. Anything not | 17 // trace_event_common.h collect and store trace events. Anything not |
17 // implementation-specific should go in trace_macros_common.h instead of here. | 18 // implementation-specific should go in trace_macros_common.h instead of here. |
18 | 19 |
19 | 20 |
20 // The pointer returned from GetCategoryGroupEnabled() points to a | 21 // The pointer returned from GetCategoryGroupEnabled() points to a |
21 // value with zero or more of the following bits. Used in this class only. | 22 // value with zero or more of the following bits. Used in this class only. |
22 // The TRACE_EVENT macros should only use the value as a bool. | 23 // The TRACE_EVENT macros should only use the value as a bool. |
23 // These values must be in sync with macro values in trace_log.h in | 24 // 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... |
275 private: \ | 276 private: \ |
276 /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ | 277 /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ |
277 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | 278 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ |
278 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ | 279 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ |
279 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ | 280 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ |
280 uint64_t cid_; \ | 281 uint64_t cid_; \ |
281 }; \ | 282 }; \ |
282 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | 283 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ |
283 INTERNAL_TRACE_EVENT_UID(scoped_context)(context.raw_id()); | 284 INTERNAL_TRACE_EVENT_UID(scoped_context)(context.raw_id()); |
284 | 285 |
| 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 |
285 namespace v8 { | 318 namespace v8 { |
286 namespace internal { | 319 namespace internal { |
287 namespace tracing { | 320 namespace tracing { |
288 | 321 |
289 // Specify these values when the corresponding argument of AddTraceEvent is not | 322 // Specify these values when the corresponding argument of AddTraceEvent is not |
290 // used. | 323 // used. |
291 const int kZeroNumArgs = 0; | 324 const int kZeroNumArgs = 0; |
292 const decltype(nullptr) kGlobalScope = nullptr; | 325 const decltype(nullptr) kGlobalScope = nullptr; |
293 const uint64_t kNoId = 0; | 326 const uint64_t kNoId = 0; |
294 | 327 |
| 328 extern bool kRuntimeCallsTracingEnabled; |
| 329 |
295 class TraceEventHelper { | 330 class TraceEventHelper { |
296 public: | 331 public: |
297 static v8::Platform* GetCurrentPlatform(); | 332 static v8::Platform* GetCurrentPlatform(); |
298 }; | 333 }; |
299 | 334 |
300 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers | 335 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers |
301 // are by default mangled with the Process ID so that they are unlikely to | 336 // are by default mangled with the Process ID so that they are unlikely to |
302 // collide when the same pointer is used on different processes. | 337 // collide when the same pointer is used on different processes. |
303 class TraceID { | 338 class TraceID { |
304 public: | 339 public: |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 static V8_INLINE void Set(const char* category_and_name) { | 618 static V8_INLINE void Set(const char* category_and_name) { |
584 TRACE_EVENT_API_ATOMIC_STORE(g_trace_state[BucketNumber], | 619 TRACE_EVENT_API_ATOMIC_STORE(g_trace_state[BucketNumber], |
585 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( | 620 reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( |
586 const_cast<char*>(category_and_name))); | 621 const_cast<char*>(category_and_name))); |
587 } | 622 } |
588 | 623 |
589 private: | 624 private: |
590 const char* previous_state_; | 625 const char* previous_state_; |
591 }; | 626 }; |
592 | 627 |
| 628 // Do not use directly. |
| 629 class CallStatsScopedTracer { |
| 630 public: |
| 631 CallStatsScopedTracer() : p_data_(nullptr) {} |
| 632 ~CallStatsScopedTracer() { |
| 633 if (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 ~CounterScope(); |
| 745 |
| 746 private: |
| 747 Isolate* isolate_; |
| 748 TraceEventCallStatsTimer timer_; |
| 749 }; |
| 750 |
593 } // namespace tracing | 751 } // namespace tracing |
594 } // namespace internal | 752 } // namespace internal |
595 } // namespace v8 | 753 } // namespace v8 |
596 | 754 |
597 #endif // SRC_TRACING_TRACE_EVENT_H_ | 755 #endif // SRC_TRACING_TRACE_EVENT_H_ |
OLD | NEW |