| 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.
|
|
|