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

Side by Side Diff: test/cctest/test-sampler-api.cc

Issue 596533002: Initial implementation of GetStackSample sampling profiler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing yurys@ comments. Created 6 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/cctest/test-api.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 // Tests the sampling API in include/v8.h
6
7 #include <map>
8 #include <string>
9 #include "include/v8.h"
10 #include "src/simulator.h"
yurys 2014/09/24 13:44:07 Do we still need this include?
alph 2014/09/24 14:00:51 Done.
11 #include "src/utils.h"
12 #include "src/v8.h"
13 #include "test/cctest/cctest.h"
14
15 namespace {
16
17 class Sample {
18 public:
19 enum { kFramesLimit = 255 };
20
21 Sample() {}
22
23 typedef const void* const* const_iterator;
24 const_iterator begin() const { return data_.start(); }
25 const_iterator end() const { return &data_[data_.length()]; }
26
27 int size() const { return data_.length(); }
28 v8::internal::Vector<void*>& data() { return data_; }
29
30 private:
31 v8::internal::EmbeddedVector<void*, kFramesLimit> data_;
32 };
33
34
35 template <class T>
36 class Singleton {
37 public:
38 static T* instance() { return instance_; }
39
40 protected:
41 Singleton() {
42 DCHECK_EQ(NULL, instance_);
yurys 2014/09/24 13:44:07 I'd rather inline this check and singlton implemen
alph 2014/09/24 14:00:51 Done.
43 instance_ = static_cast<T*>(this);
44 }
45
46 ~Singleton() { instance_ = NULL; }
47
48 private:
49 static T* instance_;
50 };
51
52 template <class T>
53 T* Singleton<T>::instance_;
54
55
56 class SamplingTestHelper : public Singleton<SamplingTestHelper> {
57 public:
58 struct CodeEventEntry {
59 std::string name;
60 const void* code_start;
61 size_t code_len;
62 };
63 typedef std::map<const void*, CodeEventEntry> CodeEntries;
64
65 explicit SamplingTestHelper(const std::string& test_function) {
66 isolate = CcTest::isolate();
67 v8::HandleScope scope(isolate);
68 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
69 global->Set(v8::String::NewFromUtf8(isolate, "CollectSample"),
70 v8::FunctionTemplate::New(isolate, CollectSample));
71 LocalContext env(isolate, NULL, global);
72 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
73 JitCodeEventHandler);
74 v8::Script::Compile(v8::String::NewFromUtf8(isolate, test_function.c_str()))
75 ->Run();
76 }
77
78 ~SamplingTestHelper() { isolate = NULL; }
79
80 Sample& get_sample() { return sample_; }
yurys 2014/09/24 13:44:07 style: no get_ prefix on simple getters.
alph 2014/09/24 14:00:51 Done.
81
82 static void CollectSample(const v8::FunctionCallbackInfo<v8::Value>& args) {
83 instance()->DoCollectSample();
84 }
85
86 // The JavaScript calls this function when on full stack depth.
87 void DoCollectSample() {
yurys 2014/09/24 13:44:07 This should be private
alph 2014/09/24 14:00:51 Done.
88 v8::RegisterState state;
89 state.pc = NULL;
90 state.fp = &state;
91 state.sp = &state;
92 v8::SampleInfo info;
93 isolate->GetStackSample(state, sample_.data().start(),
94 static_cast<size_t>(sample_.size()), &info);
95 size_t frames_count = info.frames_count;
96 CHECK_LE(frames_count, static_cast<size_t>(sample_.size()));
97 sample_.data().Truncate(static_cast<int>(frames_count));
98 }
99
100 static void JitCodeEventHandler(const v8::JitCodeEvent* event) {
101 return instance()->DoJitCodeEventHandler(event);
102 }
103
104 void DoJitCodeEventHandler(const v8::JitCodeEvent* event) {
105 switch (event->type) {
yurys 2014/09/24 13:44:07 We should ignore code events after the sample is t
alph 2014/09/24 14:00:51 Nice catch! Done.
106 case v8::JitCodeEvent::CODE_ADDED: {
107 CodeEventEntry entry;
108 entry.name = std::string(event->name.str, event->name.len);
109 entry.code_start = event->code_start;
110 entry.code_len = event->code_len;
111 code_entries.insert(std::make_pair(entry.code_start, entry));
112 break;
113 }
114 case v8::JitCodeEvent::CODE_MOVED: {
115 CodeEntries::const_iterator it = code_entries.find(event->code_start);
116 CHECK(it != code_entries.end());
117 code_entries.erase(it);
118 CodeEventEntry entry;
119 entry.name = std::string(event->name.str, event->name.len);
120 entry.code_start = event->new_code_start;
121 entry.code_len = event->code_len;
122 code_entries.insert(std::make_pair(entry.code_start, entry));
123 break;
124 }
125 case v8::JitCodeEvent::CODE_REMOVED:
126 code_entries.erase(event->code_start);
127 break;
128 default:
129 break;
130 }
131 }
132
133 const CodeEventEntry* FindEventEntry(const void* address) {
134 CodeEntries::const_iterator it = code_entries.upper_bound(address);
135 if (it == code_entries.begin()) return NULL;
136 const CodeEventEntry& entry = (--it)->second;
137 const void* code_end =
138 static_cast<const uint8_t*>(entry.code_start) + entry.code_len;
139 return address < code_end ? &entry : NULL;
140 }
141
142 private:
143 Sample sample_;
144 v8::Isolate* isolate;
145 CodeEntries code_entries;
146 };
147
148 } // namespace
149
150
151 // A JavaScript function which takes stack depth
152 // (minimum value 2) as an argument.
153 // When at the bottom of the recursion,
154 // the JavaScript code calls into C++ test code,
155 // waiting for the sampler to take a sample.
156 static const char* test_function =
157 "function func(depth) {"
158 " if (depth == 2) CollectSample();"
159 " else return func(depth - 1);"
160 "}";
161
162
163 TEST(StackDepthIsConsistent) {
164 SamplingTestHelper helper(std::string(test_function) + "func(8);");
165 CHECK_EQ(8, helper.get_sample().size());
166 }
167
168
169 TEST(StackDepthDoesNotExceedMaxValue) {
170 SamplingTestHelper helper(std::string(test_function) + "func(300);");
171 CHECK_EQ(Sample::kFramesLimit, helper.get_sample().size());
172 }
173
174
175 // The captured sample should have three pc values.
176 // They should fall in the range where the compiled code resides.
177 // The expected stack is:
178 // bottom of stack [{anon script}, outer, inner] top of stack
179 // ^ ^ ^
180 // sample.stack indices 2 1 0
181 TEST(StackFramesConsistent) {
182 // Note: The arguments.callee stuff is there so that the
183 // functions are not optimized away.
184 const char* test_script =
185 "function test_sampler_api_inner() {"
186 " CollectSample();"
187 " return arguments.callee.toString();"
188 "}"
189 "function test_sampler_api_outer() {"
190 " return test_sampler_api_inner() + arguments.callee.toString();"
191 "}"
192 "test_sampler_api_outer();";
193
194 SamplingTestHelper helper(test_script);
195 Sample& sample = helper.get_sample();
196 CHECK_EQ(3, sample.size());
197
198 const SamplingTestHelper::CodeEventEntry* entry;
199 entry = helper.FindEventEntry(sample.begin()[0]);
200 CHECK_NE(NULL, entry);
201 CHECK(std::string::npos != entry->name.find("test_sampler_api_inner"));
202
203 entry = helper.FindEventEntry(sample.begin()[1]);
204 CHECK_NE(NULL, entry);
205 CHECK(std::string::npos != entry->name.find("test_sampler_api_outer"));
206 }
OLDNEW
« no previous file with comments | « test/cctest/test-api.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698