counters.h 56.8 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_COUNTERS_H_
#define V8_COUNTERS_H_

8 9
#include "include/v8.h"
#include "src/allocation.h"
10
#include "src/base/atomic-utils.h"
11
#include "src/base/platform/elapsed-timer.h"
12
#include "src/base/platform/time.h"
13
#include "src/builtins/builtins.h"
14
#include "src/globals.h"
15
#include "src/isolate.h"
16
#include "src/objects.h"
17
#include "src/runtime/runtime.h"
18
#include "src/tracing/trace-event.h"
19
#include "src/tracing/traced-value.h"
20
#include "src/tracing/tracing-category-observer.h"
21

22 23
namespace v8 {
namespace internal {
24 25 26 27 28

// StatsCounters is an interface for plugging into external
// counters for monitoring.  Counters can be looked up and
// manipulated by name.

29
class StatsTable {
30 31 32
 public:
  // Register an application-defined function where
  // counters can be looked up.
33
  void SetCounterFunction(CounterLookupCallback f) {
34 35 36
    lookup_function_ = f;
  }

37 38
  // Register an application-defined function to create
  // a histogram for passing to the AddHistogramSample function
39
  void SetCreateHistogramFunction(CreateHistogramCallback f) {
40 41 42 43 44
    create_histogram_function_ = f;
  }

  // Register an application-defined function to add a sample
  // to a histogram created with CreateHistogram function
45
  void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
46 47 48
    add_histogram_sample_function_ = f;
  }

49
  bool HasCounterFunction() const {
50 51 52 53 54 55 56 57 58
    return lookup_function_ != NULL;
  }

  // Lookup the location of a counter by name.  If the lookup
  // is successful, returns a non-NULL pointer for writing the
  // value of the counter.  Each thread calling this function
  // may receive a different location to store it's counter.
  // The return value must not be cached and re-used across
  // threads, although a single thread is free to cache it.
59
  int* FindLocation(const char* name) {
60 61 62 63
    if (!lookup_function_) return NULL;
    return lookup_function_(name);
  }

64 65 66 67 68
  // Create a histogram by name. If the create is successful,
  // returns a non-NULL pointer for use with AddHistogramSample
  // function. min and max define the expected minimum and maximum
  // sample values. buckets is the maximum number of buckets
  // that the samples will be grouped into.
69 70 71 72
  void* CreateHistogram(const char* name,
                        int min,
                        int max,
                        size_t buckets) {
73 74 75 76 77 78
    if (!create_histogram_function_) return NULL;
    return create_histogram_function_(name, min, max, buckets);
  }

  // Add a sample to a histogram created with the CreateHistogram
  // function.
79
  void AddHistogramSample(void* histogram, int sample) {
80 81 82 83
    if (!add_histogram_sample_function_) return;
    return add_histogram_sample_function_(histogram, sample);
  }

84
 private:
85 86 87 88 89 90 91 92 93
  StatsTable();

  CounterLookupCallback lookup_function_;
  CreateHistogramCallback create_histogram_function_;
  AddHistogramSampleCallback add_histogram_sample_function_;

  friend class Isolate;

  DISALLOW_COPY_AND_ASSIGN(StatsTable);
94 95 96 97 98 99 100 101 102 103
};

// StatsCounters are dynamically created values which can be tracked in
// the StatsTable.  They are designed to be lightweight to create and
// easy to use.
//
// Internally, a counter represents a value in a row of a StatsTable.
// The row has a 32bit value for each process/thread in the table and also
// a name (stored in the table metadata).  Since the storage location can be
// thread-specific, this class cannot be shared across threads.
104 105 106
class StatsCounter {
 public:
  StatsCounter() { }
107 108
  explicit StatsCounter(Isolate* isolate, const char* name)
      : isolate_(isolate), name_(name), ptr_(NULL), lookup_done_(false) { }
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

  // Sets the counter to a specific value.
  void Set(int value) {
    int* loc = GetPtr();
    if (loc) *loc = value;
  }

  // Increments the counter.
  void Increment() {
    int* loc = GetPtr();
    if (loc) (*loc)++;
  }

  void Increment(int value) {
    int* loc = GetPtr();
    if (loc)
      (*loc) += value;
  }

  // Decrements the counter.
  void Decrement() {
    int* loc = GetPtr();
    if (loc) (*loc)--;
  }

  void Decrement(int value) {
    int* loc = GetPtr();
    if (loc) (*loc) -= value;
  }

  // Is this counter enabled?
  // Returns false if table is full.
  bool Enabled() {
    return GetPtr() != NULL;
  }

  // Get the internal pointer to the counter. This is used
  // by the code generator to emit code that manipulates a
  // given counter without calling the runtime system.
  int* GetInternalPointer() {
    int* loc = GetPtr();
150
    DCHECK(loc != NULL);
151 152 153
    return loc;
  }

154 155 156
  // Reset the cached internal pointer.
  void Reset() { lookup_done_ = false; }

157 158 159
 protected:
  // Returns the cached address of this counter location.
  int* GetPtr() {
160
    if (lookup_done_) return ptr_;
161
    lookup_done_ = true;
162
    ptr_ = FindLocationInStatsTable();
163 164
    return ptr_;
  }
165 166 167

 private:
  int* FindLocationInStatsTable() const;
168

169
  Isolate* isolate_;
170 171 172
  const char* name_;
  int* ptr_;
  bool lookup_done_;
173 174
};

175
// A Histogram represents a dynamically created histogram in the StatsTable.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
// It will be registered with the histogram system on first use.
class Histogram {
 public:
  Histogram() { }
  Histogram(const char* name,
            int min,
            int max,
            int num_buckets,
            Isolate* isolate)
      : name_(name),
        min_(min),
        max_(max),
        num_buckets_(num_buckets),
        histogram_(NULL),
        lookup_done_(false),
        isolate_(isolate) { }
192

193 194
  // Add a single sample to this histogram.
  void AddSample(int sample);
195

196 197 198
  // Returns true if this histogram is enabled.
  bool Enabled() {
    return GetHistogram() != NULL;
199 200
  }

201 202 203 204 205
  // Reset the cached internal pointer.
  void Reset() {
    lookup_done_ = false;
  }

206 207
  const char* name() { return name_; }

208 209 210 211 212
 protected:
  // Returns the handle to the histogram.
  void* GetHistogram() {
    if (!lookup_done_) {
      lookup_done_ = true;
213
      histogram_ = CreateHistogram();
214
    }
215
    return histogram_;
216
  }
217

218 219
  Isolate* isolate() const { return isolate_; }

220 221
 private:
  void* CreateHistogram() const;
222

223 224 225 226 227 228 229 230
  const char* name_;
  int min_;
  int max_;
  int num_buckets_;
  void* histogram_;
  bool lookup_done_;
  Isolate* isolate_;
};
231

232 233 234
// A HistogramTimer allows distributions of results to be created.
class HistogramTimer : public Histogram {
 public:
yangguo's avatar
yangguo committed
235 236 237 238 239 240 241 242 243 244
  enum Resolution {
    MILLISECOND,
    MICROSECOND
  };

  HistogramTimer() {}
  HistogramTimer(const char* name, int min, int max, Resolution resolution,
                 int num_buckets, Isolate* isolate)
      : Histogram(name, min, max, num_buckets, isolate),
        resolution_(resolution) {}
245 246 247 248 249 250 251 252 253

  // Start the timer.
  void Start();

  // Stop the timer and record the results.
  void Stop();

