Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1563)

Unified Diff: test/cctest/test-sampler-api.cc

Issue 519543002: [WIP] Added CodeEventListener to the sampler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: CallbackEvent also logs as code-creation, added coverage for that. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-sampler-api.cc
diff --git a/test/cctest/test-sampler-api.cc b/test/cctest/test-sampler-api.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6020aaba2f056d20f72119d52546ee2e7cf42169
--- /dev/null
+++ b/test/cctest/test-sampler-api.cc
@@ -0,0 +1,208 @@
+// Copyright 2014 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 the public sampling API in include/v8.h
+
+#include <string>
+
+#include "include/v8.h"
+#include "include/v8stdint.h"
+
+#include "src/v8.h"
+
+#include "src/base/platform/platform.h"
+
+#include "test/cctest/cctest.h"
+
+using v8::Local;
+
+namespace {
+ // Sampler thread waits on this semaphore.
+ v8::base::Semaphore* SamplerSemaphore = new v8::base::Semaphore(0);
+
+ // V8 thread (the JavaScript code) waits on this semaphore.
+ v8::base::Semaphore* V8Semaphore = new v8::base::Semaphore(0);
+
+ // The JavaScript calls this function when on full stack depth.
+ void SignalAndWaitForSampler(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ // Tell the sampler that it can take a sample now.
+ SamplerSemaphore->Signal();
+
+ // Wait for the sampler to finish collecting a sample.
+ V8Semaphore->Wait();
+ }
+}
+
+
+// A thread which collects samples from v8.
+class V8_FINAL SamplerThread : public v8::base::Thread {
+ public:
+ explicit SamplerThread(v8::Isolate* isolate)
+ : Thread(v8::base::Thread::Options("sampler-api-tester")),
+ isolate_(isolate) {
+ }
+
+ virtual ~SamplerThread() {}
+
+ virtual void Run() {
+ SamplerSemaphore->Wait(); // Wait for JS to reach full stack depth.
+ isolate_->GetSample(&sample);
+ V8Semaphore->Signal(); // Tell JS that sample collection is done.
+ }
+
+ v8::Sample sample;
+
+ private:
+ v8::Isolate* isolate_;
+};
+
+
+// A JavaScript function which takes stack depth
+// (minimum value 2) as an argument.
+// When at the bottom of the recursion,
+// the JavaScript code calls into C++ test code,
+// waiting for the sampler to take a sample.
+static const char* sampler_api_test_function = "function func(depth) {"
+" if (depth == 2) SignalAndWaitForSampler();"
+" else return func(depth - 1);"
+"}";
+
+
+// TODO(gholap): Right now, we are just checking whether GetSample
+// gets samples and whether the stack depth is reasonable.
+// After implementing code event listener API, add tests
+// to further verify the correctness of collected samples.
+TEST(StackDepthIsConsistent) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
+ global->Set(
+ v8::String::NewFromUtf8(isolate, "SignalAndWaitForSampler"),
+ v8::FunctionTemplate::New(isolate, SignalAndWaitForSampler));
+
+ LocalContext env(isolate, NULL, global);
+ std::string source(sampler_api_test_function);
+ source.append("func(8);");
+ Local<v8::Script> script = v8::Script::Compile(
+ v8::String::NewFromUtf8(isolate, source.c_str()));
+ SamplerThread sampler(isolate);
+
+ sampler.Start();
+ script->Run();
+ sampler.Join();
+
+ CHECK_EQ(8, sampler.sample.frames_count);
+}
+
+
+TEST(StackDepthDoesNotExceedMaxValue) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
+ global->Set(
+ v8::String::NewFromUtf8(isolate, "SignalAndWaitForSampler"),
+ v8::FunctionTemplate::New(isolate, SignalAndWaitForSampler));
+
+ LocalContext env(isolate, NULL, global);
+ std::string source(sampler_api_test_function);
+ source.append("func(300);");
+ Local<v8::Script> script = v8::Script::Compile(
+ v8::String::NewFromUtf8(isolate, source.c_str()));
+ SamplerThread sampler(isolate);
+
+ sampler.Start();
+ script->Run();
+ sampler.Join();
+
+ int MAX_FRAMES_COUNT = v8::Sample::kMaxFramesCount;
+ CHECK_EQ(MAX_FRAMES_COUNT, sampler.sample.frames_count);
+}
+
+
+namespace {
+ class TestCodeEventHandler : public v8::CodeEventHandler {
+ public:
+ virtual void Create(const void* from,
+ const int size,
+ const std::string& name) {
+ if (name.find("outer") == 0) {
+ outer_starts.push_back(from);
+ outer_ends.push_back((const void*)((int64_t)from + size));
+ } else if (name.find("inner") == 0) {
+ inner_starts.push_back(from);
+ inner_ends.push_back((const void*)((int64_t)from + size));
+ }
+ }
+
+ virtual void Delete(const void* from) {}
+ virtual void Move(const void* from, const void* to) {}
+ virtual void SharedLibrary(const std::string& library_path,
+ const void* start,
+ const void* end) {}
+
+ std::vector<const void*> outer_starts;
+ std::vector<const void*> outer_ends;
+ std::vector<const void*> inner_starts;
+ std::vector<const void*> inner_ends;
+ };
+}
+
+
+// Note: The argumnets.callee stuff is there so that the
+// functions are not optimized away.
+static const char* sampler_api_test_script =
+"function inner() {"
+" SignalAndWaitForSampler();"
+" return arguments.callee.toString();"
+"}"
+"function outer() {return inner() + arguments.callee.toString()}"
+"outer();";
+
+
+// The captured sample should have three pc values.
+// They should fall in the range where the compiled code
+// The expected stack is:
+// bottom of stack [{anon script}, outer, inner] top of stack
+// ^ ^ ^
+// sample.stack indices 2 1 0
+TEST(StackFramesConsistent) {
+ v8::Isolate* isolate = CcTest::isolate();
+ TestCodeEventHandler code_event_handler;
+ isolate->InstallCodeEventHandler(&code_event_handler);
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
+ global->Set(
+ v8::String::NewFromUtf8(isolate, "SignalAndWaitForSampler"),
+ v8::FunctionTemplate::New(isolate, SignalAndWaitForSampler));
+
+ LocalContext env(isolate, NULL, global);
+ Local<v8::Script> script = v8::Script::Compile(
+ v8::String::NewFromUtf8(isolate, sampler_api_test_script));
+ SamplerThread sampler(isolate);
+
+ sampler.Start();
+ script->Run();
+ sampler.Join();
+
+ CHECK_EQ(3, sampler.sample.frames_count);
+
+ bool stack_top_is_inner = false;
+ bool below_inner_is_outer = false;
+
+ for (unsigned i = 0; i < code_event_handler.inner_starts.size(); i++) {
+ if ((sampler.sample.stack[0] >= code_event_handler.inner_starts[i]) &&
+ (sampler.sample.stack[0] < code_event_handler.inner_ends[i]))
+ stack_top_is_inner = true;
+ }
+
+ for (unsigned i = 0; i < code_event_handler.outer_starts.size(); i++) {
+ if ((sampler.sample.stack[1] >= code_event_handler.outer_starts[i]) &&
+ (sampler.sample.stack[1] < code_event_handler.outer_ends[i]))
+ below_inner_is_outer = true;
+ }
+
+ CHECK_EQ(true, stack_top_is_inner);
+ CHECK_EQ(true, below_inner_is_outer);
+}
« no previous file with comments | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698