Reviewers: Søren Thygesen Gjesse,

Message:
Please take a look.

Description:
Find correct source position in inlined functions on debug break.

BUG=110010
TEST=test-debug/DebugBreakInline


Please review this at http://codereview.chromium.org/9295014/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/deoptimizer.h
  M src/deoptimizer.cc
  M src/runtime.cc
  M test/cctest/test-debug.cc


Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 56ff4549da25b5e60f60ab0709172cc1d9aad821..525ccec5bab91ee5be43811162396fd7c322672c 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -1603,6 +1603,7 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(
   SetFunction(output_frame->GetFunction());
   expression_count_ = output_frame->GetExpressionCount();
   expression_stack_ = new Object*[expression_count_];
+  pc_ = output_frame->GetPc();
   for (int i = 0; i < expression_count_; i++) {
     SetExpression(i, output_frame->GetExpression(i));
   }
Index: src/deoptimizer.h
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 8b1152d52957a7da6e37ecb56c4a07d17767accd..db6a59a259bd4b4fa3d28da6c34d3bf308d459d9 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -749,6 +749,10 @@ class DeoptimizedFrameInfo : public Malloced {
     return expression_stack_[index];
   }

+  Address GetPc() {
+    return reinterpret_cast<Address>(pc_);
+  }
+
  private:
   // Set the frame function.
   void SetFunction(JSFunction* function) {
@@ -772,6 +776,7 @@ class DeoptimizedFrameInfo : public Malloced {
   int expression_count_;
   Object** parameters_;
   Object** expression_stack_;
+  intptr_t pc_;

   friend class Deoptimizer;
 };
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index a5cc10cd8ee9d3ca46267bcbbfecd5adf308714c..5e007e2f84f08a4aa54351615c6025d826eb3f5b 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -10747,6 +10747,11 @@ class FrameInspector {
         ? deoptimized_frame_->GetExpression(index)
         : frame_->GetExpression(index);
   }
+  Address GetPc() {
+    return is_optimized_
+        ? deoptimized_frame_->GetPc()
+        : frame_->pc();
+  }

   // To inspect all the provided arguments the frame might need to be
   // replaced with the arguments frame.
@@ -10852,17 +10857,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
   // Get the frame id.
   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);

-  // Find source position.
-  int position =
-      it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
+  // Find source position in unoptimized code.
+ Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
+  Handle<SharedFunctionInfo> shared(function->shared());
+  int position = shared->code()->SourcePosition(frame_inspector.GetPc());

   // Check for constructor frame. Inlined frames cannot be construct calls.
   bool inlined_frame = is_optimized && inlined_jsframe_index != 0;
   bool constructor = !inlined_frame && it.frame()->IsConstructor();

   // Get scope info and read from it for local variable information.
- Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
-  Handle<SharedFunctionInfo> shared(function->shared());
   Handle<ScopeInfo> scope_info(shared->scope_info());
   ASSERT(*scope_info != ScopeInfo::Empty());

Index: test/cctest/test-debug.cc
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index c0ea7072fed35bd782f377a8b2d974bc9d32dc98..1e674dc2bdf89bb7a451838c52b38226238b616b 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -7286,4 +7286,57 @@ TEST(DebugBreakLoop) {
 }


+class DebugBreakSendThread : public v8::internal::Thread {
+ public:
+  DebugBreakSendThread() : Thread("DebugBreakSendThread") { }
+  virtual void Run() {
+    // Wait for crankshaft to inline f() into g();
+    OS::Sleep(2000);
+    v8::Debug::DebugBreak();
+  }
+};
+
+
+static void DebugBreakInlineListener(v8::DebugEvent event,
+                                     v8::Handle<v8::Object> exec_state,
+                                     v8::Handle<v8::Object> event_data,
+                                     v8::Handle<v8::Value> data) {
+  if (event != v8::Break) return;
+
+  int break_id = v8::internal::Isolate::Current()->debug()->break_id();
+  char script[128];
+  i::Vector<char> script_vector(script, sizeof(script));
+  OS::SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
+  v8::Local<v8::Value> result = CompileRun(script);
+  int frame_count = result->Int32Value();
+  int previous = -1;
+  for (int i = 0; i < frame_count; i++) {
+    // The 5. element in the returned array of GetFrameDetails contains the
+    // source position of that frame.
+ OS::SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
+    v8::Local<v8::Value> result = CompileRun(script);
+    ASSERT_NE(previous, result->Int32Value());
+    previous = result->Int32Value();
+  }
+
+  v8::V8::TerminateExecution();
+}
+
+
+TEST(DebugBreakInline) {
+  i::FLAG_allow_natives_syntax = true;
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  const char* source =
+      "function f() { for(var i=0; i<1000000; i++) { 1+1; } };\n"
+      "function g() { while(true) {f();} };\n"
+      "g();";
+  v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
+  DebugBreakSendThread debugbreak;
+  debugbreak.Start();
+  CompileRun(source);
+  v8::Debug::SetDebugEventListener(NULL);
+}
+
+
 #endif  // ENABLE_DEBUGGER_SUPPORT


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to