  // Returns true if the timer is running.
  bool Running() {
254
    return Enabled() && timer_.IsStarted();
255
  }
256

257 258
  // TODO(bmeurer): Remove this when HistogramTimerScope is fixed.
#ifdef DEBUG
259
  base::ElapsedTimer* timer() { return &timer_; }
260 261
#endif

262
 private:
263
  base::ElapsedTimer timer_;
yangguo's avatar
yangguo committed
264
  Resolution resolution_;
265 266
};

267
// Helper class for scoping a HistogramTimer.
268 269 270 271
// TODO(bmeurer): The ifdeffery is an ugly hack around the fact that the
// Parser is currently reentrant (when it throws an error, we call back
// into JavaScript and all bets are off), but ElapsedTimer is not
// reentry-safe. Fix this properly and remove |allow_nesting|.
272
class HistogramTimerScope BASE_EMBEDDED {
273
 public:
274 275 276 277 278 279 280 281 282 283
  explicit HistogramTimerScope(HistogramTimer* timer,
                               bool allow_nesting = false)
#ifdef DEBUG
      : timer_(timer),
        skipped_timer_start_(false) {
    if (timer_->timer()->IsStarted() && allow_nesting) {
      skipped_timer_start_ = true;
    } else {
      timer_->Start();
    }
284
  }
285 286
#else
      : timer_(timer) {
287
    timer_->Start();
288
  }
289
#endif
290
  ~HistogramTimerScope() {
291 292 293 294 295
#ifdef DEBUG
    if (!skipped_timer_start_) {
      timer_->Stop();
    }
#else
296
    timer_->Stop();
297
#endif
298
  }
299

300
 private:
301
  HistogramTimer* timer_;
302 303 304
#ifdef DEBUG
  bool skipped_timer_start_;
#endif
305 306
};

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

// A histogram timer that can aggregate events within a larger scope.
//
// Intended use of this timer is to have an outer (aggregating) and an inner
// (to be aggregated) scope, where the inner scope measure the time of events,
// and all those inner scope measurements will be summed up by the outer scope.
// An example use might be to aggregate the time spent in lazy compilation
// while running a script.
//
// Helpers:
// - AggregatingHistogramTimerScope, the "outer" scope within which
//     times will be summed up.
// - AggregatedHistogramTimerScope, the "inner" scope which defines the
//     events to be timed.
class AggregatableHistogramTimer : public Histogram {
 public:
  AggregatableHistogramTimer() {}
  AggregatableHistogramTimer(const char* name, int min, int max,
                             int num_buckets, Isolate* isolate)
      : Histogram(name, min, max, num_buckets, isolate) {}

  // Start/stop the "outer" scope.
  void Start() { time_ = base::TimeDelta(); }
yangguo's avatar
yangguo committed
330
  void Stop() { AddSample(static_cast<int>(time_.InMicroseconds())); }
331 332 333 334 335 336 337 338

  // Add a time value ("inner" scope).
  void Add(base::TimeDelta other) { time_ += other; }

 private:
  base::TimeDelta time_;
};

339
// A helper class for use with AggregatableHistogramTimer. This is the
340 341
// // outer-most timer scope used with an AggregatableHistogramTimer. It will
// // aggregate the information from the inner AggregatedHistogramTimerScope.
342 343 344 345 346 347 348 349 350 351 352 353
class AggregatingHistogramTimerScope {
 public:
  explicit AggregatingHistogramTimerScope(AggregatableHistogramTimer* histogram)
      : histogram_(histogram) {
    histogram_->Start();
  }
  ~AggregatingHistogramTimerScope() { histogram_->Stop(); }

 private:
  AggregatableHistogramTimer* histogram_;
};

354
// A helper class for use with AggregatableHistogramTimer, the "inner" scope
355
// // which defines the events to be timed.
356 357 358 359 360 361 362 363 364 365 366 367 368 369
class AggregatedHistogramTimerScope {
 public:
  explicit AggregatedHistogramTimerScope(AggregatableHistogramTimer* histogram)
      : histogram_(histogram) {
    timer_.Start();
  }
  ~AggregatedHistogramTimerScope() { histogram_->Add(timer_.Elapsed()); }

 private:
  base::ElapsedTimer timer_;
  AggregatableHistogramTimer* histogram_;
};


370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
// AggretatedMemoryHistogram collects (time, value) sample pairs and turns
// them into time-uniform samples for the backing historgram, such that the
// backing histogram receives one sample every T ms, where the T is controlled
// by the FLAG_histogram_interval.
//
// More formally: let F be a real-valued function that maps time to sample
// values. We define F as a linear interpolation between adjacent samples. For
// each time interval [x; x + T) the backing histogram gets one sample value
// that is the average of F(t) in the interval.
template <typename Histogram>
class AggregatedMemoryHistogram {
 public:
  AggregatedMemoryHistogram()
      : is_initialized_(false),
        start_ms_(0.0),
        last_ms_(0.0),
        aggregate_value_(0.0),
        last_value_(0.0),
        backing_histogram_(NULL) {}

  explicit AggregatedMemoryHistogram(Histogram* backing_histogram)
      : AggregatedMemoryHistogram() {
    backing_histogram_ = backing_histogram;
  }

  // Invariants that hold before and after AddSample if
  // is_initialized_ is true:
  //
  // 1) For we processed samples that came in before start_ms_ and sent the
  // corresponding aggregated samples to backing histogram.
  // 2) (last_ms_, last_value_) is the last received sample.
  // 3) last_ms_ < start_ms_ + FLAG_histogram_interval.
  // 4) aggregate_value_ is the average of the function that is constructed by
  // linearly interpolating samples received between start_ms_ and last_ms_.
  void AddSample(double current_ms, double current_value);

 private:
  double Aggregate(double current_ms, double current_value);
  bool is_initialized_;
  double start_ms_;
  double last_ms_;
  double aggregate_value_;
  double last_value_;
  Histogram* backing_histogram_;
};


template <typename Histogram>
void AggregatedMemoryHistogram<Histogram>::AddSample(double current_ms,
                                                     double current_value) {
  if (!is_initialized_) {
    aggregate_value_ = current_value;
    start_ms_ = current_ms;
    last_value_ = current_value;
    last_ms_ = current_ms;
    is_initialized_ = true;
  } else {
    const double kEpsilon = 1e-6;
    const int kMaxSamples = 1000;
    if (current_ms < last_ms_ + kEpsilon) {
      // Two samples have the same time, remember the last one.
      last_value_ = current_value;
    } else {
      double sample_interval_ms = FLAG_histogram_interval;
      double end_ms = start_ms_ + sample_interval_ms;
      if (end_ms <= current_ms + kEpsilon) {
        // Linearly interpolate between the last_ms_ and the current_ms.
        double slope = (current_value - last_value_) / (current_ms - last_ms_);
        int i;
        // Send aggregated samples to the backing histogram from the start_ms
        // to the current_ms.
        for (i = 0; i < kMaxSamples && end_ms <= current_ms + kEpsilon; i++) {
          double end_value = last_value_ + (end_ms - last_ms_) * slope;
          double sample_value;
          if (i == 0) {
            // Take aggregate_value_ into account.
            sample_value = Aggregate(end_ms, end_value);
          } else {
            // There is no aggregate_value_ for i > 0.
            sample_value = (last_value_ + end_value) / 2;
          }
          backing_histogram_->AddSample(static_cast<int>(sample_value + 0.5));
          last_value_ = end_value;
          last_ms_ = end_ms;
          end_ms += sample_interval_ms;
        }
        if (i == kMaxSamples) {
          // We hit the sample limit, ignore the remaining samples.
          aggregate_value_ = current_value;
          start_ms_ = current_ms;
        } else {
          aggregate_value_ = last_value_;
          start_ms_ = last_ms_;
        }
      }
      aggregate_value_ = current_ms > start_ms_ + kEpsilon
                             ? Aggregate(current_ms, current_value)
                             : aggregate_value_;
      last_value_ = current_value;
      last_ms_ = current_ms;
    }
  }
}


template <typename Histogram>
double AggregatedMemoryHistogram<Histogram>::Aggregate(double current_ms,
                                                       double current_value) {
  double interval_ms = current_ms - start_ms_;
  double value = (current_value + last_value_) / 2;
  // The aggregate_value_ is the average for [start_ms_; last_ms_].
  // The value is the average for [last_ms_; current_ms].
  // Return the weighted average of the aggregate_value_ and the value.
  return aggregate_value_ * ((last_ms_ - start_ms_) / interval_ms) +
         value * ((current_ms - last_ms_) / interval_ms);
}

487 488
struct RuntimeCallCounter {
  explicit RuntimeCallCounter(const char* name) : name(name) {}
489
  V8_NOINLINE void Reset();
490
  V8_NOINLINE void Dump(v8::tracing::TracedValue* value);
491
  void Add(RuntimeCallCounter* other);
492 493 494 495 496 497 498 499 500 501

