LCOV - code coverage report
Current view: top level - src/debug - debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 996 1008 98.8 %
Date: 2017-10-20 Functions: 125 131 95.4 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/debug/debug.h"
       6             : 
       7             : #include <memory>
       8             : 
       9             : #include "src/api.h"
      10             : #include "src/arguments.h"
      11             : #include "src/assembler-inl.h"
      12             : #include "src/bootstrapper.h"
      13             : #include "src/code-stubs.h"
      14             : #include "src/compilation-cache.h"
      15             : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
      16             : #include "src/compiler.h"
      17             : #include "src/debug/debug-evaluate.h"
      18             : #include "src/debug/liveedit.h"
      19             : #include "src/deoptimizer.h"
      20             : #include "src/execution.h"
      21             : #include "src/frames-inl.h"
      22             : #include "src/global-handles.h"
      23             : #include "src/globals.h"
      24             : #include "src/interpreter/interpreter.h"
      25             : #include "src/isolate-inl.h"
      26             : #include "src/log.h"
      27             : #include "src/messages.h"
      28             : #include "src/objects/debug-objects-inl.h"
      29             : #include "src/snapshot/natives.h"
      30             : #include "src/wasm/wasm-objects-inl.h"
      31             : 
      32             : #include "include/v8-debug.h"
      33             : 
      34             : namespace v8 {
      35             : namespace internal {
      36             : 
      37       54999 : Debug::Debug(Isolate* isolate)
      38             :     : debug_context_(Handle<Context>()),
      39             :       is_active_(false),
      40             :       hook_on_function_call_(false),
      41             :       is_suppressed_(false),
      42             :       live_edit_enabled_(false),
      43             :       break_disabled_(false),
      44             :       break_points_active_(true),
      45             :       break_on_exception_(false),
      46             :       break_on_uncaught_exception_(false),
      47             :       side_effect_check_failed_(false),
      48             :       debug_info_list_(nullptr),
      49             :       feature_tracker_(isolate),
      50      109998 :       isolate_(isolate) {
      51       54999 :   ThreadInit();
      52       54999 : }
      53             : 
      54      245266 : BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
      55             :                                        JavaScriptFrame* frame) {
      56      245266 :   auto summary = FrameSummary::GetTop(frame).AsJavaScript();
      57             :   int offset = summary.code_offset();
      58      245266 :   Handle<AbstractCode> abstract_code = summary.abstract_code();
      59      245266 :   BreakIterator it(debug_info);
      60      245266 :   it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
      61      245266 :   return it.GetBreakLocation();
      62             : }
      63             : 
      64        2268 : void BreakLocation::AllAtCurrentStatement(
      65             :     Handle<DebugInfo> debug_info, JavaScriptFrame* frame,
      66             :     std::vector<BreakLocation>* result_out) {
      67        2268 :   auto summary = FrameSummary::GetTop(frame).AsJavaScript();
      68             :   int offset = summary.code_offset();
      69             :   Handle<AbstractCode> abstract_code = summary.abstract_code();
      70        2268 :   if (abstract_code->IsCode()) offset = offset - 1;
      71             :   int statement_position;
      72             :   {
      73        2268 :     BreakIterator it(debug_info);
      74        2268 :     it.SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
      75        2268 :     statement_position = it.statement_position();
      76             :   }
      77       23716 :   for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
      78        9590 :     if (it.statement_position() == statement_position) {
      79        4636 :       result_out->push_back(it.GetBreakLocation());
      80             :     }
      81             :   }
      82        2268 : }
      83             : 
      84      247534 : int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
      85             :                                             Handle<AbstractCode> abstract_code,
      86             :                                             int offset) {
      87             :   // Run through all break points to locate the one closest to the address.
      88             :   int closest_break = 0;
      89             :   int distance = kMaxInt;
      90             :   DCHECK(0 <= offset && offset < abstract_code->Size());
      91    18331322 :   for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
      92             :     // Check if this break point is closer that what was previously found.
      93     9164397 :     if (it.code_offset() <= offset && offset - it.code_offset() < distance) {
      94     9159516 :       closest_break = it.break_index();
      95     9159516 :       distance = offset - it.code_offset();
      96             :       // Check whether we can't get any closer.
      97     9159516 :       if (distance == 0) break;
      98             :     }
      99             :   }
     100      247534 :   return closest_break;
     101             : }
     102             : 
     103       60514 : bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
     104             :   // First check whether there is a break point with the same source position.
     105      121028 :   if (!debug_info->HasBreakPoint(position_)) return false;
     106             :   // Then check whether a break point at that source position would have
     107             :   // the same code offset. Otherwise it's just a break location that we can
     108             :   // step to, but not actually a location where we can put a break point.
     109             :   DCHECK(abstract_code_->IsBytecodeArray());
     110        4152 :   BreakIterator it(debug_info);
     111        4152 :   it.SkipToPosition(position_);
     112        4152 :   return it.code_offset() == code_offset_;
     113             : }
     114             : 
     115        3490 : debug::BreakLocationType BreakLocation::type() const {
     116        3490 :   switch (type_) {
     117             :     case DEBUGGER_STATEMENT:
     118             :       return debug::kDebuggerStatementBreakLocation;
     119             :     case DEBUG_BREAK_SLOT_AT_CALL:
     120             :       return debug::kCallBreakLocation;
     121             :     case DEBUG_BREAK_SLOT_AT_RETURN:
     122             :       return debug::kReturnBreakLocation;
     123             :     default:
     124             :       return debug::kCommonBreakLocation;
     125             :   }
     126             :   return debug::kCommonBreakLocation;
     127             : }
     128             : 
     129     1643909 : BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
     130             :     : debug_info_(debug_info),
     131             :       break_index_(-1),
     132             :       source_position_iterator_(
     133     3287818 :           debug_info->DebugBytecodeArray()->SourcePositionTable()) {
     134     1643909 :   position_ = debug_info->shared()->start_position();
     135     1643909 :   statement_position_ = position_;
     136             :   // There is at least one break location.
     137             :   DCHECK(!Done());
     138     1643909 :   Next();
     139     1643909 : }
     140             : 
     141      236426 : int BreakIterator::BreakIndexFromPosition(int source_position) {
     142             :   int distance = kMaxInt;
     143             :   int closest_break = break_index();
     144      170794 :   while (!Done()) {
     145             :     int next_position = position();
     146      180958 :     if (source_position <= next_position &&
     147       78275 :         next_position - source_position < distance) {
     148             :       closest_break = break_index();
     149             :       distance = next_position - source_position;
     150             :       // Check whether we can't get any closer.
     151       67313 :       if (distance == 0) break;
     152             :     }
     153       37934 :     Next();
     154             :   }
     155       66430 :   return closest_break;
     156             : }
     157             : 
     158    33505223 : void BreakIterator::Next() {
     159             :   DisallowHeapAllocation no_gc;
     160             :   DCHECK(!Done());
     161    33505223 :   bool first = break_index_ == -1;
     162    83528354 :   while (!Done()) {
     163   148031541 :     if (!first) source_position_iterator_.Advance();
     164             :     first = false;
     165    83528354 :     if (Done()) return;
     166    49004205 :     position_ = source_position_iterator_.source_position().ScriptOffset();
     167    49004205 :     if (source_position_iterator_.is_statement()) {
     168    31532918 :       statement_position_ = position_;
     169             :     }
     170             :     DCHECK_LE(0, position_);
     171             :     DCHECK_LE(0, statement_position_);
     172             : 
     173    49004205 :     DebugBreakType type = GetDebugBreakType();
     174    49004205 :     if (type != NOT_DEBUG_BREAK) break;
     175             :   }
     176    32486297 :   break_index_++;
     177             : }
     178             : 
     179    63269261 : DebugBreakType BreakIterator::GetDebugBreakType() {
     180             :   BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
     181             :   interpreter::Bytecode bytecode =
     182             :       interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
     183             : 
     184    63269261 :   if (bytecode == interpreter::Bytecode::kDebugger) {
     185             :     return DEBUGGER_STATEMENT;
     186    61942786 :   } else if (bytecode == interpreter::Bytecode::kReturn) {
     187             :     return DEBUG_BREAK_SLOT_AT_RETURN;
     188    59687221 :   } else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) {
     189             :     return DEBUG_BREAK_SLOT_AT_CALL;
     190    58086083 :   } else if (source_position_iterator_.is_statement()) {
     191             :     return DEBUG_BREAK_SLOT;
     192             :   } else {
     193    16517908 :     return NOT_DEBUG_BREAK;
     194             :   }
     195             : }
     196             : 
     197       66430 : void BreakIterator::SkipToPosition(int position) {
     198       66430 :   BreakIterator it(debug_info_);
     199       66430 :   SkipTo(it.BreakIndexFromPosition(position));
     200       66430 : }
     201             : 
     202     3723724 : void BreakIterator::SetDebugBreak() {
     203     3723724 :   DebugBreakType debug_break_type = GetDebugBreakType();
     204     3723724 :   if (debug_break_type == DEBUGGER_STATEMENT) return;
     205             :   DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
     206             :   BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
     207             :   interpreter::Bytecode bytecode =
     208             :       interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
     209     3704332 :   if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
     210             :   interpreter::Bytecode debugbreak =
     211     3677022 :       interpreter::Bytecodes::GetDebugBreak(bytecode);
     212             :   bytecode_array->set(code_offset(),
     213             :                       interpreter::Bytecodes::ToByte(debugbreak));
     214             : }
     215             : 
     216    10288268 : void BreakIterator::ClearDebugBreak() {
     217    10288268 :   DebugBreakType debug_break_type = GetDebugBreakType();
     218    20576536 :   if (debug_break_type == DEBUGGER_STATEMENT) return;
     219             :   DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
     220             :   BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
     221             :   BytecodeArray* original = debug_info_->OriginalBytecodeArray();
     222             :   bytecode_array->set(code_offset(), original->get(code_offset()));
     223             : }
     224             : 
     225      253064 : BreakLocation BreakIterator::GetBreakLocation() {
     226             :   Handle<AbstractCode> code(
     227             :       AbstractCode::cast(debug_info_->DebugBytecodeArray()));
     228      759192 :   return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
     229             : }
     230             : 
     231             : 
     232       64470 : void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
     233       64470 :   uint32_t mask = 1 << feature;
     234             :   // Only count one sample per feature and isolate.
     235      128940 :   if (bitfield_ & mask) return;
     236        8882 :   isolate_->counters()->debug_feature_usage()->AddSample(feature);
     237        4441 :   bitfield_ |= mask;
     238             : }
     239             : 
     240             : 
     241             : // Threading support.
     242      103325 : void Debug::ThreadInit() {
     243      103325 :   thread_local_.break_count_ = 0;
     244      103325 :   thread_local_.break_id_ = 0;
     245      103325 :   thread_local_.break_frame_id_ = StackFrame::NO_ID;
     246      103325 :   thread_local_.last_step_action_ = StepNone;
     247      103325 :   thread_local_.last_statement_position_ = kNoSourcePosition;
     248      103325 :   thread_local_.last_frame_count_ = -1;
     249      103325 :   thread_local_.fast_forward_to_return_ = false;
     250      103325 :   thread_local_.ignore_step_into_function_ = Smi::kZero;
     251      103325 :   thread_local_.target_frame_count_ = -1;
     252      103325 :   thread_local_.return_value_ = Smi::kZero;
     253      103325 :   thread_local_.async_task_count_ = 0;
     254      103325 :   thread_local_.last_breakpoint_id_ = 0;
     255             :   clear_suspended_generator();
     256      103325 :   thread_local_.restart_fp_ = nullptr;
     257             :   base::Relaxed_Store(&thread_local_.current_debug_scope_,
     258      103325 :                       static_cast<base::AtomicWord>(0));
     259             :   UpdateHookOnFunctionCall();
     260      103325 : }
     261             : 
     262             : 
     263       24163 : char* Debug::ArchiveDebug(char* storage) {
     264             :   // Simply reset state. Don't archive anything.
     265       24163 :   ThreadInit();
     266       24163 :   return storage + ArchiveSpacePerThread();
     267             : }
     268             : 
     269             : 
     270       24163 : char* Debug::RestoreDebug(char* storage) {
     271             :   // Simply reset state. Don't restore anything.
     272       24163 :   ThreadInit();
     273       24163 :   return storage + ArchiveSpacePerThread();
     274             : }
     275             : 
     276        1118 : int Debug::ArchiveSpacePerThread() { return 0; }
     277             : 
     278      232423 : void Debug::Iterate(RootVisitor* v) {
     279      232423 :   v->VisitRootPointer(Root::kDebug, &thread_local_.return_value_);
     280      232423 :   v->VisitRootPointer(Root::kDebug, &thread_local_.suspended_generator_);
     281      232423 :   v->VisitRootPointer(Root::kDebug, &thread_local_.ignore_step_into_function_);
     282      232423 : }
     283             : 
     284        9122 : DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info) : next_(nullptr) {
     285             :   // Globalize the request debug info object and make it weak.
     286        9122 :   GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
     287        9122 :   debug_info_ = global_handles->Create(debug_info).location();
     288        9122 : }
     289             : 
     290             : 
     291           0 : DebugInfoListNode::~DebugInfoListNode() {
     292        9122 :   if (debug_info_ == nullptr) return;
     293        9122 :   GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
     294        9122 :   debug_info_ = nullptr;
     295           0 : }
     296             : 
     297             : 
     298      327423 : bool Debug::Load() {
     299             :   // Return if debugger is already loaded.
     300      327423 :   if (is_loaded()) return true;
     301             : 
     302             :   // Bail out if we're already in the process of compiling the native
     303             :   // JavaScript source code for the debugger.
     304        5026 :   if (is_suppressed_) return false;
     305             :   SuppressDebug while_loading(this);
     306             : 
     307             :   // Disable breakpoints and interrupts while compiling and running the
     308             :   // debugger scripts including the context creation code.
     309             :   DisableBreak disable(this);
     310       13978 :   PostponeInterruptsScope postpone(isolate_);
     311             : 
     312             :   // Create the debugger context.
     313        5026 :   HandleScope scope(isolate_);
     314             :   ExtensionConfiguration no_extensions;
     315             :   // TODO(yangguo): we rely on the fact that first context snapshot is usable
     316             :   //                as debug context. This dependency is gone once we remove
     317             :   //                debug context completely.
     318             :   static const int kFirstContextSnapshotIndex = 0;
     319             :   Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
     320             :       MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
     321             :       kFirstContextSnapshotIndex, v8::DeserializeEmbedderFieldsCallback(),
     322       10052 :       DEBUG_CONTEXT);
     323             : 
     324             :   // Fail if no context could be created.
     325        5026 :   if (context.is_null()) return false;
     326             : 
     327        7852 :   debug_context_ = isolate_->global_handles()->Create(*context);
     328             : 
     329        3926 :   feature_tracker()->Track(DebugFeatureTracker::kActive);
     330             : 
     331        3926 :   return true;
     332             : }
     333             : 
     334             : 
     335       57185 : void Debug::Unload() {
     336       57185 :   ClearAllBreakPoints();
     337       57185 :   ClearStepping();
     338       57185 :   RemoveAllCoverageInfos();
     339       57185 :   RemoveDebugDelegate();
     340             : 
     341             :   // Return debugger is not loaded.
     342      114370 :   if (!is_loaded()) return;
     343             : 
     344             :   // Clear debugger context global handle.
     345        3926 :   GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
     346        3926 :   debug_context_ = Handle<Context>();
     347             : }
     348             : 
     349      171501 : void Debug::Break(JavaScriptFrame* frame) {
     350             :   // Initialize LiveEdit.
     351       58332 :   LiveEdit::InitializeThreadLocal(this);
     352             : 
     353             :   // Just continue if breaks are disabled or debugger cannot be loaded.
     354       62701 :   if (break_disabled()) return;
     355             : 
     356             :   // Enter the debugger.
     357       58314 :   DebugScope debug_scope(this);
     358       62665 :   if (debug_scope.failed()) return;
     359             : 
     360             :   // Postpone interrupt during breakpoint processing.
     361       58314 :   PostponeInterruptsScope postpone(isolate_);
     362             :   DisableBreak no_recursive_break(this);
     363             : 
     364             :   // Return if we fail to retrieve debug info.
     365       58314 :   Handle<JSFunction> function(frame->function());
     366             :   Handle<SharedFunctionInfo> shared(function->shared());
     367       58314 :   if (!EnsureBreakInfo(shared)) return;
     368      116628 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
     369             : 
     370             :   // Find the break location where execution has stopped.
     371       58314 :   BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
     372             : 
     373             :   // Find actual break points, if any, and trigger debug break event.
     374             :   MaybeHandle<FixedArray> break_points_hit =
     375       58314 :       CheckBreakPoints(debug_info, &location);
     376       58314 :   if (!break_points_hit.is_null()) {
     377             :     // Clear all current stepping setup.
     378        3477 :     ClearStepping();
     379             :     // Notify the debug event listeners.
     380        3477 :     OnDebugBreak(break_points_hit.ToHandleChecked());
     381        3477 :     return;
     382             :   }
     383             : 
     384             :   // No break point. Check for stepping.
     385             :   StepAction step_action = last_step_action();
     386       54837 :   int current_frame_count = CurrentFrameCount();
     387       54837 :   int target_frame_count = thread_local_.target_frame_count_;
     388       54837 :   int last_frame_count = thread_local_.last_frame_count_;
     389             : 
     390             :   // StepOut at not return position was requested and return break locations
     391             :   // were flooded with one shots.
     392       54837 :   if (thread_local_.fast_forward_to_return_) {
     393             :     DCHECK(location.IsReturn());
     394             :     // We have to ignore recursive calls to function.
     395         389 :     if (current_frame_count > target_frame_count) return;
     396         342 :     ClearStepping();
     397         342 :     PrepareStep(StepOut);
     398         342 :     return;
     399             :   }
     400             : 
     401             :   bool step_break = false;
     402       54448 :   switch (step_action) {
     403             :     case StepNone:
     404             :       return;
     405             :     case StepOut:
     406             :       // Step out should not break in a deeper frame than target frame.
     407           5 :       if (current_frame_count > target_frame_count) return;
     408             :       step_break = true;
     409             :       break;
     410             :     case StepNext:
     411             :       // Step next should not break in a deeper frame than target frame.
     412        8523 :       if (current_frame_count > target_frame_count) return;
     413             :     // Fall through.
     414             :     case StepIn: {
     415       53958 :       FrameSummary summary = FrameSummary::GetTop(frame);
     416       53958 :       step_break = step_break || location.IsReturn() ||
     417       42041 :                    current_frame_count != last_frame_count ||
     418       42041 :                    thread_local_.last_statement_position_ !=
     419       42041 :                        summary.SourceStatementPosition();
     420       53958 :       break;
     421             :     }
     422             :   }
     423             : 
     424             :   // Clear all current stepping setup.
     425       53963 :   ClearStepping();
     426             : 
     427       53963 :   if (step_break) {
     428             :     // Notify the debug event listeners.
     429       98754 :     OnDebugBreak(isolate_->factory()->empty_fixed_array());
     430             :   } else {
     431             :     // Re-prepare to continue.
     432        4586 :     PrepareStep(step_action);
     433       53963 :   }
     434             : }
     435             : 
     436             : 
     437             : // Find break point objects for this location, if any, and evaluate them.
     438             : // Return an array of break point objects that evaluated true, or an empty
     439             : // handle if none evaluated true.
     440       60627 : MaybeHandle<FixedArray> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
     441        4036 :                                                 BreakLocation* location,
     442             :                                                 bool* has_break_points) {
     443             :   bool has_break_points_to_check =
     444       60627 :       break_points_active_ && location->HasBreakPoint(debug_info);
     445       60627 :   if (has_break_points) *has_break_points = has_break_points_to_check;
     446       60627 :   if (!has_break_points_to_check) return {};
     447             : 
     448             :   Handle<Object> break_point_objects =
     449        4036 :       debug_info->GetBreakPointObjects(location->position());
     450        4036 :   return Debug::GetHitBreakPointObjects(break_point_objects);
     451             : }
     452             : 
     453             : 
     454       26528 : bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
     455       26528 :   HandleScope scope(isolate_);
     456             :   // A break location is considered muted if break locations on the current
     457             :   // statement have at least one break point, and all of these break points
     458             :   // evaluate to false. Aside from not triggering a debug break event at the
     459             :   // break location, we also do not trigger one for debugger statements, nor
     460             :   // an exception event on exception at this location.
     461       53056 :   FrameSummary summary = FrameSummary::GetTop(frame);
     462             :   DCHECK(!summary.IsWasm());
     463             :   Handle<JSFunction> function = summary.AsJavaScript().function();
     464       26528 :   if (!function->shared()->HasBreakInfo()) return false;
     465        2268 :   Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
     466             :   // Enter the debugger.
     467        4536 :   DebugScope debug_scope(this);
     468        2268 :   if (debug_scope.failed()) return false;
     469             :   std::vector<BreakLocation> break_locations;
     470        2268 :   BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
     471             :   bool has_break_points_at_all = false;
     472        9050 :   for (size_t i = 0; i < break_locations.size(); i++) {
     473             :     bool has_break_points;
     474             :     MaybeHandle<FixedArray> check_result =
     475        2313 :         CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
     476        2313 :     has_break_points_at_all |= has_break_points;
     477        2450 :     if (has_break_points && !check_result.is_null()) return false;
     478             :   }
     479             :   return has_break_points_at_all;
     480             : }
     481             : 
     482      116801 : MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
     483             :                                         Handle<Object> args[],
     484             :                                         bool catch_exceptions) {
     485             :   AllowJavascriptExecutionDebugOnly allow_script(isolate_);
     486      116801 :   PostponeInterruptsScope no_interrupts(isolate_);
     487             :   AssertDebugContext();
     488             :   Handle<JSReceiver> holder =
     489      116801 :       Handle<JSReceiver>::cast(isolate_->natives_utils_object());
     490             :   Handle<JSFunction> fun = Handle<JSFunction>::cast(
     491      233602 :       JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
     492      116801 :   Handle<Object> undefined = isolate_->factory()->undefined_value();
     493      116801 :   if (catch_exceptions) {
     494             :     MaybeHandle<Object> maybe_exception;
     495             :     return Execution::TryCall(isolate_, fun, undefined, argc, args,
     496             :                               Execution::MessageHandling::kReport,
     497      116766 :                               &maybe_exception);
     498             :   } else {
     499          35 :     return Execution::Call(isolate_, fun, undefined, argc, args);
     500             :   }
     501             : }
     502             : 
     503             : 
     504             : // Check whether a single break point object is triggered.
     505        5415 : bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
     506        4258 :   Factory* factory = isolate_->factory();
     507             :   HandleScope scope(isolate_);
     508             : 
     509             :   // TODO(kozyatinskiy): replace this if by DCHEK once the JS debug API has been
     510             :   // removed.
     511        4258 :   if (break_point_object->IsBreakPoint()) {
     512             :     Handle<BreakPoint> break_point =
     513             :         Handle<BreakPoint>::cast(break_point_object);
     514        2929 :     if (!break_point->condition()->length()) return true;
     515             :     Handle<String> condition(break_point->condition());
     516             :     Handle<Object> result;
     517             :     // Since we call CheckBreakpoint only for deoptimized frame on top of stack,
     518             :     // we can use 0 as index of inlined frame.
     519         798 :     if (!DebugEvaluate::Local(isolate_, break_frame_id(),
     520         798 :                               /* inlined_jsframe_index */ 0, condition, false)
     521        1596 :              .ToHandle(&result)) {
     522          18 :       if (isolate_->has_pending_exception()) {
     523          18 :         isolate_->clear_pending_exception();
     524             :       }
     525             :       return false;
     526             :     }
     527         780 :     return result->BooleanValue();
     528             :   }
     529             : 
     530             :   // Ignore check if break point object is not a JSObject.
     531        1329 :   if (!break_point_object->IsJSObject()) return true;
     532             : 
     533             :   // Get the break id as an object.
     534         359 :   Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
     535             : 
     536             :   // Call IsBreakPointTriggered.
     537         359 :   Handle<Object> argv[] = { break_id, break_point_object };
     538             :   Handle<Object> result;
     539         359 :   if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
     540         718 :            .ToHandle(&result)) {
     541             :     return false;
     542             :   }
     543             : 
     544             :   // Return whether the break point is triggered.
     545         718 :   return result->IsTrue(isolate_);
     546             : }
     547             : 
     548             : 
     549         280 : bool Debug::SetBreakPoint(Handle<JSFunction> function,
     550             :                           Handle<Object> break_point_object,
     551             :                           int* source_position) {
     552         280 :   HandleScope scope(isolate_);
     553             : 
     554             :   // Make sure the function is compiled and has set up the debug info.
     555             :   Handle<SharedFunctionInfo> shared(function->shared());
     556         280 :   if (!EnsureBreakInfo(shared)) return true;
     557         280 :   PrepareFunctionForBreakPoints(shared);
     558         280 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
     559             :   // Source positions starts with zero.
     560             :   DCHECK_LE(0, *source_position);
     561             : 
     562             :   // Find the break point and change it.
     563         560 :   *source_position = FindBreakablePosition(debug_info, *source_position);
     564         280 :   DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
     565             :   // At least one active break point now.
     566             :   DCHECK_LT(0, debug_info->GetBreakPointCount());
     567             : 
     568         280 :   ClearBreakPoints(debug_info);
     569         280 :   ApplyBreakPoints(debug_info);
     570             : 
     571         280 :   feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
     572         280 :   return true;
     573             : }
     574             : 
     575        2179 : bool Debug::SetBreakPointForScript(Handle<Script> script,
     576             :                                    Handle<Object> break_point_object,
     577             :                                    int* source_position) {
     578        2179 :   if (script->type() == Script::TYPE_WASM) {
     579             :     Handle<WasmCompiledModule> compiled_module(
     580          70 :         WasmCompiledModule::cast(script->wasm_compiled_module()), isolate_);
     581             :     return WasmCompiledModule::SetBreakPoint(compiled_module, source_position,
     582          70 :                                              break_point_object);
     583             :   }
     584             : 
     585        2109 :   HandleScope scope(isolate_);
     586             : 
     587             :   // Obtain shared function info for the function.
     588             :   Handle<Object> result =
     589        2109 :       FindSharedFunctionInfoInScript(script, *source_position);
     590        4218 :   if (result->IsUndefined(isolate_)) return false;
     591             : 
     592             :   // Make sure the function has set up the debug info.
     593             :   Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
     594        2089 :   if (!EnsureBreakInfo(shared)) return false;
     595        2089 :   PrepareFunctionForBreakPoints(shared);
     596             : 
     597             :   // Find position within function. The script position might be before the
     598             :   // source position of the first function.
     599        2089 :   if (shared->start_position() > *source_position) {
     600          57 :     *source_position = shared->start_position();
     601             :   }
     602             : 
     603        2089 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
     604             : 
     605             :   // Find breakable position returns first breakable position after
     606             :   // *source_position, it can return 0 if no break location is found after
     607             :   // *source_position.
     608        2089 :   int breakable_position = FindBreakablePosition(debug_info, *source_position);
     609        2089 :   if (breakable_position < *source_position) return false;
     610        2079 :   *source_position = breakable_position;
     611             : 
     612        2079 :   DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
     613             :   // At least one active break point now.
     614             :   DCHECK_LT(0, debug_info->GetBreakPointCount());
     615             : 
     616        2079 :   ClearBreakPoints(debug_info);
     617        2079 :   ApplyBreakPoints(debug_info);
     618             : 
     619        2079 :   feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
     620        2079 :   return true;
     621             : }
     622             : 
     623           0 : int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
     624             :                                  int source_position) {
     625             :   DCHECK(debug_info->HasDebugBytecodeArray());
     626        2369 :   BreakIterator it(debug_info);
     627        2369 :   it.SkipToPosition(source_position);
     628        2369 :   return it.position();
     629             : }
     630             : 
     631      942370 : void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
     632             :   DisallowHeapAllocation no_gc;
     633     2827110 :   if (debug_info->break_points()->IsUndefined(isolate_)) return;
     634             :   FixedArray* break_points = debug_info->break_points();
     635     9426260 :   for (int i = 0; i < break_points->length(); i++) {
     636    11252371 :     if (break_points->get(i)->IsUndefined(isolate_)) continue;
     637             :     BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
     638       60028 :     if (info->GetBreakPointCount() == 0) continue;
     639             :     DCHECK(debug_info->HasDebugBytecodeArray());
     640       59909 :     BreakIterator it(debug_info);
     641       59909 :     it.SkipToPosition(info->source_position());
     642       59909 :     it.SetDebugBreak();
     643             :   }
     644             : }
     645             : 
     646      950666 : void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
     647             :   // If we attempt to clear breakpoints but none exist, simply return. This can
     648             :   // happen e.g. CoverageInfos exit but no breakpoints are set.
     649     1901332 :   if (!debug_info->HasDebugBytecodeArray()) return;
     650             : 
     651             :   DisallowHeapAllocation no_gc;
     652    22477868 :   for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
     653    10288268 :     it.ClearDebugBreak();
     654             :   }
     655             : }
     656             : 
     657        2274 : void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
     658        2274 :   HandleScope scope(isolate_);
     659             : 
     660        3478 :   for (DebugInfoListNode* node = debug_info_list_; node != nullptr;
     661             :        node = node->next()) {
     662             :     Handle<Object> result =
     663        1204 :         DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
     664        2718 :     if (result->IsUndefined(isolate_)) continue;
     665             :     Handle<DebugInfo> debug_info = node->debug_info();
     666         894 :     if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
     667         894 :       ClearBreakPoints(debug_info);
     668         894 :       if (debug_info->GetBreakPointCount() == 0) {
     669         803 :         RemoveBreakInfoAndMaybeFree(debug_info);
     670             :       } else {
     671          91 :         ApplyBreakPoints(debug_info);
     672             :       }
     673        3168 :       return;
     674             :     }
     675             :   }
     676             : }
     677             : 
     678        1969 : bool Debug::SetBreakpoint(Handle<Script> script, Handle<String> condition,
     679             :                           int* offset, int* id) {
     680        1969 :   *id = ++thread_local_.last_breakpoint_id_;
     681             :   Handle<BreakPoint> breakpoint =
     682        1969 :       isolate_->factory()->NewBreakPoint(*id, condition);
     683        1969 :   return SetBreakPointForScript(script, breakpoint, offset);
     684             : }
     685             : 
     686        1949 : void Debug::RemoveBreakpoint(int id) {
     687             :   Handle<BreakPoint> breakpoint = isolate_->factory()->NewBreakPoint(
     688        3898 :       id, isolate_->factory()->empty_string());
     689        1949 :   ClearBreakPoint(breakpoint);
     690        1949 : }
     691             : 
     692             : // Clear out all the debug break code.
     693       57185 : void Debug::ClearAllBreakPoints() {
     694        7493 :   ClearAllDebugInfos([=](Handle<DebugInfo> info) {
     695        7493 :     ClearBreakPoints(info);
     696        7493 :     return info->ClearBreakInfo();
     697      114370 :   });
     698       57185 : }
     699             : 
     700       62117 : void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
     701             :                              bool returns_only) {
     702       62122 :   if (IsBlackboxed(shared)) return;
     703             :   // Make sure the function is compiled and has set up the debug info.
     704       62112 :   if (!EnsureBreakInfo(shared)) return;
     705       62112 :   PrepareFunctionForBreakPoints(shared);
     706       62112 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
     707             :   // Flood the function with break points.
     708             :   DCHECK(debug_info->HasDebugBytecodeArray());
     709     7454220 :   for (BreakIterator it(debug_info); !it.Done(); it.Next()) {
     710     3664998 :     if (returns_only && !it.GetBreakLocation().IsReturn()) continue;
     711     3663815 :     it.SetDebugBreak();
     712             :   }
     713             : }
     714             : 
     715       14142 : void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
     716       14142 :   if (type == BreakUncaughtException) {
     717        7071 :     break_on_uncaught_exception_ = enable;
     718             :   } else {
     719        7071 :     break_on_exception_ = enable;
     720             :   }
     721       14142 : }
     722             : 
     723             : 
     724        3303 : bool Debug::IsBreakOnException(ExceptionBreakType type) {
     725        3303 :   if (type == BreakUncaughtException) {
     726        1080 :     return break_on_uncaught_exception_;
     727             :   } else {
     728        2223 :     return break_on_exception_;
     729             :   }
     730             : }
     731             : 
     732        4145 : MaybeHandle<FixedArray> Debug::GetHitBreakPointObjects(
     733             :     Handle<Object> break_point_objects) {
     734             :   DCHECK(!break_point_objects->IsUndefined(isolate_));
     735        4145 :   if (!break_point_objects->IsFixedArray()) {
     736        4077 :     if (!CheckBreakPoint(break_point_objects)) return {};
     737        3579 :     Handle<FixedArray> break_points_hit = isolate_->factory()->NewFixedArray(1);
     738        3579 :     break_points_hit->set(0, *break_point_objects);
     739        3579 :     return break_points_hit;
     740             :   }
     741             : 
     742             :   Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
     743             :   int num_objects = array->length();
     744             :   Handle<FixedArray> break_points_hit =
     745          68 :       isolate_->factory()->NewFixedArray(num_objects);
     746             :   int break_points_hit_count = 0;
     747         249 :   for (int i = 0; i < num_objects; ++i) {
     748         181 :     Handle<Object> break_point_object(array->get(i), isolate_);
     749         181 :     if (CheckBreakPoint(break_point_object)) {
     750         342 :       break_points_hit->set(break_points_hit_count++, *break_point_object);
     751             :     }
     752             :   }
     753          68 :   if (break_points_hit_count == 0) return {};
     754          63 :   break_points_hit->Shrink(break_points_hit_count);
     755          63 :   return break_points_hit;
     756             : }
     757             : 
     758      925223 : void Debug::PrepareStepIn(Handle<JSFunction> function) {
     759      456792 :   CHECK(last_step_action() >= StepIn);
     760      908178 :   if (ignore_events()) return;
     761      444793 :   if (in_debug_scope()) return;
     762       11639 :   if (break_disabled()) return;
     763             :   Handle<SharedFunctionInfo> shared(function->shared());
     764       11639 :   if (IsBlackboxed(shared)) return;
     765        5431 :   if (*function == thread_local_.ignore_step_into_function_) return;
     766        5406 :   thread_local_.ignore_step_into_function_ = Smi::kZero;
     767       10812 :   FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
     768             : }
     769             : 
     770         771 : void Debug::PrepareStepInSuspendedGenerator() {
     771         257 :   CHECK(has_suspended_generator());
     772         257 :   if (ignore_events()) return;
     773         257 :   if (in_debug_scope()) return;
     774         257 :   if (break_disabled()) return;
     775         257 :   thread_local_.last_step_action_ = StepIn;
     776             :   UpdateHookOnFunctionCall();
     777             :   Handle<JSFunction> function(
     778         257 :       JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
     779         514 :   FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
     780             :   clear_suspended_generator();
     781             : }
     782             : 
     783        6045 : void Debug::PrepareStepOnThrow() {
     784        7511 :   if (last_step_action() == StepNone) return;
     785         569 :   if (ignore_events()) return;
     786         569 :   if (in_debug_scope()) return;
     787         569 :   if (break_disabled()) return;
     788             : 
     789         569 :   ClearOneShot();
     790             : 
     791         569 :   int current_frame_count = CurrentFrameCount();
     792             : 
     793             :   // Iterate through the JavaScript stack looking for handlers.
     794         569 :   JavaScriptFrameIterator it(isolate_);
     795        1222 :   while (!it.done()) {
     796             :     JavaScriptFrame* frame = it.frame();
     797         638 :     if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
     798             :     std::vector<SharedFunctionInfo*> infos;
     799          84 :     frame->GetFunctions(&infos);
     800         168 :     current_frame_count -= infos.size();
     801          84 :     it.Advance();
     802             :   }
     803             : 
     804             :   // No handler found. Nothing to instrument.
     805         569 :   if (it.done()) return;
     806             : 
     807             :   bool found_handler = false;
     808             :   // Iterate frames, including inlined frames. First, find the handler frame.
     809             :   // Then skip to the frame we want to break in, then instrument for stepping.
     810         638 :   for (; !it.done(); it.Advance()) {
     811             :     JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
     812         569 :     if (last_step_action() == StepIn) {
     813             :       // Deoptimize frame to ensure calls are checked for step-in.
     814         516 :       Deoptimizer::DeoptimizeFunction(frame->function());
     815             :     }
     816             :     std::vector<FrameSummary> summaries;
     817         569 :     frame->Summarize(&summaries);
     818        1187 :     for (size_t i = summaries.size(); i != 0; i--, current_frame_count--) {
     819         576 :       const FrameSummary& summary = summaries[i - 1];
     820         576 :       if (!found_handler) {
     821             :         // We have yet to find the handler. If the frame inlines multiple
     822             :         // functions, we have to check each one for the handler.
     823             :         // If it only contains one function, we already found the handler.
     824        1122 :         if (summaries.size() > 1) {
     825             :           Handle<AbstractCode> code = summary.AsJavaScript().abstract_code();
     826          14 :           CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
     827             :           BytecodeArray* bytecode = code->GetBytecodeArray();
     828             :           HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
     829          14 :           int code_offset = summary.code_offset();
     830             :           HandlerTable::CatchPrediction prediction;
     831          14 :           int index = table->LookupRange(code_offset, nullptr, &prediction);
     832          14 :           if (index > 0) found_handler = true;
     833             :         } else {
     834             :           found_handler = true;
     835             :         }
     836             :       }
     837             : 
     838         576 :       if (found_handler) {
     839             :         // We found the handler. If we are stepping next or out, we need to
     840             :         // iterate until we found the suitable target frame to break in.
     841         622 :         if ((last_step_action() == StepNext || last_step_action() == StepOut) &&
     842          53 :             current_frame_count > thread_local_.target_frame_count_) {
     843          42 :           continue;
     844             :         }
     845             :         Handle<SharedFunctionInfo> info(
     846             :             summary.AsJavaScript().function()->shared());
     847         554 :         if (IsBlackboxed(info)) continue;
     848         527 :         FloodWithOneShot(info);
     849         527 :         return;
     850             :       }
     851             :     }
     852          42 :   }
     853             : }
     854             : 
     855             : 
     856      129107 : void Debug::PrepareStep(StepAction step_action) {
     857       57045 :   HandleScope scope(isolate_);
     858             : 
     859             :   DCHECK(in_debug_scope());
     860             : 
     861             :   // Get the frame where the execution has stopped and skip the debug frame if
     862             :   // any. The debug frame will only be present if execution was stopped due to
     863             :   // hitting a break point. In other situations (e.g. unhandled exception) the
     864             :   // debug frame is not present.
     865             :   StackFrame::Id frame_id = break_frame_id();
     866             :   // If there is no JavaScript stack don't do anything.
     867       57045 :   if (frame_id == StackFrame::NO_ID) return;
     868             : 
     869       57045 :   feature_tracker()->Track(DebugFeatureTracker::kStepping);
     870             : 
     871       57045 :   thread_local_.last_step_action_ = step_action;
     872             : 
     873       57045 :   StackTraceFrameIterator frames_it(isolate_, frame_id);
     874             :   StandardFrame* frame = frames_it.frame();
     875             : 
     876             :   // Handle stepping in wasm functions via the wasm interpreter.
     877      114090 :   if (frame->is_wasm()) {
     878             :     // If the top frame is compiled, we cannot step.
     879         261 :     if (frame->is_wasm_compiled()) return;
     880             :     WasmInterpreterEntryFrame* wasm_frame =
     881             :         WasmInterpreterEntryFrame::cast(frame);
     882         522 :     wasm_frame->wasm_instance()->debug_info()->PrepareStep(step_action);
     883         261 :     return;
     884             :   }
     885             : 
     886             :   JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
     887             :   DCHECK(js_frame->function()->IsJSFunction());
     888             : 
     889             :   // Get the debug info (create it if it does not exist).
     890       56784 :   auto summary = FrameSummary::GetTop(frame).AsJavaScript();
     891             :   Handle<JSFunction> function(summary.function());
     892             :   Handle<SharedFunctionInfo> shared(function->shared());
     893       56784 :   if (!EnsureBreakInfo(shared)) return;
     894       56784 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
     895             : 
     896       56784 :   BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame);
     897             : 
     898             :   // Any step at a return is a step-out and we need to schedule DebugOnFunction
     899             :   // call callback.
     900       56784 :   if (location.IsReturn()) {
     901             :     // On StepOut we'll ignore our further calls to current function in
     902             :     // PrepareStepIn callback.
     903        5199 :     if (last_step_action() == StepOut) {
     904         441 :       thread_local_.ignore_step_into_function_ = *function;
     905             :     }
     906             :     step_action = StepOut;
     907        5199 :     thread_local_.last_step_action_ = StepIn;
     908             :   }
     909             :   UpdateHookOnFunctionCall();
     910             : 
     911             :   // A step-next in blackboxed function is a step-out.
     912       56784 :   if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut;
     913             : 
     914             :   thread_local_.last_statement_position_ =
     915       56784 :       summary.abstract_code()->SourceStatementPosition(summary.code_offset());
     916       56784 :   int current_frame_count = CurrentFrameCount();
     917       56784 :   thread_local_.last_frame_count_ = current_frame_count;
     918             :   // No longer perform the current async step.
     919             :   clear_suspended_generator();
     920             : 
     921       56784 :   switch (step_action) {
     922             :     case StepNone:
     923           0 :       UNREACHABLE();
     924             :       break;
     925             :     case StepOut: {
     926             :       // Clear last position info. For stepping out it does not matter.
     927        5560 :       thread_local_.last_statement_position_ = kNoSourcePosition;
     928        5560 :       thread_local_.last_frame_count_ = -1;
     929        5560 :       if (!location.IsReturn() && !IsBlackboxed(shared)) {
     930             :         // At not return position we flood return positions with one shots and
     931             :         // will repeat StepOut automatically at next break.
     932         351 :         thread_local_.target_frame_count_ = current_frame_count;
     933         351 :         thread_local_.fast_forward_to_return_ = true;
     934         351 :         FloodWithOneShot(shared, true);
     935         351 :         return;
     936             :       }
     937             :       // Skip the current frame, find the first frame we want to step out to
     938             :       // and deoptimize every frame along the way.
     939             :       bool in_current_frame = true;
     940       16141 :       for (; !frames_it.done(); frames_it.Advance()) {
     941             :         // TODO(clemensh): Implement stepping out from JS to wasm.
     942       19636 :         if (frames_it.frame()->is_wasm()) continue;
     943             :         JavaScriptFrame* frame = JavaScriptFrame::cast(frames_it.frame());
     944        9818 :         if (last_step_action() == StepIn) {
     945             :           // Deoptimize frame to ensure calls are checked for step-in.
     946        9798 :           Deoptimizer::DeoptimizeFunction(frame->function());
     947             :         }
     948        9818 :         HandleScope scope(isolate_);
     949             :         std::vector<Handle<SharedFunctionInfo>> infos;
     950        9818 :         frame->GetFunctions(&infos);
     951       30568 :         for (; !infos.empty(); current_frame_count--) {
     952        9818 :           Handle<SharedFunctionInfo> info = infos.back();
     953             :           infos.pop_back();
     954        9818 :           if (in_current_frame) {
     955             :             // We want to skip out, so skip the current frame.
     956             :             in_current_frame = false;
     957        5466 :             continue;
     958             :           }
     959        4609 :           if (IsBlackboxed(info)) continue;
     960        4352 :           FloodWithOneShot(info);
     961        4352 :           thread_local_.target_frame_count_ = current_frame_count;
     962        4352 :           return;
     963             :         }
     964             :       }
     965             :       break;
     966             :     }
     967             :     case StepNext:
     968        8598 :       thread_local_.target_frame_count_ = current_frame_count;
     969             :     // Fall through.
     970             :     case StepIn:
     971             :       // TODO(clemensh): Implement stepping from JS into wasm.
     972       51224 :       FloodWithOneShot(shared);
     973       51224 :       break;
     974             :   }
     975             : }
     976             : 
     977             : // Simple function for returning the source positions for active break points.
     978         252 : Handle<Object> Debug::GetSourceBreakLocations(
     979             :     Handle<SharedFunctionInfo> shared) {
     980             :   Isolate* isolate = shared->GetIsolate();
     981         252 :   if (!shared->HasBreakInfo()) {
     982          36 :     return isolate->factory()->undefined_value();
     983             :   }
     984         216 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
     985         216 :   if (debug_info->GetBreakPointCount() == 0) {
     986           0 :     return isolate->factory()->undefined_value();
     987             :   }
     988             :   Handle<FixedArray> locations =
     989         216 :       isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
     990             :   int count = 0;
     991        2160 :   for (int i = 0; i < debug_info->break_points()->length(); ++i) {
     992         864 :     if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
     993             :       BreakPointInfo* break_point_info =
     994             :           BreakPointInfo::cast(debug_info->break_points()->get(i));
     995         441 :       int break_points = break_point_info->GetBreakPointCount();
     996         441 :       if (break_points == 0) continue;
     997         369 :       for (int j = 0; j < break_points; ++j) {
     998             :         locations->set(count++,
     999         369 :                        Smi::FromInt(break_point_info->source_position()));
    1000             :       }
    1001             :     }
    1002             :   }
    1003         216 :   return locations;
    1004             : }
    1005             : 
    1006      179493 : void Debug::ClearStepping() {
    1007             :   // Clear the various stepping setup.
    1008      179493 :   ClearOneShot();
    1009             : 
    1010      179493 :   thread_local_.last_step_action_ = StepNone;
    1011      179493 :   thread_local_.last_statement_position_ = kNoSourcePosition;
    1012      179493 :   thread_local_.ignore_step_into_function_ = Smi::kZero;
    1013      179493 :   thread_local_.fast_forward_to_return_ = false;
    1014      179493 :   thread_local_.last_frame_count_ = -1;
    1015      179493 :   thread_local_.target_frame_count_ = -1;
    1016             :   UpdateHookOnFunctionCall();
    1017      179493 : }
    1018             : 
    1019             : 
    1020             : // Clears all the one-shot break points that are currently set. Normally this
    1021             : // function is called each time a break point is hit as one shot break points
    1022             : // are used to support stepping.
    1023      180062 : void Debug::ClearOneShot() {
    1024             :   // The current implementation just runs through all the breakpoints. When the
    1025             :   // last break point for a function is removed that function is automatically
    1026             :   // removed from the list.
    1027     1119982 :   for (DebugInfoListNode* node = debug_info_list_; node != nullptr;
    1028             :        node = node->next()) {
    1029      939920 :     Handle<DebugInfo> debug_info = node->debug_info();
    1030      939920 :     ClearBreakPoints(debug_info);
    1031      939920 :     ApplyBreakPoints(debug_info);
    1032             :   }
    1033      180062 : }
    1034             : 
    1035           0 : class RedirectActiveFunctions : public ThreadVisitor {
    1036             :  public:
    1037             :   explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
    1038        7733 :       : shared_(shared) {
    1039             :     DCHECK(shared->HasBytecodeArray());
    1040             :   }
    1041             : 
    1042        7733 :   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
    1043       70474 :     for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
    1044             :       JavaScriptFrame* frame = it.frame();
    1045       27504 :       JSFunction* function = frame->function();
    1046       55008 :       if (!frame->is_interpreted()) continue;
    1047       24755 :       if (function->shared() != shared_) continue;
    1048             :       InterpretedFrame* interpreted_frame =
    1049             :           reinterpret_cast<InterpretedFrame*>(frame);
    1050        1708 :       BytecodeArray* debug_copy = shared_->GetDebugInfo()->DebugBytecodeArray();
    1051        1708 :       interpreted_frame->PatchBytecodeArray(debug_copy);
    1052             :     }
    1053        7733 :   }
    1054             : 
    1055             :  private:
    1056             :   SharedFunctionInfo* shared_;
    1057             :   DisallowHeapAllocation no_gc_;
    1058             : };
    1059             : 
    1060        9227 : void Debug::DeoptimizeFunction(Handle<SharedFunctionInfo> shared) {
    1061             :   // Deoptimize all code compiled from this shared function info including
    1062             :   // inlining.
    1063        9227 :   if (isolate_->concurrent_recompilation_enabled()) {
    1064             :     isolate_->optimizing_compile_dispatcher()->Flush(
    1065        9227 :         OptimizingCompileDispatcher::BlockingBehavior::kBlock);
    1066             :   }
    1067             : 
    1068             :   // Make sure we abort incremental marking.
    1069             :   isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
    1070        9227 :                                       GarbageCollectionReason::kDebugger);
    1071             : 
    1072             :   bool found_something = false;
    1073        9227 :   Code::OptimizedCodeIterator iterator(isolate_);
    1074       57256 :   while (Code* code = iterator.Next()) {
    1075       48029 :     if (code->Inlines(*shared)) {
    1076             :       code->set_marked_for_deoptimization(true);
    1077             :       found_something = true;
    1078             :     }
    1079             :   }
    1080             : 
    1081        9227 :   if (found_something) {
    1082             :     // Only go through with the deoptimization if something was found.
    1083         342 :     Deoptimizer::DeoptimizeMarkedCode(isolate_);
    1084             :   }
    1085        9227 : }
    1086             : 
    1087       64481 : void Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
    1088             :   // To prepare bytecode for debugging, we already need to have the debug
    1089             :   // info (containing the debug copy) upfront, but since we do not recompile,
    1090             :   // preparing for break points cannot fail.
    1091             :   DCHECK(shared->is_compiled());
    1092             :   DCHECK(shared->HasDebugInfo());
    1093             :   DCHECK(shared->HasBreakInfo());
    1094       64481 :   Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
    1095      121229 :   if (debug_info->IsPreparedForBreakpoints()) return;
    1096             : 
    1097        7733 :   DeoptimizeFunction(shared);
    1098             :   // Update PCs on the stack to point to recompiled code.
    1099             :   RedirectActiveFunctions redirect_visitor(*shared);
    1100       15466 :   redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
    1101       15466 :   isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
    1102             : 
    1103             :   debug_info->set_flags(debug_info->flags() |
    1104        7733 :                         DebugInfo::kPreparedForBreakpoints);
    1105             : }
    1106             : 
    1107             : namespace {
    1108             : template <typename Iterator>
    1109        4560 : void GetBreakablePositions(Iterator* it, int start_position, int end_position,
    1110             :                            std::vector<BreakLocation>* locations) {
    1111        5490 :   while (!it->Done()) {
    1112        3630 :     if (it->position() >= start_position && it->position() < end_position) {
    1113        6980 :       locations->push_back(it->GetBreakLocation());
    1114             :     }
    1115        3630 :     it->Next();
    1116             :   }
    1117         930 : }
    1118             : 
    1119             : void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
    1120             :                             int end_position,
    1121             :                             std::vector<BreakLocation>* locations) {
    1122             :   DCHECK(debug_info->HasDebugBytecodeArray());
    1123         930 :   BreakIterator it(debug_info);
    1124         930 :   GetBreakablePositions(&it, start_position, end_position, locations);
    1125             : }
    1126             : }  // namespace
    1127             : 
    1128         200 : bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
    1129             :                                    int end_position, bool restrict_to_function,
    1130             :                                    std::vector<BreakLocation>* locations) {
    1131         200 :   if (restrict_to_function) {
    1132             :     Handle<Object> result =
    1133           5 :         FindSharedFunctionInfoInScript(script, start_position);
    1134          10 :     if (result->IsUndefined(isolate_)) return false;
    1135             : 
    1136             :     // Make sure the function has set up the debug info.
    1137             :     Handle<SharedFunctionInfo> shared =
    1138             :         Handle<SharedFunctionInfo>::cast(result);
    1139           5 :     if (!EnsureBreakInfo(shared)) return false;
    1140             : 
    1141           5 :     Handle<DebugInfo> debug_info(shared->GetDebugInfo());
    1142             :     FindBreakablePositions(debug_info, start_position, end_position, locations);
    1143           5 :     return true;
    1144             :   }
    1145             : 
    1146             :   while (true) {
    1147         415 :     HandleScope scope(isolate_);
    1148             :     std::vector<Handle<SharedFunctionInfo>> candidates;
    1149         415 :     SharedFunctionInfo::ScriptIterator iterator(script);
    1150        3140 :     for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
    1151             :          info = iterator.Next()) {
    1152        5420 :       if (info->end_position() < start_position ||
    1153             :           info->start_position() >= end_position) {
    1154             :         continue;
    1155             :       }
    1156        2570 :       if (!info->IsSubjectToDebugging()) continue;
    1157        3175 :       if (!info->is_compiled() && !info->allows_lazy_compilation()) continue;
    1158        5140 :       candidates.push_back(i::handle(info));
    1159             :     }
    1160             : 
    1161             :     bool was_compiled = false;
    1162        3395 :     for (const auto& candidate : candidates) {
    1163             :       // Code that cannot be compiled lazily are internal and not debuggable.
    1164             :       DCHECK(candidate->allows_lazy_compilation());
    1165        2570 :       if (!candidate->is_compiled()) {
    1166         605 :         if (!Compiler::Compile(candidate, Compiler::CLEAR_EXCEPTION)) {
    1167             :           return false;
    1168             :         } else {
    1169             :           was_compiled = true;
    1170             :         }
    1171             :       }
    1172        2565 :       if (!EnsureBreakInfo(candidate)) return false;
    1173             :     }
    1174         410 :     if (was_compiled) continue;
    1175             : 
    1176        1305 :     for (const auto& candidate : candidates) {
    1177         925 :       CHECK(candidate->HasBreakInfo());
    1178         925 :       Handle<DebugInfo> debug_info(candidate->GetDebugInfo());
    1179             :       FindBreakablePositions(debug_info, start_position, end_position,
    1180             :                              locations);
    1181             :     }
    1182             :     return true;
    1183             :   }
    1184         220 :   UNREACHABLE();
    1185             : }
    1186             : 
    1187         300 : void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) {
    1188         300 :   if (last_step_action() <= StepOut) return;
    1189             : 
    1190         300 :   if (last_step_action() == StepNext) {
    1191             :     // Only consider this generator a step-next target if not stepping in.
    1192         100 :     if (thread_local_.target_frame_count_ < CurrentFrameCount()) return;
    1193             :   }
    1194             : 
    1195             :   DCHECK(!has_suspended_generator());
    1196         271 :   thread_local_.suspended_generator_ = *generator_object;
    1197         271 :   ClearStepping();
    1198             : }
    1199             : 
    1200             : class SharedFunctionInfoFinder {
    1201             :  public:
    1202             :   explicit SharedFunctionInfoFinder(int target_position)
    1203             :       : current_candidate_(nullptr),
    1204             :         current_candidate_closure_(nullptr),
    1205             :         current_start_position_(kNoSourcePosition),
    1206        3493 :         target_position_(target_position) {}
    1207             : 
    1208       15365 :   void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = nullptr) {
    1209       15365 :     if (!shared->IsSubjectToDebugging()) return;
    1210             :     int start_position = shared->function_token_position();
    1211       15160 :     if (start_position == kNoSourcePosition) {
    1212             :       start_position = shared->start_position();
    1213             :     }
    1214             : 
    1215       15160 :     if (start_position > target_position_) return;
    1216       11376 :     if (target_position_ > shared->end_position()) return;
    1217             : 
    1218        6915 :     if (current_candidate_ != nullptr) {
    1219        4079 :       if (current_start_position_ == start_position &&
    1220             :           shared->end_position() == current_candidate_->end_position()) {
    1221             :         // If we already have a matching closure, do not throw it away.
    1222         331 :         if (current_candidate_closure_ != nullptr && closure == nullptr) return;
    1223             :         // If a top-level function contains only one function
    1224             :         // declaration the source for the top-level and the function
    1225             :         // is the same. In that case prefer the non top-level function.
    1226         331 :         if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
    1227        6222 :       } else if (start_position < current_start_position_ ||
    1228             :                  current_candidate_->end_position() < shared->end_position()) {
    1229             :         return;
    1230             :       }
    1231             :     }
    1232             : 
    1233        6915 :     current_start_position_ = start_position;
    1234        6915 :     current_candidate_ = shared;
    1235        6915 :     current_candidate_closure_ = closure;
    1236             :   }
    1237             : 
    1238             :   SharedFunctionInfo* Result() { return current_candidate_; }
    1239             : 
    1240             :   JSFunction* ResultClosure() { return current_candidate_closure_; }
    1241             : 
    1242             :  private:
    1243             :   SharedFunctionInfo* current_candidate_;
    1244             :   JSFunction* current_candidate_closure_;
    1245             :   int current_start_position_;
    1246             :   int target_position_;
    1247             :   DisallowHeapAllocation no_gc_;
    1248             : };
    1249             : 
    1250             : 
    1251             : // We need to find a SFI for a literal that may not yet have been compiled yet,
    1252             : // and there may not be a JSFunction referencing it. Find the SFI closest to
    1253             : // the given position, compile it to reveal possible inner SFIs and repeat.
    1254             : // While we are at this, also ensure code with debug break slots so that we do
    1255             : // not have to compile a SFI without JSFunction, which is paifu for those that
    1256             : // cannot be compiled without context (need to find outer compilable SFI etc.)
    1257        2420 : Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
    1258             :                                                      int position) {
    1259        1073 :   for (int iteration = 0;; iteration++) {
    1260             :     // Go through all shared function infos associated with this script to
    1261             :     // find the inner most function containing this position.
    1262             :     // If there is no shared function info for this script at all, there is
    1263             :     // no point in looking for it by walking the heap.
    1264             : 
    1265             :     SharedFunctionInfo* shared;
    1266             :     {
    1267             :       SharedFunctionInfoFinder finder(position);
    1268        3493 :       SharedFunctionInfo::ScriptIterator iterator(script);
    1269       18858 :       for (SharedFunctionInfo* info = iterator.Next(); info != nullptr;
    1270             :            info = iterator.Next()) {
    1271       15365 :         finder.NewCandidate(info);
    1272             :       }
    1273        3493 :       shared = finder.Result();
    1274        3493 :       if (shared == nullptr) break;
    1275             :       // We found it if it's already compiled.
    1276        3473 :       if (shared->is_compiled()) {
    1277             :         Handle<SharedFunctionInfo> shared_handle(shared);
    1278             :         // If the iteration count is larger than 1, we had to compile the outer
    1279             :         // function in order to create this shared function info. So there can
    1280             :         // be no JSFunction referencing it. We can anticipate creating a debug
    1281             :         // info while bypassing PrepareFunctionForBreakpoints.
    1282        2400 :         if (iteration > 1) {
    1283             :           AllowHeapAllocation allow_before_return;
    1284          58 :           CreateBreakInfo(shared_handle);
    1285             :         }
    1286        2400 :         return shared_handle;
    1287             :       }
    1288             :     }
    1289             :     // If not, compile to reveal inner functions.
    1290        1073 :     HandleScope scope(isolate_);
    1291             :     // Code that cannot be compiled lazily are internal and not debuggable.
    1292             :     DCHECK(shared->allows_lazy_compilation());
    1293        1073 :     if (!Compiler::Compile(handle(shared), Compiler::CLEAR_EXCEPTION)) break;
    1294        1073 :   }
    1295          40 :   return isolate_->factory()->undefined_value();
    1296             : }
    1297             : 
    1298             : 
    1299             : // Ensures the debug information is present for shared.
    1300      182154 : bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) {
    1301             :   // Return if we already have the break info for shared.
    1302      182154 :   if (shared->HasBreakInfo()) return true;
    1303        8283 :   if (!shared->IsSubjectToDebugging()) return false;
    1304        9707 :   if (!shared->is_compiled() &&
    1305        1424 :       !Compiler::Compile(shared, Compiler::CLEAR_EXCEPTION)) {
    1306             :     return false;
    1307             :   }
    1308        8283 :   CreateBreakInfo(shared);
    1309        8283 :   return true;
    1310             : }
    1311             : 
    1312        8341 : void Debug::CreateBreakInfo(Handle<SharedFunctionInfo> shared) {
    1313        8341 :   HandleScope scope(isolate_);
    1314        8341 :   Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
    1315             : 
    1316             :   // Initialize with break information.
    1317             : 
    1318             :   DCHECK(!debug_info->HasBreakInfo());
    1319             : 
    1320        8341 :   Factory* factory = isolate_->factory();
    1321             :   Handle<FixedArray> break_points(
    1322        8341 :       factory->NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction));
    1323             : 
    1324             :   // Make a copy of the bytecode array if available.
    1325             :   Handle<Object> maybe_debug_bytecode_array = factory->undefined_value();
    1326        8341 :   if (shared->HasBytecodeArray()) {
    1327             :     Handle<BytecodeArray> original(shared->bytecode_array());
    1328        8341 :     maybe_debug_bytecode_array = factory->CopyBytecodeArray(original);
    1329             :   }
    1330             : 
    1331        8341 :   debug_info->set_flags(debug_info->flags() | DebugInfo::kHasBreakInfo);
    1332        8341 :   debug_info->set_debug_bytecode_array(*maybe_debug_bytecode_array);
    1333        8341 :   debug_info->set_break_points(*break_points);
    1334        8341 : }
    1335             : 
    1336       73603 : Handle<DebugInfo> Debug::GetOrCreateDebugInfo(
    1337             :     Handle<SharedFunctionInfo> shared) {
    1338       73603 :   if (shared->HasDebugInfo()) return handle(shared->GetDebugInfo());
    1339             : 
    1340             :   // Create debug info and add it to the list.
    1341        9122 :   Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
    1342        9122 :   DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
    1343        9122 :   node->set_next(debug_info_list_);
    1344        9122 :   debug_info_list_ = node;
    1345             : 
    1346        9122 :   return debug_info;
    1347             : }
    1348             : 
    1349         781 : void Debug::InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
    1350             :                                 Handle<CoverageInfo> coverage_info) {
    1351             :   DCHECK(!coverage_info.is_null());
    1352             : 
    1353         781 :   Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
    1354             : 
    1355             :   DCHECK(!debug_info->HasCoverageInfo());
    1356             : 
    1357         781 :   debug_info->set_flags(debug_info->flags() | DebugInfo::kHasCoverageInfo);
    1358         781 :   debug_info->set_coverage_info(*coverage_info);
    1359         781 : }
    1360             : 
    1361       57471 : void Debug::RemoveAllCoverageInfos() {
    1362             :   ClearAllDebugInfos(
    1363      115723 :       [=](Handle<DebugInfo> info) { return info->ClearCoverageInfo(); });
    1364       57471 : }
    1365             : 
    1366         848 : void Debug::FindDebugInfo(Handle<DebugInfo> debug_info,
    1367             :                           DebugInfoListNode** prev, DebugInfoListNode** curr) {
    1368         848 :   HandleScope scope(isolate_);
    1369         848 :   *prev = nullptr;
    1370         848 :   *curr = debug_info_list_;
    1371        1886 :   while (*curr != nullptr) {
    1372        3114 :     if ((*curr)->debug_info().is_identical_to(debug_info)) return;
    1373         190 :     *prev = *curr;
    1374         380 :     *curr = (*curr)->next();
    1375             :   }
    1376             : 
    1377           0 :   UNREACHABLE();
    1378             : }
    1379             : 
    1380      114656 : void Debug::ClearAllDebugInfos(DebugInfoClearFunction clear_function) {
    1381             :   DebugInfoListNode* prev = nullptr;
    1382      122930 :   DebugInfoListNode* current = debug_info_list_;
    1383      237586 :   while (current != nullptr) {
    1384             :     DebugInfoListNode* next = current->next();
    1385        8274 :     Handle<DebugInfo> debug_info = current->debug_info();
    1386        8274 :     if (clear_function(debug_info)) {
    1387        8274 :       FreeDebugInfoListNode(prev, current);
    1388             :       current = next;
    1389             :     } else {
    1390             :       prev = current;
    1391             :       current = next;
    1392             :     }
    1393             :   }
    1394      114656 : }
    1395             : 
    1396         848 : void Debug::RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info) {
    1397         848 :   bool should_unlink = debug_info->ClearBreakInfo();
    1398         848 :   if (should_unlink) {
    1399             :     DebugInfoListNode* prev;
    1400             :     DebugInfoListNode* node;
    1401         848 :     FindDebugInfo(debug_info, &prev, &node);
    1402         848 :     FreeDebugInfoListNode(prev, node);
    1403             :   }
    1404         848 : }
    1405             : 
    1406        9122 : void Debug::FreeDebugInfoListNode(DebugInfoListNode* prev,
    1407       18244 :                                   DebugInfoListNode* node) {
    1408             :   DCHECK(node->debug_info()->IsEmpty());
    1409             : 
    1410             :   // Unlink from list. If prev is nullptr we are looking at the first element.
    1411        9122 :   if (prev == nullptr) {
    1412        8976 :     debug_info_list_ = node->next();
    1413             :   } else {
    1414             :     prev->set_next(node->next());
    1415             :   }
    1416             : 
    1417             :   // Pack debugger hints back into the SFI::debug_info field.
    1418             :   Handle<DebugInfo> debug_info(node->debug_info());
    1419             :   debug_info->shared()->set_debug_info(
    1420        9122 :       Smi::FromInt(debug_info->debugger_hints()));
    1421             : 
    1422       18244 :   delete node;
    1423        9122 : }
    1424             : 
    1425       68228 : bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
    1426       68228 :   HandleScope scope(isolate_);
    1427             : 
    1428             :   // Get the executing function in which the debug break occurred.
    1429       68228 :   Handle<SharedFunctionInfo> shared(frame->function()->shared());
    1430             : 
    1431             :   // With no debug info there are no break points, so we can't be at a return.
    1432       68228 :   if (!shared->HasBreakInfo()) return false;
    1433             : 
    1434             :   DCHECK(!frame->is_optimized());
    1435       55369 :   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
    1436       55369 :   BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
    1437      110738 :   return location.IsReturn();
    1438             : }
    1439             : 
    1440         319 : void Debug::ScheduleFrameRestart(StackFrame* frame) {
    1441             :   // Set a target FP for the FrameDropperTrampoline builtin to drop to once
    1442             :   // we return from the debugger.
    1443             :   DCHECK(frame->is_java_script());
    1444             :   // Only reschedule to a frame further below a frame we already scheduled for.
    1445         618 :   if (frame->fp() <= thread_local_.restart_fp_) return;
    1446             :   // If the frame is optimized, trigger a deopt and jump into the
    1447             :   // FrameDropperTrampoline in the deoptimizer.
    1448         307 :   thread_local_.restart_fp_ = frame->fp();
    1449             : 
    1450             :   // Reset break frame ID to the frame below the restarted frame.
    1451         307 :   StackTraceFrameIterator it(isolate_);
    1452         307 :   thread_local_.break_frame_id_ = StackFrame::NO_ID;
    1453        6810 :   for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
    1454        3385 :     if (it.frame()->fp() > thread_local_.restart_fp_) {
    1455         574 :       thread_local_.break_frame_id_ = it.frame()->id();
    1456             :       return;
    1457             :     }
    1458             :   }
    1459             : }
    1460             : 
    1461             : 
    1462        1500 : bool Debug::IsDebugGlobal(JSGlobalObject* global) {
    1463       50698 :   return is_loaded() && global == debug_context()->global_object();
    1464             : }
    1465             : 
    1466             : 
    1467         271 : Handle<FixedArray> Debug::GetLoadedScripts() {
    1468             :   isolate_->heap()->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
    1469         271 :                                       GarbageCollectionReason::kDebugger);
    1470         271 :   Factory* factory = isolate_->factory();
    1471         271 :   if (!factory->script_list()->IsWeakFixedArray()) {
    1472             :     return factory->empty_fixed_array();
    1473             :   }
    1474             :   Handle<WeakFixedArray> array =
    1475             :       Handle<WeakFixedArray>::cast(factory->script_list());
    1476         271 :   Handle<FixedArray> results = factory->NewFixedArray(array->Length());
    1477             :   int length = 0;
    1478             :   {
    1479         271 :     Script::Iterator iterator(isolate_);
    1480             :     Script* script;
    1481        5855 :     while ((script = iterator.Next()) != nullptr) {
    1482       10626 :       if (script->HasValidSource()) results->set(length++, script);
    1483             :     }
    1484             :   }
    1485         271 :   results->Shrink(length);
    1486         271 :   return results;
    1487             : }
    1488             : 
    1489             : 
    1490       83230 : MaybeHandle<Object> Debug::MakeExecutionState() {
    1491             :   // Create the execution state object.
    1492       83230 :   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
    1493       83230 :   return CallFunction("MakeExecutionState", arraysize(argv), argv);
    1494             : }
    1495             : 
    1496             : 
    1497       29497 : MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
    1498             :   // Create the new break event object.
    1499       29497 :   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
    1500       29497 :                             break_points_hit };
    1501       29497 :   return CallFunction("MakeBreakEvent", arraysize(argv), argv);
    1502             : }
    1503             : 
    1504             : 
    1505         195 : MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
    1506             :                                               bool uncaught,
    1507         195 :                                               Handle<Object> promise) {
    1508             :   // Create the new exception event object.
    1509         195 :   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
    1510             :                             exception,
    1511         195 :                             isolate_->factory()->ToBoolean(uncaught),
    1512         390 :                             promise };
    1513         195 :   return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
    1514             : }
    1515             : 
    1516             : 
    1517        3425 : MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
    1518             :                                             v8::DebugEvent type) {
    1519             :   // Create the compile event object.
    1520        3425 :   Handle<Object> script_wrapper = Script::GetWrapper(script);
    1521             :   Handle<Object> argv[] = { script_wrapper,
    1522        3425 :                             isolate_->factory()->NewNumberFromInt(type) };
    1523        3425 :   return CallFunction("MakeCompileEvent", arraysize(argv), argv);
    1524             : }
    1525             : 
    1526          60 : MaybeHandle<Object> Debug::MakeAsyncTaskEvent(
    1527             :     v8::debug::PromiseDebugActionType type, int id) {
    1528             :   // Create the async task event object.
    1529             :   Handle<Object> argv[] = {Handle<Smi>(Smi::FromInt(type), isolate_),
    1530         120 :                            Handle<Smi>(Smi::FromInt(id), isolate_)};
    1531          60 :   return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
    1532             : }
    1533             : 
    1534             : 
    1535     2427613 : void Debug::OnThrow(Handle<Object> exception) {
    1536     3653237 :   if (in_debug_scope() || ignore_events()) return;
    1537             :   // Temporarily clear any scheduled_exception to allow evaluating
    1538             :   // JavaScript from the debug event handler.
    1539        3769 :   HandleScope scope(isolate_);
    1540             :   Handle<Object> scheduled_exception;
    1541        7538 :   if (isolate_->has_scheduled_exception()) {
    1542             :     scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
    1543           0 :     isolate_->clear_scheduled_exception();
    1544             :   }
    1545        3769 :   OnException(exception, isolate_->GetPromiseOnStackOnThrow());
    1546        3769 :   if (!scheduled_exception.is_null()) {
    1547           0 :     isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
    1548             :   }
    1549        3769 :   PrepareStepOnThrow();
    1550             : }
    1551             : 
    1552        1598 : void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {
    1553        2397 :   if (in_debug_scope() || ignore_events()) return;
    1554         799 :   HandleScope scope(isolate_);
    1555             :   // Check whether the promise has been marked as having triggered a message.
    1556         799 :   Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
    1557        2397 :   if (!promise->IsJSObject() ||
    1558        1484 :       JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
    1559        2169 :           ->IsUndefined(isolate_)) {
    1560         776 :     OnException(value, promise);
    1561             :   }
    1562             : }
    1563             : 
    1564             : namespace {
    1565       79718 : v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
    1566             :   Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
    1567             :   // Isolate::context() may have been nullptr when "script collected" event
    1568             :   // occurred.
    1569       79718 :   if (context.is_null()) return v8::Local<v8::Context>();
    1570             :   Handle<Context> native_context(context->native_context());
    1571             :   return v8::Utils::ToLocal(native_context);
    1572             : }
    1573             : }  // anonymous namespace
    1574             : 
    1575        1971 : bool Debug::IsExceptionBlackboxed(bool uncaught) {
    1576             :   // Uncaught exception is blackboxed if all current frames are blackboxed,
    1577             :   // caught exception if top frame is blackboxed.
    1578        1971 :   StackTraceFrameIterator it(isolate_);
    1579        5913 :   while (!it.done() && it.is_wasm()) it.Advance();
    1580             :   bool is_top_frame_blackboxed =
    1581        1971 :       !it.done() ? IsFrameBlackboxed(it.javascript_frame()) : true;
    1582        1971 :   if (!uncaught || !is_top_frame_blackboxed) return is_top_frame_blackboxed;
    1583          10 :   return AllFramesOnStackAreBlackboxed();
    1584             : }
    1585             : 
    1586       42543 : bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
    1587       42543 :   HandleScope scope(isolate_);
    1588             :   std::vector<Handle<SharedFunctionInfo>> infos;
    1589       42543 :   frame->GetFunctions(&infos);
    1590       87326 :   for (const auto& info : infos) {
    1591       42543 :     if (!IsBlackboxed(info)) return false;
    1592             :   }
    1593             :   return true;
    1594             : }
    1595             : 
    1596        4545 : void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
    1597             :   // We cannot generate debug events when JS execution is disallowed.
    1598             :   // TODO(5530): Reenable debug events within DisallowJSScopes once relevant
    1599             :   // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++.
    1600        7159 :   if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
    1601             : 
    1602        4523 :   Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
    1603             : 
    1604             :   // Don't notify listener of exceptions that are internal to a desugaring.
    1605        4523 :   if (catch_type == Isolate::CAUGHT_BY_DESUGARING) return;
    1606             : 
    1607        4523 :   bool uncaught = catch_type == Isolate::NOT_CAUGHT;
    1608        4523 :   if (promise->IsJSObject()) {
    1609             :     Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
    1610             :     // Mark the promise as already having triggered a message.
    1611        1844 :     Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
    1612        1844 :     JSObject::SetProperty(jspromise, key, key, LanguageMode::kStrict).Assert();
    1613             :     // Check whether the promise reject is considered an uncaught exception.
    1614        1844 :     uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
    1615             :   }
    1616             : 
    1617        4523 :   if (!debug_delegate_) return;
    1618             : 
    1619             :   // Bail out if exception breaks are not active
    1620        4523 :   if (uncaught) {
    1621             :     // Uncaught exceptions are reported by either flags.
    1622        1324 :     if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
    1623             :   } else {
    1624             :     // Caught exceptions are reported is activated.
    1625        3199 :     if (!break_on_exception_) return;
    1626             :   }
    1627             : 
    1628             :   {
    1629        2054 :     JavaScriptFrameIterator it(isolate_);
    1630             :     // Check whether the top frame is blackboxed or the break location is muted.
    1631        4025 :     if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) ||
    1632        1971 :                        IsExceptionBlackboxed(uncaught))) {
    1633             :       return;
    1634             :     }
    1635        1951 :     if (it.done()) return;  // Do not trigger an event with an empty stack.
    1636             :   }
    1637             : 
    1638        1931 :   DebugScope debug_scope(this);
    1639        1931 :   if (debug_scope.failed()) return;
    1640        1931 :   HandleScope scope(isolate_);
    1641        1931 :   PostponeInterruptsScope postpone(isolate_);
    1642             :   DisableBreak no_recursive_break(this);
    1643             : 
    1644             :   // Create the execution state.
    1645             :   Handle<Object> exec_state;
    1646             :   // Bail out and don't call debugger if exception.
    1647        3862 :   if (!MakeExecutionState().ToHandle(&exec_state)) return;
    1648             : 
    1649             :   debug_delegate_->ExceptionThrown(
    1650             :       GetDebugEventContext(isolate_),
    1651             :       v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
    1652        3862 :       v8::Utils::ToLocal(exception), v8::Utils::ToLocal(promise), uncaught);
    1653             : }
    1654             : 
    1655       77679 : void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) {
    1656             :   DCHECK(!break_points_hit.is_null());
    1657             :   // The caller provided for DebugScope.
    1658             :   AssertDebugContext();
    1659             :   // Bail out if there is no listener for this event
    1660       77691 :   if (ignore_events()) return;
    1661             : 
    1662             : #ifdef DEBUG
    1663             :   PrintBreakLocation();
    1664             : #endif  // DEBUG
    1665             : 
    1666       77679 :   if (!debug_delegate_) return;
    1667       77679 :   HandleScope scope(isolate_);
    1668       77679 :   PostponeInterruptsScope no_interrupts(isolate_);
    1669             :   DisableBreak no_recursive_break(this);
    1670             : 
    1671             :   // Create the execution state.
    1672             :   Handle<Object> exec_state;
    1673             :   // Bail out and don't call debugger if exception.
    1674      155358 :   if (!MakeExecutionState().ToHandle(&exec_state)) return;
    1675             : 
    1676             :   std::vector<int> inspector_break_points_hit;
    1677             :   int inspector_break_points_count = 0;
    1678             :   // This array contains breakpoints installed using JS debug API.
    1679      162698 :   for (int i = 0; i < break_points_hit->length(); ++i) {
    1680             :     Object* break_point = break_points_hit->get(i);
    1681        3682 :     if (break_point->IsBreakPoint()) {
    1682        4806 :       inspector_break_points_hit.push_back(BreakPoint::cast(break_point)->id());
    1683        2403 :       ++inspector_break_points_count;
    1684             :     } else {
    1685        2558 :       break_points_hit->set(i - inspector_break_points_count, break_point);
    1686             :     }
    1687             :   }
    1688             :   int break_points_length =
    1689       77667 :       break_points_hit->length() - inspector_break_points_count;
    1690             :   Handle<Object> break_points;
    1691       77667 :   if (break_points_length) {
    1692        1261 :     break_points_hit->Shrink(break_points_length);
    1693             :     break_points = isolate_->factory()->NewJSArrayWithElements(
    1694        1261 :         break_points_hit, PACKED_ELEMENTS, break_points_length);
    1695             :   } else {
    1696       76406 :     break_points = isolate_->factory()->undefined_value();
    1697             :   }
    1698             : 
    1699             :   debug_delegate_->BreakProgramRequested(
    1700             :       GetDebugEventContext(isolate_),
    1701             :       v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
    1702       77667 :       v8::Utils::ToLocal(break_points), inspector_break_points_hit);
    1703             : }
    1704             : 
    1705             : 
    1706      313095 : void Debug::OnCompileError(Handle<Script> script) {
    1707      313095 :   ProcessCompileEvent(v8::CompileError, script);
    1708      313095 : }
    1709             : 
    1710             : 
    1711             : // Handle debugger actions when a new script is compiled.
    1712     3830837 : void Debug::OnAfterCompile(Handle<Script> script) {
    1713     3830837 :   ProcessCompileEvent(v8::AfterCompile, script);
    1714     3830837 : }
    1715             : 
    1716             : namespace {
    1717             : // In an async function, reuse the existing stack related to the outer
    1718             : // Promise. Otherwise, e.g. in a direct call to then, save a new stack.
    1719             : // Promises with multiple reactions with one or more of them being async
    1720             : // functions will not get a good stack trace, as async functions require
    1721             : // different stacks from direct Promise use, but we save and restore a
    1722             : // stack once for all reactions.
    1723             : //
    1724             : // If this isn't a case of async function, we return false, otherwise
    1725             : // we set the correct id and return true.
    1726             : //
    1727             : // TODO(littledan): Improve this case.
    1728      256636 : int GetReferenceAsyncTaskId(Isolate* isolate, Handle<JSPromise> promise) {
    1729             :   Handle<Symbol> handled_by_symbol =
    1730             :       isolate->factory()->promise_handled_by_symbol();
    1731             :   Handle<Object> handled_by_promise =
    1732      134687 :       JSObject::GetDataProperty(promise, handled_by_symbol);
    1733      134687 :   if (!handled_by_promise->IsJSPromise()) {
    1734      115259 :     return isolate->debug()->NextAsyncTaskId(promise);
    1735             :   }
    1736             :   Handle<JSPromise> handled_by_promise_js =
    1737             :       Handle<JSPromise>::cast(handled_by_promise);
    1738             :   Handle<Symbol> async_stack_id_symbol =
    1739             :       isolate->factory()->promise_async_stack_id_symbol();
    1740             :   Handle<Object> async_task_id =
    1741       19428 :       JSObject::GetDataProperty(handled_by_promise_js, async_stack_id_symbol);
    1742       19428 :   if (!async_task_id->IsSmi()) {
    1743        6690 :     return isolate->debug()->NextAsyncTaskId(promise);
    1744             :   }
    1745             :   return Handle<Smi>::cast(async_task_id)->value();
    1746             : }
    1747             : }  //  namespace
    1748             : 
    1749      117071 : void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
    1750             :                            Handle<Object> parent) {
    1751      117071 :   if (!debug_delegate_) return;
    1752      117071 :   int id = GetReferenceAsyncTaskId(isolate_, promise);
    1753      117071 :   switch (type) {
    1754             :     case PromiseHookType::kInit:
    1755             :       OnAsyncTaskEvent(debug::kDebugPromiseCreated, id,
    1756             :                        parent->IsJSPromise()
    1757             :                            ? GetReferenceAsyncTaskId(
    1758       17616 :                                  isolate_, Handle<JSPromise>::cast(parent))
    1759       60604 :                            : 0);
    1760       42988 :       return;
    1761             :     case PromiseHookType::kResolve:
    1762             :       // We can't use this hook because it's called before promise object will
    1763             :       // get resolved status.
    1764             :       return;
    1765             :     case PromiseHookType::kBefore:
    1766       13503 :       OnAsyncTaskEvent(debug::kDebugWillHandle, id, 0);
    1767       13503 :       return;
    1768             :     case PromiseHookType::kAfter:
    1769       13498 :       OnAsyncTaskEvent(debug::kDebugDidHandle, id, 0);
    1770       13498 :       return;
    1771             :   }
    1772             : }
    1773             : 
    1774      169395 : int Debug::NextAsyncTaskId(Handle<JSObject> promise) {
    1775      338790 :   LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol());
    1776      169395 :   Maybe<bool> maybe = JSReceiver::HasProperty(&it);
    1777      169395 :   if (maybe.ToChecked()) {
    1778      126407 :     MaybeHandle<Object> result = Object::GetProperty(&it);
    1779             :     return Handle<Smi>::cast(result.ToHandleChecked())->value();
    1780             :   }
    1781             :   Handle<Smi> async_id =
    1782       42988 :       handle(Smi::FromInt(++thread_local_.async_task_count_), isolate_);
    1783             :   Object::SetProperty(&it, async_id, LanguageMode::kSloppy,
    1784       42988 :                       Object::MAY_BE_STORE_FROM_KEYED)
    1785       85976 :       .ToChecked();
    1786       42988 :   return async_id->value();
    1787             : }
    1788             : 
    1789             : namespace {
    1790       28364 : debug::Location GetDebugLocation(Handle<Script> script, int source_position) {
    1791             :   Script::PositionInfo info;
    1792       28364 :   Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
    1793             :   // V8 provides ScriptCompiler::CompileFunctionInContext method which takes
    1794             :   // expression and compile it as anonymous function like (function() ..
    1795             :   // expression ..). To produce correct locations for stmts inside of this
    1796             :   // expression V8 compile this function with negative offset. Instead of stmt
    1797             :   // position blackboxing use function start position which is negative in
    1798             :   // described case.
    1799       85092 :   return debug::Location(std::max(info.line, 0), std::max(info.column, 0));
    1800             : }
    1801             : }  // namespace
    1802             : 
    1803      155416 : bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
    1804      155416 :   if (!debug_delegate_) return !shared->IsSubjectToDebugging();
    1805      155416 :   if (!shared->computed_debug_is_blackboxed()) {
    1806             :     bool is_blackboxed =
    1807       30248 :         !shared->IsSubjectToDebugging() || !shared->script()->IsScript();
    1808       16066 :     if (!is_blackboxed) {
    1809             :       SuppressDebug while_processing(this);
    1810       14182 :       HandleScope handle_scope(isolate_);
    1811       14182 :       PostponeInterruptsScope no_interrupts(isolate_);
    1812             :       DisableBreak no_recursive_break(this);
    1813             :       DCHECK(shared->script()->IsScript());
    1814             :       Handle<Script> script(Script::cast(shared->script()));
    1815             :       DCHECK(script->IsUserJavaScript());
    1816             :       debug::Location start =
    1817       14182 :           GetDebugLocation(script, shared->start_position());
    1818       14182 :       debug::Location end = GetDebugLocation(script, shared->end_position());
    1819             :       is_blackboxed = debug_delegate_->IsFunctionBlackboxed(
    1820       14182 :           ToApiHandle<debug::Script>(script), start, end);
    1821             :     }
    1822       32132 :     shared->set_debug_is_blackboxed(is_blackboxed);
    1823       16066 :     shared->set_computed_debug_is_blackboxed(true);
    1824             :   }
    1825      155416 :   return shared->debug_is_blackboxed();
    1826             : }
    1827             : 
    1828         210 : bool Debug::AllFramesOnStackAreBlackboxed() {
    1829         210 :   HandleScope scope(isolate_);
    1830         670 :   for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) {
    1831         320 :     if (!IsFrameBlackboxed(it.javascript_frame())) return false;
    1832             :   }
    1833          15 :   return true;
    1834             : }
    1835             : 
    1836          35 : bool Debug::SetScriptSource(Handle<Script> script, Handle<String> source,
    1837             :                             bool preview, bool* stack_changed) {
    1838          35 :   DebugScope debug_scope(this);
    1839             :   set_live_edit_enabled(true);
    1840          35 :   Handle<Object> script_wrapper = Script::GetWrapper(script);
    1841             :   Handle<Object> argv[] = {script_wrapper, source,
    1842          35 :                            isolate_->factory()->ToBoolean(preview),
    1843          70 :                            isolate_->factory()->NewJSArray(0)};
    1844             :   Handle<Object> result;
    1845          35 :   if (!CallFunction("SetScriptSource", arraysize(argv), argv, false)
    1846          70 :            .ToHandle(&result)) {
    1847          10 :     isolate_->OptionalRescheduleException(false);
    1848             :     set_live_edit_enabled(false);
    1849          10 :     return false;
    1850             :   }
    1851             :   set_live_edit_enabled(false);
    1852             :   Handle<Object> stack_changed_value =
    1853             :       JSReceiver::GetProperty(isolate_, Handle<JSObject>::cast(result),
    1854          50 :                               "stack_modified")
    1855          50 :           .ToHandleChecked();
    1856          50 :   *stack_changed = stack_changed_value->IsTrue(isolate_);
    1857          25 :   return true;
    1858             : }
    1859             : 
    1860      117435 : void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
    1861      117019 :                              int parent_id) {
    1862      234870 :   if (in_debug_scope() || ignore_events()) return;
    1863      117019 :   if (!debug_delegate_) return;
    1864             :   SuppressDebug while_processing(this);
    1865      117019 :   PostponeInterruptsScope no_interrupts(isolate_);
    1866             :   DisableBreak no_recursive_break(this);
    1867             :   bool created_by_user = false;
    1868      117019 :   if (type == debug::kDebugPromiseCreated) {
    1869       42599 :     JavaScriptFrameIterator it(isolate_);
    1870             :     // We need to skip top frame which contains instrumentation.
    1871       42599 :     it.Advance();
    1872             :     created_by_user =
    1873       82851 :         !it.done() &&
    1874       40252 :         !IsFrameBlackboxed(it.frame());
    1875             :   }
    1876      117019 :   debug_delegate_->PromiseEventOccurred(type, id, parent_id, created_by_user);
    1877             : }
    1878             : 
    1879     8287864 : void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
    1880             :   // Attach the correct debug id to the script. The debug id is used by the
    1881             :   // inspector to filter scripts by native context.
    1882     8287864 :   script->set_context_data(isolate_->native_context()->debug_context_id());
    1883     8266556 :   if (ignore_events()) return;
    1884       26965 :   if (!script->IsUserJavaScript() && script->type() != i::Script::TYPE_WASM) {
    1885             :     return;
    1886             :   }
    1887       21308 :   if (!debug_delegate_) return;
    1888             :   SuppressDebug while_processing(this);
    1889       42616 :   DebugScope debug_scope(this);
    1890       21308 :   if (debug_scope.failed()) return;
    1891       21308 :   HandleScope scope(isolate_);
    1892       21308 :   PostponeInterruptsScope postpone(isolate_);
    1893             :   DisableBreak no_recursive_break(this);
    1894       42616 :   AllowJavascriptExecution allow_script(isolate_);
    1895             :   debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
    1896             :                                   live_edit_enabled(),
    1897       42616 :                                   event != v8::AfterCompile);
    1898             : }
    1899             : 
    1900             : 
    1901       51072 : Handle<Context> Debug::GetDebugContext() {
    1902       51072 :   if (!is_loaded()) return Handle<Context>();
    1903       51072 :   DebugScope debug_scope(this);
    1904       51072 :   if (debug_scope.failed()) return Handle<Context>();
    1905             :   // The global handle may be destroyed soon after.  Return it reboxed.
    1906      102144 :   return handle(*debug_context(), isolate_);
    1907             : }
    1908             : 
    1909      696502 : int Debug::CurrentFrameCount() {
    1910      112290 :   StackTraceFrameIterator it(isolate_);
    1911      112290 :   if (break_frame_id() != StackFrame::NO_ID) {
    1912             :     // Skip to break frame.
    1913             :     DCHECK(in_debug_scope());
    1914     1304145 :     while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
    1915             :   }
    1916             :   int counter = 0;
    1917      307476 :   while (!it.done()) {
    1918      390372 :     if (it.frame()->is_optimized()) {
    1919             :       std::vector<SharedFunctionInfo*> infos;
    1920        5973 :       OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
    1921       11946 :       counter += infos.size();
    1922             :     } else {
    1923      189213 :       counter++;
    1924             :     }
    1925      195186 :     it.Advance();
    1926             :   }
    1927      112290 :   return counter;
    1928             : }
    1929             : 
    1930        7361 : void Debug::SetDebugDelegate(debug::DebugDelegate* delegate,
    1931             :                              bool pass_ownership) {
    1932        7361 :   RemoveDebugDelegate();
    1933        7361 :   debug_delegate_ = delegate;
    1934        7361 :   owns_debug_delegate_ = pass_ownership;
    1935        7361 :   UpdateState();
    1936        7361 : }
    1937             : 
    1938       64546 : void Debug::RemoveDebugDelegate() {
    1939      129092 :   if (debug_delegate_ == nullptr) return;
    1940        3731 :   if (owns_debug_delegate_) {
    1941         605 :     owns_debug_delegate_ = false;
    1942         605 :     delete debug_delegate_;
    1943             :   }
    1944        3731 :   debug_delegate_ = nullptr;
    1945             : }
    1946             : 
    1947      332213 : void Debug::UpdateState() {
    1948      332213 :   bool is_active = debug_delegate_ != nullptr;
    1949      338699 :   if (is_active || in_debug_scope()) {
    1950             :     // Note that the debug context could have already been loaded to
    1951             :     // bootstrap test cases.
    1952      331108 :     isolate_->compilation_cache()->Disable();
    1953      327288 :     is_active = Load();
    1954        4925 :   } else if (is_loaded()) {
    1955        7640 :     isolate_->compilation_cache()->Enable();
    1956        3820 :     Unload();
    1957             :   }
    1958      332213 :   is_active_ = is_active;
    1959      332213 :   isolate_->DebugStateUpdated();
    1960      332213 : }
    1961             : 
    1962       14207 : void Debug::UpdateHookOnFunctionCall() {
    1963             :   STATIC_ASSERT(LastStepAction == StepIn);
    1964      508714 :   hook_on_function_call_ = thread_local_.last_step_action_ == StepIn ||
    1965      688464 :                            isolate_->needs_side_effect_check();
    1966       14207 : }
    1967             : 
    1968         135 : MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
    1969             :   AllowJavascriptExecutionDebugOnly allow_script(isolate_);
    1970         135 :   DebugScope debug_scope(this);
    1971         135 :   if (debug_scope.failed()) return isolate_->factory()->undefined_value();
    1972             : 
    1973             :   // Create the execution state.
    1974             :   Handle<Object> exec_state;
    1975         270 :   if (!MakeExecutionState().ToHandle(&exec_state)) {
    1976           0 :     return isolate_->factory()->undefined_value();
    1977             :   }
    1978             : 
    1979         135 :   Handle<Object> argv[] = { exec_state, data };
    1980             :   return Execution::Call(
    1981             :       isolate_,
    1982             :       fun,
    1983         135 :       Handle<Object>(debug_context()->global_proxy(), isolate_),
    1984             :       arraysize(argv),
    1985         270 :       argv);
    1986             : }
    1987             : 
    1988      383279 : void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
    1989             :   // Initialize LiveEdit.
    1990      127791 :   LiveEdit::InitializeThreadLocal(this);
    1991             :   // Ignore debug break during bootstrapping.
    1992      231106 :   if (isolate_->bootstrapper()->IsActive()) return;
    1993             :   // Just continue if breaks are disabled.
    1994      127781 :   if (break_disabled()) return;
    1995             :   // Ignore debug break if debugger is not active.
    1996      127707 :   if (!is_active()) return;
    1997             : 
    1998             :   StackLimitCheck check(isolate_);
    1999       25085 :   if (check.HasOverflowed()) return;
    2000             : 
    2001       25085 :   { JavaScriptFrameIterator it(isolate_);
    2002             :     DCHECK(!it.done());
    2003       25085 :     Object* fun = it.frame()->function();
    2004       50170 :     if (fun && fun->IsJSFunction()) {
    2005       25085 :       HandleScope scope(isolate_);
    2006       25085 :       Handle<JSFunction> function(JSFunction::cast(fun), isolate_);
    2007             :       // Don't stop in builtin and blackboxed functions.
    2008       25085 :       Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
    2009             :       bool ignore_break = ignore_break_mode == kIgnoreIfTopFrameBlackboxed
    2010             :                               ? IsBlackboxed(shared)
    2011       25085 :                               : AllFramesOnStackAreBlackboxed();
    2012       25085 :       if (ignore_break) {
    2013             :         // Inspector uses pause on next statement for asynchronous breakpoints.
    2014             :         // When breakpoint is fired we try to break on first not blackboxed
    2015             :         // statement. To achieve this goal we need to deoptimize current
    2016             :         // function and don't clear requested DebugBreak even if it's blackboxed
    2017             :         // to be able to break on not blackboxed function call.
    2018             :         // TODO(yangguo): introduce break_on_function_entry since current
    2019             :         // implementation is slow.
    2020        1182 :         if (isolate_->stack_guard()->CheckDebugBreak()) {
    2021         576 :           Deoptimizer::DeoptimizeFunction(*function);
    2022             :         }
    2023             :         return;
    2024             :       }
    2025       24494 :       JSGlobalObject* global = function->context()->global_object();
    2026             :       // Don't stop in debugger functions.
    2027       24494 :       if (IsDebugGlobal(global)) return;
    2028             :       // Don't stop if the break location is muted.
    2029       24494 :       if (IsMutedAtCurrentLocation(it.frame())) return;
    2030             :     }
    2031             :   }
    2032             : 
    2033       24476 :   isolate_->stack_guard()->ClearDebugBreak();
    2034             : 
    2035             :   // Clear stepping to avoid duplicate breaks.
    2036       24476 :   ClearStepping();
    2037             : 
    2038       24476 :   HandleScope scope(isolate_);
    2039       48952 :   DebugScope debug_scope(this);
    2040       24476 :   if (debug_scope.failed()) return;
    2041             : 
    2042       48952 :   OnDebugBreak(isolate_->factory()->empty_fixed_array());
    2043             : }
    2044             : 
    2045             : #ifdef DEBUG
    2046             : void Debug::PrintBreakLocation() {
    2047             :   if (!FLAG_print_break_location) return;
    2048             :   HandleScope scope(isolate_);
    2049             :   StackTraceFrameIterator iterator(isolate_);
    2050             :   if (iterator.done()) return;
    2051             :   StandardFrame* frame = iterator.frame();
    2052             :   FrameSummary summary = FrameSummary::GetTop(frame);
    2053             :   int source_position = summary.SourcePosition();
    2054             :   Handle<Object> script_obj = summary.script();
    2055             :   PrintF("[debug] break in function '");
    2056             :   summary.FunctionName()->PrintOn(stdout);
    2057             :   PrintF("'.\n");
    2058             :   if (script_obj->IsScript()) {
    2059             :     Handle<Script> script = Handle<Script>::cast(script_obj);
    2060             :     Handle<String> source(String::cast(script->source()));
    2061             :     Script::InitLineEnds(script);
    2062             :     int line =
    2063             :         Script::GetLineNumber(script, source_position) - script->line_offset();
    2064             :     int column = Script::GetColumnNumber(script, source_position) -
    2065             :                  (line == 0 ? script->column_offset() : 0);
    2066             :     Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
    2067             :     int line_start = line == 0 ? 0 : Smi::ToInt(line_ends->get(line - 1)) + 1;
    2068             :     int line_end = Smi::ToInt(line_ends->get(line));
    2069             :     DisallowHeapAllocation no_gc;
    2070             :     String::FlatContent content = source->GetFlatContent();
    2071             :     if (content.IsOneByte()) {
    2072             :       PrintF("[debug] %.*s\n", line_end - line_start,
    2073             :              content.ToOneByteVector().start() + line_start);
    2074             :       PrintF("[debug] ");
    2075             :       for (int i = 0; i < column; i++) PrintF(" ");
    2076             :       PrintF("^\n");
    2077             :     } else {
    2078             :       PrintF("[debug] at line %d column %d\n", line, column);
    2079             :     }
    2080             :   }
    2081             : }
    2082             : #endif  // DEBUG
    2083             : 
    2084      162426 : DebugScope::DebugScope(Debug* debug)
    2085             :     : debug_(debug),
    2086             :       prev_(debug->debugger_entry()),
    2087             :       save_(debug_->isolate_),
    2088             :       no_termination_exceptons_(debug_->isolate_,
    2089      649704 :                                 StackGuard::TERMINATE_EXECUTION) {
    2090             :   // Link recursive debugger entry.
    2091             :   base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
    2092      162426 :                       reinterpret_cast<base::AtomicWord>(this));
    2093             : 
    2094             :   // Store the previous break id, frame id and return value.
    2095      324852 :   break_id_ = debug_->break_id();
    2096      162426 :   break_frame_id_ = debug_->break_frame_id();
    2097             : 
    2098             :   // Create the new break info. If there is no proper frames there is no break
    2099             :   // frame id.
    2100      162426 :   StackTraceFrameIterator it(isolate());
    2101             :   bool has_frames = !it.done();
    2102             :   debug_->thread_local_.break_frame_id_ =
    2103      324852 :       has_frames ? it.frame()->id() : StackFrame::NO_ID;
    2104      162426 :   debug_->SetNextBreakId();
    2105             : 
    2106      162426 :   debug_->UpdateState();
    2107             :   // Make sure that debugger is loaded and enter the debugger context.
    2108             :   // The previous context is kept in save_.
    2109      324852 :   failed_ = !debug_->is_loaded();
    2110      162426 :   if (!failed_) isolate()->set_context(*debug->debug_context());
    2111      162426 : }
    2112             : 
    2113             : 
    2114      324852 : DebugScope::~DebugScope() {
    2115             :   // Leaving this debugger entry.
    2116             :   base::Relaxed_Store(&debug_->thread_local_.current_debug_scope_,
    2117      162426 :                       reinterpret_cast<base::AtomicWord>(prev_));
    2118             : 
    2119             :   // Restore to the previous break state.
    2120      162426 :   debug_->thread_local_.break_frame_id_ = break_frame_id_;
    2121      162426 :   debug_->thread_local_.break_id_ = break_id_;
    2122             : 
    2123      162426 :   debug_->UpdateState();
    2124      162426 : }
    2125             : 
    2126       58332 : ReturnValueScope::ReturnValueScope(Debug* debug) : debug_(debug) {
    2127       58332 :   return_value_ = debug_->return_value_handle();
    2128       58332 : }
    2129             : 
    2130       58332 : ReturnValueScope::~ReturnValueScope() {
    2131       58332 :   debug_->set_return_value(*return_value_);
    2132       58332 : }
    2133             : 
    2134        9732 : bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) {
    2135             :   DCHECK(isolate_->needs_side_effect_check());
    2136        9732 :   DisallowJavascriptExecution no_js(isolate_);
    2137       11308 :   if (!function->is_compiled() &&
    2138        1576 :       !Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
    2139             :     return false;
    2140             :   }
    2141        9732 :   Deoptimizer::DeoptimizeFunction(*function);
    2142        9732 :   if (!function->shared()->HasNoSideEffect()) {
    2143        3190 :     if (FLAG_trace_side_effect_free_debug_evaluate) {
    2144             :       PrintF("[debug-evaluate] Function %s failed side effect check.\n",
    2145           0 :              function->shared()->DebugName()->ToCString().get());
    2146             :     }
    2147        3190 :     side_effect_check_failed_ = true;
    2148             :     // Throw an uncatchable termination exception.
    2149        3190 :     isolate_->TerminateExecution();
    2150        3190 :     return false;
    2151             :   }
    2152        9732 :   return true;
    2153             : }
    2154             : 
    2155          70 : bool Debug::PerformSideEffectCheckForCallback(Address function) {
    2156             :   DCHECK(isolate_->needs_side_effect_check());
    2157          70 :   if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true;
    2158           9 :   side_effect_check_failed_ = true;
    2159             :   // Throw an uncatchable termination exception.
    2160           9 :   isolate_->TerminateExecution();
    2161           9 :   isolate_->OptionalRescheduleException(false);
    2162           9 :   return false;
    2163             : }
    2164             : 
    2165          60 : void LegacyDebugDelegate::PromiseEventOccurred(
    2166             :     v8::debug::PromiseDebugActionType type, int id, int parent_id,
    2167             :     bool created_by_user) {
    2168         120 :   DebugScope debug_scope(isolate_->debug());
    2169          60 :   if (debug_scope.failed()) return;
    2170          60 :   HandleScope scope(isolate_);
    2171             :   Handle<Object> event_data;
    2172         180 :   if (isolate_->debug()->MakeAsyncTaskEvent(type, id).ToHandle(&event_data)) {
    2173          60 :     ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
    2174          60 :   }
    2175             : }
    2176             : 
    2177        3425 : void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script,
    2178             :                                          bool is_live_edited,
    2179             :                                          bool is_compile_error) {
    2180             :   Handle<Object> event_data;
    2181        3425 :   v8::DebugEvent event = is_compile_error ? v8::CompileError : v8::AfterCompile;
    2182        3425 :   if (isolate_->debug()
    2183        3425 :           ->MakeCompileEvent(v8::Utils::OpenHandle(*script), event)
    2184        6850 :           .ToHandle(&event_data)) {
    2185        3425 :     ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
    2186             :   }
    2187        3425 : }
    2188             : 
    2189       29497 : void LegacyDebugDelegate::BreakProgramRequested(
    2190             :     v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
    2191             :     v8::Local<v8::Value> break_points_hit,
    2192             :     const std::vector<debug::BreakpointId>&) {
    2193             :   Handle<Object> event_data;
    2194       29497 :   if (isolate_->debug()
    2195       29497 :           ->MakeBreakEvent(v8::Utils::OpenHandle(*break_points_hit))
    2196       58994 :           .ToHandle(&event_data)) {
    2197             :     ProcessDebugEvent(
    2198             :         v8::Break, Handle<JSObject>::cast(event_data),
    2199       58994 :         Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
    2200             :   }
    2201       29497 : }
    2202             : 
    2203         195 : void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context,
    2204             :                                           v8::Local<v8::Object> exec_state,
    2205             :                                           v8::Local<v8::Value> exception,
    2206             :                                           v8::Local<v8::Value> promise,
    2207             :                                           bool is_uncaught) {
    2208             :   Handle<Object> event_data;
    2209         195 :   if (isolate_->debug()
    2210             :           ->MakeExceptionEvent(v8::Utils::OpenHandle(*exception), is_uncaught,
    2211         390 :                                v8::Utils::OpenHandle(*promise))
    2212         390 :           .ToHandle(&event_data)) {
    2213             :     ProcessDebugEvent(
    2214             :         v8::Exception, Handle<JSObject>::cast(event_data),
    2215         390 :         Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
    2216             :   }
    2217         195 : }
    2218             : 
    2219        3485 : void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
    2220             :                                             Handle<JSObject> event_data) {
    2221             :   Handle<Object> exec_state;
    2222        6970 :   if (isolate_->debug()->MakeExecutionState().ToHandle(&exec_state)) {
    2223        3485 :     ProcessDebugEvent(event, event_data, Handle<JSObject>::cast(exec_state));
    2224             :   }
    2225        3485 : }
    2226             : 
    2227         130 : JavaScriptDebugDelegate::JavaScriptDebugDelegate(Isolate* isolate,
    2228             :                                                  Handle<JSFunction> listener,
    2229             :                                                  Handle<Object> data)
    2230          65 :     : LegacyDebugDelegate(isolate) {
    2231             :   GlobalHandles* global_handles = isolate->global_handles();
    2232          65 :   listener_ = global_handles->Create(*listener);
    2233          65 :   data_ = global_handles->Create(*data);
    2234          65 : }
    2235             : 
    2236         130 : JavaScriptDebugDelegate::~JavaScriptDebugDelegate() {
    2237          65 :   GlobalHandles::Destroy(Handle<Object>::cast(listener_).location());
    2238          65 :   GlobalHandles::Destroy(data_.location());
    2239         130 : }
    2240             : 
    2241          27 : void JavaScriptDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
    2242             :                                                 Handle<JSObject> event_data,
    2243             :                                                 Handle<JSObject> exec_state) {
    2244             :   AllowJavascriptExecutionDebugOnly allow_script(isolate_);
    2245          27 :   Handle<Object> argv[] = {Handle<Object>(Smi::FromInt(event), isolate_),
    2246          54 :                            exec_state, event_data, data_};
    2247          27 :   Handle<JSReceiver> global = isolate_->global_proxy();
    2248             :   // Listener must not throw.
    2249          54 :   Execution::Call(isolate_, listener_, global, arraysize(argv), argv)
    2250          54 :       .ToHandleChecked();
    2251          27 : }
    2252             : 
    2253        1080 : NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate,
    2254             :                                          v8::Debug::EventCallback callback,
    2255             :                                          Handle<Object> data)
    2256         540 :     : LegacyDebugDelegate(isolate), callback_(callback) {
    2257         540 :   data_ = isolate->global_handles()->Create(*data);
    2258         540 : }
    2259             : 
    2260         540 : NativeDebugDelegate::~NativeDebugDelegate() {
    2261         540 :   GlobalHandles::Destroy(data_.location());
    2262         540 : }
    2263             : 
    2264           0 : NativeDebugDelegate::EventDetails::EventDetails(DebugEvent event,
    2265             :                                                 Handle<JSObject> exec_state,
    2266             :                                                 Handle<JSObject> event_data,
    2267             :                                                 Handle<Object> callback_data)
    2268             :     : event_(event),
    2269             :       exec_state_(exec_state),
    2270             :       event_data_(event_data),
    2271       33150 :       callback_data_(callback_data) {}
    2272             : 
    2273       28090 : DebugEvent NativeDebugDelegate::EventDetails::GetEvent() const {
    2274       28090 :   return event_;
    2275             : }
    2276             : 
    2277        1955 : v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetExecutionState()
    2278             :     const {
    2279        1955 :   return v8::Utils::ToLocal(exec_state_);
    2280             : }
    2281             : 
    2282         280 : v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetEventData() const {
    2283         280 :   return v8::Utils::ToLocal(event_data_);
    2284             : }
    2285             : 
    2286         120 : v8::Local<v8::Context> NativeDebugDelegate::EventDetails::GetEventContext()
    2287             :     const {
    2288         120 :   return GetDebugEventContext(exec_state_->GetIsolate());
    2289             : }
    2290             : 
    2291          15 : v8::Local<v8::Value> NativeDebugDelegate::EventDetails::GetCallbackData()
    2292             :     const {
    2293          15 :   return v8::Utils::ToLocal(callback_data_);
    2294             : }
    2295             : 
    2296          10 : v8::Isolate* NativeDebugDelegate::EventDetails::GetIsolate() const {
    2297          10 :   return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
    2298             : }
    2299             : 
    2300       33150 : void NativeDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
    2301             :                                             Handle<JSObject> event_data,
    2302             :                                             Handle<JSObject> exec_state) {
    2303             :   EventDetails event_details(event, exec_state, event_data, data_);
    2304       33150 :   Isolate* isolate = isolate_;
    2305       33150 :   callback_(event_details);
    2306       33150 :   CHECK(!isolate->has_scheduled_exception());
    2307       33150 : }
    2308             : 
    2309       14207 : NoSideEffectScope::~NoSideEffectScope() {
    2310       42621 :   if (isolate_->needs_side_effect_check() &&
    2311             :       isolate_->debug()->side_effect_check_failed_) {
    2312             :     DCHECK(isolate_->has_pending_exception());
    2313             :     DCHECK_EQ(isolate_->heap()->termination_exception(),
    2314             :               isolate_->pending_exception());
    2315             :     // Convert the termination exception into a regular exception.
    2316        3199 :     isolate_->CancelTerminateExecution();
    2317             :     isolate_->Throw(*isolate_->factory()->NewEvalError(
    2318        6398 :         MessageTemplate::kNoSideEffectDebugEvaluate));
    2319             :   }
    2320       14207 :   isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
    2321       14207 :   isolate_->debug()->UpdateHookOnFunctionCall();
    2322       28414 :   isolate_->debug()->side_effect_check_failed_ = false;
    2323       14207 : }
    2324             : 
    2325             : }  // namespace internal
    2326             : }  // namespace v8

Generated by: LCOV version 1.10