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/builtins/accessors.h"
8#include "src/deoptimizer/deoptimizer.h"
9#include "src/execution/frames-inl.h"
10
11#if V8_ENABLE_WEBASSEMBLY
12#include "src/debug/debug-wasm-objects.h"
13#endif  // V8_ENABLE_WEBASSEMBLY
14
15namespace v8 {
16namespace internal {
17
18FrameInspector::FrameInspector(CommonFrame* frame, int inlined_frame_index,
19                               Isolate* isolate)
20    : frame_(frame),
21      inlined_frame_index_(inlined_frame_index),
22      isolate_(isolate) {
23  // Extract the relevant information from the frame summary and discard it.
24  FrameSummary summary = FrameSummary::Get(frame, inlined_frame_index);
25  summary.EnsureSourcePositionsAvailable();
26
27  is_constructor_ = summary.is_constructor();
28  source_position_ = summary.SourcePosition();
29  script_ = Handle<Script>::cast(summary.script());
30  receiver_ = summary.receiver();
31
32  if (summary.IsJavaScript()) {
33    function_ = summary.AsJavaScript().function();
34  }
35
36#if V8_ENABLE_WEBASSEMBLY
37  JavaScriptFrame* js_frame =
38      frame->is_java_script() ? javascript_frame() : nullptr;
39  DCHECK(js_frame || frame->is_wasm());
40#else
41  JavaScriptFrame* js_frame = javascript_frame();
42#endif  // V8_ENABLE_WEBASSEMBLY
43  is_optimized_ = frame_->is_optimized();
44
45  // Calculate the deoptimized frame.
46  if (is_optimized_) {
47    DCHECK_NOT_NULL(js_frame);
48    deoptimized_frame_.reset(Deoptimizer::DebuggerInspectableFrame(
49        js_frame, inlined_frame_index, isolate));
50  }
51}
52
53// Destructor needs to be defined in the .cc file, because it instantiates
54// std::unique_ptr destructors but the types are not known in the header.
55FrameInspector::~FrameInspector() = default;
56
57JavaScriptFrame* FrameInspector::javascript_frame() {
58  return JavaScriptFrame::cast(frame_);
59}
60
61Handle<Object> FrameInspector::GetParameter(int index) {
62  if (is_optimized_) return deoptimized_frame_->GetParameter(index);
63  DCHECK(IsJavaScript());
64  return handle(javascript_frame()->GetParameter(index), isolate_);
65}
66
67Handle<Object> FrameInspector::GetExpression(int index) {
68  return is_optimized_ ? deoptimized_frame_->GetExpression(index)
69                       : handle(frame_->GetExpression(index), isolate_);
70}
71
72Handle<Object> FrameInspector::GetContext() {
73  return deoptimized_frame_ ? deoptimized_frame_->GetContext()
74                            : handle(frame_->context(), isolate_);
75}
76
77Handle<String> FrameInspector::GetFunctionName() {
78#if V8_ENABLE_WEBASSEMBLY
79  if (IsWasm()) {
80    auto wasm_frame = WasmFrame::cast(frame_);
81    auto wasm_instance = handle(wasm_frame->wasm_instance(), isolate_);
82    return GetWasmFunctionDebugName(isolate_, wasm_instance,
83                                    wasm_frame->function_index());
84  }
85#endif  // V8_ENABLE_WEBASSEMBLY
86  return JSFunction::GetDebugName(function_);
87}
88
89#if V8_ENABLE_WEBASSEMBLY
90bool FrameInspector::IsWasm() { return frame_->is_wasm(); }
91#endif  // V8_ENABLE_WEBASSEMBLY
92
93bool FrameInspector::IsJavaScript() { return frame_->is_java_script(); }
94
95bool FrameInspector::ParameterIsShadowedByContextLocal(
96    Handle<ScopeInfo> info, Handle<String> parameter_name) {
97  return info->ContextSlotIndex(parameter_name) != -1;
98}
99
100RedirectActiveFunctions::RedirectActiveFunctions(SharedFunctionInfo shared,
101                                                 Mode mode)
102    : shared_(shared), mode_(mode) {
103  DCHECK(shared.HasBytecodeArray());
104  if (mode == Mode::kUseDebugBytecode) {
105    DCHECK(shared.HasDebugInfo());
106  }
107}
108
109void RedirectActiveFunctions::VisitThread(Isolate* isolate,
110                                          ThreadLocalTop* top) {
111  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
112    JavaScriptFrame* frame = it.frame();
113    JSFunction function = frame->function();
114    if (!frame->is_interpreted()) continue;
115    if (function.shared() != shared_) continue;
116    InterpretedFrame* interpreted_frame =
117        reinterpret_cast<InterpretedFrame*>(frame);
118    BytecodeArray bytecode = mode_ == Mode::kUseDebugBytecode
119                                 ? shared_.GetDebugInfo().DebugBytecodeArray()
120                                 : shared_.GetBytecodeArray(isolate);
121    interpreted_frame->PatchBytecodeArray(bytecode);
122  }
123}
124
125}  // namespace internal
126}  // namespace v8
127