  const char* name;
  int64_t count = 0;
  base::TimeDelta time;
};

// RuntimeCallTimer is used to keep track of the stack of currently active
// timers used for properly measuring the own time of a RuntimeCallCounter.
class RuntimeCallTimer {
 public:
502 503
  RuntimeCallCounter* counter() { return counter_; }
  base::ElapsedTimer timer() { return timer_; }
504
  RuntimeCallTimer* parent() const { return parent_.Value(); }
505 506 507 508 509

 private:
  friend class RuntimeCallStats;

  inline void Start(RuntimeCallCounter* counter, RuntimeCallTimer* parent) {
510
    counter_ = counter;
511
    parent_.SetValue(parent);
512 513 514 515
    if (FLAG_runtime_stats !=
        v8::tracing::TracingCategoryObserver::ENABLED_BY_SAMPLING) {
      timer_.Start();
    }
516 517 518
  }

  inline RuntimeCallTimer* Stop() {
519
    if (!timer_.IsStarted()) return parent();
520
    base::TimeDelta delta = timer_.Elapsed();
521
    timer_.Stop();
522
    counter_->count++;
523
    counter_->time += delta;
524
    if (parent()) {
525
      // Adjust parent timer so that it does not include sub timer's time.
526
      parent()->counter_->time -= delta;
527
    }
528
    return parent();
529 530
  }

531 532 533
  inline void Elapsed() {
    base::TimeDelta delta = timer_.Elapsed();
    counter_->time += delta;
534 535 536
    if (parent()) {
      parent()->counter_->time -= delta;
      parent()->Elapsed();
537 538 539 540
    }
    timer_.Restart();
  }

541 542
  const char* name() { return counter_->name; }

543
  RuntimeCallCounter* counter_ = nullptr;
544
  base::AtomicValue<RuntimeCallTimer*> parent_;
545 546 547
  base::ElapsedTimer timer_;
};

548 549 550 551 552 553 554 555 556
#define FOR_EACH_API_COUNTER(V)                            \
  V(ArrayBuffer_Cast)                                      \
  V(ArrayBuffer_Neuter)                                    \
  V(ArrayBuffer_New)                                       \
  V(Array_CloneElementAt)                                  \
  V(Array_New)                                             \
  V(BooleanObject_BooleanValue)                            \
  V(BooleanObject_New)                                     \
  V(Context_New)                                           \
557
  V(Context_NewRemoteContext)                              \
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
  V(DataView_New)                                          \
  V(Date_DateTimeConfigurationChangeNotification)          \
  V(Date_New)                                              \
  V(Date_NumberValue)                                      \
  V(Debug_Call)                                            \
  V(Debug_GetMirror)                                       \
  V(Error_New)                                             \
  V(External_New)                                          \
  V(Float32Array_New)                                      \
  V(Float64Array_New)                                      \
  V(Function_Call)                                         \
  V(Function_New)                                          \
  V(Function_NewInstance)                                  \
  V(FunctionTemplate_GetFunction)                          \
  V(FunctionTemplate_New)                                  \
573
  V(FunctionTemplate_NewRemoteInstance)                    \
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
  V(FunctionTemplate_NewWithFastHandler)                   \
  V(Int16Array_New)                                        \
  V(Int32Array_New)                                        \
  V(Int8Array_New)                                         \
  V(JSON_Parse)                                            \
  V(JSON_Stringify)                                        \
  V(Map_AsArray)                                           \
  V(Map_Clear)                                             \
  V(Map_Delete)                                            \
  V(Map_Get)                                               \
  V(Map_Has)                                               \
  V(Map_New)                                               \
  V(Map_Set)                                               \
  V(Message_GetEndColumn)                                  \
  V(Message_GetLineNumber)                                 \
  V(Message_GetSourceLine)                                 \
  V(Message_GetStartColumn)                                \
591 592
  V(Module_Evaluate)                                       \
  V(Module_Instantiate)                                    \
593 594 595 596 597 598
  V(NumberObject_New)                                      \
  V(NumberObject_NumberValue)                              \
  V(Object_CallAsConstructor)                              \
  V(Object_CallAsFunction)                                 \
  V(Object_CreateDataProperty)                             \
  V(Object_DefineOwnProperty)                              \
599
  V(Object_DefineProperty)                                 \
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
  V(Object_Delete)                                         \
  V(Object_DeleteProperty)                                 \
  V(Object_ForceSet)                                       \
  V(Object_Get)                                            \
  V(Object_GetOwnPropertyDescriptor)                       \
  V(Object_GetOwnPropertyNames)                            \
  V(Object_GetPropertyAttributes)                          \
  V(Object_GetPropertyNames)                               \
  V(Object_GetRealNamedProperty)                           \
  V(Object_GetRealNamedPropertyAttributes)                 \
  V(Object_GetRealNamedPropertyAttributesInPrototypeChain) \
  V(Object_GetRealNamedPropertyInPrototypeChain)           \
  V(Object_HasOwnProperty)                                 \
  V(Object_HasRealIndexedProperty)                         \
  V(Object_HasRealNamedCallbackProperty)                   \
  V(Object_HasRealNamedProperty)                           \
  V(Object_Int32Value)                                     \
  V(Object_IntegerValue)                                   \
  V(Object_New)                                            \
  V(Object_NumberValue)                                    \
  V(Object_ObjectProtoToString)                            \
  V(Object_Set)                                            \
  V(Object_SetAccessor)                                    \
  V(Object_SetIntegrityLevel)                              \
  V(Object_SetPrivate)                                     \
  V(Object_SetPrototype)                                   \
  V(ObjectTemplate_New)                                    \
  V(ObjectTemplate_NewInstance)                            \
  V(Object_ToArrayIndex)                                   \
  V(Object_ToDetailString)                                 \
  V(Object_ToInt32)                                        \
  V(Object_ToInteger)                                      \
  V(Object_ToNumber)                                       \
  V(Object_ToObject)                                       \
  V(Object_ToString)                                       \
  V(Object_ToUint32)                                       \
  V(Object_Uint32Value)                                    \
  V(Persistent_New)                                        \
  V(Private_New)                                           \
  V(Promise_Catch)                                         \
  V(Promise_Chain)                                         \
  V(Promise_HasRejectHandler)                              \
  V(Promise_Resolver_New)                                  \
  V(Promise_Resolver_Resolve)                              \
  V(Promise_Then)                                          \
  V(Proxy_New)                                             \
  V(RangeError_New)                                        \
  V(ReferenceError_New)                                    \
  V(RegExp_New)                                            \
  V(ScriptCompiler_Compile)                                \
  V(ScriptCompiler_CompileFunctionInContext)               \
  V(ScriptCompiler_CompileUnbound)                         \
  V(Script_Run)                                            \
  V(Set_Add)                                               \
  V(Set_AsArray)                                           \
  V(Set_Clear)                                             \
  V(Set_Delete)                                            \
  V(Set_Has)                                               \
  V(Set_New)                                               \
  V(SharedArrayBuffer_New)                                 \
  V(String_Concat)                                         \
  V(String_NewExternalOneByte)                             \
  V(String_NewExternalTwoByte)                             \
  V(String_NewFromOneByte)                                 \
  V(String_NewFromTwoByte)                                 \
  V(String_NewFromUtf8)                                    \
  V(StringObject_New)                                      \
  V(StringObject_StringValue)                              \
  V(String_Write)                                          \
  V(String_WriteUtf8)                                      \
  V(Symbol_New)                                            \
  V(SymbolObject_New)                                      \
  V(SymbolObject_SymbolValue)                              \
  V(SyntaxError_New)                                       \
  V(TryCatch_StackTrace)                                   \
  V(TypeError_New)                                         \
  V(Uint16Array_New)                                       \
  V(Uint32Array_New)                                       \
  V(Uint8Array_New)                                        \
  V(Uint8ClampedArray_New)                                 \
  V(UnboundScript_GetId)                                   \
  V(UnboundScript_GetLineNumber)                           \
  V(UnboundScript_GetName)                                 \
  V(UnboundScript_GetSourceMappingURL)                     \
  V(UnboundScript_GetSourceURL)                            \
685
  V(Value_TypeOf)                                          \
686
  V(ValueDeserializer_ReadHeader)                          \
687 688
  V(ValueDeserializer_ReadValue)                           \
  V(ValueSerializer_WriteValue)
689 690 691 692

#define FOR_EACH_MANUAL_COUNTER(V)                  \
  V(AccessorGetterCallback)                         \
  V(AccessorNameGetterCallback)                     \
693 694 695 696 697
  V(AccessorNameGetterCallback_ArrayLength)         \
  V(AccessorNameGetterCallback_BoundFunctionLength) \
  V(AccessorNameGetterCallback_BoundFunctionName)   \
  V(AccessorNameGetterCallback_FunctionPrototype)   \
  V(AccessorNameGetterCallback_StringLength)        \
698 699 700
  V(AccessorNameSetterCallback)                     \
  V(Compile)                                        \
  V(CompileCode)                                    \
701
  V(CompileCodeLazy)                                \
702 703 704 705
  V(CompileDeserialize)                             \
  V(CompileEval)                                    \
  V(CompileFullCode)                                \
  V(CompileIgnition)                                \
706
  V(CompilerDispatcher)                             \
707 708 709 710
  V(CompileSerialize)                               \
  V(DeoptimizeCode)                                 \
  V(FunctionCallback)                               \
  V(GC)                                             \
711
  V(GenericNamedPropertyDefinerCallback)            \
712
  V(GenericNamedPropertyDeleterCallback)            \
713
  V(GenericNamedPropertyDescriptorCallback)         \
714 715
  V(GenericNamedPropertyQueryCallback)              \
  V(GenericNamedPropertySetterCallback)             \
716
  V(IndexedPropertyDefinerCallback)                 \
717
  V(IndexedPropertyDeleterCallback)                 \
718
  V(IndexedPropertyDescriptorCallback)              \
719 720 721
  V(IndexedPropertyGetterCallback)                  \
  V(IndexedPropertyQueryCallback)                   \
  V(IndexedPropertySetterCallback)                  \
722
  V(InvokeApiInterruptCallbacks)                    \
723 724 725 726 727 728 729
  V(InvokeFunctionCallback)                         \
  V(JS_Execution)                                   \
  V(Map_SetPrototype)                               \
  V(Map_TransitionToAccessorProperty)               \
  V(Map_TransitionToDataProperty)                   \
  V(Object_DeleteProperty)                          \
  V(OptimizeCode)                                   \
730
  V(ParseArrowFunctionLiteral)                      \
731 732
  V(ParseBackgroundArrowFunctionLiteral)            \
  V(ParseBackgroundFunctionLiteral)                 \
733
  V(ParseEval)                                      \
734
  V(ParseFunction)                                  \
735 736 737
  V(ParseFunctionLiteral)                           \
  V(ParseProgram)                                   \
  V(PreParseArrowFunctionLiteral)                   \
738 739 740
  V(PreParseBackgroundArrowFunctionLiteral)         \
  V(PreParseBackgroundNoVariableResolution)         \
  V(PreParseBackgroundWithVariableResolution)       \
741 742
  V(PreParseNoVariableResolution)                   \
  V(PreParseWithVariableResolution)                 \
743 744 745 746 747 748 749 750
  V(PropertyCallback)                               \
  V(PrototypeMap_TransitionToAccessorProperty)      \
  V(PrototypeMap_TransitionToDataProperty)          \
  V(PrototypeObject_DeleteProperty)                 \
  V(RecompileConcurrent)                            \
  V(RecompileSynchronous)                           \
  /* Dummy counter for the unexpected stub miss. */ \
  V(UnexpectedStubMiss)
751

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
#define FOR_EACH_HANDLER_COUNTER(V)              \
  V(IC_HandlerCacheHit)                          \
  V(KeyedLoadIC_LoadIndexedStringStub)           \
  V(KeyedLoadIC_LoadIndexedInterceptorStub)      \
  V(KeyedLoadIC_KeyedLoadSloppyArgumentsStub)    \
  V(KeyedLoadIC_LoadElementDH)                   \
  V(KeyedLoadIC_LoadFastElementStub)             \
  V(KeyedLoadIC_LoadDictionaryElementStub)       \
  V(KeyedLoadIC_SlowStub)                        \
  V(KeyedStoreIC_ElementsTransitionAndStoreStub) \
  V(KeyedStoreIC_KeyedStoreSloppyArgumentsStub)  \
  V(KeyedStoreIC_SlowStub)                       \
  V(KeyedStoreIC_StoreFastElementStub)           \
  V(KeyedStoreIC_StoreElementStub)               \
  V(LoadIC_FunctionPrototypeStub)                \
  V(LoadIC_HandlerCacheHit_AccessCheck)          \
  V(LoadIC_HandlerCacheHit_Exotic)               \
  V(LoadIC_HandlerCacheHit_Interceptor)          \
  V(LoadIC_HandlerCacheHit_JSProxy)              \
  V(LoadIC_HandlerCacheHit_NonExistent)          \
  V(LoadIC_HandlerCacheHit_Accessor)             \
  V(LoadIC_HandlerCacheHit_Data)                 \
  V(LoadIC_HandlerCacheHit_Transition)           \
  V(LoadIC_LoadApiGetterDH)                      \
  V(LoadIC_LoadApiGetterFromPrototypeDH)         \
  V(LoadIC_LoadApiGetterStub)                    \
  V(LoadIC_LoadCallback)                         \
  V(LoadIC_LoadConstantDH)                       \
  V(LoadIC_LoadConstantFromPrototypeDH)          \
  V(LoadIC_LoadConstant)                         \
  V(LoadIC_LoadConstantStub)                     \
  V(LoadIC_LoadFieldDH)                          \
  V(LoadIC_LoadFieldFromPrototypeDH)             \
  V(LoadIC_LoadField)                            \
  V(LoadIC_LoadFieldStub)                        \
  V(LoadIC_LoadGlobal)                           \
  V(LoadIC_LoadInterceptor)                      \
  V(LoadIC_LoadNonexistentDH)                    \
  V(LoadIC_LoadNonexistent)                      \
  V(LoadIC_LoadNormal)                           \
  V(LoadIC_LoadScriptContextFieldStub)           \
  V(LoadIC_LoadViaGetter)                        \
  V(LoadIC_Premonomorphic)                       \
  V(LoadIC_SlowStub)                             \
  V(LoadIC_StringLengthStub)                     \
  V(StoreIC_HandlerCacheHit_AccessCheck)         \
  V(StoreIC_HandlerCacheHit_Exotic)              \
  V(StoreIC_HandlerCacheHit_Interceptor)         \
  V(StoreIC_HandlerCacheHit_JSProxy)             \
  V(StoreIC_HandlerCacheHit_NonExistent)         \
  V(StoreIC_HandlerCacheHit_Accessor)            \
  V(StoreIC_HandlerCacheHit_Data)                \
  V(StoreIC_HandlerCacheHit_Transition)          \
  V(StoreIC_Premonomorphic)                      \
  V(StoreIC_SlowStub)                            \
  V(StoreIC_StoreCallback)                       \
  V(StoreIC_StoreField)                          \
  V(StoreIC_StoreFieldDH)                        \
  V(StoreIC_StoreFieldStub)                      \
  V(StoreIC_StoreGlobal)                         \
  V(StoreIC_StoreGlobalTransition)               \
  V(StoreIC_StoreInterceptorStub)                \
  V(StoreIC_StoreNormal)                         \
  V(StoreIC_StoreScriptContextFieldStub)         \
  V(StoreIC_StoreTransition)                     \
817
  V(StoreIC_StoreTransitionDH)                   \
818 819
  V(StoreIC_StoreViaSetter)

820
class RuntimeCallStats : public ZoneObject {
821 822 823
 public:
  typedef RuntimeCallCounter RuntimeCallStats::*CounterId;

824 825 826 827
#define CALL_RUNTIME_COUNTER(name) \
  RuntimeCallCounter name = RuntimeCallCounter(#name);
  FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)
#undef CALL_RUNTIME_COUNTER
828 829 830 831
#define CALL_RUNTIME_COUNTER(name, nargs, ressize) \
  RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name);
  FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)
