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

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: Rebase 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
« no previous file with comments | « src/objects.cc ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 9920 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.cc ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698