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 9882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9893 if (!maybe_result->ToObject(&result)) return maybe_result; | 9893 if (!maybe_result->ToObject(&result)) return maybe_result; |
9894 } | 9894 } |
9895 | 9895 |
9896 // Count all frames which are relevant to debugging stack trace. | 9896 // Count all frames which are relevant to debugging stack trace. |
9897 int n = 0; | 9897 int n = 0; |
9898 StackFrame::Id id = isolate->debug()->break_frame_id(); | 9898 StackFrame::Id id = isolate->debug()->break_frame_id(); |
9899 if (id == StackFrame::NO_ID) { | 9899 if (id == StackFrame::NO_ID) { |
9900 // If there is no JavaScript stack frame count is 0. | 9900 // If there is no JavaScript stack frame count is 0. |
9901 return Smi::FromInt(0); | 9901 return Smi::FromInt(0); |
9902 } | 9902 } |
9903 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++; | 9903 |
| 9904 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { |
| 9905 n += it.frame()->GetInlineCount(); |
| 9906 } |
9904 return Smi::FromInt(n); | 9907 return Smi::FromInt(n); |
9905 } | 9908 } |
9906 | 9909 |
9907 | 9910 |
9908 static const int kFrameDetailsFrameIdIndex = 0; | 9911 static const int kFrameDetailsFrameIdIndex = 0; |
9909 static const int kFrameDetailsReceiverIndex = 1; | 9912 static const int kFrameDetailsReceiverIndex = 1; |
9910 static const int kFrameDetailsFunctionIndex = 2; | 9913 static const int kFrameDetailsFunctionIndex = 2; |
9911 static const int kFrameDetailsArgumentCountIndex = 3; | 9914 static const int kFrameDetailsArgumentCountIndex = 3; |
9912 static const int kFrameDetailsLocalCountIndex = 4; | 9915 static const int kFrameDetailsLocalCountIndex = 4; |
9913 static const int kFrameDetailsSourcePositionIndex = 5; | 9916 static const int kFrameDetailsSourcePositionIndex = 5; |
9914 static const int kFrameDetailsConstructCallIndex = 6; | 9917 static const int kFrameDetailsConstructCallIndex = 6; |
9915 static const int kFrameDetailsAtReturnIndex = 7; | 9918 static const int kFrameDetailsAtReturnIndex = 7; |
9916 static const int kFrameDetailsDebuggerFrameIndex = 8; | 9919 static const int kFrameDetailsFlagsIndex = 8; |
9917 static const int kFrameDetailsFirstDynamicIndex = 9; | 9920 static const int kFrameDetailsFirstDynamicIndex = 9; |
9918 | 9921 |
9919 // Return an array with frame details | 9922 // Return an array with frame details |
9920 // args[0]: number: break id | 9923 // args[0]: number: break id |
9921 // args[1]: number: frame index | 9924 // args[1]: number: frame index |
9922 // | 9925 // |
9923 // The array returned contains the following information: | 9926 // The array returned contains the following information: |
9924 // 0: Frame id | 9927 // 0: Frame id |
9925 // 1: Receiver | 9928 // 1: Receiver |
9926 // 2: Function | 9929 // 2: Function |
9927 // 3: Argument count | 9930 // 3: Argument count |
9928 // 4: Local count | 9931 // 4: Local count |
9929 // 5: Source position | 9932 // 5: Source position |
9930 // 6: Constructor call | 9933 // 6: Constructor call |
9931 // 7: Is at return | 9934 // 7: Is at return |
9932 // 8: Debugger frame | 9935 // 8: Flags |
9933 // Arguments name, value | 9936 // Arguments name, value |
9934 // Locals name, value | 9937 // Locals name, value |
9935 // Return value if any | 9938 // Return value if any |
9936 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { | 9939 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { |
9937 HandleScope scope(isolate); | 9940 HandleScope scope(isolate); |
9938 ASSERT(args.length() == 2); | 9941 ASSERT(args.length() == 2); |
9939 | 9942 |
9940 // Check arguments. | 9943 // Check arguments. |
9941 Object* check; | 9944 Object* check; |
9942 { MaybeObject* maybe_check = Runtime_CheckExecutionState( | 9945 { MaybeObject* maybe_check = Runtime_CheckExecutionState( |
9943 RUNTIME_ARGUMENTS(isolate, args)); | 9946 RUNTIME_ARGUMENTS(isolate, args)); |
9944 if (!maybe_check->ToObject(&check)) return maybe_check; | 9947 if (!maybe_check->ToObject(&check)) return maybe_check; |
9945 } | 9948 } |
9946 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | 9949 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); |
9947 Heap* heap = isolate->heap(); | 9950 Heap* heap = isolate->heap(); |
9948 | 9951 |
9949 // Find the relevant frame with the requested index. | 9952 // Find the relevant frame with the requested index. |
9950 StackFrame::Id id = isolate->debug()->break_frame_id(); | 9953 StackFrame::Id id = isolate->debug()->break_frame_id(); |
9951 if (id == StackFrame::NO_ID) { | 9954 if (id == StackFrame::NO_ID) { |
9952 // If there are no JavaScript stack frames return undefined. | 9955 // If there are no JavaScript stack frames return undefined. |
9953 return heap->undefined_value(); | 9956 return heap->undefined_value(); |
9954 } | 9957 } |
| 9958 |
| 9959 int deoptimized_frame_index = -1; // Frame index in optimized frame. |
| 9960 DeoptimizedFrameInfo* deoptimized_frame = NULL; |
| 9961 |
9955 int count = 0; | 9962 int count = 0; |
9956 JavaScriptFrameIterator it(isolate, id); | 9963 JavaScriptFrameIterator it(isolate, id); |
9957 for (; !it.done(); it.Advance()) { | 9964 for (; !it.done(); it.Advance()) { |
9958 if (count == index) break; | 9965 if (index < count + it.frame()->GetInlineCount()) break; |
9959 count++; | 9966 count += it.frame()->GetInlineCount(); |
9960 } | 9967 } |
9961 if (it.done()) return heap->undefined_value(); | 9968 if (it.done()) return heap->undefined_value(); |
9962 | 9969 |
9963 bool is_optimized_frame = | 9970 if (it.frame()->is_optimized()) { |
9964 it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION; | 9971 deoptimized_frame_index = |
| 9972 it.frame()->GetInlineCount() - (index - count) - 1; |
| 9973 deoptimized_frame = Deoptimizer::DebuggerInspectableFrame( |
| 9974 it.frame(), |
| 9975 deoptimized_frame_index, |
| 9976 isolate); |
| 9977 } |
9965 | 9978 |
9966 // Traverse the saved contexts chain to find the active context for the | 9979 // Traverse the saved contexts chain to find the active context for the |
9967 // selected frame. | 9980 // selected frame. |
9968 SaveContext* save = isolate->save_context(); | 9981 SaveContext* save = isolate->save_context(); |
9969 while (save != NULL && !save->below(it.frame())) { | 9982 while (save != NULL && !save->below(it.frame())) { |
9970 save = save->prev(); | 9983 save = save->prev(); |
9971 } | 9984 } |
9972 ASSERT(save != NULL); | 9985 ASSERT(save != NULL); |
9973 | 9986 |
9974 // Get the frame id. | 9987 // Get the frame id. |
9975 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | 9988 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); |
9976 | 9989 |
9977 // Find source position. | 9990 // Find source position. |
9978 int position = | 9991 int position = |
9979 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); | 9992 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); |
9980 | 9993 |
9981 // Check for constructor frame. | 9994 // Check for constructor frame. |
9982 bool constructor = it.frame()->IsConstructor(); | 9995 bool constructor = it.frame()->IsConstructor(); |
9983 | 9996 |
9984 // Get scope info and read from it for local variable information. | 9997 // Get scope info and read from it for local variable information. |
9985 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); | 9998 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); |
9986 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); | 9999 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); |
| 10000 ASSERT(*scope_info != SerializedScopeInfo::Empty()); |
9987 ScopeInfo<> info(*scope_info); | 10001 ScopeInfo<> info(*scope_info); |
9988 | 10002 |
9989 // Get the nearest enclosing function context. | 10003 // Get the nearest enclosing function context. |
9990 Handle<Context> context(Context::cast(it.frame()->context())->fcontext()); | 10004 Handle<Context> context(Context::cast(it.frame()->context())->fcontext()); |
9991 | 10005 |
9992 // Get the locals names and values into a temporary array. | 10006 // Get the locals names and values into a temporary array. |
9993 // | 10007 // |
9994 // TODO(1240907): Hide compiler-introduced stack variables | 10008 // TODO(1240907): Hide compiler-introduced stack variables |
9995 // (e.g. .result)? For users of the debugger, they will probably be | 10009 // (e.g. .result)? For users of the debugger, they will probably be |
9996 // confusing. | 10010 // confusing. |
9997 Handle<FixedArray> locals = | 10011 Handle<FixedArray> locals = |
9998 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); | 10012 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); |
9999 | 10013 |
10000 // Fill in the names of the locals. | 10014 // Fill in the names of the locals. |
10001 for (int i = 0; i < info.NumberOfLocals(); i++) { | 10015 for (int i = 0; i < info.NumberOfLocals(); i++) { |
10002 locals->set(i * 2, *info.LocalName(i)); | 10016 locals->set(i * 2, *info.LocalName(i)); |
10003 } | 10017 } |
10004 | 10018 |
10005 // Fill in the values of the locals. | 10019 // Fill in the values of the locals. |
10006 if (is_optimized_frame) { | 10020 for (int i = 0; i < info.number_of_stack_slots(); i++) { |
10007 // If we are inspecting an optimized frame use undefined as the | 10021 if (it.frame()->is_optimized()) { |
10008 // value for all locals. | 10022 // Get the value from the deoptimized frame. |
10009 // | 10023 locals->set(i * 2 + 1, |
10010 // TODO(1140): We should be able to get the correct values | 10024 deoptimized_frame->GetExpression(i)); |
10011 // for locals in optimized frames. | 10025 } else { |
10012 for (int i = 0; i < info.NumberOfLocals(); i++) { | |
10013 locals->set(i * 2 + 1, isolate->heap()->undefined_value()); | |
10014 } | |
10015 } else { | |
10016 for (int i = 0; i < info.number_of_stack_slots(); i++) { | |
10017 // Get the value from the stack. | 10026 // Get the value from the stack. |
10018 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 10027 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); |
10019 } | 10028 } |
10020 for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) { | 10029 } |
10021 Handle<String> name = info.LocalName(i); | 10030 for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) { |
10022 locals->set(i * 2 + 1, | 10031 Handle<String> name = info.LocalName(i); |
10023 context->get(scope_info->ContextSlotIndex(*name, NULL))); | 10032 locals->set(i * 2 + 1, |
10024 } | 10033 context->get(scope_info->ContextSlotIndex(*name, NULL))); |
10025 } | 10034 } |
10026 | 10035 |
10027 // Check whether this frame is positioned at return. If not top | 10036 // Check whether this frame is positioned at return. If not top |
10028 // frame or if the frame is optimized it cannot be at a return. | 10037 // frame or if the frame is optimized it cannot be at a return. |
10029 bool at_return = false; | 10038 bool at_return = false; |
10030 if (!is_optimized_frame && index == 0) { | 10039 if (!it.frame()->is_optimized() && index == 0) { |
10031 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); | 10040 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); |
10032 } | 10041 } |
10033 | 10042 |
10034 // If positioned just before return find the value to be returned and add it | 10043 // If positioned just before return find the value to be returned and add it |
10035 // to the frame information. | 10044 // to the frame information. |
10036 Handle<Object> return_value = isolate->factory()->undefined_value(); | 10045 Handle<Object> return_value = isolate->factory()->undefined_value(); |
10037 if (at_return) { | 10046 if (at_return) { |
10038 StackFrameIterator it2(isolate); | 10047 StackFrameIterator it2(isolate); |
10039 Address internal_frame_sp = NULL; | 10048 Address internal_frame_sp = NULL; |
10040 while (!it2.done()) { | 10049 while (!it2.done()) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10101 } else { | 10110 } else { |
10102 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); | 10111 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); |
10103 } | 10112 } |
10104 | 10113 |
10105 // Add the constructor information. | 10114 // Add the constructor information. |
10106 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); | 10115 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); |
10107 | 10116 |
10108 // Add the at return information. | 10117 // Add the at return information. |
10109 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); | 10118 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); |
10110 | 10119 |
10111 // Add information on whether this frame is invoked in the debugger context. | 10120 // Add flags to indicate information on whether this frame is |
10112 details->set(kFrameDetailsDebuggerFrameIndex, | 10121 // bit 0: invoked in the debugger context. |
10113 heap->ToBoolean(*save->context() == | 10122 // bit 1: optimized frame. |
10114 *isolate->debug()->debug_context())); | 10123 // bit 2: inlined in optimized frame |
| 10124 int flags = 0; |
| 10125 if (*save->context() == *isolate->debug()->debug_context()) { |
| 10126 flags |= 1 << 0; |
| 10127 } |
| 10128 if (it.frame()->is_optimized()) { |
| 10129 flags |= 1 << 1; |
| 10130 if (deoptimized_frame_index > 0) { |
| 10131 flags |= 1 << 2; |
| 10132 } |
| 10133 } |
| 10134 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); |
10115 | 10135 |
10116 // Fill the dynamic part. | 10136 // Fill the dynamic part. |
10117 int details_index = kFrameDetailsFirstDynamicIndex; | 10137 int details_index = kFrameDetailsFirstDynamicIndex; |
10118 | 10138 |
10119 // Add arguments name and value. | 10139 // Add arguments name and value. |
10120 for (int i = 0; i < argument_count; i++) { | 10140 for (int i = 0; i < argument_count; i++) { |
10121 // Name of the argument. | 10141 // Name of the argument. |
10122 if (i < info.number_of_parameters()) { | 10142 if (i < info.number_of_parameters()) { |
10123 details->set(details_index++, *info.parameter_name(i)); | 10143 details->set(details_index++, *info.parameter_name(i)); |
10124 } else { | 10144 } else { |
10125 details->set(details_index++, heap->undefined_value()); | 10145 details->set(details_index++, heap->undefined_value()); |
10126 } | 10146 } |
10127 | 10147 |
10128 // Parameter value. If we are inspecting an optimized frame, use | 10148 // Parameter value. If we are inspecting an optimized frame, use |
10129 // undefined as the value. | 10149 // undefined as the value. |
10130 // | 10150 // |
10131 // TODO(3141533): We should be able to get the actual parameter | 10151 // TODO(3141533): We should be able to get the actual parameter |
10132 // value for optimized frames. | 10152 // value for optimized frames. |
10133 if (!is_optimized_frame && | 10153 if (!it.frame()->is_optimized() && |
10134 (i < it.frame()->ComputeParametersCount())) { | 10154 (i < it.frame()->ComputeParametersCount())) { |
10135 details->set(details_index++, it.frame()->GetParameter(i)); | 10155 details->set(details_index++, it.frame()->GetParameter(i)); |
10136 } else { | 10156 } else { |
10137 details->set(details_index++, heap->undefined_value()); | 10157 details->set(details_index++, heap->undefined_value()); |
10138 } | 10158 } |
10139 } | 10159 } |
10140 | 10160 |
10141 // Add locals name and value from the temporary copy from the function frame. | 10161 // Add locals name and value from the temporary copy from the function frame. |
10142 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { | 10162 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { |
10143 details->set(details_index++, locals->get(i)); | 10163 details->set(details_index++, locals->get(i)); |
(...skipping 15 matching lines...) Expand all Loading... |
10159 // by creating correct wrapper object based on the calling frame's | 10179 // by creating correct wrapper object based on the calling frame's |
10160 // global context. | 10180 // global context. |
10161 it.Advance(); | 10181 it.Advance(); |
10162 Handle<Context> calling_frames_global_context( | 10182 Handle<Context> calling_frames_global_context( |
10163 Context::cast(Context::cast(it.frame()->context())->global_context())); | 10183 Context::cast(Context::cast(it.frame()->context())->global_context())); |
10164 receiver = | 10184 receiver = |
10165 isolate->factory()->ToObject(receiver, calling_frames_global_context); | 10185 isolate->factory()->ToObject(receiver, calling_frames_global_context); |
10166 } | 10186 } |
10167 details->set(kFrameDetailsReceiverIndex, *receiver); | 10187 details->set(kFrameDetailsReceiverIndex, *receiver); |
10168 | 10188 |
| 10189 // Get rid of the calculated deoptimized frame if any. |
| 10190 if (deoptimized_frame != NULL) { |
| 10191 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame, |
| 10192 isolate); |
| 10193 } |
| 10194 |
10169 ASSERT_EQ(details_size, details_index); | 10195 ASSERT_EQ(details_size, details_index); |
10170 return *isolate->factory()->NewJSArrayWithElements(details); | 10196 return *isolate->factory()->NewJSArrayWithElements(details); |
10171 } | 10197 } |
10172 | 10198 |
10173 | 10199 |
10174 // Copy all the context locals into an object used to materialize a scope. | 10200 // Copy all the context locals into an object used to materialize a scope. |
10175 static bool CopyContextLocalsToScopeObject( | 10201 static bool CopyContextLocalsToScopeObject( |
10176 Isolate* isolate, | 10202 Isolate* isolate, |
10177 Handle<SerializedScopeInfo> serialized_scope_info, | 10203 Handle<SerializedScopeInfo> serialized_scope_info, |
10178 ScopeInfo<>& scope_info, | 10204 ScopeInfo<>& scope_info, |
(...skipping 2302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12481 } else { | 12507 } else { |
12482 // Handle last resort GC and make sure to allow future allocations | 12508 // Handle last resort GC and make sure to allow future allocations |
12483 // to grow the heap without causing GCs (if possible). | 12509 // to grow the heap without causing GCs (if possible). |
12484 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12510 isolate->counters()->gc_last_resort_from_js()->Increment(); |
12485 isolate->heap()->CollectAllGarbage(false); | 12511 isolate->heap()->CollectAllGarbage(false); |
12486 } | 12512 } |
12487 } | 12513 } |
12488 | 12514 |
12489 | 12515 |
12490 } } // namespace v8::internal | 12516 } } // namespace v8::internal |
OLD | NEW |