#undef CALL_RUNTIME_COUNTER
832
#define CALL_BUILTIN_COUNTER(name) \
833 834 835
  RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name);
  BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)
#undef CALL_BUILTIN_COUNTER
836 837 838 839
#define CALL_BUILTIN_COUNTER(name) \
  RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name);
  FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER)
#undef CALL_BUILTIN_COUNTER
840 841 842 843
#define CALL_BUILTIN_COUNTER(name) \
  RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name);
  FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)
#undef CALL_BUILTIN_COUNTER
844

845 846
  static const CounterId counters[];

847 848
  // Starting measuring the time for a function. This will establish the
  // connection to the parent counter for properly calculating the own times.
849
  static void Enter(RuntimeCallStats* stats, RuntimeCallTimer* timer,
850 851
                    CounterId counter_id);

852 853 854
  // Leave a scope for a measured runtime function. This will properly add
  // the time delta to the current_counter and subtract the delta from its
  // parent.
855
  static void Leave(RuntimeCallStats* stats, RuntimeCallTimer* timer);
856

857 858
  // Set counter id for the innermost measurement. It can be used to refine
  // event kind when a runtime entry counter is too generic.
859 860
  static void CorrectCurrentCounterId(RuntimeCallStats* stats,
                                      CounterId counter_id);
