LCOV - code coverage report
Current view: top level - src - counters.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 149 223 66.8 %
Date: 2019-01-20 Functions: 30 43 69.8 %

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

Generated by: LCOV version 1.10