LCOV - code coverage report
Current view: top level - src/debug - debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 982 1008 97.4 %
Date: 2019-03-21 Functions: 109 117 93.2 %

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

Generated by: LCOV version 1.10