861

862
  void Reset();
863 864
  // Add all entries from another stats object.
  void Add(RuntimeCallStats* other);
865
  void Print(std::ostream& os);
866
  V8_NOINLINE void Dump(v8::tracing::TracedValue* value);
867 868 869 870 871

  RuntimeCallStats() {
    Reset();
    in_use_ = false;
  }
872

873
  RuntimeCallTimer* current_timer() { return current_timer_.Value(); }
874
  bool InUse() { return in_use_; }
875 876 877

 private:
  // Counter to track recursive time events.
878
  base::AtomicValue<RuntimeCallTimer*> current_timer_;
879
  // Used to track nested tracing scopes.
880
  bool in_use_;
881 882
};

883 884 885 886 887 888
#define CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats, counter_name) \
  do {                                                                   \
    if (V8_UNLIKELY(FLAG_runtime_stats)) {                               \
      RuntimeCallStats::CorrectCurrentCounterId(                         \
          runtime_call_stats, &RuntimeCallStats::counter_name);          \
    }                                                                    \
889 890
  } while (false)

891 892 893
#define TRACE_HANDLER_STATS(isolate, counter_name)                          \
  CHANGE_CURRENT_RUNTIME_COUNTER(isolate->counters()->runtime_call_stats(), \
                                 Handler_##counter_name)
894

895 896
#define HISTOGRAM_RANGE_LIST(HR)                                              \
  /* Generic range histograms */                                              \
897
  HR(detached_context_age_in_gc, V8.DetachedContextAgeInGC, 0, 20, 21)        \
898 899
  HR(gc_idle_time_allotted_in_ms, V8.GCIdleTimeAllottedInMS, 0, 10000, 101)   \
  HR(gc_idle_time_limit_overshot, V8.GCIdleTimeLimit.Overshot, 0, 10000, 101) \
900 901
  HR(gc_idle_time_limit_undershot, V8.GCIdleTimeLimit.Undershot, 0, 10000,    \
     101)                                                                     \
902
  HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6)             \
903
  HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20)        \
904
  HR(debug_feature_usage, V8.DebugFeatureUsage, 1, 7, 7)                      \
905 906 907
  HR(incremental_marking_reason, V8.GCIncrementalMarkingReason, 0, 21, 22)    \
  HR(mark_compact_reason, V8.GCMarkCompactReason, 0, 21, 22)                  \
  HR(scavenge_reason, V8.GCScavengeReason, 0, 21, 22)                         \
908
  /* Asm/Wasm. */                                                             \
909
  HR(wasm_functions_per_module, V8.WasmFunctionsPerModule, 1, 10000, 51)
910

911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
#define HISTOGRAM_TIMER_LIST(HT)                                               \
  /* Garbage collection timers. */                                             \
  HT(gc_compactor, V8.GCCompactor, 10000, MILLISECOND)                         \
  HT(gc_finalize, V8.GCFinalizeMC, 10000, MILLISECOND)                         \
  HT(gc_finalize_reduce_memory, V8.GCFinalizeMCReduceMemory, 10000,            \
     MILLISECOND)                                                              \
  HT(gc_scavenger, V8.GCScavenger, 10000, MILLISECOND)                         \
  HT(gc_context, V8.GCContext, 10000,                                          \
     MILLISECOND) /* GC context cleanup time */                                \
  HT(gc_idle_notification, V8.GCIdleNotification, 10000, MILLISECOND)          \
  HT(gc_incremental_marking, V8.GCIncrementalMarking, 10000, MILLISECOND)      \
  HT(gc_incremental_marking_start, V8.GCIncrementalMarkingStart, 10000,        \
     MILLISECOND)                                                              \
  HT(gc_incremental_marking_finalize, V8.GCIncrementalMarkingFinalize, 10000,  \
     MILLISECOND)                                                              \
  HT(gc_low_memory_notification, V8.GCLowMemoryNotification, 10000,            \
     MILLISECOND)                                                              \
  /* Compilation times. */                                                     \
  HT(compile, V8.CompileMicroSeconds, 1000000, MICROSECOND)                    \
  HT(compile_eval, V8.CompileEvalMicroSeconds, 1000000, MICROSECOND)           \
  /* Serialization as part of compilation (code caching) */                    \
  HT(compile_serialize, V8.CompileSerializeMicroSeconds, 100000, MICROSECOND)  \
  HT(compile_deserialize, V8.CompileDeserializeMicroSeconds, 1000000,          \
     MICROSECOND)                                                              \
  /* Total compilation time incl. caching/parsing */                           \
  HT(compile_script, V8.CompileScriptMicroSeconds, 1000000, MICROSECOND)       \
  /* Total JavaScript execution time (including callbacks and runtime calls */ \
  HT(execute, V8.Execute, 1000000, MICROSECOND)                                \
  /* Asm/Wasm */                                                               \
  HT(wasm_instantiate_module_time, V8.WasmInstantiateModuleMicroSeconds,       \
     1000000, MICROSECOND)                                                     \
  HT(wasm_decode_module_time, V8.WasmDecodeModuleMicroSeconds, 1000000,        \
     MICROSECOND)                                                              \
  HT(wasm_decode_function_time, V8.WasmDecodeFunctionMicroSeconds, 1000000,    \
     MICROSECOND)                                                              \
  HT(wasm_compile_module_time, V8.WasmCompileModuleMicroSeconds, 1000000,      \
     MICROSECOND)                                                              \
  HT(wasm_compile_function_time, V8.WasmCompileFunctionMicroSeconds, 1000000,  \
949
     MICROSECOND)
