blob: 25634be8d233178429cfd8cf0fe3ae739cf96f0c [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
9namespace v8 {
10namespace internal {
11
12FrameInspector::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();
Ben Murdoch097c5b22016-05-18 11:27:45 +010018 is_interpreted_ = frame_->is_interpreted();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019 // 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
35FrameInspector::~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
43int FrameInspector::GetParametersCount() {
44 return is_optimized_ ? deoptimized_frame_->parameters_count()
45 : frame_->ComputeParametersCount();
46}
47
Ben Murdoch097c5b22016-05-18 11:27:45 +010048Handle<Object> FrameInspector::GetFunction() {
49 return is_optimized_ ? deoptimized_frame_->GetFunction()
50 : handle(frame_->function(), isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051}
52
Ben Murdoch097c5b22016-05-18 11:27:45 +010053Handle<Object> FrameInspector::GetParameter(int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 return is_optimized_ ? deoptimized_frame_->GetParameter(index)
Ben Murdoch097c5b22016-05-18 11:27:45 +010055 : handle(frame_->GetParameter(index), isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056}
57
Ben Murdoch097c5b22016-05-18 11:27:45 +010058Handle<Object> FrameInspector::GetExpression(int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 // TODO(turbofan): Revisit once we support deoptimization.
60 if (frame_->LookupCode()->is_turbofanned() &&
61 frame_->function()->shared()->asm_function() &&
62 !FLAG_turbo_asm_deoptimization) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010063 return isolate_->factory()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 }
65 return is_optimized_ ? deoptimized_frame_->GetExpression(index)
Ben Murdoch097c5b22016-05-18 11:27:45 +010066 : handle(frame_->GetExpression(index), isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067}
68
69
70int FrameInspector::GetSourcePosition() {
Ben Murdoch097c5b22016-05-18 11:27:45 +010071 if (is_optimized_) {
72 return deoptimized_frame_->GetSourcePosition();
73 } else if (is_interpreted_) {
74 InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
75 BytecodeArray* bytecode_array =
76 frame->function()->shared()->bytecode_array();
77 return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
78 } else {
79 Code* code = frame_->LookupCode();
80 int offset = static_cast<int>(frame_->pc() - code->instruction_start());
81 return code->SourcePosition(offset);
82 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083}
84
85
86bool FrameInspector::IsConstructor() {
87 return is_optimized_ && !is_bottommost_
88 ? deoptimized_frame_->HasConstructStub()
89 : frame_->IsConstructor();
90}
91
Ben Murdoch097c5b22016-05-18 11:27:45 +010092Handle<Object> FrameInspector::GetContext() {
93 return is_optimized_ ? deoptimized_frame_->GetContext()
94 : handle(frame_->context(), isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095}
96
97
98// To inspect all the provided arguments the frame might need to be
99// replaced with the arguments frame.
100void FrameInspector::SetArgumentsFrame(JavaScriptFrame* frame) {
101 DCHECK(has_adapted_arguments_);
102 frame_ = frame;
103 is_optimized_ = frame_->is_optimized();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100104 is_interpreted_ = frame_->is_interpreted();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 DCHECK(!is_optimized_);
106}
107
108
109// Create a plain JSObject which materializes the local scope for the specified
110// frame.
111void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
112 Handle<ScopeInfo> scope_info) {
113 HandleScope scope(isolate_);
114 // First fill all parameters.
115 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
116 // Do not materialize the parameter if it is shadowed by a context local.
117 // TODO(yangguo): check whether this is necessary, now that we materialize
118 // context locals as well.
119 Handle<String> name(scope_info->ParameterName(i));
120 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
121
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 Handle<Object> value =
123 i < GetParametersCount()
124 ? GetParameter(i)
125 : Handle<Object>::cast(isolate_->factory()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 DCHECK(!value->IsTheHole());
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 if (scope_info->LocalIsSynthetic(i)) continue;
134 Handle<String> name(scope_info->StackLocalName(i));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100135 Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
137
138 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
139 }
140}
141
142
143void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
144 Handle<JSFunction> function) {
145 Handle<SharedFunctionInfo> shared(function->shared());
146 Handle<ScopeInfo> scope_info(shared->scope_info());
147 MaterializeStackLocals(target, scope_info);
148}
149
150
151void FrameInspector::UpdateStackLocalsFromMaterializedObject(
152 Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
153 if (is_optimized_) {
154 // Optimized frames are not supported. Simply give up.
155 return;
156 }
157
158 HandleScope scope(isolate_);
159
160 // Parameters.
161 for (int i = 0; i < scope_info->ParameterCount(); ++i) {
162 // Shadowed parameters were not materialized.
163 Handle<String> name(scope_info->ParameterName(i));
164 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
165
166 DCHECK(!frame_->GetParameter(i)->IsTheHole());
167 Handle<Object> value =
168 Object::GetPropertyOrElement(target, name).ToHandleChecked();
169 frame_->SetParameterValue(i, *value);
170 }
171
172 // Stack locals.
173 for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
174 if (scope_info->LocalIsSynthetic(i)) continue;
175 int index = scope_info->StackLocalIndex(i);
176 if (frame_->GetExpression(index)->IsTheHole()) continue;
177 Handle<Object> value =
178 Object::GetPropertyOrElement(
179 target, handle(scope_info->StackLocalName(i), isolate_))
180 .ToHandleChecked();
181 frame_->SetExpression(index, *value);
182 }
183}
184
185
186bool FrameInspector::ParameterIsShadowedByContextLocal(
187 Handle<ScopeInfo> info, Handle<String> parameter_name) {
188 VariableMode mode;
189 InitializationFlag init_flag;
190 MaybeAssignedFlag maybe_assigned_flag;
191 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
192 &maybe_assigned_flag) != -1;
193}
194
195
196SaveContext* DebugFrameHelper::FindSavedContextForFrame(
197 Isolate* isolate, JavaScriptFrame* frame) {
198 SaveContext* save = isolate->save_context();
199 while (save != NULL && !save->IsBelowFrame(frame)) {
200 save = save->prev();
201 }
202 DCHECK(save != NULL);
203 return save;
204}
205
206
207int DebugFrameHelper::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it,
208 int index) {
209 int count = -1;
210 for (; !it->done(); it->Advance()) {
211 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
212 it->frame()->Summarize(&frames);
213 for (int i = frames.length() - 1; i >= 0; i--) {
214 // Omit functions from native and extension scripts.
215 if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue;
216 if (++count == index) return i;
217 }
218 }
219 return -1;
220}
221
222
223} // namespace internal
224} // namespace v8