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