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.