v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
debug-stack-trace-iterator.cc
Go to the documentation of this file.
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
6
8#include "src/api/api-inl.h"
11#include "src/debug/debug.h"
15
16#if V8_ENABLE_WEBASSEMBLY
18#endif // V8_ENABLE_WEBASSEMBLY
19
20namespace v8 {
21
22std::unique_ptr<debug::StackTraceIterator> debug::StackTraceIterator::Create(
23 v8::Isolate* isolate, int index) {
24 return std::unique_ptr<debug::StackTraceIterator>(
26 reinterpret_cast<internal::Isolate*>(isolate), index));
27}
28
29namespace internal {
30
31DebugStackTraceIterator::DebugStackTraceIterator(Isolate* isolate, int index)
32 : isolate_(isolate),
33 iterator_(isolate, isolate->debug()->break_frame_id()),
34 is_top_frame_(true),
35 resumable_fn_on_stack_(false) {
36 if (iterator_.done()) return;
38 Advance();
39 for (; !Done() && index > 0; --index) Advance();
40}
41
43
45
47 while (true) {
50 // Omit functions from native and extension scripts.
53 break;
54 }
55 is_top_frame_ = false;
56 }
57 if (inlined_frame_index_ >= 0) {
60 break;
61 }
62 is_top_frame_ = false;
63 frame_inspector_.reset();
65 if (iterator_.done()) break;
67 }
68}
69
71 DCHECK(!Done());
72 DirectHandle<Object> context = frame_inspector_->GetContext();
73 if (IsContext(*context)) {
74 Tagged<Object> value =
75 Cast<Context>(*context)->native_context()->debug_context_id();
76 if (IsSmi(value)) return Smi::ToInt(value);
77 }
78 return 0;
79}
80
82 DCHECK(!Done());
83 if (frame_inspector_->IsJavaScript() &&
84 frame_inspector_->GetFunction()->shared()->kind() ==
86 // FrameInspector is not able to get receiver for arrow function.
87 // So let's try to fetch it using same logic as is used to retrieve 'this'
88 // during DebugEvaluate::Local.
89 DirectHandle<JSFunction> function = frame_inspector_->GetFunction();
90 DirectHandle<Context> context(function->context(), isolate_);
91 // Arrow function defined in top level function without references to
92 // variables may have NativeContext as context.
93 if (!context->IsFunctionContext()) return v8::MaybeLocal<v8::Value>();
94 ScopeIterator scope_iterator(
97 // We lookup this variable in function context only when it is used in arrow
98 // function otherwise V8 can optimize it out.
99 if (!scope_iterator.ClosureScopeHasThisReference()) {
101 }
103 int slot_index = context->scope_info()->ContextSlotIndex(
104 isolate_->factory()->this_string());
105 if (slot_index < 0) return v8::MaybeLocal<v8::Value>();
106 DirectHandle<Object> value(context->get(slot_index), isolate_);
107 if (IsTheHole(*value, isolate_)) return v8::MaybeLocal<v8::Value>();
108 return Utils::ToLocal(value);
109 }
110
111 DirectHandle<Object> value = frame_inspector_->GetReceiver();
112 if (value.is_null() || (IsSmi(*value) || !IsTheHole(*value, isolate_))) {
113 return Utils::ToLocal(value);
114 }
116}
117
119 CHECK(!Done());
120#if V8_ENABLE_WEBASSEMBLY
121 if (frame_inspector_ && frame_inspector_->IsWasm()) {
122 return v8::Local<v8::Value>();
123 }
124#endif // V8_ENABLE_WEBASSEMBLY
126 bool is_optimized = iterator_.frame()->is_optimized_js();
127 if (is_optimized || !is_top_frame_ ||
129 return v8::Local<v8::Value>();
130 }
131 return Utils::ToLocal(isolate_->debug()->return_value_handle());
132}
133
135 DCHECK(!Done());
136 return Utils::ToLocal(frame_inspector_->GetFunctionName());
137}
138
145
147 DCHECK(!Done());
149 if (script.IsEmpty()) return v8::debug::Location();
150 return script->GetSourceLocation(frame_inspector_->GetSourcePosition());
151}
152
154 DCHECK(!Done());
155
157 if (!func.IsEmpty()) {
158 return v8::debug::Location(func->GetScriptLineNumber(),
159 func->GetScriptColumnNumber());
160 }
161#if V8_ENABLE_WEBASSEMBLY
162#if V8_ENABLE_DRUMBRAKE
163 if (iterator_.frame()->is_wasm_interpreter_entry()) {
164 auto frame = WasmInterpreterEntryFrame::cast(iterator_.frame());
165 Handle<WasmInstanceObject> instance(frame->wasm_instance(), isolate_);
166 auto offset =
167 instance->module()->functions[frame->function_index(0)].code.offset();
169 }
170#endif // V8_ENABLE_DRUMBRAKE
171 if (iterator_.frame()->is_wasm()) {
172 auto frame = WasmFrame::cast(iterator_.frame());
173 const wasm::WasmModule* module = frame->trusted_instance_data()->module();
174 auto offset = module->functions[frame->function_index()].code.offset();
175 return v8::debug::Location(0, offset);
176 }
177#endif
178 return v8::debug::Location();
179}
180
182 DCHECK(!Done());
183 if (!frame_inspector_->IsJavaScript()) return v8::Local<v8::Function>();
184 return Utils::ToLocal(frame_inspector_->GetFunction());
185}
186
188 const {
189 DCHECK(!Done());
190 if (!frame_inspector_->IsJavaScript()) return Handle<SharedFunctionInfo>();
191 return handle(frame_inspector_->GetFunction()->shared(), isolate_);
192}
193
194std::unique_ptr<v8::debug::ScopeIterator>
196 DCHECK(!Done());
197#if V8_ENABLE_WEBASSEMBLY
198#if V8_ENABLE_DRUMBRAKE
199 if (iterator_.frame()->is_wasm_interpreter_entry()) {
200 return GetWasmInterpreterScopeIterator(
201 WasmInterpreterEntryFrame::cast(iterator_.frame()));
202 } else {
203#endif // V8_ENABLE_DRUMBRAKE
204 if (iterator_.frame()->is_wasm()) {
205 return GetWasmScopeIterator(WasmFrame::cast(iterator_.frame()));
206 }
207#if V8_ENABLE_DRUMBRAKE
208 }
209#endif // V8_ENABLE_DRUMBRAKE
210#endif // V8_ENABLE_WEBASSEMBLY
211 return std::make_unique<DebugScopeIterator>(isolate_, frame_inspector_.get());
212}
213
215 DCHECK(!Done());
216
217 if (resumable_fn_on_stack_) return false;
218
219 StackFrame* frame = iterator_.frame();
220 // We do not support restarting WASM frames.
221#if V8_ENABLE_WEBASSEMBLY
222 if (frame->is_wasm()) return false;
223#endif // V8_ENABLE_WEBASSEMBLY
224
225 // Check that no embedder API calls are between the top-most frame, and the
226 // current frame. While we *could* determine whether embedder
227 // frames are safe to terminate (via the CallDepthScope chain), we don't know
228 // if embedder frames would cancel the termination effectively breaking
229 // restart frame.
230 if (isolate_->thread_local_top()->last_api_entry_ < frame->fp()) {
231 return false;
232 }
233
234 return true;
235}
236
238 CHECK(!iterator_.done());
239
240 FrameSummaries summaries = iterator_.frame()->Summarize();
241 inlined_frame_index_ = static_cast<int>(summaries.size());
242
243 if (resumable_fn_on_stack_) return;
244
245 StackFrame* frame = iterator_.frame();
246 if (!frame->is_javascript()) return;
247
248 std::vector<Handle<SharedFunctionInfo>> shareds;
249 JavaScriptFrame::cast(frame)->GetFunctions(&shareds);
250 for (auto& shared : shareds) {
251 if (IsResumableFunction(shared->kind())) {
253 return;
254 }
255 }
256}
257
259 v8::Local<v8::String> source, bool throw_on_side_effect) {
260 DCHECK(!Done());
262
263 i::SafeForInterruptsScope safe_for_interrupt_scope(isolate_);
266 Utils::OpenDirectHandle(*source), throw_on_side_effect)
267 .ToHandle(&value)) {
269 }
270 return Utils::ToLocal(value);
271}
272
280
281} // namespace internal
282} // namespace v8
Isolate * isolate_
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
Definition api.h:279
static std::unique_ptr< StackTraceIterator > Create(Isolate *isolate, int index=0)
virtual FrameSummaries Summarize() const
Definition frames.cc:1508
static V8_EXPORT_PRIVATE MaybeDirectHandle< Object > Local(Isolate *isolate, StackFrameId frame_id, int inlined_jsframe_index, DirectHandle< String > source, bool throw_on_side_effect)
std::unique_ptr< FrameInspector > frame_inspector_
v8::Local< v8::Function > GetFunction() const override
v8::Local< v8::debug::Script > GetScript() const override
Handle< SharedFunctionInfo > GetSharedFunctionInfo() const
v8::MaybeLocal< v8::Value > GetReceiver() const override
v8::Local< v8::Value > GetReturnValue() const override
std::unique_ptr< v8::debug::ScopeIterator > GetScopeIterator() const override
debug::Location GetFunctionLocation() const override
v8::MaybeLocal< v8::Value > Evaluate(v8::Local< v8::String > source, bool throw_on_side_effect) override
v8::Local< v8::String > GetFunctionDebugName() const override
debug::Location GetSourceLocation() const override
Handle< Object > return_value_handle()
Definition debug.cc:3173
void PrepareRestartFrame(JavaScriptFrame *frame, int inlined_frame_index)
Definition debug.cc:3369
bool IsBreakAtReturn(JavaScriptFrame *frame)
Definition debug.cc:2377
JavaScriptFrame * javascript_frame() const
Definition frames-inl.h:423
bool is_subject_to_debugging() const
static FrameSummary Get(const CommonFrame *frame, int index)
Definition frames.cc:2981
v8::internal::Factory * factory()
Definition isolate.h:1527
Debug * debug() const
Definition isolate.h:1474
ThreadLocalTop * thread_local_top()
Definition isolate.h:1331
virtual void GetFunctions(std::vector< Tagged< SharedFunctionInfo > > *functions) const
Definition frames.cc:2436
static JavaScriptFrame * cast(StackFrame *frame)
Definition frames.h:805
bool ClosureScopeHasThisReference() const
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
bool is_javascript() const
Definition frames.h:290
StackFrameId id() const
Definition frames.h:334
Address fp() const
Definition frames.h:297
bool is_optimized_js() const
Definition frames.h:233
int32_t offset
TNode< Context > context
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
std::unique_ptr< debug::ScopeIterator > GetWasmScopeIterator(WasmFrame *frame)
bool IsResumableFunction(FunctionKind kind)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
return value
Definition map-inl.h:893
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Local< T > Handle
v8::Local< T > ToApiHandle(v8::internal::DirectHandle< v8::internal::Object > obj)
Definition api.h:297
#define CHECK(condition)
Definition logging.h:124
#define CHECK_NOT_NULL(val)
#define DCHECK(condition)
Definition logging.h:482