test-sampler.cc 4.18 KB
Newer Older
1 2 3 4 5
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Tests of sampler functionalities.

6
#include "src/libsampler/sampler.h"
7 8

#include "src/base/platform/platform.h"
9
#include "src/base/platform/time.h"
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#include "test/cctest/cctest.h"


namespace v8 {
namespace sampler {

namespace {

class TestSamplingThread : public base::Thread {
 public:
  static const int kSamplerThreadStackSize = 64 * 1024;

  explicit TestSamplingThread(Sampler* sampler)
      : Thread(base::Thread::Options("TestSamplingThread",
                                     kSamplerThreadStackSize)),
        sampler_(sampler) {}

  // Implement Thread::Run().
  void Run() override {
    while (sampler_->IsProfiling()) {
      sampler_->DoSample();
      base::OS::Sleep(base::TimeDelta::FromMilliseconds(1));
    }
  }

 private:
  Sampler* sampler_;
};


class TestSampler : public Sampler {
 public:
  explicit TestSampler(Isolate* isolate) : Sampler(isolate) {}

  void SampleStack(const v8::RegisterState& regs) override {
45
    void* frames[kMaxFramesCount];
46
    SampleInfo sample_info;
47
    isolate()->GetStackSample(regs, frames, kMaxFramesCount, &sample_info);
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 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
    if (is_counting_samples_) {
      if (sample_info.vm_state == JS) ++js_sample_count_;
      if (sample_info.vm_state == EXTERNAL) ++external_sample_count_;
    }
  }
};


class TestApiCallbacks {
 public:
  TestApiCallbacks() {}

  static void Getter(v8::Local<v8::String> name,
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
  }

  static void Setter(v8::Local<v8::String> name,
                     v8::Local<v8::Value> value,
                     const v8::PropertyCallbackInfo<void>& info) {
  }
};


static void RunSampler(v8::Local<v8::Context> env,
                       v8::Local<v8::Function> function,
                       v8::Local<v8::Value> argv[], int argc,
                       unsigned min_js_samples = 0,
                       unsigned min_external_samples = 0) {
  Sampler::SetUp();
  TestSampler* sampler = new TestSampler(env->GetIsolate());
  TestSamplingThread* thread = new TestSamplingThread(sampler);
  sampler->IncreaseProfilingDepth();
  sampler->Start();
  sampler->StartCountingSamples();
  thread->StartSynchronously();
  do {
    function->Call(env, env->Global(), argc, argv).ToLocalChecked();
  } while (sampler->js_sample_count() < min_js_samples ||
           sampler->external_sample_count() < min_external_samples);
  sampler->Stop();
  sampler->DecreaseProfilingDepth();
  thread->Join();
  delete thread;
  delete sampler;
  Sampler::TearDown();
}

}  // namespace

static const char* sampler_test_source = "function start(count) {\n"
"  for (var i = 0; i < count; i++) {\n"
"    var o = instance.foo;\n"
"    instance.foo = o + 1;\n"
"  }\n"
"}\n";

static v8::Local<v8::Function> GetFunction(v8::Local<v8::Context> env,
                                           const char* name) {
  return v8::Local<v8::Function>::Cast(
      env->Global()->Get(env, v8_str(name)).ToLocalChecked());
}


TEST(LibSamplerCollectSample) {
  LocalContext env;
  v8::Isolate* isolate = env->GetIsolate();
  v8::HandleScope scope(isolate);

  v8::Local<v8::FunctionTemplate> func_template =
      v8::FunctionTemplate::New(isolate);
  v8::Local<v8::ObjectTemplate> instance_template =
      func_template->InstanceTemplate();

  TestApiCallbacks accessors;
  v8::Local<v8::External> data =
      v8::External::New(isolate, &accessors);
  instance_template->SetAccessor(v8_str("foo"), &TestApiCallbacks::Getter,
                                 &TestApiCallbacks::Setter, data);
  v8::Local<v8::Function> func =
      func_template->GetFunction(env.local()).ToLocalChecked();
  v8::Local<v8::Object> instance =
      func->NewInstance(env.local()).ToLocalChecked();
  env->Global()->Set(env.local(), v8_str("instance"), instance).FromJust();

  CompileRun(sampler_test_source);
  v8::Local<v8::Function> function = GetFunction(env.local(), "start");

  int32_t repeat_count = 100;
  v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
  RunSampler(env.local(), function, args, arraysize(args), 100, 100);
}

}  // namespace sampler
}  // namespace v8