950

951
#define AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT) \
yangguo's avatar
yangguo committed
952
  AHT(compile_lazy, V8.CompileLazyMicroSeconds)
953

954 955 956
#define HISTOGRAM_PERCENTAGE_LIST(HP)                                          \
  /* Heap fragmentation. */                                                    \
  HP(external_fragmentation_total, V8.MemoryExternalFragmentationTotal)        \
957
  HP(external_fragmentation_old_space, V8.MemoryExternalFragmentationOldSpace) \
958 959 960 961 962 963
  HP(external_fragmentation_code_space,                                        \
     V8.MemoryExternalFragmentationCodeSpace)                                  \
  HP(external_fragmentation_map_space, V8.MemoryExternalFragmentationMapSpace) \
  HP(external_fragmentation_lo_space, V8.MemoryExternalFragmentationLoSpace)   \
  /* Percentages of heap committed to each space. */                           \
  HP(heap_fraction_new_space, V8.MemoryHeapFractionNewSpace)                   \
964
  HP(heap_fraction_old_space, V8.MemoryHeapFractionOldSpace)                   \
965 966
  HP(heap_fraction_code_space, V8.MemoryHeapFractionCodeSpace)                 \
  HP(heap_fraction_map_space, V8.MemoryHeapFractionMapSpace)                   \
967
  HP(heap_fraction_lo_space, V8.MemoryHeapFractionLoSpace)
968

969 970 971 972 973 974 975
#define HISTOGRAM_LEGACY_MEMORY_LIST(HM)                                      \
  HM(heap_sample_total_committed, V8.MemoryHeapSampleTotalCommitted)          \
  HM(heap_sample_total_used, V8.MemoryHeapSampleTotalUsed)                    \
  HM(heap_sample_map_space_committed, V8.MemoryHeapSampleMapSpaceCommitted)   \
  HM(heap_sample_code_space_committed, V8.MemoryHeapSampleCodeSpaceCommitted) \
  HM(heap_sample_maximum_committed, V8.MemoryHeapSampleMaximumCommitted)

976 977 978 979 980 981 982 983 984 985
#define HISTOGRAM_MEMORY_LIST(HM)                                              \
  HM(memory_heap_committed, V8.MemoryHeapCommitted)                            \
  HM(memory_heap_used, V8.MemoryHeapUsed)                                      \
  /* Asm/Wasm */                                                               \
  HM(wasm_decode_module_peak_memory_bytes, V8.WasmDecodeModulePeakMemoryBytes) \
  HM(wasm_compile_function_peak_memory_bytes,                                  \
     V8.WasmCompileFunctionPeakMemoryBytes)                                    \
  HM(wasm_min_mem_pages_count, V8.WasmMinMemPagesCount)                        \
  HM(wasm_max_mem_pages_count, V8.WasmMaxMemPagesCount)                        \
  HM(wasm_function_size_bytes, V8.WasmFunctionSizeBytes)                       \
986
  HM(wasm_module_size_bytes, V8.WasmModuleSizeBytes)
987 988 989 990 991 992 993 994 995 996 997

// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
// Intellisense to crash.  It was broken into two macros (each of length 40
// lines) rather than one macro (of length about 80 lines) to work around
// this problem.  Please avoid using recursive macros of this length when
// possible.
#define STATS_COUNTER_LIST_1(SC)                                      \
  /* Global Handle Count*/                                            \
  SC(global_handles, V8.GlobalHandles)                                \
  /* OS Memory allocated */                                           \
  SC(memory_allocated, V8.OsMemoryAllocated)                          \
cbruni's avatar
cbruni committed
998 999 1000
  SC(maps_normalized, V8.MapsNormalized)                            \
  SC(maps_created, V8.MapsCreated)                                  \
  SC(elements_transitions, V8.ObjectElementsTransitions)            \
1001 1002 1003 1004 1005 1006 1007 1008
  SC(props_to_dictionary, V8.ObjectPropertiesToDictionary)            \
  SC(elements_to_dictionary, V8.ObjectElementsToDictionary)           \
  SC(alive_after_last_gc, V8.AliveAfterLastGC)                        \
  SC(objs_since_last_young, V8.ObjsSinceLastYoung)                    \
  SC(objs_since_last_full, V8.ObjsSinceLastFull)                      \
  SC(string_table_capacity, V8.StringTableCapacity)                   \
  SC(number_of_symbols, V8.NumberOfSymbols)                           \
  SC(script_wrappers, V8.ScriptWrappers)                              \
1009
  SC(inlined_copied_elements, V8.InlinedCopiedElements)               \
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
  SC(arguments_adaptors, V8.ArgumentsAdaptors)                        \
  SC(compilation_cache_hits, V8.CompilationCacheHits)                 \
  SC(compilation_cache_misses, V8.CompilationCacheMisses)             \
  /* Amount of evaled source code. */                                 \
  SC(total_eval_size, V8.TotalEvalSize)                               \
  /* Amount of loaded source code. */                                 \
  SC(total_load_size, V8.TotalLoadSize)                               \
  /* Amount of parsed source code. */                                 \
  SC(total_parse_size, V8.TotalParseSize)                             \
  /* Amount of source code skipped over using preparsing. */          \
  SC(total_preparse_skipped, V8.TotalPreparseSkipped)                 \
  /* Amount of compiled source code. */                               \
  SC(total_compile_size, V8.TotalCompileSize)                         \
  /* Amount of source code compiled with the full codegen. */         \
  SC(total_full_codegen_source_size, V8.TotalFullCodegenSourceSize)   \
  /* Number of contexts created from scratch. */                      \
  SC(contexts_created_from_scratch, V8.ContextsCreatedFromScratch)    \
  /* Number of contexts created by partial snapshot. */               \
  SC(contexts_created_by_snapshot, V8.ContextsCreatedBySnapshot)      \
  /* Number of code objects found from pc. */                         \
  SC(pc_to_code, V8.PcToCode)                                         \
  SC(pc_to_code_cached, V8.PcToCodeCached)                            \
  /* The store-buffer implementation of the write barrier. */         \
  SC(store_buffer_overflows, V8.StoreBufferOverflows)

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
#define STATS_COUNTER_LIST_2(SC)                                               \
  /* Number of code stubs. */                                                  \
  SC(code_stubs, V8.CodeStubs)                                                 \
  /* Amount of stub code. */                                                   \
  SC(total_stubs_code_size, V8.TotalStubsCodeSize)                             \
  /* Amount of (JS) compiled code. */                                          \
  SC(total_compiled_code_size, V8.TotalCompiledCodeSize)                       \
  SC(gc_compactor_caused_by_request, V8.GCCompactorCausedByRequest)            \
  SC(gc_compactor_caused_by_promoted_data, V8.GCCompactorCausedByPromotedData) \
  SC(gc_compactor_caused_by_oldspace_exhaustion,                               \
     V8.GCCompactorCausedByOldspaceExhaustion)                                 \
  SC(gc_last_resort_from_js, V8.GCLastResortFromJS)                            \
  SC(gc_last_resort_from_handles, V8.GCLastResortFromHandles)                  \
cbruni's avatar
cbruni committed
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
  SC(ic_keyed_load_generic_smi, V8.ICKeyedLoadGenericSmi)                      \
  SC(ic_keyed_load_generic_symbol, V8.ICKeyedLoadGenericSymbol)                \
  SC(ic_keyed_load_generic_slow, V8.ICKeyedLoadGenericSlow)                    \
  SC(ic_named_load_global_stub, V8.ICNamedLoadGlobalStub)                      \
  SC(ic_store_normal_miss, V8.ICStoreNormalMiss)                               \
  SC(ic_store_normal_hit, V8.ICStoreNormalHit)                                 \
  SC(ic_binary_op_miss, V8.ICBinaryOpMiss)                                     \
  SC(ic_compare_miss, V8.ICCompareMiss)                                        \
  SC(ic_call_miss, V8.ICCallMiss)                                              \
  SC(ic_keyed_call_miss, V8.ICKeyedCallMiss)                                   \
  SC(ic_load_miss, V8.ICLoadMiss)                                              \
  SC(ic_keyed_load_miss, V8.ICKeyedLoadMiss)                                   \
  SC(ic_store_miss, V8.ICStoreMiss)                                            \
  SC(ic_keyed_store_miss, V8.ICKeyedStoreMiss)                                 \
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
  SC(cow_arrays_created_runtime, V8.COWArraysCreatedRuntime)                   \
  SC(cow_arrays_converted, V8.COWArraysConverted)                              \
  SC(constructed_objects, V8.ConstructedObjects)                               \
  SC(constructed_objects_runtime, V8.ConstructedObjectsRuntime)                \
  SC(negative_lookups, V8.NegativeLookups)                                     \
  SC(negative_lookups_miss, V8.NegativeLookupsMiss)                            \
  SC(megamorphic_stub_cache_probes, V8.MegamorphicStubCacheProbes)             \
  SC(megamorphic_stub_cache_misses, V8.MegamorphicStubCacheMisses)             \
  SC(megamorphic_stub_cache_updates, V8.MegamorphicStubCacheUpdates)           \
  SC(enum_cache_hits, V8.EnumCacheHits)                                        \
  SC(enum_cache_misses, V8.EnumCacheMisses)                                    \
  SC(fast_new_closure_total, V8.FastNewClosureTotal)                           \
  SC(string_add_runtime, V8.StringAddRuntime)                                  \
  SC(string_add_native, V8.StringAddNative)                                    \
  SC(string_add_runtime_ext_to_one_byte, V8.StringAddRuntimeExtToOneByte)      \
  SC(sub_string_runtime, V8.SubStringRuntime)                                  \
  SC(sub_string_native, V8.SubStringNative)                                    \
  SC(string_compare_native, V8.StringCompareNative)                            \
  SC(string_compare_runtime, V8.StringCompareRuntime)                          \
  SC(regexp_entry_runtime, V8.RegExpEntryRuntime)                              \
  SC(regexp_entry_native, V8.RegExpEntryNative)                                \
  SC(number_to_string_native, V8.NumberToStringNative)                         \
  SC(number_to_string_runtime, V8.NumberToStringRuntime)                       \
cbruni's avatar
cbruni committed
1085 1086 1087
  SC(math_exp_runtime, V8.MathExpRuntime)                                      \
  SC(math_log_runtime, V8.MathLogRuntime)                                      \
  SC(math_pow_runtime, V8.MathPowRuntime)                                      \
1088 1089
  SC(stack_interrupts, V8.StackInterrupts)                                     \
  SC(runtime_profiler_ticks, V8.RuntimeProfilerTicks)                          \
1090
  SC(runtime_calls, V8.RuntimeCalls)                                           \
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
  SC(bounds_checks_eliminated, V8.BoundsChecksEliminated)                      \
  SC(bounds_checks_hoisted, V8.BoundsChecksHoisted)                            \
  SC(soft_deopts_requested, V8.SoftDeoptsRequested)                            \
  SC(soft_deopts_inserted, V8.SoftDeoptsInserted)                              \
  SC(soft_deopts_executed, V8.SoftDeoptsExecuted)                              \
  /* Number of write barriers in generated code. */                            \
  SC(write_barriers_dynamic, V8.WriteBarriersDynamic)                          \
  SC(write_barriers_static, V8.WriteBarriersStatic)                            \
  SC(new_space_bytes_available, V8.MemoryNewSpaceBytesAvailable)               \
  SC(new_space_bytes_committed, V8.MemoryNewSpaceBytesCommitted)               \
  SC(new_space_bytes_used, V8.MemoryNewSpaceBytesUsed)                         \
1102 1103 1104
  SC(old_space_bytes_available, V8.MemoryOldSpaceBytesAvailable)               \
  SC(old_space_bytes_committed, V8.MemoryOldSpaceBytesCommitted)               \
  SC(old_space_bytes_used, V8.MemoryOldSpaceBytesUsed)                         \
1105 1106 1107 1108 1109 1110 1111 1112
  SC(code_space_bytes_available, V8.MemoryCodeSpaceBytesAvailable)             \
  SC(code_space_bytes_committed, V8.MemoryCodeSpaceBytesCommitted)             \
  SC(code_space_bytes_used, V8.MemoryCodeSpaceBytesUsed)                       \
  SC(map_space_bytes_available, V8.MemoryMapSpaceBytesAvailable)               \
  SC(map_space_bytes_committed, V8.MemoryMapSpaceBytesCommitted)               \
  SC(map_space_bytes_used, V8.MemoryMapSpaceBytesUsed)                         \
  SC(lo_space_bytes_available, V8.MemoryLoSpaceBytesAvailable)                 \
  SC(lo_space_bytes_committed, V8.MemoryLoSpaceBytesCommitted)                 \
1113 1114 1115 1116
  SC(lo_space_bytes_used, V8.MemoryLoSpaceBytesUsed)                           \
  SC(turbo_escape_allocs_replaced, V8.TurboEscapeAllocsReplaced)               \
  SC(crankshaft_escape_allocs_replaced, V8.CrankshaftEscapeAllocsReplaced)     \
  SC(turbo_escape_loads_replaced, V8.TurboEscapeLoadsReplaced)                 \
1117 1118 1119 1120
  SC(crankshaft_escape_loads_replaced, V8.CrankshaftEscapeLoadsReplaced)       \
  /* Total code size (including metadata) of baseline code or bytecode. */     \
  SC(total_baseline_code_size, V8.TotalBaselineCodeSize)                       \
  /* Total count of functions compiled using the baseline compiler. */         \
1121 1122 1123
  SC(total_baseline_compile_count, V8.TotalBaselineCompileCount)               \
  SC(wasm_generated_code_size, V8.WasmGeneratedCodeBytes)                      \
  SC(wasm_reloc_size, V8.WasmRelocBytes)
1124 1125 1126 1127

