LCOV - code coverage report
Current view: top level - src - counters.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 58 191 30.4 %
Date: 2017-10-20 Functions: 10 33 30.3 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/counters.h"
       6             : 
       7             : #include <iomanip>
       8             : 
       9             : #include "src/base/platform/platform.h"
      10             : #include "src/builtins/builtins-definitions.h"
      11             : #include "src/isolate.h"
      12             : #include "src/log-inl.h"
      13             : #include "src/log.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18           0 : StatsTable::StatsTable(Counters* counters)
      19             :     : lookup_function_(nullptr),
      20             :       create_histogram_function_(nullptr),
      21       54999 :       add_histogram_sample_function_(nullptr) {}
      22             : 
      23           0 : void StatsTable::SetCounterFunction(CounterLookupCallback f) {
      24           5 :   lookup_function_ = f;
      25           0 : }
      26             : 
      27     1155963 : int* StatsCounterBase::FindLocationInStatsTable() const {
      28     2311941 :   return counters_->FindLocation(name_);
      29             : }
      30             : 
      31           0 : StatsCounterThreadSafe::StatsCounterThreadSafe(Counters* counters,
      32             :                                                const char* name)
      33      164997 :     : StatsCounterBase(counters, name) {}
      34             : 
      35           0 : void StatsCounterThreadSafe::Set(int Value) {
      36           0 :   if (ptr_) {
      37           0 :     base::LockGuard<base::Mutex> Guard(&mutex_);
      38           0 :     SetLoc(ptr_, Value);
      39             :   }
      40           0 : }
      41             : 
      42       11259 : void StatsCounterThreadSafe::Increment() {
      43       11259 :   if (ptr_) {
      44           0 :     base::LockGuard<base::Mutex> Guard(&mutex_);
      45           0 :     IncrementLoc(ptr_);
      46             :   }
      47       11259 : }
      48             : 
      49     1089536 : void StatsCounterThreadSafe::Increment(int value) {
      50     1089536 :   if (ptr_) {
      51           0 :     base::LockGuard<base::Mutex> Guard(&mutex_);
      52           0 :     IncrementLoc(ptr_, value);
      53             :   }
      54     1089536 : }
      55             : 
      56           0 : void StatsCounterThreadSafe::Decrement() {
      57           0 :   if (ptr_) {
      58           0 :     base::LockGuard<base::Mutex> Guard(&mutex_);
      59           0 :     DecrementLoc(ptr_);
      60             :   }
      61           0 : }
      62             : 
      63           0 : void StatsCounterThreadSafe::Decrement(int value) {
      64           0 :   if (ptr_) {
      65           0 :     base::LockGuard<base::Mutex> Guard(&mutex_);
      66           0 :     DecrementLoc(ptr_, value);
      67             :   }
      68           0 : }
      69             : 
      70     2822316 : void Histogram::AddSample(int sample) {
      71     2822316 :   if (Enabled()) {
      72           0 :     counters_->AddHistogramSample(histogram_, sample);
      73             :   }
      74     2822336 : }
      75             : 
      76           0 : void* Histogram::CreateHistogram() const {
      77         350 :   return counters_->CreateHistogram(name_, min_, max_, num_buckets_);
      78             : }
      79             : 
      80     3037327 : void TimedHistogram::Start(base::ElapsedTimer* timer, Isolate* isolate) {
      81     5068077 :   if (Enabled()) timer->Start();
      82     3037327 :   if (isolate) Logger::CallEventLogger(isolate, name(), Logger::START, true);
      83     3037327 : }
      84             : 
      85     3037305 : void TimedHistogram::Stop(base::ElapsedTimer* timer, Isolate* isolate) {
      86     5068056 :   if (Enabled()) {
      87             :     // Compute the delta between start and stop, in microseconds.
      88           0 :     int64_t sample = resolution_ == HistogramTimerResolution::MICROSECOND
      89             :                          ? timer->Elapsed().InMicroseconds()
      90           0 :                          : timer->Elapsed().InMilliseconds();
      91             :     timer->Stop();
      92           0 :     AddSample(static_cast<int>(sample));
      93             :   }
      94     3037285 :   if (isolate != nullptr) {
      95             :     Logger::CallEventLogger(isolate, name(), Logger::END, true);
      96             :   }
      97     3037285 : }
      98             : 
      99       54999 : Counters::Counters(Isolate* isolate)
     100             :     : isolate_(isolate),
     101             :       stats_table_(this),
     102             : // clang format off
     103             : #define SC(name, caption) name##_(this, "c:" #caption),
     104             :       STATS_COUNTER_TS_LIST(SC)
     105             : #undef SC
     106             :       // clang format on
     107      109998 :       runtime_call_stats_() {
     108             :   static const struct {
     109             :     Histogram Counters::*member;
     110             :     const char* caption;
     111             :     int min;
     112             :     int max;
     113             :     int num_buckets;
     114             :   } kHistograms[] = {
     115             : #define HR(name, caption, min, max, num_buckets) \
     116             :   {&Counters::name##_, #caption, min, max, num_buckets},
     117             :       HISTOGRAM_RANGE_LIST(HR)
     118             : #undef HR
     119             :   };
     120     1594971 :   for (const auto& histogram : kHistograms) {
     121             :     this->*histogram.member =
     122             :         Histogram(histogram.caption, histogram.min, histogram.max,
     123     1539972 :                   histogram.num_buckets, this);
     124             :   }
     125             : 
     126             :   const int DefaultTimedHistogramNumBuckets = 50;
     127             : 
     128             :   static const struct {
     129             :     HistogramTimer Counters::*member;
     130             :     const char* caption;
     131             :     int max;
     132             :     HistogramTimerResolution res;
     133             :   } kHistogramTimers[] = {
     134             : #define HT(name, caption, max, res) \
     135             :   {&Counters::name##_, #caption, max, HistogramTimerResolution::res},
     136             :       HISTOGRAM_TIMER_LIST(HT)
     137             : #undef HT
     138             :   };
     139     1044981 :   for (const auto& timer : kHistogramTimers) {
     140             :     this->*timer.member = HistogramTimer(timer.caption, 0, timer.max, timer.res,
     141     1044981 :                                          DefaultTimedHistogramNumBuckets, this);
     142             :   }
     143             : 
     144             :   static const struct {
     145             :     TimedHistogram Counters::*member;
     146             :     const char* caption;
     147             :     int max;
     148             :     HistogramTimerResolution res;
     149             :   } kTimedHistograms[] = {
     150             : #define HT(name, caption, max, res) \
     151             :   {&Counters::name##_, #caption, max, HistogramTimerResolution::res},
     152             :       TIMED_HISTOGRAM_LIST(HT)
     153             : #undef HT
     154             :   };
     155      549990 :   for (const auto& timer : kTimedHistograms) {
     156             :     this->*timer.member = TimedHistogram(timer.caption, 0, timer.max, timer.res,
     157      549990 :                                          DefaultTimedHistogramNumBuckets, this);
     158             :   }
     159             : 
     160             :   static const struct {
     161             :     AggregatableHistogramTimer Counters::*member;
     162             :     const char* caption;
     163             :   } kAggregatableHistogramTimers[] = {
     164             : #define AHT(name, caption) {&Counters::name##_, #caption},
     165             :       AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
     166             : #undef AHT
     167             :   };
     168       54999 :   for (const auto& aht : kAggregatableHistogramTimers) {
     169       54999 :     this->*aht.member = AggregatableHistogramTimer(
     170             :         aht.caption, 0, 10000000, DefaultTimedHistogramNumBuckets, this);
     171             :   }
     172             : 
     173             :   static const struct {
     174             :     Histogram Counters::*member;
     175             :     const char* caption;
     176             :   } kHistogramPercentages[] = {
     177             : #define HP(name, caption) {&Counters::name##_, #caption},
     178             :       HISTOGRAM_PERCENTAGE_LIST(HP)
     179             : #undef HP
     180             :   };
     181      274995 :   for (const auto& percentage : kHistogramPercentages) {
     182      274995 :     this->*percentage.member = Histogram(percentage.caption, 0, 101, 100, this);
     183             :   }
     184             : 
     185             :   // Exponential histogram assigns bucket limits to points
     186             :   // p[1], p[2], ... p[n] such that p[i+1] / p[i] = constant.
     187             :   // The constant factor is equal to the n-th root of (high / low),
     188             :   // where the n is the number of buckets, the low is the lower limit,
     189             :   // the high is the upper limit.
     190             :   // For n = 50, low = 1000, high = 500000: the factor = 1.13.
     191             :   static const struct {
     192             :     Histogram Counters::*member;
     193             :     const char* caption;
     194             :   } kLegacyMemoryHistograms[] = {
     195             : #define HM(name, caption) {&Counters::name##_, #caption},
     196             :       HISTOGRAM_LEGACY_MEMORY_LIST(HM)
     197             : #undef HM
     198             :   };
     199      274995 :   for (const auto& histogram : kLegacyMemoryHistograms) {
     200             :     this->*histogram.member =
     201      274995 :         Histogram(histogram.caption, 1000, 500000, 50, this);
     202             :   }
     203             : 
     204             :   // For n = 100, low = 4000, high = 2000000: the factor = 1.06.
     205             :   static const struct {
     206             :     Histogram Counters::*member;
     207             :     AggregatedMemoryHistogram<Histogram> Counters::*aggregated;
     208             :     const char* caption;
     209             :   } kMemoryHistograms[] = {
     210             : #define HM(name, caption) \
     211             :   {&Counters::name##_, &Counters::aggregated_##name##_, #caption},
     212             :       HISTOGRAM_MEMORY_LIST(HM)
     213             : #undef HM
     214             :   };
     215      109998 :   for (const auto& histogram : kMemoryHistograms) {
     216             :     this->*histogram.member =
     217      109998 :         Histogram(histogram.caption, 4000, 2000000, 100, this);
     218             :     this->*histogram.aggregated =
     219      109998 :         AggregatedMemoryHistogram<Histogram>(&(this->*histogram.member));
     220             :   }
     221             : 
     222             :   // clang-format off
     223             :   static const struct {
     224             :     StatsCounter Counters::*member;
     225             :     const char* caption;
     226             :   } kStatsCounters[] = {
     227             : #define SC(name, caption) {&Counters::name##_, "c:" #caption},
     228             :       STATS_COUNTER_LIST_1(SC) STATS_COUNTER_LIST_2(SC)
     229             : #undef SC
     230             : #define SC(name)                                             \
     231             :   {&Counters::count_of_##name##_, "c:" "V8.CountOf_" #name}, \
     232             :   {&Counters::size_of_##name##_, "c:" "V8.SizeOf_" #name},
     233             :       INSTANCE_TYPE_LIST(SC)
     234             : #undef SC
     235             : #define SC(name)                            \
     236             :   {&Counters::count_of_CODE_TYPE_##name##_, \
     237             :     "c:" "V8.CountOf_CODE_TYPE-" #name},     \
     238             :   {&Counters::size_of_CODE_TYPE_##name##_,  \
     239             :     "c:" "V8.SizeOf_CODE_TYPE-" #name},
     240             :       CODE_KIND_LIST(SC)
     241             : #undef SC
     242             : #define SC(name)                              \
     243             :   {&Counters::count_of_FIXED_ARRAY_##name##_, \
     244             :     "c:" "V8.CountOf_FIXED_ARRAY-" #name},     \
     245             :   {&Counters::size_of_FIXED_ARRAY_##name##_,  \
     246             :     "c:" "V8.SizeOf_FIXED_ARRAY-" #name},
     247             :       FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
     248             : #undef SC
     249             :   };
     250             :   // clang-format on
     251    27498726 :   for (const auto& counter : kStatsCounters) {
     252    27498726 :     this->*counter.member = StatsCounter(this, counter.caption);
     253             :   }
     254       54999 : }
     255             : 
     256           5 : void Counters::ResetCounterFunction(CounterLookupCallback f) {
     257             :   stats_table_.SetCounterFunction(f);
     258             : 
     259             : #define SC(name, caption) name##_.Reset();
     260             :   STATS_COUNTER_LIST_1(SC)
     261             :   STATS_COUNTER_LIST_2(SC)
     262             : #undef SC
     263             : 
     264             : #define SC(name, caption) name##_.Reset();
     265             :   STATS_COUNTER_TS_LIST(SC)
     266             : #undef SC
     267             : 
     268             : #define SC(name)              \
     269             :   count_of_##name##_.Reset(); \
     270             :   size_of_##name##_.Reset();
     271             :   INSTANCE_TYPE_LIST(SC)
     272             : #undef SC
     273             : 
     274             : #define SC(name)                        \
     275             :   count_of_CODE_TYPE_##name##_.Reset(); \
     276             :   size_of_CODE_TYPE_##name##_.Reset();
     277             :   CODE_KIND_LIST(SC)
     278             : #undef SC
     279             : 
     280             : #define SC(name)                          \
     281             :   count_of_FIXED_ARRAY_##name##_.Reset(); \
     282             :   size_of_FIXED_ARRAY_##name##_.Reset();
     283             :   FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
     284             : #undef SC
     285           5 : }
     286             : 
     287           5 : void Counters::ResetCreateHistogramFunction(CreateHistogramCallback f) {
     288             :   stats_table_.SetCreateHistogramFunction(f);
     289             : 
     290             : #define HR(name, caption, min, max, num_buckets) name##_.Reset();
     291           5 :   HISTOGRAM_RANGE_LIST(HR)
     292             : #undef HR
     293             : 
     294             : #define HT(name, caption, max, res) name##_.Reset();
     295           5 :     HISTOGRAM_TIMER_LIST(HT)
     296             : #undef HT
     297             : 
     298             : #define HT(name, caption, max, res) name##_.Reset();
     299           5 :     TIMED_HISTOGRAM_LIST(HT)
     300             : #undef HT
     301             : 
     302             : #define AHT(name, caption) name##_.Reset();
     303           5 :     AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
     304             : #undef AHT
     305             : 
     306             : #define HP(name, caption) name##_.Reset();
     307           5 :     HISTOGRAM_PERCENTAGE_LIST(HP)
     308             : #undef HP
     309             : 
     310             : #define HM(name, caption) name##_.Reset();
     311           5 :     HISTOGRAM_LEGACY_MEMORY_LIST(HM)
     312           5 :     HISTOGRAM_MEMORY_LIST(HM)
     313             : #undef HM
     314           5 : }
     315             : 
     316           0 : class RuntimeCallStatEntries {
     317             :  public:
     318           0 :   void Print(std::ostream& os) {
     319           0 :     if (total_call_count == 0) return;
     320           0 :     std::sort(entries.rbegin(), entries.rend());
     321           0 :     os << std::setw(50) << "Runtime Function/C++ Builtin" << std::setw(12)
     322           0 :        << "Time" << std::setw(18) << "Count" << std::endl
     323           0 :        << std::string(88, '=') << std::endl;
     324           0 :     for (Entry& entry : entries) {
     325           0 :       entry.SetTotal(total_time, total_call_count);
     326           0 :       entry.Print(os);
     327             :     }
     328           0 :     os << std::string(88, '-') << std::endl;
     329           0 :     Entry("Total", total_time, total_call_count).Print(os);
     330             :   }
     331             : 
     332             :   // By default, the compiler will usually inline this, which results in a large
     333             :   // binary size increase: std::vector::push_back expands to a large amount of
     334             :   // instructions, and this function is invoked repeatedly by macros.
     335           0 :   V8_NOINLINE void Add(RuntimeCallCounter* counter) {
     336           0 :     if (counter->count() == 0) return;
     337             :     entries.push_back(
     338           0 :         Entry(counter->name(), counter->time(), counter->count()));
     339             :     total_time += counter->time();
     340           0 :     total_call_count += counter->count();
     341             :   }
     342             : 
     343             :  private:
     344             :   class Entry {
     345             :    public:
     346             :     Entry(const char* name, base::TimeDelta time, uint64_t count)
     347             :         : name_(name),
     348             :           time_(time.InMicroseconds()),
     349             :           count_(count),
     350             :           time_percent_(100),
     351           0 :           count_percent_(100) {}
     352             : 
     353             :     bool operator<(const Entry& other) const {
     354           0 :       if (time_ < other.time_) return true;
     355           0 :       if (time_ > other.time_) return false;
     356           0 :       return count_ < other.count_;
     357             :     }
     358             : 
     359           0 :     V8_NOINLINE void Print(std::ostream& os) {
     360           0 :       os.precision(2);
     361             :       os << std::fixed << std::setprecision(2);
     362           0 :       os << std::setw(50) << name_;
     363           0 :       os << std::setw(10) << static_cast<double>(time_) / 1000 << "ms ";
     364           0 :       os << std::setw(6) << time_percent_ << "%";
     365           0 :       os << std::setw(10) << count_ << " ";
     366           0 :       os << std::setw(6) << count_percent_ << "%";
     367             :       os << std::endl;
     368           0 :     }
     369             : 
     370           0 :     V8_NOINLINE void SetTotal(base::TimeDelta total_time,
     371             :                               uint64_t total_count) {
     372           0 :       if (total_time.InMicroseconds() == 0) {
     373           0 :         time_percent_ = 0;
     374             :       } else {
     375           0 :         time_percent_ = 100.0 * time_ / total_time.InMicroseconds();
     376             :       }
     377           0 :       count_percent_ = 100.0 * count_ / total_count;
     378           0 :     }
     379             : 
     380             :    private:
     381             :     const char* name_;
     382             :     int64_t time_;
     383             :     uint64_t count_;
     384             :     double time_percent_;
     385             :     double count_percent_;
     386             :   };
     387             : 
     388             :   uint64_t total_call_count = 0;
     389             :   base::TimeDelta total_time;
     390             :   std::vector<Entry> entries;
     391             : };
     392             : 
     393           0 : void RuntimeCallCounter::Reset() {
     394           0 :   count_ = 0;
     395           0 :   time_ = 0;
     396           0 : }
     397             : 
     398           0 : void RuntimeCallCounter::Dump(v8::tracing::TracedValue* value) {
     399           0 :   value->BeginArray(name_);
     400           0 :   value->AppendDouble(count_);
     401           0 :   value->AppendDouble(time_);
     402           0 :   value->EndArray();
     403           0 : }
     404             : 
     405           0 : void RuntimeCallCounter::Add(RuntimeCallCounter* other) {
     406           0 :   count_ += other->count();
     407           0 :   time_ += other->time().InMicroseconds();
     408           0 : }
     409             : 
     410           0 : void RuntimeCallTimer::Snapshot() {
     411             :   base::TimeTicks now = Now();
     412             :   // Pause only / topmost timer in the timer stack.
     413             :   Pause(now);
     414             :   // Commit all the timer's elapsed time to the counters.
     415             :   RuntimeCallTimer* timer = this;
     416           0 :   while (timer != nullptr) {
     417             :     timer->CommitTimeToCounter();
     418             :     timer = timer->parent();
     419             :   }
     420             :   Resume(now);
     421           0 : }
     422             : 
     423      109998 : RuntimeCallStats::RuntimeCallStats() : in_use_(false) {
     424             :   static const char* const kNames[] = {
     425             : #define CALL_BUILTIN_COUNTER(name) "GC_" #name,
     426             :       FOR_EACH_GC_COUNTER(CALL_BUILTIN_COUNTER)  //
     427             : #undef CALL_BUILTIN_COUNTER
     428             : #define CALL_RUNTIME_COUNTER(name) #name,
     429             :       FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)  //
     430             : #undef CALL_RUNTIME_COUNTER
     431             : #define CALL_RUNTIME_COUNTER(name, nargs, ressize) #name,
     432             :       FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)  //
     433             : #undef CALL_RUNTIME_COUNTER
     434             : #define CALL_BUILTIN_COUNTER(name) #name,
     435             :       BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)  //
     436             : #undef CALL_BUILTIN_COUNTER
     437             : #define CALL_BUILTIN_COUNTER(name) "API_" #name,
     438             :       FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER)  //
     439             : #undef CALL_BUILTIN_COUNTER
     440             : #define CALL_BUILTIN_COUNTER(name) #name,
     441             :       FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)  //
     442             : #undef CALL_BUILTIN_COUNTER
     443             :   };
     444    62972920 :   for (int i = 0; i < counters_count; i++) {
     445    62917921 :     this->*(counters[i]) = RuntimeCallCounter(kNames[i]);
     446             :   }
     447       54999 : }
     448             : 
     449             : // static
     450             : const RuntimeCallStats::CounterId RuntimeCallStats::counters[] = {
     451             : #define CALL_BUILTIN_COUNTER(name) &RuntimeCallStats::GC_##name,
     452             :     FOR_EACH_GC_COUNTER(CALL_BUILTIN_COUNTER)  //
     453             : #undef CALL_BUILTIN_COUNTER
     454             : #define CALL_RUNTIME_COUNTER(name) &RuntimeCallStats::name,
     455             :     FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)  //
     456             : #undef CALL_RUNTIME_COUNTER
     457             : #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \
     458             :   &RuntimeCallStats::Runtime_##name,          //
     459             :     FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)  //
     460             : #undef CALL_RUNTIME_COUNTER
     461             : #define CALL_BUILTIN_COUNTER(name) &RuntimeCallStats::Builtin_##name,
     462             :     BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)  //
     463             : #undef CALL_BUILTIN_COUNTER
     464             : #define CALL_BUILTIN_COUNTER(name) &RuntimeCallStats::API_##name,
     465             :     FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER)  //
     466             : #undef CALL_BUILTIN_COUNTER
     467             : #define CALL_BUILTIN_COUNTER(name) &RuntimeCallStats::Handler_##name,
     468             :     FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)  //
     469             : #undef CALL_BUILTIN_COUNTER
     470             : };
     471             : 
     472             : // static
     473             : const int RuntimeCallStats::counters_count =
     474             :     arraysize(RuntimeCallStats::counters);
     475             : 
     476             : // static
     477           0 : void RuntimeCallStats::Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer,
     478             :                              CounterId counter_id) {
     479           0 :   CHECK(stats->IsCalledOnTheSameThread());
     480           0 :   RuntimeCallCounter* counter = &(stats->*counter_id);
     481             :   DCHECK_NOT_NULL(counter->name());
     482           0 :   timer->Start(counter, stats->current_timer_.Value());
     483             :   stats->current_timer_.SetValue(timer);
     484             :   stats->current_counter_.SetValue(counter);
     485           0 : }
     486             : 
     487             : // static
     488           0 : void RuntimeCallStats::Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer) {
     489           0 :   CHECK(stats->IsCalledOnTheSameThread());
     490           0 :   if (stats->current_timer_.Value() != timer) {
     491             :     // The branch is added to catch a crash crbug.com/760649
     492           0 :     RuntimeCallTimer* stack_top = stats->current_timer_.Value();
     493             :     EmbeddedVector<char, 200> text;
     494             :     SNPrintF(text, "ERROR: Leaving counter '%s', stack top '%s'.\n",
     495           0 :              timer->name(), stack_top ? stack_top->name() : "(null)");
     496             :     USE(text);
     497           0 :     CHECK(false);
     498             :   }
     499           0 :   stats->current_timer_.SetValue(timer->Stop());
     500           0 :   RuntimeCallTimer* cur_timer = stats->current_timer_.Value();
     501           0 :   stats->current_counter_.SetValue(cur_timer ? cur_timer->counter() : nullptr);
     502           0 : }
     503             : 
     504           0 : void RuntimeCallStats::Add(RuntimeCallStats* other) {
     505           0 :   for (const RuntimeCallStats::CounterId counter_id :
     506           0 :        RuntimeCallStats::counters) {
     507           0 :     RuntimeCallCounter* counter = &(this->*counter_id);
     508           0 :     RuntimeCallCounter* other_counter = &(other->*counter_id);
     509             :     counter->Add(other_counter);
     510             :   }
     511           0 : }
     512             : 
     513             : // static
     514           0 : void RuntimeCallStats::CorrectCurrentCounterId(RuntimeCallStats* stats,
     515             :                                                CounterId counter_id) {
     516             :   RuntimeCallTimer* timer = stats->current_timer_.Value();
     517             :   // When RCS are enabled dynamically there might be no current timer set up.
     518           0 :   if (timer == nullptr) return;
     519           0 :   RuntimeCallCounter* counter = &(stats->*counter_id);
     520             :   timer->set_counter(counter);
     521             :   stats->current_counter_.SetValue(counter);
     522             : }
     523             : 
     524           0 : bool RuntimeCallStats::IsCalledOnTheSameThread() {
     525           0 :   if (!thread_id_.Equals(ThreadId::Invalid()))
     526           0 :     return thread_id_.Equals(ThreadId::Current());
     527           0 :   thread_id_ = ThreadId::Current();
     528           0 :   return true;
     529             : }
     530             : 
     531           0 : void RuntimeCallStats::Print(std::ostream& os) {
     532             :   RuntimeCallStatEntries entries;
     533           0 :   if (current_timer_.Value() != nullptr) {
     534           0 :     current_timer_.Value()->Snapshot();
     535             :   }
     536           0 :   for (const RuntimeCallStats::CounterId counter_id :
     537           0 :        RuntimeCallStats::counters) {
     538           0 :     RuntimeCallCounter* counter = &(this->*counter_id);
     539           0 :     entries.Add(counter);
     540             :   }
     541           0 :   entries.Print(os);
     542           0 : }
     543             : 
     544           0 : void RuntimeCallStats::Reset() {
     545           0 :   if (V8_LIKELY(FLAG_runtime_stats == 0)) return;
     546             : 
     547             :   // In tracing, we only what to trace the time spent on top level trace events,
     548             :   // if runtime counter stack is not empty, we should clear the whole runtime
     549             :   // counter stack, and then reset counters so that we can dump counters into
     550             :   // top level trace events accurately.
     551           0 :   while (current_timer_.Value()) {
     552           0 :     current_timer_.SetValue(current_timer_.Value()->Stop());
     553             :   }
     554             : 
     555           0 :   for (const RuntimeCallStats::CounterId counter_id :
     556           0 :        RuntimeCallStats::counters) {
     557           0 :     RuntimeCallCounter* counter = &(this->*counter_id);
     558           0 :     counter->Reset();
     559             :   }
     560             : 
     561           0 :   in_use_ = true;
     562             : }
     563             : 
     564           0 : void RuntimeCallStats::Dump(v8::tracing::TracedValue* value) {
     565           0 :   for (const RuntimeCallStats::CounterId counter_id :
     566           0 :        RuntimeCallStats::counters) {
     567           0 :     RuntimeCallCounter* counter = &(this->*counter_id);
     568           0 :     if (counter->count() > 0) counter->Dump(value);
     569             :   }
     570             : 
     571           0 :   in_use_ = false;
     572           0 : }
     573             : 
     574             : }  // namespace internal
     575             : }  // namespace v8

Generated by: LCOV version 1.10