| Index: test/cctest/test-log-stack-tracer.cc
|
| diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
|
| index d96e5e787877081c115ce716f05d0000776a4698..532311bfbc212a31cccccacaf7e9674997f62615 100644
|
| --- a/test/cctest/test-log-stack-tracer.cc
|
| +++ b/test/cctest/test-log-stack-tracer.cc
|
| @@ -284,12 +284,18 @@ static void CreateTraceCallerFunction(const char* func_name,
|
| }
|
|
|
|
|
| +// This test verifies that stack tracing works when called during
|
| +// execution of a native function called from JS code. In this case,
|
| +// StackTracer uses Top::c_entry_fp as a starting point for stack
|
| +// walking.
|
| TEST(CFromJSStackTrace) {
|
| TickSample sample;
|
| InitTraceEnv(&sample);
|
|
|
| InitializeVM();
|
| v8::HandleScope scope;
|
| + // Create global function JSFuncDoTrace which calls
|
| + // extension function trace() with the current frame pointer value.
|
| CreateTraceCallerFunction("JSFuncDoTrace", "trace");
|
| Local<Value> result = CompileRun(
|
| "function JSTrace() {"
|
| @@ -298,8 +304,15 @@ TEST(CFromJSStackTrace) {
|
| "JSTrace();\n"
|
| "true;");
|
| CHECK(!result.IsEmpty());
|
| + // When stack tracer is invoked, the stack should look as follows:
|
| + // script [JS]
|
| + // JSTrace() [JS]
|
| + // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
|
| + // trace(EBP encoded as Smi) [native (extension)]
|
| + // DoTrace(EBP) [native]
|
| + // StackTracer::Trace
|
| CHECK_GT(sample.frames_count, 1);
|
| - // Stack sampling will start from the first JS function, i.e. "JSFuncDoTrace"
|
| + // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
|
| CheckRetAddrIsInJSFunction("JSFuncDoTrace",
|
| sample.stack[0]);
|
| CheckRetAddrIsInJSFunction("JSTrace",
|
| @@ -307,12 +320,19 @@ TEST(CFromJSStackTrace) {
|
| }
|
|
|
|
|
| +// This test verifies that stack tracing works when called during
|
| +// execution of JS code. However, as calling StackTracer requires
|
| +// entering native code, we can only emulate pure JS by erasing
|
| +// Top::c_entry_fp value. In this case, StackTracer uses passed frame
|
| +// pointer value as a starting point for stack walking.
|
| TEST(PureJSStackTrace) {
|
| TickSample sample;
|
| InitTraceEnv(&sample);
|
|
|
| InitializeVM();
|
| v8::HandleScope scope;
|
| + // Create global function JSFuncDoTrace which calls
|
| + // extension function js_trace() with the current frame pointer value.
|
| CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
|
| Local<Value> result = CompileRun(
|
| "function JSTrace() {"
|
| @@ -324,7 +344,17 @@ TEST(PureJSStackTrace) {
|
| "OuterJSTrace();\n"
|
| "true;");
|
| CHECK(!result.IsEmpty());
|
| - // The last JS function called.
|
| + // When stack tracer is invoked, the stack should look as follows:
|
| + // script [JS]
|
| + // OuterJSTrace() [JS]
|
| + // JSTrace() [JS]
|
| + // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
|
| + // js_trace(EBP encoded as Smi) [native (extension)]
|
| + // DoTraceHideCEntryFPAddress(EBP) [native]
|
| + // StackTracer::Trace
|
| + //
|
| + // The last JS function called. It is only visible through
|
| + // sample.function, as its return address is above captured EBP value.
|
| CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(),
|
| sample.function);
|
| CHECK_GT(sample.frames_count, 1);
|
| @@ -361,6 +391,9 @@ static int CFunc(int depth) {
|
| }
|
|
|
|
|
| +// This test verifies that stack tracing doesn't crash when called on
|
| +// pure native code. StackTracer only unrolls JS code, so we can't
|
| +// get any meaningful info here.
|
| TEST(PureCStackTrace) {
|
| TickSample sample;
|
| InitTraceEnv(&sample);
|
|
|