// This file contains all the v8 counters that are in use.
class Counters {
 public:
1128 1129 1130 1131 1132
#define HR(name, caption, min, max, num_buckets) \
  Histogram* name() { return &name##_; }
  HISTOGRAM_RANGE_LIST(HR)
#undef HR

yangguo's avatar
yangguo committed
1133
#define HT(name, caption, max, res) \
1134 1135 1136 1137
  HistogramTimer* name() { return &name##_; }
  HISTOGRAM_TIMER_LIST(HT)
#undef HT

1138 1139 1140 1141 1142
#define AHT(name, caption) \
  AggregatableHistogramTimer* name() { return &name##_; }
  AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
#undef AHT

1143 1144 1145 1146 1147 1148 1149
#define HP(name, caption) \
  Histogram* name() { return &name##_; }
  HISTOGRAM_PERCENTAGE_LIST(HP)
#undef HP

#define HM(name, caption) \
  Histogram* name() { return &name##_; }
1150 1151 1152 1153 1154 1155 1156 1157
  HISTOGRAM_LEGACY_MEMORY_LIST(HM)
  HISTOGRAM_MEMORY_LIST(HM)
#undef HM

#define HM(name, caption)                                     \
  AggregatedMemoryHistogram<Histogram>* aggregated_##name() { \
    return &aggregated_##name##_;                             \
  }
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
  HISTOGRAM_MEMORY_LIST(HM)
#undef HM

#define SC(name, caption) \
  StatsCounter* name() { return &name##_; }
  STATS_COUNTER_LIST_1(SC)
  STATS_COUNTER_LIST_2(SC)
#undef SC

#define SC(name) \
  StatsCounter* count_of_##name() { return &count_of_##name##_; } \
  StatsCounter* size_of_##name() { return &size_of_##name##_; }
  INSTANCE_TYPE_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter* count_of_CODE_TYPE_##name() \
    { return &count_of_CODE_TYPE_##name##_; } \
  StatsCounter* size_of_CODE_TYPE_##name() \
    { return &size_of_CODE_TYPE_##name##_; }
  CODE_KIND_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter* count_of_FIXED_ARRAY_##name() \
    { return &count_of_FIXED_ARRAY_##name##_; } \
  StatsCounter* size_of_FIXED_ARRAY_##name() \
    { return &size_of_FIXED_ARRAY_##name##_; }
  FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter* count_of_CODE_AGE_##name() \
    { return &count_of_CODE_AGE_##name##_; } \
  StatsCounter* size_of_CODE_AGE_##name() \
    { return &size_of_CODE_AGE_##name##_; }
  CODE_AGE_LIST_COMPLETE(SC)
#undef SC

  enum Id {
yangguo's avatar
yangguo committed
1198
#define RATE_ID(name, caption, max, res) k_##name,
1199 1200
    HISTOGRAM_TIMER_LIST(RATE_ID)
#undef RATE_ID
1201 1202 1203
#define AGGREGATABLE_ID(name, caption) k_##name,
    AGGREGATABLE_HISTOGRAM_TIMER_LIST(AGGREGATABLE_ID)
#undef AGGREGATABLE_ID
1204 1205 1206 1207
#define PERCENTAGE_ID(name, caption) k_##name,
    HISTOGRAM_PERCENTAGE_LIST(PERCENTAGE_ID)
#undef PERCENTAGE_ID
#define MEMORY_ID(name, caption) k_##name,
1208
    HISTOGRAM_LEGACY_MEMORY_LIST(MEMORY_ID)
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
    HISTOGRAM_MEMORY_LIST(MEMORY_ID)
#undef MEMORY_ID
#define COUNTER_ID(name, caption) k_##name,
    STATS_COUNTER_LIST_1(COUNTER_ID)
    STATS_COUNTER_LIST_2(COUNTER_ID)
#undef COUNTER_ID
#define COUNTER_ID(name) kCountOf##name, kSizeOf##name,
    INSTANCE_TYPE_LIST(COUNTER_ID)
#undef COUNTER_ID
#define COUNTER_ID(name) kCountOfCODE_TYPE_##name, \
    kSizeOfCODE_TYPE_##name,
    CODE_KIND_LIST(COUNTER_ID)
#undef COUNTER_ID
#define COUNTER_ID(name) kCountOfFIXED_ARRAY__##name, \
    kSizeOfFIXED_ARRAY__##name,
    FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COUNTER_ID)
#undef COUNTER_ID
#define COUNTER_ID(name) kCountOfCODE_AGE__##name, \
    kSizeOfCODE_AGE__##name,
    CODE_AGE_LIST_COMPLETE(COUNTER_ID)
#undef COUNTER_ID
    stats_counter_count
  };

1233
  void ResetCounters();
1234
  void ResetHistograms();
1235
  RuntimeCallStats* runtime_call_stats() { return &runtime_call_stats_; }
1236 1237

 private:
1238 1239 1240 1241
#define HR(name, caption, min, max, num_buckets) Histogram name##_;
  HISTOGRAM_RANGE_LIST(HR)
#undef HR

yangguo's avatar
yangguo committed
1242
#define HT(name, caption, max, res) HistogramTimer name##_;
1243 1244 1245
  HISTOGRAM_TIMER_LIST(HT)
#undef HT

1246 1247 1248 1249 1250
#define AHT(name, caption) \
  AggregatableHistogramTimer name##_;
  AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT)
#undef AHT

1251 1252 1253 1254 1255 1256 1257
#define HP(name, caption) \
  Histogram name##_;
  HISTOGRAM_PERCENTAGE_LIST(HP)
#undef HP

#define HM(name, caption) \
  Histogram name##_;
1258 1259 1260 1261 1262 1263
  HISTOGRAM_LEGACY_MEMORY_LIST(HM)
  HISTOGRAM_MEMORY_LIST(HM)
#undef HM

#define HM(name, caption) \
  AggregatedMemoryHistogram<Histogram> aggregated_##name##_;
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
  HISTOGRAM_MEMORY_LIST(HM)
#undef HM

#define SC(name, caption) \
  StatsCounter name##_;
  STATS_COUNTER_LIST_1(SC)
  STATS_COUNTER_LIST_2(SC)
#undef SC

#define SC(name) \
  StatsCounter size_of_##name##_; \
  StatsCounter count_of_##name##_;
  INSTANCE_TYPE_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter size_of_CODE_TYPE_##name##_; \
  StatsCounter count_of_CODE_TYPE_##name##_;
  CODE_KIND_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter size_of_FIXED_ARRAY_##name##_; \
  StatsCounter count_of_FIXED_ARRAY_##name##_;
  FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC)
#undef SC

#define SC(name) \
  StatsCounter size_of_CODE_AGE_##name##_; \
  StatsCounter count_of_CODE_AGE_##name##_;
  CODE_AGE_LIST_COMPLETE(SC)
#undef SC

1297 1298
  RuntimeCallStats runtime_call_stats_;

1299 1300 1301 1302 1303 1304 1305
  friend class Isolate;

  explicit Counters(Isolate* isolate);

  DISALLOW_IMPLICIT_CONSTRUCTORS(Counters);
};

1306 1307 1308 1309 1310
// A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the
// the time of C++ scope.
class RuntimeCallTimerScope {
 public:
  inline RuntimeCallTimerScope(Isolate* isolate,
1311
                               RuntimeCallStats::CounterId counter_id);
1312 1313 1314 1315
  // This constructor is here just to avoid calling GetIsolate() when the
  // stats are disabled and the isolate is not directly available.
  inline RuntimeCallTimerScope(HeapObject* heap_object,
                               RuntimeCallStats::CounterId counter_id);
1316 1317
  inline RuntimeCallTimerScope(RuntimeCallStats* stats,
                               RuntimeCallStats::CounterId counter_id);
1318 1319

  inline ~RuntimeCallTimerScope() {
1320 1321
    if (V8_UNLIKELY(stats_ != nullptr)) {
      RuntimeCallStats::Leave(stats_, &timer_);
1322 1323 1324 1325
    }
  }

 private:
1326
  V8_INLINE void Initialize(RuntimeCallStats* stats,
1327
                            RuntimeCallStats::CounterId counter_id) {
1328 1329
    stats_ = stats;
    RuntimeCallStats::Enter(stats_, &timer_, counter_id);
1330 1331
  }

1332
  RuntimeCallStats* stats_ = nullptr;
1333 1334 1335
  RuntimeCallTimer timer_;
};

1336 1337
}  // namespace internal
}  // namespace v8
1338 1339

#endif  // V8_COUNTERS_H_