V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
debug.cc
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 #include <unordered_set>
9 
10 #include "src/api-inl.h"
11 #include "src/arguments.h"
12 #include "src/assembler-inl.h"
13 #include "src/base/platform/mutex.h"
14 #include "src/bootstrapper.h"
15 #include "src/builtins/builtins.h"
16 #include "src/code-stubs.h"
17 #include "src/compilation-cache.h"
18 #include "src/compiler.h"
19 #include "src/counters.h"
20 #include "src/debug/debug-evaluate.h"
21 #include "src/debug/liveedit.h"
22 #include "src/deoptimizer.h"
23 #include "src/execution.h"
24 #include "src/frames-inl.h"
25 #include "src/global-handles.h"
26 #include "src/globals.h"
27 #include "src/interpreter/bytecode-array-accessor.h"
28 #include "src/interpreter/bytecode-array-iterator.h"
29 #include "src/interpreter/interpreter.h"
30 #include "src/isolate-inl.h"
31 #include "src/log.h"
32 #include "src/message-template.h"
33 #include "src/objects/api-callbacks-inl.h"
34 #include "src/objects/debug-objects-inl.h"
35 #include "src/objects/js-generator-inl.h"
36 #include "src/objects/js-promise-inl.h"
37 #include "src/objects/slots.h"
38 #include "src/snapshot/natives.h"
39 #include "src/snapshot/snapshot.h"
40 #include "src/wasm/wasm-objects-inl.h"
41 
42 namespace v8 {
43 namespace internal {
44 
46  public:
47  TemporaryObjectsTracker() = default;
48  ~TemporaryObjectsTracker() override = default;
49 
50  void AllocationEvent(Address addr, int) override { objects_.insert(addr); }
51 
52  void MoveEvent(Address from, Address to, int) override {
53  if (from == to) return;
54  base::MutexGuard guard(&mutex_);
55  auto it = objects_.find(from);
56  if (it == objects_.end()) {
57  // If temporary object was collected we can get MoveEvent which moves
58  // existing non temporary object to the address where we had temporary
59  // object. So we should mark new address as non temporary.
60  objects_.erase(to);
61  return;
62  }
63  objects_.erase(it);
64  objects_.insert(to);
65  }
66 
67  bool HasObject(Handle<HeapObject> obj) const {
68  if (obj->IsJSObject() &&
69  Handle<JSObject>::cast(obj)->GetEmbedderFieldCount()) {
70  // Embedder may store any pointers using embedder fields and implements
71  // non trivial logic, e.g. create wrappers lazily and store pointer to
72  // native object inside embedder field. We should consider all objects
73  // with embedder fields as non temporary.
74  return false;
75  }
76  return objects_.find(obj->address()) != objects_.end();
77  }
78 
79  private:
80  std::unordered_set<Address> objects_;
81  base::Mutex mutex_;
82  DISALLOW_COPY_AND_ASSIGN(TemporaryObjectsTracker);
83 };
84 
85 Debug::Debug(Isolate* isolate)
86  : is_active_(false),
87  hook_on_function_call_(false),
88  is_suppressed_(false),
89  break_disabled_(false),
90  break_points_active_(true),
91  break_on_exception_(false),
92  break_on_uncaught_exception_(false),
93  side_effect_check_failed_(false),
94  debug_info_list_(nullptr),
95  feature_tracker_(isolate),
96  isolate_(isolate) {
97  ThreadInit();
98 }
99 
100 Debug::~Debug() { DCHECK_NULL(debug_delegate_); }
101 
102 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
103  JavaScriptFrame* frame) {
104  if (debug_info->CanBreakAtEntry()) {
105  return BreakLocation(Debug::kBreakAtEntryPosition, DEBUG_BREAK_AT_ENTRY);
106  }
107  auto summary = FrameSummary::GetTop(frame).AsJavaScript();
108  int offset = summary.code_offset();
109  Handle<AbstractCode> abstract_code = summary.abstract_code();
110  BreakIterator it(debug_info);
111  it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
112  return it.GetBreakLocation();
113 }
114 
115 void BreakLocation::AllAtCurrentStatement(
116  Handle<DebugInfo> debug_info, JavaScriptFrame* frame,
117  std::vector<BreakLocation>* result_out) {
118  DCHECK(!debug_info->CanBreakAtEntry());
119  auto summary = FrameSummary::GetTop(frame).AsJavaScript();
120  int offset = summary.code_offset();
121  Handle<AbstractCode> abstract_code = summary.abstract_code();
122  if (abstract_code->IsCode()) offset = offset - 1;
123  int statement_position;
124  {
125  BreakIterator it(debug_info);
126  it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
127  statement_position = it.statement_position();
128  }
129  for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
130  if (it.statement_position() == statement_position) {
131  result_out->push_back(it.GetBreakLocation());
132  }
133  }
134 }
135 
136 JSGeneratorObject* BreakLocation::GetGeneratorObjectForSuspendedFrame(
137  JavaScriptFrame* frame) const {
138  DCHECK(IsSuspend());
139  DCHECK_GE(generator_obj_reg_index_, 0);
140 
141  Object* generator_obj =
142  InterpretedFrame::cast(frame)->ReadInterpreterRegister(
143  generator_obj_reg_index_);
144 
145  return JSGeneratorObject::cast(generator_obj);
146 }
147 
148 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
149  Handle<AbstractCode> abstract_code,
150  int offset) {
151  // Run through all break points to locate the one closest to the address.
152  int closest_break = 0;
153  int distance = kMaxInt;
154  DCHECK(0 <= offset && offset < abstract_code->Size());
155  for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
156  // Check if this break point is closer that what was previously found.
157  if (it.code_offset() <= offset && offset - it.code_offset() < distance) {
158  closest_break = it.break_index();
159  distance = offset - it.code_offset();
160  // Check whether we can't get any closer.
161  if (distance == 0) break;
162  }
163  }
164  return closest_break;
165 }
166 
167 bool BreakLocation::HasBreakPoint(Isolate* isolate,
168  Handle<DebugInfo> debug_info) const {
169  // First check whether there is a break point with the same source position.
170  if (!debug_info->HasBreakPoint(isolate, position_)) return false;
171  if (debug_info->CanBreakAtEntry()) {
172  DCHECK_EQ(Debug::kBreakAtEntryPosition, position_);
173  return debug_info->BreakAtEntry();
174  } else {
175  // Then check whether a break point at that source position would have
176  // the same code offset. Otherwise it's just a break location that we can
177  // step to, but not actually a location where we can put a break point.
178  DCHECK(abstract_code_->IsBytecodeArray());
179  BreakIterator it(debug_info);
180  it.SkipToPosition(position_);
181  return it.code_offset() == code_offset_;
182  }
183 }
184 
185 debug::BreakLocationType BreakLocation::type() const {
186  switch (type_) {
187  case DEBUGGER_STATEMENT:
188  return debug::kDebuggerStatementBreakLocation;
189  case DEBUG_BREAK_SLOT_AT_CALL:
190  return debug::kCallBreakLocation;
191  case DEBUG_BREAK_SLOT_AT_RETURN:
192  return debug::kReturnBreakLocation;
193 
194  // Externally, suspend breaks should look like normal breaks.
195  case DEBUG_BREAK_SLOT_AT_SUSPEND:
196  default:
197  return debug::kCommonBreakLocation;
198  }
199 }
200 
201 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
202  : debug_info_(debug_info),
203  break_index_(-1),
204  source_position_iterator_(
205  debug_info->DebugBytecodeArray()->SourcePositionTable()) {
206  position_ = debug_info->shared()->StartPosition();
207  statement_position_ = position_;
208  // There is at least one break location.
209  DCHECK(!Done());
210  Next();
211 }
212 
213 int BreakIterator::BreakIndexFromPosition(int source_position) {
214  int distance = kMaxInt;
215  int closest_break = break_index();
216  while (!Done()) {
217  int next_position = position();
218  if (source_position <= next_position &&
219  next_position - source_position < distance) {
220  closest_break = break_index();
221  distance = next_position - source_position;
222  // Check whether we can't get any closer.
223  if (distance == 0) break;
224  }
225  Next();
226  }
227  return closest_break;
228 }
229 
230 void BreakIterator::Next() {
231  DisallowHeapAllocation no_gc;
232  DCHECK(!Done());
233  bool first = break_index_ == -1;
234  while (!Done()) {
235  if (!first) source_position_iterator_.Advance();
236  first = false;
237  if (Done()) return;
238  position_ = source_position_iterator_.source_position().ScriptOffset();
239  if (source_position_iterator_.is_statement()) {
240  statement_position_ = position_;
241  }
242  DCHECK_LE(0, position_);
243  DCHECK_LE(0, statement_position_);
244 
245  DebugBreakType type = GetDebugBreakType();
246  if (type != NOT_DEBUG_BREAK) break;
247  }
248  break_index_++;
249 }
250 
251 DebugBreakType BreakIterator::GetDebugBreakType() {
252  BytecodeArray bytecode_array = debug_info_->OriginalBytecodeArray();
253  interpreter::Bytecode bytecode =
254  interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
255 
256  // Make sure we read the actual bytecode, not a prefix scaling bytecode.
257  if (interpreter::Bytecodes::IsPrefixScalingBytecode(bytecode)) {
258  bytecode = interpreter::Bytecodes::FromByte(
259  bytecode_array->get(code_offset() + 1));
260  }
261 
262  if (bytecode == interpreter::Bytecode::kDebugger) {
263  return DEBUGGER_STATEMENT;
264  } else if (bytecode == interpreter::Bytecode::kReturn) {
265  return DEBUG_BREAK_SLOT_AT_RETURN;
266  } else if (bytecode == interpreter::Bytecode::kSuspendGenerator) {
267  return DEBUG_BREAK_SLOT_AT_SUSPEND;
268  } else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) {
269  return DEBUG_BREAK_SLOT_AT_CALL;
270  } else if (source_position_iterator_.is_statement()) {
271  return DEBUG_BREAK_SLOT;
272  } else {
273  return NOT_DEBUG_BREAK;
274  }
275 }
276 
277 void BreakIterator::SkipToPosition(int position) {
278  BreakIterator it(debug_info_);
279  SkipTo(it.BreakIndexFromPosition(position));
280 }
281 
282 void BreakIterator::SetDebugBreak() {
283  DebugBreakType debug_break_type = GetDebugBreakType();
284  if (debug_break_type == DEBUGGER_STATEMENT) return;
285  HandleScope scope(isolate());
286  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
287  Handle<BytecodeArray> bytecode_array(debug_info_->DebugBytecodeArray(),
288  isolate());
289  interpreter::BytecodeArrayAccessor(bytecode_array, code_offset())
290  .ApplyDebugBreak();
291 }
292 
293 void BreakIterator::ClearDebugBreak() {
294  DebugBreakType debug_break_type = GetDebugBreakType();
295  if (debug_break_type == DEBUGGER_STATEMENT) return;
296  DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
297  BytecodeArray bytecode_array = debug_info_->DebugBytecodeArray();
298  BytecodeArray original = debug_info_->OriginalBytecodeArray();
299  bytecode_array->set(code_offset(), original->get(code_offset()));
300 }
301 
302 BreakLocation BreakIterator::GetBreakLocation() {
303  Handle<AbstractCode> code(
304  AbstractCode::cast(debug_info_->DebugBytecodeArray()), isolate());
305  DebugBreakType type = GetDebugBreakType();
306  int generator_object_reg_index = -1;
307  if (type == DEBUG_BREAK_SLOT_AT_SUSPEND) {
308  // For suspend break, we'll need the generator object to be able to step
309  // over the suspend as if it didn't return. We get the interpreter register
310  // index that holds the generator object by reading it directly off the
311  // bytecode array, and we'll read the actual generator object off the
312  // interpreter stack frame in GetGeneratorObjectForSuspendedFrame.
313  BytecodeArray bytecode_array = debug_info_->OriginalBytecodeArray();
314  interpreter::BytecodeArrayAccessor accessor(
315  handle(bytecode_array, isolate()), code_offset());
316 
317  DCHECK_EQ(accessor.current_bytecode(),
318  interpreter::Bytecode::kSuspendGenerator);
319  interpreter::Register generator_obj_reg = accessor.GetRegisterOperand(0);
320  generator_object_reg_index = generator_obj_reg.index();
321  }
322  return BreakLocation(code, type, code_offset(), position_,
323  generator_object_reg_index);
324 }
325 
326 Isolate* BreakIterator::isolate() { return debug_info_->GetIsolate(); }
327 
328 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
329  uint32_t mask = 1 << feature;
330  // Only count one sample per feature and isolate.
331  if (bitfield_ & mask) return;
332  isolate_->counters()->debug_feature_usage()->AddSample(feature);
333  bitfield_ |= mask;
334 }
335 
336 
337 // Threading support.
338 void Debug::ThreadInit() {
339  thread_local_.break_frame_id_ = StackFrame::NO_ID;
340  thread_local_.last_step_action_ = StepNone;
341  thread_local_.last_statement_position_ = kNoSourcePosition;
342  thread_local_.last_frame_count_ = -1;
343  thread_local_.fast_forward_to_return_ = false;
344  thread_local_.ignore_step_into_function_ = Smi::kZero;
345  thread_local_.target_frame_count_ = -1;
346  thread_local_.return_value_ = Smi::kZero;
347  thread_local_.last_breakpoint_id_ = 0;
348  clear_suspended_generator();
349  thread_local_.restart_fp_ = kNullAddress;
350  base::Relaxed_Store(&thread_local_.current_debug_scope_,
351  static_cast<base::AtomicWord>(0));
352  thread_local_.break_on_next_function_call_ = false;
353  UpdateHookOnFunctionCall();
354 }
355 
356 
357 char* Debug::ArchiveDebug(char* storage) {
358  MemCopy(storage, reinterpret_cast<char*>(&thread_local_),
359  ArchiveSpacePerThread());
360  return storage + ArchiveSpacePerThread();
361 }
362 
363 char* Debug::RestoreDebug(char* storage) {
364  MemCopy(reinterpret_cast<char*>(&thread_local_), storage,
365  ArchiveSpacePerThread());
366 
367  // Enter the debugger.
368  DebugScope debug_scope(this);
369 
370  // Clear any one-shot breakpoints that may have been set by the other
371  // thread, and reapply breakpoints for this thread.
372  ClearOneShot();
373 
374  if (thread_local_.last_step_action_ != StepNone) {
375  // Reset the previous step action for this thread.
376  PrepareStep(thread_local_.last_step_action_);
377  }
378 
379  return storage + ArchiveSpacePerThread();
380 }
381 
382 int Debug::ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
383 
384 void Debug::Iterate(RootVisitor* v) {
385  v->VisitRootPointer(Root::kDebug, nullptr,
386  ObjectSlot(&thread_local_.return_value_));
387  v->VisitRootPointer(Root::kDebug, nullptr,
388  ObjectSlot(&thread_local_.suspended_generator_));
389  v->VisitRootPointer(Root::kDebug, nullptr,
390  ObjectSlot(&thread_local_.ignore_step_into_function_));
391 }
392 
393 DebugInfoListNode::DebugInfoListNode(Isolate* isolate, DebugInfo* debug_info)
394  : next_(nullptr) {
395  // Globalize the request debug info object and make it weak.
396  GlobalHandles* global_handles = isolate->global_handles();
397  debug_info_ = global_handles->Create(debug_info).location();
398 }
399 
400 
401 DebugInfoListNode::~DebugInfoListNode() {
402  if (debug_info_ == nullptr) return;
403  GlobalHandles::Destroy(debug_info_);
404  debug_info_ = nullptr;
405 }
406 
407 void Debug::Unload() {
408  ClearAllBreakPoints();
409  ClearStepping();
410  RemoveAllCoverageInfos();
411  ClearAllDebuggerHints();
412  debug_delegate_ = nullptr;
413 }
414 
415 void Debug::Break(JavaScriptFrame* frame, Handle<JSFunction> break_target) {
416  // Initialize LiveEdit.
417  LiveEdit::InitializeThreadLocal(this);
418 
419  // Just continue if breaks are disabled or debugger cannot be loaded.
420  if (break_disabled()) return;
421 
422  // Enter the debugger.
423  DebugScope debug_scope(this);
424  DisableBreak no_recursive_break(this);
425 
426  // Return if we fail to retrieve debug info.
427  Handle<SharedFunctionInfo> shared(break_target->shared(), isolate_);
428  if (!EnsureBreakInfo(shared)) return;
429  PrepareFunctionForDebugExecution(shared);
430 
431  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
432 
433  // Find the break location where execution has stopped.
434  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
435 
436  // Find actual break points, if any, and trigger debug break event.
437  MaybeHandle<FixedArray> break_points_hit =
438  CheckBreakPoints(debug_info, &location);
439  if (!break_points_hit.is_null() || break_on_next_function_call()) {
440  // Clear all current stepping setup.
441  ClearStepping();
442  // Notify the debug event listeners.
443  OnDebugBreak(!break_points_hit.is_null()
444  ? break_points_hit.ToHandleChecked()
445  : isolate_->factory()->empty_fixed_array());
446  return;
447  }
448 
449  // Debug break at function entry, do not worry about stepping.
450  if (location.IsDebugBreakAtEntry()) {
451  DCHECK(debug_info->BreakAtEntry());
452  return;
453  }
454 
455  DCHECK_NOT_NULL(frame);
456 
457  // No break point. Check for stepping.
458  StepAction step_action = last_step_action();
459  int current_frame_count = CurrentFrameCount();
460  int target_frame_count = thread_local_.target_frame_count_;
461  int last_frame_count = thread_local_.last_frame_count_;
462 
463  // StepOut at not return position was requested and return break locations
464  // were flooded with one shots.
465  if (thread_local_.fast_forward_to_return_) {
466  DCHECK(location.IsReturnOrSuspend());
467  // We have to ignore recursive calls to function.
468  if (current_frame_count > target_frame_count) return;
469  ClearStepping();
470  PrepareStep(StepOut);
471  return;
472  }
473 
474  bool step_break = false;
475  switch (step_action) {
476  case StepNone:
477  return;
478  case StepOut:
479  // Step out should not break in a deeper frame than target frame.
480  if (current_frame_count > target_frame_count) return;
481  step_break = true;
482  break;
483  case StepNext:
484  // Step next should not break in a deeper frame than target frame.
485  if (current_frame_count > target_frame_count) return;
486  V8_FALLTHROUGH;
487  case StepIn: {
488  // Special case "next" and "in" for generators that are about to suspend.
489  if (location.IsSuspend()) {
490  DCHECK(!has_suspended_generator());
491  thread_local_.suspended_generator_ =
492  location.GetGeneratorObjectForSuspendedFrame(frame);
493  ClearStepping();
494  return;
495  }
496 
497  FrameSummary summary = FrameSummary::GetTop(frame);
498  step_break = step_break || location.IsReturn() ||
499  current_frame_count != last_frame_count ||
500  thread_local_.last_statement_position_ !=
501  summary.SourceStatementPosition();
502  break;
503  }
504  }
505 
506  // Clear all current stepping setup.
507  ClearStepping();
508 
509  if (step_break) {
510  // Notify the debug event listeners.
511  OnDebugBreak(isolate_->factory()->empty_fixed_array());
512  } else {
513  // Re-prepare to continue.
514  PrepareStep(step_action);
515  }
516 }
517 
518 
519 // Find break point objects for this location, if any, and evaluate them.
520 // Return an array of break point objects that evaluated true, or an empty
521 // handle if none evaluated true.
522 MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
523  BreakLocation* location,
524  bool* has_break_points) {
525  bool has_break_points_to_check =
526  break_points_active_ && location->HasBreakPoint(isolate_, debug_info);
527  if (has_break_points) *has_break_points = has_break_points_to_check;
528  if (!has_break_points_to_check) return {};
529 
530  return Debug::GetHitBreakPoints(debug_info, location->position());
531 }
532 
533 
534 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
535  HandleScope scope(isolate_);
536  // A break location is considered muted if break locations on the current
537  // statement have at least one break point, and all of these break points
538  // evaluate to false. Aside from not triggering a debug break event at the
539  // break location, we also do not trigger one for debugger statements, nor
540  // an exception event on exception at this location.
541  FrameSummary summary = FrameSummary::GetTop(frame);
542  DCHECK(!summary.IsWasm());
543  Handle<JSFunction> function = summary.AsJavaScript().function();
544  if (!function->shared()->HasBreakInfo()) return false;
545  Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo(), isolate_);
546  // Enter the debugger.
547  DebugScope debug_scope(this);
548  std::vector<BreakLocation> break_locations;
549  BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
550  bool has_break_points_at_all = false;
551  for (size_t i = 0; i < break_locations.size(); i++) {
552  bool has_break_points;
553  MaybeHandle<FixedArray> check_result =
554  CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
555  has_break_points_at_all |= has_break_points;
556  if (has_break_points && !check_result.is_null()) return false;
557  }
558  return has_break_points_at_all;
559 }
560 
561 // Check whether a single break point object is triggered.
562 bool Debug::CheckBreakPoint(Handle<BreakPoint> break_point,
563  bool is_break_at_entry) {
564  HandleScope scope(isolate_);
565 
566  if (!break_point->condition()->length()) return true;
567  Handle<String> condition(break_point->condition(), isolate_);
568  MaybeHandle<Object> maybe_result;
569  Handle<Object> result;
570 
571  if (is_break_at_entry) {
572  maybe_result = DebugEvaluate::WithTopmostArguments(isolate_, condition);
573  } else {
574  // Since we call CheckBreakpoint only for deoptimized frame on top of stack,
575  // we can use 0 as index of inlined frame.
576  const int inlined_jsframe_index = 0;
577  const bool throw_on_side_effect = false;
578  maybe_result =
579  DebugEvaluate::Local(isolate_, break_frame_id(), inlined_jsframe_index,
580  condition, throw_on_side_effect);
581  }
582 
583  if (!maybe_result.ToHandle(&result)) {
584  if (isolate_->has_pending_exception()) {
585  isolate_->clear_pending_exception();
586  }
587  return false;
588  }
589  return result->BooleanValue(isolate_);
590 }
591 
592 bool Debug::SetBreakPoint(Handle<JSFunction> function,
593  Handle<BreakPoint> break_point,
594  int* source_position) {
595  HandleScope scope(isolate_);
596 
597  // Make sure the function is compiled and has set up the debug info.
598  Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
599  if (!EnsureBreakInfo(shared)) return false;
600  PrepareFunctionForDebugExecution(shared);
601 
602  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
603  // Source positions starts with zero.
604  DCHECK_LE(0, *source_position);
605 
606  // Find the break point and change it.
607  *source_position = FindBreakablePosition(debug_info, *source_position);
608  DebugInfo::SetBreakPoint(isolate_, debug_info, *source_position, break_point);
609  // At least one active break point now.
610  DCHECK_LT(0, debug_info->GetBreakPointCount(isolate_));
611 
612  ClearBreakPoints(debug_info);
613  ApplyBreakPoints(debug_info);
614 
615  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
616  return true;
617 }
618 
619 bool Debug::SetBreakPointForScript(Handle<Script> script,
620  Handle<String> condition,
621  int* source_position, int* id) {
622  *id = ++thread_local_.last_breakpoint_id_;
623  Handle<BreakPoint> break_point =
624  isolate_->factory()->NewBreakPoint(*id, condition);
625  if (script->type() == Script::TYPE_WASM) {
626  Handle<WasmModuleObject> module_object(
627  WasmModuleObject::cast(script->wasm_module_object()), isolate_);
628  return WasmModuleObject::SetBreakPoint(module_object, source_position,
629  break_point);
630  }
631 
632  HandleScope scope(isolate_);
633 
634  // Obtain shared function info for the function.
635  Handle<Object> result =
636  FindSharedFunctionInfoInScript(script, *source_position);
637  if (result->IsUndefined(isolate_)) return false;
638 
639  // Make sure the function has set up the debug info.
640  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
641  if (!EnsureBreakInfo(shared)) return false;
642  PrepareFunctionForDebugExecution(shared);
643 
644  // Find position within function. The script position might be before the
645  // source position of the first function.
646  if (shared->StartPosition() > *source_position) {
647  *source_position = shared->StartPosition();
648  }
649 
650  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
651 
652  // Find breakable position returns first breakable position after
653  // *source_position, it can return 0 if no break location is found after
654  // *source_position.
655  int breakable_position = FindBreakablePosition(debug_info, *source_position);
656  if (breakable_position < *source_position) return false;
657  *source_position = breakable_position;
658 
659  DebugInfo::SetBreakPoint(isolate_, debug_info, *source_position, break_point);
660  // At least one active break point now.
661  DCHECK_LT(0, debug_info->GetBreakPointCount(isolate_));
662 
663  ClearBreakPoints(debug_info);
664  ApplyBreakPoints(debug_info);
665 
666  feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
667  return true;
668 }
669 
670 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
671  int source_position) {
672  if (debug_info->CanBreakAtEntry()) {
673  return kBreakAtEntryPosition;
674  } else {
675  DCHECK(debug_info->HasInstrumentedBytecodeArray());
676  BreakIterator it(debug_info);
677  it.SkipToPosition(source_position);
678  return it.position();
679  }
680 }
681 
682 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
683  DisallowHeapAllocation no_gc;
684  if (debug_info->CanBreakAtEntry()) {
685  debug_info->SetBreakAtEntry();
686  } else {
687  if (!debug_info->HasInstrumentedBytecodeArray()) return;
688  FixedArray break_points = debug_info->break_points();
689  for (int i = 0; i < break_points->length(); i++) {
690  if (break_points->get(i)->IsUndefined(isolate_)) continue;
691  BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
692  if (info->GetBreakPointCount(isolate_) == 0) continue;
693  DCHECK(debug_info->HasInstrumentedBytecodeArray());
694  BreakIterator it(debug_info);
695  it.SkipToPosition(info->source_position());
696  it.SetDebugBreak();
697  }
698  }
699  debug_info->SetDebugExecutionMode(DebugInfo::kBreakpoints);
700 }
701 
702 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
703  if (debug_info->CanBreakAtEntry()) {
704  debug_info->ClearBreakAtEntry();
705  } else {
706  // If we attempt to clear breakpoints but none exist, simply return. This
707  // can happen e.g. CoverageInfos exist but no breakpoints are set.
708  if (!debug_info->HasInstrumentedBytecodeArray() ||
709  !debug_info->HasBreakInfo()) {
710  return;
711  }
712 
713  DisallowHeapAllocation no_gc;
714  for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
715  it.ClearDebugBreak();
716  }
717  }
718 }
719 
720 void Debug::ClearBreakPoint(Handle<BreakPoint> break_point) {
721  HandleScope scope(isolate_);
722 
723  for (DebugInfoListNode* node = debug_info_list_; node != nullptr;
724  node = node->next()) {
725  if (!node->debug_info()->HasBreakInfo()) continue;
726  Handle<Object> result = DebugInfo::FindBreakPointInfo(
727  isolate_, node->debug_info(), break_point);
728  if (result->IsUndefined(isolate_)) continue;
729  Handle<DebugInfo> debug_info = node->debug_info();
730  if (DebugInfo::ClearBreakPoint(isolate_, debug_info, break_point)) {
731  ClearBreakPoints(debug_info);
732  if (debug_info->GetBreakPointCount(isolate_) == 0) {
733  RemoveBreakInfoAndMaybeFree(debug_info);
734  } else {
735  ApplyBreakPoints(debug_info);
736  }
737  return;
738  }
739  }
740 }
741 
742 int Debug::GetFunctionDebuggingId(Handle<JSFunction> function) {
743  Handle<SharedFunctionInfo> shared = handle(function->shared(), isolate_);
744  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
745  int id = debug_info->debugging_id();
746  if (id == DebugInfo::kNoDebuggingId) {
747  id = isolate_->heap()->NextDebuggingId();
748  debug_info->set_debugging_id(id);
749  }
750  return id;
751 }
752 
753 bool Debug::SetBreakpointForFunction(Handle<JSFunction> function,
754  Handle<String> condition, int* id) {
755  *id = ++thread_local_.last_breakpoint_id_;
756  Handle<BreakPoint> breakpoint =
757  isolate_->factory()->NewBreakPoint(*id, condition);
758  int source_position = 0;
759  return SetBreakPoint(function, breakpoint, &source_position);
760 }
761 
762 void Debug::RemoveBreakpoint(int id) {
763  Handle<BreakPoint> breakpoint = isolate_->factory()->NewBreakPoint(
764  id, isolate_->factory()->empty_string());
765  ClearBreakPoint(breakpoint);
766 }
767 
768 // Clear out all the debug break code.
769 void Debug::ClearAllBreakPoints() {
770  ClearAllDebugInfos([=](Handle<DebugInfo> info) {
771  ClearBreakPoints(info);
772  info->ClearBreakInfo(isolate_);
773  });
774 }
775 
776 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
777  bool returns_only) {
778  if (IsBlackboxed(shared)) return;
779  // Make sure the function is compiled and has set up the debug info.
780  if (!EnsureBreakInfo(shared)) return;
781  PrepareFunctionForDebugExecution(shared);
782 
783  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
784  // Flood the function with break points.
785  DCHECK(debug_info->HasInstrumentedBytecodeArray());
786  for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
787  if (returns_only && !it.GetBreakLocation().IsReturnOrSuspend()) continue;
788  it.SetDebugBreak();
789  }
790 }
791 
792 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
793  if (type == BreakUncaughtException) {
794  break_on_uncaught_exception_ = enable;
795  } else {
796  break_on_exception_ = enable;
797  }
798 }
799 
800 
801 bool Debug::IsBreakOnException(ExceptionBreakType type) {
802  if (type == BreakUncaughtException) {
803  return break_on_uncaught_exception_;
804  } else {
805  return break_on_exception_;
806  }
807 }
808 
809 MaybeHandle<FixedArray> Debug::GetHitBreakPoints(Handle<DebugInfo> debug_info,
810  int position) {
811  Handle<Object> break_points = debug_info->GetBreakPoints(isolate_, position);
812  bool is_break_at_entry = debug_info->BreakAtEntry();
813  DCHECK(!break_points->IsUndefined(isolate_));
814  if (!break_points->IsFixedArray()) {
815  if (!CheckBreakPoint(Handle<BreakPoint>::cast(break_points),
816  is_break_at_entry)) {
817  return {};
818  }
819  Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
820  break_points_hit->set(0, *break_points);
821  return break_points_hit;
822  }
823 
824  Handle<FixedArray> array(FixedArray::cast(*break_points), isolate_);
825  int num_objects = array->length();
826  Handle<FixedArray> break_points_hit =
827  isolate_->factory()->NewFixedArray(num_objects);
828  int break_points_hit_count = 0;
829  for (int i = 0; i < num_objects; ++i) {
830  Handle<Object> break_point(array->get(i), isolate_);
831  if (CheckBreakPoint(Handle<BreakPoint>::cast(break_point),
832  is_break_at_entry)) {
833  break_points_hit->set(break_points_hit_count++, *break_point);
834  }
835  }
836  if (break_points_hit_count == 0) return {};
837  break_points_hit->Shrink(isolate_, break_points_hit_count);
838  return break_points_hit;
839 }
840 
841 void Debug::SetBreakOnNextFunctionCall() {
842  // This method forces V8 to break on next function call regardless current
843  // last_step_action_. If any break happens between SetBreakOnNextFunctionCall
844  // and ClearBreakOnNextFunctionCall, we will clear this flag and stepping. If
845  // break does not happen, e.g. all called functions are blackboxed or no
846  // function is called, then we will clear this flag and let stepping continue
847  // its normal business.
848  thread_local_.break_on_next_function_call_ = true;
849  UpdateHookOnFunctionCall();
850 }
851 
852 void Debug::ClearBreakOnNextFunctionCall() {
853  thread_local_.break_on_next_function_call_ = false;
854  UpdateHookOnFunctionCall();
855 }
856 
857 void Debug::PrepareStepIn(Handle<JSFunction> function) {
858  CHECK(last_step_action() >= StepIn || break_on_next_function_call());
859  if (ignore_events()) return;
860  if (in_debug_scope()) return;
861  if (break_disabled()) return;
862  Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
863  if (IsBlackboxed(shared)) return;
864  if (*function == thread_local_.ignore_step_into_function_) return;
865  thread_local_.ignore_step_into_function_ = Smi::kZero;
866  FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
867 }
868 
869 void Debug::PrepareStepInSuspendedGenerator() {
870  CHECK(has_suspended_generator());
871  if (ignore_events()) return;
872  if (in_debug_scope()) return;
873  if (break_disabled()) return;
874  thread_local_.last_step_action_ = StepIn;
875  UpdateHookOnFunctionCall();
876  Handle<JSFunction> function(
877  JSGeneratorObject::cast(thread_local_.suspended_generator_)->function(),
878  isolate_);
879  FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
880  clear_suspended_generator();
881 }
882 
883 void Debug::PrepareStepOnThrow() {
884  if (last_step_action() == StepNone) return;
885  if (ignore_events()) return;
886  if (in_debug_scope()) return;
887  if (break_disabled()) return;
888 
889  ClearOneShot();
890 
891  int current_frame_count = CurrentFrameCount();
892 
893  // Iterate through the JavaScript stack looking for handlers.
894  JavaScriptFrameIterator it(isolate_);
895  while (!it.done()) {
896  JavaScriptFrame* frame = it.frame();
897  if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
898  std::vector<SharedFunctionInfo*> infos;
899  frame->GetFunctions(&infos);
900  current_frame_count -= infos.size();
901  it.Advance();
902  }
903 
904  // No handler found. Nothing to instrument.
905  if (it.done()) return;
906 
907  bool found_handler = false;
908  // Iterate frames, including inlined frames. First, find the handler frame.
909  // Then skip to the frame we want to break in, then instrument for stepping.
910  for (; !it.done(); it.Advance()) {
911  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
912  if (last_step_action() == StepIn) {
913  // Deoptimize frame to ensure calls are checked for step-in.
914  Deoptimizer::DeoptimizeFunction(frame->function());
915  }
916  std::vector<FrameSummary> summaries;
917  frame->Summarize(&summaries);
918  for (size_t i = summaries.size(); i != 0; i--, current_frame_count--) {
919  const FrameSummary& summary = summaries[i - 1];
920  if (!found_handler) {
921  // We have yet to find the handler. If the frame inlines multiple
922  // functions, we have to check each one for the handler.
923  // If it only contains one function, we already found the handler.
924  if (summaries.size() > 1) {
925  Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
926  CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
927  HandlerTable table(code->GetBytecodeArray());
928  int code_offset = summary.code_offset();
929  HandlerTable::CatchPrediction prediction;
930  int index = table.LookupRange(code_offset, nullptr, &prediction);
931  if (index > 0) found_handler = true;
932  } else {
933  found_handler = true;
934  }
935  }
936 
937  if (found_handler) {
938  // We found the handler. If we are stepping next or out, we need to
939  // iterate until we found the suitable target frame to break in.
940  if ((last_step_action() == StepNext || last_step_action() == StepOut) &&
941  current_frame_count > thread_local_.target_frame_count_) {
942  continue;
943  }
944  Handle<SharedFunctionInfo> info(
945  summary.AsJavaScript().function()->shared(), isolate_);
946  if (IsBlackboxed(info)) continue;
947  FloodWithOneShot(info);
948  return;
949  }
950  }
951  }
952 }
953 
954 
955 void Debug::PrepareStep(StepAction step_action) {
956  HandleScope scope(isolate_);
957 
958  DCHECK(in_debug_scope());
959 
960  // Get the frame where the execution has stopped and skip the debug frame if
961  // any. The debug frame will only be present if execution was stopped due to
962  // hitting a break point. In other situations (e.g. unhandled exception) the
963  // debug frame is not present.
964  StackFrame::Id frame_id = break_frame_id();
965  // If there is no JavaScript stack don't do anything.
966  if (frame_id == StackFrame::NO_ID) return;
967 
968  feature_tracker()->Track(DebugFeatureTracker::kStepping);
969 
970  thread_local_.last_step_action_ = step_action;
971 
972  StackTraceFrameIterator frames_it(isolate_, frame_id);
973  StandardFrame* frame = frames_it.frame();
974 
975  // Handle stepping in wasm functions via the wasm interpreter.
976  if (frame->is_wasm()) {
977  // If the top frame is compiled, we cannot step.
978  if (frame->is_wasm_compiled()) return;
979  WasmInterpreterEntryFrame* wasm_frame =
980  WasmInterpreterEntryFrame::cast(frame);
981  wasm_frame->debug_info()->PrepareStep(step_action);
982  return;
983  }
984 
985  JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
986  DCHECK(js_frame->function()->IsJSFunction());
987 
988  // Get the debug info (create it if it does not exist).
989  auto summary = FrameSummary::GetTop(frame).AsJavaScript();
990  Handle<JSFunction> function(summary.function());
991  Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
992  if (!EnsureBreakInfo(shared)) return;
993  PrepareFunctionForDebugExecution(shared);
994 
995  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
996 
997  BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame);
998 
999  // Any step at a return is a step-out, and a step-out at a suspend behaves
1000  // like a return.
1001  if (location.IsReturn() || (location.IsSuspend() && step_action == StepOut)) {
1002  // On StepOut we'll ignore our further calls to current function in
1003  // PrepareStepIn callback.
1004  if (last_step_action() == StepOut) {
1005  thread_local_.ignore_step_into_function_ = *function;
1006  }
1007  step_action = StepOut;
1008  thread_local_.last_step_action_ = StepIn;
1009  }
1010 
1011  // We need to schedule DebugOnFunction call callback
1012  UpdateHookOnFunctionCall();
1013 
1014  // A step-next in blackboxed function is a step-out.
1015  if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut;
1016 
1017  thread_local_.last_statement_position_ =
1018  summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1019  int current_frame_count = CurrentFrameCount();
1020  thread_local_.last_frame_count_ = current_frame_count;
1021  // No longer perform the current async step.
1022  clear_suspended_generator();
1023 
1024  switch (step_action) {
1025  case StepNone:
1026  UNREACHABLE();
1027  break;
1028  case StepOut: {
1029  // Clear last position info. For stepping out it does not matter.
1030  thread_local_.last_statement_position_ = kNoSourcePosition;
1031  thread_local_.last_frame_count_ = -1;
1032  if (!location.IsReturnOrSuspend() && !IsBlackboxed(shared)) {
1033  // At not return position we flood return positions with one shots and
1034  // will repeat StepOut automatically at next break.
1035  thread_local_.target_frame_count_ = current_frame_count;
1036  thread_local_.fast_forward_to_return_ = true;
1037  FloodWithOneShot(shared, true);
1038  return;
1039  }
1040  // Skip the current frame, find the first frame we want to step out to
1041  // and deoptimize every frame along the way.
1042  bool in_current_frame = true;
1043  for (; !frames_it.done(); frames_it.Advance()) {
1044  // TODO(clemensh): Implement stepping out from JS to wasm.
1045  if (frames_it.frame()->is_wasm()) continue;
1046  JavaScriptFrame* frame = JavaScriptFrame::cast(frames_it.frame());
1047  if (last_step_action() == StepIn) {
1048  // Deoptimize frame to ensure calls are checked for step-in.
1049  Deoptimizer::DeoptimizeFunction(frame->function());
1050  }
1051  HandleScope scope(isolate_);
1052  std::vector<Handle<SharedFunctionInfo>> infos;
1053  frame->GetFunctions(&infos);
1054  for (; !infos.empty(); current_frame_count--) {
1055  Handle<SharedFunctionInfo> info = infos.back();
1056  infos.pop_back();
1057  if (in_current_frame) {
1058  // We want to skip out, so skip the current frame.
1059  in_current_frame = false;
1060  continue;
1061  }
1062  if (IsBlackboxed(info)) continue;
1063  FloodWithOneShot(info);
1064  thread_local_.target_frame_count_ = current_frame_count;
1065  return;
1066  }
1067  }
1068  break;
1069  }
1070  case StepNext:
1071  thread_local_.target_frame_count_ = current_frame_count;
1072  V8_FALLTHROUGH;
1073  case StepIn:
1074  // TODO(clemensh): Implement stepping from JS into wasm.
1075  FloodWithOneShot(shared);
1076  break;
1077  }
1078 }
1079 
1080 // Simple function for returning the source positions for active break points.
1081 Handle<Object> Debug::GetSourceBreakLocations(
1082  Isolate* isolate, Handle<SharedFunctionInfo> shared) {
1083  if (!shared->HasBreakInfo()) {
1084  return isolate->factory()->undefined_value();
1085  }
1086 
1087  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate);
1088  if (debug_info->GetBreakPointCount(isolate) == 0) {
1089  return isolate->factory()->undefined_value();
1090  }
1091  Handle<FixedArray> locations = isolate->factory()->NewFixedArray(
1092  debug_info->GetBreakPointCount(isolate));
1093  int count = 0;
1094  for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1095  if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
1096  BreakPointInfo* break_point_info =
1097  BreakPointInfo::cast(debug_info->break_points()->get(i));
1098  int break_points = break_point_info->GetBreakPointCount(isolate);
1099  if (break_points == 0) continue;
1100  for (int j = 0; j < break_points; ++j) {
1101  locations->set(count++,
1102  Smi::FromInt(break_point_info->source_position()));
1103  }
1104  }
1105  }
1106  return locations;
1107 }
1108 
1109 void Debug::ClearStepping() {
1110  // Clear the various stepping setup.
1111  ClearOneShot();
1112 
1113  thread_local_.last_step_action_ = StepNone;
1114  thread_local_.last_statement_position_ = kNoSourcePosition;
1115  thread_local_.ignore_step_into_function_ = Smi::kZero;
1116  thread_local_.fast_forward_to_return_ = false;
1117  thread_local_.last_frame_count_ = -1;
1118  thread_local_.target_frame_count_ = -1;
1119  thread_local_.break_on_next_function_call_ = false;
1120  UpdateHookOnFunctionCall();
1121 }
1122 
1123 
1124 // Clears all the one-shot break points that are currently set. Normally this
1125 // function is called each time a break point is hit as one shot break points
1126 // are used to support stepping.
1127 void Debug::ClearOneShot() {
1128  // The current implementation just runs through all the breakpoints. When the
1129  // last break point for a function is removed that function is automatically
1130  // removed from the list.
1131  for (DebugInfoListNode* node = debug_info_list_; node != nullptr;
1132  node = node->next()) {
1133  Handle<DebugInfo> debug_info = node->debug_info();
1134  ClearBreakPoints(debug_info);
1135  ApplyBreakPoints(debug_info);
1136  }
1137 }
1138 
1140  public:
1142  : shared_(shared) {
1143  DCHECK(shared->HasBytecodeArray());
1144  }
1145 
1146  void VisitThread(Isolate* isolate, ThreadLocalTop* top) override {
1147  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1148  JavaScriptFrame* frame = it.frame();
1149  JSFunction* function = frame->function();
1150  if (!frame->is_interpreted()) continue;
1151  if (function->shared() != shared_) continue;
1152  InterpretedFrame* interpreted_frame =
1153  reinterpret_cast<InterpretedFrame*>(frame);
1154  BytecodeArray debug_copy = shared_->GetDebugInfo()->DebugBytecodeArray();
1155  interpreted_frame->PatchBytecodeArray(debug_copy);
1156  }
1157  }
1158 
1159  private:
1160  SharedFunctionInfo* shared_;
1161  DisallowHeapAllocation no_gc_;
1162 };
1163 
1164 void Debug::DeoptimizeFunction(Handle<SharedFunctionInfo> shared) {
1165  // Deoptimize all code compiled from this shared function info including
1166  // inlining.
1167  isolate_->AbortConcurrentOptimization(BlockingBehavior::kBlock);
1168 
1169  // TODO(mlippautz): Try to remove this call.
1170  isolate_->heap()->PreciseCollectAllGarbage(
1171  Heap::kNoGCFlags, GarbageCollectionReason::kDebugger);
1172 
1173  bool found_something = false;
1174  Code::OptimizedCodeIterator iterator(isolate_);
1175  do {
1176  Code code = iterator.Next();
1177  if (code.is_null()) break;
1178  if (code->Inlines(*shared)) {
1179  code->set_marked_for_deoptimization(true);
1180  found_something = true;
1181  }
1182  } while (true);
1183 
1184  if (found_something) {
1185  // Only go through with the deoptimization if something was found.
1186  Deoptimizer::DeoptimizeMarkedCode(isolate_);
1187  }
1188 }
1189 
1190 void Debug::PrepareFunctionForDebugExecution(
1191  Handle<SharedFunctionInfo> shared) {
1192  // To prepare bytecode for debugging, we already need to have the debug
1193  // info (containing the debug copy) upfront, but since we do not recompile,
1194  // preparing for break points cannot fail.
1195  DCHECK(shared->is_compiled());
1196  DCHECK(shared->HasDebugInfo());
1197  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1198  if (debug_info->flags() & DebugInfo::kPreparedForDebugExecution) return;
1199 
1200  // Make a copy of the bytecode array if available.
1201  Handle<Object> maybe_original_bytecode_array =
1202  isolate_->factory()->undefined_value();
1203  if (shared->HasBytecodeArray()) {
1204  Handle<BytecodeArray> original_bytecode_array =
1205  handle(shared->GetBytecodeArray(), isolate_);
1206  Handle<BytecodeArray> debug_bytecode_array =
1207  isolate_->factory()->CopyBytecodeArray(original_bytecode_array);
1208  debug_info->set_debug_bytecode_array(*debug_bytecode_array);
1209  shared->SetDebugBytecodeArray(*debug_bytecode_array);
1210  maybe_original_bytecode_array = original_bytecode_array;
1211  }
1212  debug_info->set_original_bytecode_array(*maybe_original_bytecode_array);
1213 
1214  if (debug_info->CanBreakAtEntry()) {
1215  // Deopt everything in case the function is inlined anywhere.
1216  Deoptimizer::DeoptimizeAll(isolate_);
1217  InstallDebugBreakTrampoline();
1218  } else {
1219  DeoptimizeFunction(shared);
1220  // Update PCs on the stack to point to recompiled code.
1221  RedirectActiveFunctions redirect_visitor(*shared);
1222  redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1223  isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1224  }
1225  debug_info->set_flags(debug_info->flags() |
1226  DebugInfo::kPreparedForDebugExecution);
1227 }
1228 
1229 void Debug::InstallDebugBreakTrampoline() {
1230  // Check the list of debug infos whether the debug break trampoline needs to
1231  // be installed. If that's the case, iterate the heap for functions to rewire
1232  // to the trampoline.
1233  HandleScope scope(isolate_);
1234  // If there is a breakpoint at function entry, we need to install trampoline.
1235  bool needs_to_use_trampoline = false;
1236  // If there we break at entry to an api callback, we need to clear ICs.
1237  bool needs_to_clear_ic = false;
1238  for (DebugInfoListNode* current = debug_info_list_; current != nullptr;
1239  current = current->next()) {
1240  if (current->debug_info()->CanBreakAtEntry()) {
1241  needs_to_use_trampoline = true;
1242  if (current->debug_info()->shared()->IsApiFunction()) {
1243  needs_to_clear_ic = true;
1244  break;
1245  }
1246  }
1247  }
1248 
1249  if (!needs_to_use_trampoline) return;
1250 
1251  Handle<Code> trampoline = BUILTIN_CODE(isolate_, DebugBreakTrampoline);
1252  std::vector<Handle<JSFunction>> needs_compile;
1253  {
1254  HeapIterator iterator(isolate_->heap());
1255  while (HeapObject* obj = iterator.next()) {
1256  if (needs_to_clear_ic && obj->IsFeedbackVector()) {
1257  FeedbackVector::cast(obj)->ClearSlots(isolate_);
1258  continue;
1259  } else if (obj->IsJSFunction()) {
1260  JSFunction* fun = JSFunction::cast(obj);
1261  SharedFunctionInfo* shared = fun->shared();
1262  if (!shared->HasDebugInfo()) continue;
1263  if (!shared->GetDebugInfo()->CanBreakAtEntry()) continue;
1264  if (!fun->is_compiled()) {
1265  needs_compile.push_back(handle(fun, isolate_));
1266  } else {
1267  fun->set_code(*trampoline);
1268  }
1269  }
1270  }
1271  }
1272  // By overwriting the function code with DebugBreakTrampoline, which tailcalls
1273  // to shared code, we bypass CompileLazy. Perform CompileLazy here instead.
1274  for (Handle<JSFunction> fun : needs_compile) {
1275  Compiler::Compile(fun, Compiler::CLEAR_EXCEPTION);
1276  fun->set_code(*trampoline);
1277  }
1278 }
1279 
1280 namespace {
1281 template <typename Iterator>
1282 void GetBreakablePositions(Iterator* it, int start_position, int end_position,
1283  std::vector<BreakLocation>* locations) {
1284  while (!it->Done()) {
1285  if (it->position() >= start_position && it->position() < end_position) {
1286  locations->push_back(it->GetBreakLocation());
1287  }
1288  it->Next();
1289  }
1290 }
1291 
1292 void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
1293  int end_position,
1294  std::vector<BreakLocation>* locations) {
1295  DCHECK(debug_info->HasInstrumentedBytecodeArray());
1296  BreakIterator it(debug_info);
1297  GetBreakablePositions(&it, start_position, end_position, locations);
1298 }
1299 } // namespace
1300 
1301 bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
1302  int end_position, bool restrict_to_function,
1303  std::vector<BreakLocation>* locations) {
1304  if (restrict_to_function) {
1305  Handle<Object> result =
1306  FindSharedFunctionInfoInScript(script, start_position);
1307  if (result->IsUndefined(isolate_)) return false;
1308 
1309  // Make sure the function has set up the debug info.
1310  Handle<SharedFunctionInfo> shared =
1311  Handle<SharedFunctionInfo>::cast(result);
1312  if (!EnsureBreakInfo(shared)) return false;
1313  PrepareFunctionForDebugExecution(shared);
1314 
1315  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
1316  FindBreakablePositions(debug_info, start_position, end_position, locations);
1317  return true;
1318  }
1319 
1320  while (true) {
1321  HandleScope scope(isolate_);
1322  std::vector<Handle<SharedFunctionInfo>> candidates;
1323  SharedFunctionInfo::ScriptIterator iterator(isolate_, *script);
1324  for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
1325  info = iterator.Next()) {
1326  if (info->EndPosition() < start_position ||
1327  info->StartPosition() >= end_position) {
1328  continue;
1329  }
1330  if (!info->IsSubjectToDebugging()) continue;
1331  if (!info->is_compiled() && !info->allows_lazy_compilation()) continue;
1332  candidates.push_back(i::handle(info, isolate_));
1333  }
1334 
1335  bool was_compiled = false;
1336  for (const auto& candidate : candidates) {
1337  // Code that cannot be compiled lazily are internal and not debuggable.
1338  DCHECK(candidate->allows_lazy_compilation());
1339  if (!candidate->is_compiled()) {
1340  if (!Compiler::Compile(candidate, Compiler::CLEAR_EXCEPTION)) {
1341  return false;
1342  } else {
1343  was_compiled = true;
1344  }
1345  }
1346  if (!EnsureBreakInfo(candidate)) return false;
1347  PrepareFunctionForDebugExecution(candidate);
1348  }
1349  if (was_compiled) continue;
1350 
1351  for (const auto& candidate : candidates) {
1352  CHECK(candidate->HasBreakInfo());
1353  Handle<DebugInfo> debug_info(candidate->GetDebugInfo(), isolate_);
1354  FindBreakablePositions(debug_info, start_position, end_position,
1355  locations);
1356  }
1357  return true;
1358  }
1359  UNREACHABLE();
1360 }
1361 
1363  public:
1364  explicit SharedFunctionInfoFinder(int target_position)
1365  : current_candidate_(nullptr),
1366  current_candidate_closure_(nullptr),
1367  current_start_position_(kNoSourcePosition),
1368  target_position_(target_position) {}
1369 
1370  void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = nullptr) {
1371  if (!shared->IsSubjectToDebugging()) return;
1372  int start_position = shared->function_token_position();
1373  if (start_position == kNoSourcePosition) {
1374  start_position = shared->StartPosition();
1375  }
1376 
1377  if (start_position > target_position_) return;
1378  if (target_position_ > shared->EndPosition()) return;
1379 
1380  if (current_candidate_ != nullptr) {
1381  if (current_start_position_ == start_position &&
1382  shared->EndPosition() == current_candidate_->EndPosition()) {
1383  // If we already have a matching closure, do not throw it away.
1384  if (current_candidate_closure_ != nullptr && closure == nullptr) return;
1385  // If a top-level function contains only one function
1386  // declaration the source for the top-level and the function
1387  // is the same. In that case prefer the non top-level function.
1388  if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1389  } else if (start_position < current_start_position_ ||
1390  current_candidate_->EndPosition() < shared->EndPosition()) {
1391  return;
1392  }
1393  }
1394 
1395  current_start_position_ = start_position;
1396  current_candidate_ = shared;
1397  current_candidate_closure_ = closure;
1398  }
1399 
1400  SharedFunctionInfo* Result() { return current_candidate_; }
1401 
1402  JSFunction* ResultClosure() { return current_candidate_closure_; }
1403 
1404  private:
1405  SharedFunctionInfo* current_candidate_;
1406  JSFunction* current_candidate_closure_;
1407  int current_start_position_;
1408  int target_position_;
1409  DisallowHeapAllocation no_gc_;
1410 };
1411 
1412 
1413 // We need to find a SFI for a literal that may not yet have been compiled yet,
1414 // and there may not be a JSFunction referencing it. Find the SFI closest to
1415 // the given position, compile it to reveal possible inner SFIs and repeat.
1416 // While we are at this, also ensure code with debug break slots so that we do
1417 // not have to compile a SFI without JSFunction, which is paifu for those that
1418 // cannot be compiled without context (need to find outer compilable SFI etc.)
1419 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
1420  int position) {
1421  for (int iteration = 0;; iteration++) {
1422  // Go through all shared function infos associated with this script to
1423  // find the inner most function containing this position.
1424  // If there is no shared function info for this script at all, there is
1425  // no point in looking for it by walking the heap.
1426 
1427  SharedFunctionInfo* shared;
1428  {
1429  SharedFunctionInfoFinder finder(position);
1430  SharedFunctionInfo::ScriptIterator iterator(isolate_, *script);
1431  for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
1432  info = iterator.Next()) {
1433  finder.NewCandidate(info);
1434  }
1435  shared = finder.Result();
1436  if (shared == nullptr) break;
1437  // We found it if it's already compiled.
1438  if (shared->is_compiled()) {
1439  Handle<SharedFunctionInfo> shared_handle(shared, isolate_);
1440  // If the iteration count is larger than 1, we had to compile the outer
1441  // function in order to create this shared function info. So there can
1442  // be no JSFunction referencing it. We can anticipate creating a debug
1443  // info while bypassing PrepareFunctionForDebugExecution.
1444  if (iteration > 1) {
1445  AllowHeapAllocation allow_before_return;
1446  CreateBreakInfo(shared_handle);
1447  }
1448  return shared_handle;
1449  }
1450  }
1451  // If not, compile to reveal inner functions.
1452  HandleScope scope(isolate_);
1453  // Code that cannot be compiled lazily are internal and not debuggable.
1454  DCHECK(shared->allows_lazy_compilation());
1455  if (!Compiler::Compile(handle(shared, isolate_), Compiler::CLEAR_EXCEPTION))
1456  break;
1457  }
1458  return isolate_->factory()->undefined_value();
1459 }
1460 
1461 
1462 // Ensures the debug information is present for shared.
1463 bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) {
1464  // Return if we already have the break info for shared.
1465  if (shared->HasBreakInfo()) return true;
1466  if (!shared->IsSubjectToDebugging() && !CanBreakAtEntry(shared)) {
1467  return false;
1468  }
1469  if (!shared->is_compiled() &&
1470  !Compiler::Compile(shared, Compiler::CLEAR_EXCEPTION)) {
1471  return false;
1472  }
1473  CreateBreakInfo(shared);
1474  return true;
1475 }
1476 
1477 void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) {
1478  HandleScope scope(isolate_);
1479  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1480 
1481  // Initialize with break information.
1482 
1483  DCHECK(!debug_info->HasBreakInfo());
1484 
1485  Factory* factory = isolate_->factory();
1486  Handle<FixedArray> break_points(
1487  factory->NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction));
1488 
1489  int flags = debug_info->flags();
1490  flags |= DebugInfo::kHasBreakInfo;
1491  if (CanBreakAtEntry(shared)) flags |= DebugInfo::kCanBreakAtEntry;
1492  debug_info->set_flags(flags);
1493  debug_info->set_break_points(*break_points);
1494 }
1495 
1496 Handle<DebugInfo> Debug::GetOrCreateDebugInfo(
1497  Handle<SharedFunctionInfo> shared) {
1498  if (shared->HasDebugInfo()) return handle(shared->GetDebugInfo(), isolate_);
1499 
1500  // Create debug info and add it to the list.
1501  Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1502  DebugInfoListNode* node = new DebugInfoListNode(isolate_, *debug_info);
1503  node->set_next(debug_info_list_);
1504  debug_info_list_ = node;
1505 
1506  return debug_info;
1507 }
1508 
1509 void Debug::InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
1510  Handle<CoverageInfo> coverage_info) {
1511  DCHECK(!coverage_info.is_null());
1512 
1513  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1514 
1515  DCHECK(!debug_info->HasCoverageInfo());
1516 
1517  debug_info->set_flags(debug_info->flags() | DebugInfo::kHasCoverageInfo);
1518  debug_info->set_coverage_info(*coverage_info);
1519 }
1520 
1521 void Debug::RemoveAllCoverageInfos() {
1522  ClearAllDebugInfos(
1523  [=](Handle<DebugInfo> info) { info->ClearCoverageInfo(isolate_); });
1524 }
1525 
1526 void Debug::ClearAllDebuggerHints() {
1527  ClearAllDebugInfos(
1528  [=](Handle<DebugInfo> info) { info->set_debugger_hints(0); });
1529 }
1530 
1531 void Debug::FindDebugInfo(Handle<DebugInfo> debug_info,
1532  DebugInfoListNode** prev, DebugInfoListNode** curr) {
1533  HandleScope scope(isolate_);
1534  *prev = nullptr;
1535  *curr = debug_info_list_;
1536  while (*curr != nullptr) {
1537  if ((*curr)->debug_info().is_identical_to(debug_info)) return;
1538  *prev = *curr;
1539  *curr = (*curr)->next();
1540  }
1541 
1542  UNREACHABLE();
1543 }
1544 
1545 void Debug::ClearAllDebugInfos(const DebugInfoClearFunction& clear_function) {
1546  DebugInfoListNode* prev = nullptr;
1547  DebugInfoListNode* current = debug_info_list_;
1548  while (current != nullptr) {
1549  DebugInfoListNode* next = current->next();
1550  Handle<DebugInfo> debug_info = current->debug_info();
1551  clear_function(debug_info);
1552  if (debug_info->IsEmpty()) {
1553  FreeDebugInfoListNode(prev, current);
1554  current = next;
1555  } else {
1556  prev = current;
1557  current = next;
1558  }
1559  }
1560 }
1561 
1562 void Debug::RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info) {
1563  debug_info->ClearBreakInfo(isolate_);
1564  if (debug_info->IsEmpty()) {
1565  DebugInfoListNode* prev;
1566  DebugInfoListNode* node;
1567  FindDebugInfo(debug_info, &prev, &node);
1568  FreeDebugInfoListNode(prev, node);
1569  }
1570 }
1571 
1572 void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev,
1573  DebugInfoListNode* node) {
1574  DCHECK(node->debug_info()->IsEmpty());
1575 
1576  // Unlink from list. If prev is nullptr we are looking at the first element.
1577  if (prev == nullptr) {
1578  debug_info_list_ = node->next();
1579  } else {
1580  prev->set_next(node->next());
1581  }
1582 
1583  // Pack script back into the
1584  // SFI::script_or_debug_info field.
1585  Handle<DebugInfo> debug_info(node->debug_info());
1586  debug_info->shared()->set_script_or_debug_info(debug_info->script());
1587 
1588  delete node;
1589 }
1590 
1591 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1592  HandleScope scope(isolate_);
1593 
1594  // Get the executing function in which the debug break occurred.
1595  Handle<SharedFunctionInfo> shared(frame->function()->shared(), isolate_);
1596 
1597  // With no debug info there are no break points, so we can't be at a return.
1598  if (!shared->HasBreakInfo()) return false;
1599 
1600  DCHECK(!frame->is_optimized());
1601  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
1602  BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1603  return location.IsReturn();
1604 }
1605 
1606 void Debug::ScheduleFrameRestart(StackFrame* frame) {
1607  // Set a target FP for the FrameDropperTrampoline builtin to drop to once
1608  // we return from the debugger.
1609  DCHECK(frame->is_java_script());
1610  // Only reschedule to a frame further below a frame we already scheduled for.
1611  if (frame->fp() <= thread_local_.restart_fp_) return;
1612  // If the frame is optimized, trigger a deopt and jump into the
1613  // FrameDropperTrampoline in the deoptimizer.
1614  thread_local_.restart_fp_ = frame->fp();
1615 
1616  // Reset break frame ID to the frame below the restarted frame.
1617  StackTraceFrameIterator it(isolate_);
1618  thread_local_.break_frame_id_ = StackFrame::NO_ID;
1619  for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1620  if (it.frame()->fp() > thread_local_.restart_fp_) {
1621  thread_local_.break_frame_id_ = it.frame()->id();
1622  return;
1623  }
1624  }
1625 }
1626 
1627 Handle<FixedArray> Debug::GetLoadedScripts() {
1628  isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1629  GarbageCollectionReason::kDebugger);
1630  Factory* factory = isolate_->factory();
1631  if (!factory->script_list()->IsWeakArrayList()) {
1632  return factory->empty_fixed_array();
1633  }
1634  Handle<WeakArrayList> array =
1635  Handle<WeakArrayList>::cast(factory->script_list());
1636  Handle<FixedArray> results = factory->NewFixedArray(array->length());
1637  int length = 0;
1638  {
1639  Script::Iterator iterator(isolate_);
1640  Script* script;
1641  while ((script = iterator.Next()) != nullptr) {
1642  if (script->HasValidSource()) results->set(length++, script);
1643  }
1644  }
1645  return FixedArray::ShrinkOrEmpty(isolate_, results, length);
1646 }
1647 
1648 void Debug::OnThrow(Handle<Object> exception) {
1649  if (in_debug_scope() || ignore_events()) return;
1650  // Temporarily clear any scheduled_exception to allow evaluating
1651  // JavaScript from the debug event handler.
1652  HandleScope scope(isolate_);
1653  Handle<Object> scheduled_exception;
1654  if (isolate_->has_scheduled_exception()) {
1655  scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1656  isolate_->clear_scheduled_exception();
1657  }
1658  Handle<Object> maybe_promise = isolate_->GetPromiseOnStackOnThrow();
1659  OnException(exception, maybe_promise,
1660  maybe_promise->IsJSPromise() ? v8::debug::kPromiseRejection
1661  : v8::debug::kException);
1662  if (!scheduled_exception.is_null()) {
1663  isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1664  }
1665  PrepareStepOnThrow();
1666 }
1667 
1668 void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {
1669  if (in_debug_scope() || ignore_events()) return;
1670  HandleScope scope(isolate_);
1671  // Check whether the promise has been marked as having triggered a message.
1672  Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1673  if (!promise->IsJSObject() ||
1674  JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
1675  ->IsUndefined(isolate_)) {
1676  OnException(value, promise, v8::debug::kPromiseRejection);
1677  }
1678 }
1679 
1680 bool Debug::IsExceptionBlackboxed(bool uncaught) {
1681  // Uncaught exception is blackboxed if all current frames are blackboxed,
1682  // caught exception if top frame is blackboxed.
1683  StackTraceFrameIterator it(isolate_);
1684  while (!it.done() && it.is_wasm()) it.Advance();
1685  bool is_top_frame_blackboxed =
1686  !it.done() ? IsFrameBlackboxed(it.javascript_frame()) : true;
1687  if (!uncaught || !is_top_frame_blackboxed) return is_top_frame_blackboxed;
1688  return AllFramesOnStackAreBlackboxed();
1689 }
1690 
1691 bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
1692  HandleScope scope(isolate_);
1693  std::vector<Handle<SharedFunctionInfo>> infos;
1694  frame->GetFunctions(&infos);
1695  for (const auto& info : infos) {
1696  if (!IsBlackboxed(info)) return false;
1697  }
1698  return true;
1699 }
1700 
1701 void Debug::OnException(Handle<Object> exception, Handle<Object> promise,
1702  v8::debug::ExceptionType exception_type) {
1703  // TODO(kozyatinskiy): regress-662674.js test fails on arm without this.
1704  if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
1705 
1706  Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1707 
1708  // Don't notify listener of exceptions that are internal to a desugaring.
1709  if (catch_type == Isolate::CAUGHT_BY_DESUGARING) return;
1710 
1711  bool uncaught = catch_type == Isolate::NOT_CAUGHT;
1712  if (promise->IsJSObject()) {
1713  Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1714  // Mark the promise as already having triggered a message.
1715  Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1716  JSObject::SetProperty(isolate_, jspromise, key, key, LanguageMode::kStrict)
1717  .Assert();
1718  // Check whether the promise reject is considered an uncaught exception.
1719  uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
1720  }
1721 
1722  if (!debug_delegate_) return;
1723 
1724  // Bail out if exception breaks are not active
1725  if (uncaught) {
1726  // Uncaught exceptions are reported by either flags.
1727  if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1728  } else {
1729  // Caught exceptions are reported is activated.
1730  if (!break_on_exception_) return;
1731  }
1732 
1733  {
1734  JavaScriptFrameIterator it(isolate_);
1735  // Check whether the top frame is blackboxed or the break location is muted.
1736  if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) ||
1737  IsExceptionBlackboxed(uncaught))) {
1738  return;
1739  }
1740  if (it.done()) return; // Do not trigger an event with an empty stack.
1741  }
1742 
1743  DebugScope debug_scope(this);
1744  HandleScope scope(isolate_);
1745  DisableBreak no_recursive_break(this);
1746 
1747  Handle<Context> native_context(isolate_->native_context());
1748  debug_delegate_->ExceptionThrown(
1749  v8::Utils::ToLocal(native_context), v8::Utils::ToLocal(exception),
1750  v8::Utils::ToLocal(promise), uncaught, exception_type);
1751 }
1752 
1753 void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
1754  DCHECK(!break_points_hit.is_null());
1755  // The caller provided for DebugScope.
1756  AssertDebugContext();
1757  // Bail out if there is no listener for this event
1758  if (ignore_events()) return;
1759 
1760 #ifdef DEBUG
1761  PrintBreakLocation();
1762 #endif // DEBUG
1763 
1764  if (!debug_delegate_) return;
1765  DCHECK(in_debug_scope());
1766  HandleScope scope(isolate_);
1767  DisableBreak no_recursive_break(this);
1768 
1769  std::vector<int> inspector_break_points_hit;
1770  int inspector_break_points_count = 0;
1771  // This array contains breakpoints installed using JS debug API.
1772  for (int i = 0; i < break_points_hit->length(); ++i) {
1773  BreakPoint* break_point = BreakPoint::cast(break_points_hit->get(i));
1774  inspector_break_points_hit.push_back(break_point->id());
1775  ++inspector_break_points_count;
1776  }
1777 
1778  Handle<Context> native_context(isolate_->native_context());
1779  debug_delegate_->BreakProgramRequested(v8::Utils::ToLocal(native_context),
1780  inspector_break_points_hit);
1781 }
1782 
1783 namespace {
1784 debug::Location GetDebugLocation(Handle<Script> script, int source_position) {
1785  Script::PositionInfo info;
1786  Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
1787  // V8 provides ScriptCompiler::CompileFunctionInContext method which takes
1788  // expression and compile it as anonymous function like (function() ..
1789  // expression ..). To produce correct locations for stmts inside of this
1790  // expression V8 compile this function with negative offset. Instead of stmt
1791  // position blackboxing use function start position which is negative in
1792  // described case.
1793  return debug::Location(std::max(info.line, 0), std::max(info.column, 0));
1794 }
1795 } // namespace
1796 
1797 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
1798  if (!debug_delegate_) return !shared->IsSubjectToDebugging();
1799  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
1800  if (!debug_info->computed_debug_is_blackboxed()) {
1801  bool is_blackboxed =
1802  !shared->IsSubjectToDebugging() || !shared->script()->IsScript();
1803  if (!is_blackboxed) {
1804  SuppressDebug while_processing(this);
1805  HandleScope handle_scope(isolate_);
1806  PostponeInterruptsScope no_interrupts(isolate_);
1807  DisableBreak no_recursive_break(this);
1808  DCHECK(shared->script()->IsScript());
1809  Handle<Script> script(Script::cast(shared->script()), isolate_);
1810  DCHECK(script->IsUserJavaScript());
1811  debug::Location start = GetDebugLocation(script, shared->StartPosition());
1812  debug::Location end = GetDebugLocation(script, shared->EndPosition());
1813  is_blackboxed = debug_delegate_->IsFunctionBlackboxed(
1814  ToApiHandle<debug::Script>(script), start, end);
1815  }
1816  debug_info->set_debug_is_blackboxed(is_blackboxed);
1817  debug_info->set_computed_debug_is_blackboxed(true);
1818  }
1819  return debug_info->debug_is_blackboxed();
1820 }
1821 
1822 bool Debug::AllFramesOnStackAreBlackboxed() {
1823  HandleScope scope(isolate_);
1824  for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
1825  if (!it.is_javascript()) continue;
1826  if (!IsFrameBlackboxed(it.javascript_frame())) return false;
1827  }
1828  return true;
1829 }
1830 
1831 bool Debug::CanBreakAtEntry(Handle<SharedFunctionInfo> shared) {
1832  // Allow break at entry for builtin functions.
1833  if (shared->native() || shared->IsApiFunction()) {
1834  // Functions that are subject to debugging can have regular breakpoints.
1835  DCHECK(!shared->IsSubjectToDebugging());
1836  return true;
1837  }
1838  return false;
1839 }
1840 
1841 bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
1842  bool preview, debug::LiveEditResult* result) {
1843  DebugScope debug_scope(this);
1844  running_live_edit_ = true;
1845  LiveEdit::PatchScript(isolate_, script, source, preview, result);
1846  running_live_edit_ = false;
1847  return result->status == debug::LiveEditResult::OK;
1848 }
1849 
1850 void Debug::OnCompileError(Handle<Script> script) {
1851  ProcessCompileEvent(true, script);
1852 }
1853 
1854 void Debug::OnAfterCompile(Handle<Script> script) {
1855  ProcessCompileEvent(false, script);
1856 }
1857 
1858 void Debug::ProcessCompileEvent(bool has_compile_error, Handle<Script> script) {
1859  // TODO(kozyatinskiy): teach devtools to work with liveedit scripts better
1860  // first and then remove this fast return.
1861  if (running_live_edit_) return;
1862  // Attach the correct debug id to the script. The debug id is used by the
1863  // inspector to filter scripts by native context.
1864  script->set_context_data(isolate_->native_context()->debug_context_id());
1865  if (ignore_events()) return;
1866  if (!script->IsUserJavaScript() && script->type() != i::Script::TYPE_WASM) {
1867  return;
1868  }
1869  if (!debug_delegate_) return;
1870  SuppressDebug while_processing(this);
1871  DebugScope debug_scope(this);
1872  HandleScope scope(isolate_);
1873  DisableBreak no_recursive_break(this);
1874  AllowJavascriptExecution allow_script(isolate_);
1875  debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1876  running_live_edit_, has_compile_error);
1877 }
1878 
1879 int Debug::CurrentFrameCount() {
1880  StackTraceFrameIterator it(isolate_);
1881  if (break_frame_id() != StackFrame::NO_ID) {
1882  // Skip to break frame.
1883  DCHECK(in_debug_scope());
1884  while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
1885  }
1886  int counter = 0;
1887  while (!it.done()) {
1888  if (it.frame()->is_optimized()) {
1889  std::vector<SharedFunctionInfo*> infos;
1890  OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
1891  counter += infos.size();
1892  } else {
1893  counter++;
1894  }
1895  it.Advance();
1896  }
1897  return counter;
1898 }
1899 
1900 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) {
1901  debug_delegate_ = delegate;
1902  UpdateState();
1903 }
1904 
1905 void Debug::UpdateState() {
1906  bool is_active = debug_delegate_ != nullptr;
1907  if (is_active == is_active_) return;
1908  if (is_active) {
1909  // Note that the debug context could have already been loaded to
1910  // bootstrap test cases.
1911  isolate_->compilation_cache()->Disable();
1912  is_active = true;
1913  feature_tracker()->Track(DebugFeatureTracker::kActive);
1914  } else {
1915  isolate_->compilation_cache()->Enable();
1916  Unload();
1917  }
1918  is_active_ = is_active;
1919  isolate_->PromiseHookStateUpdated();
1920 }
1921 
1922 void Debug::UpdateHookOnFunctionCall() {
1923  STATIC_ASSERT(LastStepAction == StepIn);
1924  hook_on_function_call_ =
1925  thread_local_.last_step_action_ == StepIn ||
1926  isolate_->debug_execution_mode() == DebugInfo::kSideEffects ||
1927  thread_local_.break_on_next_function_call_;
1928 }
1929 
1930 void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
1931  // Initialize LiveEdit.
1932  LiveEdit::InitializeThreadLocal(this);
1933  // Ignore debug break during bootstrapping.
1934  if (isolate_->bootstrapper()->IsActive()) return;
1935  // Just continue if breaks are disabled.
1936  if (break_disabled()) return;
1937  // Ignore debug break if debugger is not active.
1938  if (!is_active()) return;
1939 
1940  StackLimitCheck check(isolate_);
1941  if (check.HasOverflowed()) return;
1942 
1943  { JavaScriptFrameIterator it(isolate_);
1944  DCHECK(!it.done());
1945  Object* fun = it.frame()->function();
1946  if (fun && fun->IsJSFunction()) {
1947  HandleScope scope(isolate_);
1948  Handle<JSFunction> function(JSFunction::cast(fun), isolate_);
1949  // Don't stop in builtin and blackboxed functions.
1950  Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
1951  bool ignore_break = ignore_break_mode == kIgnoreIfTopFrameBlackboxed
1952  ? IsBlackboxed(shared)
1953  : AllFramesOnStackAreBlackboxed();
1954  if (ignore_break) return;
1955  // Don't stop if the break location is muted.
1956  if (IsMutedAtCurrentLocation(it.frame())) return;
1957  }
1958  }
1959 
1960  // Clear stepping to avoid duplicate breaks.
1961  ClearStepping();
1962 
1963  HandleScope scope(isolate_);
1964  DebugScope debug_scope(this);
1965 
1966  OnDebugBreak(isolate_->factory()->empty_fixed_array());
1967 }
1968 
1969 #ifdef DEBUG
1970 void Debug::PrintBreakLocation() {
1971  if (!FLAG_print_break_location) return;
1972  HandleScope scope(isolate_);
1973  StackTraceFrameIterator iterator(isolate_);
1974  if (iterator.done()) return;
1975  StandardFrame* frame = iterator.frame();
1976  FrameSummary summary = FrameSummary::GetTop(frame);
1977  int source_position = summary.SourcePosition();
1978  Handle<Object> script_obj = summary.script();
1979  PrintF("[debug] break in function '");
1980  summary.FunctionName()->PrintOn(stdout);
1981  PrintF("'.\n");
1982  if (script_obj->IsScript()) {
1983  Handle<Script> script = Handle<Script>::cast(script_obj);
1984  Handle<String> source(String::cast(script->source()), isolate_);
1985  Script::InitLineEnds(script);
1986  int line =
1987  Script::GetLineNumber(script, source_position) - script->line_offset();
1988  int column = Script::GetColumnNumber(script, source_position) -
1989  (line == 0 ? script->column_offset() : 0);
1990  Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()),
1991  isolate_);
1992  int line_start = line == 0 ? 0 : Smi::ToInt(line_ends->get(line - 1)) + 1;
1993  int line_end = Smi::ToInt(line_ends->get(line));
1994  DisallowHeapAllocation no_gc;
1995  String::FlatContent content = source->GetFlatContent();
1996  if (content.IsOneByte()) {
1997  PrintF("[debug] %.*s\n", line_end - line_start,
1998  content.ToOneByteVector().start() + line_start);
1999  PrintF("[debug] ");
2000  for (int i = 0; i < column; i++) PrintF(" ");
2001  PrintF("^\n");
2002  } else {
2003  PrintF("[debug] at line %d column %d\n", line, column);
2004  }
2005  }
2006 }
2007 #endif // DEBUG
2008 
2009 DebugScope::DebugScope(Debug* debug)
2010  : debug_(debug),
2011  prev_(reinterpret_cast<DebugScope*>(
2012  base::Relaxed_Load(&debug->thread_local_.current_debug_scope_))),
2013  no_interrupts_(debug_->isolate_) {
2014  // Link recursive debugger entry.
2015  base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
2016  reinterpret_cast<base::AtomicWord>(this));
2017 
2018  // Store the previous frame id and return value.
2019  break_frame_id_ = debug_->break_frame_id();
2020 
2021  // Create the new break info. If there is no proper frames there is no break
2022  // frame id.
2023  StackTraceFrameIterator it(isolate());
2024  bool has_frames = !it.done();
2025  debug_->thread_local_.break_frame_id_ =
2026  has_frames ? it.frame()->id() : StackFrame::NO_ID;
2027 
2028  debug_->UpdateState();
2029 }
2030 
2031 
2032 DebugScope::~DebugScope() {
2033  // Leaving this debugger entry.
2034  base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
2035  reinterpret_cast<base::AtomicWord>(prev_));
2036 
2037  // Restore to the previous break state.
2038  debug_->thread_local_.break_frame_id_ = break_frame_id_;
2039 
2040  debug_->UpdateState();
2041 }
2042 
2043 ReturnValueScope::ReturnValueScope(Debug* debug) : debug_(debug) {
2044  return_value_ = debug_->return_value_handle();
2045 }
2046 
2047 ReturnValueScope::~ReturnValueScope() {
2048  debug_->set_return_value(*return_value_);
2049 }
2050 
2051 void Debug::UpdateDebugInfosForExecutionMode() {
2052  // Walk all debug infos and update their execution mode if it is different
2053  // from the isolate execution mode.
2054  DebugInfoListNode* current = debug_info_list_;
2055  while (current != nullptr) {
2056  Handle<DebugInfo> debug_info = current->debug_info();
2057  if (debug_info->HasInstrumentedBytecodeArray() &&
2058  debug_info->DebugExecutionMode() != isolate_->debug_execution_mode()) {
2059  DCHECK(debug_info->shared()->HasBytecodeArray());
2060  if (isolate_->debug_execution_mode() == DebugInfo::kBreakpoints) {
2061  ClearSideEffectChecks(debug_info);
2062  ApplyBreakPoints(debug_info);
2063  } else {
2064  ClearBreakPoints(debug_info);
2065  ApplySideEffectChecks(debug_info);
2066  }
2067  }
2068  current = current->next();
2069  }
2070 }
2071 
2072 void Debug::StartSideEffectCheckMode() {
2073  DCHECK(isolate_->debug_execution_mode() != DebugInfo::kSideEffects);
2074  isolate_->set_debug_execution_mode(DebugInfo::kSideEffects);
2075  UpdateHookOnFunctionCall();
2076  side_effect_check_failed_ = false;
2077 
2078  DCHECK(!temporary_objects_);
2079  temporary_objects_.reset(new TemporaryObjectsTracker());
2080  isolate_->heap()->AddHeapObjectAllocationTracker(temporary_objects_.get());
2081  Handle<FixedArray> array(isolate_->native_context()->regexp_last_match_info(),
2082  isolate_);
2083  regexp_match_info_ =
2084  Handle<RegExpMatchInfo>::cast(isolate_->factory()->CopyFixedArray(array));
2085 
2086  // Update debug infos to have correct execution mode.
2087  UpdateDebugInfosForExecutionMode();
2088 }
2089 
2090 void Debug::StopSideEffectCheckMode() {
2091  DCHECK(isolate_->debug_execution_mode() == DebugInfo::kSideEffects);
2092  if (side_effect_check_failed_) {
2093  DCHECK(isolate_->has_pending_exception());
2094  DCHECK_EQ(ReadOnlyRoots(isolate_).termination_exception(),
2095  isolate_->pending_exception());
2096  // Convert the termination exception into a regular exception.
2097  isolate_->CancelTerminateExecution();
2098  isolate_->Throw(*isolate_->factory()->NewEvalError(
2099  MessageTemplate::kNoSideEffectDebugEvaluate));
2100  }
2101  isolate_->set_debug_execution_mode(DebugInfo::kBreakpoints);
2102  UpdateHookOnFunctionCall();
2103  side_effect_check_failed_ = false;
2104 
2105  DCHECK(temporary_objects_);
2106  isolate_->heap()->RemoveHeapObjectAllocationTracker(temporary_objects_.get());
2107  temporary_objects_.reset();
2108  isolate_->native_context()->set_regexp_last_match_info(*regexp_match_info_);
2109  regexp_match_info_ = Handle<RegExpMatchInfo>::null();
2110 
2111  // Update debug infos to have correct execution mode.
2112  UpdateDebugInfosForExecutionMode();
2113 }
2114 
2115 void Debug::ApplySideEffectChecks(Handle<DebugInfo> debug_info) {
2116  DCHECK(debug_info->HasInstrumentedBytecodeArray());
2117  Handle<BytecodeArray> debug_bytecode(debug_info->DebugBytecodeArray(),
2118  isolate_);
2119  DebugEvaluate::ApplySideEffectChecks(debug_bytecode);
2120  debug_info->SetDebugExecutionMode(DebugInfo::kSideEffects);
2121 }
2122 
2123 void Debug::ClearSideEffectChecks(Handle<DebugInfo> debug_info) {
2124  DCHECK(debug_info->HasInstrumentedBytecodeArray());
2125  Handle<BytecodeArray> debug_bytecode(debug_info->DebugBytecodeArray(),
2126  isolate_);
2127  Handle<BytecodeArray> original(debug_info->OriginalBytecodeArray(), isolate_);
2128  for (interpreter::BytecodeArrayIterator it(debug_bytecode); !it.done();
2129  it.Advance()) {
2130  // Restore from original. This may copy only the scaling prefix, which is
2131  // correct, since we patch scaling prefixes to debug breaks if exists.
2132  debug_bytecode->set(it.current_offset(),
2133  original->get(it.current_offset()));
2134  }
2135 }
2136 
2137 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function,
2138  Handle<Object> receiver) {
2139  DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2140  DisallowJavascriptExecution no_js(isolate_);
2141  if (!function->is_compiled() &&
2142  !Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
2143  return false;
2144  }
2145  Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
2146  Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
2147  DebugInfo::SideEffectState side_effect_state =
2148  debug_info->GetSideEffectState(isolate_);
2149  switch (side_effect_state) {
2150  case DebugInfo::kHasSideEffects:
2151  if (FLAG_trace_side_effect_free_debug_evaluate) {
2152  PrintF("[debug-evaluate] Function %s failed side effect check.\n",
2153  function->shared()->DebugName()->ToCString().get());
2154  }
2155  side_effect_check_failed_ = true;
2156  // Throw an uncatchable termination exception.
2157  isolate_->TerminateExecution();
2158  return false;
2159  case DebugInfo::kRequiresRuntimeChecks: {
2160  if (!shared->HasBytecodeArray()) {
2161  return PerformSideEffectCheckForObject(receiver);
2162  }
2163  // If function has bytecode array then prepare function for debug
2164  // execution to perform runtime side effect checks.
2165  DCHECK(shared->is_compiled());
2166  PrepareFunctionForDebugExecution(shared);
2167  ApplySideEffectChecks(debug_info);
2168  return true;
2169  }
2170  case DebugInfo::kHasNoSideEffect:
2171  return true;
2172  case DebugInfo::kNotComputed:
2173  UNREACHABLE();
2174  return false;
2175  }
2176  UNREACHABLE();
2177  return false;
2178 }
2179 
2180 Handle<Object> Debug::return_value_handle() {
2181  return handle(thread_local_.return_value_, isolate_);
2182 }
2183 
2184 bool Debug::PerformSideEffectCheckForCallback(
2185  Handle<Object> callback_info, Handle<Object> receiver,
2186  Debug::AccessorKind accessor_kind) {
2187  DCHECK_EQ(!receiver.is_null(), callback_info->IsAccessorInfo());
2188  DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2189  if (!callback_info.is_null() && callback_info->IsCallHandlerInfo() &&
2190  i::CallHandlerInfo::cast(*callback_info)->NextCallHasNoSideEffect()) {
2191  return true;
2192  }
2193  // TODO(7515): always pass a valid callback info object.
2194  if (!callback_info.is_null()) {
2195  if (callback_info->IsAccessorInfo()) {
2196  // List of whitelisted internal accessors can be found in accessors.h.
2197  AccessorInfo* info = AccessorInfo::cast(*callback_info);
2198  DCHECK_NE(kNotAccessor, accessor_kind);
2199  switch (accessor_kind == kSetter ? info->setter_side_effect_type()
2200  : info->getter_side_effect_type()) {
2201  case SideEffectType::kHasNoSideEffect:
2202  // We do not support setter accessors with no side effects, since
2203  // calling set accessors go through a store bytecode. Store bytecodes
2204  // are considered to cause side effects (to non-temporary objects).
2205  DCHECK_NE(kSetter, accessor_kind);
2206  return true;
2207  case SideEffectType::kHasSideEffectToReceiver:
2208  DCHECK(!receiver.is_null());
2209  if (PerformSideEffectCheckForObject(receiver)) return true;
2210  isolate_->OptionalRescheduleException(false);
2211  return false;
2212  case SideEffectType::kHasSideEffect:
2213  break;
2214  }
2215  if (FLAG_trace_side_effect_free_debug_evaluate) {
2216  PrintF("[debug-evaluate] API Callback '");
2217  info->name()->ShortPrint();
2218  PrintF("' may cause side effect.\n");
2219  }
2220  } else if (callback_info->IsInterceptorInfo()) {
2221  InterceptorInfo* info = InterceptorInfo::cast(*callback_info);
2222  if (info->has_no_side_effect()) return true;
2223  if (FLAG_trace_side_effect_free_debug_evaluate) {
2224  PrintF("[debug-evaluate] API Interceptor may cause side effect.\n");
2225  }
2226  } else if (callback_info->IsCallHandlerInfo()) {
2227  CallHandlerInfo* info = CallHandlerInfo::cast(*callback_info);
2228  if (info->IsSideEffectFreeCallHandlerInfo()) return true;
2229  if (FLAG_trace_side_effect_free_debug_evaluate) {
2230  PrintF("[debug-evaluate] API CallHandlerInfo may cause side effect.\n");
2231  }
2232  }
2233  }
2234  side_effect_check_failed_ = true;
2235  // Throw an uncatchable termination exception.
2236  isolate_->TerminateExecution();
2237  isolate_->OptionalRescheduleException(false);
2238  return false;
2239 }
2240 
2241 bool Debug::PerformSideEffectCheckAtBytecode(InterpretedFrame* frame) {
2242  using interpreter::Bytecode;
2243 
2244  DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2245  SharedFunctionInfo* shared = frame->function()->shared();
2246  BytecodeArray bytecode_array = shared->GetBytecodeArray();
2247  int offset = frame->GetBytecodeOffset();
2248  interpreter::BytecodeArrayAccessor bytecode_accessor(
2249  handle(bytecode_array, isolate_), offset);
2250 
2251  Bytecode bytecode = bytecode_accessor.current_bytecode();
2252  interpreter::Register reg;
2253  switch (bytecode) {
2254  case Bytecode::kStaCurrentContextSlot:
2255  reg = interpreter::Register::current_context();
2256  break;
2257  default:
2258  reg = bytecode_accessor.GetRegisterOperand(0);
2259  break;
2260  }
2261  Handle<Object> object =
2262  handle(frame->ReadInterpreterRegister(reg.index()), isolate_);
2263  return PerformSideEffectCheckForObject(object);
2264 }
2265 
2266 bool Debug::PerformSideEffectCheckForObject(Handle<Object> object) {
2267  DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects);
2268 
2269  // We expect no side-effects for primitives.
2270  if (object->IsNumber()) return true;
2271  if (object->IsName()) return true;
2272 
2273  if (temporary_objects_->HasObject(Handle<HeapObject>::cast(object))) {
2274  return true;
2275  }
2276 
2277  if (FLAG_trace_side_effect_free_debug_evaluate) {
2278  PrintF("[debug-evaluate] failed runtime side effect check.\n");
2279  }
2280  side_effect_check_failed_ = true;
2281  // Throw an uncatchable termination exception.
2282  isolate_->TerminateExecution();
2283  return false;
2284 }
2285 } // namespace internal
2286 } // namespace v8
Definition: v8.h:85
Definition: libplatform.h:13