| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 9920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9931 if (!maybe_result->ToObject(&result)) return maybe_result; | 9931 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 9932 } | 9932 } |
| 9933 | 9933 |
| 9934 // Count all frames which are relevant to debugging stack trace. | 9934 // Count all frames which are relevant to debugging stack trace. |
| 9935 int n = 0; | 9935 int n = 0; |
| 9936 StackFrame::Id id = isolate->debug()->break_frame_id(); | 9936 StackFrame::Id id = isolate->debug()->break_frame_id(); |
| 9937 if (id == StackFrame::NO_ID) { | 9937 if (id == StackFrame::NO_ID) { |
| 9938 // If there is no JavaScript stack frame count is 0. | 9938 // If there is no JavaScript stack frame count is 0. |
| 9939 return Smi::FromInt(0); | 9939 return Smi::FromInt(0); |
| 9940 } | 9940 } |
| 9941 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++; | 9941 |
| 9942 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { |
| 9943 n += it.frame()->GetInlineCount(); |
| 9944 } |
| 9942 return Smi::FromInt(n); | 9945 return Smi::FromInt(n); |
| 9943 } | 9946 } |
| 9944 | 9947 |
| 9945 | 9948 |
| 9946 static const int kFrameDetailsFrameIdIndex = 0; | 9949 static const int kFrameDetailsFrameIdIndex = 0; |
| 9947 static const int kFrameDetailsReceiverIndex = 1; | 9950 static const int kFrameDetailsReceiverIndex = 1; |
| 9948 static const int kFrameDetailsFunctionIndex = 2; | 9951 static const int kFrameDetailsFunctionIndex = 2; |
| 9949 static const int kFrameDetailsArgumentCountIndex = 3; | 9952 static const int kFrameDetailsArgumentCountIndex = 3; |
| 9950 static const int kFrameDetailsLocalCountIndex = 4; | 9953 static const int kFrameDetailsLocalCountIndex = 4; |
| 9951 static const int kFrameDetailsSourcePositionIndex = 5; | 9954 static const int kFrameDetailsSourcePositionIndex = 5; |
| 9952 static const int kFrameDetailsConstructCallIndex = 6; | 9955 static const int kFrameDetailsConstructCallIndex = 6; |
| 9953 static const int kFrameDetailsAtReturnIndex = 7; | 9956 static const int kFrameDetailsAtReturnIndex = 7; |
| 9954 static const int kFrameDetailsDebuggerFrameIndex = 8; | 9957 static const int kFrameDetailsFlagsIndex = 8; |
| 9955 static const int kFrameDetailsFirstDynamicIndex = 9; | 9958 static const int kFrameDetailsFirstDynamicIndex = 9; |
| 9956 | 9959 |
| 9957 // Return an array with frame details | 9960 // Return an array with frame details |
| 9958 // args[0]: number: break id | 9961 // args[0]: number: break id |
| 9959 // args[1]: number: frame index | 9962 // args[1]: number: frame index |
| 9960 // | 9963 // |
| 9961 // The array returned contains the following information: | 9964 // The array returned contains the following information: |
| 9962 // 0: Frame id | 9965 // 0: Frame id |
| 9963 // 1: Receiver | 9966 // 1: Receiver |
| 9964 // 2: Function | 9967 // 2: Function |
| 9965 // 3: Argument count | 9968 // 3: Argument count |
| 9966 // 4: Local count | 9969 // 4: Local count |
| 9967 // 5: Source position | 9970 // 5: Source position |
| 9968 // 6: Constructor call | 9971 // 6: Constructor call |
| 9969 // 7: Is at return | 9972 // 7: Is at return |
| 9970 // 8: Debugger frame | 9973 // 8: Flags |
| 9971 // Arguments name, value | 9974 // Arguments name, value |
| 9972 // Locals name, value | 9975 // Locals name, value |
| 9973 // Return value if any | 9976 // Return value if any |
| 9974 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { | 9977 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { |
| 9975 HandleScope scope(isolate); | 9978 HandleScope scope(isolate); |
| 9976 ASSERT(args.length() == 2); | 9979 ASSERT(args.length() == 2); |
| 9977 | 9980 |
| 9978 // Check arguments. | 9981 // Check arguments. |
| 9979 Object* check; | 9982 Object* check; |
| 9980 { MaybeObject* maybe_check = Runtime_CheckExecutionState( | 9983 { MaybeObject* maybe_check = Runtime_CheckExecutionState( |
| 9981 RUNTIME_ARGUMENTS(isolate, args)); | 9984 RUNTIME_ARGUMENTS(isolate, args)); |
| 9982 if (!maybe_check->ToObject(&check)) return maybe_check; | 9985 if (!maybe_check->ToObject(&check)) return maybe_check; |
| 9983 } | 9986 } |
| 9984 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | 9987 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); |
| 9985 Heap* heap = isolate->heap(); | 9988 Heap* heap = isolate->heap(); |
| 9986 | 9989 |
| 9987 // Find the relevant frame with the requested index. | 9990 // Find the relevant frame with the requested index. |
| 9988 StackFrame::Id id = isolate->debug()->break_frame_id(); | 9991 StackFrame::Id id = isolate->debug()->break_frame_id(); |
| 9989 if (id == StackFrame::NO_ID) { | 9992 if (id == StackFrame::NO_ID) { |
| 9990 // If there are no JavaScript stack frames return undefined. | 9993 // If there are no JavaScript stack frames return undefined. |
| 9991 return heap->undefined_value(); | 9994 return heap->undefined_value(); |
| 9992 } | 9995 } |
| 9996 |
| 9997 int deoptimized_frame_index = -1; // Frame index in optimized frame. |
| 9998 DeoptimizedFrameInfo* deoptimized_frame = NULL; |
| 9999 |
| 9993 int count = 0; | 10000 int count = 0; |
| 9994 JavaScriptFrameIterator it(isolate, id); | 10001 JavaScriptFrameIterator it(isolate, id); |
| 9995 for (; !it.done(); it.Advance()) { | 10002 for (; !it.done(); it.Advance()) { |
| 9996 if (count == index) break; | 10003 if (index < count + it.frame()->GetInlineCount()) break; |
| 9997 count++; | 10004 count += it.frame()->GetInlineCount(); |
| 9998 } | 10005 } |
| 9999 if (it.done()) return heap->undefined_value(); | 10006 if (it.done()) return heap->undefined_value(); |
| 10000 | 10007 |
| 10001 bool is_optimized_frame = | 10008 if (it.frame()->is_optimized()) { |
| 10002 it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION; | 10009 deoptimized_frame_index = |
| 10010 it.frame()->GetInlineCount() - (index - count) - 1; |
| 10011 deoptimized_frame = Deoptimizer::DebuggerInspectableFrame( |
| 10012 it.frame(), |
| 10013 deoptimized_frame_index, |
| 10014 isolate); |
| 10015 } |
| 10003 | 10016 |
| 10004 // Traverse the saved contexts chain to find the active context for the | 10017 // Traverse the saved contexts chain to find the active context for the |
| 10005 // selected frame. | 10018 // selected frame. |
| 10006 SaveContext* save = isolate->save_context(); | 10019 SaveContext* save = isolate->save_context(); |
| 10007 while (save != NULL && !save->below(it.frame())) { | 10020 while (save != NULL && !save->below(it.frame())) { |
| 10008 save = save->prev(); | 10021 save = save->prev(); |
| 10009 } | 10022 } |
| 10010 ASSERT(save != NULL); | 10023 ASSERT(save != NULL); |
| 10011 | 10024 |
| 10012 // Get the frame id. | 10025 // Get the frame id. |
| 10013 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | 10026 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); |
| 10014 | 10027 |
| 10015 // Find source position. | 10028 // Find source position. |
| 10016 int position = | 10029 int position = |
| 10017 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); | 10030 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); |
| 10018 | 10031 |
| 10019 // Check for constructor frame. | 10032 // Check for constructor frame. |
| 10020 bool constructor = it.frame()->IsConstructor(); | 10033 bool constructor = it.frame()->IsConstructor(); |
| 10021 | 10034 |
| 10022 // Get scope info and read from it for local variable information. | 10035 // Get scope info and read from it for local variable information. |
| 10023 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); | 10036 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); |
| 10024 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); | 10037 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); |
| 10038 ASSERT(*scope_info != SerializedScopeInfo::Empty()); |
| 10025 ScopeInfo<> info(*scope_info); | 10039 ScopeInfo<> info(*scope_info); |
| 10026 | 10040 |
| 10027 // Get the locals names and values into a temporary array. | 10041 // Get the locals names and values into a temporary array. |
| 10028 // | 10042 // |
| 10029 // TODO(1240907): Hide compiler-introduced stack variables | 10043 // TODO(1240907): Hide compiler-introduced stack variables |
| 10030 // (e.g. .result)? For users of the debugger, they will probably be | 10044 // (e.g. .result)? For users of the debugger, they will probably be |
| 10031 // confusing. | 10045 // confusing. |
| 10032 Handle<FixedArray> locals = | 10046 Handle<FixedArray> locals = |
| 10033 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); | 10047 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); |
| 10034 | 10048 |
| 10035 // Fill in the values of the locals. | 10049 // Fill in the values of the locals. |
| 10036 if (is_optimized_frame) { | 10050 int i = 0; |
| 10037 // If we are inspecting an optimized frame use undefined as the | 10051 for (; i < info.number_of_stack_slots(); ++i) { |
| 10038 // value for all locals. | 10052 // Use the value from the stack. |
| 10039 // | 10053 locals->set(i * 2, *info.LocalName(i)); |
| 10040 // TODO(1140): We should be able to get the correct values | 10054 if (it.frame()->is_optimized()) { |
| 10041 // for locals in optimized frames. | 10055 // Get the value from the deoptimized frame. |
| 10042 for (int i = 0; i < info.NumberOfLocals(); i++) { | 10056 locals->set(i * 2 + 1, |
| 10043 locals->set(i * 2, *info.LocalName(i)); | 10057 deoptimized_frame->GetExpression(i)); |
| 10044 locals->set(i * 2 + 1, isolate->heap()->undefined_value()); | 10058 } else { |
| 10045 } | 10059 // Get the value from the stack. |
| 10046 } else { | |
| 10047 int i = 0; | |
| 10048 for (; i < info.number_of_stack_slots(); ++i) { | |
| 10049 // Use the value from the stack. | |
| 10050 locals->set(i * 2, *info.LocalName(i)); | |
| 10051 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 10060 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); |
| 10052 } | 10061 } |
| 10053 // Get the context containing declarations. | 10062 } |
| 10054 Handle<Context> context( | 10063 // Get the context containing declarations. |
| 10055 Context::cast(it.frame()->context())->declaration_context()); | 10064 Handle<Context> context( |
| 10056 for (; i < info.NumberOfLocals(); ++i) { | 10065 Context::cast(it.frame()->context())->declaration_context()); |
| 10057 Handle<String> name = info.LocalName(i); | 10066 for (; i < info.NumberOfLocals(); ++i) { |
| 10058 locals->set(i * 2, *name); | 10067 Handle<String> name = info.LocalName(i); |
| 10059 locals->set(i * 2 + 1, | 10068 locals->set(i * 2, *name); |
| 10060 context->get(scope_info->ContextSlotIndex(*name, NULL))); | 10069 locals->set(i * 2 + 1, |
| 10061 } | 10070 context->get(scope_info->ContextSlotIndex(*name, NULL))); |
| 10062 } | 10071 } |
| 10063 | 10072 |
| 10064 // Check whether this frame is positioned at return. If not top | 10073 // Check whether this frame is positioned at return. If not top |
| 10065 // frame or if the frame is optimized it cannot be at a return. | 10074 // frame or if the frame is optimized it cannot be at a return. |
| 10066 bool at_return = false; | 10075 bool at_return = false; |
| 10067 if (!is_optimized_frame && index == 0) { | 10076 if (!it.frame()->is_optimized() && index == 0) { |
| 10068 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); | 10077 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); |
| 10069 } | 10078 } |
| 10070 | 10079 |
| 10071 // If positioned just before return find the value to be returned and add it | 10080 // If positioned just before return find the value to be returned and add it |
| 10072 // to the frame information. | 10081 // to the frame information. |
| 10073 Handle<Object> return_value = isolate->factory()->undefined_value(); | 10082 Handle<Object> return_value = isolate->factory()->undefined_value(); |
| 10074 if (at_return) { | 10083 if (at_return) { |
| 10075 StackFrameIterator it2(isolate); | 10084 StackFrameIterator it2(isolate); |
| 10076 Address internal_frame_sp = NULL; | 10085 Address internal_frame_sp = NULL; |
| 10077 while (!it2.done()) { | 10086 while (!it2.done()) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10138 } else { | 10147 } else { |
| 10139 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); | 10148 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); |
| 10140 } | 10149 } |
| 10141 | 10150 |
| 10142 // Add the constructor information. | 10151 // Add the constructor information. |
| 10143 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); | 10152 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); |
| 10144 | 10153 |
| 10145 // Add the at return information. | 10154 // Add the at return information. |
| 10146 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); | 10155 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); |
| 10147 | 10156 |
| 10148 // Add information on whether this frame is invoked in the debugger context. | 10157 // Add flags to indicate information on whether this frame is |
| 10149 details->set(kFrameDetailsDebuggerFrameIndex, | 10158 // bit 0: invoked in the debugger context. |
| 10150 heap->ToBoolean(*save->context() == | 10159 // bit 1: optimized frame. |
| 10151 *isolate->debug()->debug_context())); | 10160 // bit 2: inlined in optimized frame |
| 10161 int flags = 0; |
| 10162 if (*save->context() == *isolate->debug()->debug_context()) { |
| 10163 flags |= 1 << 0; |
| 10164 } |
| 10165 if (it.frame()->is_optimized()) { |
| 10166 flags |= 1 << 1; |
| 10167 if (deoptimized_frame_index > 0) { |
| 10168 flags |= 1 << 2; |
| 10169 } |
| 10170 } |
| 10171 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); |
| 10152 | 10172 |
| 10153 // Fill the dynamic part. | 10173 // Fill the dynamic part. |
| 10154 int details_index = kFrameDetailsFirstDynamicIndex; | 10174 int details_index = kFrameDetailsFirstDynamicIndex; |
| 10155 | 10175 |
| 10156 // Add arguments name and value. | 10176 // Add arguments name and value. |
| 10157 for (int i = 0; i < argument_count; i++) { | 10177 for (int i = 0; i < argument_count; i++) { |
| 10158 // Name of the argument. | 10178 // Name of the argument. |
| 10159 if (i < info.number_of_parameters()) { | 10179 if (i < info.number_of_parameters()) { |
| 10160 details->set(details_index++, *info.parameter_name(i)); | 10180 details->set(details_index++, *info.parameter_name(i)); |
| 10161 } else { | 10181 } else { |
| 10162 details->set(details_index++, heap->undefined_value()); | 10182 details->set(details_index++, heap->undefined_value()); |
| 10163 } | 10183 } |
| 10164 | 10184 |
| 10165 // Parameter value. If we are inspecting an optimized frame, use | 10185 // Parameter value. If we are inspecting an optimized frame, use |
| 10166 // undefined as the value. | 10186 // undefined as the value. |
| 10167 // | 10187 // |
| 10168 // TODO(3141533): We should be able to get the actual parameter | 10188 // TODO(3141533): We should be able to get the actual parameter |
| 10169 // value for optimized frames. | 10189 // value for optimized frames. |
| 10170 if (!is_optimized_frame && | 10190 if (!it.frame()->is_optimized() && |
| 10171 (i < it.frame()->ComputeParametersCount())) { | 10191 (i < it.frame()->ComputeParametersCount())) { |
| 10172 details->set(details_index++, it.frame()->GetParameter(i)); | 10192 details->set(details_index++, it.frame()->GetParameter(i)); |
| 10173 } else { | 10193 } else { |
| 10174 details->set(details_index++, heap->undefined_value()); | 10194 details->set(details_index++, heap->undefined_value()); |
| 10175 } | 10195 } |
| 10176 } | 10196 } |
| 10177 | 10197 |
| 10178 // Add locals name and value from the temporary copy from the function frame. | 10198 // Add locals name and value from the temporary copy from the function frame. |
| 10179 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { | 10199 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { |
| 10180 details->set(details_index++, locals->get(i)); | 10200 details->set(details_index++, locals->get(i)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 10196 // by creating correct wrapper object based on the calling frame's | 10216 // by creating correct wrapper object based on the calling frame's |
| 10197 // global context. | 10217 // global context. |
| 10198 it.Advance(); | 10218 it.Advance(); |
| 10199 Handle<Context> calling_frames_global_context( | 10219 Handle<Context> calling_frames_global_context( |
| 10200 Context::cast(Context::cast(it.frame()->context())->global_context())); | 10220 Context::cast(Context::cast(it.frame()->context())->global_context())); |
| 10201 receiver = | 10221 receiver = |
| 10202 isolate->factory()->ToObject(receiver, calling_frames_global_context); | 10222 isolate->factory()->ToObject(receiver, calling_frames_global_context); |
| 10203 } | 10223 } |
| 10204 details->set(kFrameDetailsReceiverIndex, *receiver); | 10224 details->set(kFrameDetailsReceiverIndex, *receiver); |
| 10205 | 10225 |
| 10226 // Get rid of the calculated deoptimized frame if any. |
| 10227 if (deoptimized_frame != NULL) { |
| 10228 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame, |
| 10229 isolate); |
| 10230 } |
| 10231 |
| 10206 ASSERT_EQ(details_size, details_index); | 10232 ASSERT_EQ(details_size, details_index); |
| 10207 return *isolate->factory()->NewJSArrayWithElements(details); | 10233 return *isolate->factory()->NewJSArrayWithElements(details); |
| 10208 } | 10234 } |
| 10209 | 10235 |
| 10210 | 10236 |
| 10211 // Copy all the context locals into an object used to materialize a scope. | 10237 // Copy all the context locals into an object used to materialize a scope. |
| 10212 static bool CopyContextLocalsToScopeObject( | 10238 static bool CopyContextLocalsToScopeObject( |
| 10213 Isolate* isolate, | 10239 Isolate* isolate, |
| 10214 Handle<SerializedScopeInfo> serialized_scope_info, | 10240 Handle<SerializedScopeInfo> serialized_scope_info, |
| 10215 ScopeInfo<>& scope_info, | 10241 ScopeInfo<>& scope_info, |
| (...skipping 2308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12524 } else { | 12550 } else { |
| 12525 // Handle last resort GC and make sure to allow future allocations | 12551 // Handle last resort GC and make sure to allow future allocations |
| 12526 // to grow the heap without causing GCs (if possible). | 12552 // to grow the heap without causing GCs (if possible). |
| 12527 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12553 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 12528 isolate->heap()->CollectAllGarbage(false); | 12554 isolate->heap()->CollectAllGarbage(false); |
| 12529 } | 12555 } |
| 12530 } | 12556 } |
| 12531 | 12557 |
| 12532 | 12558 |
| 12533 } } // namespace v8::internal | 12559 } } // namespace v8::internal |
| OLD | NEW |