OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // | 2 // |
3 // Tests of profiler-related functions from log.h | 3 // Tests of profiler-related functions from log.h |
4 | 4 |
5 #ifdef ENABLE_LOGGING_AND_PROFILING | 5 #ifdef ENABLE_LOGGING_AND_PROFILING |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 | 10 |
11 #include "codegen.h" | 11 #include "codegen.h" |
12 #include "log.h" | 12 #include "log.h" |
13 #include "top.h" | 13 #include "top.h" |
14 #include "cctest.h" | 14 #include "cctest.h" |
15 #include "disassembler.h" | 15 #include "disassembler.h" |
16 #include "register-allocator-inl.h" | 16 #include "register-allocator-inl.h" |
17 | 17 |
18 using v8::Function; | 18 using v8::Function; |
19 using v8::Local; | 19 using v8::Local; |
20 using v8::Object; | 20 using v8::Object; |
21 using v8::Script; | 21 using v8::Script; |
22 using v8::String; | 22 using v8::String; |
23 using v8::Value; | 23 using v8::Value; |
24 | 24 |
25 using v8::internal::byte; | 25 using v8::internal::byte; |
26 using v8::internal::Address; | 26 using v8::internal::Address; |
27 using v8::internal::Handle; | 27 using v8::internal::Handle; |
28 using v8::internal::JSFunction; | 28 using v8::internal::JSFunction; |
29 using v8::internal::SharedFunctionInfo; | |
30 using v8::internal::StackTracer; | 29 using v8::internal::StackTracer; |
31 using v8::internal::TickSample; | 30 using v8::internal::TickSample; |
32 using v8::internal::Top; | 31 using v8::internal::Top; |
33 | 32 |
34 namespace i = v8::internal; | 33 namespace i = v8::internal; |
35 | 34 |
36 | 35 |
37 static v8::Persistent<v8::Context> env; | 36 static v8::Persistent<v8::Context> env; |
38 | 37 |
39 | 38 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 Address ret_addr, | 70 Address ret_addr, |
72 Address func_start_addr, | 71 Address func_start_addr, |
73 unsigned int func_len) { | 72 unsigned int func_len) { |
74 printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n", | 73 printf("CheckRetAddrIsInFunction \"%s\": %p %p %p\n", |
75 func_name, func_start_addr, ret_addr, func_start_addr + func_len); | 74 func_name, func_start_addr, ret_addr, func_start_addr + func_len); |
76 CHECK_GE(ret_addr, func_start_addr); | 75 CHECK_GE(ret_addr, func_start_addr); |
77 CHECK_GE(func_start_addr + func_len, ret_addr); | 76 CHECK_GE(func_start_addr + func_len, ret_addr); |
78 } | 77 } |
79 | 78 |
80 | 79 |
81 static void CheckRetAddrIsInSharedFunctionInfo( | 80 static void CheckRetAddrIsInJSFunction(const char* func_name, |
82 const char* func_name, | 81 Address ret_addr, |
83 Address ret_addr, | 82 Handle<JSFunction> func) { |
84 Handle<SharedFunctionInfo> func) { | |
85 v8::internal::Code* func_code = func->code(); | 83 v8::internal::Code* func_code = func->code(); |
86 CheckRetAddrIsInFunction( | 84 CheckRetAddrIsInFunction( |
87 func_name, ret_addr, | 85 func_name, ret_addr, |
88 func_code->instruction_start(), | 86 func_code->instruction_start(), |
89 func_code->ExecutableSize()); | 87 func_code->ExecutableSize()); |
90 } | 88 } |
91 | 89 |
92 | 90 |
93 // --- T r a c e E x t e n s i o n --- | 91 // --- T r a c e E x t e n s i o n --- |
94 | 92 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 v8::HandleScope scope; | 183 v8::HandleScope scope; |
186 const char* extensions[] = { "v8/trace" }; | 184 const char* extensions[] = { "v8/trace" }; |
187 v8::ExtensionConfiguration config(1, extensions); | 185 v8::ExtensionConfiguration config(1, extensions); |
188 env = v8::Context::New(&config); | 186 env = v8::Context::New(&config); |
189 } | 187 } |
190 v8::HandleScope scope; | 188 v8::HandleScope scope; |
191 env->Enter(); | 189 env->Enter(); |
192 } | 190 } |
193 | 191 |
194 | 192 |
195 static Handle<SharedFunctionInfo> CompileFunction(const char* source) { | 193 static Handle<JSFunction> CompileFunction(const char* source) { |
196 Handle<v8::internal::Object> obj = | 194 Handle<JSFunction> result(JSFunction::cast( |
197 v8::Utils::OpenHandle(*Script::Compile(String::New(source))); | 195 *v8::Utils::OpenHandle(*Script::Compile(String::New(source))))); |
198 Handle<SharedFunctionInfo> shared; | 196 return result; |
199 if (obj->IsSharedFunctionInfo()) { | |
200 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(*obj)); | |
201 } else { | |
202 shared = Handle<SharedFunctionInfo>(JSFunction::cast(*obj)->shared()); | |
203 } | |
204 return shared; | |
205 } | 197 } |
206 | 198 |
207 | 199 |
208 static Local<Value> GetGlobalProperty(const char* name) { | 200 static Local<Value> GetGlobalProperty(const char* name) { |
209 return env->Global()->Get(String::New(name)); | 201 return env->Global()->Get(String::New(name)); |
210 } | 202 } |
211 | 203 |
212 | 204 |
213 static Handle<SharedFunctionInfo> GetGlobalJSFunction(const char* name) { | 205 static Handle<JSFunction> GetGlobalJSFunction(const char* name) { |
214 Handle<SharedFunctionInfo> js_func( | 206 Handle<JSFunction> result(JSFunction::cast( |
215 SharedFunctionInfo::cast( | 207 *v8::Utils::OpenHandle(*GetGlobalProperty(name)))); |
216 *(v8::Utils::OpenHandle(*GetGlobalProperty(name))))); | 208 return result; |
217 return js_func; | |
218 } | 209 } |
219 | 210 |
220 | 211 |
221 static void CheckRetAddrIsInSharedFunctionInfo(const char* func_name, | 212 static void CheckRetAddrIsInJSFunction(const char* func_name, |
222 Address ret_addr) { | 213 Address ret_addr) { |
223 CheckRetAddrIsInSharedFunctionInfo(func_name, | 214 CheckRetAddrIsInJSFunction(func_name, |
224 ret_addr, | 215 ret_addr, |
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
225 GetGlobalJSFunction(func_name)); | 216 GetGlobalJSFunction(func_name)); |
226 } | 217 } |
227 | 218 |
228 | 219 |
229 static void SetGlobalProperty(const char* name, Local<Value> value) { | 220 static void SetGlobalProperty(const char* name, Local<Value> value) { |
230 env->Global()->Set(String::New(name), value); | 221 env->Global()->Set(String::New(name), value); |
231 } | 222 } |
232 | 223 |
233 | 224 |
234 static Handle<v8::internal::String> NewString(const char* s) { | 225 static Handle<v8::internal::String> NewString(const char* s) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 // shifted right to be presented as Smi. | 262 // shifted right to be presented as Smi. |
272 static void CreateTraceCallerFunction(const char* func_name, | 263 static void CreateTraceCallerFunction(const char* func_name, |
273 const char* trace_func_name) { | 264 const char* trace_func_name) { |
274 i::EmbeddedVector<char, 256> trace_call_buf; | 265 i::EmbeddedVector<char, 256> trace_call_buf; |
275 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); | 266 i::OS::SNPrintF(trace_call_buf, "%s(%%_GetFramePointer());", trace_func_name); |
276 | 267 |
277 // Compile the script. | 268 // Compile the script. |
278 i::CodeGeneratorPatcher patcher; | 269 i::CodeGeneratorPatcher patcher; |
279 bool allow_natives_syntax = i::FLAG_allow_natives_syntax; | 270 bool allow_natives_syntax = i::FLAG_allow_natives_syntax; |
280 i::FLAG_allow_natives_syntax = true; | 271 i::FLAG_allow_natives_syntax = true; |
281 Handle<SharedFunctionInfo> func = CompileFunction(trace_call_buf.start()); | 272 Handle<JSFunction> func = CompileFunction(trace_call_buf.start()); |
282 CHECK(!func.is_null()); | 273 CHECK(!func.is_null()); |
283 i::FLAG_allow_natives_syntax = allow_natives_syntax; | 274 i::FLAG_allow_natives_syntax = allow_natives_syntax; |
284 | 275 |
285 #ifdef DEBUG | 276 #ifdef DEBUG |
286 v8::internal::Code* func_code = func->code(); | 277 v8::internal::Code* func_code = func->code(); |
287 CHECK(func_code->IsCode()); | 278 CHECK(func_code->IsCode()); |
288 func_code->Print(); | 279 func_code->Print(); |
289 #endif | 280 #endif |
290 | 281 |
291 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); | 282 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); |
283 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); | |
292 } | 284 } |
293 | 285 |
294 | 286 |
295 TEST(CFromJSStackTrace) { | 287 TEST(CFromJSStackTrace) { |
296 // TODO(657): Fixup test after FunctionBoilerplate removal. | |
297 return; | |
298 | |
299 TickSample sample; | 288 TickSample sample; |
300 InitTraceEnv(&sample); | 289 InitTraceEnv(&sample); |
301 | 290 |
302 InitializeVM(); | 291 InitializeVM(); |
303 v8::HandleScope scope; | 292 v8::HandleScope scope; |
304 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); | 293 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); |
305 CompileRun( | 294 CHECK(!CompileRun( |
Kasper Lund
2010/03/23 11:53:28
I would create a local handle for the result and d
mnaganov (inactive)
2010/03/23 12:39:18
Good point. Done.
| |
306 "function JSTrace() {" | 295 "function JSTrace() {" |
307 " JSFuncDoTrace();" | 296 " JSFuncDoTrace();" |
308 "};\n" | 297 "};\n" |
309 "JSTrace();"); | 298 "JSTrace();\n" |
299 "true;").IsEmpty()); | |
310 CHECK_GT(sample.frames_count, 1); | 300 CHECK_GT(sample.frames_count, 1); |
311 // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace" | 301 // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace" |
312 CheckRetAddrIsInSharedFunctionInfo("JSFuncDoTrace", | 302 CheckRetAddrIsInJSFunction("JSFuncDoTrace", |
313 sample.stack[0]); | 303 sample.stack[0]); |
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
314 CheckRetAddrIsInSharedFunctionInfo("JSTrace", | 304 CheckRetAddrIsInJSFunction("JSTrace", |
315 sample.stack[1]); | 305 sample.stack[1]); |
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
316 } | 306 } |
317 | 307 |
318 | 308 |
319 TEST(PureJSStackTrace) { | 309 TEST(PureJSStackTrace) { |
320 // TODO(657): Fixup test after FunctionBoilerplate removal. | |
321 return; | |
322 | |
323 TickSample sample; | 310 TickSample sample; |
324 InitTraceEnv(&sample); | 311 InitTraceEnv(&sample); |
325 | 312 |
326 InitializeVM(); | 313 InitializeVM(); |
327 v8::HandleScope scope; | 314 v8::HandleScope scope; |
328 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); | 315 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); |
329 CompileRun( | 316 CHECK(!CompileRun( |
Kasper Lund
2010/03/23 11:53:28
I would create a local handle for the result and d
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
330 "function JSTrace() {" | 317 "function JSTrace() {" |
331 " JSFuncDoTrace();" | 318 " JSFuncDoTrace();" |
332 "};\n" | 319 "};\n" |
333 "function OuterJSTrace() {" | 320 "function OuterJSTrace() {" |
334 " JSTrace();" | 321 " JSTrace();" |
335 "};\n" | 322 "};\n" |
336 "OuterJSTrace();"); | 323 "OuterJSTrace();\n" |
324 "true;").IsEmpty()); | |
337 // The last JS function called. | 325 // The last JS function called. |
338 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), | 326 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), |
339 sample.function); | 327 sample.function); |
340 CHECK_GT(sample.frames_count, 1); | 328 CHECK_GT(sample.frames_count, 1); |
341 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" | 329 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" |
342 CheckRetAddrIsInSharedFunctionInfo("JSTrace", | 330 CheckRetAddrIsInJSFunction("JSTrace", |
343 sample.stack[0]); | 331 sample.stack[0]); |
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
344 CheckRetAddrIsInSharedFunctionInfo("OuterJSTrace", | 332 CheckRetAddrIsInJSFunction("OuterJSTrace", |
345 sample.stack[1]); | 333 sample.stack[1]); |
Kasper Lund
2010/03/23 11:53:28
Indentation.
mnaganov (inactive)
2010/03/23 12:39:18
Done.
| |
346 } | 334 } |
347 | 335 |
348 | 336 |
349 static void CFuncDoTrace(byte dummy_parameter) { | 337 static void CFuncDoTrace(byte dummy_parameter) { |
350 Address fp; | 338 Address fp; |
351 #ifdef __GNUC__ | 339 #ifdef __GNUC__ |
352 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); | 340 fp = reinterpret_cast<Address>(__builtin_frame_address(0)); |
353 #elif defined _MSC_VER | 341 #elif defined _MSC_VER |
354 // Approximate a frame pointer address. We compile without base pointers, | 342 // Approximate a frame pointer address. We compile without base pointers, |
355 // so we can't trust ebp/rbp. | 343 // so we can't trust ebp/rbp. |
(...skipping 29 matching lines...) Expand all Loading... | |
385 CHECK_EQ(0, GetJsEntrySp()); | 373 CHECK_EQ(0, GetJsEntrySp()); |
386 CompileRun("a = 1; b = a + 1;"); | 374 CompileRun("a = 1; b = a + 1;"); |
387 CHECK_EQ(0, GetJsEntrySp()); | 375 CHECK_EQ(0, GetJsEntrySp()); |
388 CompileRun("js_entry_sp();"); | 376 CompileRun("js_entry_sp();"); |
389 CHECK_EQ(0, GetJsEntrySp()); | 377 CHECK_EQ(0, GetJsEntrySp()); |
390 CompileRun("js_entry_sp_level2();"); | 378 CompileRun("js_entry_sp_level2();"); |
391 CHECK_EQ(0, GetJsEntrySp()); | 379 CHECK_EQ(0, GetJsEntrySp()); |
392 } | 380 } |
393 | 381 |
394 #endif // ENABLE_LOGGING_AND_PROFILING | 382 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |