Line data Source code
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 : #include "src/wasm/wasm-interpreter.h"
9 : #include "src/wasm/wasm-objects.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 451502 : FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index,
15 : Isolate* isolate)
16 : : frame_(frame),
17 : frame_summary_(FrameSummary::Get(frame, inlined_frame_index)),
18 451502 : isolate_(isolate) {
19 : JavaScriptFrame* js_frame =
20 451502 : frame->is_java_script() ? javascript_frame() : nullptr;
21 : DCHECK(js_frame || frame->is_wasm());
22 902532 : has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
23 451502 : is_bottommost_ = inlined_frame_index == 0;
24 903280 : is_optimized_ = frame_->is_optimized();
25 903004 : is_interpreted_ = frame_->is_interpreted();
26 :
27 : // Calculate the deoptimized frame.
28 451502 : if (is_optimized_) {
29 : DCHECK(js_frame != nullptr);
30 : // TODO(turbofan): Revisit once we support deoptimization.
31 80067 : if (js_frame->LookupCode()->is_turbofanned() &&
32 31017 : js_frame->function()->shared()->asm_function()) {
33 56 : is_optimized_ = false;
34 451558 : return;
35 : }
36 :
37 : deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
38 48994 : js_frame, inlined_frame_index, isolate));
39 804904 : } else if (frame_->is_wasm_interpreter_entry()) {
40 828 : wasm_interpreted_frame_ =
41 : frame_summary_.AsWasm()
42 : .wasm_instance()
43 : ->debug_info()
44 : ->GetInterpretedFrame(frame_->fp(), inlined_frame_index);
45 : DCHECK(wasm_interpreted_frame_);
46 : }
47 : }
48 :
49 903004 : FrameInspector::~FrameInspector() {
50 : // Destructor needs to be defined in the .cc file, because it instantiates
51 : // std::unique_ptr destructors but the types are not known in the header.
52 451502 : }
53 :
54 344589 : int FrameInspector::GetParametersCount() {
55 392216 : if (is_optimized_) return deoptimized_frame_->parameters_count();
56 296962 : if (wasm_interpreted_frame_)
57 0 : return wasm_interpreted_frame_->GetParameterCount();
58 296962 : return frame_->ComputeParametersCount();
59 : }
60 :
61 229547 : Handle<Script> FrameInspector::GetScript() {
62 229547 : return Handle<Script>::cast(frame_summary_.script());
63 : }
64 :
65 1019474 : Handle<JSFunction> FrameInspector::GetFunction() {
66 1019474 : return frame_summary_.AsJavaScript().function();
67 : }
68 :
69 96918 : Handle<Object> FrameInspector::GetParameter(int index) {
70 96918 : if (is_optimized_) return deoptimized_frame_->GetParameter(index);
71 : // TODO(clemensh): Handle wasm_interpreted_frame_.
72 75344 : return handle(frame_->GetParameter(index), isolate_);
73 : }
74 :
75 9519700 : Handle<Object> FrameInspector::GetExpression(int index) {
76 : // TODO(turbofan): Revisit once we support deoptimization.
77 28559100 : if (frame_->is_java_script() &&
78 9537462 : javascript_frame()->LookupCode()->is_turbofanned() &&
79 17762 : javascript_frame()->function()->shared()->asm_function()) {
80 24 : return isolate_->factory()->undefined_value();
81 : }
82 : return is_optimized_ ? deoptimized_frame_->GetExpression(index)
83 19012014 : : handle(frame_->GetExpression(index), isolate_);
84 : }
85 :
86 424115 : int FrameInspector::GetSourcePosition() {
87 424115 : return frame_summary_.SourcePosition();
88 : }
89 :
90 229173 : bool FrameInspector::IsConstructor() { return frame_summary_.is_constructor(); }
91 :
92 749086 : Handle<Object> FrameInspector::GetContext() {
93 : return is_optimized_ ? deoptimized_frame_->GetContext()
94 2182478 : : handle(frame_->context(), isolate_);
95 : }
96 :
97 : // To inspect all the provided arguments the frame might need to be
98 : // replaced with the arguments frame.
99 16015 : void FrameInspector::SetArgumentsFrame(StandardFrame* frame) {
100 : DCHECK(has_adapted_arguments_);
101 : DCHECK(frame->is_arguments_adaptor());
102 16015 : frame_ = frame;
103 32030 : is_optimized_ = frame_->is_optimized();
104 32030 : is_interpreted_ = frame_->is_interpreted();
105 : DCHECK(!is_optimized_);
106 16015 : }
107 :
108 :
109 : // Create a plain JSObject which materializes the local scope for the specified
110 : // frame.
111 130126 : void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
112 : Handle<ScopeInfo> scope_info) {
113 130126 : HandleScope scope(isolate_);
114 : // First fill all parameters.
115 357804 : 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 48776 : Handle<String> name(scope_info->ParameterName(i));
120 58320 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
121 47492 : if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
122 :
123 : Handle<Object> value =
124 39232 : i < GetParametersCount()
125 : ? GetParameter(i)
126 40842 : : Handle<Object>::cast(isolate_->factory()->undefined_value());
127 : DCHECK(!value->IsTheHole(isolate_));
128 :
129 78464 : JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
130 : }
131 :
132 : // Second fill all stack locals.
133 9560192 : for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
134 4715033 : Handle<String> name(scope_info->StackLocalName(i));
135 4715033 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
136 4615413 : Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
137 : // TODO(yangguo): We convert optimized out values to {undefined} when they
138 : // are passed to the debugger. Eventually we should handle them somehow.
139 9230826 : if (value->IsTheHole(isolate_)) {
140 1791 : value = isolate_->factory()->undefined_value();
141 : }
142 9230826 : if (value->IsOptimizedOut(isolate_)) {
143 1296 : value = isolate_->factory()->undefined_value();
144 : }
145 9230826 : JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
146 : }
147 130126 : }
148 :
149 :
150 120194 : void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
151 : Handle<JSFunction> function) {
152 : Handle<SharedFunctionInfo> shared(function->shared());
153 : Handle<ScopeInfo> scope_info(shared->scope_info());
154 120194 : MaterializeStackLocals(target, scope_info);
155 120194 : }
156 :
157 :
158 14390 : void FrameInspector::UpdateStackLocalsFromMaterializedObject(
159 : Handle<JSObject> target, Handle<ScopeInfo> scope_info) {
160 : // Optimized frames and wasm frames are not supported. Simply give up.
161 36934 : if (is_optimized_ || frame_->is_wasm()) return;
162 :
163 8154 : HandleScope scope(isolate_);
164 :
165 : // Parameters.
166 22644 : for (int i = 0; i < scope_info->ParameterCount(); ++i) {
167 : // Shadowed parameters were not materialized.
168 3168 : Handle<String> name(scope_info->ParameterName(i));
169 3168 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
170 2880 : if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
171 :
172 : DCHECK(!javascript_frame()->GetParameter(i)->IsTheHole(isolate_));
173 : Handle<Object> value =
174 4872 : Object::GetPropertyOrElement(target, name).ToHandleChecked();
175 2436 : javascript_frame()->SetParameterValue(i, *value);
176 : }
177 :
178 : // Stack locals.
179 94312 : for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
180 43079 : Handle<String> name(scope_info->StackLocalName(i));
181 43079 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
182 42991 : int index = scope_info->StackLocalIndex(i);
183 85982 : if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
184 : Handle<Object> value =
185 85758 : Object::GetPropertyOrElement(target, name).ToHandleChecked();
186 42879 : frame_->SetExpression(index, *value);
187 : }
188 : }
189 :
190 :
191 0 : bool FrameInspector::ParameterIsShadowedByContextLocal(
192 : Handle<ScopeInfo> info, Handle<String> parameter_name) {
193 : VariableMode mode;
194 : InitializationFlag init_flag;
195 : MaybeAssignedFlag maybe_assigned_flag;
196 : return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
197 50372 : &maybe_assigned_flag) != -1;
198 : }
199 :
200 245126 : SaveContext* DebugFrameHelper::FindSavedContextForFrame(Isolate* isolate,
201 : StandardFrame* frame) {
202 1266656 : SaveContext* save = isolate->save_context();
203 1756908 : while (save != NULL && !save->IsBelowFrame(frame)) {
204 : save = save->prev();
205 : }
206 : DCHECK(save != NULL);
207 245126 : return save;
208 : }
209 :
210 229701 : int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
211 : int index) {
212 : int count = -1;
213 2624120 : for (; !it->done(); it->Advance()) {
214 1312060 : List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
215 1312060 : it->frame()->Summarize(&frames);
216 2396538 : for (int i = frames.length() - 1; i >= 0; i--) {
217 : // Omit functions from native and extension scripts.
218 2628358 : if (!frames[i].is_subject_to_debugging()) continue;
219 1314179 : if (++count == index) return i;
220 : }
221 : }
222 : return -1;
223 : }
224 :
225 :
226 : } // namespace internal
227 : } // namespace v8
|