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