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

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

Issue 578163002: Implemented GetSample. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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
« src/api.cc ('K') | « test/cctest/cctest.gyp ('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 <string>
8 #include "include/v8.h"
9 #include "src/v8.h"
10 #include "test/cctest/cctest.h"
11
12 #if V8_OS_POSIX && !V8_OS_CYGWIN
13 #include <ucontext.h>
14 #elif V8_OS_WIN || V8_OS_CYGWIN
15 #include "src/base/win32-headers.h"
16 #endif
17
18 using v8::Local;
19
20 namespace {
21 // The Sample which CollectSample fills up
22 v8::Sample* sample;
23
24 // The isolate used in the test
25 v8::Isolate* isolate;
26
27 // Forward declaration
28 // (platform specific implementation at the bottom of this file)
29 void GetStackAndFramePointers(void** sp, void** fp);
30
31 // The JavaScript calls this function when on full stack depth.
32 void CollectSample(const v8::FunctionCallbackInfo<v8::Value>& args) {
33 void* sp = NULL;
34 void* fp = NULL;
35 GetStackAndFramePointers(&sp, &fp);
36 isolate->GetSample(sp, fp, sample);
37 }
38
39
40 // A JavaScript function which takes stack depth
41 // (minimum value 2) as an argument.
42 // When at the bottom of the recursion,
43 // the JavaScript code calls into C++ test code,
44 // waiting for the sampler to take a sample.
45 static const char* test_function =
46 "function func(depth) {"
47 " if (depth == 2) CollectSample();"
48 " else return func(depth - 1);"
49 "}";
50 }
51
52
53 #define SAMPLER_API_TESTS_BOOTSTRAP() \
54 v8::Sample sample_; \
55 sample = &sample_; \
56 isolate = CcTest::isolate(); \
57 v8::HandleScope scope(isolate); \
58 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); \
59 global->Set(v8::String::NewFromUtf8(isolate, "CollectSample"), \
60 v8::FunctionTemplate::New(isolate, CollectSample)); \
61 LocalContext env(isolate, NULL, global)
62
63
64 TEST(StackDepthIsConsistent) {
65 SAMPLER_API_TESTS_BOOTSTRAP();
66
67 std::string source(test_function);
68 source.append("func(8);");
69 v8::Script::Compile(v8::String::NewFromUtf8(isolate, source.c_str()))->Run();
70
71 CHECK_EQ(8, sample->size());
72 }
73
74
75 TEST(StackDepthDoesNotExceedMaxValue) {
76 SAMPLER_API_TESTS_BOOTSTRAP();
77
78 std::string source(test_function);
79 source.append("func(300);");
80 v8::Script::Compile(v8::String::NewFromUtf8(isolate, source.c_str()))->Run();
81
82 int MAX_SIZE = v8::Sample::kMaxSize;
83 CHECK_EQ(MAX_SIZE, sample->size());
84 }
85
86
87 namespace {
88 std::vector<v8::JitCodeEvent> inner_funcs;
89 std::vector<v8::JitCodeEvent> outer_funcs;
90
91 void TestJitCodeEventHandler(const v8::JitCodeEvent* event) {
92 if (event->type != v8::JitCodeEvent::CODE_ADDED) return;
93 std::string name(event->name.str, event->name.len);
94 if (name.find("test_sampler_api_inner") != std::string::npos)
95 inner_funcs.push_back(*event);
96 if (name.find("test_sampler_api_outer") != std::string::npos)
97 outer_funcs.push_back(*event);
98 }
99
100
101 // Note: The argumnets.callee stuff is there so that the
alph 2014/09/18 11:34:29 typo
gholap 2014/09/18 23:24:15 Done.
102 // functions are not optimized away.
103 static const char* test_script =
104 "function test_sampler_api_inner() {"
105 " CollectSample();"
106 " return arguments.callee.toString();"
107 "}"
108 "function test_sampler_api_outer() {"
109 " return test_sampler_api_inner() + arguments.callee.toString();"
110 "}"
111 "test_sampler_api_outer();";
112 }
113
114
115 // The captured sample should have three pc values.
116 // They should fall in the range where the compiled code
117 // The expected stack is:
118 // bottom of stack [{anon script}, outer, inner] top of stack
119 // ^ ^ ^
120 // sample.stack indices 2 1 0
121 TEST(StackFramesConsistent) {
122 SAMPLER_API_TESTS_BOOTSTRAP();
123
124 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
125 TestJitCodeEventHandler);
126 v8::Script::Compile(v8::String::NewFromUtf8(isolate, test_script))->Run();
127
128 CHECK_EQ(3, sample->size());
129
130 bool stack_top_is_inner = false;
131 bool below_inner_is_outer = false;
132
133 for (unsigned i = 0; i < inner_funcs.size(); i++) {
134 void* start_addr = inner_funcs[i].code_start;
135 void* end_addr = reinterpret_cast<void*>(
136 (int64_t)inner_funcs[i].code_start + inner_funcs[i].code_len);
137 if ((*sample->begin() >= start_addr) && (*sample->begin() < end_addr))
138 stack_top_is_inner = true;
139 }
140
141 for (unsigned i = 0; i < outer_funcs.size(); i++) {
142 void* start_addr = outer_funcs[i].code_start;
143 void* end_addr = reinterpret_cast<void*>(
144 (int64_t)outer_funcs[i].code_start + outer_funcs[i].code_len);
145 if ((*(sample->begin() + 1) >= start_addr) &&
146 (*(sample->begin() + 1) < end_addr))
147 below_inner_is_outer = true;
148 }
149
150 CHECK_EQ(true, stack_top_is_inner);
alph 2014/09/18 11:34:29 CHECK
gholap 2014/09/18 23:24:15 Done.
151 CHECK_EQ(true, below_inner_is_outer);
152 }
153
154
155 // Platform specific implementation of GetStackAndFramePointers
loislo 2014/09/18 14:42:44 this is doesn't look as a good idea. I mean we ha
gholap 2014/09/18 23:24:15 Oh! I did not know that... I checked the TickSampl
156 namespace {
157 #if V8_OS_POSIX && !V8_OS_CYGWIN
158 void GetStackAndFramePointers(void** sp, void** fp) {
159 ucontext_t ucontext;
160 getcontext(&ucontext);
161 #if !V8_OS_OPENBSD
162 mcontext_t& mcontext = ucontext.uc_mcontext;
163 #endif
164 #if V8_OS_LINUX
165 #if V8_HOST_ARCH_IA32
166 *sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
167 *fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
168 #elif V8_HOST_ARCH_X64
169 *sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]);
170 *fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]);
171 #elif V8_HOST_ARCH_ARM
172 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
173 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
174 // Old GLibc ARM versions used a gregs[] array to access the register
175 // values from mcontext_t.
176 *sp = reinterpret_cast<void*>(mcontext.gregs[R13]);
177 *fp = reinterpret_cast<void*>(mcontext.gregs[R11]);
178 #else
179 *sp = reinterpret_cast<void*>(mcontext.arm_sp);
180 *fp = reinterpret_cast<void*>(mcontext.arm_fp);
181 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
182 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
183 #elif V8_HOST_ARCH_ARM64
184 *sp = reinterpret_cast<void*>(mcontext.sp);
185 // FP is an alias for x29.
186 *fp = reinterpret_cast<void*>(mcontext.regs[29]);
187 #elif V8_HOST_ARCH_MIPS
188 *sp = reinterpret_cast<void*>(mcontext.gregs[29]);
189 *fp = reinterpret_cast<void*>(mcontext.gregs[30]);
190 #endif // V8_HOST_ARCH_*
191 #elif V8_OS_MACOSX
192 #if V8_HOST_ARCH_X64
193 #if __DARWIN_UNIX03
194 *sp = reinterpret_cast<void*>(mcontext->__ss.__rsp);
195 *fp = reinterpret_cast<void*>(mcontext->__ss.__rbp);
196 #else // !__DARWIN_UNIX03
197 *sp = reinterpret_cast<void*>(mcontext->ss.rsp);
198 *fp = reinterpret_cast<void*>(mcontext->ss.rbp);
199 #endif // __DARWIN_UNIX03
200 #elif V8_HOST_ARCH_IA32
201 #if __DARWIN_UNIX03
202 *sp = mcontext->__ss.__esp);
203 *fp = mcontext->__ss.__ebp);
204 #else // !__DARWIN_UNIX03
205 *sp = mcontext->ss.esp);
206 *fp = mcontext->ss.ebp);
207 #endif // __DARWIN_UNIX03
208 #endif // V8_HOST_ARCH_IA32
209 #elif V8_OS_FREEBSD
210 #if V8_HOST_ARCH_IA32
211 *sp = reinterpret_cast<void*>(mcontext.mc_esp);
212 *fp = reinterpret_cast<void*>(mcontext.mc_ebp);
213 #elif V8_HOST_ARCH_X64
214 *sp = reinterpret_cast<void*>(mcontext.mc_rsp);
215 *fp = reinterpret_cast<void*>(mcontext.mc_rbp);
216 #elif V8_HOST_ARCH_ARM
217 *sp = reinterpret_cast<void*>(mcontext.mc_r13);
218 *fp = reinterpret_cast<void*>(mcontext.mc_r11);
219 #endif // V8_HOST_ARCH_*
220 #elif V8_OS_NETBSD
221 #if V8_HOST_ARCH_IA32
222 *sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_ESP]);
223 *fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_EBP]);
224 #elif V8_HOST_ARCH_X64
225 *sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RSP]);
226 *fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RBP]);
227 #endif // V8_HOST_ARCH_*
228 #elif V8_OS_OPENBSD
229 #if V8_HOST_ARCH_IA32
230 *sp = reinterpret_cast<void*>(ucontext.sc_esp);
231 *fp = reinterpret_cast<void*>(ucontext.sc_ebp);
232 #elif V8_HOST_ARCH_X64
233 *sp = reinterpret_cast<void*>(ucontext.sc_rsp);
234 *fp = reinterpret_cast<void*>(ucontext.sc_rbp);
235 #endif // V8_HOST_ARCH_*
236 #elif V8_OS_SOLARIS
237 *sp = reinterpret_cast<void*>(mcontext.gregs[REG_SP]);
238 *fp = reinterpret_cast<void*>(mcontext.gregs[REG_FP]);
239 #elif V8_OS_QNX
240 #if V8_HOST_ARCH_IA32
241 *sp = reinterpret_cast<void*>(mcontext.cpu.esp);
242 *fp = reinterpret_cast<void*>(mcontext.cpu.ebp);
243 #elif V8_HOST_ARCH_ARM
244 *sp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_SP]);
245 *fp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_FP]);
246 #endif // V8_HOST_ARCH_*
247 #endif // V8_OS_QNX
248 }
249 #elif V8_OS_WIN || V8_OS_CYGWIN
250 void GetStackAndFramePointers(void** sp, void** fp) {
alph 2014/09/18 11:34:29 you can move the function name & args out of #ifde
gholap 2014/09/18 23:24:15 Done.
251 CONTEXT context;
252 memset(&context, 0, sizeof(context));
253 context.ContextFlags = CONTEXT_FULL;
254 GetThreadContext(OpenThread(THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME |
255 THREAD_QUERY_INFORMATION,
256 false, GetCurrentThreadId()),
257 &context);
258 #if V8_HOST_ARCH_X64
259 *sp = reinterpret_cast<void*>(context.Rsp);
260 *fp = reinterpret_cast<void*>(context.Rbp);
261 #else
262 *sp = reinterpret_cast<void*>(context.Esp);
263 *fp = reinterpret_cast<void*>(context.Ebp);
264 #endif // V8_HOST_ARCH_X64
265 }
266 #endif // V8_OS_POSIX && !V8_OS_CYGWIN / V8_OS_WIN || V8_OS_CYGWIN
267 }
OLDNEW
« src/api.cc ('K') | « test/cctest/cctest.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698