| Index: test/cctest/libsampler/test-sampler.cc | 
| diff --git a/test/cctest/libsampler/test-sampler.cc b/test/cctest/libsampler/test-sampler.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..99e23783e6465ae2b29fa639eb3eba72aade8c89 | 
| --- /dev/null | 
| +++ b/test/cctest/libsampler/test-sampler.cc | 
| @@ -0,0 +1,187 @@ | 
| +// 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. | 
| + | 
| +#include "src/libsampler/v8-sampler.h" | 
| + | 
| +#include "src/base/platform/platform.h" | 
| +#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(). | 
| +  virtual void Run() { | 
| +    while (true) { | 
| +      if (!sampler_->IsProfiling()) break; | 
| +      sampler_->DoSample(); | 
| +      base::OS::Sleep(base::TimeDelta::FromMilliseconds(10)); | 
| +    } | 
| +  } | 
| + | 
| + private: | 
| +  Sampler* sampler_; | 
| +}; | 
| + | 
| + | 
| +class TestSampler : public Sampler { | 
| + public: | 
| +  explicit TestSampler(Isolate* isolate) : Sampler(isolate) {} | 
| + | 
| +  void SampleStack(const v8::RegisterState& regs) override { | 
| +    void* frames[Sampler::kMaxFramesCount]; | 
| +    SampleInfo sample_info; | 
| +    isolate()->GetStackSample(regs, reinterpret_cast<void**>(frames), | 
| +                              Sampler::kMaxFramesCount, &sample_info); | 
| +    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: | 
| +  explicit TestApiCallbacks(int min_duration_ms) | 
| +      : min_duration_ms_(min_duration_ms), | 
| +        is_warming_up_(false) {} | 
| + | 
| +  static void Getter(v8::Local<v8::String> name, | 
| +                     const v8::PropertyCallbackInfo<v8::Value>& info) { | 
| +    TestApiCallbacks* data = FromInfo(info); | 
| +    data->Wait(); | 
| +  } | 
| + | 
| +  static void Setter(v8::Local<v8::String> name, | 
| +                     v8::Local<v8::Value> value, | 
| +                     const v8::PropertyCallbackInfo<void>& info) { | 
| +    TestApiCallbacks* data = FromInfo(info); | 
| +    data->Wait(); | 
| +  } | 
| + | 
| +  static void Callback(const v8::FunctionCallbackInfo<v8::Value>& info) { | 
| +    TestApiCallbacks* data = FromInfo(info); | 
| +    data->Wait(); | 
| +  } | 
| + | 
| +  void set_warming_up(bool value) { is_warming_up_ = value; } | 
| + | 
| + private: | 
| +  void Wait() { | 
| +    if (is_warming_up_) return; | 
| +    double start = v8::base::OS::TimeCurrentMillis(); | 
| +    double duration = 0; | 
| +    while (duration < min_duration_ms_) { | 
| +      v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1)); | 
| +      duration = v8::base::OS::TimeCurrentMillis() - start; | 
| +    } | 
| +  } | 
| + | 
| +  template <typename T> | 
| +  static TestApiCallbacks* FromInfo(const T& info) { | 
| +    void* data = v8::External::Cast(*info.Data())->Value(); | 
| +    return reinterpret_cast<TestApiCallbacks*>(data); | 
| +  } | 
| + | 
| +  int min_duration_ms_; | 
| +  bool is_warming_up_; | 
| +}; | 
| + | 
| + | 
| +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(); | 
| +  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(1); | 
| +  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"); | 
| + | 
| +  /* | 
| +  { | 
| +    // Make sure accessors ICs are in monomorphic state before starting | 
| +    // profiling. | 
| +    accessors.set_warming_up(true); | 
| +    int32_t warm_up_iterations = 3; | 
| +    v8::Local<v8::Value> args[] = { | 
| +        v8::Integer::New(isolate, warm_up_iterations)}; | 
| +    function->Call(env.local(), env->Global(), arraysize(args), args) | 
| +        .ToLocalChecked(); | 
| +    accessors.set_warming_up(false); | 
| +  } | 
| +  */ | 
| + | 
| +  int32_t repeat_count = 100; | 
| +  v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)}; | 
| +  RunSampler(env.local(), function, args, arraysize(args), 0, 100); | 
| +} | 
| + | 
| +}  // namespace sampler | 
| +}  // namespace v8 | 
|  |