LCOV - code coverage report
Current view: top level - test/unittests - counters-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 402 402 100.0 %
Date: 2019-04-17 Functions: 86 113 76.1 %

          Line data    Source code
       1             : // Copyright 2014 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 <vector>
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/base/atomic-utils.h"
       9             : #include "src/base/platform/time.h"
      10             : #include "src/counters-inl.h"
      11             : #include "src/counters.h"
      12             : #include "src/handles-inl.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/tracing/tracing-category-observer.h"
      15             : 
      16             : #include "test/unittests/test-utils.h"
      17             : #include "testing/gtest/include/gtest/gtest.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : namespace {
      23             : 
      24          14 : class MockHistogram : public Histogram {
      25             :  public:
      26        2020 :   void AddSample(int value) { samples_.push_back(value); }
      27             :   std::vector<int>* samples() { return &samples_; }
      28             : 
      29             :  private:
      30             :   std::vector<int> samples_;
      31             : };
      32             : 
      33             : 
      34             : class AggregatedMemoryHistogramTest : public ::testing::Test {
      35             :  public:
      36          14 :   AggregatedMemoryHistogramTest() : aggregated_(&mock_) {}
      37          28 :   ~AggregatedMemoryHistogramTest() override = default;
      38             : 
      39             :   void AddSample(double current_ms, double current_value) {
      40          14 :     aggregated_.AddSample(current_ms, current_value);
      41             :   }
      42             : 
      43             :   std::vector<int>* samples() { return mock_.samples(); }
      44             : 
      45             :  private:
      46             :   AggregatedMemoryHistogram<MockHistogram> aggregated_;
      47             :   MockHistogram mock_;
      48             : };
      49             : 
      50             : static base::TimeTicks runtime_call_stats_test_time_ = base::TimeTicks();
      51             : // Time source used for the RuntimeCallTimer during tests. We cannot rely on
      52             : // the native timer since it's too unpredictable on the build bots.
      53       48378 : static base::TimeTicks RuntimeCallStatsTestNow() {
      54       48378 :   return runtime_call_stats_test_time_;
      55             : }
      56             : 
      57             : class RuntimeCallStatsTest : public TestWithNativeContext {
      58             :  public:
      59          26 :   RuntimeCallStatsTest() {
      60             :     TracingFlags::runtime_stats.store(
      61             :         v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE,
      62             :         std::memory_order_relaxed);
      63             :     // We need to set {time_} to a non-zero value since it would otherwise
      64             :     // cause runtime call timers to think they are uninitialized.
      65             :     Sleep(1);
      66          13 :     stats()->Reset();
      67          13 :   }
      68             : 
      69          26 :   ~RuntimeCallStatsTest() override {
      70             :     // Disable RuntimeCallStats before tearing down the isolate to prevent
      71             :     // printing the tests table. Comment the following line for debugging
      72             :     // purposes.
      73             :     TracingFlags::runtime_stats.store(0, std::memory_order_relaxed);
      74          13 :   }
      75             : 
      76          13 :   static void SetUpTestCase() {
      77             :     TestWithIsolate::SetUpTestCase();
      78             :     // Use a custom time source to precisly emulate system time.
      79          13 :     RuntimeCallTimer::Now = &RuntimeCallStatsTestNow;
      80          13 :   }
      81             : 
      82          13 :   static void TearDownTestCase() {
      83             :     TestWithIsolate::TearDownTestCase();
      84             :     // Restore the original time source.
      85          13 :     RuntimeCallTimer::Now = &base::TimeTicks::HighResolutionNow;
      86          13 :   }
      87             : 
      88             :   RuntimeCallStats* stats() {
      89             :     return isolate()->counters()->runtime_call_stats();
      90             :   }
      91             : 
      92             :   // Print current RuntimeCallStats table. For debugging purposes.
      93           4 :   void PrintStats() { stats()->Print(); }
      94             : 
      95             :   RuntimeCallCounterId counter_id() {
      96             :     return RuntimeCallCounterId::kTestCounter1;
      97             :   }
      98             : 
      99             :   RuntimeCallCounterId counter_id2() {
     100             :     return RuntimeCallCounterId::kTestCounter2;
     101             :   }
     102             : 
     103             :   RuntimeCallCounterId counter_id3() {
     104             :     return RuntimeCallCounterId::kTestCounter3;
     105             :   }
     106             : 
     107             :   RuntimeCallCounter* js_counter() {
     108             :     return stats()->GetCounter(RuntimeCallCounterId::kJS_Execution);
     109             :   }
     110             :   RuntimeCallCounter* counter() { return stats()->GetCounter(counter_id()); }
     111             :   RuntimeCallCounter* counter2() { return stats()->GetCounter(counter_id2()); }
     112             :   RuntimeCallCounter* counter3() { return stats()->GetCounter(counter_id3()); }
     113             : 
     114             :   void Sleep(int64_t microseconds) {
     115             :     base::TimeDelta delta = base::TimeDelta::FromMicroseconds(microseconds);
     116             :     time_ += delta;
     117             :     runtime_call_stats_test_time_ =
     118        8066 :         base::TimeTicks::FromInternalValue(time_.InMicroseconds());
     119             :   }
     120             : 
     121             :  private:
     122             :   base::TimeDelta time_;
     123             : };
     124             : 
     125             : // Temporarily use the native time to modify the test time.
     126             : class ElapsedTimeScope {
     127             :  public:
     128             :   explicit ElapsedTimeScope(RuntimeCallStatsTest* test) : test_(test) {
     129             :     timer_.Start();
     130             :   }
     131             :   ~ElapsedTimeScope() { test_->Sleep(timer_.Elapsed().InMicroseconds()); }
     132             : 
     133             :  private:
     134             :   base::ElapsedTimer timer_;
     135             :   RuntimeCallStatsTest* test_;
     136             : };
     137             : 
     138             : // Temporarily use the default time source.
     139             : class NativeTimeScope {
     140             :  public:
     141           6 :   NativeTimeScope() {
     142           6 :     CHECK_EQ(RuntimeCallTimer::Now, &RuntimeCallStatsTestNow);
     143           6 :     RuntimeCallTimer::Now = &base::TimeTicks::HighResolutionNow;
     144           6 :   }
     145           6 :   ~NativeTimeScope() {
     146           6 :     CHECK_EQ(RuntimeCallTimer::Now, &base::TimeTicks::HighResolutionNow);
     147           6 :     RuntimeCallTimer::Now = &RuntimeCallStatsTestNow;
     148           6 :   }
     149             : };
     150             : 
     151           6 : class SnapshotNativeCounterTest : public TestWithNativeContextAndCounters {
     152             :  public:
     153           3 :   SnapshotNativeCounterTest() {}
     154             : 
     155             :   bool SupportsNativeCounters() const {
     156             : #ifdef V8_USE_SNAPSHOT
     157             : #ifdef V8_SNAPSHOT_NATIVE_CODE_COUNTERS
     158             :     return true;
     159             : #else
     160             :     return false;
     161             : #endif  // V8_SNAPSHOT_NATIVE_CODE_COUNTERS
     162             : #else
     163             :     // If we do not have a snapshot then we rely on the runtime option.
     164             :     return internal::FLAG_native_code_counters;
     165             : #endif  // V8_USE_SNAPSHOT
     166             :   }
     167             : 
     168             : #define SC(name, caption)                                        \
     169             :   int name() {                                                   \
     170             :     CHECK(isolate()->counters()->name()->Enabled());             \
     171             :     return *isolate()->counters()->name()->GetInternalPointer(); \
     172             :   }
     173         108 :   STATS_COUNTER_NATIVE_CODE_LIST(SC)
     174             : #undef SC
     175             : 
     176           3 :   void PrintAll() {
     177             : #define SC(name, caption) PrintF(#caption " = %d\n", name());
     178           3 :     STATS_COUNTER_NATIVE_CODE_LIST(SC)
     179             : #undef SC
     180           3 :   }
     181             : };
     182             : 
     183             : }  // namespace
     184             : 
     185             : 
     186       15443 : TEST_F(AggregatedMemoryHistogramTest, OneSample1) {
     187           1 :   FLAG_histogram_interval = 10;
     188             :   AddSample(10, 1000);
     189             :   AddSample(20, 1000);
     190           2 :   EXPECT_EQ(1U, samples()->size());
     191           2 :   EXPECT_EQ(1000, (*samples())[0]);
     192           1 : }
     193             : 
     194             : 
     195       15443 : TEST_F(AggregatedMemoryHistogramTest, OneSample2) {
     196           1 :   FLAG_histogram_interval = 10;
     197             :   AddSample(10, 500);
     198             :   AddSample(20, 1000);
     199           2 :   EXPECT_EQ(1U, samples()->size());
     200           2 :   EXPECT_EQ(750, (*samples())[0]);
     201           1 : }
     202             : 
     203             : 
     204       15443 : TEST_F(AggregatedMemoryHistogramTest, OneSample3) {
     205           1 :   FLAG_histogram_interval = 10;
     206             :   AddSample(10, 500);
     207             :   AddSample(15, 500);
     208             :   AddSample(15, 1000);
     209             :   AddSample(20, 1000);
     210           2 :   EXPECT_EQ(1U, samples()->size());
     211           2 :   EXPECT_EQ(750, (*samples())[0]);
     212           1 : }
     213             : 
     214             : 
     215       15443 : TEST_F(AggregatedMemoryHistogramTest, OneSample4) {
     216           1 :   FLAG_histogram_interval = 10;
     217             :   AddSample(10, 500);
     218             :   AddSample(15, 750);
     219             :   AddSample(20, 1000);
     220           2 :   EXPECT_EQ(1U, samples()->size());
     221           2 :   EXPECT_EQ(750, (*samples())[0]);
     222           1 : }
     223             : 
     224             : 
     225       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples1) {
     226           1 :   FLAG_histogram_interval = 10;
     227             :   AddSample(10, 1000);
     228             :   AddSample(30, 1000);
     229           2 :   EXPECT_EQ(2U, samples()->size());
     230           2 :   EXPECT_EQ(1000, (*samples())[0]);
     231           2 :   EXPECT_EQ(1000, (*samples())[1]);
     232           1 : }
     233             : 
     234             : 
     235       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples2) {
     236           1 :   FLAG_histogram_interval = 10;
     237             :   AddSample(10, 1000);
     238             :   AddSample(20, 1000);
     239             :   AddSample(30, 1000);
     240           2 :   EXPECT_EQ(2U, samples()->size());
     241           2 :   EXPECT_EQ(1000, (*samples())[0]);
     242           2 :   EXPECT_EQ(1000, (*samples())[1]);
     243           1 : }
     244             : 
     245             : 
     246       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples3) {
     247           1 :   FLAG_histogram_interval = 10;
     248             :   AddSample(10, 1000);
     249             :   AddSample(20, 1000);
     250             :   AddSample(20, 500);
     251             :   AddSample(30, 500);
     252           2 :   EXPECT_EQ(2U, samples()->size());
     253           2 :   EXPECT_EQ(1000, (*samples())[0]);
     254           2 :   EXPECT_EQ(500, (*samples())[1]);
     255           1 : }
     256             : 
     257             : 
     258       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples4) {
     259           1 :   FLAG_histogram_interval = 10;
     260             :   AddSample(10, 1000);
     261             :   AddSample(30, 0);
     262           2 :   EXPECT_EQ(2U, samples()->size());
     263           2 :   EXPECT_EQ(750, (*samples())[0]);
     264           2 :   EXPECT_EQ(250, (*samples())[1]);
     265           1 : }
     266             : 
     267             : 
     268       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples5) {
     269           1 :   FLAG_histogram_interval = 10;
     270             :   AddSample(10, 0);
     271             :   AddSample(30, 1000);
     272           2 :   EXPECT_EQ(2U, samples()->size());
     273           2 :   EXPECT_EQ(250, (*samples())[0]);
     274           2 :   EXPECT_EQ(750, (*samples())[1]);
     275             : }
     276             : 
     277             : 
     278       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples6) {
     279           1 :   FLAG_histogram_interval = 10;
     280             :   AddSample(10, 0);
     281             :   AddSample(15, 1000);
     282             :   AddSample(30, 1000);
     283           2 :   EXPECT_EQ(2U, samples()->size());
     284           2 :   EXPECT_EQ((500 + 1000) / 2, (*samples())[0]);
     285           2 :   EXPECT_EQ(1000, (*samples())[1]);
     286           1 : }
     287             : 
     288             : 
     289       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples7) {
     290           1 :   FLAG_histogram_interval = 10;
     291             :   AddSample(10, 0);
     292             :   AddSample(15, 1000);
     293             :   AddSample(25, 0);
     294             :   AddSample(30, 1000);
     295           2 :   EXPECT_EQ(2U, samples()->size());
     296           2 :   EXPECT_EQ((500 + 750) / 2, (*samples())[0]);
     297           2 :   EXPECT_EQ((250 + 500) / 2, (*samples())[1]);
     298           1 : }
     299             : 
     300             : 
     301       15443 : TEST_F(AggregatedMemoryHistogramTest, TwoSamples8) {
     302           1 :   FLAG_histogram_interval = 10;
     303             :   AddSample(10, 1000);
     304             :   AddSample(15, 0);
     305             :   AddSample(25, 1000);
     306             :   AddSample(30, 0);
     307           2 :   EXPECT_EQ(2U, samples()->size());
     308           2 :   EXPECT_EQ((500 + 250) / 2, (*samples())[0]);
     309           2 :   EXPECT_EQ((750 + 500) / 2, (*samples())[1]);
     310           1 : }
     311             : 
     312             : 
     313       15443 : TEST_F(AggregatedMemoryHistogramTest, ManySamples1) {
     314           1 :   FLAG_histogram_interval = 10;
     315             :   const int kMaxSamples = 1000;
     316             :   AddSample(0, 0);
     317             :   AddSample(10 * kMaxSamples, 10 * kMaxSamples);
     318           2 :   EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size());
     319        2001 :   for (int i = 0; i < kMaxSamples; i++) {
     320        3000 :     EXPECT_EQ(i * 10 + 5, (*samples())[i]);
     321             :   }
     322           1 : }
     323             : 
     324             : 
     325       15443 : TEST_F(AggregatedMemoryHistogramTest, ManySamples2) {
     326           1 :   FLAG_histogram_interval = 10;
     327             :   const int kMaxSamples = 1000;
     328             :   AddSample(0, 0);
     329             :   AddSample(10 * (2 * kMaxSamples), 10 * (2 * kMaxSamples));
     330           2 :   EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size());
     331        2001 :   for (int i = 0; i < kMaxSamples; i++) {
     332        3000 :     EXPECT_EQ(i * 10 + 5, (*samples())[i]);
     333             :   }
     334           1 : }
     335             : 
     336       15443 : TEST_F(RuntimeCallStatsTest, RuntimeCallTimer) {
     337             :   RuntimeCallTimer timer;
     338             : 
     339             :   Sleep(50);
     340           1 :   stats()->Enter(&timer, counter_id());
     341           3 :   EXPECT_EQ(counter(), timer.counter());
     342           1 :   EXPECT_EQ(nullptr, timer.parent());
     343           1 :   EXPECT_TRUE(timer.IsStarted());
     344           2 :   EXPECT_EQ(&timer, stats()->current_timer());
     345             : 
     346             :   Sleep(100);
     347             : 
     348           1 :   stats()->Leave(&timer);
     349             :   Sleep(50);
     350           2 :   EXPECT_FALSE(timer.IsStarted());
     351           2 :   EXPECT_EQ(1, counter()->count());
     352           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     353           1 : }
     354             : 
     355       15443 : TEST_F(RuntimeCallStatsTest, RuntimeCallTimerSubTimer) {
     356             :   RuntimeCallTimer timer;
     357             :   RuntimeCallTimer timer2;
     358             : 
     359           1 :   stats()->Enter(&timer, counter_id());
     360           1 :   EXPECT_TRUE(timer.IsStarted());
     361           2 :   EXPECT_FALSE(timer2.IsStarted());
     362           3 :   EXPECT_EQ(counter(), timer.counter());
     363           1 :   EXPECT_EQ(nullptr, timer.parent());
     364           2 :   EXPECT_EQ(&timer, stats()->current_timer());
     365             : 
     366             :   Sleep(50);
     367             : 
     368           1 :   stats()->Enter(&timer2, counter_id2());
     369             :   // timer 1 is paused, while timer 2 is active.
     370           1 :   EXPECT_TRUE(timer2.IsStarted());
     371           3 :   EXPECT_EQ(counter(), timer.counter());
     372           3 :   EXPECT_EQ(counter2(), timer2.counter());
     373           1 :   EXPECT_EQ(nullptr, timer.parent());
     374           2 :   EXPECT_EQ(&timer, timer2.parent());
     375           2 :   EXPECT_EQ(&timer2, stats()->current_timer());
     376             : 
     377             :   Sleep(100);
     378           1 :   stats()->Leave(&timer2);
     379             : 
     380             :   // The subtimer subtracts its time from the parent timer.
     381           1 :   EXPECT_TRUE(timer.IsStarted());
     382           2 :   EXPECT_FALSE(timer2.IsStarted());
     383           2 :   EXPECT_EQ(0, counter()->count());
     384           2 :   EXPECT_EQ(1, counter2()->count());
     385           2 :   EXPECT_EQ(0, counter()->time().InMicroseconds());
     386           2 :   EXPECT_EQ(100, counter2()->time().InMicroseconds());
     387           2 :   EXPECT_EQ(&timer, stats()->current_timer());
     388             : 
     389             :   Sleep(100);
     390             : 
     391           1 :   stats()->Leave(&timer);
     392           2 :   EXPECT_FALSE(timer.IsStarted());
     393           2 :   EXPECT_EQ(1, counter()->count());
     394           2 :   EXPECT_EQ(1, counter2()->count());
     395           2 :   EXPECT_EQ(150, counter()->time().InMicroseconds());
     396           2 :   EXPECT_EQ(100, counter2()->time().InMicroseconds());
     397           1 :   EXPECT_EQ(nullptr, stats()->current_timer());
     398           1 : }
     399             : 
     400       15443 : TEST_F(RuntimeCallStatsTest, RuntimeCallTimerRecursive) {
     401             :   RuntimeCallTimer timer;
     402             :   RuntimeCallTimer timer2;
     403             : 
     404           1 :   stats()->Enter(&timer, counter_id());
     405           3 :   EXPECT_EQ(counter(), timer.counter());
     406           1 :   EXPECT_EQ(nullptr, timer.parent());
     407           1 :   EXPECT_TRUE(timer.IsStarted());
     408           2 :   EXPECT_EQ(&timer, stats()->current_timer());
     409             : 
     410           1 :   stats()->Enter(&timer2, counter_id());
     411           3 :   EXPECT_EQ(counter(), timer2.counter());
     412           1 :   EXPECT_EQ(nullptr, timer.parent());
     413           2 :   EXPECT_EQ(&timer, timer2.parent());
     414           1 :   EXPECT_TRUE(timer2.IsStarted());
     415           2 :   EXPECT_EQ(&timer2, stats()->current_timer());
     416             : 
     417             :   Sleep(50);
     418             : 
     419           1 :   stats()->Leave(&timer2);
     420           1 :   EXPECT_EQ(nullptr, timer.parent());
     421           2 :   EXPECT_FALSE(timer2.IsStarted());
     422           1 :   EXPECT_TRUE(timer.IsStarted());
     423           2 :   EXPECT_EQ(1, counter()->count());
     424           2 :   EXPECT_EQ(50, counter()->time().InMicroseconds());
     425             : 
     426             :   Sleep(100);
     427             : 
     428           1 :   stats()->Leave(&timer);
     429           2 :   EXPECT_FALSE(timer.IsStarted());
     430           2 :   EXPECT_EQ(2, counter()->count());
     431           2 :   EXPECT_EQ(150, counter()->time().InMicroseconds());
     432           1 : }
     433             : 
     434       15443 : TEST_F(RuntimeCallStatsTest, RuntimeCallTimerScope) {
     435             :   {
     436           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     437             :     Sleep(50);
     438             :   }
     439             :   Sleep(100);
     440           2 :   EXPECT_EQ(1, counter()->count());
     441           2 :   EXPECT_EQ(50, counter()->time().InMicroseconds());
     442             :   {
     443           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     444             :     Sleep(50);
     445             :   }
     446           2 :   EXPECT_EQ(2, counter()->count());
     447           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     448           1 : }
     449             : 
     450       15443 : TEST_F(RuntimeCallStatsTest, RuntimeCallTimerScopeRecursive) {
     451             :   {
     452           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     453             :     Sleep(50);
     454           2 :     EXPECT_EQ(0, counter()->count());
     455           2 :     EXPECT_EQ(0, counter()->time().InMicroseconds());
     456             :     {
     457           1 :       RuntimeCallTimerScope scope(stats(), counter_id());
     458             :       Sleep(50);
     459             :     }
     460           2 :     EXPECT_EQ(1, counter()->count());
     461           2 :     EXPECT_EQ(50, counter()->time().InMicroseconds());
     462             :   }
     463           2 :   EXPECT_EQ(2, counter()->count());
     464           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     465           1 : }
     466             : 
     467       15443 : TEST_F(RuntimeCallStatsTest, RenameTimer) {
     468             :   {
     469           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     470             :     Sleep(50);
     471           2 :     EXPECT_EQ(0, counter()->count());
     472           2 :     EXPECT_EQ(0, counter2()->count());
     473           2 :     EXPECT_EQ(0, counter()->time().InMicroseconds());
     474           2 :     EXPECT_EQ(0, counter2()->time().InMicroseconds());
     475             :     {
     476           1 :       RuntimeCallTimerScope scope(stats(), counter_id());
     477             :       Sleep(100);
     478             :     }
     479           3 :     CHANGE_CURRENT_RUNTIME_COUNTER(stats(),
     480             :                                    RuntimeCallCounterId::kTestCounter2);
     481           2 :     EXPECT_EQ(1, counter()->count());
     482           2 :     EXPECT_EQ(0, counter2()->count());
     483           2 :     EXPECT_EQ(100, counter()->time().InMicroseconds());
     484           2 :     EXPECT_EQ(0, counter2()->time().InMicroseconds());
     485             :   }
     486           2 :   EXPECT_EQ(1, counter()->count());
     487           2 :   EXPECT_EQ(1, counter2()->count());
     488           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     489           2 :   EXPECT_EQ(50, counter2()->time().InMicroseconds());
     490           1 : }
     491             : 
     492       15443 : TEST_F(RuntimeCallStatsTest, BasicPrintAndSnapshot) {
     493           2 :   std::ostringstream out;
     494           1 :   stats()->Print(out);
     495           2 :   EXPECT_EQ(0, counter()->count());
     496           2 :   EXPECT_EQ(0, counter2()->count());
     497           2 :   EXPECT_EQ(0, counter3()->count());
     498           2 :   EXPECT_EQ(0, counter()->time().InMicroseconds());
     499           2 :   EXPECT_EQ(0, counter2()->time().InMicroseconds());
     500           2 :   EXPECT_EQ(0, counter3()->time().InMicroseconds());
     501             : 
     502             :   {
     503           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     504             :     Sleep(50);
     505           1 :     stats()->Print(out);
     506             :   }
     507           1 :   stats()->Print(out);
     508           2 :   EXPECT_EQ(1, counter()->count());
     509           2 :   EXPECT_EQ(0, counter2()->count());
     510           2 :   EXPECT_EQ(0, counter3()->count());
     511           2 :   EXPECT_EQ(50, counter()->time().InMicroseconds());
     512           2 :   EXPECT_EQ(0, counter2()->time().InMicroseconds());
     513           2 :   EXPECT_EQ(0, counter3()->time().InMicroseconds());
     514           1 : }
     515             : 
     516       15443 : TEST_F(RuntimeCallStatsTest, PrintAndSnapshot) {
     517             :   {
     518           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     519             :     Sleep(100);
     520           2 :     EXPECT_EQ(0, counter()->count());
     521           2 :     EXPECT_EQ(0, counter()->time().InMicroseconds());
     522             :     {
     523           1 :       RuntimeCallTimerScope scope(stats(), counter_id2());
     524           2 :       EXPECT_EQ(0, counter2()->count());
     525           2 :       EXPECT_EQ(0, counter2()->time().InMicroseconds());
     526             :       Sleep(50);
     527             : 
     528             :       // This calls Snapshot on the current active timer and sychronizes and
     529             :       // commits the whole timer stack.
     530           2 :       std::ostringstream out;
     531           1 :       stats()->Print(out);
     532           2 :       EXPECT_EQ(0, counter()->count());
     533           2 :       EXPECT_EQ(0, counter2()->count());
     534           2 :       EXPECT_EQ(100, counter()->time().InMicroseconds());
     535           2 :       EXPECT_EQ(50, counter2()->time().InMicroseconds());
     536             :       // Calling Print several times shouldn't have a (big) impact on the
     537             :       // measured times.
     538           1 :       stats()->Print(out);
     539           2 :       EXPECT_EQ(0, counter()->count());
     540           2 :       EXPECT_EQ(0, counter2()->count());
     541           2 :       EXPECT_EQ(100, counter()->time().InMicroseconds());
     542           2 :       EXPECT_EQ(50, counter2()->time().InMicroseconds());
     543             : 
     544             :       Sleep(50);
     545           1 :       stats()->Print(out);
     546           2 :       EXPECT_EQ(0, counter()->count());
     547           2 :       EXPECT_EQ(0, counter2()->count());
     548           2 :       EXPECT_EQ(100, counter()->time().InMicroseconds());
     549           2 :       EXPECT_EQ(100, counter2()->time().InMicroseconds());
     550             :       Sleep(50);
     551             :     }
     552             :     Sleep(50);
     553           2 :     EXPECT_EQ(0, counter()->count());
     554           2 :     EXPECT_EQ(1, counter2()->count());
     555           2 :     EXPECT_EQ(100, counter()->time().InMicroseconds());
     556           2 :     EXPECT_EQ(150, counter2()->time().InMicroseconds());
     557             :     Sleep(50);
     558             :   }
     559           2 :   EXPECT_EQ(1, counter()->count());
     560           2 :   EXPECT_EQ(1, counter2()->count());
     561           2 :   EXPECT_EQ(200, counter()->time().InMicroseconds());
     562           2 :   EXPECT_EQ(150, counter2()->time().InMicroseconds());
     563           1 : }
     564             : 
     565       15443 : TEST_F(RuntimeCallStatsTest, NestedScopes) {
     566             :   {
     567           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     568             :     Sleep(100);
     569             :     {
     570           1 :       RuntimeCallTimerScope scope(stats(), counter_id2());
     571             :       Sleep(100);
     572             :       {
     573           1 :         RuntimeCallTimerScope scope(stats(), counter_id3());
     574             :         Sleep(50);
     575             :       }
     576             :       Sleep(50);
     577             :       {
     578           1 :         RuntimeCallTimerScope scope(stats(), counter_id3());
     579             :         Sleep(50);
     580             :       }
     581             :       Sleep(50);
     582             :     }
     583             :     Sleep(100);
     584             :     {
     585           1 :       RuntimeCallTimerScope scope(stats(), counter_id2());
     586             :       Sleep(100);
     587             :     }
     588             :     Sleep(50);
     589             :   }
     590           2 :   EXPECT_EQ(1, counter()->count());
     591           2 :   EXPECT_EQ(2, counter2()->count());
     592           2 :   EXPECT_EQ(2, counter3()->count());
     593           2 :   EXPECT_EQ(250, counter()->time().InMicroseconds());
     594           2 :   EXPECT_EQ(300, counter2()->time().InMicroseconds());
     595           2 :   EXPECT_EQ(100, counter3()->time().InMicroseconds());
     596           1 : }
     597             : 
     598       15443 : TEST_F(RuntimeCallStatsTest, BasicJavaScript) {
     599             :   RuntimeCallCounter* counter =
     600             :       stats()->GetCounter(RuntimeCallCounterId::kJS_Execution);
     601           2 :   EXPECT_EQ(0, counter->count());
     602           2 :   EXPECT_EQ(0, counter->time().InMicroseconds());
     603             : 
     604             :   {
     605           2 :     NativeTimeScope native_timer_scope;
     606             :     RunJS("function f() { return 1; };");
     607             :   }
     608           2 :   EXPECT_EQ(1, counter->count());
     609           1 :   int64_t time = counter->time().InMicroseconds();
     610           1 :   EXPECT_LT(0, time);
     611             : 
     612             :   {
     613           2 :     NativeTimeScope native_timer_scope;
     614             :     RunJS("f();");
     615             :   }
     616           2 :   EXPECT_EQ(2, counter->count());
     617           1 :   EXPECT_LE(time, counter->time().InMicroseconds());
     618           1 : }
     619             : 
     620       15443 : TEST_F(RuntimeCallStatsTest, FunctionLengthGetter) {
     621             :   RuntimeCallCounter* getter_counter =
     622             :       stats()->GetCounter(RuntimeCallCounterId::kFunctionLengthGetter);
     623           2 :   EXPECT_EQ(0, getter_counter->count());
     624           2 :   EXPECT_EQ(0, js_counter()->count());
     625           2 :   EXPECT_EQ(0, getter_counter->time().InMicroseconds());
     626           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     627             : 
     628             :   {
     629           2 :     NativeTimeScope native_timer_scope;
     630             :     RunJS("function f(array) { return array.length; };");
     631             :   }
     632           2 :   EXPECT_EQ(0, getter_counter->count());
     633           2 :   EXPECT_EQ(1, js_counter()->count());
     634           2 :   EXPECT_EQ(0, getter_counter->time().InMicroseconds());
     635           1 :   int64_t js_time = js_counter()->time().InMicroseconds();
     636           1 :   EXPECT_LT(0, js_time);
     637             : 
     638             :   {
     639           2 :     NativeTimeScope native_timer_scope;
     640             :     RunJS("f.length;");
     641             :   }
     642           2 :   EXPECT_EQ(1, getter_counter->count());
     643           2 :   EXPECT_EQ(2, js_counter()->count());
     644           1 :   EXPECT_LE(0, getter_counter->time().InMicroseconds());
     645           1 :   EXPECT_LE(js_time, js_counter()->time().InMicroseconds());
     646             : 
     647             :   {
     648           2 :     NativeTimeScope native_timer_scope;
     649             :     RunJS("for (let i = 0; i < 50; i++) { f.length };");
     650             :   }
     651           2 :   EXPECT_EQ(51, getter_counter->count());
     652           2 :   EXPECT_EQ(3, js_counter()->count());
     653             : 
     654             :   {
     655           2 :     NativeTimeScope native_timer_scope;
     656             :     RunJS("for (let i = 0; i < 1000; i++) { f.length; };");
     657             :   }
     658           2 :   EXPECT_EQ(1051, getter_counter->count());
     659           2 :   EXPECT_EQ(4, js_counter()->count());
     660           1 : }
     661             : 
     662             : namespace {
     663             : static RuntimeCallStatsTest* current_test;
     664             : static const int kCustomCallbackTime = 1234;
     665        8020 : static void CustomCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
     666             :   RuntimeCallTimerScope scope(current_test->stats(),
     667        8020 :                               current_test->counter_id2());
     668        8020 :   current_test->Sleep(kCustomCallbackTime);
     669        8020 : }
     670             : }  // namespace
     671             : 
     672       15443 : TEST_F(RuntimeCallStatsTest, CallbackFunction) {
     673             :   RuntimeCallCounter* callback_counter =
     674             :       stats()->GetCounter(RuntimeCallCounterId::kFunctionCallback);
     675             : 
     676           1 :   current_test = this;
     677             :   // Set up a function template with a custom callback.
     678             :   v8::Isolate* isolate = v8_isolate();
     679           2 :   v8::HandleScope scope(isolate);
     680             : 
     681             :   v8::Local<v8::ObjectTemplate> object_template =
     682           1 :       v8::ObjectTemplate::New(isolate);
     683           2 :   object_template->Set(isolate, "callback",
     684             :                        v8::FunctionTemplate::New(isolate, CustomCallback));
     685             :   v8::Local<v8::Object> object =
     686           1 :       object_template->NewInstance(v8_context()).ToLocalChecked();
     687           1 :   SetGlobalProperty("custom_object", object);
     688             : 
     689           2 :   EXPECT_EQ(0, js_counter()->count());
     690           2 :   EXPECT_EQ(0, counter()->count());
     691           2 :   EXPECT_EQ(0, callback_counter->count());
     692           2 :   EXPECT_EQ(0, counter2()->count());
     693             :   {
     694           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     695             :     Sleep(100);
     696             :     RunJS("custom_object.callback();");
     697             :   }
     698           2 :   EXPECT_EQ(1, js_counter()->count());
     699           2 :   EXPECT_EQ(1, counter()->count());
     700           2 :   EXPECT_EQ(1, callback_counter->count());
     701           2 :   EXPECT_EQ(1, counter2()->count());
     702             :   // Given that no native timers are used, only the two scopes explitly
     703             :   // mentioned above will track the time.
     704           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     705           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     706           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     707           2 :   EXPECT_EQ(kCustomCallbackTime, counter2()->time().InMicroseconds());
     708             : 
     709             :   RunJS("for (let i = 0; i < 9; i++) { custom_object.callback(); };");
     710           2 :   EXPECT_EQ(2, js_counter()->count());
     711           2 :   EXPECT_EQ(1, counter()->count());
     712           2 :   EXPECT_EQ(10, callback_counter->count());
     713           2 :   EXPECT_EQ(10, counter2()->count());
     714           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     715           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     716           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     717           2 :   EXPECT_EQ(kCustomCallbackTime * 10, counter2()->time().InMicroseconds());
     718             : 
     719             :   RunJS("for (let i = 0; i < 4000; i++) { custom_object.callback(); };");
     720           2 :   EXPECT_EQ(3, js_counter()->count());
     721           2 :   EXPECT_EQ(1, counter()->count());
     722           2 :   EXPECT_EQ(4010, callback_counter->count());
     723           2 :   EXPECT_EQ(4010, counter2()->count());
     724           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     725           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     726           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     727           2 :   EXPECT_EQ(kCustomCallbackTime * 4010, counter2()->time().InMicroseconds());
     728           1 : }
     729             : 
     730       15443 : TEST_F(RuntimeCallStatsTest, ApiGetter) {
     731             :   RuntimeCallCounter* callback_counter =
     732             :       stats()->GetCounter(RuntimeCallCounterId::kFunctionCallback);
     733           1 :   current_test = this;
     734             :   // Set up a function template with an api accessor.
     735             :   v8::Isolate* isolate = v8_isolate();
     736           2 :   v8::HandleScope scope(isolate);
     737             : 
     738             :   v8::Local<v8::ObjectTemplate> object_template =
     739           1 :       v8::ObjectTemplate::New(isolate);
     740           2 :   object_template->SetAccessorProperty(
     741             :       NewString("apiGetter"),
     742           1 :       v8::FunctionTemplate::New(isolate, CustomCallback));
     743             :   v8::Local<v8::Object> object =
     744           1 :       object_template->NewInstance(v8_context()).ToLocalChecked();
     745           1 :   SetGlobalProperty("custom_object", object);
     746             : 
     747             :   // TODO(cbruni): Check api accessor timer (one above the custom callback).
     748           2 :   EXPECT_EQ(0, js_counter()->count());
     749           2 :   EXPECT_EQ(0, counter()->count());
     750           2 :   EXPECT_EQ(0, callback_counter->count());
     751           2 :   EXPECT_EQ(0, counter2()->count());
     752             : 
     753             :   {
     754           1 :     RuntimeCallTimerScope scope(stats(), counter_id());
     755             :     Sleep(100);
     756             :     RunJS("custom_object.apiGetter;");
     757             :   }
     758             :   PrintStats();
     759             : 
     760           2 :   EXPECT_EQ(1, js_counter()->count());
     761           2 :   EXPECT_EQ(1, counter()->count());
     762           2 :   EXPECT_EQ(1, callback_counter->count());
     763           2 :   EXPECT_EQ(1, counter2()->count());
     764             :   // Given that no native timers are used, only the two scopes explitly
     765             :   // mentioned above will track the time.
     766           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     767           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     768           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     769           2 :   EXPECT_EQ(kCustomCallbackTime, counter2()->time().InMicroseconds());
     770             : 
     771             :   RunJS("for (let i = 0; i < 9; i++) { custom_object.apiGetter };");
     772             :   PrintStats();
     773             : 
     774           2 :   EXPECT_EQ(2, js_counter()->count());
     775           2 :   EXPECT_EQ(1, counter()->count());
     776           2 :   EXPECT_EQ(10, callback_counter->count());
     777           2 :   EXPECT_EQ(10, counter2()->count());
     778             : 
     779           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     780           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     781           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     782           2 :   EXPECT_EQ(kCustomCallbackTime * 10, counter2()->time().InMicroseconds());
     783             : 
     784             :   RunJS("for (let i = 0; i < 4000; i++) { custom_object.apiGetter };");
     785             :   PrintStats();
     786             : 
     787           2 :   EXPECT_EQ(3, js_counter()->count());
     788           2 :   EXPECT_EQ(1, counter()->count());
     789           2 :   EXPECT_EQ(4010, callback_counter->count());
     790           2 :   EXPECT_EQ(4010, counter2()->count());
     791             : 
     792           2 :   EXPECT_EQ(0, js_counter()->time().InMicroseconds());
     793           2 :   EXPECT_EQ(100, counter()->time().InMicroseconds());
     794           2 :   EXPECT_EQ(0, callback_counter->time().InMicroseconds());
     795           2 :   EXPECT_EQ(kCustomCallbackTime * 4010, counter2()->time().InMicroseconds());
     796             : 
     797             :   PrintStats();
     798           1 : }
     799             : 
     800       15445 : TEST_F(SnapshotNativeCounterTest, StringAddNative) {
     801             :   RunJS("let s = 'hello, ' + 'world!'");
     802             : 
     803             :   if (SupportsNativeCounters()) {
     804             :     EXPECT_NE(0, string_add_native());
     805             :   } else {
     806           2 :     EXPECT_EQ(0, string_add_native());
     807             :   }
     808             : 
     809           1 :   PrintAll();
     810           1 : }
     811             : 
     812       15445 : TEST_F(SnapshotNativeCounterTest, SubStringNative) {
     813             :   RunJS("'hello, world!'.substring(6);");
     814             : 
     815             :   if (SupportsNativeCounters()) {
     816             :     EXPECT_NE(0, sub_string_native());
     817             :   } else {
     818           2 :     EXPECT_EQ(0, sub_string_native());
     819             :   }
     820             : 
     821           1 :   PrintAll();
     822           1 : }
     823             : 
     824       15445 : TEST_F(SnapshotNativeCounterTest, WriteBarrier) {
     825             :   RunJS("let o = {a: 42};");
     826             : 
     827             :   if (SupportsNativeCounters()) {
     828             :     EXPECT_NE(0, write_barriers());
     829             :   } else {
     830           2 :     EXPECT_EQ(0, write_barriers());
     831             :   }
     832             : 
     833           1 :   PrintAll();
     834           1 : }
     835             : 
     836             : }  // namespace internal
     837        9264 : }  // namespace v8

Generated by: LCOV version 1.10