OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 V8_COUNTERS_H_ | 5 #ifndef V8_COUNTERS_H_ |
6 #define V8_COUNTERS_H_ | 6 #define V8_COUNTERS_H_ |
7 | 7 |
8 #include "include/v8.h" | 8 #include "include/v8.h" |
9 #include "src/allocation.h" | 9 #include "src/allocation.h" |
10 #include "src/base/atomic-utils.h" | 10 #include "src/base/atomic-utils.h" |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 // The value is the average for [last_ms_; current_ms]. | 481 // The value is the average for [last_ms_; current_ms]. |
482 // Return the weighted average of the aggregate_value_ and the value. | 482 // Return the weighted average of the aggregate_value_ and the value. |
483 return aggregate_value_ * ((last_ms_ - start_ms_) / interval_ms) + | 483 return aggregate_value_ * ((last_ms_ - start_ms_) / interval_ms) + |
484 value * ((current_ms - last_ms_) / interval_ms); | 484 value * ((current_ms - last_ms_) / interval_ms); |
485 } | 485 } |
486 | 486 |
487 struct RuntimeCallCounter { | 487 struct RuntimeCallCounter { |
488 explicit RuntimeCallCounter(const char* name) : name(name) {} | 488 explicit RuntimeCallCounter(const char* name) : name(name) {} |
489 V8_NOINLINE void Reset(); | 489 V8_NOINLINE void Reset(); |
490 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); | 490 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); |
| 491 void Add(RuntimeCallCounter* other); |
491 | 492 |
492 const char* name; | 493 const char* name; |
493 int64_t count = 0; | 494 int64_t count = 0; |
494 base::TimeDelta time; | 495 base::TimeDelta time; |
495 }; | 496 }; |
496 | 497 |
497 // RuntimeCallTimer is used to keep track of the stack of currently active | 498 // RuntimeCallTimer is used to keep track of the stack of currently active |
498 // timers used for properly measuring the own time of a RuntimeCallCounter. | 499 // timers used for properly measuring the own time of a RuntimeCallCounter. |
499 class RuntimeCallTimer { | 500 class RuntimeCallTimer { |
500 public: | 501 public: |
(...skipping 29 matching lines...) Expand all Loading... |
530 inline void Elapsed() { | 531 inline void Elapsed() { |
531 base::TimeDelta delta = timer_.Elapsed(); | 532 base::TimeDelta delta = timer_.Elapsed(); |
532 counter_->time += delta; | 533 counter_->time += delta; |
533 if (parent()) { | 534 if (parent()) { |
534 parent()->counter_->time -= delta; | 535 parent()->counter_->time -= delta; |
535 parent()->Elapsed(); | 536 parent()->Elapsed(); |
536 } | 537 } |
537 timer_.Restart(); | 538 timer_.Restart(); |
538 } | 539 } |
539 | 540 |
| 541 const char* name() { return counter_->name; } |
| 542 |
540 RuntimeCallCounter* counter_ = nullptr; | 543 RuntimeCallCounter* counter_ = nullptr; |
541 base::AtomicValue<RuntimeCallTimer*> parent_; | 544 base::AtomicValue<RuntimeCallTimer*> parent_; |
542 base::ElapsedTimer timer_; | 545 base::ElapsedTimer timer_; |
543 }; | 546 }; |
544 | 547 |
545 #define FOR_EACH_API_COUNTER(V) \ | 548 #define FOR_EACH_API_COUNTER(V) \ |
546 V(ArrayBuffer_Cast) \ | 549 V(ArrayBuffer_Cast) \ |
547 V(ArrayBuffer_Neuter) \ | 550 V(ArrayBuffer_Neuter) \ |
548 V(ArrayBuffer_New) \ | 551 V(ArrayBuffer_New) \ |
549 V(Array_CloneElementAt) \ | 552 V(Array_CloneElementAt) \ |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 V(IndexedPropertyQueryCallback) \ | 720 V(IndexedPropertyQueryCallback) \ |
718 V(IndexedPropertySetterCallback) \ | 721 V(IndexedPropertySetterCallback) \ |
719 V(InvokeApiInterruptCallbacks) \ | 722 V(InvokeApiInterruptCallbacks) \ |
720 V(InvokeFunctionCallback) \ | 723 V(InvokeFunctionCallback) \ |
721 V(JS_Execution) \ | 724 V(JS_Execution) \ |
722 V(Map_SetPrototype) \ | 725 V(Map_SetPrototype) \ |
723 V(Map_TransitionToAccessorProperty) \ | 726 V(Map_TransitionToAccessorProperty) \ |
724 V(Map_TransitionToDataProperty) \ | 727 V(Map_TransitionToDataProperty) \ |
725 V(Object_DeleteProperty) \ | 728 V(Object_DeleteProperty) \ |
726 V(OptimizeCode) \ | 729 V(OptimizeCode) \ |
| 730 V(ParseArrowFunctionLiteral) \ |
| 731 V(ParseEval) \ |
| 732 V(ParseFunction) \ |
| 733 V(ParseFunctionLiteral) \ |
727 V(ParseProgram) \ | 734 V(ParseProgram) \ |
728 V(ParseFunction) \ | 735 V(PreParseArrowFunctionLiteral) \ |
| 736 V(PreParseNoVariableResolution) \ |
| 737 V(PreParseWithVariableResolution) \ |
729 V(PropertyCallback) \ | 738 V(PropertyCallback) \ |
730 V(PrototypeMap_TransitionToAccessorProperty) \ | 739 V(PrototypeMap_TransitionToAccessorProperty) \ |
731 V(PrototypeMap_TransitionToDataProperty) \ | 740 V(PrototypeMap_TransitionToDataProperty) \ |
732 V(PrototypeObject_DeleteProperty) \ | 741 V(PrototypeObject_DeleteProperty) \ |
733 V(RecompileConcurrent) \ | 742 V(RecompileConcurrent) \ |
734 V(RecompileSynchronous) \ | 743 V(RecompileSynchronous) \ |
735 /* Dummy counter for the unexpected stub miss. */ \ | 744 /* Dummy counter for the unexpected stub miss. */ \ |
736 V(UnexpectedStubMiss) | 745 V(UnexpectedStubMiss) |
737 | 746 |
738 #define FOR_EACH_HANDLER_COUNTER(V) \ | 747 #define FOR_EACH_HANDLER_COUNTER(V) \ |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 V(StoreIC_StoreFieldStub) \ | 805 V(StoreIC_StoreFieldStub) \ |
797 V(StoreIC_StoreGlobal) \ | 806 V(StoreIC_StoreGlobal) \ |
798 V(StoreIC_StoreGlobalTransition) \ | 807 V(StoreIC_StoreGlobalTransition) \ |
799 V(StoreIC_StoreInterceptorStub) \ | 808 V(StoreIC_StoreInterceptorStub) \ |
800 V(StoreIC_StoreNormal) \ | 809 V(StoreIC_StoreNormal) \ |
801 V(StoreIC_StoreScriptContextFieldStub) \ | 810 V(StoreIC_StoreScriptContextFieldStub) \ |
802 V(StoreIC_StoreTransition) \ | 811 V(StoreIC_StoreTransition) \ |
803 V(StoreIC_StoreTransitionDH) \ | 812 V(StoreIC_StoreTransitionDH) \ |
804 V(StoreIC_StoreViaSetter) | 813 V(StoreIC_StoreViaSetter) |
805 | 814 |
806 class RuntimeCallStats { | 815 class RuntimeCallStats : public ZoneObject { |
807 public: | 816 public: |
808 typedef RuntimeCallCounter RuntimeCallStats::*CounterId; | 817 typedef RuntimeCallCounter RuntimeCallStats::*CounterId; |
809 | 818 |
810 #define CALL_RUNTIME_COUNTER(name) \ | 819 #define CALL_RUNTIME_COUNTER(name) \ |
811 RuntimeCallCounter name = RuntimeCallCounter(#name); | 820 RuntimeCallCounter name = RuntimeCallCounter(#name); |
812 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) | 821 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) |
813 #undef CALL_RUNTIME_COUNTER | 822 #undef CALL_RUNTIME_COUNTER |
814 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ | 823 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ |
815 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); | 824 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); |
816 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) | 825 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) |
817 #undef CALL_RUNTIME_COUNTER | 826 #undef CALL_RUNTIME_COUNTER |
818 #define CALL_BUILTIN_COUNTER(name) \ | 827 #define CALL_BUILTIN_COUNTER(name) \ |
819 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); | 828 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); |
820 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) | 829 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) |
821 #undef CALL_BUILTIN_COUNTER | 830 #undef CALL_BUILTIN_COUNTER |
822 #define CALL_BUILTIN_COUNTER(name) \ | 831 #define CALL_BUILTIN_COUNTER(name) \ |
823 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); | 832 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); |
824 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) | 833 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) |
825 #undef CALL_BUILTIN_COUNTER | 834 #undef CALL_BUILTIN_COUNTER |
826 #define CALL_BUILTIN_COUNTER(name) \ | 835 #define CALL_BUILTIN_COUNTER(name) \ |
827 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); | 836 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); |
828 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) | 837 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) |
829 #undef CALL_BUILTIN_COUNTER | 838 #undef CALL_BUILTIN_COUNTER |
830 | 839 |
| 840 static const CounterId counters[]; |
| 841 |
831 // Starting measuring the time for a function. This will establish the | 842 // Starting measuring the time for a function. This will establish the |
832 // connection to the parent counter for properly calculating the own times. | 843 // connection to the parent counter for properly calculating the own times. |
833 static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer, | 844 static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer, |
834 CounterId counter_id); | 845 CounterId counter_id); |
835 | 846 |
836 // Leave a scope for a measured runtime function. This will properly add | 847 // Leave a scope for a measured runtime function. This will properly add |
837 // the time delta to the current_counter and subtract the delta from its | 848 // the time delta to the current_counter and subtract the delta from its |
838 // parent. | 849 // parent. |
839 static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer); | 850 static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer); |
840 | 851 |
841 // Set counter id for the innermost measurement. It can be used to refine | 852 // Set counter id for the innermost measurement. It can be used to refine |
842 // event kind when a runtime entry counter is too generic. | 853 // event kind when a runtime entry counter is too generic. |
843 static void CorrectCurrentCounterId(RuntimeCallStats* stats, | 854 static void CorrectCurrentCounterId(RuntimeCallStats* stats, |
844 CounterId counter_id); | 855 CounterId counter_id); |
845 | 856 |
846 void Reset(); | 857 void Reset(); |
| 858 // Add all entries from another stats object. |
| 859 void Add(RuntimeCallStats* other); |
847 void Print(std::ostream& os); | 860 void Print(std::ostream& os); |
848 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); | 861 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); |
849 | 862 |
850 RuntimeCallStats() { | 863 RuntimeCallStats() { |
851 Reset(); | 864 Reset(); |
852 in_use_ = false; | 865 in_use_ = false; |
853 } | 866 } |
854 | 867 |
855 RuntimeCallTimer* current_timer() { return current_timer_.Value(); } | 868 RuntimeCallTimer* current_timer() { return current_timer_.Value(); } |
856 bool InUse() { return in_use_; } | 869 bool InUse() { return in_use_; } |
857 | 870 |
858 private: | 871 private: |
859 // Counter to track recursive time events. | 872 // Counter to track recursive time events. |
860 base::AtomicValue<RuntimeCallTimer*> current_timer_; | 873 base::AtomicValue<RuntimeCallTimer*> current_timer_; |
861 // Used to track nested tracing scopes. | 874 // Used to track nested tracing scopes. |
862 bool in_use_; | 875 bool in_use_; |
863 }; | 876 }; |
864 | 877 |
865 #define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \ | 878 #define CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats, counter_name) \ |
866 do { \ | 879 do { \ |
867 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ | 880 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ |
868 RuntimeCallStats::CorrectCurrentCounterId( \ | 881 RuntimeCallStats::CorrectCurrentCounterId( \ |
869 isolate->counters()->runtime_call_stats(), \ | 882 runtime_call_stats, &RuntimeCallStats::counter_name); \ |
870 &RuntimeCallStats::counter_name); \ | 883 } \ |
871 } \ | |
872 } while (false) | 884 } while (false) |
873 | 885 |
874 #define TRACE_HANDLER_STATS(isolate, counter_name) \ | 886 #define TRACE_HANDLER_STATS(isolate, counter_name) \ |
875 TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name) | 887 CHANGE_CURRENT_RUNTIME_COUNTER(isolate->counters()->runtime_call_stats(), \ |
| 888 Handler_##counter_name) |
876 | 889 |
877 #define HISTOGRAM_RANGE_LIST(HR) \ | 890 #define HISTOGRAM_RANGE_LIST(HR) \ |
878 /* Generic range histograms */ \ | 891 /* Generic range histograms */ \ |
879 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ | 892 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ |
880 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ | 893 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ |
881 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ | 894 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ |
882 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ | 895 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ |
883 101) \ | 896 101) \ |
884 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ | 897 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ |
885 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ | 898 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the | 1301 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the |
1289 // the time of C++ scope. | 1302 // the time of C++ scope. |
1290 class RuntimeCallTimerScope { | 1303 class RuntimeCallTimerScope { |
1291 public: | 1304 public: |
1292 inline RuntimeCallTimerScope(Isolate* isolate, | 1305 inline RuntimeCallTimerScope(Isolate* isolate, |
1293 RuntimeCallStats::CounterId counter_id); | 1306 RuntimeCallStats::CounterId counter_id); |
1294 // This constructor is here just to avoid calling GetIsolate() when the | 1307 // This constructor is here just to avoid calling GetIsolate() when the |
1295 // stats are disabled and the isolate is not directly available. | 1308 // stats are disabled and the isolate is not directly available. |
1296 inline RuntimeCallTimerScope(HeapObject* heap_object, | 1309 inline RuntimeCallTimerScope(HeapObject* heap_object, |
1297 RuntimeCallStats::CounterId counter_id); | 1310 RuntimeCallStats::CounterId counter_id); |
| 1311 inline RuntimeCallTimerScope(RuntimeCallStats* stats, |
| 1312 RuntimeCallStats::CounterId counter_id); |
1298 | 1313 |
1299 inline ~RuntimeCallTimerScope() { | 1314 inline ~RuntimeCallTimerScope() { |
1300 if (V8_UNLIKELY(isolate_ != nullptr)) { | 1315 if (V8_UNLIKELY(stats_ != nullptr)) { |
1301 RuntimeCallStats::Leave(isolate_->counters()->runtime_call_stats(), | 1316 RuntimeCallStats::Leave(stats_, &timer_); |
1302 &timer_); | |
1303 } | 1317 } |
1304 } | 1318 } |
1305 | 1319 |
1306 private: | 1320 private: |
1307 V8_INLINE void Initialize(Isolate* isolate, | 1321 V8_INLINE void Initialize(RuntimeCallStats* stats, |
1308 RuntimeCallStats::CounterId counter_id) { | 1322 RuntimeCallStats::CounterId counter_id) { |
1309 isolate_ = isolate; | 1323 stats_ = stats; |
1310 RuntimeCallStats::Enter(isolate_->counters()->runtime_call_stats(), &timer_, | 1324 RuntimeCallStats::Enter(stats_, &timer_, counter_id); |
1311 counter_id); | |
1312 } | 1325 } |
1313 | 1326 |
1314 Isolate* isolate_ = nullptr; | 1327 RuntimeCallStats* stats_ = nullptr; |
1315 RuntimeCallTimer timer_; | 1328 RuntimeCallTimer timer_; |
1316 }; | 1329 }; |
1317 | 1330 |
1318 } // namespace internal | 1331 } // namespace internal |
1319 } // namespace v8 | 1332 } // namespace v8 |
1320 | 1333 |
1321 #endif // V8_COUNTERS_H_ | 1334 #endif // V8_COUNTERS_H_ |
OLD | NEW |