LCOV - code coverage report
Current view: top level - src - counters.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 144 224 64.3 %
Date: 2019-02-19 Functions: 28 44 63.6 %

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

Generated by: LCOV version 1.10