| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/debug/debug-frames.h" | 5 #include "src/debug/debug-frames.h" |
| 6 | 6 |
| 7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
| 8 #include "src/wasm/wasm-module.h" |
| 8 | 9 |
| 9 namespace v8 { | 10 namespace v8 { |
| 10 namespace internal { | 11 namespace internal { |
| 11 | 12 |
| 12 FrameInspector::FrameInspector(StandardFrame* frame, int inlined_jsframe_index, | 13 FrameInspector::FrameInspector(StandardFrame* frame, int inlined_frame_index, |
| 13 Isolate* isolate) | 14 Isolate* isolate) |
| 14 : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { | 15 : frame_(frame), isolate_(isolate) { |
| 15 JavaScriptFrame* js_frame = | 16 JavaScriptFrame* js_frame = |
| 16 frame->is_java_script() ? javascript_frame() : nullptr; | 17 frame->is_java_script() ? javascript_frame() : nullptr; |
| 17 DCHECK(js_frame || frame->is_wasm()); | 18 DCHECK(js_frame || frame->is_wasm()); |
| 18 has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments(); | 19 has_adapted_arguments_ = js_frame && js_frame->has_adapted_arguments(); |
| 19 is_bottommost_ = inlined_jsframe_index == 0; | 20 is_bottommost_ = inlined_frame_index == 0; |
| 20 is_optimized_ = frame_->is_optimized(); | |
| 21 is_interpreted_ = frame_->is_interpreted(); | 21 is_interpreted_ = frame_->is_interpreted(); |
| 22 // Calculate the deoptimized frame. | 22 // Calculate the deoptimized frame. |
| 23 if (frame->is_optimized()) { | 23 if (frame->is_optimized()) { |
| 24 DCHECK(js_frame != nullptr); | 24 DCHECK(js_frame != nullptr); |
| 25 // TODO(turbofan): Revisit once we support deoptimization. | 25 // TODO(turbofan): Revisit once we support deoptimization. |
| 26 if (js_frame->LookupCode()->is_turbofanned() && | 26 if (js_frame->LookupCode()->is_turbofanned() && |
| 27 js_frame->function()->shared()->asm_function() && | 27 js_frame->function()->shared()->asm_function() && |
| 28 !FLAG_turbo_asm_deoptimization) { | 28 !FLAG_turbo_asm_deoptimization) { |
| 29 is_optimized_ = false; | |
| 30 return; | 29 return; |
| 31 } | 30 } |
| 32 | 31 |
| 33 deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( | 32 deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame( |
| 34 js_frame, inlined_jsframe_index, isolate); | 33 js_frame, inlined_frame_index, isolate)); |
| 35 } | 34 } else if (frame->is_wasm_interpreted()) { |
| 36 } | 35 // Get wasm interpreted frame information. |
| 37 | 36 Handle<JSObject> wasm(JSObject::cast(WasmFrame::cast(frame)->wasm_obj()), |
| 38 | 37 isolate); |
| 39 FrameInspector::~FrameInspector() { | 38 wasm::InterpreterFrameIterator frame_it = |
| 40 // Get rid of the calculated deoptimized frame if any. | 39 wasm::GetDebugInfo(wasm)->GetInterpreterFrameIterator(); |
| 41 if (deoptimized_frame_ != NULL) { | 40 for (int count = inlined_frame_index; count > 0; --count) frame_it.Next(); |
| 42 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_); | 41 DCHECK(!frame_it.Done()); |
| 42 wasm_interpreted_frame_.reset( |
| 43 new wasm::InterpreterFrameInfo(frame_it.GetFrameInfo())); |
| 43 } | 44 } |
| 44 } | 45 } |
| 45 | 46 |
| 46 | 47 |
| 47 int FrameInspector::GetParametersCount() { | 48 int FrameInspector::GetParametersCount() { |
| 48 return is_optimized_ ? deoptimized_frame_->parameters_count() | 49 return deoptimized_frame_ ? deoptimized_frame_->parameters_count() |
| 49 : frame_->ComputeParametersCount(); | 50 : frame_->ComputeParametersCount(); |
| 50 } | 51 } |
| 51 | 52 |
| 52 Handle<Script> FrameInspector::GetScript() { | 53 Handle<Script> FrameInspector::GetScript() { |
| 53 Object* script = is_optimized_ | 54 Object* script = deoptimized_frame_ |
| 54 ? deoptimized_frame_->GetFunction()->shared()->script() | 55 ? deoptimized_frame_->GetFunction()->shared()->script() |
| 55 : frame_->script(); | 56 : wasm_interpreted_frame_ |
| 57 ? wasm_interpreted_frame_->GetScript() |
| 58 : frame_->script(); |
| 56 return handle(Script::cast(script), isolate_); | 59 return handle(Script::cast(script), isolate_); |
| 57 } | 60 } |
| 58 | 61 |
| 62 bool FrameInspector::HasFunction() { |
| 63 return frame_->is_java_script() || frame_->is_arguments_adaptor(); |
| 64 } |
| 65 |
| 59 Handle<JSFunction> FrameInspector::GetFunction() { | 66 Handle<JSFunction> FrameInspector::GetFunction() { |
| 60 DCHECK(!frame_->is_wasm()); | 67 DCHECK(HasFunction()); |
| 61 return is_optimized_ ? deoptimized_frame_->GetFunction() | 68 return deoptimized_frame_ ? deoptimized_frame_->GetFunction() |
| 62 : handle(javascript_frame()->function(), isolate_); | 69 : handle(javascript_frame()->function(), isolate_); |
| 70 } |
| 71 |
| 72 Handle<String> FrameInspector::GetFunctionName() { |
| 73 if (!frame_->is_wasm()) return JSFunction::GetDebugName(GetFunction()); |
| 74 Handle<JSObject> wasm_obj(JSObject::cast(WasmFrame::cast(frame_)->wasm_obj()), |
| 75 isolate_); |
| 76 int func_index = wasm_interpreted_frame_ |
| 77 ? wasm_interpreted_frame_->func_index() |
| 78 : WasmCompiledFrame::cast(frame_)->function_index(); |
| 79 return wasm::GetWasmFunctionName(isolate_, wasm_obj, func_index); |
| 63 } | 80 } |
| 64 | 81 |
| 65 Handle<Object> FrameInspector::GetParameter(int index) { | 82 Handle<Object> FrameInspector::GetParameter(int index) { |
| 66 return is_optimized_ ? deoptimized_frame_->GetParameter(index) | 83 return deoptimized_frame_ ? deoptimized_frame_->GetParameter(index) |
| 67 : handle(frame_->GetParameter(index), isolate_); | 84 : handle(frame_->GetParameter(index), isolate_); |
| 68 } | 85 } |
| 69 | 86 |
| 70 Handle<Object> FrameInspector::GetExpression(int index) { | 87 Handle<Object> FrameInspector::GetExpression(int index) { |
| 71 // TODO(turbofan): Revisit once we support deoptimization. | 88 // TODO(turbofan): Revisit once we support deoptimization. |
| 72 if (frame_->is_java_script() && | 89 if (frame_->is_java_script() && |
| 73 javascript_frame()->LookupCode()->is_turbofanned() && | 90 javascript_frame()->LookupCode()->is_turbofanned() && |
| 74 javascript_frame()->function()->shared()->asm_function() && | 91 javascript_frame()->function()->shared()->asm_function() && |
| 75 !FLAG_turbo_asm_deoptimization) { | 92 !FLAG_turbo_asm_deoptimization) { |
| 76 return isolate_->factory()->undefined_value(); | 93 return isolate_->factory()->undefined_value(); |
| 77 } | 94 } |
| 78 return is_optimized_ ? deoptimized_frame_->GetExpression(index) | 95 return deoptimized_frame_ ? deoptimized_frame_->GetExpression(index) |
| 79 : handle(frame_->GetExpression(index), isolate_); | 96 : handle(frame_->GetExpression(index), isolate_); |
| 80 } | 97 } |
| 81 | 98 |
| 82 | 99 |
| 83 int FrameInspector::GetSourcePosition() { | 100 int FrameInspector::GetSourcePosition() { |
| 84 if (is_optimized_) { | 101 if (deoptimized_frame_) return deoptimized_frame_->GetSourcePosition(); |
| 85 return deoptimized_frame_->GetSourcePosition(); | 102 if (wasm_interpreted_frame_) return wasm_interpreted_frame_->pc_offset(); |
| 86 } else if (is_interpreted_) { | 103 if (is_interpreted_) { |
| 87 InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_); | 104 InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_); |
| 88 BytecodeArray* bytecode_array = frame->GetBytecodeArray(); | 105 BytecodeArray* bytecode_array = frame->GetBytecodeArray(); |
| 89 return bytecode_array->SourcePosition(frame->GetBytecodeOffset()); | 106 return bytecode_array->SourcePosition(frame->GetBytecodeOffset()); |
| 90 } else { | |
| 91 Code* code = frame_->LookupCode(); | |
| 92 int offset = static_cast<int>(frame_->pc() - code->instruction_start()); | |
| 93 return code->SourcePosition(offset); | |
| 94 } | 107 } |
| 108 Code* code = frame_->LookupCode(); |
| 109 int offset = static_cast<int>(frame_->pc() - code->instruction_start()); |
| 110 return code->SourcePosition(offset); |
| 95 } | 111 } |
| 96 | 112 |
| 97 | 113 |
| 98 bool FrameInspector::IsConstructor() { | 114 bool FrameInspector::IsConstructor() { |
| 99 return is_optimized_ && !is_bottommost_ | 115 return deoptimized_frame_ && !is_bottommost_ |
| 100 ? deoptimized_frame_->HasConstructStub() | 116 ? deoptimized_frame_->HasConstructStub() |
| 101 : frame_->IsConstructor(); | 117 : frame_->IsConstructor(); |
| 102 } | 118 } |
| 103 | 119 |
| 104 Handle<Object> FrameInspector::GetContext() { | 120 Handle<Object> FrameInspector::GetContext() { |
| 105 return is_optimized_ ? deoptimized_frame_->GetContext() | 121 return deoptimized_frame_ ? deoptimized_frame_->GetContext() |
| 106 : handle(frame_->context(), isolate_); | 122 : handle(frame_->context(), isolate_); |
| 107 } | 123 } |
| 108 | 124 |
| 109 | 125 |
| 110 // To inspect all the provided arguments the frame might need to be | 126 // To inspect all the provided arguments the frame might need to be |
| 111 // replaced with the arguments frame. | 127 // replaced with the arguments frame. |
| 112 void FrameInspector::SetArgumentsFrame(StandardFrame* frame) { | 128 void FrameInspector::SetArgumentsFrame(StandardFrame* frame) { |
| 113 DCHECK(has_adapted_arguments_); | 129 DCHECK(has_adapted_arguments_); |
| 114 DCHECK(frame->is_arguments_adaptor()); | 130 DCHECK(frame->is_arguments_adaptor()); |
| 115 frame_ = frame; | 131 frame_ = frame; |
| 116 is_optimized_ = frame_->is_optimized(); | 132 DCHECK(!frame_->is_optimized()); |
| 133 deoptimized_frame_ = nullptr; |
| 117 is_interpreted_ = frame_->is_interpreted(); | 134 is_interpreted_ = frame_->is_interpreted(); |
| 118 DCHECK(!is_optimized_); | |
| 119 } | 135 } |
| 120 | 136 |
| 121 | 137 |
| 122 // Create a plain JSObject which materializes the local scope for the specified | 138 // Create a plain JSObject which materializes the local scope for the specified |
| 123 // frame. | 139 // frame. |
| 124 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, | 140 void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, |
| 125 Handle<ScopeInfo> scope_info) { | 141 Handle<ScopeInfo> scope_info) { |
| 126 HandleScope scope(isolate_); | 142 HandleScope scope(isolate_); |
| 127 // First fill all parameters. | 143 // First fill all parameters. |
| 128 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 144 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 Handle<JSFunction> function) { | 180 Handle<JSFunction> function) { |
| 165 Handle<SharedFunctionInfo> shared(function->shared()); | 181 Handle<SharedFunctionInfo> shared(function->shared()); |
| 166 Handle<ScopeInfo> scope_info(shared->scope_info()); | 182 Handle<ScopeInfo> scope_info(shared->scope_info()); |
| 167 MaterializeStackLocals(target, scope_info); | 183 MaterializeStackLocals(target, scope_info); |
| 168 } | 184 } |
| 169 | 185 |
| 170 | 186 |
| 171 void FrameInspector::UpdateStackLocalsFromMaterializedObject( | 187 void FrameInspector::UpdateStackLocalsFromMaterializedObject( |
| 172 Handle<JSObject> target, Handle<ScopeInfo> scope_info) { | 188 Handle<JSObject> target, Handle<ScopeInfo> scope_info) { |
| 173 // Optimized frames and wasm frames are not supported. Simply give up. | 189 // Optimized frames and wasm frames are not supported. Simply give up. |
| 174 if (is_optimized_ || frame_->is_wasm()) return; | 190 if (deoptimized_frame_ || frame_->is_wasm()) return; |
| 175 | 191 |
| 176 HandleScope scope(isolate_); | 192 HandleScope scope(isolate_); |
| 177 | 193 |
| 178 // Parameters. | 194 // Parameters. |
| 179 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 195 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
| 180 // Shadowed parameters were not materialized. | 196 // Shadowed parameters were not materialized. |
| 181 Handle<String> name(scope_info->ParameterName(i)); | 197 Handle<String> name(scope_info->ParameterName(i)); |
| 182 if (ScopeInfo::VariableIsSynthetic(*name)) continue; | 198 if (ScopeInfo::VariableIsSynthetic(*name)) continue; |
| 183 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; | 199 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; |
| 184 | 200 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 save = save->prev(); | 233 save = save->prev(); |
| 218 } | 234 } |
| 219 DCHECK(save != NULL); | 235 DCHECK(save != NULL); |
| 220 return save; | 236 return save; |
| 221 } | 237 } |
| 222 | 238 |
| 223 int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it, | 239 int DebugFrameHelper::FindIndexedNonNativeFrame(StackTraceFrameIterator* it, |
| 224 int index) { | 240 int index) { |
| 225 int count = -1; | 241 int count = -1; |
| 226 for (; !it->done(); it->Advance()) { | 242 for (; !it->done(); it->Advance()) { |
| 227 if (it->is_wasm()) { | |
| 228 if (++count == index) return 0; | |
| 229 continue; | |
| 230 } | |
| 231 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 243 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| 232 it->javascript_frame()->Summarize(&frames); | 244 it->frame()->Summarize(&frames); |
| 233 for (int i = frames.length() - 1; i >= 0; i--) { | 245 for (int i = frames.length() - 1; i >= 0; i--) { |
| 234 // Omit functions from native and extension scripts. | 246 // Omit functions from native and extension scripts. |
| 235 if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue; | 247 if (!frames[i].is_subject_to_debugging()) continue; |
| 236 if (++count == index) return i; | 248 if (++count == index) return i; |
| 237 } | 249 } |
| 238 } | 250 } |
| 239 return -1; | 251 return -1; |
| 240 } | 252 } |
| 241 | 253 |
| 242 | 254 |
| 243 } // namespace internal | 255 } // namespace internal |
| 244 } // namespace v8 | 256 } // namespace v8 |
| OLD | NEW |