LCOV - code coverage report
Current view: top level - src - counters.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 136 216 63.0 %
Date: 2019-04-17 Functions: 26 43 60.5 %

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

Generated by: LCOV version 1.10