Line data Source code
1 : // Copyright 2012 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.h"
6 :
7 : #include <memory>
8 :
9 : #include "src/api.h"
10 : #include "src/arguments.h"
11 : #include "src/assembler-inl.h"
12 : #include "src/bootstrapper.h"
13 : #include "src/code-stubs.h"
14 : #include "src/codegen.h"
15 : #include "src/compilation-cache.h"
16 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
17 : #include "src/compiler.h"
18 : #include "src/debug/debug-evaluate.h"
19 : #include "src/debug/liveedit.h"
20 : #include "src/deoptimizer.h"
21 : #include "src/execution.h"
22 : #include "src/frames-inl.h"
23 : #include "src/full-codegen/full-codegen.h"
24 : #include "src/global-handles.h"
25 : #include "src/globals.h"
26 : #include "src/interpreter/interpreter.h"
27 : #include "src/isolate-inl.h"
28 : #include "src/list.h"
29 : #include "src/log.h"
30 : #include "src/messages.h"
31 : #include "src/snapshot/natives.h"
32 : #include "src/wasm/wasm-module.h"
33 : #include "src/wasm/wasm-objects.h"
34 :
35 : #include "include/v8-debug.h"
36 :
37 : namespace v8 {
38 : namespace internal {
39 :
40 60782 : Debug::Debug(Isolate* isolate)
41 : : debug_context_(Handle<Context>()),
42 : is_active_(false),
43 : hook_on_function_call_(false),
44 : is_suppressed_(false),
45 : live_edit_enabled_(false),
46 : break_disabled_(false),
47 : break_points_active_(true),
48 : break_on_exception_(false),
49 : break_on_uncaught_exception_(false),
50 : side_effect_check_failed_(false),
51 : debug_info_list_(NULL),
52 : feature_tracker_(isolate),
53 121564 : isolate_(isolate) {
54 60782 : ThreadInit();
55 60782 : }
56 :
57 380444 : BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
58 : JavaScriptFrame* frame) {
59 380444 : auto summary = FrameSummary::GetTop(frame).AsJavaScript();
60 : int offset = summary.code_offset();
61 : Handle<AbstractCode> abstract_code = summary.abstract_code();
62 380444 : if (abstract_code->IsCode()) offset = offset - 1;
63 380444 : auto it = BreakIterator::GetIterator(debug_info, abstract_code);
64 380444 : it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
65 760888 : return it->GetBreakLocation();
66 : }
67 :
68 3542 : void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
69 : JavaScriptFrame* frame,
70 : List<BreakLocation>* result_out) {
71 3542 : auto summary = FrameSummary::GetTop(frame).AsJavaScript();
72 : int offset = summary.code_offset();
73 : Handle<AbstractCode> abstract_code = summary.abstract_code();
74 3542 : if (abstract_code->IsCode()) offset = offset - 1;
75 : int statement_position;
76 : {
77 3542 : auto it = BreakIterator::GetIterator(debug_info, abstract_code);
78 3542 : it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
79 3542 : statement_position = it->statement_position();
80 : }
81 34136 : for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
82 57646 : !it->Done(); it->Next()) {
83 27052 : if (it->statement_position() == statement_position) {
84 3630 : result_out->Add(it->GetBreakLocation());
85 : }
86 : }
87 3542 : }
88 :
89 383986 : int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
90 : Handle<AbstractCode> abstract_code,
91 : int offset) {
92 : // Run through all break points to locate the one closest to the address.
93 : int closest_break = 0;
94 : int distance = kMaxInt;
95 : DCHECK(0 <= offset && offset < abstract_code->Size());
96 19076814 : for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
97 37001670 : !it->Done(); it->Next()) {
98 : // Check if this break point is closer that what was previously found.
99 32894299 : if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
100 14297908 : closest_break = it->break_index();
101 14297908 : distance = offset - it->code_offset();
102 : // Check whether we can't get any closer.
103 14297908 : if (distance == 0) break;
104 : }
105 : }
106 383986 : return closest_break;
107 : }
108 :
109 94236 : bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
110 : // First check whether there is a break point with the same source position.
111 188472 : if (!debug_info->HasBreakPoint(position_)) return false;
112 : // Then check whether a break point at that source position would have
113 : // the same code offset. Otherwise it's just a break location that we can
114 : // step to, but not actually a location where we can put a break point.
115 5201 : if (abstract_code_->IsCode()) {
116 : DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode());
117 1639 : CodeBreakIterator it(debug_info);
118 1639 : it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
119 1639 : return it.code_offset() == code_offset_;
120 : } else {
121 : DCHECK(abstract_code_->IsBytecodeArray());
122 3562 : BytecodeArrayBreakIterator it(debug_info);
123 3562 : it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
124 3562 : return it.code_offset() == code_offset_;
125 : }
126 : }
127 :
128 3438 : debug::BreakLocationType BreakLocation::type() const {
129 3438 : switch (type_) {
130 : case DEBUGGER_STATEMENT:
131 : return debug::kDebuggerStatementBreakLocation;
132 : case DEBUG_BREAK_SLOT_AT_CALL:
133 : return debug::kCallBreakLocation;
134 : case DEBUG_BREAK_SLOT_AT_RETURN:
135 : return debug::kReturnBreakLocation;
136 : default:
137 : return debug::kCommonBreakLocation;
138 : }
139 : return debug::kCommonBreakLocation;
140 : }
141 :
142 771520 : std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
143 : Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code) {
144 771520 : if (abstract_code->IsBytecodeArray()) {
145 : DCHECK(debug_info->HasDebugBytecodeArray());
146 : return std::unique_ptr<BreakIterator>(
147 1162140 : new BytecodeArrayBreakIterator(debug_info));
148 : } else {
149 : DCHECK(abstract_code->IsCode());
150 : DCHECK(debug_info->HasDebugCode());
151 380900 : return std::unique_ptr<BreakIterator>(new CodeBreakIterator(debug_info));
152 : }
153 : }
154 :
155 0 : BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
156 2512147 : : debug_info_(debug_info), break_index_(-1) {
157 2512147 : position_ = debug_info->shared()->start_position();
158 2512147 : statement_position_ = position_;
159 0 : }
160 :
161 96904 : int BreakIterator::BreakIndexFromPosition(int source_position,
162 197165 : BreakPositionAlignment alignment) {
163 : int distance = kMaxInt;
164 : int closest_break = break_index();
165 249411 : while (!Done()) {
166 : int next_position;
167 149336 : if (alignment == STATEMENT_ALIGNED) {
168 : next_position = statement_position();
169 : } else {
170 : DCHECK(alignment == BREAK_POSITION_ALIGNED);
171 : next_position = position();
172 : }
173 264724 : if (source_position <= next_position &&
174 115388 : next_position - source_position < distance) {
175 : closest_break = break_index();
176 : distance = next_position - source_position;
177 : // Check whether we can't get any closer.
178 98074 : if (distance == 0) break;
179 : }
180 55603 : Next();
181 : }
182 96904 : return closest_break;
183 : }
184 :
185 460400 : CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info)
186 : : BreakIterator(debug_info),
187 : reloc_iterator_(debug_info->DebugCode(), GetModeMask()),
188 : source_position_iterator_(
189 1381200 : debug_info->DebugCode()->SourcePositionTable()) {
190 : // There is at least one break location.
191 : DCHECK(!Done());
192 460400 : Next();
193 460400 : }
194 :
195 0 : int CodeBreakIterator::GetModeMask() {
196 : int mask = 0;
197 : mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
198 : mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
199 : mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL);
200 : mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
201 0 : return mask;
202 : }
203 :
204 21569522 : void CodeBreakIterator::Next() {
205 : DisallowHeapAllocation no_gc;
206 : DCHECK(!Done());
207 :
208 : // Iterate through reloc info stopping at each breakable code target.
209 21569522 : bool first = break_index_ == -1;
210 :
211 21569522 : if (!first) reloc_iterator_.next();
212 : first = false;
213 43139044 : if (Done()) return;
214 :
215 21278568 : int offset = code_offset();
216 203903944 : while (!source_position_iterator_.done() &&
217 : source_position_iterator_.code_offset() <= offset) {
218 322998012 : position_ = source_position_iterator_.source_position().ScriptOffset();
219 70186318 : if (source_position_iterator_.is_statement()) {
220 21299505 : statement_position_ = position_;
221 : }
222 70186318 : source_position_iterator_.Advance();
223 : }
224 :
225 : DCHECK(RelocInfo::IsDebugBreakSlot(rmode()));
226 21278568 : break_index_++;
227 : }
228 :
229 2308338 : DebugBreakType CodeBreakIterator::GetDebugBreakType() {
230 2308338 : if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
231 : return DEBUG_BREAK_SLOT_AT_RETURN;
232 2273372 : } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
233 : return DEBUG_BREAK_SLOT_AT_CALL;
234 2248897 : } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
235 150 : return isolate()->is_tail_call_elimination_enabled()
236 : ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
237 150 : : DEBUG_BREAK_SLOT_AT_CALL;
238 2248747 : } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
239 : return DEBUG_BREAK_SLOT;
240 : } else {
241 0 : return NOT_DEBUG_BREAK;
242 : }
243 : }
244 :
245 37647 : void CodeBreakIterator::SkipToPosition(int position,
246 : BreakPositionAlignment alignment) {
247 37647 : CodeBreakIterator it(debug_info_);
248 37647 : SkipTo(it.BreakIndexFromPosition(position, alignment));
249 37647 : }
250 :
251 2212169 : void CodeBreakIterator::SetDebugBreak() {
252 2212169 : DebugBreakType debug_break_type = GetDebugBreakType();
253 : DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
254 2212169 : Builtins* builtins = isolate()->builtins();
255 : Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN
256 : ? builtins->Return_DebugBreak()
257 2212169 : : builtins->Slot_DebugBreak();
258 4424338 : DebugCodegen::PatchDebugBreakSlot(isolate(), rinfo()->pc(), target);
259 2212169 : }
260 :
261 4619772 : void CodeBreakIterator::ClearDebugBreak() {
262 : DCHECK(GetDebugBreakType() >= DEBUG_BREAK_SLOT);
263 9239544 : DebugCodegen::ClearDebugBreakSlot(isolate(), rinfo()->pc());
264 4619772 : }
265 :
266 0 : bool CodeBreakIterator::IsDebugBreak() {
267 : DCHECK(GetDebugBreakType() >= DEBUG_BREAK_SLOT);
268 0 : return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc());
269 : }
270 :
271 96169 : BreakLocation CodeBreakIterator::GetBreakLocation() {
272 : Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode()));
273 192338 : return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
274 : }
275 :
276 2051747 : BytecodeArrayBreakIterator::BytecodeArrayBreakIterator(
277 : Handle<DebugInfo> debug_info)
278 : : BreakIterator(debug_info),
279 : source_position_iterator_(
280 4103494 : debug_info->DebugBytecodeArray()->SourcePositionTable()) {
281 : // There is at least one break location.
282 : DCHECK(!Done());
283 2051747 : Next();
284 2051747 : }
285 :
286 35699122 : void BytecodeArrayBreakIterator::Next() {
287 : DisallowHeapAllocation no_gc;
288 : DCHECK(!Done());
289 35699122 : bool first = break_index_ == -1;
290 89179377 : while (!Done()) {
291 157720971 : if (!first) source_position_iterator_.Advance();
292 : first = false;
293 89179377 : if (Done()) return;
294 52120358 : position_ = source_position_iterator_.source_position().ScriptOffset();
295 52120358 : if (source_position_iterator_.is_statement()) {
296 32368031 : statement_position_ = position_;
297 : }
298 : DCHECK(position_ >= 0);
299 : DCHECK(statement_position_ >= 0);
300 :
301 52120358 : DebugBreakType type = GetDebugBreakType();
302 52120358 : if (type != NOT_DEBUG_BREAK) break;
303 : }
304 34339225 : break_index_++;
305 : }
306 :
307 68080015 : DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() {
308 : BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
309 : interpreter::Bytecode bytecode =
310 68080015 : interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
311 :
312 68080015 : if (bytecode == interpreter::Bytecode::kDebugger) {
313 : return DEBUGGER_STATEMENT;
314 65877788 : } else if (bytecode == interpreter::Bytecode::kReturn) {
315 : return DEBUG_BREAK_SLOT_AT_RETURN;
316 62881878 : } else if (bytecode == interpreter::Bytecode::kTailCall) {
317 2616 : return isolate()->is_tail_call_elimination_enabled()
318 : ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
319 2616 : : DEBUG_BREAK_SLOT_AT_CALL;
320 62879262 : } else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) {
321 : return DEBUG_BREAK_SLOT_AT_CALL;
322 59718192 : } else if (source_position_iterator_.is_statement()) {
323 : return DEBUG_BREAK_SLOT;
324 : } else {
325 17781133 : return NOT_DEBUG_BREAK;
326 : }
327 : }
328 :
329 59257 : void BytecodeArrayBreakIterator::SkipToPosition(
330 : int position, BreakPositionAlignment alignment) {
331 59257 : BytecodeArrayBreakIterator it(debug_info_);
332 59257 : SkipTo(it.BreakIndexFromPosition(position, alignment));
333 59257 : }
334 :
335 3714230 : void BytecodeArrayBreakIterator::SetDebugBreak() {
336 3714230 : DebugBreakType debug_break_type = GetDebugBreakType();
337 3714230 : if (debug_break_type == DEBUGGER_STATEMENT) return;
338 : DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
339 : BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
340 : interpreter::Bytecode bytecode =
341 3674930 : interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
342 3674930 : if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
343 : interpreter::Bytecode debugbreak =
344 3651698 : interpreter::Bytecodes::GetDebugBreak(bytecode);
345 3651698 : bytecode_array->set(code_offset(),
346 3651698 : interpreter::Bytecodes::ToByte(debugbreak));
347 : }
348 :
349 11950610 : void BytecodeArrayBreakIterator::ClearDebugBreak() {
350 11950610 : DebugBreakType debug_break_type = GetDebugBreakType();
351 23901220 : if (debug_break_type == DEBUGGER_STATEMENT) return;
352 : DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
353 : BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
354 : BytecodeArray* original = debug_info_->OriginalBytecodeArray();
355 22039622 : bytecode_array->set(code_offset(), original->get(code_offset()));
356 : }
357 :
358 0 : bool BytecodeArrayBreakIterator::IsDebugBreak() {
359 0 : DebugBreakType debug_break_type = GetDebugBreakType();
360 0 : if (debug_break_type == DEBUGGER_STATEMENT) return false;
361 : DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
362 : BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
363 : interpreter::Bytecode bytecode =
364 0 : interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
365 0 : return interpreter::Bytecodes::IsDebugBreak(bytecode);
366 : }
367 :
368 294817 : BreakLocation BytecodeArrayBreakIterator::GetBreakLocation() {
369 : Handle<AbstractCode> code(
370 : AbstractCode::cast(debug_info_->DebugBytecodeArray()));
371 589634 : return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
372 : }
373 :
374 :
375 99715 : void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
376 99715 : uint32_t mask = 1 << feature;
377 : // Only count one sample per feature and isolate.
378 199430 : if (bitfield_ & mask) return;
379 5066 : isolate_->counters()->debug_feature_usage()->AddSample(feature);
380 5066 : bitfield_ |= mask;
381 : }
382 :
383 :
384 : // Threading support.
385 105930 : void Debug::ThreadInit() {
386 105930 : thread_local_.break_count_ = 0;
387 105930 : thread_local_.break_id_ = 0;
388 105930 : thread_local_.break_frame_id_ = StackFrame::NO_ID;
389 105930 : thread_local_.last_step_action_ = StepNone;
390 105930 : thread_local_.last_statement_position_ = kNoSourcePosition;
391 105930 : thread_local_.last_frame_count_ = -1;
392 105930 : thread_local_.fast_forward_to_return_ = false;
393 105930 : thread_local_.ignore_step_into_function_ = Smi::kZero;
394 105930 : thread_local_.target_frame_count_ = -1;
395 105930 : thread_local_.return_value_ = Smi::kZero;
396 105930 : thread_local_.async_task_count_ = 0;
397 : clear_suspended_generator();
398 105930 : thread_local_.restart_fp_ = nullptr;
399 : base::NoBarrier_Store(&thread_local_.current_debug_scope_,
400 105930 : static_cast<base::AtomicWord>(0));
401 : UpdateHookOnFunctionCall();
402 105930 : }
403 :
404 :
405 22574 : char* Debug::ArchiveDebug(char* storage) {
406 : // Simply reset state. Don't archive anything.
407 22574 : ThreadInit();
408 22574 : return storage + ArchiveSpacePerThread();
409 : }
410 :
411 :
412 22574 : char* Debug::RestoreDebug(char* storage) {
413 : // Simply reset state. Don't restore anything.
414 22574 : ThreadInit();
415 22574 : return storage + ArchiveSpacePerThread();
416 : }
417 :
418 1280 : int Debug::ArchiveSpacePerThread() { return 0; }
419 :
420 241585 : void Debug::Iterate(RootVisitor* v) {
421 241585 : v->VisitRootPointer(Root::kDebug, &thread_local_.return_value_);
422 241585 : v->VisitRootPointer(Root::kDebug, &thread_local_.suspended_generator_);
423 241585 : v->VisitRootPointer(Root::kDebug, &thread_local_.ignore_step_into_function_);
424 241585 : }
425 :
426 11715 : DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
427 : // Globalize the request debug info object and make it weak.
428 11715 : GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
429 11715 : debug_info_ = global_handles->Create(debug_info).location();
430 11715 : }
431 :
432 :
433 0 : DebugInfoListNode::~DebugInfoListNode() {
434 11715 : if (debug_info_ == nullptr) return;
435 11715 : GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
436 11715 : debug_info_ = nullptr;
437 0 : }
438 :
439 :
440 667616 : bool Debug::Load() {
441 : // Return if debugger is already loaded.
442 667616 : if (is_loaded()) return true;
443 :
444 : // Bail out if we're already in the process of compiling the native
445 : // JavaScript source code for the debugger.
446 6970 : if (is_suppressed_) return false;
447 : SuppressDebug while_loading(this);
448 :
449 : // Disable breakpoints and interrupts while compiling and running the
450 : // debugger scripts including the context creation code.
451 : DisableBreak disable(this);
452 19310 : PostponeInterruptsScope postpone(isolate_);
453 :
454 : // Create the debugger context.
455 6970 : HandleScope scope(isolate_);
456 : ExtensionConfiguration no_extensions;
457 : // TODO(yangguo): we rely on the fact that first context snapshot is usable
458 : // as debug context. This dependency is gone once we remove
459 : // debug context completely.
460 : static const int kFirstContextSnapshotIndex = 0;
461 : Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
462 : MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
463 : kFirstContextSnapshotIndex, v8::DeserializeEmbedderFieldsCallback(),
464 6970 : DEBUG_CONTEXT);
465 :
466 : // Fail if no context could be created.
467 6970 : if (context.is_null()) return false;
468 :
469 10740 : debug_context_ = isolate_->global_handles()->Create(*context);
470 :
471 5370 : feature_tracker()->Track(DebugFeatureTracker::kActive);
472 :
473 5370 : return true;
474 : }
475 :
476 :
477 64527 : void Debug::Unload() {
478 64527 : ClearAllBreakPoints();
479 64528 : ClearStepping();
480 64528 : RemoveDebugDelegate();
481 :
482 : // Return debugger is not loaded.
483 129056 : if (!is_loaded()) return;
484 :
485 : // Clear debugger context global handle.
486 5370 : GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
487 5370 : debug_context_ = Handle<Context>();
488 : }
489 :
490 268233 : void Debug::Break(JavaScriptFrame* frame) {
491 : // Initialize LiveEdit.
492 90822 : LiveEdit::InitializeThreadLocal(this);
493 :
494 : // Just continue if breaks are disabled or debugger cannot be loaded.
495 96380 : if (break_disabled()) return;
496 :
497 : // Enter the debugger.
498 90794 : DebugScope debug_scope(this);
499 96324 : if (debug_scope.failed()) return;
500 :
501 : // Postpone interrupt during breakpoint processing.
502 90794 : PostponeInterruptsScope postpone(isolate_);
503 : DisableBreak no_recursive_break(this);
504 :
505 : // Return if we fail to retrieve debug info.
506 90794 : Handle<JSFunction> function(frame->function());
507 : Handle<SharedFunctionInfo> shared(function->shared());
508 90794 : if (!EnsureDebugInfo(shared)) return;
509 90794 : Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
510 :
511 : // Find the break location where execution has stopped.
512 90794 : BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
513 :
514 : // Find actual break points, if any, and trigger debug break event.
515 : MaybeHandle<FixedArray> break_points_hit =
516 90794 : CheckBreakPoints(debug_info, &location);
517 90794 : if (!break_points_hit.is_null()) {
518 : // Clear all current stepping setup.
519 4205 : ClearStepping();
520 : // Notify the debug event listeners.
521 : Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements(
522 4205 : break_points_hit.ToHandleChecked());
523 4205 : OnDebugBreak(jsarr);
524 : return;
525 : }
526 :
527 : // No break point. Check for stepping.
528 : StepAction step_action = last_step_action();
529 86589 : int current_frame_count = CurrentFrameCount();
530 86589 : int target_frame_count = thread_local_.target_frame_count_;
531 86589 : int last_frame_count = thread_local_.last_frame_count_;
532 :
533 : // StepOut at not return position was requested and return break locations
534 : // were flooded with one shots.
535 86589 : if (thread_local_.fast_forward_to_return_) {
536 : DCHECK(location.IsReturn());
537 : // We have to ignore recursive calls to function.
538 579 : if (current_frame_count > target_frame_count) return;
539 513 : ClearStepping();
540 513 : PrepareStep(StepOut);
541 513 : return;
542 : }
543 :
544 : bool step_break = false;
545 86010 : switch (step_action) {
546 : case StepNone:
547 : return;
548 : case StepOut:
549 : // Step out should not break in a deeper frame than target frame.
550 6 : if (current_frame_count > target_frame_count) return;
551 : step_break = true;
552 : break;
553 : case StepNext:
554 : // Step next should not break in a deeper frame than target frame.
555 13494 : if (current_frame_count > target_frame_count) return;
556 : // For step-next, a tail call is like a return and should break.
557 13398 : step_break = location.IsTailCall();
558 : // Fall through.
559 : case StepIn: {
560 85258 : FrameSummary summary = FrameSummary::GetTop(frame);
561 85252 : step_break = step_break || location.IsReturn() ||
562 151229 : current_frame_count != last_frame_count ||
563 65971 : thread_local_.last_statement_position_ !=
564 65971 : summary.SourceStatementPosition();
565 85258 : break;
566 : }
567 : }
568 :
569 : // Clear all current stepping setup.
570 85264 : ClearStepping();
571 :
572 85264 : if (step_break) {
573 : // Notify the debug event listeners.
574 147928 : OnDebugBreak(isolate_->factory()->undefined_value());
575 : } else {
576 : // Re-prepare to continue.
577 11300 : PrepareStep(step_action);
578 85264 : }
579 : }
580 :
581 :
582 : // Find break point objects for this location, if any, and evaluate them.
583 : // Return an array of break point objects that evaluated true, or an empty
584 : // handle if none evaluated true.
585 94404 : MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
586 5033 : BreakLocation* location,
587 : bool* has_break_points) {
588 : bool has_break_points_to_check =
589 94404 : break_points_active_ && location->HasBreakPoint(debug_info);
590 94404 : if (has_break_points) *has_break_points = has_break_points_to_check;
591 94404 : if (!has_break_points_to_check) return {};
592 :
593 : Handle<Object> break_point_objects =
594 5033 : debug_info->GetBreakPointObjects(location->position());
595 5033 : return Debug::GetHitBreakPointObjects(break_point_objects);
596 : }
597 :
598 :
599 34565 : bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
600 34565 : HandleScope scope(isolate_);
601 : // A break location is considered muted if break locations on the current
602 : // statement have at least one break point, and all of these break points
603 : // evaluate to false. Aside from not triggering a debug break event at the
604 : // break location, we also do not trigger one for debugger statements, nor
605 : // an exception event on exception at this location.
606 69130 : FrameSummary summary = FrameSummary::GetTop(frame);
607 : DCHECK(!summary.IsWasm());
608 : Handle<JSFunction> function = summary.AsJavaScript().function();
609 34565 : if (!function->shared()->HasDebugInfo()) return false;
610 : Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
611 : // Enter the debugger.
612 7084 : DebugScope debug_scope(this);
613 3542 : if (debug_scope.failed()) return false;
614 : List<BreakLocation> break_locations;
615 3542 : BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
616 : bool has_break_points_at_all = false;
617 7072 : for (int i = 0; i < break_locations.length(); i++) {
618 : bool has_break_points;
619 : MaybeHandle<FixedArray> check_result =
620 7220 : CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
621 3610 : has_break_points_at_all |= has_break_points;
622 3816 : if (has_break_points && !check_result.is_null()) return false;
623 : }
624 : return has_break_points_at_all;
625 : }
626 :
627 :
628 168765 : MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
629 : Handle<Object> args[]) {
630 168765 : PostponeInterruptsScope no_interrupts(isolate_);
631 : AssertDebugContext();
632 : Handle<JSReceiver> holder =
633 168765 : Handle<JSReceiver>::cast(isolate_->natives_utils_object());
634 : Handle<JSFunction> fun = Handle<JSFunction>::cast(
635 337530 : JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
636 168765 : Handle<Object> undefined = isolate_->factory()->undefined_value();
637 : MaybeHandle<Object> maybe_exception;
638 : return Execution::TryCall(isolate_, fun, undefined, argc, args,
639 : Execution::MessageHandling::kReport,
640 337530 : &maybe_exception);
641 : }
642 :
643 :
644 : // Check whether a single break point object is triggered.
645 9290 : bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
646 5227 : Factory* factory = isolate_->factory();
647 : HandleScope scope(isolate_);
648 :
649 : // Ignore check if break point object is not a JSObject.
650 5227 : if (!break_point_object->IsJSObject()) return true;
651 :
652 : // Get the break id as an object.
653 4063 : Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
654 :
655 : // Call IsBreakPointTriggered.
656 4063 : Handle<Object> argv[] = { break_id, break_point_object };
657 : Handle<Object> result;
658 4063 : if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
659 8126 : .ToHandle(&result)) {
660 : return false;
661 : }
662 :
663 : // Return whether the break point is triggered.
664 8102 : return result->IsTrue(isolate_);
665 : }
666 :
667 :
668 342 : bool Debug::SetBreakPoint(Handle<JSFunction> function,
669 : Handle<Object> break_point_object,
670 : int* source_position) {
671 342 : HandleScope scope(isolate_);
672 :
673 : // Make sure the function is compiled and has set up the debug info.
674 : Handle<SharedFunctionInfo> shared(function->shared());
675 342 : if (!EnsureDebugInfo(shared)) return true;
676 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
677 : // Source positions starts with zero.
678 : DCHECK(*source_position >= 0);
679 :
680 : // Find the break point and change it.
681 : *source_position =
682 342 : FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED);
683 342 : DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
684 : // At least one active break point now.
685 : DCHECK(debug_info->GetBreakPointCount() > 0);
686 :
687 342 : ClearBreakPoints(debug_info);
688 342 : ApplyBreakPoints(debug_info);
689 :
690 342 : feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
691 342 : return true;
692 : }
693 :
694 :
695 2719 : bool Debug::SetBreakPointForScript(Handle<Script> script,
696 : Handle<Object> break_point_object,
697 : int* source_position,
698 : BreakPositionAlignment alignment) {
699 2719 : if (script->type() == Script::TYPE_WASM) {
700 : Handle<WasmCompiledModule> compiled_module(
701 78 : WasmCompiledModule::cast(script->wasm_compiled_module()), isolate_);
702 : return WasmCompiledModule::SetBreakPoint(compiled_module, source_position,
703 78 : break_point_object);
704 : }
705 :
706 2641 : HandleScope scope(isolate_);
707 :
708 : // Obtain shared function info for the function.
709 : Handle<Object> result =
710 2641 : FindSharedFunctionInfoInScript(script, *source_position);
711 5282 : if (result->IsUndefined(isolate_)) return false;
712 :
713 : // Make sure the function has set up the debug info.
714 : Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
715 2635 : if (!EnsureDebugInfo(shared)) return false;
716 :
717 : // Find position within function. The script position might be before the
718 : // source position of the first function.
719 2635 : if (shared->start_position() > *source_position) {
720 66 : *source_position = shared->start_position();
721 : }
722 :
723 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
724 :
725 : // Find the break point and change it.
726 : *source_position =
727 2635 : FindBreakablePosition(debug_info, *source_position, alignment);
728 2635 : DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
729 : // At least one active break point now.
730 : DCHECK(debug_info->GetBreakPointCount() > 0);
731 :
732 2635 : ClearBreakPoints(debug_info);
733 2635 : ApplyBreakPoints(debug_info);
734 :
735 2635 : feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
736 2635 : return true;
737 : }
738 :
739 2977 : int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
740 : int source_position,
741 : BreakPositionAlignment alignment) {
742 : int statement_position;
743 : int position;
744 2977 : if (debug_info->HasDebugCode()) {
745 927 : CodeBreakIterator it(debug_info);
746 927 : it.SkipToPosition(source_position, alignment);
747 927 : statement_position = it.statement_position();
748 927 : position = it.position();
749 : } else {
750 : DCHECK(debug_info->HasDebugBytecodeArray());
751 2050 : BytecodeArrayBreakIterator it(debug_info);
752 2050 : it.SkipToPosition(source_position, alignment);
753 2050 : statement_position = it.statement_position();
754 2050 : position = it.position();
755 : }
756 2977 : return alignment == STATEMENT_ALIGNED ? statement_position : position;
757 : }
758 :
759 1437169 : void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
760 : DisallowHeapAllocation no_gc;
761 4311507 : if (debug_info->break_points()->IsUndefined(isolate_)) return;
762 : FixedArray* break_points = debug_info->break_points();
763 14375978 : for (int i = 0; i < break_points->length(); i++) {
764 11501640 : if (break_points->get(i)->IsUndefined(isolate_)) continue;
765 : BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
766 88078 : if (info->GetBreakPointCount() == 0) continue;
767 87220 : if (debug_info->HasDebugCode()) {
768 34649 : CodeBreakIterator it(debug_info);
769 34649 : it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
770 34649 : it.SetDebugBreak();
771 : }
772 87220 : if (debug_info->HasDebugBytecodeArray()) {
773 52571 : BytecodeArrayBreakIterator it(debug_info);
774 52571 : it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
775 52571 : it.SetDebugBreak();
776 : }
777 : }
778 : }
779 :
780 1448814 : void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
781 : DisallowHeapAllocation no_gc;
782 1448814 : if (debug_info->HasDebugCode()) {
783 9579584 : for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) {
784 4619772 : it.ClearDebugBreak();
785 : }
786 : }
787 1448814 : if (debug_info->HasDebugBytecodeArray()) {
788 26458808 : for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) {
789 11950610 : it.ClearDebugBreak();
790 : }
791 : }
792 1448814 : }
793 :
794 2854 : void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
795 2854 : HandleScope scope(isolate_);
796 :
797 12468 : for (DebugInfoListNode* node = debug_info_list_; node != NULL;
798 : node = node->next()) {
799 : Handle<Object> result =
800 9614 : DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
801 26242 : if (result->IsUndefined(isolate_)) continue;
802 : Handle<DebugInfo> debug_info = node->debug_info();
803 2600 : if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
804 2600 : ClearBreakPoints(debug_info);
805 2600 : if (debug_info->GetBreakPointCount() == 0) {
806 1978 : RemoveDebugInfoAndClearFromShared(debug_info);
807 : } else {
808 622 : ApplyBreakPoints(debug_info);
809 : }
810 5454 : return;
811 : }
812 : }
813 : }
814 :
815 : // Clear out all the debug break code. This is ONLY supposed to be used when
816 : // shutting down the debugger as it will leave the break point information in
817 : // DebugInfo even though the code is patched back to the non break point state.
818 64527 : void Debug::ClearAllBreakPoints() {
819 74194 : for (DebugInfoListNode* node = debug_info_list_; node != NULL;
820 : node = node->next()) {
821 9667 : ClearBreakPoints(node->debug_info());
822 : }
823 : // Remove all debug info.
824 74194 : while (debug_info_list_ != NULL) {
825 9667 : RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
826 : }
827 64527 : }
828 :
829 98011 : void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
830 : bool returns_only) {
831 98011 : if (IsBlackboxed(shared)) return;
832 : // Make sure the function is compiled and has set up the debug info.
833 98005 : if (!EnsureDebugInfo(shared)) return;
834 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
835 : // Flood the function with break points.
836 98005 : if (debug_info->HasDebugCode()) {
837 4404980 : for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) {
838 2177854 : if (returns_only && !it.GetBreakLocation().IsReturn()) continue;
839 2177520 : it.SetDebugBreak();
840 : }
841 : }
842 98005 : if (debug_info->HasDebugBytecodeArray()) {
843 7473614 : for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) {
844 3663438 : if (returns_only && !it.GetBreakLocation().IsReturn()) continue;
845 3661659 : it.SetDebugBreak();
846 : }
847 : }
848 : }
849 :
850 20802 : void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
851 20802 : if (type == BreakUncaughtException) {
852 10401 : break_on_uncaught_exception_ = enable;
853 : } else {
854 10401 : break_on_exception_ = enable;
855 : }
856 20802 : }
857 :
858 :
859 5124 : bool Debug::IsBreakOnException(ExceptionBreakType type) {
860 5124 : if (type == BreakUncaughtException) {
861 1666 : return break_on_uncaught_exception_;
862 : } else {
863 3458 : return break_on_exception_;
864 : }
865 : }
866 :
867 5157 : MaybeHandle<FixedArray> Debug::GetHitBreakPointObjects(
868 : Handle<Object> break_point_objects) {
869 : DCHECK(!break_point_objects->IsUndefined(isolate_));
870 5157 : if (!break_point_objects->IsFixedArray()) {
871 5093 : if (!CheckBreakPoint(break_point_objects)) return {};
872 4351 : Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
873 4351 : break_points_hit->set(0, *break_point_objects);
874 : return break_points_hit;
875 : }
876 :
877 : Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
878 : int num_objects = array->length();
879 : Handle<FixedArray> break_points_hit =
880 64 : isolate_->factory()->NewFixedArray(num_objects);
881 : int break_points_hit_count = 0;
882 198 : for (int i = 0; i < num_objects; ++i) {
883 134 : Handle<Object> break_point_object(array->get(i), isolate_);
884 134 : if (CheckBreakPoint(break_point_object)) {
885 244 : break_points_hit->set(break_points_hit_count++, *break_point_object);
886 : }
887 : }
888 64 : if (break_points_hit_count == 0) return {};
889 58 : break_points_hit->Shrink(break_points_hit_count);
890 : return break_points_hit;
891 : }
892 :
893 2752526 : void Debug::PrepareStepIn(Handle<JSFunction> function) {
894 1368204 : CHECK(last_step_action() >= StepIn);
895 2727880 : if (ignore_events()) return;
896 1349947 : if (in_debug_scope()) return;
897 16118 : if (break_disabled()) return;
898 : Handle<SharedFunctionInfo> shared(function->shared());
899 16118 : if (IsBlackboxed(shared)) return;
900 8558 : if (*function == thread_local_.ignore_step_into_function_) return;
901 8528 : thread_local_.ignore_step_into_function_ = Smi::kZero;
902 17056 : FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
903 : }
904 :
905 648 : void Debug::PrepareStepInSuspendedGenerator() {
906 216 : CHECK(has_suspended_generator());
907 216 : if (ignore_events()) return;
908 216 : if (in_debug_scope()) return;
909 216 : if (break_disabled()) return;
910 216 : thread_local_.last_step_action_ = StepIn;
911 : UpdateHookOnFunctionCall();
912 : Handle<JSFunction> function(
913 216 : JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
914 432 : FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
915 : clear_suspended_generator();
916 : }
917 :
918 8503 : void Debug::PrepareStepOnThrow() {
919 10320 : if (last_step_action() == StepNone) return;
920 834 : if (ignore_events()) return;
921 834 : if (in_debug_scope()) return;
922 834 : if (break_disabled()) return;
923 :
924 834 : ClearOneShot();
925 :
926 834 : int current_frame_count = CurrentFrameCount();
927 :
928 : // Iterate through the JavaScript stack looking for handlers.
929 834 : JavaScriptFrameIterator it(isolate_);
930 1750 : while (!it.done()) {
931 : JavaScriptFrame* frame = it.frame();
932 898 : if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
933 : List<SharedFunctionInfo*> infos;
934 82 : frame->GetFunctions(&infos);
935 82 : current_frame_count -= infos.length();
936 82 : it.Advance();
937 : }
938 :
939 : // No handler found. Nothing to instrument.
940 834 : if (it.done()) return;
941 :
942 : bool found_handler = false;
943 : // Iterate frames, including inlined frames. First, find the handler frame.
944 : // Then skip to the frame we want to break in, then instrument for stepping.
945 880 : for (; !it.done(); it.Advance()) {
946 : JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
947 834 : if (last_step_action() == StepIn) {
948 : // Deoptimize frame to ensure calls are checked for step-in.
949 764 : Deoptimizer::DeoptimizeFunction(frame->function());
950 : }
951 : List<FrameSummary> summaries;
952 834 : frame->Summarize(&summaries);
953 878 : for (int i = summaries.length() - 1; i >= 0; i--, current_frame_count--) {
954 846 : if (!found_handler) {
955 : // We have yet to find the handler. If the frame inlines multiple
956 : // functions, we have to check each one for the handler.
957 : // If it only contains one function, we already found the handler.
958 828 : if (summaries.length() > 1) {
959 : Handle<AbstractCode> code =
960 24 : summaries[i].AsJavaScript().abstract_code();
961 24 : CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
962 : BytecodeArray* bytecode = code->GetBytecodeArray();
963 : HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
964 48 : int code_offset = summaries[i].code_offset();
965 : HandlerTable::CatchPrediction prediction;
966 24 : int index = table->LookupRange(code_offset, nullptr, &prediction);
967 24 : if (index > 0) found_handler = true;
968 : } else {
969 : found_handler = true;
970 : }
971 : }
972 :
973 846 : if (found_handler) {
974 : // We found the handler. If we are stepping next or out, we need to
975 : // iterate until we found the suitable target frame to break in.
976 904 : if ((last_step_action() == StepNext || last_step_action() == StepOut) &&
977 70 : current_frame_count > thread_local_.target_frame_count_) {
978 32 : continue;
979 : }
980 : Handle<SharedFunctionInfo> info(
981 816 : summaries[i].AsJavaScript().function()->shared());
982 816 : if (IsBlackboxed(info)) continue;
983 802 : FloodWithOneShot(info);
984 802 : return;
985 : }
986 : }
987 : }
988 : }
989 :
990 :
991 203947 : void Debug::PrepareStep(StepAction step_action) {
992 89701 : HandleScope scope(isolate_);
993 :
994 : DCHECK(in_debug_scope());
995 :
996 : // Get the frame where the execution has stopped and skip the debug frame if
997 : // any. The debug frame will only be present if execution was stopped due to
998 : // hitting a break point. In other situations (e.g. unhandled exception) the
999 : // debug frame is not present.
1000 : StackFrame::Id frame_id = break_frame_id();
1001 : // If there is no JavaScript stack don't do anything.
1002 89701 : if (frame_id == StackFrame::NO_ID) return;
1003 :
1004 89701 : feature_tracker()->Track(DebugFeatureTracker::kStepping);
1005 :
1006 89701 : thread_local_.last_step_action_ = step_action;
1007 :
1008 89701 : StackTraceFrameIterator frames_it(isolate_, frame_id);
1009 : StandardFrame* frame = frames_it.frame();
1010 :
1011 : // Handle stepping in wasm functions via the wasm interpreter.
1012 179402 : if (frame->is_wasm()) {
1013 : // If the top frame is compiled, we cannot step.
1014 244 : if (frame->is_wasm_compiled()) return;
1015 : WasmInterpreterEntryFrame* wasm_frame =
1016 : WasmInterpreterEntryFrame::cast(frame);
1017 244 : wasm_frame->wasm_instance()->debug_info()->PrepareStep(step_action);
1018 244 : return;
1019 : }
1020 :
1021 : JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
1022 : DCHECK(js_frame->function()->IsJSFunction());
1023 :
1024 : // Get the debug info (create it if it does not exist).
1025 89457 : auto summary = FrameSummary::GetTop(frame).AsJavaScript();
1026 : Handle<JSFunction> function(summary.function());
1027 : Handle<SharedFunctionInfo> shared(function->shared());
1028 89457 : if (!EnsureDebugInfo(shared)) return;
1029 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1030 :
1031 89457 : BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame);
1032 :
1033 : // Any step at a return is a step-out and we need to schedule DebugOnFunction
1034 : // call callback.
1035 89457 : if (location.IsReturn()) {
1036 : // On StepOut we'll ignore our further calls to current function in
1037 : // PrepareStepIn callback.
1038 8402 : if (last_step_action() == StepOut) {
1039 665 : thread_local_.ignore_step_into_function_ = *function;
1040 : }
1041 : step_action = StepOut;
1042 8402 : thread_local_.last_step_action_ = StepIn;
1043 : }
1044 : UpdateHookOnFunctionCall();
1045 :
1046 : // A step-next at a tail call is a step-out.
1047 89457 : if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
1048 : // A step-next in blackboxed function is a step-out.
1049 89457 : if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut;
1050 :
1051 : thread_local_.last_statement_position_ =
1052 89457 : summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1053 89457 : int current_frame_count = CurrentFrameCount();
1054 89457 : thread_local_.last_frame_count_ = current_frame_count;
1055 : // No longer perform the current async step.
1056 : clear_suspended_generator();
1057 :
1058 89457 : switch (step_action) {
1059 : case StepNone:
1060 0 : UNREACHABLE();
1061 : break;
1062 : case StepOut: {
1063 : // Clear last position info. For stepping out it does not matter.
1064 8941 : thread_local_.last_statement_position_ = kNoSourcePosition;
1065 8941 : thread_local_.last_frame_count_ = -1;
1066 8941 : if (!location.IsReturn() && !IsBlackboxed(shared)) {
1067 : // At not return position we flood return positions with one shots and
1068 : // will repeat StepOut automatically at next break.
1069 527 : thread_local_.target_frame_count_ = current_frame_count;
1070 527 : thread_local_.fast_forward_to_return_ = true;
1071 527 : FloodWithOneShot(shared, true);
1072 527 : return;
1073 : }
1074 : // Skip the current frame, find the first frame we want to step out to
1075 : // and deoptimize every frame along the way.
1076 : bool in_current_frame = true;
1077 25856 : for (; !frames_it.done(); frames_it.Advance()) {
1078 : // TODO(clemensh): Implement stepping out from JS to WASM.
1079 32286 : if (frames_it.frame()->is_wasm()) continue;
1080 : JavaScriptFrame* frame = JavaScriptFrame::cast(frames_it.frame());
1081 16143 : if (last_step_action() == StepIn) {
1082 : // Deoptimize frame to ensure calls are checked for step-in.
1083 16119 : Deoptimizer::DeoptimizeFunction(frame->function());
1084 : }
1085 16143 : HandleScope scope(isolate_);
1086 : List<Handle<SharedFunctionInfo>> infos;
1087 16143 : frame->GetFunctions(&infos);
1088 24865 : for (; !infos.is_empty(); current_frame_count--) {
1089 16144 : Handle<SharedFunctionInfo> info = infos.RemoveLast();
1090 16144 : if (in_current_frame) {
1091 : // We want to skip out, so skip the current frame.
1092 : in_current_frame = false;
1093 8722 : continue;
1094 : }
1095 7730 : if (IsBlackboxed(info)) continue;
1096 7422 : FloodWithOneShot(info);
1097 7422 : thread_local_.target_frame_count_ = current_frame_count;
1098 7422 : return;
1099 : }
1100 : }
1101 : break;
1102 : }
1103 : case StepNext:
1104 13578 : thread_local_.target_frame_count_ = current_frame_count;
1105 : // Fall through.
1106 : case StepIn:
1107 : // TODO(clemensh): Implement stepping from JS into WASM.
1108 80516 : FloodWithOneShot(shared);
1109 80516 : break;
1110 : }
1111 : }
1112 :
1113 : // Simple function for returning the source positions for active break points.
1114 392 : Handle<Object> Debug::GetSourceBreakLocations(
1115 : Handle<SharedFunctionInfo> shared,
1116 : BreakPositionAlignment position_alignment) {
1117 : Isolate* isolate = shared->GetIsolate();
1118 392 : if (!shared->HasDebugInfo()) {
1119 56 : return isolate->factory()->undefined_value();
1120 : }
1121 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1122 336 : if (debug_info->GetBreakPointCount() == 0) {
1123 0 : return isolate->factory()->undefined_value();
1124 : }
1125 : Handle<FixedArray> locations =
1126 336 : isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1127 : int count = 0;
1128 3360 : for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1129 1344 : if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
1130 : BreakPointInfo* break_point_info =
1131 : BreakPointInfo::cast(debug_info->break_points()->get(i));
1132 686 : int break_points = break_point_info->GetBreakPointCount();
1133 686 : if (break_points == 0) continue;
1134 : Smi* position = NULL;
1135 546 : if (position_alignment == STATEMENT_ALIGNED) {
1136 546 : if (debug_info->HasDebugCode()) {
1137 234 : CodeBreakIterator it(debug_info);
1138 : it.SkipToPosition(break_point_info->source_position(),
1139 234 : BREAK_POSITION_ALIGNED);
1140 234 : position = Smi::FromInt(it.statement_position());
1141 : } else {
1142 : DCHECK(debug_info->HasDebugBytecodeArray());
1143 312 : BytecodeArrayBreakIterator it(debug_info);
1144 : it.SkipToPosition(break_point_info->source_position(),
1145 312 : BREAK_POSITION_ALIGNED);
1146 312 : position = Smi::FromInt(it.statement_position());
1147 : }
1148 : } else {
1149 : DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment);
1150 : position = Smi::FromInt(break_point_info->source_position());
1151 : }
1152 1120 : for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1153 : }
1154 : }
1155 336 : return locations;
1156 : }
1157 :
1158 249321 : void Debug::ClearStepping() {
1159 : // Clear the various stepping setup.
1160 249321 : ClearOneShot();
1161 :
1162 249321 : thread_local_.last_step_action_ = StepNone;
1163 249321 : thread_local_.last_statement_position_ = kNoSourcePosition;
1164 249321 : thread_local_.ignore_step_into_function_ = Smi::kZero;
1165 249321 : thread_local_.fast_forward_to_return_ = false;
1166 249321 : thread_local_.last_frame_count_ = -1;
1167 249321 : thread_local_.target_frame_count_ = -1;
1168 : UpdateHookOnFunctionCall();
1169 249321 : }
1170 :
1171 :
1172 : // Clears all the one-shot break points that are currently set. Normally this
1173 : // function is called each time a break point is hit as one shot break points
1174 : // are used to support stepping.
1175 250154 : void Debug::ClearOneShot() {
1176 : // The current implementation just runs through all the breakpoints. When the
1177 : // last break point for a function is removed that function is automatically
1178 : // removed from the list.
1179 1683724 : for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1180 : node = node->next()) {
1181 1433570 : Handle<DebugInfo> debug_info = node->debug_info();
1182 1433570 : ClearBreakPoints(debug_info);
1183 1433570 : ApplyBreakPoints(debug_info);
1184 : }
1185 250154 : }
1186 :
1187 :
1188 5392 : bool MatchingCodeTargets(Code* target1, Code* target2) {
1189 5392 : if (target1 == target2) return true;
1190 4824 : if (target1->kind() != target2->kind()) return false;
1191 3152 : return target1->is_handler() || target1->is_inline_cache_stub();
1192 : }
1193 :
1194 :
1195 : // Count the number of calls before the current frame PC to find the
1196 : // corresponding PC in the newly recompiled code.
1197 249 : static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
1198 : Address old_pc) {
1199 : DCHECK_EQ(old_code->kind(), Code::FUNCTION);
1200 : DCHECK_EQ(new_code->kind(), Code::FUNCTION);
1201 : DCHECK(new_code->has_debug_break_slots());
1202 : static const int mask = RelocInfo::kCodeTargetMask;
1203 :
1204 : // Find the target of the current call.
1205 : Code* target = NULL;
1206 : intptr_t delta = 0;
1207 2945 : for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1208 2945 : RelocInfo* rinfo = it.rinfo();
1209 : Address current_pc = rinfo->pc();
1210 : // The frame PC is behind the call instruction by the call instruction size.
1211 2945 : if (current_pc > old_pc) break;
1212 2696 : delta = old_pc - current_pc;
1213 2696 : target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1214 : }
1215 :
1216 : // Count the number of calls to the same target before the current call.
1217 : int index = 0;
1218 2945 : for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1219 2945 : RelocInfo* rinfo = it.rinfo();
1220 : Address current_pc = rinfo->pc();
1221 2945 : if (current_pc > old_pc) break;
1222 2696 : Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1223 2696 : if (MatchingCodeTargets(target, current)) index++;
1224 : }
1225 :
1226 : DCHECK(index > 0);
1227 :
1228 : // Repeat the count on the new code to find corresponding call.
1229 2696 : for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
1230 2696 : RelocInfo* rinfo = it.rinfo();
1231 2696 : Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1232 2696 : if (MatchingCodeTargets(target, current)) index--;
1233 2696 : if (index == 0) return rinfo->pc() + delta;
1234 : }
1235 :
1236 0 : UNREACHABLE();
1237 : return NULL;
1238 : }
1239 :
1240 :
1241 11715 : class RedirectActiveFunctions : public ThreadVisitor {
1242 : public:
1243 : explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
1244 11715 : : shared_(shared) {
1245 : DCHECK(shared->HasDebugCode());
1246 : }
1247 :
1248 11715 : void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1249 123486 : for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1250 : JavaScriptFrame* frame = it.frame();
1251 50028 : JSFunction* function = frame->function();
1252 100056 : if (frame->is_optimized()) continue;
1253 43481 : if (!function->Inlines(shared_)) continue;
1254 :
1255 2451 : if (frame->is_interpreted()) {
1256 : InterpretedFrame* interpreted_frame =
1257 : reinterpret_cast<InterpretedFrame*>(frame);
1258 : BytecodeArray* debug_copy =
1259 2196 : shared_->GetDebugInfo()->DebugBytecodeArray();
1260 2196 : interpreted_frame->PatchBytecodeArray(debug_copy);
1261 2196 : continue;
1262 : }
1263 :
1264 : Code* frame_code = frame->LookupCode();
1265 : DCHECK(frame_code->kind() == Code::FUNCTION);
1266 255 : if (frame_code->has_debug_break_slots()) continue;
1267 :
1268 : Code* new_code = function->shared()->code();
1269 : Address old_pc = frame->pc();
1270 249 : Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);
1271 :
1272 249 : if (FLAG_trace_deopt) {
1273 : PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
1274 : "\n",
1275 : reinterpret_cast<intptr_t>(old_pc),
1276 0 : reinterpret_cast<intptr_t>(new_pc));
1277 : }
1278 :
1279 : if (FLAG_enable_embedded_constant_pool) {
1280 : // Update constant pool pointer for new code.
1281 : frame->set_constant_pool(new_code->constant_pool());
1282 : }
1283 :
1284 : // Patch the return address to return into the code with
1285 : // debug break slots.
1286 : frame->set_pc(new_pc);
1287 : }
1288 11715 : }
1289 :
1290 : private:
1291 : SharedFunctionInfo* shared_;
1292 : DisallowHeapAllocation no_gc_;
1293 : };
1294 :
1295 :
1296 11715 : bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
1297 : DCHECK(shared->is_compiled());
1298 :
1299 23430 : if (isolate_->concurrent_recompilation_enabled()) {
1300 : isolate_->optimizing_compile_dispatcher()->Flush(
1301 11715 : OptimizingCompileDispatcher::BlockingBehavior::kBlock);
1302 : }
1303 :
1304 : List<Handle<JSFunction> > functions;
1305 :
1306 : // Flush all optimized code maps. Note that the below heap iteration does not
1307 : // cover this, because the given function might have been inlined into code
1308 : // for which no JSFunction exists.
1309 : {
1310 11715 : SharedFunctionInfo::GlobalIterator iterator(isolate_);
1311 16600465 : while (SharedFunctionInfo* shared = iterator.Next()) {
1312 16588750 : shared->ClearCodeFromOptimizedCodeMap();
1313 16588750 : }
1314 : }
1315 :
1316 : // The native context also has a list of OSR'd optimized code. Clear it.
1317 11715 : isolate_->ClearOSROptimizedCode();
1318 :
1319 : // Make sure we abort incremental marking.
1320 : isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1321 11715 : GarbageCollectionReason::kDebugger);
1322 :
1323 : DCHECK(shared->is_compiled());
1324 : bool baseline_exists = shared->HasBaselineCode();
1325 :
1326 : {
1327 : // TODO(yangguo): with bytecode, we still walk the heap to find all
1328 : // optimized code for the function to deoptimize. We can probably be
1329 : // smarter here and avoid the heap walk.
1330 11715 : HeapIterator iterator(isolate_->heap());
1331 : HeapObject* obj;
1332 :
1333 219690666 : while ((obj = iterator.next()) != nullptr) {
1334 219667236 : if (obj->IsJSFunction()) {
1335 : JSFunction* function = JSFunction::cast(obj);
1336 24775531 : if (!function->Inlines(*shared)) continue;
1337 11243 : if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
1338 579 : Deoptimizer::DeoptimizeFunction(function);
1339 : }
1340 13343 : if (baseline_exists && function->shared() == *shared) {
1341 2081 : functions.Add(handle(function));
1342 : }
1343 : }
1344 11715 : }
1345 : }
1346 :
1347 : // We do not need to replace code to debug bytecode.
1348 : DCHECK(baseline_exists || functions.is_empty());
1349 :
1350 : // We do not need to recompile to debug bytecode.
1351 13940 : if (baseline_exists && !shared->code()->has_debug_break_slots()) {
1352 849 : if (!Compiler::CompileDebugCode(shared)) return false;
1353 : }
1354 :
1355 25511 : for (Handle<JSFunction> const function : functions) {
1356 2081 : function->ReplaceCode(shared->code());
1357 2081 : JSFunction::EnsureLiterals(function);
1358 : }
1359 :
1360 : // Update PCs on the stack to point to recompiled code.
1361 : RedirectActiveFunctions redirect_visitor(*shared);
1362 11715 : redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1363 23430 : isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1364 :
1365 : return true;
1366 : }
1367 :
1368 : namespace {
1369 : template <typename Iterator>
1370 960 : void GetBreakablePositions(Iterator* it, int start_position, int end_position,
1371 : std::vector<BreakLocation>* locations) {
1372 960 : it->SkipToPosition(start_position, BREAK_POSITION_ALIGNED);
1373 5358 : while (!it->Done() && it->position() < end_position &&
1374 : it->position() >= start_position) {
1375 6876 : locations->push_back(it->GetBreakLocation());
1376 3438 : it->Next();
1377 : }
1378 960 : }
1379 :
1380 960 : void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
1381 : int end_position,
1382 : std::vector<BreakLocation>* locations) {
1383 960 : if (debug_info->HasDebugCode()) {
1384 198 : CodeBreakIterator it(debug_info);
1385 198 : GetBreakablePositions(&it, start_position, end_position, locations);
1386 : } else {
1387 : DCHECK(debug_info->HasDebugBytecodeArray());
1388 762 : BytecodeArrayBreakIterator it(debug_info);
1389 762 : GetBreakablePositions(&it, start_position, end_position, locations);
1390 : }
1391 960 : }
1392 : } // namespace
1393 :
1394 192 : bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
1395 : int end_position, bool restrict_to_function,
1396 : std::vector<BreakLocation>* locations) {
1397 192 : if (restrict_to_function) {
1398 : Handle<Object> result =
1399 6 : FindSharedFunctionInfoInScript(script, start_position);
1400 12 : if (result->IsUndefined(isolate_)) return false;
1401 :
1402 : // Make sure the function has set up the debug info.
1403 : Handle<SharedFunctionInfo> shared =
1404 : Handle<SharedFunctionInfo>::cast(result);
1405 6 : if (!EnsureDebugInfo(shared)) return false;
1406 :
1407 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1408 6 : FindBreakablePositions(debug_info, start_position, end_position, locations);
1409 6 : return true;
1410 : }
1411 :
1412 : while (true) {
1413 298 : HandleScope scope(isolate_);
1414 : List<Handle<SharedFunctionInfo>> candidates;
1415 298 : SharedFunctionInfo::ScriptIterator iterator(script);
1416 1878 : for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
1417 : info = iterator.Next()) {
1418 3128 : if (info->end_position() < start_position ||
1419 : info->start_position() >= end_position) {
1420 : continue;
1421 : }
1422 1398 : if (!info->IsSubjectToDebugging()) continue;
1423 1776 : if (!info->HasDebugCode() && !info->allows_lazy_compilation()) continue;
1424 1398 : candidates.Add(i::handle(info));
1425 : }
1426 :
1427 : bool was_compiled = false;
1428 1398 : for (int i = 0; i < candidates.length(); ++i) {
1429 : // Code that cannot be compiled lazily are internal and not debuggable.
1430 : DCHECK(candidates[i]->allows_lazy_compilation());
1431 2796 : if (!candidates[i]->HasDebugCode()) {
1432 704 : if (!Compiler::CompileDebugCode(candidates[i])) {
1433 : return false;
1434 : } else {
1435 : was_compiled = true;
1436 : }
1437 : }
1438 2796 : if (!EnsureDebugInfo(candidates[i])) return false;
1439 : }
1440 298 : if (was_compiled) continue;
1441 :
1442 954 : for (int i = 0; i < candidates.length(); ++i) {
1443 1908 : CHECK(candidates[i]->HasDebugInfo());
1444 : Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo());
1445 : FindBreakablePositions(debug_info, start_position, end_position,
1446 954 : locations);
1447 : }
1448 : return true;
1449 : }
1450 : UNREACHABLE();
1451 112 : return false;
1452 : }
1453 :
1454 250 : void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) {
1455 250 : if (last_step_action() <= StepOut) return;
1456 :
1457 250 : if (last_step_action() == StepNext) {
1458 : // Only consider this generator a step-next target if not stepping in.
1459 126 : if (thread_local_.target_frame_count_ < CurrentFrameCount()) return;
1460 : }
1461 :
1462 : DCHECK(!has_suspended_generator());
1463 236 : thread_local_.suspended_generator_ = *generator_object;
1464 236 : ClearStepping();
1465 : }
1466 :
1467 : class SharedFunctionInfoFinder {
1468 : public:
1469 : explicit SharedFunctionInfoFinder(int target_position)
1470 : : current_candidate_(NULL),
1471 : current_candidate_closure_(NULL),
1472 : current_start_position_(kNoSourcePosition),
1473 4391 : target_position_(target_position) {}
1474 :
1475 20697 : void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
1476 20697 : if (!shared->IsSubjectToDebugging()) return;
1477 : int start_position = shared->function_token_position();
1478 20547 : if (start_position == kNoSourcePosition) {
1479 : start_position = shared->start_position();
1480 : }
1481 :
1482 20547 : if (start_position > target_position_) return;
1483 15252 : if (target_position_ > shared->end_position()) return;
1484 :
1485 8717 : if (current_candidate_ != NULL) {
1486 4863 : if (current_start_position_ == start_position &&
1487 : shared->end_position() == current_candidate_->end_position()) {
1488 : // If we already have a matching closure, do not throw it away.
1489 235 : if (current_candidate_closure_ != NULL && closure == NULL) return;
1490 : // If a top-level function contains only one function
1491 : // declaration the source for the top-level and the function
1492 : // is the same. In that case prefer the non top-level function.
1493 235 : if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1494 8194 : } else if (start_position < current_start_position_ ||
1495 : current_candidate_->end_position() < shared->end_position()) {
1496 : return;
1497 : }
1498 : }
1499 :
1500 8717 : current_start_position_ = start_position;
1501 8717 : current_candidate_ = shared;
1502 8717 : current_candidate_closure_ = closure;
1503 : }
1504 :
1505 : SharedFunctionInfo* Result() { return current_candidate_; }
1506 :
1507 : JSFunction* ResultClosure() { return current_candidate_closure_; }
1508 :
1509 : private:
1510 : SharedFunctionInfo* current_candidate_;
1511 : JSFunction* current_candidate_closure_;
1512 : int current_start_position_;
1513 : int target_position_;
1514 : DisallowHeapAllocation no_gc_;
1515 : };
1516 :
1517 :
1518 : // We need to find a SFI for a literal that may not yet have been compiled yet,
1519 : // and there may not be a JSFunction referencing it. Find the SFI closest to
1520 : // the given position, compile it to reveal possible inner SFIs and repeat.
1521 : // While we are at this, also ensure code with debug break slots so that we do
1522 : // not have to compile a SFI without JSFunction, which is paifu for those that
1523 : // cannot be compiled without context (need to find outer compilable SFI etc.)
1524 3004 : Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
1525 : int position) {
1526 1387 : for (int iteration = 0;; iteration++) {
1527 : // Go through all shared function infos associated with this script to
1528 : // find the inner most function containing this position.
1529 : // If there is no shared function info for this script at all, there is
1530 : // no point in looking for it by walking the heap.
1531 :
1532 : SharedFunctionInfo* shared;
1533 : {
1534 : SharedFunctionInfoFinder finder(position);
1535 4391 : SharedFunctionInfo::ScriptIterator iterator(script);
1536 25088 : for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
1537 : info = iterator.Next()) {
1538 20697 : finder.NewCandidate(info);
1539 : }
1540 4391 : shared = finder.Result();
1541 4391 : if (shared == NULL) break;
1542 : // We found it if it's already compiled and has debug code.
1543 4385 : if (shared->HasDebugCode()) {
1544 : Handle<SharedFunctionInfo> shared_handle(shared);
1545 : // If the iteration count is larger than 1, we had to compile the outer
1546 : // function in order to create this shared function info. So there can
1547 : // be no JSFunction referencing it. We can anticipate creating a debug
1548 : // info while bypassing PrepareFunctionForBreakpoints.
1549 2998 : if (iteration > 1) {
1550 : AllowHeapAllocation allow_before_return;
1551 0 : CreateDebugInfo(shared_handle);
1552 : }
1553 2998 : return shared_handle;
1554 : }
1555 : }
1556 : // If not, compile to reveal inner functions.
1557 1387 : HandleScope scope(isolate_);
1558 : // Code that cannot be compiled lazily are internal and not debuggable.
1559 : DCHECK(shared->allows_lazy_compilation());
1560 1387 : if (!Compiler::CompileDebugCode(handle(shared))) break;
1561 1387 : }
1562 12 : return isolate_->factory()->undefined_value();
1563 : }
1564 :
1565 :
1566 : // Ensures the debug information is present for shared.
1567 282643 : bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
1568 : // Return if we already have the debug info for shared.
1569 282643 : if (shared->HasDebugInfo()) return true;
1570 11715 : if (!shared->IsSubjectToDebugging()) return false;
1571 11715 : if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) {
1572 : return false;
1573 : }
1574 :
1575 : // To prepare bytecode for debugging, we already need to have the debug
1576 : // info (containing the debug copy) upfront, but since we do not recompile,
1577 : // preparing for break points cannot fail.
1578 11715 : CreateDebugInfo(shared);
1579 11715 : CHECK(PrepareFunctionForBreakPoints(shared));
1580 : return true;
1581 : }
1582 :
1583 :
1584 11715 : void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) {
1585 : // Create the debug info object.
1586 11715 : Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1587 :
1588 : // Add debug info to the list.
1589 11715 : DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1590 11715 : node->set_next(debug_info_list_);
1591 11715 : debug_info_list_ = node;
1592 11715 : }
1593 :
1594 :
1595 11715 : void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
1596 11715 : HandleScope scope(isolate_);
1597 : Handle<SharedFunctionInfo> shared(debug_info->shared());
1598 :
1599 : DCHECK_NOT_NULL(debug_info_list_);
1600 : // Run through the debug info objects to find this one and remove it.
1601 : DebugInfoListNode* prev = NULL;
1602 40889 : DebugInfoListNode* current = debug_info_list_;
1603 26302 : while (current != NULL) {
1604 14587 : if (current->debug_info().is_identical_to(debug_info)) {
1605 : // Unlink from list. If prev is NULL we are looking at the first element.
1606 11715 : if (prev == NULL) {
1607 11079 : debug_info_list_ = current->next();
1608 : } else {
1609 : prev->set_next(current->next());
1610 : }
1611 11715 : shared->set_debug_info(Smi::FromInt(debug_info->debugger_hints()));
1612 23430 : delete current;
1613 11715 : return;
1614 : }
1615 : // Move to next in list.
1616 : prev = current;
1617 : current = current->next();
1618 : }
1619 :
1620 0 : UNREACHABLE();
1621 : }
1622 :
1623 99182 : bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1624 99182 : HandleScope scope(isolate_);
1625 :
1626 : // Get the executing function in which the debug break occurred.
1627 99182 : Handle<SharedFunctionInfo> shared(frame->function()->shared());
1628 :
1629 : // With no debug info there are no break points, so we can't be at a return.
1630 99182 : if (!shared->HasDebugInfo()) return false;
1631 :
1632 : DCHECK(!frame->is_optimized());
1633 : Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1634 83491 : BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1635 83491 : return location.IsReturn() || location.IsTailCall();
1636 : }
1637 :
1638 442 : void Debug::ScheduleFrameRestart(StackFrame* frame) {
1639 : // Set a target FP for the FrameDropperTrampoline builtin to drop to once
1640 : // we return from the debugger.
1641 : DCHECK(frame->is_java_script());
1642 : // Only reschedule to a frame further below a frame we already scheduled for.
1643 884 : if (frame->fp() <= thread_local_.restart_fp_) return;
1644 : // If the frame is optimized, trigger a deopt and jump into the
1645 : // FrameDropperTrampoline in the deoptimizer.
1646 422 : thread_local_.restart_fp_ = frame->fp();
1647 :
1648 : // Reset break frame ID to the frame below the restarted frame.
1649 422 : StackTraceFrameIterator it(isolate_);
1650 422 : thread_local_.break_frame_id_ = StackFrame::NO_ID;
1651 9908 : for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1652 4954 : if (it.frame()->fp() > thread_local_.restart_fp_) {
1653 844 : thread_local_.break_frame_id_ = it.frame()->id();
1654 : return;
1655 : }
1656 : }
1657 : }
1658 :
1659 :
1660 1869 : bool Debug::IsDebugGlobal(JSGlobalObject* global) {
1661 65241 : return is_loaded() && global == debug_context()->global_object();
1662 : }
1663 :
1664 :
1665 2826 : Handle<FixedArray> Debug::GetLoadedScripts() {
1666 : isolate_->heap()->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
1667 2826 : GarbageCollectionReason::kDebugger);
1668 2826 : Factory* factory = isolate_->factory();
1669 2826 : if (!factory->script_list()->IsWeakFixedArray()) {
1670 : return factory->empty_fixed_array();
1671 : }
1672 : Handle<WeakFixedArray> array =
1673 : Handle<WeakFixedArray>::cast(factory->script_list());
1674 2826 : Handle<FixedArray> results = factory->NewFixedArray(array->Length());
1675 : int length = 0;
1676 : {
1677 2826 : Script::Iterator iterator(isolate_);
1678 : Script* script;
1679 81272 : while ((script = iterator.Next()) != nullptr) {
1680 151240 : if (script->HasValidSource()) results->set(length++, script);
1681 : }
1682 : }
1683 2826 : results->Shrink(length);
1684 2826 : return results;
1685 : }
1686 :
1687 :
1688 124842 : MaybeHandle<Object> Debug::MakeExecutionState() {
1689 : // Create the execution state object.
1690 124842 : Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
1691 124842 : return CallFunction("MakeExecutionState", arraysize(argv), argv);
1692 : }
1693 :
1694 :
1695 35444 : MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
1696 : // Create the new break event object.
1697 35444 : Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1698 35444 : break_points_hit };
1699 35444 : return CallFunction("MakeBreakEvent", arraysize(argv), argv);
1700 : }
1701 :
1702 :
1703 234 : MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
1704 : bool uncaught,
1705 234 : Handle<Object> promise) {
1706 : // Create the new exception event object.
1707 234 : Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1708 : exception,
1709 234 : isolate_->factory()->ToBoolean(uncaught),
1710 468 : promise };
1711 234 : return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
1712 : }
1713 :
1714 :
1715 4110 : MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1716 : v8::DebugEvent type) {
1717 : // Create the compile event object.
1718 4110 : Handle<Object> script_wrapper = Script::GetWrapper(script);
1719 : Handle<Object> argv[] = { script_wrapper,
1720 4110 : isolate_->factory()->NewNumberFromInt(type) };
1721 4110 : return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1722 : }
1723 :
1724 72 : MaybeHandle<Object> Debug::MakeAsyncTaskEvent(
1725 : v8::debug::PromiseDebugActionType type, int id) {
1726 : // Create the async task event object.
1727 : Handle<Object> argv[] = {Handle<Smi>(Smi::FromInt(type), isolate_),
1728 144 : Handle<Smi>(Smi::FromInt(id), isolate_)};
1729 72 : return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1730 : }
1731 :
1732 :
1733 2915872 : void Debug::OnThrow(Handle<Object> exception) {
1734 4377841 : if (in_debug_scope() || ignore_events()) return;
1735 : // Temporarily clear any scheduled_exception to allow evaluating
1736 : // JavaScript from the debug event handler.
1737 5167 : HandleScope scope(isolate_);
1738 : Handle<Object> scheduled_exception;
1739 5167 : if (isolate_->has_scheduled_exception()) {
1740 : scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1741 0 : isolate_->clear_scheduled_exception();
1742 : }
1743 5167 : OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1744 5167 : if (!scheduled_exception.is_null()) {
1745 0 : isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1746 : }
1747 5167 : PrepareStepOnThrow();
1748 : }
1749 :
1750 2440 : void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {
1751 3660 : if (in_debug_scope() || ignore_events()) return;
1752 1220 : HandleScope scope(isolate_);
1753 : // Check whether the promise has been marked as having triggered a message.
1754 : Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1755 3660 : if (!promise->IsJSObject() ||
1756 2268 : JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
1757 3316 : ->IsUndefined(isolate_)) {
1758 1186 : OnException(value, promise);
1759 : }
1760 : }
1761 :
1762 : namespace {
1763 113053 : v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
1764 : Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
1765 : // Isolate::context() may have been NULL when "script collected" event
1766 : // occured.
1767 113053 : if (context.is_null()) return v8::Local<v8::Context>();
1768 : Handle<Context> native_context(context->native_context());
1769 : return v8::Utils::ToLocal(native_context);
1770 : }
1771 : } // anonymous namespace
1772 :
1773 2956 : bool Debug::IsExceptionBlackboxed(bool uncaught) {
1774 : // Uncaught exception is blackboxed if all current frames are blackboxed,
1775 : // caught exception if top frame is blackboxed.
1776 2956 : StackTraceFrameIterator it(isolate_);
1777 8868 : while (!it.done() && it.is_wasm()) it.Advance();
1778 : bool is_top_frame_blackboxed =
1779 2956 : !it.done() ? IsFrameBlackboxed(it.javascript_frame()) : true;
1780 2956 : if (!uncaught || !is_top_frame_blackboxed) return is_top_frame_blackboxed;
1781 11 : return AllFramesOnStackAreBlackboxed();
1782 : }
1783 :
1784 37943 : bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
1785 37943 : HandleScope scope(isolate_);
1786 : List<Handle<SharedFunctionInfo>> infos;
1787 37943 : frame->GetFunctions(&infos);
1788 79046 : for (const auto& info : infos) {
1789 37955 : if (!IsBlackboxed(info)) return false;
1790 : }
1791 : return true;
1792 : }
1793 :
1794 6353 : void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1795 : // We cannot generate debug events when JS execution is disallowed.
1796 : // TODO(5530): Reenable debug events within DisallowJSScopes once relevant
1797 : // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++.
1798 9798 : if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
1799 :
1800 6321 : Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1801 :
1802 : // Don't notify listener of exceptions that are internal to a desugaring.
1803 6321 : if (catch_type == Isolate::CAUGHT_BY_DESUGARING) return;
1804 :
1805 6307 : bool uncaught = catch_type == Isolate::NOT_CAUGHT;
1806 6307 : if (promise->IsJSObject()) {
1807 : Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1808 : // Mark the promise as already having triggered a message.
1809 2864 : Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1810 2864 : JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
1811 : // Check whether the promise reject is considered an uncaught exception.
1812 2864 : uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
1813 : }
1814 :
1815 6307 : if (!debug_delegate_) return;
1816 :
1817 : // Bail out if exception breaks are not active
1818 6307 : if (uncaught) {
1819 : // Uncaught exceptions are reported by either flags.
1820 1962 : if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1821 : } else {
1822 : // Caught exceptions are reported is activated.
1823 4345 : if (!break_on_exception_) return;
1824 : }
1825 :
1826 : {
1827 3078 : JavaScriptFrameIterator it(isolate_);
1828 : // Check whether the top frame is blackboxed or the break location is muted.
1829 6034 : if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) ||
1830 2956 : IsExceptionBlackboxed(uncaught))) {
1831 : return;
1832 : }
1833 2932 : if (it.done()) return; // Do not trigger an event with an empty stack.
1834 : }
1835 :
1836 2908 : DebugScope debug_scope(this);
1837 2908 : if (debug_scope.failed()) return;
1838 2908 : HandleScope scope(isolate_);
1839 : PostponeInterruptsScope postpone(isolate_);
1840 : DisableBreak no_recursive_break(this);
1841 :
1842 : // Create the execution state.
1843 : Handle<Object> exec_state;
1844 : // Bail out and don't call debugger if exception.
1845 5816 : if (!MakeExecutionState().ToHandle(&exec_state)) return;
1846 :
1847 : debug_delegate_->ExceptionThrown(
1848 : GetDebugEventContext(isolate_),
1849 : v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1850 5816 : v8::Utils::ToLocal(exception), v8::Utils::ToLocal(promise), uncaught);
1851 : }
1852 :
1853 110001 : void Debug::OnDebugBreak(Handle<Object> break_points_hit) {
1854 : // The caller provided for DebugScope.
1855 : AssertDebugContext();
1856 : // Bail out if there is no listener for this event
1857 110001 : if (ignore_events()) return;
1858 :
1859 : #ifdef DEBUG
1860 : PrintBreakLocation();
1861 : #endif // DEBUG
1862 :
1863 110001 : if (!debug_delegate_) return;
1864 110001 : HandleScope scope(isolate_);
1865 : PostponeInterruptsScope no_interrupts(isolate_);
1866 : DisableBreak no_recursive_break(this);
1867 :
1868 : // Create the execution state.
1869 : Handle<Object> exec_state;
1870 : // Bail out and don't call debugger if exception.
1871 220002 : if (!MakeExecutionState().ToHandle(&exec_state)) return;
1872 :
1873 : debug_delegate_->BreakProgramRequested(
1874 : GetDebugEventContext(isolate_),
1875 : v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1876 110001 : v8::Utils::ToLocal(break_points_hit));
1877 : }
1878 :
1879 :
1880 376708 : void Debug::OnCompileError(Handle<Script> script) {
1881 376708 : ProcessCompileEvent(v8::CompileError, script);
1882 376708 : }
1883 :
1884 :
1885 : // Handle debugger actions when a new script is compiled.
1886 5654383 : void Debug::OnAfterCompile(Handle<Script> script) {
1887 5654383 : ProcessCompileEvent(v8::AfterCompile, script);
1888 5654394 : }
1889 :
1890 : namespace {
1891 : // In an async function, reuse the existing stack related to the outer
1892 : // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
1893 : // Promises with multiple reactions with one or more of them being async
1894 : // functions will not get a good stack trace, as async functions require
1895 : // different stacks from direct Promise use, but we save and restore a
1896 : // stack once for all reactions.
1897 : //
1898 : // If this isn't a case of async function, we return false, otherwise
1899 : // we set the correct id and return true.
1900 : //
1901 : // TODO(littledan): Improve this case.
1902 254884 : int GetReferenceAsyncTaskId(Isolate* isolate, Handle<JSPromise> promise) {
1903 : Handle<Symbol> handled_by_symbol =
1904 : isolate->factory()->promise_handled_by_symbol();
1905 : Handle<Object> handled_by_promise =
1906 137590 : JSObject::GetDataProperty(promise, handled_by_symbol);
1907 137590 : if (!handled_by_promise->IsJSPromise()) {
1908 108256 : return isolate->debug()->NextAsyncTaskId(promise);
1909 : }
1910 : Handle<JSPromise> handled_by_promise_js =
1911 : Handle<JSPromise>::cast(handled_by_promise);
1912 : Handle<Symbol> async_stack_id_symbol =
1913 : isolate->factory()->promise_async_stack_id_symbol();
1914 : Handle<Object> async_task_id =
1915 29334 : JSObject::GetDataProperty(handled_by_promise_js, async_stack_id_symbol);
1916 29334 : if (!async_task_id->IsSmi()) {
1917 9038 : return isolate->debug()->NextAsyncTaskId(promise);
1918 : }
1919 : return Handle<Smi>::cast(async_task_id)->value();
1920 : }
1921 : } // namespace
1922 :
1923 118660 : void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
1924 : Handle<Object> parent) {
1925 118660 : if (!debug_delegate_) return;
1926 118660 : int id = GetReferenceAsyncTaskId(isolate_, promise);
1927 118660 : switch (type) {
1928 : case PromiseHookType::kInit:
1929 : OnAsyncTaskEvent(debug::kDebugPromiseCreated, id,
1930 : parent->IsJSPromise()
1931 : ? GetReferenceAsyncTaskId(
1932 18930 : isolate_, Handle<JSPromise>::cast(parent))
1933 56372 : : 0);
1934 37442 : return;
1935 : case PromiseHookType::kResolve:
1936 : // We can't use this hook because it's called before promise object will
1937 : // get resolved status.
1938 : return;
1939 : case PromiseHookType::kBefore:
1940 18990 : OnAsyncTaskEvent(debug::kDebugWillHandle, id, 0);
1941 18990 : return;
1942 : case PromiseHookType::kAfter:
1943 18990 : OnAsyncTaskEvent(debug::kDebugDidHandle, id, 0);
1944 18990 : return;
1945 : }
1946 : }
1947 :
1948 162002 : int Debug::NextAsyncTaskId(Handle<JSObject> promise) {
1949 324004 : LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol());
1950 162002 : Maybe<bool> maybe = JSReceiver::HasProperty(&it);
1951 162002 : if (maybe.ToChecked()) {
1952 124560 : MaybeHandle<Object> result = Object::GetProperty(&it);
1953 : return Handle<Smi>::cast(result.ToHandleChecked())->value();
1954 : }
1955 : Handle<Smi> async_id =
1956 37442 : handle(Smi::FromInt(++thread_local_.async_task_count_), isolate_);
1957 37442 : Object::SetProperty(&it, async_id, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED)
1958 74884 : .ToChecked();
1959 37442 : return async_id->value();
1960 : }
1961 :
1962 : namespace {
1963 39882 : debug::Location GetDebugLocation(Handle<Script> script, int source_position) {
1964 : Script::PositionInfo info;
1965 39882 : Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
1966 39882 : return debug::Location(info.line, info.column);
1967 : }
1968 : } // namespace
1969 :
1970 207540 : bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
1971 207540 : if (!debug_delegate_) return !shared->IsSubjectToDebugging();
1972 207540 : if (!shared->computed_debug_is_blackboxed()) {
1973 : bool is_blackboxed =
1974 41677 : !shared->IsSubjectToDebugging() || !shared->script()->IsScript();
1975 21736 : if (!is_blackboxed) {
1976 : SuppressDebug while_processing(this);
1977 19941 : HandleScope handle_scope(isolate_);
1978 : PostponeInterruptsScope no_interrupts(isolate_);
1979 : DisableBreak no_recursive_break(this);
1980 : DCHECK(shared->script()->IsScript());
1981 : Handle<Script> script(Script::cast(shared->script()));
1982 : DCHECK(script->IsUserJavaScript());
1983 : debug::Location start =
1984 19941 : GetDebugLocation(script, shared->start_position());
1985 19941 : debug::Location end = GetDebugLocation(script, shared->end_position());
1986 : is_blackboxed = debug_delegate_->IsFunctionBlackboxed(
1987 19941 : ToApiHandle<debug::Script>(script), start, end);
1988 : }
1989 43472 : shared->set_debug_is_blackboxed(is_blackboxed);
1990 21736 : shared->set_computed_debug_is_blackboxed(true);
1991 : }
1992 207540 : return shared->debug_is_blackboxed();
1993 : }
1994 :
1995 221 : bool Debug::AllFramesOnStackAreBlackboxed() {
1996 221 : HandleScope scope(isolate_);
1997 818 : for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1998 391 : if (!IsFrameBlackboxed(it.javascript_frame())) return false;
1999 : }
2000 18 : return true;
2001 : }
2002 :
2003 120130 : void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
2004 119650 : int parent_id) {
2005 240260 : if (in_debug_scope() || ignore_events()) return;
2006 119650 : if (!debug_delegate_) return;
2007 : SuppressDebug while_processing(this);
2008 119650 : PostponeInterruptsScope no_interrupts(isolate_);
2009 : DisableBreak no_recursive_break(this);
2010 : bool created_by_user = false;
2011 119650 : if (type == debug::kDebugPromiseCreated) {
2012 37004 : JavaScriptFrameIterator it(isolate_);
2013 : // We need to skip top frame which contains instrumentation.
2014 37004 : it.Advance();
2015 : created_by_user =
2016 71600 : !it.done() &&
2017 34596 : !IsFrameBlackboxed(it.frame());
2018 : }
2019 119650 : debug_delegate_->PromiseEventOccurred(type, id, parent_id, created_by_user);
2020 : }
2021 :
2022 12062195 : void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
2023 : // Attach the correct debug id to the script. The debug id is used by the
2024 : // inspector to filter scripts by native context.
2025 12062195 : script->set_context_data(isolate_->native_context()->debug_context_id());
2026 12033371 : if (ignore_events()) return;
2027 45265 : if (!script->IsUserJavaScript() && script->type() != i::Script::TYPE_WASM) {
2028 : return;
2029 : }
2030 28833 : if (!debug_delegate_) return;
2031 : SuppressDebug while_processing(this);
2032 57666 : DebugScope debug_scope(this);
2033 28833 : if (debug_scope.failed()) return;
2034 28833 : HandleScope scope(isolate_);
2035 : PostponeInterruptsScope postpone(isolate_);
2036 : DisableBreak no_recursive_break(this);
2037 : debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
2038 28833 : event != v8::AfterCompile);
2039 : }
2040 :
2041 :
2042 160252 : Handle<Context> Debug::GetDebugContext() {
2043 160252 : if (!is_loaded()) return Handle<Context>();
2044 160252 : DebugScope debug_scope(this);
2045 160252 : if (debug_scope.failed()) return Handle<Context>();
2046 : // The global handle may be destroyed soon after. Return it reboxed.
2047 320504 : return handle(*debug_context(), isolate_);
2048 : }
2049 :
2050 1119024 : int Debug::CurrentFrameCount() {
2051 177006 : StackTraceFrameIterator it(isolate_);
2052 177006 : if (break_frame_id() != StackFrame::NO_ID) {
2053 : // Skip to break frame.
2054 : DCHECK(in_debug_scope());
2055 2118990 : while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
2056 : }
2057 : int counter = 0;
2058 497185 : while (!it.done()) {
2059 640358 : if (it.frame()->is_optimized()) {
2060 : List<SharedFunctionInfo*> infos;
2061 12971 : OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
2062 12971 : counter += infos.length();
2063 : } else {
2064 307208 : counter++;
2065 : }
2066 320179 : it.Advance();
2067 : }
2068 177006 : return counter;
2069 : }
2070 :
2071 10127 : void Debug::SetDebugDelegate(debug::DebugDelegate* delegate,
2072 : bool pass_ownership) {
2073 10127 : RemoveDebugDelegate();
2074 10127 : debug_delegate_ = delegate;
2075 10127 : owns_debug_delegate_ = pass_ownership;
2076 10127 : UpdateState();
2077 10127 : }
2078 :
2079 74655 : void Debug::RemoveDebugDelegate() {
2080 149310 : if (debug_delegate_ == nullptr) return;
2081 5127 : if (owns_debug_delegate_) {
2082 753 : owns_debug_delegate_ = false;
2083 753 : delete debug_delegate_;
2084 : }
2085 5127 : debug_delegate_ = nullptr;
2086 : }
2087 :
2088 674297 : void Debug::UpdateState() {
2089 674297 : bool is_active = debug_delegate_ != nullptr;
2090 683254 : if (is_active || in_debug_scope()) {
2091 : // Note that the debug context could have already been loaded to
2092 : // bootstrap test cases.
2093 672691 : isolate_->compilation_cache()->Disable();
2094 667448 : is_active = Load();
2095 6849 : } else if (is_loaded()) {
2096 10486 : isolate_->compilation_cache()->Enable();
2097 5243 : Unload();
2098 : }
2099 674297 : is_active_ = is_active;
2100 674297 : isolate_->DebugStateUpdated();
2101 674297 : }
2102 :
2103 20101 : void Debug::UpdateHookOnFunctionCall() {
2104 : STATIC_ASSERT(LastStepAction == StepIn);
2105 645159 : hook_on_function_call_ = thread_local_.last_step_action_ == StepIn ||
2106 894696 : isolate_->needs_side_effect_check();
2107 20101 : }
2108 :
2109 7751 : MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2110 7751 : DebugScope debug_scope(this);
2111 7751 : if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2112 :
2113 : // Create the execution state.
2114 : Handle<Object> exec_state;
2115 15502 : if (!MakeExecutionState().ToHandle(&exec_state)) {
2116 0 : return isolate_->factory()->undefined_value();
2117 : }
2118 :
2119 7751 : Handle<Object> argv[] = { exec_state, data };
2120 : return Execution::Call(
2121 : isolate_,
2122 : fun,
2123 7751 : Handle<Object>(debug_context()->global_proxy(), isolate_),
2124 : arraysize(argv),
2125 15502 : argv);
2126 : }
2127 :
2128 538701 : void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
2129 : // Initialize LiveEdit.
2130 179602 : LiveEdit::InitializeThreadLocal(this);
2131 : // Ignore debug break during bootstrapping.
2132 327721 : if (isolate_->bootstrapper()->IsActive()) return;
2133 : // Just continue if breaks are disabled.
2134 179590 : if (break_disabled()) return;
2135 : // Ignore debug break if debugger is not active.
2136 179509 : if (!is_active()) return;
2137 :
2138 : StackLimitCheck check(isolate_);
2139 32853 : if (check.HasOverflowed()) return;
2140 :
2141 32853 : { JavaScriptFrameIterator it(isolate_);
2142 : DCHECK(!it.done());
2143 32853 : Object* fun = it.frame()->function();
2144 65706 : if (fun && fun->IsJSFunction()) {
2145 32853 : HandleScope scope(isolate_);
2146 : // Don't stop in builtin and blackboxed functions.
2147 : Handle<SharedFunctionInfo> shared(JSFunction::cast(fun)->shared(),
2148 : isolate_);
2149 : bool ignore_break = ignore_break_mode == kIgnoreIfTopFrameBlackboxed
2150 : ? IsBlackboxed(shared)
2151 32853 : : AllFramesOnStackAreBlackboxed();
2152 32853 : if (ignore_break) {
2153 : // Inspector uses pause on next statement for asynchronous breakpoints.
2154 : // When breakpoint is fired we try to break on first not blackboxed
2155 : // statement. To achieve this goal we need to deoptimize current
2156 : // function and don't clear requested DebugBreak even if it's blackboxed
2157 : // to be able to break on not blackboxed function call.
2158 : // TODO(yangguo): introduce break_on_function_entry since current
2159 : // implementation is slow.
2160 2684 : if (isolate_->stack_guard()->CheckDebugBreak()) {
2161 1330 : Deoptimizer::DeoptimizeFunction(JSFunction::cast(fun));
2162 : }
2163 : return;
2164 : }
2165 : JSGlobalObject* global =
2166 31511 : JSFunction::cast(fun)->context()->global_object();
2167 : // Don't stop in debugger functions.
2168 31511 : if (IsDebugGlobal(global)) return;
2169 : // Don't stop if the break location is muted.
2170 31511 : if (IsMutedAtCurrentLocation(it.frame())) return;
2171 : }
2172 : }
2173 :
2174 31483 : isolate_->stack_guard()->ClearDebugBreak();
2175 :
2176 : // Clear stepping to avoid duplicate breaks.
2177 31483 : ClearStepping();
2178 :
2179 31483 : HandleScope scope(isolate_);
2180 62966 : DebugScope debug_scope(this);
2181 31483 : if (debug_scope.failed()) return;
2182 :
2183 62966 : OnDebugBreak(isolate_->factory()->undefined_value());
2184 : }
2185 :
2186 : #ifdef DEBUG
2187 : void Debug::PrintBreakLocation() {
2188 : if (!FLAG_print_break_location) return;
2189 : HandleScope scope(isolate_);
2190 : StackTraceFrameIterator iterator(isolate_);
2191 : if (iterator.done()) return;
2192 : StandardFrame* frame = iterator.frame();
2193 : FrameSummary summary = FrameSummary::GetTop(frame);
2194 : int source_position = summary.SourcePosition();
2195 : Handle<Object> script_obj = summary.script();
2196 : PrintF("[debug] break in function '");
2197 : summary.FunctionName()->PrintOn(stdout);
2198 : PrintF("'.\n");
2199 : if (script_obj->IsScript()) {
2200 : Handle<Script> script = Handle<Script>::cast(script_obj);
2201 : Handle<String> source(String::cast(script->source()));
2202 : Script::InitLineEnds(script);
2203 : int line =
2204 : Script::GetLineNumber(script, source_position) - script->line_offset();
2205 : int column = Script::GetColumnNumber(script, source_position) -
2206 : (line == 0 ? script->column_offset() : 0);
2207 : Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
2208 : int line_start =
2209 : line == 0 ? 0 : Smi::cast(line_ends->get(line - 1))->value() + 1;
2210 : int line_end = Smi::cast(line_ends->get(line))->value();
2211 : DisallowHeapAllocation no_gc;
2212 : String::FlatContent content = source->GetFlatContent();
2213 : if (content.IsOneByte()) {
2214 : PrintF("[debug] %.*s\n", line_end - line_start,
2215 : content.ToOneByteVector().start() + line_start);
2216 : PrintF("[debug] ");
2217 : for (int i = 0; i < column; i++) PrintF(" ");
2218 : PrintF("^\n");
2219 : } else {
2220 : PrintF("[debug] at line %d column %d\n", line, column);
2221 : }
2222 : }
2223 : }
2224 : #endif // DEBUG
2225 :
2226 332085 : DebugScope::DebugScope(Debug* debug)
2227 : : debug_(debug),
2228 : prev_(debug->debugger_entry()),
2229 : save_(debug_->isolate_),
2230 : no_termination_exceptons_(debug_->isolate_,
2231 1328340 : StackGuard::TERMINATE_EXECUTION) {
2232 : // Link recursive debugger entry.
2233 : base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2234 332085 : reinterpret_cast<base::AtomicWord>(this));
2235 :
2236 : // Store the previous break id, frame id and return value.
2237 664170 : break_id_ = debug_->break_id();
2238 332085 : break_frame_id_ = debug_->break_frame_id();
2239 :
2240 : // Create the new break info. If there is no proper frames there is no break
2241 : // frame id.
2242 332085 : StackTraceFrameIterator it(isolate());
2243 : bool has_frames = !it.done();
2244 : debug_->thread_local_.break_frame_id_ =
2245 664170 : has_frames ? it.frame()->id() : StackFrame::NO_ID;
2246 332085 : debug_->SetNextBreakId();
2247 :
2248 332085 : debug_->UpdateState();
2249 : // Make sure that debugger is loaded and enter the debugger context.
2250 : // The previous context is kept in save_.
2251 664170 : failed_ = !debug_->is_loaded();
2252 332085 : if (!failed_) isolate()->set_context(*debug->debug_context());
2253 332085 : }
2254 :
2255 :
2256 664170 : DebugScope::~DebugScope() {
2257 : // Leaving this debugger entry.
2258 : base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2259 332085 : reinterpret_cast<base::AtomicWord>(prev_));
2260 :
2261 : // Restore to the previous break state.
2262 332085 : debug_->thread_local_.break_frame_id_ = break_frame_id_;
2263 332085 : debug_->thread_local_.break_id_ = break_id_;
2264 :
2265 332085 : debug_->UpdateState();
2266 332085 : }
2267 :
2268 90822 : ReturnValueScope::ReturnValueScope(Debug* debug) : debug_(debug) {
2269 90822 : return_value_ = debug_->return_value_handle();
2270 90822 : }
2271 :
2272 90822 : ReturnValueScope::~ReturnValueScope() {
2273 90822 : debug_->set_return_value(*return_value_);
2274 90822 : }
2275 :
2276 14088 : bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) {
2277 : DCHECK(isolate_->needs_side_effect_check());
2278 14088 : DisallowJavascriptExecution no_js(isolate_);
2279 14088 : if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false;
2280 14088 : Deoptimizer::DeoptimizeFunction(*function);
2281 14088 : if (!function->shared()->HasNoSideEffect()) {
2282 4278 : if (FLAG_trace_side_effect_free_debug_evaluate) {
2283 : PrintF("[debug-evaluate] Function %s failed side effect check.\n",
2284 0 : function->shared()->DebugName()->ToCString().get());
2285 : }
2286 4278 : side_effect_check_failed_ = true;
2287 : // Throw an uncatchable termination exception.
2288 4278 : isolate_->TerminateExecution();
2289 4278 : return false;
2290 : }
2291 14088 : return true;
2292 : }
2293 :
2294 266 : bool Debug::PerformSideEffectCheckForCallback(Address function) {
2295 : DCHECK(isolate_->needs_side_effect_check());
2296 266 : if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true;
2297 14 : side_effect_check_failed_ = true;
2298 : // Throw an uncatchable termination exception.
2299 14 : isolate_->TerminateExecution();
2300 14 : isolate_->OptionalRescheduleException(false);
2301 14 : return false;
2302 : }
2303 :
2304 72 : void LegacyDebugDelegate::PromiseEventOccurred(
2305 : v8::debug::PromiseDebugActionType type, int id, int parent_id,
2306 : bool created_by_user) {
2307 144 : DebugScope debug_scope(isolate_->debug());
2308 72 : if (debug_scope.failed()) return;
2309 72 : HandleScope scope(isolate_);
2310 : Handle<Object> event_data;
2311 144 : if (isolate_->debug()->MakeAsyncTaskEvent(type, id).ToHandle(&event_data)) {
2312 72 : ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
2313 72 : }
2314 : }
2315 :
2316 4110 : void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script,
2317 : bool is_compile_error) {
2318 : Handle<Object> event_data;
2319 4110 : v8::DebugEvent event = is_compile_error ? v8::CompileError : v8::AfterCompile;
2320 4110 : if (isolate_->debug()
2321 : ->MakeCompileEvent(v8::Utils::OpenHandle(*script), event)
2322 8220 : .ToHandle(&event_data)) {
2323 4110 : ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
2324 : }
2325 4110 : }
2326 :
2327 35444 : void LegacyDebugDelegate::BreakProgramRequested(
2328 : v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
2329 : v8::Local<v8::Value> break_points_hit) {
2330 : Handle<Object> event_data;
2331 35444 : if (isolate_->debug()
2332 : ->MakeBreakEvent(v8::Utils::OpenHandle(*break_points_hit))
2333 70888 : .ToHandle(&event_data)) {
2334 : ProcessDebugEvent(
2335 : v8::Break, Handle<JSObject>::cast(event_data),
2336 70888 : Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
2337 : }
2338 35444 : }
2339 :
2340 234 : void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context,
2341 : v8::Local<v8::Object> exec_state,
2342 : v8::Local<v8::Value> exception,
2343 : v8::Local<v8::Value> promise,
2344 : bool is_uncaught) {
2345 : Handle<Object> event_data;
2346 234 : if (isolate_->debug()
2347 : ->MakeExceptionEvent(v8::Utils::OpenHandle(*exception), is_uncaught,
2348 : v8::Utils::OpenHandle(*promise))
2349 702 : .ToHandle(&event_data)) {
2350 : ProcessDebugEvent(
2351 : v8::Exception, Handle<JSObject>::cast(event_data),
2352 468 : Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
2353 : }
2354 234 : }
2355 :
2356 4182 : void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2357 : Handle<JSObject> event_data) {
2358 : Handle<Object> exec_state;
2359 8364 : if (isolate_->debug()->MakeExecutionState().ToHandle(&exec_state)) {
2360 4182 : ProcessDebugEvent(event, event_data, Handle<JSObject>::cast(exec_state));
2361 : }
2362 4182 : }
2363 :
2364 210 : JavaScriptDebugDelegate::JavaScriptDebugDelegate(Isolate* isolate,
2365 : Handle<JSFunction> listener,
2366 : Handle<Object> data)
2367 105 : : LegacyDebugDelegate(isolate) {
2368 : GlobalHandles* global_handles = isolate->global_handles();
2369 105 : listener_ = global_handles->Create(*listener);
2370 105 : data_ = global_handles->Create(*data);
2371 105 : }
2372 :
2373 210 : JavaScriptDebugDelegate::~JavaScriptDebugDelegate() {
2374 105 : GlobalHandles::Destroy(Handle<Object>::cast(listener_).location());
2375 105 : GlobalHandles::Destroy(data_.location());
2376 210 : }
2377 :
2378 120 : void JavaScriptDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2379 : Handle<JSObject> event_data,
2380 : Handle<JSObject> exec_state) {
2381 120 : Handle<Object> argv[] = {Handle<Object>(Smi::FromInt(event), isolate_),
2382 240 : exec_state, event_data, data_};
2383 120 : Handle<JSReceiver> global = isolate_->global_proxy();
2384 : // Listener must not throw.
2385 : Execution::Call(isolate_, listener_, global, arraysize(argv), argv)
2386 240 : .ToHandleChecked();
2387 120 : }
2388 :
2389 1296 : NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate,
2390 : v8::Debug::EventCallback callback,
2391 : Handle<Object> data)
2392 648 : : LegacyDebugDelegate(isolate), callback_(callback) {
2393 648 : data_ = isolate->global_handles()->Create(*data);
2394 648 : }
2395 :
2396 648 : NativeDebugDelegate::~NativeDebugDelegate() {
2397 648 : GlobalHandles::Destroy(data_.location());
2398 648 : }
2399 :
2400 0 : NativeDebugDelegate::EventDetails::EventDetails(DebugEvent event,
2401 : Handle<JSObject> exec_state,
2402 : Handle<JSObject> event_data,
2403 : Handle<Object> callback_data)
2404 : : event_(event),
2405 : exec_state_(exec_state),
2406 : event_data_(event_data),
2407 39740 : callback_data_(callback_data) {}
2408 :
2409 33708 : DebugEvent NativeDebugDelegate::EventDetails::GetEvent() const {
2410 33708 : return event_;
2411 : }
2412 :
2413 2347 : v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetExecutionState()
2414 : const {
2415 2347 : return v8::Utils::ToLocal(exec_state_);
2416 : }
2417 :
2418 336 : v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetEventData() const {
2419 336 : return v8::Utils::ToLocal(event_data_);
2420 : }
2421 :
2422 144 : v8::Local<v8::Context> NativeDebugDelegate::EventDetails::GetEventContext()
2423 : const {
2424 144 : return GetDebugEventContext(exec_state_->GetIsolate());
2425 : }
2426 :
2427 18 : v8::Local<v8::Value> NativeDebugDelegate::EventDetails::GetCallbackData()
2428 : const {
2429 18 : return v8::Utils::ToLocal(callback_data_);
2430 : }
2431 :
2432 12 : v8::Isolate* NativeDebugDelegate::EventDetails::GetIsolate() const {
2433 12 : return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2434 : }
2435 :
2436 39740 : void NativeDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2437 : Handle<JSObject> event_data,
2438 : Handle<JSObject> exec_state) {
2439 : EventDetails event_details(event, exec_state, event_data, data_);
2440 39740 : Isolate* isolate = isolate_;
2441 39740 : callback_(event_details);
2442 39740 : CHECK(!isolate->has_scheduled_exception());
2443 39740 : }
2444 :
2445 20101 : NoSideEffectScope::~NoSideEffectScope() {
2446 60303 : if (isolate_->needs_side_effect_check() &&
2447 : isolate_->debug()->side_effect_check_failed_) {
2448 : DCHECK(isolate_->has_pending_exception());
2449 : DCHECK_EQ(isolate_->heap()->termination_exception(),
2450 : isolate_->pending_exception());
2451 : // Convert the termination exception into a regular exception.
2452 4292 : isolate_->CancelTerminateExecution();
2453 : isolate_->Throw(*isolate_->factory()->NewEvalError(
2454 8584 : MessageTemplate::kNoSideEffectDebugEvaluate));
2455 : }
2456 20101 : isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2457 : isolate_->debug()->UpdateHookOnFunctionCall();
2458 20101 : isolate_->debug()->side_effect_check_failed_ = false;
2459 20101 : }
2460 :
2461 : } // namespace internal
2462 : } // namespace v8
|