Line data Source code
1 : // Copyright 2017 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-stack-trace-iterator.h"
6 :
7 : #include "src/api.h"
8 : #include "src/debug/debug-evaluate.h"
9 : #include "src/debug/debug-scope-iterator.h"
10 : #include "src/debug/debug.h"
11 : #include "src/debug/liveedit.h"
12 : #include "src/frames-inl.h"
13 : #include "src/isolate.h"
14 :
15 : namespace v8 {
16 :
17 59807 : std::unique_ptr<debug::StackTraceIterator> debug::StackTraceIterator::Create(
18 : v8::Isolate* isolate, int index) {
19 : return std::unique_ptr<debug::StackTraceIterator>(
20 : new internal::DebugStackTraceIterator(
21 119614 : reinterpret_cast<internal::Isolate*>(isolate), index));
22 : }
23 :
24 : namespace internal {
25 :
26 119614 : DebugStackTraceIterator::DebugStackTraceIterator(Isolate* isolate, int index)
27 : : isolate_(isolate),
28 : iterator_(isolate, isolate->debug()->break_frame_id()),
29 119614 : is_top_frame_(true) {
30 59807 : if (iterator_.done()) return;
31 : std::vector<FrameSummary> frames;
32 59807 : frames.reserve(FLAG_max_inlining_levels + 1);
33 59807 : iterator_.frame()->Summarize(&frames);
34 119614 : inlined_frame_index_ = static_cast<int>(frames.size());
35 59807 : Advance();
36 128337 : for (; !Done() && index > 0; --index) Advance();
37 : }
38 :
39 179421 : DebugStackTraceIterator::~DebugStackTraceIterator() {}
40 :
41 369770 : bool DebugStackTraceIterator::Done() const { return iterator_.done(); }
42 :
43 193608 : void DebugStackTraceIterator::Advance() {
44 : while (true) {
45 271108 : --inlined_frame_index_;
46 271136 : for (; inlined_frame_index_ >= 0; --inlined_frame_index_) {
47 : // Omit functions from native and extension scripts.
48 287580 : if (FrameSummary::Get(iterator_.frame(), inlined_frame_index_)
49 287580 : .is_subject_to_debugging()) {
50 : break;
51 : }
52 28 : is_top_frame_ = false;
53 : }
54 271108 : if (inlined_frame_index_ >= 0) {
55 : frame_inspector_.reset(new FrameInspector(
56 143762 : iterator_.frame(), inlined_frame_index_, isolate_));
57 193608 : break;
58 : }
59 127346 : is_top_frame_ = false;
60 : frame_inspector_.reset();
61 127346 : iterator_.Advance();
62 127346 : if (iterator_.done()) break;
63 : std::vector<FrameSummary> frames;
64 77500 : frames.reserve(FLAG_max_inlining_levels + 1);
65 77500 : iterator_.frame()->Summarize(&frames);
66 155000 : inlined_frame_index_ = static_cast<int>(frames.size());
67 77500 : }
68 193608 : }
69 :
70 125171 : int DebugStackTraceIterator::GetContextId() const {
71 : DCHECK(!Done());
72 125171 : Handle<Object> context = frame_inspector_->GetContext();
73 125171 : if (context->IsContext()) {
74 : Object* value =
75 : Context::cast(*context)->native_context()->debug_context_id();
76 250114 : if (value->IsSmi()) return Smi::ToInt(value);
77 : }
78 : return 0;
79 : }
80 :
81 124988 : v8::Local<v8::Value> DebugStackTraceIterator::GetReceiver() const {
82 : DCHECK(!Done());
83 : Handle<Object> value = frame_inspector_->GetReceiver();
84 374955 : if (value.is_null() || (value->IsSmi() || !value->IsTheHole(isolate_))) {
85 : return Utils::ToLocal(value);
86 : }
87 570 : return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
88 : }
89 :
90 125078 : v8::Local<v8::Value> DebugStackTraceIterator::GetReturnValue() const {
91 : DCHECK(!Done());
92 125078 : if (frame_inspector_->IsWasm()) return v8::Local<v8::Value>();
93 124682 : bool is_optimized = iterator_.frame()->is_optimized();
94 173146 : if (is_optimized || !is_top_frame_ ||
95 53963 : !isolate_->debug()->IsBreakAtReturn(iterator_.javascript_frame())) {
96 119183 : return v8::Local<v8::Value>();
97 : }
98 10998 : return Utils::ToLocal(isolate_->debug()->return_value_handle());
99 : }
100 :
101 125078 : v8::Local<v8::String> DebugStackTraceIterator::GetFunctionName() const {
102 : DCHECK(!Done());
103 125078 : return Utils::ToLocal(frame_inspector_->GetFunctionName());
104 : }
105 :
106 250249 : v8::Local<v8::debug::Script> DebugStackTraceIterator::GetScript() const {
107 : DCHECK(!Done());
108 : Handle<Object> value = frame_inspector_->GetScript();
109 250249 : if (!value->IsScript()) return v8::Local<v8::debug::Script>();
110 : return ToApiHandle<debug::Script>(Handle<Script>::cast(value));
111 : }
112 :
113 125171 : debug::Location DebugStackTraceIterator::GetSourceLocation() const {
114 : DCHECK(!Done());
115 125171 : v8::Local<v8::debug::Script> script = GetScript();
116 125171 : if (script.IsEmpty()) return v8::debug::Location();
117 125171 : return script->GetSourceLocation(frame_inspector_->GetSourcePosition());
118 : }
119 :
120 125078 : v8::Local<v8::Function> DebugStackTraceIterator::GetFunction() const {
121 : DCHECK(!Done());
122 125078 : if (!frame_inspector_->IsJavaScript()) return v8::Local<v8::Function>();
123 : return Utils::ToLocal(frame_inspector_->GetFunction());
124 : }
125 :
126 : std::unique_ptr<v8::debug::ScopeIterator>
127 125387 : DebugStackTraceIterator::GetScopeIterator() const {
128 : DCHECK(!Done());
129 : StandardFrame* frame = iterator_.frame();
130 250774 : if (frame->is_wasm_interpreter_entry()) {
131 : return std::unique_ptr<v8::debug::ScopeIterator>(new DebugWasmScopeIterator(
132 285 : isolate_, iterator_.frame(), inlined_frame_index_));
133 : }
134 : return std::unique_ptr<v8::debug::ScopeIterator>(
135 125102 : new DebugScopeIterator(isolate_, frame_inspector_.get()));
136 : }
137 :
138 99 : bool DebugStackTraceIterator::Restart() {
139 : DCHECK(!Done());
140 99 : if (iterator_.is_wasm()) return false;
141 99 : return !LiveEdit::RestartFrame(iterator_.javascript_frame());
142 : }
143 :
144 9553 : v8::MaybeLocal<v8::Value> DebugStackTraceIterator::Evaluate(
145 : v8::Local<v8::String> source, bool throw_on_side_effect) {
146 : DCHECK(!Done());
147 : Handle<Object> value;
148 9553 : if (!DebugEvaluate::Local(isolate_, iterator_.frame()->id(),
149 : inlined_frame_index_, Utils::OpenHandle(*source),
150 38212 : throw_on_side_effect)
151 19106 : .ToHandle(&value)) {
152 912 : isolate_->OptionalRescheduleException(false);
153 912 : return v8::MaybeLocal<v8::Value>();
154 : }
155 8641 : return Utils::ToLocal(value);
156 : }
157 : } // namespace internal
158 : } // namespace v8
|