Push version 2.2.17 to trunk.

Improved debugger support for stepping out of functions.

Incremental performance improvements.


git-svn-id: http://v8.googlecode.com/svn/trunk@4851 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index 4c27171..88786e8 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8243,8 +8243,9 @@
 static const int kFrameDetailsLocalCountIndex = 4;
 static const int kFrameDetailsSourcePositionIndex = 5;
 static const int kFrameDetailsConstructCallIndex = 6;
-static const int kFrameDetailsDebuggerFrameIndex = 7;
-static const int kFrameDetailsFirstDynamicIndex = 8;
+static const int kFrameDetailsAtReturnIndex = 7;
+static const int kFrameDetailsDebuggerFrameIndex = 8;
+static const int kFrameDetailsFirstDynamicIndex = 9;
 
 // Return an array with frame details
 // args[0]: number: break id
@@ -8258,9 +8259,11 @@
 // 4: Local count
 // 5: Source position
 // 6: Constructor call
-// 7: Debugger frame
+// 7: Is at return
+// 8: Debugger frame
 // Arguments name, value
 // Locals name, value
+// Return value if any
 static Object* Runtime_GetFrameDetails(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 2);
@@ -8336,8 +8339,39 @@
     }
   }
 
-  // Now advance to the arguments adapter frame (if any). If contains all
-  // the provided parameters and
+  // Check whether this frame is positioned at return.
+  int at_return = (index == 0) ? Debug::IsBreakAtReturn(it.frame()) : false;
+
+  // If positioned just before return find the value to be returned and add it
+  // to the frame information.
+  Handle<Object> return_value = Factory::undefined_value();
+  if (at_return) {
+    StackFrameIterator it2;
+    Address internal_frame_sp = NULL;
+    while (!it2.done()) {
+      if (it2.frame()->is_internal()) {
+        internal_frame_sp = it2.frame()->sp();
+      } else {
+        if (it2.frame()->is_java_script()) {
+          if (it2.frame()->id() == it.frame()->id()) {
+            // The internal frame just before the JavaScript frame contains the
+            // value to return on top. A debug break at return will create an
+            // internal frame to store the return value (eax/rax/r0) before
+            // entering the debug break exit frame.
+            if (internal_frame_sp != NULL) {
+              return_value =
+                  Handle<Object>(Memory::Object_at(internal_frame_sp));
+              break;
+            }
+          }
+        }
+
+        // Indicate that the previous frame was not an internal frame.
+        internal_frame_sp = NULL;
+      }
+      it2.Advance();
+    }
+  }
 
   // Now advance to the arguments adapter frame (if any). It contains all
   // the provided parameters whereas the function frame always have the number
@@ -8354,7 +8388,8 @@
 
   // Calculate the size of the result.
   int details_size = kFrameDetailsFirstDynamicIndex +
-                     2 * (argument_count + info.NumberOfLocals());
+                     2 * (argument_count + info.NumberOfLocals()) +
+                     (at_return ? 1 : 0);
   Handle<FixedArray> details = Factory::NewFixedArray(details_size);
 
   // Add the frame id.
@@ -8380,6 +8415,9 @@
   // Add the constructor information.
   details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
 
+  // Add the at return information.
+  details->set(kFrameDetailsAtReturnIndex, Heap::ToBoolean(at_return));
+
   // Add information on whether this frame is invoked in the debugger context.
   details->set(kFrameDetailsDebuggerFrameIndex,
                Heap::ToBoolean(*save->context() == *Debug::debug_context()));
@@ -8409,6 +8447,11 @@
     details->set(details_index++, locals->get(i));
   }
 
+  // Add the value being returned.
+  if (at_return) {
+    details->set(details_index++, *return_value);
+  }
+
   // Add the receiver (same as in function frame).
   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
   // THE FRAME ITERATOR TO WRAP THE RECEIVER.