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 |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 v8::internal::Code* func_code = func->code(); | 277 v8::internal::Code* func_code = func->code(); |
278 CHECK(func_code->IsCode()); | 278 CHECK(func_code->IsCode()); |
279 func_code->Print(); | 279 func_code->Print(); |
280 #endif | 280 #endif |
281 | 281 |
282 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); | 282 SetGlobalProperty(func_name, v8::ToApi<Value>(func)); |
283 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); | 283 CHECK_EQ(*func, *GetGlobalJSFunction(func_name)); |
284 } | 284 } |
285 | 285 |
286 | 286 |
| 287 // This test verifies that stack tracing works when called during |
| 288 // execution of a native function called from JS code. In this case, |
| 289 // StackTracer uses Top::c_entry_fp as a starting point for stack |
| 290 // walking. |
287 TEST(CFromJSStackTrace) { | 291 TEST(CFromJSStackTrace) { |
288 TickSample sample; | 292 TickSample sample; |
289 InitTraceEnv(&sample); | 293 InitTraceEnv(&sample); |
290 | 294 |
291 InitializeVM(); | 295 InitializeVM(); |
292 v8::HandleScope scope; | 296 v8::HandleScope scope; |
| 297 // Create global function JSFuncDoTrace which calls |
| 298 // extension function trace() with the current frame pointer value. |
293 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); | 299 CreateTraceCallerFunction("JSFuncDoTrace", "trace"); |
294 Local<Value> result = CompileRun( | 300 Local<Value> result = CompileRun( |
295 "function JSTrace() {" | 301 "function JSTrace() {" |
296 " JSFuncDoTrace();" | 302 " JSFuncDoTrace();" |
297 "};\n" | 303 "};\n" |
298 "JSTrace();\n" | 304 "JSTrace();\n" |
299 "true;"); | 305 "true;"); |
300 CHECK(!result.IsEmpty()); | 306 CHECK(!result.IsEmpty()); |
| 307 // When stack tracer is invoked, the stack should look as follows: |
| 308 // script [JS] |
| 309 // JSTrace() [JS] |
| 310 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] |
| 311 // trace(EBP encoded as Smi) [native (extension)] |
| 312 // DoTrace(EBP) [native] |
| 313 // StackTracer::Trace |
301 CHECK_GT(sample.frames_count, 1); | 314 CHECK_GT(sample.frames_count, 1); |
302 // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace" | 315 // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" |
303 CheckRetAddrIsInJSFunction("JSFuncDoTrace", | 316 CheckRetAddrIsInJSFunction("JSFuncDoTrace", |
304 sample.stack[0]); | 317 sample.stack[0]); |
305 CheckRetAddrIsInJSFunction("JSTrace", | 318 CheckRetAddrIsInJSFunction("JSTrace", |
306 sample.stack[1]); | 319 sample.stack[1]); |
307 } | 320 } |
308 | 321 |
309 | 322 |
| 323 // This test verifies that stack tracing works when called during |
| 324 // execution of JS code. However, as calling StackTracer requires |
| 325 // entering native code, we can only emulate pure JS by erasing |
| 326 // Top::c_entry_fp value. In this case, StackTracer uses passed frame |
| 327 // pointer value as a starting point for stack walking. |
310 TEST(PureJSStackTrace) { | 328 TEST(PureJSStackTrace) { |
311 TickSample sample; | 329 TickSample sample; |
312 InitTraceEnv(&sample); | 330 InitTraceEnv(&sample); |
313 | 331 |
314 InitializeVM(); | 332 InitializeVM(); |
315 v8::HandleScope scope; | 333 v8::HandleScope scope; |
| 334 // Create global function JSFuncDoTrace which calls |
| 335 // extension function js_trace() with the current frame pointer value. |
316 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); | 336 CreateTraceCallerFunction("JSFuncDoTrace", "js_trace"); |
317 Local<Value> result = CompileRun( | 337 Local<Value> result = CompileRun( |
318 "function JSTrace() {" | 338 "function JSTrace() {" |
319 " JSFuncDoTrace();" | 339 " JSFuncDoTrace();" |
320 "};\n" | 340 "};\n" |
321 "function OuterJSTrace() {" | 341 "function OuterJSTrace() {" |
322 " JSTrace();" | 342 " JSTrace();" |
323 "};\n" | 343 "};\n" |
324 "OuterJSTrace();\n" | 344 "OuterJSTrace();\n" |
325 "true;"); | 345 "true;"); |
326 CHECK(!result.IsEmpty()); | 346 CHECK(!result.IsEmpty()); |
327 // The last JS function called. | 347 // When stack tracer is invoked, the stack should look as follows: |
| 348 // script [JS] |
| 349 // OuterJSTrace() [JS] |
| 350 // JSTrace() [JS] |
| 351 // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi] |
| 352 // js_trace(EBP encoded as Smi) [native (extension)] |
| 353 // DoTraceHideCEntryFPAddress(EBP) [native] |
| 354 // StackTracer::Trace |
| 355 // |
| 356 // The last JS function called. It is only visible through |
| 357 // sample.function, as its return address is above captured EBP value. |
328 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), | 358 CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(), |
329 sample.function); | 359 sample.function); |
330 CHECK_GT(sample.frames_count, 1); | 360 CHECK_GT(sample.frames_count, 1); |
331 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" | 361 // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace" |
332 CheckRetAddrIsInJSFunction("JSTrace", | 362 CheckRetAddrIsInJSFunction("JSTrace", |
333 sample.stack[0]); | 363 sample.stack[0]); |
334 CheckRetAddrIsInJSFunction("OuterJSTrace", | 364 CheckRetAddrIsInJSFunction("OuterJSTrace", |
335 sample.stack[1]); | 365 sample.stack[1]); |
336 } | 366 } |
337 | 367 |
(...skipping 16 matching lines...) Expand all Loading... |
354 static int CFunc(int depth) { | 384 static int CFunc(int depth) { |
355 if (depth <= 0) { | 385 if (depth <= 0) { |
356 CFuncDoTrace(0); | 386 CFuncDoTrace(0); |
357 return 0; | 387 return 0; |
358 } else { | 388 } else { |
359 return CFunc(depth - 1) + 1; | 389 return CFunc(depth - 1) + 1; |
360 } | 390 } |
361 } | 391 } |
362 | 392 |
363 | 393 |
| 394 // This test verifies that stack tracing doesn't crash when called on |
| 395 // pure native code. StackTracer only unrolls JS code, so we can't |
| 396 // get any meaningful info here. |
364 TEST(PureCStackTrace) { | 397 TEST(PureCStackTrace) { |
365 TickSample sample; | 398 TickSample sample; |
366 InitTraceEnv(&sample); | 399 InitTraceEnv(&sample); |
367 // Check that sampler doesn't crash | 400 // Check that sampler doesn't crash |
368 CHECK_EQ(10, CFunc(10)); | 401 CHECK_EQ(10, CFunc(10)); |
369 } | 402 } |
370 | 403 |
371 | 404 |
372 TEST(JsEntrySp) { | 405 TEST(JsEntrySp) { |
373 InitializeVM(); | 406 InitializeVM(); |
374 v8::HandleScope scope; | 407 v8::HandleScope scope; |
375 CHECK_EQ(0, GetJsEntrySp()); | 408 CHECK_EQ(0, GetJsEntrySp()); |
376 CompileRun("a = 1; b = a + 1;"); | 409 CompileRun("a = 1; b = a + 1;"); |
377 CHECK_EQ(0, GetJsEntrySp()); | 410 CHECK_EQ(0, GetJsEntrySp()); |
378 CompileRun("js_entry_sp();"); | 411 CompileRun("js_entry_sp();"); |
379 CHECK_EQ(0, GetJsEntrySp()); | 412 CHECK_EQ(0, GetJsEntrySp()); |
380 CompileRun("js_entry_sp_level2();"); | 413 CompileRun("js_entry_sp_level2();"); |
381 CHECK_EQ(0, GetJsEntrySp()); | 414 CHECK_EQ(0, GetJsEntrySp()); |
382 } | 415 } |
383 | 416 |
384 #endif // ENABLE_LOGGING_AND_PROFILING | 417 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |