| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 117e5ab36f6f7b7743ea43ef2e666220ee090e23..d340f45c2fe44b8834edce2559402345de53f85b 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -9976,6 +9976,71 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
|
| }
|
|
|
|
|
| +class FrameInspector {
|
| + public:
|
| + FrameInspector(JavaScriptFrame* frame,
|
| + int inlined_frame_index,
|
| + Isolate* isolate)
|
| + : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
|
| + // Calculate the deoptimized frame.
|
| + if (frame->is_optimized()) {
|
| + deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
|
| + frame, inlined_frame_index, isolate);
|
| + }
|
| + has_adapted_arguments_ = frame_->has_adapted_arguments();
|
| + is_optimized_ = frame_->is_optimized();
|
| + }
|
| +
|
| + ~FrameInspector() {
|
| + // Get rid of the calculated deoptimized frame if any.
|
| + if (deoptimized_frame_ != NULL) {
|
| + Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
|
| + isolate_);
|
| + }
|
| + }
|
| +
|
| + int GetParametersCount() {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->parameters_count()
|
| + : frame_->ComputeParametersCount();
|
| + }
|
| + int expression_count() { return deoptimized_frame_->expression_count(); }
|
| + Object* GetFunction() {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetFunction()
|
| + : frame_->function();
|
| + }
|
| + Object* GetParameter(int index) {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetParameter(index)
|
| + : frame_->GetParameter(index);
|
| + }
|
| + Object* GetExpression(int index) {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetExpression(index)
|
| + : frame_->GetExpression(index);
|
| + }
|
| +
|
| + // To inspect all the provided arguments the frame might need to be
|
| + // replaced with the arguments frame.
|
| + void SetArgumentsFrame(JavaScriptFrame* frame) {
|
| + ASSERT(has_adapted_arguments_);
|
| + frame_ = frame;
|
| + is_optimized_ = frame_->is_optimized();
|
| + ASSERT(!is_optimized_);
|
| + }
|
| +
|
| + private:
|
| + JavaScriptFrame* frame_;
|
| + DeoptimizedFrameInfo* deoptimized_frame_;
|
| + Isolate* isolate_;
|
| + bool is_optimized_;
|
| + bool has_adapted_arguments_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FrameInspector);
|
| +};
|
| +
|
| +
|
| static const int kFrameDetailsFrameIdIndex = 0;
|
| static const int kFrameDetailsReceiverIndex = 1;
|
| static const int kFrameDetailsFunctionIndex = 2;
|
| @@ -10024,8 +10089,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| return heap->undefined_value();
|
| }
|
|
|
| - int deoptimized_frame_index = -1; // Frame index in optimized frame.
|
| - DeoptimizedFrameInfo* deoptimized_frame = NULL;
|
| + int inlined_frame_index = 0; // Inlined frame index in optimized frame.
|
|
|
| int count = 0;
|
| JavaScriptFrameIterator it(isolate, id);
|
| @@ -10036,13 +10100,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| if (it.done()) return heap->undefined_value();
|
|
|
| if (it.frame()->is_optimized()) {
|
| - deoptimized_frame_index =
|
| + inlined_frame_index =
|
| it.frame()->GetInlineCount() - (index - count) - 1;
|
| - deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
|
| - it.frame(),
|
| - deoptimized_frame_index,
|
| - isolate);
|
| }
|
| + FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
|
|
|
| // Traverse the saved contexts chain to find the active context for the
|
| // selected frame.
|
| @@ -10061,7 +10122,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
|
|
| // Check for constructor frame. Inlined frames cannot be construct calls.
|
| bool inlined_frame =
|
| - it.frame()->is_optimized() && deoptimized_frame_index != 0;
|
| + it.frame()->is_optimized() && inlined_frame_index != 0;
|
| bool constructor = !inlined_frame && it.frame()->IsConstructor();
|
|
|
| // Get scope info and read from it for local variable information.
|
| @@ -10083,14 +10144,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| 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,
|
| - deoptimized_frame->GetExpression(i));
|
| - } else {
|
| - // Get the value from the stack.
|
| - locals->set(i * 2 + 1, it.frame()->GetExpression(i));
|
| - }
|
| + locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
|
| }
|
| if (i < info.NumberOfLocals()) {
|
| // Get the context containing declarations.
|
| @@ -10147,18 +10201,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| // the provided parameters whereas the function frame always have the number
|
| // of arguments matching the functions parameters. The rest of the
|
| // information (except for what is collected above) is the same.
|
| - it.AdvanceToArgumentsFrame();
|
| + if (it.frame()->has_adapted_arguments()) {
|
| + it.AdvanceToArgumentsFrame();
|
| + frame_inspector.SetArgumentsFrame(it.frame());
|
| + }
|
|
|
| // Find the number of arguments to fill. At least fill the number of
|
| // parameters for the function and fill more if more parameters are provided.
|
| int argument_count = info.number_of_parameters();
|
| + if (argument_count < frame_inspector.GetParametersCount()) {
|
| + argument_count = frame_inspector.GetParametersCount();
|
| + }
|
| +#ifdef DEBUG
|
| if (it.frame()->is_optimized()) {
|
| - ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
|
| - } else {
|
| - if (argument_count < it.frame()->ComputeParametersCount()) {
|
| - argument_count = it.frame()->ComputeParametersCount();
|
| - }
|
| + ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
|
| }
|
| +#endif
|
|
|
| // Calculate the size of the result.
|
| int details_size = kFrameDetailsFirstDynamicIndex +
|
| @@ -10170,13 +10228,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| details->set(kFrameDetailsFrameIdIndex, *frame_id);
|
|
|
| // Add the function (same as in function frame).
|
| - if (it.frame()->is_optimized()) {
|
| - // Get the function from the deoptimized frame.
|
| - details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
|
| - } else {
|
| - // Get the function from the stack.
|
| - details->set(kFrameDetailsFunctionIndex, it.frame()->function());
|
| - }
|
| + details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
|
|
|
| // Add the arguments count.
|
| details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
|
| @@ -10208,9 +10260,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| }
|
| if (it.frame()->is_optimized()) {
|
| flags |= 1 << 1;
|
| - if (deoptimized_frame_index > 0) {
|
| - flags |= 1 << 2;
|
| - }
|
| + flags |= inlined_frame_index << 2;
|
| }
|
| details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
|
|
|
| @@ -10227,16 +10277,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
| }
|
|
|
| // Parameter value.
|
| - if (it.frame()->is_optimized()) {
|
| - // Get the value from the deoptimized frame.
|
| - details->set(details_index++, deoptimized_frame->GetParameter(i));
|
| + if (i < it.frame()->ComputeParametersCount()) {
|
| + // Get the value from the stack.
|
| + details->set(details_index++, frame_inspector.GetParameter(i));
|
| } else {
|
| - if (i < it.frame()->ComputeParametersCount()) {
|
| - // Get the value from the stack.
|
| - details->set(details_index++, it.frame()->GetParameter(i));
|
| - } else {
|
| - details->set(details_index++, heap->undefined_value());
|
| - }
|
| + details->set(details_index++, heap->undefined_value());
|
| }
|
| }
|
|
|
| @@ -10268,12 +10313,6 @@ 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);
|
| }
|
| @@ -10309,12 +10348,15 @@ static bool CopyContextLocalsToScopeObject(
|
|
|
| // Create a plain JSObject which materializes the local scope for the specified
|
| // frame.
|
| -static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
|
| - JavaScriptFrame* frame) {
|
| +static Handle<JSObject> MaterializeLocalScope(
|
| + Isolate* isolate,
|
| + JavaScriptFrame* frame,
|
| + int inlined_frame_index) {
|
| Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
| Handle<SharedFunctionInfo> shared(function->shared());
|
| Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
|
| ScopeInfo<> scope_info(*serialized_scope_info);
|
| + FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
|
|
|
| // Allocate and initialize a JSObject with all the arguments, stack locals
|
| // heap locals and extension properties of the debugged function.
|
| @@ -10327,7 +10369,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
|
| isolate,
|
| SetProperty(local_scope,
|
| scope_info.parameter_name(i),
|
| - Handle<Object>(frame->GetParameter(i), isolate),
|
| + Handle<Object>(frame_inspector.GetParameter(i)),
|
| NONE,
|
| kNonStrictMode),
|
| Handle<JSObject>());
|
| @@ -10339,7 +10381,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
|
| isolate,
|
| SetProperty(local_scope,
|
| scope_info.stack_slot_name(i),
|
| - Handle<Object>(frame->GetExpression(i), isolate),
|
| + Handle<Object>(frame_inspector.GetExpression(i)),
|
| NONE,
|
| kNonStrictMode),
|
| Handle<JSObject>());
|
| @@ -10459,9 +10501,12 @@ class ScopeIterator {
|
| ScopeTypeCatch
|
| };
|
|
|
| - ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
|
| + ScopeIterator(Isolate* isolate,
|
| + JavaScriptFrame* frame,
|
| + int inlined_frame_index)
|
| : isolate_(isolate),
|
| frame_(frame),
|
| + inlined_frame_index_(inlined_frame_index),
|
| function_(JSFunction::cast(frame->function())),
|
| context_(Context::cast(frame->context())),
|
| local_done_(false),
|
| @@ -10546,7 +10591,7 @@ class ScopeIterator {
|
| return Handle<JSObject>(CurrentContext()->global());
|
| case ScopeIterator::ScopeTypeLocal:
|
| // Materialize the content of the local scope into a JSObject.
|
| - return MaterializeLocalScope(isolate_, frame_);
|
| + return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
|
| case ScopeIterator::ScopeTypeWith:
|
| // Return the with object.
|
| return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
|
| @@ -10626,6 +10671,7 @@ class ScopeIterator {
|
| private:
|
| Isolate* isolate_;
|
| JavaScriptFrame* frame_;
|
| + int inlined_frame_index_;
|
| Handle<JSFunction> function_;
|
| Handle<Context> context_;
|
| bool local_done_;
|
| @@ -10654,7 +10700,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
|
|
|
| // Count the visible scopes.
|
| int n = 0;
|
| - for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
|
| + for (ScopeIterator it(isolate, frame, 0);
|
| + !it.Done();
|
| + it.Next()) {
|
| n++;
|
| }
|
|
|
| @@ -10669,14 +10717,15 @@ static const int kScopeDetailsSize = 2;
|
| // Return an array with scope details
|
| // args[0]: number: break id
|
| // args[1]: number: frame index
|
| -// args[2]: number: scope index
|
| +// args[2]: number: inlined frame index
|
| +// args[3]: number: scope index
|
| //
|
| // The array returned contains the following information:
|
| // 0: Scope type
|
| // 1: Scope object
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
|
| HandleScope scope(isolate);
|
| - ASSERT(args.length() == 3);
|
| + ASSERT(args.length() == 4);
|
|
|
| // Check arguments.
|
| Object* check;
|
| @@ -10685,7 +10734,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
|
| if (!maybe_check->ToObject(&check)) return maybe_check;
|
| }
|
| CONVERT_CHECKED(Smi, wrapped_id, args[1]);
|
| - CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
|
| + CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
|
| + CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
|
|
|
| // Get the frame where the debugging is performed.
|
| StackFrame::Id id = UnwrapFrameId(wrapped_id);
|
| @@ -10694,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
|
|
|
| // Find the requested scope.
|
| int n = 0;
|
| - ScopeIterator it(isolate, frame);
|
| + ScopeIterator it(isolate, frame, inlined_frame_index);
|
| for (; !it.Done() && n < index; it.Next()) {
|
| n++;
|
| }
|
| @@ -10724,7 +10774,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
|
| // Print the scopes for the top frame.
|
| StackFrameLocator locator;
|
| JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
|
| - for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
|
| + for (ScopeIterator it(isolate, frame, 0);
|
| + !it.Done();
|
| + it.Next()) {
|
| it.DebugPrint();
|
| }
|
| #endif
|
| @@ -11117,6 +11169,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate,
|
| // Runtime_DebugEvaluate.
|
| static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
| JavaScriptFrame* frame,
|
| + int inlined_frame_index,
|
| Handle<JSFunction> function,
|
| Handle<SerializedScopeInfo> scope_info,
|
| const ScopeInfo<>* sinfo,
|
| @@ -11128,6 +11181,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
| if (sinfo->number_of_stack_slots() > 0) {
|
| index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
|
| if (index != -1) {
|
| + CHECK(false);
|
| return Handle<Object>(frame->GetExpression(index), isolate);
|
| }
|
| }
|
| @@ -11140,7 +11194,9 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
| }
|
| }
|
|
|
| - const int length = frame->ComputeParametersCount();
|
| + FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
|
| +
|
| + int length = frame_inspector.GetParametersCount();
|
| Handle<JSObject> arguments =
|
| isolate->factory()->NewArgumentsObject(function, length);
|
| Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
|
| @@ -11148,7 +11204,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
| AssertNoAllocation no_gc;
|
| WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
|
| for (int i = 0; i < length; i++) {
|
| - array->set(i, frame->GetParameter(i), mode);
|
| + array->set(i, frame_inspector.GetParameter(i), mode);
|
| }
|
| arguments->set_elements(*array);
|
| return arguments;
|
| @@ -11175,7 +11231,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
|
|
| // Check the execution state and decode arguments frame and source to be
|
| // evaluated.
|
| - ASSERT(args.length() == 5);
|
| + ASSERT(args.length() == 6);
|
| Object* check_result;
|
| { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
|
| RUNTIME_ARGUMENTS(isolate, args));
|
| @@ -11184,9 +11240,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
| }
|
| }
|
| CONVERT_CHECKED(Smi, wrapped_id, args[1]);
|
| - CONVERT_ARG_CHECKED(String, source, 2);
|
| - CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
|
| - Handle<Object> additional_context(args[4]);
|
| + CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
|
| + CONVERT_ARG_CHECKED(String, source, 3);
|
| + CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
|
| + Handle<Object> additional_context(args[5]);
|
|
|
| // Handle the processing of break.
|
| DisableBreak disable_break_save(disable_break);
|
| @@ -11226,7 +11283,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
| #endif
|
|
|
| // Materialize the content of the local scope into a JSObject.
|
| - Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
|
| + Handle<JSObject> local_scope = MaterializeLocalScope(
|
| + isolate, frame, inlined_frame_index);
|
| RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
|
|
|
| // Allocate a new context for the debug evaluation and set the extension
|
| @@ -11275,7 +11333,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
|
| &has_pending_exception);
|
| if (has_pending_exception) return Failure::Exception();
|
|
|
| - Handle<Object> arguments = GetArgumentsObject(isolate, frame,
|
| + Handle<Object> arguments = GetArgumentsObject(isolate,
|
| + frame, inlined_frame_index,
|
| function, scope_info,
|
| &sinfo, function_context);
|
|
|
|
|