| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index df99fdc671ff48d25e3e0cb75c6cbd8d04a7f1b1..bd9f516503ced013de57ead704621ec1ef5b17cc 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -9938,7 +9938,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
|
| // If there is no JavaScript stack frame count is 0.
|
| return Smi::FromInt(0);
|
| }
|
| - for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++;
|
| +
|
| + for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
|
| + n += it.frame()->GetInlineCount();
|
| + }
|
| return Smi::FromInt(n);
|
| }
|
|
|
| @@ -9951,7 +9954,7 @@ static const int kFrameDetailsLocalCountIndex = 4;
|
| static const int kFrameDetailsSourcePositionIndex = 5;
|
| static const int kFrameDetailsConstructCallIndex = 6;
|
| static const int kFrameDetailsAtReturnIndex = 7;
|
| -static const int kFrameDetailsDebuggerFrameIndex = 8;
|
| +static const int kFrameDetailsFlagsIndex = 8;
|
| static const int kFrameDetailsFirstDynamicIndex = 9;
|
|
|
| // Return an array with frame details
|
| @@ -9967,7 +9970,7 @@ static const int kFrameDetailsFirstDynamicIndex = 9;
|
| // 5: Source position
|
| // 6: Constructor call
|
| // 7: Is at return
|
| -// 8: Debugger frame
|
| +// 8: Flags
|
| // Arguments name, value
|
| // Locals name, value
|
| // Return value if any
|
| @@ -9990,16 +9993,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| // If there are no JavaScript stack frames return undefined.
|
| return heap->undefined_value();
|
| }
|
| +
|
| + int deoptimized_frame_index = -1; // Frame index in optimized frame.
|
| + DeoptimizedFrameInfo* deoptimized_frame = NULL;
|
| +
|
| int count = 0;
|
| JavaScriptFrameIterator it(isolate, id);
|
| for (; !it.done(); it.Advance()) {
|
| - if (count == index) break;
|
| - count++;
|
| + if (index < count + it.frame()->GetInlineCount()) break;
|
| + count += it.frame()->GetInlineCount();
|
| }
|
| if (it.done()) return heap->undefined_value();
|
|
|
| - bool is_optimized_frame =
|
| - it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION;
|
| + if (it.frame()->is_optimized()) {
|
| + deoptimized_frame_index =
|
| + it.frame()->GetInlineCount() - (index - count) - 1;
|
| + deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
|
| + it.frame(),
|
| + deoptimized_frame_index,
|
| + isolate);
|
| + }
|
|
|
| // Traverse the saved contexts chain to find the active context for the
|
| // selected frame.
|
| @@ -10022,6 +10035,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| // Get scope info and read from it for local variable information.
|
| Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
|
| Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
|
| + ASSERT(*scope_info != SerializedScopeInfo::Empty());
|
| ScopeInfo<> info(*scope_info);
|
|
|
| // Get the locals names and values into a temporary array.
|
| @@ -10033,38 +10047,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2);
|
|
|
| // Fill in the values of the locals.
|
| - if (is_optimized_frame) {
|
| - // If we are inspecting an optimized frame use undefined as the
|
| - // value for all locals.
|
| - //
|
| - // TODO(1140): We should be able to get the correct values
|
| - // for locals in optimized frames.
|
| - for (int i = 0; i < info.NumberOfLocals(); i++) {
|
| - locals->set(i * 2, *info.LocalName(i));
|
| - locals->set(i * 2 + 1, isolate->heap()->undefined_value());
|
| - }
|
| - } else {
|
| - int i = 0;
|
| - for (; i < info.number_of_stack_slots(); ++i) {
|
| - // Use the value from the stack.
|
| - locals->set(i * 2, *info.LocalName(i));
|
| - locals->set(i * 2 + 1, it.frame()->GetExpression(i));
|
| - }
|
| - // Get the context containing declarations.
|
| - Handle<Context> context(
|
| - Context::cast(it.frame()->context())->declaration_context());
|
| - for (; i < info.NumberOfLocals(); ++i) {
|
| - Handle<String> name = info.LocalName(i);
|
| - locals->set(i * 2, *name);
|
| + int i = 0;
|
| + for (; i < info.number_of_stack_slots(); ++i) {
|
| + // Use the value from the stack.
|
| + locals->set(i * 2, *info.LocalName(i));
|
| + if (it.frame()->is_optimized()) {
|
| + // Get the value from the deoptimized frame.
|
| locals->set(i * 2 + 1,
|
| - context->get(scope_info->ContextSlotIndex(*name, NULL)));
|
| + deoptimized_frame->GetExpression(i));
|
| + } else {
|
| + // Get the value from the stack.
|
| + locals->set(i * 2 + 1, it.frame()->GetExpression(i));
|
| }
|
| }
|
| + // Get the context containing declarations.
|
| + Handle<Context> context(
|
| + Context::cast(it.frame()->context())->declaration_context());
|
| + for (; i < info.NumberOfLocals(); ++i) {
|
| + Handle<String> name = info.LocalName(i);
|
| + locals->set(i * 2, *name);
|
| + locals->set(i * 2 + 1,
|
| + context->get(scope_info->ContextSlotIndex(*name, NULL)));
|
| + }
|
|
|
| // Check whether this frame is positioned at return. If not top
|
| // frame or if the frame is optimized it cannot be at a return.
|
| bool at_return = false;
|
| - if (!is_optimized_frame && index == 0) {
|
| + if (!it.frame()->is_optimized() && index == 0) {
|
| at_return = isolate->debug()->IsBreakAtReturn(it.frame());
|
| }
|
|
|
| @@ -10145,10 +10154,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| // 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() ==
|
| - *isolate->debug()->debug_context()));
|
| + // Add flags to indicate information on whether this frame is
|
| + // bit 0: invoked in the debugger context.
|
| + // bit 1: optimized frame.
|
| + // bit 2: inlined in optimized frame
|
| + int flags = 0;
|
| + if (*save->context() == *isolate->debug()->debug_context()) {
|
| + flags |= 1 << 0;
|
| + }
|
| + if (it.frame()->is_optimized()) {
|
| + flags |= 1 << 1;
|
| + if (deoptimized_frame_index > 0) {
|
| + flags |= 1 << 2;
|
| + }
|
| + }
|
| + details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
|
|
|
| // Fill the dynamic part.
|
| int details_index = kFrameDetailsFirstDynamicIndex;
|
| @@ -10167,7 +10187,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| //
|
| // TODO(3141533): We should be able to get the actual parameter
|
| // value for optimized frames.
|
| - if (!is_optimized_frame &&
|
| + if (!it.frame()->is_optimized() &&
|
| (i < it.frame()->ComputeParametersCount())) {
|
| details->set(details_index++, it.frame()->GetParameter(i));
|
| } else {
|
| @@ -10203,6 +10223,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| }
|
| details->set(kFrameDetailsReceiverIndex, *receiver);
|
|
|
| + // Get rid of the calculated deoptimized frame if any.
|
| + if (deoptimized_frame != NULL) {
|
| + Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
|
| + isolate);
|
| + }
|
| +
|
| ASSERT_EQ(details_size, details_index);
|
| return *isolate->factory()->NewJSArrayWithElements(details);
|
| }
|
|
|