Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 4834) |
+++ src/runtime.cc (working copy) |
@@ -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,9 +8339,40 @@ |
} |
} |
- // 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 |
// of arguments matching the functions parameters. The rest of the |
@@ -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. |