Fix assertion when collecting stack trace from debug break.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Apr 2014 12:08:17 +0000 (12:08 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 28 Apr 2014 12:08:17 +0000 (12:08 +0000)
R=mstarzinger@chromium.org
BUG=v8:3296
LOG=N

Review URL: https://codereview.chromium.org/256113003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21015 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/frames.cc
test/cctest/test-debug.cc

index 46dd5ef..e6fee95 100644 (file)
@@ -990,13 +990,10 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
       it.Next();  // Skip height.
 
       // The translation commands are ordered and the receiver is always
-      // at the first position. Since we are always at a call when we need
-      // to construct a stack trace, the receiver is always in a stack slot.
+      // at the first position.
+      // If we are at a call, the receiver is always in a stack slot.
+      // Otherwise we are not guaranteed to get the receiver value.
       opcode = static_cast<Translation::Opcode>(it.Next());
-      ASSERT(opcode == Translation::STACK_SLOT ||
-             opcode == Translation::LITERAL ||
-             opcode == Translation::CAPTURED_OBJECT ||
-             opcode == Translation::DUPLICATED_OBJECT);
       int index = it.Next();
 
       // Get the correct receiver in the optimized frame.
@@ -1020,6 +1017,7 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
               : this->GetParameter(parameter_index);
         }
       } else {
+        // The receiver is not in a stack slot nor in a literal.  We give up.
         // TODO(3029): Materializing a captured object (or duplicated
         // object) is hard, we return undefined for now. This breaks the
         // produced stack trace, as constructor frames aren't marked as
index a11c030..85e4512 100644 (file)
@@ -7659,3 +7659,34 @@ TEST(PrecompiledFunction) {
   v8::Debug::SetDebugEventListener2(NULL);
   CheckDebuggerUnloaded();
 }
+
+
+static void DebugBreakStackTraceListener(
+    const v8::Debug::EventDetails& event_details) {
+  v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
+}
+
+
+static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Debug::DebugBreak(args.GetIsolate());
+}
+
+
+TEST(DebugBreakStackTrace) {
+  DebugLocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::Debug::SetDebugEventListener2(DebugBreakStackTraceListener);
+  v8::Handle<v8::FunctionTemplate> add_debug_break_template =
+      v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
+  v8::Handle<v8::Function> add_debug_break =
+      add_debug_break_template->GetFunction();
+  env->Global()->Set(v8_str("add_debug_break"), add_debug_break);
+
+  CompileRun("(function loop() {"
+             "  for (var j = 0; j < 1000; j++) {"
+             "    for (var i = 0; i < 1000; i++) {"
+             "      if (i == 999) add_debug_break();"
+             "    }"
+             "  }"
+             "})()");
+}