• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/debug/debug-frames.h"
6 
7 #include "src/frames-inl.h"
8 
9 namespace v8 {
10 namespace internal {
11 
FrameInspector(JavaScriptFrame * frame,int inlined_jsframe_index,Isolate * isolate)12 FrameInspector::FrameInspector(JavaScriptFrame* frame,
13                                int inlined_jsframe_index, Isolate* isolate)
14     : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
15   has_adapted_arguments_ = frame_->has_adapted_arguments();
16   is_bottommost_ = inlined_jsframe_index == 0;
17   is_optimized_ = frame_->is_optimized();
18   is_interpreted_ = frame_->is_interpreted();
19   // Calculate the deoptimized frame.
20   if (frame->is_optimized()) {
21     // TODO(turbofan): Revisit once we support deoptimization.
22     if (frame->LookupCode()->is_turbofanned() &&
23         frame->function()->shared()->asm_function() &&
24         !FLAG_turbo_asm_deoptimization) {
25       is_optimized_ = false;
26       return;
27     }
28 
29     deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
30         frame, inlined_jsframe_index, isolate);
31   }
32 }
33 
34 
~FrameInspector()35 FrameInspector::~FrameInspector() {
36   // Get rid of the calculated deoptimized frame if any.
37   if (deoptimized_frame_ != NULL) {
38     Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_);
39   }
40 }
41 
42 
GetParametersCount()43 int FrameInspector::GetParametersCount() {
44   return is_optimized_ ? deoptimized_frame_->parameters_count()
45                        : frame_->ComputeParametersCount();
46 }
47 
GetFunction()48 Handle<Object> FrameInspector::GetFunction() {
49   return is_optimized_ ? deoptimized_frame_->GetFunction()
50                        : handle(frame_->function(), isolate_);
51 }
52 
GetParameter(int index)53 Handle<Object> FrameInspector::GetParameter(int index) {
54   return is_optimized_ ? deoptimized_frame_->GetParameter(index)
55                        : handle(frame_->GetParameter(index), isolate_);
56 }
57 
GetExpression(int index)58 Handle<Object> FrameInspector::GetExpression(int index) {
59   // TODO(turbofan): Revisit once we support deoptimization.
60   if (frame_->LookupCode()->is_turbofanned() &&
61       frame_->function()->shared()->asm_function() &&
62       !FLAG_turbo_asm_deoptimization) {
63     return isolate_->factory()->undefined_value();
64   }
65   return is_optimized_ ? deoptimized_frame_->GetExpression(index)
66                        : handle(frame_->GetExpression(index), isolate_);
67 }
68 
69 
GetSourcePosition()70 int FrameInspector::GetSourcePosition() {
71   if (is_optimized_) {
72     return deoptimized_frame_->GetSourcePosition();
73   } else if (is_interpreted_) {
74     InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
75     BytecodeArray* bytecode_array = frame->GetBytecodeArray();
76     return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
77   } else {
78     Code* code = frame_->LookupCode();
79     int offset = static_cast<int>(frame_->pc() - code->instruction_start());
80     return code->SourcePosition(offset);
81   }
82 }
83 
84 
IsConstructor()85 bool FrameInspector::IsConstructor() {
86   return is_optimized_ && !is_bottommost_
87              ? deoptimized_frame_->HasConstructStub()
88              : frame_->IsConstructor();
89 }
90 
GetContext()91 Handle<Object> FrameInspector::GetContext() {
92   return is_optimized_ ? deoptimized_frame_->GetContext()
93                        : handle(frame_->context(), isolate_);
94 }
95 
96 
97 // To inspect all the provided arguments the frame might need to be
98 // replaced with the arguments frame.
SetArgumentsFrame(JavaScriptFrame * frame)99 void FrameInspector::SetArgumentsFrame(JavaScriptFrame* frame) {
100   DCHECK(has_adapted_arguments_);
101   frame_ = frame;
102   is_optimized_ = frame_->is_optimized();
103   is_interpreted_ = frame_->is_interpreted();
104   DCHECK(!is_optimized_);
105 }
106 
107 
108 // Create a plain JSObject which materializes the local scope for the specified
109 // frame.
MaterializeStackLocals(Handle<JSObject> target,Handle<ScopeInfo> scope_info)110 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
111                                             Handle<ScopeInfo> scope_info) {
112   HandleScope scope(isolate_);
113   // First fill all parameters.
114   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
115     // Do not materialize the parameter if it is shadowed by a context local.
116     // TODO(yangguo): check whether this is necessary, now that we materialize
117     //                context locals as well.
118     Handle<String> name(scope_info->ParameterName(i));
119     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
120     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
121 
122     Handle<Object> value =
123         i < GetParametersCount()
124             ? GetParameter(i)
125             : Handle<Object>::cast(isolate_->factory()->undefined_value());
126     DCHECK(!value->IsTheHole(isolate_));
127 
128     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
129   }
130 
131   // Second fill all stack locals.
132   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
133     Handle<String> name(scope_info->StackLocalName(i));
134     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
135     Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
136     // TODO(yangguo): We convert optimized out values to {undefined} when they
137     // are passed to the debugger. Eventually we should handle them somehow.
138     if (value->IsTheHole(isolate_)) {
139       value = isolate_->factory()->undefined_value();
140     }
141     if (value->IsOptimizedOut(isolate_)) {
142       value = isolate_->factory()->undefined_value();
143     }
144     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
145   }
146 }
147 
148 
MaterializeStackLocals(Handle<JSObject> target,Handle<JSFunction> function)149 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
150                                             Handle<JSFunction> function) {
151   Handle<SharedFunctionInfo> shared(function->shared());
152   Handle<ScopeInfo> scope_info(shared->scope_info());
153   MaterializeStackLocals(target, scope_info);
154 }
155 
156 
UpdateStackLocalsFromMaterializedObject(Handle<JSObject> target,Handle<ScopeInfo> scope_info)157 void FrameInspector::UpdateStackLocalsFromMaterializedObject(
158     Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
159   if (is_optimized_) {
160     // Optimized frames are not supported. Simply give up.
161     return;
162   }
163 
164   HandleScope scope(isolate_);
165 
166   // Parameters.
167   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
168     // Shadowed parameters were not materialized.
169     Handle<String> name(scope_info->ParameterName(i));
170     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
171     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
172 
173     DCHECK(!frame_->GetParameter(i)->IsTheHole(isolate_));
174     Handle<Object> value =
175         Object::GetPropertyOrElement(target, name).ToHandleChecked();
176     frame_->SetParameterValue(i, *value);
177   }
178 
179   // Stack locals.
180   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
181     Handle<String> name(scope_info->StackLocalName(i));
182     if (ScopeInfo::VariableIsSynthetic(*name)) continue;
183     int index = scope_info->StackLocalIndex(i);
184     if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
185     Handle<Object> value =
186         Object::GetPropertyOrElement(target, name).ToHandleChecked();
187     frame_->SetExpression(index, *value);
188   }
189 }
190 
191 
ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,Handle<String> parameter_name)192 bool FrameInspector::ParameterIsShadowedByContextLocal(
193     Handle<ScopeInfo> info, Handle<String> parameter_name) {
194   VariableMode mode;
195   InitializationFlag init_flag;
196   MaybeAssignedFlag maybe_assigned_flag;
197   return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
198                                      &maybe_assigned_flag) != -1;
199 }
200 
201 
FindSavedContextForFrame(Isolate * isolate,JavaScriptFrame * frame)202 SaveContext* DebugFrameHelper::FindSavedContextForFrame(
203     Isolate* isolate, JavaScriptFrame* frame) {
204   SaveContext* save = isolate->save_context();
205   while (save != NULL && !save->IsBelowFrame(frame)) {
206     save = save->prev();
207   }
208   DCHECK(save != NULL);
209   return save;
210 }
211 
212 
FindIndexedNonNativeFrame(JavaScriptFrameIterator * it,int index)213 int DebugFrameHelper::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it,
214                                                 int index) {
215   int count = -1;
216   for (; !it->done(); it->Advance()) {
217     List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
218     it->frame()->Summarize(&frames);
219     for (int i = frames.length() - 1; i >= 0; i--) {
220       // Omit functions from native and extension scripts.
221       if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue;
222       if (++count == index) return i;
223     }
224   }
225   return -1;
226 }
227 
228 
229 }  // namespace internal
230 }  // namespace v8
231