Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: src/runtime.cc

Issue 7230045: Support debugger inspection of locals in optimized frames (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Removed test code Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698