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 451250 : FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index,
15 : Isolate* isolate)
16 : : frame_(frame),
17 : frame_summary_(FrameSummary::Get(frame, inlined_frame_index)),
18 451250 : isolate_(isolate) {
19 : JavaScriptFrame* js_frame =
20 451250 : frame->is_java_script() ? javascript_frame() : nullptr;
21 : DCHECK(js_frame || frame->is_wasm());
22 902028 : has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments();
23 451250 : is_bottommost_ = inlined_frame_index == 0;
24 902776 : is_optimized_ = frame_->is_optimized();
25 902500 : is_interpreted_ = frame_->is_interpreted();
26 :
27 : // Calculate the deoptimized frame.
28 451250 : if (is_optimized_) {
29 : DCHECK(js_frame != nullptr);
30 : // TODO(turbofan): Revisit once we support deoptimization.
31 80003 : if (js_frame->LookupCode()->is_turbofanned() &&
32 31002 : js_frame->function()->shared()->asm_function()) {
33 56 : is_optimized_ = false;
34 451306 : return;
35 : }
36 :
37 : deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
38 48945 : js_frame, inlined_frame_index, isolate));
39 804498 : } 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 902500 : 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 451250 : }
53 :
54 344367 : int FrameInspector::GetParametersCount() {
55 391985 : if (is_optimized_) return deoptimized_frame_->parameters_count();
56 296749 : if (wasm_interpreted_frame_)
57 0 : return wasm_interpreted_frame_->GetParameterCount();
58 296749 : return frame_->ComputeParametersCount();
59 : }
60 :
61 229421 : Handle<Script> FrameInspector::GetScript() {
62 229421 : return Handle<Script>::cast(frame_summary_.script());
63 : }
64 :
65 1018880 : Handle<JSFunction> FrameInspector::GetFunction() {
66 1018880 : return frame_summary_.AsJavaScript().function();
67 : }
68 :
69 96846 : Handle<Object> FrameInspector::GetParameter(int index) {
70 96846 : if (is_optimized_) return deoptimized_frame_->GetParameter(index);
71 : // TODO(clemensh): Handle wasm_interpreted_frame_.
72 75278 : return handle(frame_->GetParameter(index), isolate_);
73 : }
74 :
75 9519520 : Handle<Object> FrameInspector::GetExpression(int index) {
76 : // TODO(turbofan): Revisit once we support deoptimization.
77 28558560 : if (frame_->is_java_script() &&
78 9537278 : javascript_frame()->LookupCode()->is_turbofanned() &&
79 17758 : javascript_frame()->function()->shared()->asm_function()) {
80 24 : return isolate_->factory()->undefined_value();
81 : }
82 : return is_optimized_ ? deoptimized_frame_->GetExpression(index)
83 19011658 : : handle(frame_->GetExpression(index), isolate_);
84 : }
85 :
86 423887 : int FrameInspector::GetSourcePosition() {
87 423887 : return frame_summary_.SourcePosition();
88 : }
89 :
90 229047 : bool FrameInspector::IsConstructor() { return frame_summary_.is_constructor(); }
91 :
92 748630 : Handle<Object> FrameInspector::GetContext() {
93 : return is_optimized_ ? deoptimized_frame_->GetContext()
94 2181219 : : 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 15991 : void FrameInspector::SetArgumentsFrame(StandardFrame* frame) {
100 : DCHECK(has_adapted_arguments_);
101 : DCHECK(frame->is_arguments_adaptor());
102 15991 : frame_ = frame;
103 31982 : is_optimized_ = frame_->is_optimized();
104 31982 : is_interpreted_ = frame_->is_interpreted();
105 : DCHECK(!is_optimized_);
106 15991 : }
107 :
108 :
109 : // Create a plain JSObject which materializes the local scope for the specified
110 : // frame.
111 130048 : void FrameInspector::MaterializeStackLocals(Handle<JSObject> target,
112 : Handle<ScopeInfo> scope_info) {
113 130048 : HandleScope scope(isolate_);
114 : // First fill all parameters.
115 357576 : 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 48740 : Handle<String> name(scope_info->ParameterName(i));
120 58260 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
121 47480 : if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
122 :
123 : Handle<Object> value =
124 39220 : i < GetParametersCount()
125 : ? GetParameter(i)
126 40830 : : Handle<Object>::cast(isolate_->factory()->undefined_value());
127 : DCHECK(!value->IsTheHole(isolate_));
128 :
129 78440 : JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
130 : }
131 :
132 : // Second fill all stack locals.
133 9559886 : for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
134 4714919 : Handle<String> name(scope_info->StackLocalName(i));
135 4714919 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
136 4615323 : 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 9230646 : if (value->IsTheHole(isolate_)) {
140 1791 : value = isolate_->factory()->undefined_value();
141 : }
142 9230646 : if (value->IsOptimizedOut(isolate_)) {
143 1296 : value = isolate_->factory()->undefined_value();
144 : }
145 9230646 : JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
146 : }
147 130048 : }
148 :
149 :
150 120116 : 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 120116 : MaterializeStackLocals(target, scope_info);
155 120116 : }
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 36938 : if (is_optimized_ || frame_->is_wasm()) return;
162 :
163 8158 : HandleScope scope(isolate_);
164 :
165 : // Parameters.
166 22652 : 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 94316 : 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 50360 : &maybe_assigned_flag) != -1;
198 : }
199 :
200 245000 : SaveContext* DebugFrameHelper::FindSavedContextForFrame(Isolate* isolate,
201 : StandardFrame* frame) {
202 1266026 : SaveContext* save = isolate->save_context();
203 1756026 : while (save != NULL && !save->IsBelowFrame(frame)) {
204 : save = save->prev();
205 : }
206 : DCHECK(save != NULL);
207 245000 : return save;
208 : }
209 :
210 229575 : int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it,
211 : int index) {
212 : int count = -1;
213 2623616 : for (; !it->done(); it->Advance()) {
214 1311808 : List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
215 1311808 : it->frame()->Summarize(&frames);
216 2396160 : for (int i = frames.length() - 1; i >= 0; i--) {
217 : // Omit functions from native and extension scripts.
218 2627854 : if (!frames[i].is_subject_to_debugging()) continue;
219 1313927 : if (++count == index) return i;
220 : }
221 : }
222 : return -1;
223 : }
224 :
225 :
226 : } // namespace internal
227 : } // namespace v8
|