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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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) \ |
727 V(ParseProgram) \ | 730 V(ParseProgram) \ |
| 731 V(ParseEval) \ |
728 V(ParseFunction) \ | 732 V(ParseFunction) \ |
| 733 V(ParseFunctionLiteral) \ |
| 734 V(PreParseWithVariableResolution) \ |
| 735 V(PreParseNoVariableResolution) \ |
| 736 V(ParseArrowFunctionLiteral) \ |
| 737 V(PreParseArrowFunctionLiteral) \ |
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 V(StoreIC_StoreFieldDH) \ | 803 V(StoreIC_StoreFieldDH) \ |
795 V(StoreIC_StoreFieldStub) \ | 804 V(StoreIC_StoreFieldStub) \ |
796 V(StoreIC_StoreGlobal) \ | 805 V(StoreIC_StoreGlobal) \ |
797 V(StoreIC_StoreGlobalTransition) \ | 806 V(StoreIC_StoreGlobalTransition) \ |
798 V(StoreIC_StoreInterceptorStub) \ | 807 V(StoreIC_StoreInterceptorStub) \ |
799 V(StoreIC_StoreNormal) \ | 808 V(StoreIC_StoreNormal) \ |
800 V(StoreIC_StoreScriptContextFieldStub) \ | 809 V(StoreIC_StoreScriptContextFieldStub) \ |
801 V(StoreIC_StoreTransition) \ | 810 V(StoreIC_StoreTransition) \ |
802 V(StoreIC_StoreViaSetter) | 811 V(StoreIC_StoreViaSetter) |
803 | 812 |
804 class RuntimeCallStats { | 813 class RuntimeCallStats : public ZoneObject { |
805 public: | 814 public: |
806 typedef RuntimeCallCounter RuntimeCallStats::*CounterId; | 815 typedef RuntimeCallCounter RuntimeCallStats::*CounterId; |
807 | 816 |
| 817 RuntimeCallCounter First = RuntimeCallCounter("First"); |
808 #define CALL_RUNTIME_COUNTER(name) \ | 818 #define CALL_RUNTIME_COUNTER(name) \ |
809 RuntimeCallCounter name = RuntimeCallCounter(#name); | 819 RuntimeCallCounter name = RuntimeCallCounter(#name); |
810 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) | 820 FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER) |
811 #undef CALL_RUNTIME_COUNTER | 821 #undef CALL_RUNTIME_COUNTER |
812 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ | 822 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ |
813 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); | 823 RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); |
814 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) | 824 FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) |
815 #undef CALL_RUNTIME_COUNTER | 825 #undef CALL_RUNTIME_COUNTER |
816 #define CALL_BUILTIN_COUNTER(name) \ | 826 #define CALL_BUILTIN_COUNTER(name) \ |
817 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); | 827 RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name); |
818 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) | 828 BUILTIN_LIST_C(CALL_BUILTIN_COUNTER) |
819 #undef CALL_BUILTIN_COUNTER | 829 #undef CALL_BUILTIN_COUNTER |
820 #define CALL_BUILTIN_COUNTER(name) \ | 830 #define CALL_BUILTIN_COUNTER(name) \ |
821 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); | 831 RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name); |
822 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) | 832 FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER) |
823 #undef CALL_BUILTIN_COUNTER | 833 #undef CALL_BUILTIN_COUNTER |
824 #define CALL_BUILTIN_COUNTER(name) \ | 834 #define CALL_BUILTIN_COUNTER(name) \ |
825 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); | 835 RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name); |
826 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) | 836 FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER) |
827 #undef CALL_BUILTIN_COUNTER | 837 #undef CALL_BUILTIN_COUNTER |
| 838 RuntimeCallCounter Last = RuntimeCallCounter("Last"); |
828 | 839 |
829 // Starting measuring the time for a function. This will establish the | 840 // Starting measuring the time for a function. This will establish the |
830 // connection to the parent counter for properly calculating the own times. | 841 // connection to the parent counter for properly calculating the own times. |
831 static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer, | 842 static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer, |
832 CounterId counter_id); | 843 CounterId counter_id); |
833 | 844 |
834 // Leave a scope for a measured runtime function. This will properly add | 845 // Leave a scope for a measured runtime function. This will properly add |
835 // the time delta to the current_counter and subtract the delta from its | 846 // the time delta to the current_counter and subtract the delta from its |
836 // parent. | 847 // parent. |
837 static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer); | 848 static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer); |
838 | 849 |
839 // Set counter id for the innermost measurement. It can be used to refine | 850 // Set counter id for the innermost measurement. It can be used to refine |
840 // event kind when a runtime entry counter is too generic. | 851 // event kind when a runtime entry counter is too generic. |
841 static void CorrectCurrentCounterId(RuntimeCallStats* stats, | 852 static void CorrectCurrentCounterId(RuntimeCallStats* stats, |
842 CounterId counter_id); | 853 CounterId counter_id); |
843 | 854 |
844 void Reset(); | 855 void Reset(); |
| 856 // Add all entries from another stats object. |
| 857 void Add(RuntimeCallStats* other); |
845 void Print(std::ostream& os); | 858 void Print(std::ostream& os); |
846 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); | 859 V8_NOINLINE void Dump(v8::tracing::TracedValue* value); |
847 | 860 |
848 RuntimeCallStats() { | 861 RuntimeCallStats() { |
849 Reset(); | 862 Reset(); |
850 in_use_ = false; | 863 in_use_ = false; |
851 } | 864 } |
852 | 865 |
853 RuntimeCallTimer* current_timer() { return current_timer_.Value(); } | 866 RuntimeCallTimer* current_timer() { return current_timer_.Value(); } |
854 bool InUse() { return in_use_; } | 867 bool InUse() { return in_use_; } |
855 | 868 |
856 private: | 869 private: |
857 // Counter to track recursive time events. | 870 // Counter to track recursive time events. |
858 base::AtomicValue<RuntimeCallTimer*> current_timer_; | 871 base::AtomicValue<RuntimeCallTimer*> current_timer_; |
859 // Used to track nested tracing scopes. | 872 // Used to track nested tracing scopes. |
860 bool in_use_; | 873 bool in_use_; |
861 }; | 874 }; |
862 | 875 |
863 #define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \ | 876 #define CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats, counter_name) \ |
864 do { \ | 877 do { \ |
865 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ | 878 if (V8_UNLIKELY(FLAG_runtime_stats)) { \ |
866 RuntimeCallStats::CorrectCurrentCounterId( \ | 879 RuntimeCallStats::CorrectCurrentCounterId( \ |
867 isolate->counters()->runtime_call_stats(), \ | 880 runtime_call_stats, &RuntimeCallStats::counter_name); \ |
868 &RuntimeCallStats::counter_name); \ | 881 } \ |
869 } \ | |
870 } while (false) | 882 } while (false) |
871 | 883 |
872 #define TRACE_HANDLER_STATS(isolate, counter_name) \ | 884 #define TRACE_HANDLER_STATS(isolate, counter_name) \ |
873 TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name) | 885 CHANGE_CURRENT_RUNTIME_COUNTER(isolate->counters()->runtime_call_stats(), \ |
| 886 Handler_##counter_name) |
874 | 887 |
875 #define HISTOGRAM_RANGE_LIST(HR) \ | 888 #define HISTOGRAM_RANGE_LIST(HR) \ |
876 /* Generic range histograms */ \ | 889 /* Generic range histograms */ \ |
877 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ | 890 HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21) \ |
878 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ | 891 HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101) \ |
879 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ | 892 HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \ |
880 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ | 893 HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000, \ |
881 101) \ | 894 101) \ |
882 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ | 895 HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6) \ |
883 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ | 896 HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20) \ |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the | 1299 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the |
1287 // the time of C++ scope. | 1300 // the time of C++ scope. |
1288 class RuntimeCallTimerScope { | 1301 class RuntimeCallTimerScope { |
1289 public: | 1302 public: |
1290 inline RuntimeCallTimerScope(Isolate* isolate, | 1303 inline RuntimeCallTimerScope(Isolate* isolate, |
1291 RuntimeCallStats::CounterId counter_id); | 1304 RuntimeCallStats::CounterId counter_id); |
1292 // This constructor is here just to avoid calling GetIsolate() when the | 1305 // This constructor is here just to avoid calling GetIsolate() when the |
1293 // stats are disabled and the isolate is not directly available. | 1306 // stats are disabled and the isolate is not directly available. |
1294 inline RuntimeCallTimerScope(HeapObject* heap_object, | 1307 inline RuntimeCallTimerScope(HeapObject* heap_object, |
1295 RuntimeCallStats::CounterId counter_id); | 1308 RuntimeCallStats::CounterId counter_id); |
| 1309 inline RuntimeCallTimerScope(RuntimeCallStats* stats, |
| 1310 RuntimeCallStats::CounterId counter_id); |
1296 | 1311 |
1297 inline ~RuntimeCallTimerScope() { | 1312 inline ~RuntimeCallTimerScope() { |
1298 if (V8_UNLIKELY(isolate_ != nullptr)) { | 1313 if (V8_UNLIKELY(stats_ != nullptr)) { |
1299 RuntimeCallStats::Leave(isolate_->counters()->runtime_call_stats(), | 1314 RuntimeCallStats::Leave(stats_, &timer_); |
1300 &timer_); | |
1301 } | 1315 } |
1302 } | 1316 } |
1303 | 1317 |
1304 private: | 1318 private: |
1305 V8_INLINE void Initialize(Isolate* isolate, | 1319 V8_INLINE void Initialize(RuntimeCallStats* stats, |
1306 RuntimeCallStats::CounterId counter_id) { | 1320 RuntimeCallStats::CounterId counter_id) { |
1307 isolate_ = isolate; | 1321 stats_ = stats; |
1308 RuntimeCallStats::Enter(isolate_->counters()->runtime_call_stats(), &timer_, | 1322 RuntimeCallStats::Enter(stats_, &timer_, counter_id); |
1309 counter_id); | |
1310 } | 1323 } |
1311 | 1324 |
1312 Isolate* isolate_ = nullptr; | 1325 RuntimeCallStats* stats_ = nullptr; |
1313 RuntimeCallTimer timer_; | 1326 RuntimeCallTimer timer_; |
1314 }; | 1327 }; |
1315 | 1328 |
1316 } // namespace internal | 1329 } // namespace internal |
1317 } // namespace v8 | 1330 } // namespace v8 |
1318 | 1331 |
1319 #endif // V8_COUNTERS_H_ | 1332 #endif // V8_COUNTERS_H_ |
OLD | NEW |