LCOV - code coverage report
Current view: top level - src/runtime - runtime-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 634 883 71.8 %
Date: 2017-10-20 Functions: 55 142 38.7 %

          Line data    Source code
       1             : // Copyright 2014 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/runtime/runtime-utils.h"
       6             : 
       7             : #include <vector>
       8             : 
       9             : #include "src/arguments.h"
      10             : #include "src/compiler.h"
      11             : #include "src/debug/debug-coverage.h"
      12             : #include "src/debug/debug-evaluate.h"
      13             : #include "src/debug/debug-frames.h"
      14             : #include "src/debug/debug-scopes.h"
      15             : #include "src/debug/debug.h"
      16             : #include "src/debug/liveedit.h"
      17             : #include "src/frames-inl.h"
      18             : #include "src/globals.h"
      19             : #include "src/interpreter/bytecodes.h"
      20             : #include "src/interpreter/interpreter.h"
      21             : #include "src/isolate-inl.h"
      22             : #include "src/objects/debug-objects-inl.h"
      23             : #include "src/runtime/runtime.h"
      24             : #include "src/wasm/wasm-objects-inl.h"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : 
      29      349992 : RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
      30             :   SealHandleScope shs(isolate);
      31             :   DCHECK_EQ(1, args.length());
      32       58332 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
      33      116664 :   HandleScope scope(isolate);
      34      116664 :   ReturnValueScope result_scope(isolate->debug());
      35       58332 :   isolate->debug()->set_return_value(*value);
      36             : 
      37             :   // Get the top-most JavaScript frame.
      38      116664 :   JavaScriptFrameIterator it(isolate);
      39      116664 :   isolate->debug()->Break(it.frame());
      40             : 
      41             :   // Return the handler from the original bytecode array.
      42             :   DCHECK(it.frame()->is_interpreted());
      43             :   InterpretedFrame* interpreted_frame =
      44       58332 :       reinterpret_cast<InterpretedFrame*>(it.frame());
      45       58332 :   SharedFunctionInfo* shared = interpreted_frame->function()->shared();
      46       58332 :   BytecodeArray* bytecode_array = shared->bytecode_array();
      47       58332 :   int bytecode_offset = interpreted_frame->GetBytecodeOffset();
      48             :   interpreter::Bytecode bytecode =
      49       58332 :       interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
      50       58332 :   if (bytecode == interpreter::Bytecode::kReturn) {
      51             :     // If we are returning, reset the bytecode array on the interpreted stack
      52             :     // frame to the non-debug variant so that the interpreter entry trampoline
      53             :     // sees the return bytecode rather than the DebugBreak.
      54        6744 :     interpreted_frame->PatchBytecodeArray(bytecode_array);
      55             :   }
      56             :   return isolate->interpreter()->GetBytecodeHandler(
      57       58332 :       bytecode, interpreter::OperandScale::kSingle);
      58             : }
      59             : 
      60             : 
      61       16244 : RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
      62             :   SealHandleScope shs(isolate);
      63             :   DCHECK_EQ(0, args.length());
      64        8122 :   if (isolate->debug()->break_points_active()) {
      65        8069 :     isolate->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
      66             :   }
      67        8122 :   return isolate->heap()->undefined_value();
      68             : }
      69             : 
      70             : 
      71             : // Adds a JavaScript function as a debug event listener.
      72             : // args[0]: debug event listener function to set or null or undefined for
      73             : //          clearing the event listener function
      74             : // args[1]: object supplied during callback
      75         282 : RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
      76             :   SealHandleScope shs(isolate);
      77             :   DCHECK_EQ(2, args.length());
      78         217 :   CHECK(args[0]->IsJSFunction() || args[0]->IsNullOrUndefined(isolate));
      79          94 :   CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
      80          94 :   CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
      81          94 :   if (callback->IsJSFunction()) {
      82             :     JavaScriptDebugDelegate* delegate = new JavaScriptDebugDelegate(
      83          65 :         isolate, Handle<JSFunction>::cast(callback), data);
      84          65 :     isolate->debug()->SetDebugDelegate(delegate, true);
      85             :   } else {
      86          29 :     isolate->debug()->SetDebugDelegate(nullptr, false);
      87             :   }
      88          94 :   return isolate->heap()->undefined_value();
      89             : }
      90             : 
      91             : 
      92         254 : RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
      93             :   SealHandleScope shs(isolate);
      94             :   DCHECK_EQ(0, args.length());
      95         127 :   isolate->stack_guard()->RequestDebugBreak();
      96         127 :   return isolate->heap()->undefined_value();
      97             : }
      98             : 
      99         375 : static Handle<Object> DebugGetProperty(LookupIterator* it,
     100             :                                        bool* has_caught = nullptr) {
     101         290 :   for (; it->IsFound(); it->Next()) {
     102         140 :     switch (it->state()) {
     103             :       case LookupIterator::NOT_FOUND:
     104             :       case LookupIterator::TRANSITION:
     105           0 :         UNREACHABLE();
     106             :       case LookupIterator::ACCESS_CHECK:
     107             :         // Ignore access checks.
     108             :         break;
     109             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     110             :       case LookupIterator::INTERCEPTOR:
     111             :       case LookupIterator::JSPROXY:
     112          60 :         return it->isolate()->factory()->undefined_value();
     113             :       case LookupIterator::ACCESSOR: {
     114          25 :         Handle<Object> accessors = it->GetAccessors();
     115          25 :         if (!accessors->IsAccessorInfo()) {
     116           0 :           return it->isolate()->factory()->undefined_value();
     117             :         }
     118             :         MaybeHandle<Object> maybe_result =
     119          25 :             JSObject::GetPropertyWithAccessor(it);
     120             :         Handle<Object> result;
     121          25 :         if (!maybe_result.ToHandle(&result)) {
     122          10 :           result = handle(it->isolate()->pending_exception(), it->isolate());
     123             :           it->isolate()->clear_pending_exception();
     124          10 :           if (has_caught != nullptr) *has_caught = true;
     125             :         }
     126          25 :         return result;
     127             :       }
     128             : 
     129             :       case LookupIterator::DATA:
     130          55 :         return it->GetDataValue();
     131             :     }
     132             :   }
     133             : 
     134           5 :   return it->isolate()->factory()->undefined_value();
     135             : }
     136             : 
     137             : template <class IteratorType>
     138          97 : static MaybeHandle<JSArray> GetIteratorInternalProperties(
     139             :     Isolate* isolate, Handle<IteratorType> object) {
     140             :   Factory* factory = isolate->factory();
     141             :   Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
     142             :   const char* kind = nullptr;
     143          97 :   switch (iterator->map()->instance_type()) {
     144             :     case JS_MAP_KEY_ITERATOR_TYPE:
     145             :       kind = "keys";
     146             :       break;
     147             :     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
     148             :     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
     149             :       kind = "entries";
     150          49 :       break;
     151             :     case JS_MAP_VALUE_ITERATOR_TYPE:
     152             :     case JS_SET_VALUE_ITERATOR_TYPE:
     153             :       kind = "values";
     154          34 :       break;
     155             :     default:
     156           0 :       UNREACHABLE();
     157             :   }
     158             : 
     159          97 :   Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     160             :   Handle<String> has_more =
     161          97 :       factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
     162          97 :   result->set(0, *has_more);
     163         194 :   result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
     164             : 
     165             :   Handle<String> index =
     166          97 :       factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
     167          97 :   result->set(2, *index);
     168          97 :   result->set(3, iterator->index());
     169             : 
     170             :   Handle<String> iterator_kind =
     171          97 :       factory->NewStringFromAsciiChecked("[[IteratorKind]]");
     172          97 :   result->set(4, *iterator_kind);
     173          97 :   Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
     174          97 :   result->set(5, *kind_str);
     175          97 :   return factory->NewJSArrayWithElements(result);
     176             : }
     177             : 
     178             : 
     179       67176 : MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
     180             :                                                     Handle<Object> object) {
     181             :   Factory* factory = isolate->factory();
     182       67176 :   if (object->IsJSBoundFunction()) {
     183             :     Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
     184             : 
     185           5 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     186             :     Handle<String> target =
     187           5 :         factory->NewStringFromAsciiChecked("[[TargetFunction]]");
     188           5 :     result->set(0, *target);
     189           5 :     result->set(1, function->bound_target_function());
     190             : 
     191             :     Handle<String> bound_this =
     192           5 :         factory->NewStringFromAsciiChecked("[[BoundThis]]");
     193           5 :     result->set(2, *bound_this);
     194           5 :     result->set(3, function->bound_this());
     195             : 
     196             :     Handle<String> bound_args =
     197           5 :         factory->NewStringFromAsciiChecked("[[BoundArgs]]");
     198           5 :     result->set(4, *bound_args);
     199             :     Handle<FixedArray> bound_arguments =
     200           5 :         factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
     201             :     Handle<JSArray> arguments_array =
     202             :         factory->NewJSArrayWithElements(bound_arguments);
     203           5 :     result->set(5, *arguments_array);
     204           5 :     return factory->NewJSArrayWithElements(result);
     205       67171 :   } else if (object->IsJSMapIterator()) {
     206          62 :     Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
     207          62 :     return GetIteratorInternalProperties(isolate, iterator);
     208       67109 :   } else if (object->IsJSSetIterator()) {
     209          35 :     Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
     210          35 :     return GetIteratorInternalProperties(isolate, iterator);
     211       67074 :   } else if (object->IsJSGeneratorObject()) {
     212             :     Handle<JSGeneratorObject> generator =
     213             :         Handle<JSGeneratorObject>::cast(object);
     214             : 
     215             :     const char* status = "suspended";
     216          45 :     if (generator->is_closed()) {
     217             :       status = "closed";
     218          35 :     } else if (generator->is_executing()) {
     219             :       status = "running";
     220             :     } else {
     221             :       DCHECK(generator->is_suspended());
     222             :     }
     223             : 
     224          45 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     225             :     Handle<String> generator_status =
     226          45 :         factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
     227          45 :     result->set(0, *generator_status);
     228          45 :     Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
     229          45 :     result->set(1, *status_str);
     230             : 
     231             :     Handle<String> function =
     232          45 :         factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
     233          45 :     result->set(2, *function);
     234          45 :     result->set(3, generator->function());
     235             : 
     236             :     Handle<String> receiver =
     237          45 :         factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
     238          45 :     result->set(4, *receiver);
     239          45 :     result->set(5, generator->receiver());
     240          45 :     return factory->NewJSArrayWithElements(result);
     241       67029 :   } else if (object->IsJSPromise()) {
     242             :     Handle<JSPromise> promise = Handle<JSPromise>::cast(object);
     243          25 :     const char* status = JSPromise::Status(promise->status());
     244          25 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
     245             :     Handle<String> promise_status =
     246          25 :         factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
     247          25 :     result->set(0, *promise_status);
     248          25 :     Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
     249          25 :     result->set(1, *status_str);
     250             : 
     251             :     Handle<Object> value_obj(promise->result(), isolate);
     252             :     Handle<String> promise_value =
     253          25 :         factory->NewStringFromAsciiChecked("[[PromiseValue]]");
     254          25 :     result->set(2, *promise_value);
     255          25 :     result->set(3, *value_obj);
     256          25 :     return factory->NewJSArrayWithElements(result);
     257       67004 :   } else if (object->IsJSProxy()) {
     258             :     Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
     259           0 :     Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
     260             : 
     261             :     Handle<String> handler_str =
     262           0 :         factory->NewStringFromAsciiChecked("[[Handler]]");
     263           0 :     result->set(0, *handler_str);
     264           0 :     result->set(1, js_proxy->handler());
     265             : 
     266             :     Handle<String> target_str =
     267           0 :         factory->NewStringFromAsciiChecked("[[Target]]");
     268           0 :     result->set(2, *target_str);
     269           0 :     result->set(3, js_proxy->target());
     270             : 
     271             :     Handle<String> is_revoked_str =
     272           0 :         factory->NewStringFromAsciiChecked("[[IsRevoked]]");
     273           0 :     result->set(4, *is_revoked_str);
     274           0 :     result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
     275           0 :     return factory->NewJSArrayWithElements(result);
     276       67004 :   } else if (object->IsJSValue()) {
     277             :     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
     278             : 
     279         108 :     Handle<FixedArray> result = factory->NewFixedArray(2);
     280             :     Handle<String> primitive_value =
     281         108 :         factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
     282         108 :     result->set(0, *primitive_value);
     283         108 :     result->set(1, js_value->value());
     284         108 :     return factory->NewJSArrayWithElements(result);
     285             :   }
     286       66896 :   return factory->NewJSArray(0);
     287             : }
     288             : 
     289             : 
     290           0 : RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
     291           0 :   HandleScope scope(isolate);
     292             :   DCHECK_EQ(1, args.length());
     293           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
     294           0 :   RETURN_RESULT_OR_FAILURE(isolate,
     295           0 :                            Runtime::GetInternalProperties(isolate, obj));
     296             : }
     297             : 
     298             : 
     299             : // Get debugger related details for an object property, in the following format:
     300             : // 0: Property value
     301             : // 1: Property details
     302             : // 2: Property value is exception
     303             : // 3: Getter function if defined
     304             : // 4: Setter function if defined
     305             : // Items 2-4 are only filled if the property has either a getter or a setter.
     306         560 : RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
     307         185 :   HandleScope scope(isolate);
     308             :   DCHECK_EQ(2, args.length());
     309         370 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
     310         185 :   CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
     311             : 
     312             :   // Convert the {name_obj} to a Name.
     313             :   Handle<Name> name;
     314         370 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     315             :                                      Object::ToName(isolate, name_obj));
     316             : 
     317             :   // Make sure to set the current context to the context before the debugger was
     318             :   // entered (if the debugger is entered). The reason for switching context here
     319             :   // is that for some property lookups (accessors and interceptors) callbacks
     320             :   // into the embedding application can occur, and the embedding application
     321             :   // could have the assumption that its own native context is the current
     322             :   // context and not some internal debugger context.
     323         370 :   SaveContext save(isolate);
     324         185 :   if (isolate->debug()->in_debug_scope()) {
     325          10 :     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
     326             :   }
     327             : 
     328             :   // Check if the name is trivially convertible to an index and get the element
     329             :   // if so.
     330             :   uint32_t index;
     331             :   // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
     332             :   // this special case.
     333         185 :   if (name->AsArrayIndex(&index)) {
     334          40 :     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
     335             :     Handle<Object> element_or_char;
     336         120 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     337             :         isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
     338          40 :     details->set(0, *element_or_char);
     339          80 :     details->set(1, PropertyDetails::Empty().AsSmi());
     340          80 :     return *isolate->factory()->NewJSArrayWithElements(details);
     341             :   }
     342             : 
     343         145 :   LookupIterator it(obj, name, LookupIterator::OWN);
     344         145 :   bool has_caught = false;
     345         145 :   Handle<Object> value = DebugGetProperty(&it, &has_caught);
     346         145 :   if (!it.IsFound()) return isolate->heap()->undefined_value();
     347             : 
     348             :   Handle<Object> maybe_pair;
     349         140 :   if (it.state() == LookupIterator::ACCESSOR) {
     350          25 :     maybe_pair = it.GetAccessors();
     351             :   }
     352             : 
     353             :   // If the callback object is a fixed array then it contains JavaScript
     354             :   // getter and/or setter.
     355         165 :   bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
     356             :   Handle<FixedArray> details =
     357         140 :       isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
     358         140 :   details->set(0, *value);
     359             :   // TODO(verwaest): Get rid of this random way of handling interceptors.
     360         140 :   PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
     361             :                           ? PropertyDetails::Empty()
     362         140 :                           : it.property_details();
     363         280 :   details->set(1, d.AsSmi());
     364             :   details->set(
     365         280 :       2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
     366         140 :   if (has_js_accessors) {
     367           0 :     Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
     368           0 :     details->set(3, isolate->heap()->ToBoolean(has_caught));
     369             :     Handle<Object> getter =
     370           0 :         AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
     371             :     Handle<Object> setter =
     372           0 :         AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
     373           0 :     details->set(4, *getter);
     374           0 :     details->set(5, *setter);
     375             :   }
     376             : 
     377         465 :   return *isolate->factory()->NewJSArrayWithElements(details);
     378             : }
     379             : 
     380             : 
     381           0 : RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
     382           0 :   HandleScope scope(isolate);
     383             : 
     384             :   DCHECK_EQ(2, args.length());
     385             : 
     386           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
     387           0 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
     388             : 
     389           0 :   LookupIterator it(obj, name);
     390           0 :   return *DebugGetProperty(&it);
     391             : }
     392             : 
     393             : // Return the property kind calculated from the property details.
     394             : // args[0]: smi with property details.
     395           0 : RUNTIME_FUNCTION(Runtime_DebugPropertyKindFromDetails) {
     396             :   SealHandleScope shs(isolate);
     397             :   DCHECK_EQ(1, args.length());
     398           0 :   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
     399           0 :   return Smi::FromInt(static_cast<int>(details.kind()));
     400             : }
     401             : 
     402             : 
     403             : // Return the property attribute calculated from the property details.
     404             : // args[0]: smi with property details.
     405           0 : RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
     406             :   SealHandleScope shs(isolate);
     407             :   DCHECK_EQ(1, args.length());
     408           0 :   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
     409           0 :   return Smi::FromInt(static_cast<int>(details.attributes()));
     410             : }
     411             : 
     412             : 
     413        3492 : RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
     414             :   SealHandleScope shs(isolate);
     415             :   DCHECK_EQ(1, args.length());
     416        2328 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     417        1164 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     418        1164 :   return isolate->heap()->true_value();
     419             : }
     420             : 
     421             : 
     422        3088 : RUNTIME_FUNCTION(Runtime_GetFrameCount) {
     423         772 :   HandleScope scope(isolate);
     424             :   DCHECK_EQ(1, args.length());
     425        1544 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     426         772 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     427             : 
     428             :   // Count all frames which are relevant to debugging stack trace.
     429             :   int n = 0;
     430         772 :   StackFrame::Id id = isolate->debug()->break_frame_id();
     431         772 :   if (id == StackFrame::NO_ID) {
     432             :     // If there is no JavaScript stack frame count is 0.
     433             :     return Smi::kZero;
     434             :   }
     435             : 
     436        1494 :   std::vector<FrameSummary> frames;
     437         747 :   frames.reserve(FLAG_max_inlining_levels + 1);
     438        1972 :   for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
     439        1225 :     frames.clear();
     440        1225 :     it.frame()->Summarize(&frames);
     441        3681 :     for (size_t i = frames.size(); i != 0; i--) {
     442             :       // Omit functions from native and extension scripts.
     443        1231 :       if (frames[i - 1].is_subject_to_debugging()) n++;
     444             :     }
     445         747 :   }
     446        1519 :   return Smi::FromInt(n);
     447             : }
     448             : 
     449             : static const int kFrameDetailsFrameIdIndex = 0;
     450             : static const int kFrameDetailsReceiverIndex = 1;
     451             : static const int kFrameDetailsFunctionIndex = 2;
     452             : static const int kFrameDetailsScriptIndex = 3;
     453             : static const int kFrameDetailsArgumentCountIndex = 4;
     454             : static const int kFrameDetailsLocalCountIndex = 5;
     455             : static const int kFrameDetailsSourcePositionIndex = 6;
     456             : static const int kFrameDetailsConstructCallIndex = 7;
     457             : static const int kFrameDetailsAtReturnIndex = 8;
     458             : static const int kFrameDetailsFlagsIndex = 9;
     459             : static const int kFrameDetailsFirstDynamicIndex = 10;
     460             : 
     461             : // Return an array with frame details
     462             : // args[0]: number: break id
     463             : // args[1]: number: frame index
     464             : //
     465             : // The array returned contains the following information:
     466             : // 0: Frame id
     467             : // 1: Receiver
     468             : // 2: Function
     469             : // 3: Script
     470             : // 4: Argument count
     471             : // 5: Local count
     472             : // 6: Source position
     473             : // 7: Constructor call
     474             : // 8: Is at return
     475             : // 9: Flags
     476             : // Arguments name, value
     477             : // Locals name, value
     478             : // Return value if any
     479       60438 : RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
     480      141435 :   HandleScope scope(isolate);
     481             :   DCHECK_EQ(2, args.length());
     482       60438 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     483       60438 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     484             : 
     485       60438 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     486       30449 :   Heap* heap = isolate->heap();
     487             : 
     488             :   // Find the relevant frame with the requested index.
     489       60438 :   StackFrame::Id id = isolate->debug()->break_frame_id();
     490       30219 :   if (id == StackFrame::NO_ID) {
     491             :     // If there are no JavaScript stack frames return undefined.
     492           0 :     return heap->undefined_value();
     493             :   }
     494             : 
     495       60438 :   StackTraceFrameIterator it(isolate, id);
     496             :   // Inlined frame index in optimized frame, starting from outer function.
     497             :   int inlined_frame_index =
     498       30219 :       DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
     499       30219 :   if (inlined_frame_index == -1) return heap->undefined_value();
     500             : 
     501       60438 :   FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
     502             : 
     503             :   // Traverse the saved contexts chain to find the active context for the
     504             :   // selected frame.
     505             :   SaveContext* save =
     506       30219 :       DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
     507             : 
     508             :   // Get the frame id.
     509       30219 :   Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
     510       30219 :                           isolate);
     511             : 
     512       30219 :   if (frame_inspector.IsWasm()) {
     513             :     // Create the details array (no dynamic information for wasm).
     514             :     Handle<FixedArray> details =
     515           0 :         isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
     516             : 
     517             :     // Add the frame id.
     518           0 :     details->set(kFrameDetailsFrameIdIndex, *frame_id);
     519             : 
     520             :     // Add the function name.
     521           0 :     Handle<String> func_name = frame_inspector.GetFunctionName();
     522           0 :     details->set(kFrameDetailsFunctionIndex, *func_name);
     523             : 
     524             :     // Add the script wrapper
     525             :     Handle<Object> script_wrapper =
     526           0 :         Script::GetWrapper(frame_inspector.GetScript());
     527           0 :     details->set(kFrameDetailsScriptIndex, *script_wrapper);
     528             : 
     529             :     // Add the arguments count.
     530           0 :     details->set(kFrameDetailsArgumentCountIndex, Smi::kZero);
     531             : 
     532             :     // Add the locals count
     533           0 :     details->set(kFrameDetailsLocalCountIndex, Smi::kZero);
     534             : 
     535             :     // Add the source position.
     536           0 :     int position = frame_inspector.GetSourcePosition();
     537           0 :     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
     538             : 
     539             :     // Add the constructor information.
     540           0 :     details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
     541             : 
     542             :     // Add the at return information.
     543           0 :     details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
     544             : 
     545             :     // Add flags to indicate information on whether this frame is
     546             :     //   bit 0: invoked in the debugger context.
     547             :     //   bit 1: optimized frame.
     548             :     //   bit 2: inlined in optimized frame
     549           0 :     int flags = inlined_frame_index << 2;
     550           0 :     if (*save->context() == *isolate->debug()->debug_context()) {
     551           0 :       flags |= 1 << 0;
     552             :     }
     553           0 :     details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
     554             : 
     555           0 :     return *isolate->factory()->NewJSArrayWithElements(details);
     556             :   }
     557             : 
     558             :   // Find source position in unoptimized code.
     559       30219 :   int position = frame_inspector.GetSourcePosition();
     560             : 
     561             :   // Handle JavaScript frames.
     562       30219 :   bool is_optimized = it.frame()->is_optimized();
     563             : 
     564             :   // Check for constructor frame.
     565       30219 :   bool constructor = frame_inspector.IsConstructor();
     566             : 
     567             :   // Get scope info and read from it for local variable information.
     568             :   Handle<JSFunction> function =
     569       30219 :       Handle<JSFunction>::cast(frame_inspector.GetFunction());
     570       30219 :   CHECK(function->shared()->IsSubjectToDebugging());
     571       30219 :   Handle<SharedFunctionInfo> shared(function->shared());
     572       30219 :   Handle<ScopeInfo> scope_info(shared->scope_info());
     573             :   DCHECK(*scope_info != ScopeInfo::Empty(isolate));
     574             : 
     575             :   // Get the locals names and values into a temporary array.
     576       30219 :   Handle<Object> maybe_context = frame_inspector.GetContext();
     577             :   const int local_count_with_synthetic = maybe_context->IsContext()
     578             :                                              ? scope_info->LocalCount()
     579       60438 :                                              : scope_info->StackLocalCount();
     580             :   int local_count = local_count_with_synthetic;
     581       42945 :   for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
     582             :     // Hide compiler-introduced temporary variables, whether on the stack or on
     583             :     // the context.
     584       42945 :     if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
     585        1120 :       local_count--;
     586             :     }
     587             :   }
     588             : 
     589       60438 :   std::vector<Handle<Object>> locals;
     590             :   // Fill in the values of the locals.
     591             :   int i = 0;
     592      116059 :   for (; i < scope_info->StackLocalCount(); ++i) {
     593             :     // Use the value from the stack.
     594       44030 :     if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
     595       41810 :     locals.emplace_back(scope_info->LocalName(i), isolate);
     596             :     Handle<Object> value =
     597       41810 :         frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
     598             :     // TODO(yangguo): We convert optimized out values to {undefined} when they
     599             :     // are passed to the debugger. Eventually we should handle them somehow.
     600       83620 :     if (value->IsOptimizedOut(isolate)) {
     601        3995 :       value = isolate->factory()->undefined_value();
     602             :     }
     603       41810 :     locals.push_back(value);
     604             :   }
     605       30219 :   if (static_cast<int>(locals.size()) < local_count * 2) {
     606             :     // Get the context containing declarations.
     607             :     DCHECK(maybe_context->IsContext());
     608          15 :     Handle<Context> context(Context::cast(*maybe_context)->closure_context());
     609             : 
     610          65 :     for (; i < scope_info->LocalCount(); ++i) {
     611          25 :       Handle<String> name(scope_info->LocalName(i));
     612          35 :       if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     613             :       VariableMode mode;
     614             :       InitializationFlag init_flag;
     615             :       MaybeAssignedFlag maybe_assigned_flag;
     616          15 :       locals.push_back(name);
     617             :       int context_slot_index = ScopeInfo::ContextSlotIndex(
     618          15 :           scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
     619          15 :       Object* value = context->get(context_slot_index);
     620          15 :       locals.emplace_back(value, isolate);
     621             :     }
     622             :   }
     623             : 
     624             :   // Check whether this frame is positioned at return. If not top
     625             :   // frame or if the frame is optimized it cannot be at a return.
     626             :   bool at_return = false;
     627       30219 :   if (!is_optimized && index == 0) {
     628       39528 :     at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
     629             :   }
     630             : 
     631             :   // If positioned just before return find the value to be returned and add it
     632             :   // to the frame information.
     633       30219 :   Handle<Object> return_value = isolate->factory()->undefined_value();
     634       30219 :   if (at_return) {
     635        1590 :     return_value = handle(isolate->debug()->return_value(), isolate);
     636             :   }
     637             : 
     638             :   // Now advance to the arguments adapter frame (if any). It contains all
     639             :   // the provided parameters whereas the function frame always have the number
     640             :   // of arguments matching the functions parameters. The rest of the
     641             :   // information (except for what is collected above) is the same.
     642       60429 :   if ((inlined_frame_index == 0) &&
     643       30210 :       it.javascript_frame()->has_adapted_arguments()) {
     644         180 :     it.AdvanceOneFrame();
     645             :     DCHECK(it.frame()->is_arguments_adaptor());
     646         180 :     frame_inspector.SetArgumentsFrame(it.frame());
     647             :   }
     648             : 
     649             :   // Find the number of arguments to fill. At least fill the number of
     650             :   // parameters for the function and fill more if more parameters are provided.
     651       30219 :   int argument_count = scope_info->ParameterCount();
     652       30219 :   if (argument_count < frame_inspector.GetParametersCount()) {
     653          35 :     argument_count = frame_inspector.GetParametersCount();
     654             :   }
     655             : 
     656             :   // Calculate the size of the result.
     657       30219 :   int details_size = kFrameDetailsFirstDynamicIndex +
     658       60438 :                      2 * (argument_count + local_count) + (at_return ? 1 : 0);
     659       30219 :   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
     660             : 
     661             :   // Add the frame id.
     662       30219 :   details->set(kFrameDetailsFrameIdIndex, *frame_id);
     663             : 
     664             :   // Add the function (same as in function frame).
     665       60438 :   details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
     666             : 
     667             :   // Add the script wrapper
     668             :   Handle<Object> script_wrapper =
     669       30219 :       Script::GetWrapper(frame_inspector.GetScript());
     670       30219 :   details->set(kFrameDetailsScriptIndex, *script_wrapper);
     671             : 
     672             :   // Add the arguments count.
     673       60438 :   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
     674             : 
     675             :   // Add the locals count
     676       60438 :   details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
     677             : 
     678             :   // Add the source position.
     679       30219 :   if (position != kNoSourcePosition) {
     680       60438 :     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
     681             :   } else {
     682           0 :     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
     683             :   }
     684             : 
     685             :   // Add the constructor information.
     686       60438 :   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
     687             : 
     688             :   // Add the at return information.
     689       60438 :   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
     690             : 
     691             :   // Add flags to indicate information on whether this frame is
     692             :   //   bit 0: invoked in the debugger context.
     693             :   //   bit 1: optimized frame.
     694             :   //   bit 2: inlined in optimized frame
     695             :   int flags = 0;
     696      120876 :   if (*save->context() == *isolate->debug()->debug_context()) {
     697             :     flags |= 1 << 0;
     698             :   }
     699       30219 :   if (is_optimized) {
     700       10429 :     flags |= 1 << 1;
     701       10429 :     flags |= inlined_frame_index << 2;
     702             :   }
     703       60438 :   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
     704             : 
     705             :   // Fill the dynamic part.
     706             :   int details_index = kFrameDetailsFirstDynamicIndex;
     707             : 
     708             :   // Add arguments name and value.
     709       11780 :   for (int i = 0; i < argument_count; i++) {
     710             :     // Name of the argument.
     711       11780 :     if (i < scope_info->ParameterCount()) {
     712       23450 :       details->set(details_index++, scope_info->ParameterName(i));
     713             :     } else {
     714         110 :       details->set(details_index++, heap->undefined_value());
     715             :     }
     716             : 
     717             :     // Parameter value.
     718       11780 :     if (i < frame_inspector.GetParametersCount()) {
     719             :       // Get the value from the stack.
     720       34815 :       details->set(details_index++, *(frame_inspector.GetParameter(i)));
     721             :     } else {
     722         350 :       details->set(details_index++, heap->undefined_value());
     723             :     }
     724             :   }
     725             : 
     726             :   // Add locals name and value from the temporary copy from the function frame.
     727      197519 :   for (const auto& local : locals) details->set(details_index++, *local);
     728             : 
     729             :   // Add the value being returned.
     730       30219 :   if (at_return) {
     731         795 :     details->set(details_index++, *return_value);
     732             :   }
     733             : 
     734             :   // Add the receiver (same as in function frame).
     735       30219 :   Handle<Object> receiver = frame_inspector.GetReceiver();
     736             :   DCHECK(function->shared()->IsUserJavaScript());
     737             :   // Optimized frames only restore the receiver as best-effort (see
     738             :   // OptimizedFrame::Summarize).
     739             :   DCHECK_IMPLIES(!is_optimized && is_sloppy(shared->language_mode()),
     740             :                  receiver->IsJSReceiver());
     741       30219 :   details->set(kFrameDetailsReceiverIndex, *receiver);
     742             : 
     743             :   DCHECK_EQ(details_size, details_index);
     744       90657 :   return *isolate->factory()->NewJSArrayWithElements(details);
     745             : }
     746             : 
     747             : 
     748           0 : RUNTIME_FUNCTION(Runtime_GetScopeCount) {
     749           0 :   HandleScope scope(isolate);
     750             :   DCHECK_EQ(2, args.length());
     751           0 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     752           0 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     753             : 
     754           0 :   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
     755             : 
     756             :   // Get the frame where the debugging is performed.
     757           0 :   StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
     758           0 :   StackTraceFrameIterator it(isolate, id);
     759           0 :   StandardFrame* frame = it.frame();
     760           0 :   if (it.frame()->is_wasm()) return 0;
     761             : 
     762           0 :   FrameInspector frame_inspector(frame, 0, isolate);
     763             : 
     764             :   // Count the visible scopes.
     765             :   int n = 0;
     766           0 :   for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
     767           0 :     n++;
     768           0 :   }
     769             : 
     770           0 :   return Smi::FromInt(n);
     771             : }
     772             : 
     773             : 
     774             : // Return an array with scope details
     775             : // args[0]: number: break id
     776             : // args[1]: number: frame index
     777             : // args[2]: number: inlined frame index
     778             : // args[3]: number: scope index
     779             : //
     780             : // The array returned contains the following information:
     781             : // 0: Scope type
     782             : // 1: Scope object
     783           0 : RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
     784           0 :   HandleScope scope(isolate);
     785             :   DCHECK_EQ(4, args.length());
     786           0 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     787           0 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     788             : 
     789           0 :   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
     790           0 :   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
     791           0 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
     792             : 
     793             :   // Get the frame where the debugging is performed.
     794           0 :   StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
     795           0 :   StackTraceFrameIterator frame_it(isolate, id);
     796             :   // Wasm has no scopes, this must be javascript.
     797           0 :   JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
     798           0 :   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
     799             : 
     800             :   // Find the requested scope.
     801             :   int n = 0;
     802           0 :   ScopeIterator it(isolate, &frame_inspector);
     803           0 :   for (; !it.Done() && n < index; it.Next()) {
     804           0 :     n++;
     805             :   }
     806           0 :   if (it.Done()) {
     807           0 :     return isolate->heap()->undefined_value();
     808             :   }
     809           0 :   RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
     810             : }
     811             : 
     812             : 
     813             : // Return an array of scope details
     814             : // args[0]: number: break id
     815             : // args[1]: number: frame index
     816             : // args[2]: number: inlined frame index
     817             : // args[3]: boolean: ignore nested scopes
     818             : //
     819             : // The array returned contains arrays with the following information:
     820             : // 0: Scope type
     821             : // 1: Scope object
     822          30 : RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
     823          10 :   HandleScope scope(isolate);
     824             :   DCHECK(args.length() == 3 || args.length() == 4);
     825          20 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     826          10 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
     827             : 
     828          20 :   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
     829          20 :   CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
     830             : 
     831             :   ScopeIterator::Option option = ScopeIterator::DEFAULT;
     832          10 :   if (args.length() == 4) {
     833          20 :     CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
     834          10 :     if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
     835             :   }
     836             : 
     837             :   // Get the frame where the debugging is performed.
     838          10 :   StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
     839          20 :   StackTraceFrameIterator frame_it(isolate, id);
     840          10 :   StandardFrame* frame = frame_it.frame();
     841             : 
     842             :   // Handle wasm frames specially. They provide exactly two scopes (global /
     843             :   // local).
     844          10 :   if (frame->is_wasm_interpreter_entry()) {
     845             :     Handle<WasmDebugInfo> debug_info(
     846             :         WasmInterpreterEntryFrame::cast(frame)->wasm_instance()->debug_info(),
     847           0 :         isolate);
     848             :     return *WasmDebugInfo::GetScopeDetails(debug_info, frame->fp(),
     849           0 :                                            inlined_frame_index);
     850             :   }
     851             : 
     852          20 :   FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
     853          20 :   std::vector<Handle<JSObject>> result;
     854          20 :   ScopeIterator it(isolate, &frame_inspector, option);
     855          20 :   for (; !it.Done(); it.Next()) {
     856             :     Handle<JSObject> details;
     857          40 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
     858             :                                        it.MaterializeScopeDetails());
     859          20 :     result.push_back(details);
     860             :   }
     861             : 
     862          10 :   int result_size = static_cast<int>(result.size());
     863          10 :   Handle<FixedArray> array = isolate->factory()->NewFixedArray(result_size);
     864          20 :   for (int i = 0; i < result_size; ++i) {
     865          40 :     array->set(i, *result[i]);
     866             :   }
     867          30 :   return *isolate->factory()->NewJSArrayWithElements(array);
     868             : }
     869             : 
     870             : 
     871           0 : RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
     872           0 :   HandleScope scope(isolate);
     873             :   DCHECK_EQ(1, args.length());
     874             : 
     875             :   // Check arguments.
     876           0 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
     877             : 
     878             :   // Count the visible scopes.
     879             :   int n = 0;
     880           0 :   if (function->IsJSFunction()) {
     881           0 :     for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
     882           0 :          !it.Done(); it.Next()) {
     883           0 :       n++;
     884           0 :     }
     885             :   }
     886             : 
     887           0 :   return Smi::FromInt(n);
     888             : }
     889             : 
     890             : 
     891           0 : RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
     892           0 :   HandleScope scope(isolate);
     893             :   DCHECK_EQ(2, args.length());
     894             : 
     895             :   // Check arguments.
     896           0 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
     897           0 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     898             : 
     899             :   // Find the requested scope.
     900             :   int n = 0;
     901           0 :   ScopeIterator it(isolate, fun);
     902           0 :   for (; !it.Done() && n < index; it.Next()) {
     903           0 :     n++;
     904             :   }
     905           0 :   if (it.Done()) {
     906           0 :     return isolate->heap()->undefined_value();
     907             :   }
     908             : 
     909           0 :   RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
     910             : }
     911             : 
     912         576 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
     913         288 :   HandleScope scope(isolate);
     914             :   DCHECK_EQ(1, args.length());
     915             : 
     916         576 :   if (!args[0]->IsJSGeneratorObject()) return Smi::kZero;
     917             : 
     918             :   // Check arguments.
     919         576 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     920             : 
     921             :   // Only inspect suspended generator scopes.
     922         288 :   if (!gen->is_suspended()) {
     923             :     return Smi::kZero;
     924             :   }
     925             : 
     926             :   // Count the visible scopes.
     927             :   int n = 0;
     928        1368 :   for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
     929        1080 :     n++;
     930         288 :   }
     931             : 
     932         288 :   return Smi::FromInt(n);
     933             : }
     934             : 
     935        1890 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
     936         945 :   HandleScope scope(isolate);
     937             :   DCHECK_EQ(2, args.length());
     938             : 
     939        1890 :   if (!args[0]->IsJSGeneratorObject()) {
     940           0 :     return isolate->heap()->undefined_value();
     941             :   }
     942             : 
     943             :   // Check arguments.
     944        1890 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     945        1890 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     946             : 
     947             :   // Only inspect suspended generator scopes.
     948         945 :   if (!gen->is_suspended()) {
     949           0 :     return isolate->heap()->undefined_value();
     950             :   }
     951             : 
     952             :   // Find the requested scope.
     953             :   int n = 0;
     954        1890 :   ScopeIterator it(isolate, gen);
     955         927 :   for (; !it.Done() && n < index; it.Next()) {
     956         927 :     n++;
     957             :   }
     958         945 :   if (it.Done()) {
     959           0 :     return isolate->heap()->undefined_value();
     960             :   }
     961             : 
     962        2835 :   RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
     963             : }
     964             : 
     965         137 : static bool SetScopeVariableValue(ScopeIterator* it, int index,
     966             :                                   Handle<String> variable_name,
     967             :                                   Handle<Object> new_value) {
     968         418 :   for (int n = 0; !it->Done() && n < index; it->Next()) {
     969          72 :     n++;
     970             :   }
     971         137 :   if (it->Done()) {
     972             :     return false;
     973             :   }
     974         137 :   return it->SetVariableValue(variable_name, new_value);
     975             : }
     976             : 
     977             : 
     978             : // Change variable value in closure or local scope
     979             : // args[0]: number or JsFunction: break id or function
     980             : // args[1]: number: frame index (when arg[0] is break id)
     981             : // args[2]: number: inlined frame index (when arg[0] is break id)
     982             : // args[3]: number: scope index
     983             : // args[4]: string: variable name
     984             : // args[5]: object: new value
     985             : //
     986             : // Return true if success and false otherwise
     987         294 : RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
     988         137 :   HandleScope scope(isolate);
     989             :   DCHECK_EQ(6, args.length());
     990             : 
     991             :   // Check arguments.
     992         274 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
     993         274 :   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
     994         137 :   CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
     995             : 
     996             :   bool res;
     997         274 :   if (args[0]->IsNumber()) {
     998          40 :     CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
     999          20 :     CHECK(isolate->debug()->CheckExecutionState(break_id));
    1000             : 
    1001          40 :     CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
    1002          40 :     CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
    1003             : 
    1004             :     // Get the frame where the debugging is performed.
    1005          20 :     StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
    1006          20 :     StackTraceFrameIterator frame_it(isolate, id);
    1007             :     // Wasm has no scopes, this must be javascript.
    1008          20 :     JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
    1009          40 :     FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
    1010             : 
    1011          40 :     ScopeIterator it(isolate, &frame_inspector);
    1012          40 :     res = SetScopeVariableValue(&it, index, variable_name, new_value);
    1013         234 :   } else if (args[0]->IsJSFunction()) {
    1014           0 :     CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
    1015           0 :     ScopeIterator it(isolate, fun);
    1016           0 :     res = SetScopeVariableValue(&it, index, variable_name, new_value);
    1017             :   } else {
    1018         234 :     CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
    1019         117 :     ScopeIterator it(isolate, gen);
    1020         117 :     res = SetScopeVariableValue(&it, index, variable_name, new_value);
    1021             :   }
    1022             : 
    1023         137 :   return isolate->heap()->ToBoolean(res);
    1024             : }
    1025             : 
    1026             : 
    1027           0 : RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
    1028           0 :   HandleScope scope(isolate);
    1029             :   DCHECK_EQ(0, args.length());
    1030             : 
    1031             : #ifdef DEBUG
    1032             :   // Print the scopes for the top frame.
    1033             :   JavaScriptFrameIterator it(isolate);
    1034             :   if (!it.done()) {
    1035             :     JavaScriptFrame* frame = it.frame();
    1036             :     FrameInspector frame_inspector(frame, 0, isolate);
    1037             :     for (ScopeIterator si(isolate, &frame_inspector); !si.Done(); si.Next()) {
    1038             :       si.DebugPrint();
    1039             :     }
    1040             :   }
    1041             : #endif
    1042           0 :   return isolate->heap()->undefined_value();
    1043             : }
    1044             : 
    1045             : 
    1046             : // Sets the disable break state
    1047             : // args[0]: disable break state
    1048           0 : RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
    1049           0 :   HandleScope scope(isolate);
    1050             :   DCHECK_EQ(1, args.length());
    1051           0 :   CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
    1052           0 :   isolate->debug()->set_break_points_active(active);
    1053           0 :   return isolate->heap()->undefined_value();
    1054             : }
    1055             : 
    1056             : 
    1057         756 : RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
    1058         252 :   HandleScope scope(isolate);
    1059             :   DCHECK_EQ(1, args.length());
    1060         252 :   CHECK(isolate->debug()->is_active());
    1061         504 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
    1062             : 
    1063         252 :   Handle<SharedFunctionInfo> shared(fun->shared());
    1064             :   // Find the number of break points
    1065         252 :   Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
    1066         252 :   if (break_locations->IsUndefined(isolate)) {
    1067          36 :     return isolate->heap()->undefined_value();
    1068             :   }
    1069             :   // Return array as JS array
    1070             :   return *isolate->factory()->NewJSArrayWithElements(
    1071         648 :       Handle<FixedArray>::cast(break_locations));
    1072             : }
    1073             : 
    1074             : 
    1075             : // Set a break point in a function.
    1076             : // args[0]: function
    1077             : // args[1]: number: break source position (within the function source)
    1078             : // args[2]: number: break point object
    1079           0 : RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
    1080           0 :   HandleScope scope(isolate);
    1081             :   DCHECK_EQ(3, args.length());
    1082           0 :   CHECK(isolate->debug()->is_active());
    1083           0 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
    1084           0 :   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
    1085           0 :   CHECK(source_position >= function->shared()->start_position() &&
    1086             :         source_position <= function->shared()->end_position());
    1087           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
    1088             : 
    1089             :   // Set break point.
    1090           0 :   CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
    1091             :                                         &source_position));
    1092             : 
    1093           0 :   return Smi::FromInt(source_position);
    1094             : }
    1095             : 
    1096             : // Changes the state of a break point in a script and returns source position
    1097             : // where break point was set. NOTE: Regarding performance see the NOTE for
    1098             : // GetScriptFromScriptData.
    1099             : // args[0]: script to set break point in
    1100             : // args[1]: number: break source position (within the script source)
    1101             : // args[2]: number: break point object
    1102         840 : RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
    1103         210 :   HandleScope scope(isolate);
    1104             :   DCHECK_EQ(3, args.length());
    1105         210 :   CHECK(isolate->debug()->is_active());
    1106         420 :   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
    1107         420 :   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
    1108         210 :   CHECK_GE(source_position, 0);
    1109         210 :   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
    1110             : 
    1111             :   // Get the script from the script wrapper.
    1112         420 :   CHECK(wrapper->value()->IsScript());
    1113         210 :   Handle<Script> script(Script::cast(wrapper->value()));
    1114             : 
    1115             :   // Set break point.
    1116         210 :   if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
    1117         210 :                                                 &source_position)) {
    1118          10 :     return isolate->heap()->undefined_value();
    1119             :   }
    1120             : 
    1121         200 :   return Smi::FromInt(source_position);
    1122             : }
    1123             : 
    1124             : 
    1125             : // Clear a break point
    1126             : // args[0]: number: break point object
    1127         530 : RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
    1128         265 :   HandleScope scope(isolate);
    1129             :   DCHECK_EQ(1, args.length());
    1130         265 :   CHECK(isolate->debug()->is_active());
    1131         265 :   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
    1132             : 
    1133             :   // Clear break point.
    1134         265 :   isolate->debug()->ClearBreakPoint(break_point_object_arg);
    1135             : 
    1136         265 :   return isolate->heap()->undefined_value();
    1137             : }
    1138             : 
    1139             : 
    1140             : // Change the state of break on exceptions.
    1141             : // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
    1142             : // args[1]: Boolean indicating on/off.
    1143         120 : RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
    1144          40 :   HandleScope scope(isolate);
    1145             :   DCHECK_EQ(2, args.length());
    1146          80 :   CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
    1147          80 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
    1148             : 
    1149             :   // If the number doesn't match an enum value, the ChangeBreakOnException
    1150             :   // function will default to affecting caught exceptions.
    1151             :   ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
    1152             :   // Update break point state.
    1153          80 :   isolate->debug()->ChangeBreakOnException(type, enable);
    1154          40 :   return isolate->heap()->undefined_value();
    1155             : }
    1156             : 
    1157             : 
    1158             : // Returns the state of break on exceptions
    1159             : // args[0]: boolean indicating uncaught exceptions
    1160        9909 : RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
    1161        3303 :   HandleScope scope(isolate);
    1162             :   DCHECK_EQ(1, args.length());
    1163        6606 :   CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
    1164             : 
    1165             :   ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
    1166        3303 :   bool result = isolate->debug()->IsBreakOnException(type);
    1167        3303 :   return Smi::FromInt(result);
    1168             : }
    1169             : 
    1170             : 
    1171             : // Prepare for stepping
    1172             : // args[0]: break id for checking execution state
    1173             : // args[1]: step action from the enumeration StepAction
    1174             : // args[2]: number of times to perform the step, for step out it is the number
    1175             : //          of frames to step down.
    1176           0 : RUNTIME_FUNCTION(Runtime_PrepareStep) {
    1177           0 :   HandleScope scope(isolate);
    1178             :   DCHECK_EQ(2, args.length());
    1179           0 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
    1180           0 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
    1181             : 
    1182           0 :   if (!args[1]->IsNumber()) {
    1183           0 :     return isolate->Throw(isolate->heap()->illegal_argument_string());
    1184             :   }
    1185             : 
    1186             :   // Get the step action and check validity.
    1187           0 :   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
    1188           0 :   if (step_action != StepIn && step_action != StepNext &&
    1189             :       step_action != StepOut) {
    1190           0 :     return isolate->Throw(isolate->heap()->illegal_argument_string());
    1191             :   }
    1192             : 
    1193             :   // Clear all current stepping setup.
    1194           0 :   isolate->debug()->ClearStepping();
    1195             : 
    1196             :   // Prepare step.
    1197           0 :   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
    1198           0 :   return isolate->heap()->undefined_value();
    1199             : }
    1200             : 
    1201             : // Clear all stepping set by PrepareStep.
    1202          36 : RUNTIME_FUNCTION(Runtime_ClearStepping) {
    1203          18 :   HandleScope scope(isolate);
    1204             :   DCHECK_EQ(0, args.length());
    1205          18 :   CHECK(isolate->debug()->is_active());
    1206          18 :   isolate->debug()->ClearStepping();
    1207          18 :   return isolate->heap()->undefined_value();
    1208             : }
    1209             : 
    1210             : 
    1211         420 : RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
    1212         140 :   HandleScope scope(isolate);
    1213             : 
    1214             :   // Check the execution state and decode arguments frame and source to be
    1215             :   // evaluated.
    1216             :   DCHECK_EQ(5, args.length());
    1217         280 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
    1218         140 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
    1219             : 
    1220         280 :   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
    1221         280 :   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
    1222         280 :   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
    1223         280 :   CONVERT_BOOLEAN_ARG_CHECKED(throw_on_side_effect, 4);
    1224             : 
    1225         140 :   StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
    1226             : 
    1227         280 :   RETURN_RESULT_OR_FAILURE(
    1228             :       isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
    1229         140 :                                     throw_on_side_effect));
    1230             : }
    1231             : 
    1232             : 
    1233          15 : RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
    1234           5 :   HandleScope scope(isolate);
    1235             : 
    1236             :   // Check the execution state and decode arguments frame and source to be
    1237             :   // evaluated.
    1238             :   DCHECK_EQ(2, args.length());
    1239          10 :   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
    1240           5 :   CHECK(isolate->debug()->CheckExecutionState(break_id));
    1241             : 
    1242          10 :   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
    1243             : 
    1244          15 :   RETURN_RESULT_OR_FAILURE(isolate, DebugEvaluate::Global(isolate, source));
    1245             : }
    1246             : 
    1247             : 
    1248        1364 : RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
    1249         366 :   HandleScope scope(isolate);
    1250             :   DCHECK_EQ(0, args.length());
    1251             : 
    1252             :   Handle<FixedArray> instances;
    1253             :   {
    1254         366 :     DebugScope debug_scope(isolate->debug());
    1255         366 :     if (debug_scope.failed()) {
    1256             :       DCHECK(isolate->has_pending_exception());
    1257         100 :       return isolate->heap()->exception();
    1258             :     }
    1259             :     // Fill the script objects.
    1260         266 :     instances = isolate->debug()->GetLoadedScripts();
    1261             :   }
    1262             : 
    1263             :   // Convert the script objects to proper JS objects.
    1264       10732 :   for (int i = 0; i < instances->length(); i++) {
    1265        5233 :     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
    1266             :     // Get the script wrapper in a local handle before calling GetScriptWrapper,
    1267             :     // because using
    1268             :     //   instances->set(i, *GetScriptWrapper(script))
    1269             :     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
    1270             :     // already have dereferenced the instances handle.
    1271        5233 :     Handle<JSObject> wrapper = Script::GetWrapper(script);
    1272        5233 :     instances->set(i, *wrapper);
    1273             :   }
    1274             : 
    1275             :   // Return result as a JS array.
    1276         532 :   return *isolate->factory()->NewJSArrayWithElements(instances);
    1277             : }
    1278             : 
    1279           0 : static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
    1280             :                                                JSObject* object,
    1281             :                                                Object* proto) {
    1282             :   PrototypeIterator iter(isolate, object, kStartAtReceiver);
    1283             :   while (true) {
    1284           0 :     iter.AdvanceIgnoringProxies();
    1285           0 :     if (iter.IsAtEnd()) return false;
    1286           0 :     if (iter.GetCurrent() == proto) return true;
    1287             :   }
    1288             : }
    1289             : 
    1290             : 
    1291             : // Scan the heap for objects with direct references to an object
    1292             : // args[0]: the object to find references to
    1293             : // args[1]: constructor function for instances to exclude (Mirror)
    1294             : // args[2]: the the maximum number of objects to return
    1295           0 : RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
    1296           0 :   HandleScope scope(isolate);
    1297             :   DCHECK_EQ(3, args.length());
    1298           0 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
    1299           0 :   CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
    1300           0 :   CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
    1301           0 :   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
    1302           0 :   CHECK_GE(max_references, 0);
    1303             : 
    1304           0 :   std::vector<Handle<JSObject>> instances;
    1305           0 :   Heap* heap = isolate->heap();
    1306             :   {
    1307           0 :     HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
    1308             :     // Get the constructor function for context extension and arguments array.
    1309           0 :     Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
    1310             :     HeapObject* heap_obj;
    1311           0 :     while ((heap_obj = iterator.next()) != nullptr) {
    1312           0 :       if (!heap_obj->IsJSObject()) continue;
    1313           0 :       JSObject* obj = JSObject::cast(heap_obj);
    1314           0 :       if (obj->IsJSContextExtensionObject()) continue;
    1315           0 :       if (obj->map()->GetConstructor() == arguments_fun) continue;
    1316           0 :       if (!obj->ReferencesObject(*target)) continue;
    1317             :       // Check filter if supplied. This is normally used to avoid
    1318             :       // references from mirror objects.
    1319           0 :       if (!filter->IsUndefined(isolate) &&
    1320           0 :           HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
    1321             :         continue;
    1322             :       }
    1323           0 :       if (obj->IsJSGlobalObject()) {
    1324           0 :         obj = JSGlobalObject::cast(obj)->global_proxy();
    1325             :       }
    1326           0 :       instances.emplace_back(obj);
    1327           0 :       if (static_cast<int32_t>(instances.size()) == max_references) break;
    1328             :     }
    1329             :     // Iterate the rest of the heap to satisfy HeapIterator constraints.
    1330           0 :     while (iterator.next()) {
    1331           0 :     }
    1332             :   }
    1333             : 
    1334             :   Handle<FixedArray> result;
    1335           0 :   if (instances.size() == 1 && instances.back().is_identical_to(target)) {
    1336             :     // Check for circular reference only. This can happen when the object is
    1337             :     // only referenced from mirrors and has a circular reference in which case
    1338             :     // the object is not really alive and would have been garbage collected if
    1339             :     // not referenced from the mirror.
    1340           0 :     result = isolate->factory()->empty_fixed_array();
    1341             :   } else {
    1342           0 :     int instances_size = static_cast<int>(instances.size());
    1343           0 :     result = isolate->factory()->NewFixedArray(instances_size);
    1344           0 :     for (int i = 0; i < instances_size; ++i) result->set(i, *instances[i]);
    1345             :   }
    1346           0 :   return *isolate->factory()->NewJSArrayWithElements(result);
    1347             : }
    1348             : 
    1349             : 
    1350             : // Scan the heap for objects constructed by a specific function.
    1351             : // args[0]: the constructor to find instances of
    1352             : // args[1]: the the maximum number of objects to return
    1353           0 : RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
    1354           0 :   HandleScope scope(isolate);
    1355             :   DCHECK_EQ(2, args.length());
    1356           0 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
    1357           0 :   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
    1358           0 :   CHECK_GE(max_references, 0);
    1359             : 
    1360           0 :   std::vector<Handle<JSObject>> instances;
    1361           0 :   Heap* heap = isolate->heap();
    1362             :   {
    1363           0 :     HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
    1364             :     HeapObject* heap_obj;
    1365           0 :     while ((heap_obj = iterator.next()) != nullptr) {
    1366           0 :       if (!heap_obj->IsJSObject()) continue;
    1367           0 :       JSObject* obj = JSObject::cast(heap_obj);
    1368           0 :       if (obj->map()->GetConstructor() != *constructor) continue;
    1369           0 :       instances.emplace_back(obj);
    1370           0 :       if (static_cast<int32_t>(instances.size()) == max_references) break;
    1371             :     }
    1372             :     // Iterate the rest of the heap to satisfy HeapIterator constraints.
    1373           0 :     while (iterator.next()) {
    1374           0 :     }
    1375             :   }
    1376             : 
    1377           0 :   int instances_size = static_cast<int>(instances.size());
    1378           0 :   Handle<FixedArray> result = isolate->factory()->NewFixedArray(instances_size);
    1379           0 :   for (int i = 0; i < instances_size; ++i) result->set(i, *instances[i]);
    1380           0 :   return *isolate->factory()->NewJSArrayWithElements(result);
    1381             : }
    1382             : 
    1383             : 
    1384             : // Find the effective prototype object as returned by __proto__.
    1385             : // args[0]: the object to find the prototype for.
    1386          10 : RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
    1387           5 :   HandleScope shs(isolate);
    1388             :   DCHECK_EQ(1, args.length());
    1389          10 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
    1390             :   // TODO(1543): Come up with a solution for clients to handle potential errors
    1391             :   // thrown by an intermediate proxy.
    1392          15 :   RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
    1393             : }
    1394             : 
    1395             : 
    1396             : // Patches script source (should be called upon BeforeCompile event).
    1397             : // TODO(5530): Remove once uses in debug.js are gone.
    1398           0 : RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
    1399           0 :   HandleScope scope(isolate);
    1400             :   DCHECK_EQ(2, args.length());
    1401             : 
    1402           0 :   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
    1403           0 :   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
    1404             : 
    1405           0 :   CHECK(script_wrapper->value()->IsScript());
    1406           0 :   Handle<Script> script(Script::cast(script_wrapper->value()));
    1407             : 
    1408             :   // The following condition is not guaranteed to hold and a failure is also
    1409             :   // propagated to callers. Hence we fail gracefully here and don't crash.
    1410           0 :   if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
    1411           0 :     return isolate->ThrowIllegalOperation();
    1412             :   }
    1413             : 
    1414           0 :   script->set_source(*source);
    1415             : 
    1416           0 :   return isolate->heap()->undefined_value();
    1417             : }
    1418             : 
    1419             : 
    1420         140 : RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
    1421             :   SealHandleScope shs(isolate);
    1422             :   DCHECK_EQ(1, args.length());
    1423             : 
    1424          70 :   CONVERT_ARG_CHECKED(Object, f, 0);
    1425          70 :   if (f->IsJSFunction()) {
    1426          60 :     return JSFunction::cast(f)->shared()->inferred_name();
    1427             :   }
    1428          10 :   return isolate->heap()->empty_string();
    1429             : }
    1430             : 
    1431             : 
    1432           0 : RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
    1433           0 :   HandleScope scope(isolate);
    1434             :   DCHECK_EQ(1, args.length());
    1435             : 
    1436           0 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
    1437             : 
    1438           0 :   if (function->IsJSBoundFunction()) {
    1439           0 :     RETURN_RESULT_OR_FAILURE(
    1440             :         isolate, JSBoundFunction::GetName(
    1441             :                      isolate, Handle<JSBoundFunction>::cast(function)));
    1442             :   } else {
    1443           0 :     return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
    1444           0 :   }
    1445             : }
    1446             : 
    1447             : 
    1448        7408 : RUNTIME_FUNCTION(Runtime_GetDebugContext) {
    1449        2102 :   HandleScope scope(isolate);
    1450             :   DCHECK_EQ(0, args.length());
    1451             :   Handle<Context> context;
    1452             :   {
    1453        2102 :     DebugScope debug_scope(isolate->debug());
    1454        2102 :     if (debug_scope.failed()) {
    1455             :       DCHECK(isolate->has_pending_exception());
    1456        1000 :       return isolate->heap()->exception();
    1457             :     }
    1458        1102 :     context = isolate->debug()->GetDebugContext();
    1459             :   }
    1460        1102 :   if (context.is_null()) return isolate->heap()->undefined_value();
    1461        3306 :   context->set_security_token(isolate->native_context()->security_token());
    1462        1102 :   return context->global_proxy();
    1463             : }
    1464             : 
    1465             : 
    1466             : // Performs a GC.
    1467             : // Presently, it only does a full GC.
    1468         444 : RUNTIME_FUNCTION(Runtime_CollectGarbage) {
    1469             :   SealHandleScope shs(isolate);
    1470             :   DCHECK_EQ(1, args.length());
    1471             :   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
    1472         222 :                                      GarbageCollectionReason::kRuntime);
    1473         222 :   return isolate->heap()->undefined_value();
    1474             : }
    1475             : 
    1476             : 
    1477             : // Gets the current heap usage.
    1478           0 : RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
    1479             :   SealHandleScope shs(isolate);
    1480             :   DCHECK_EQ(0, args.length());
    1481           0 :   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
    1482           0 :   if (!Smi::IsValid(usage)) {
    1483           0 :     return *isolate->factory()->NewNumberFromInt(usage);
    1484             :   }
    1485           0 :   return Smi::FromInt(usage);
    1486             : }
    1487             : 
    1488             : 
    1489             : // Finds the script object from the script data. NOTE: This operation uses
    1490             : // heap traversal to find the function generated for the source position
    1491             : // for the requested break point. For lazily compiled functions several heap
    1492             : // traversals might be required rendering this operation as a rather slow
    1493             : // operation. However for setting break points which is normally done through
    1494             : // some kind of user interaction the performance is not crucial.
    1495          80 : RUNTIME_FUNCTION(Runtime_GetScript) {
    1496          40 :   HandleScope scope(isolate);
    1497             :   DCHECK_EQ(1, args.length());
    1498          80 :   CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
    1499             : 
    1500             :   Handle<Script> found;
    1501             :   {
    1502          40 :     Script::Iterator iterator(isolate);
    1503             :     Script* script = nullptr;
    1504         560 :     while ((script = iterator.Next()) != nullptr) {
    1505        1090 :       if (!script->name()->IsString()) continue;
    1506         465 :       String* name = String::cast(script->name());
    1507         465 :       if (name->Equals(*script_name)) {
    1508             :         found = Handle<Script>(script, isolate);
    1509             :         break;
    1510             :       }
    1511             :     }
    1512             :   }
    1513             : 
    1514          40 :   if (found.is_null()) return isolate->heap()->undefined_value();
    1515          50 :   return *Script::GetWrapper(found);
    1516             : }
    1517             : 
    1518             : // TODO(5530): Remove once uses in debug.js are gone.
    1519        4930 : RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
    1520        2465 :   HandleScope scope(isolate);
    1521             :   DCHECK_EQ(1, args.length());
    1522        4930 :   CONVERT_ARG_CHECKED(JSValue, script, 0);
    1523             : 
    1524        4930 :   CHECK(script->value()->IsScript());
    1525        2465 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1526             : 
    1527        2465 :   if (script_handle->type() == Script::TYPE_WASM) {
    1528             :     // Return 0 for now; this function will disappear soon anyway.
    1529           0 :     return Smi::FromInt(0);
    1530             :   }
    1531             : 
    1532        2465 :   Script::InitLineEnds(script_handle);
    1533             : 
    1534        2465 :   FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
    1535        2465 :   return Smi::FromInt(line_ends_array->length());
    1536             : }
    1537             : 
    1538             : namespace {
    1539             : 
    1540      129822 : int ScriptLinePosition(Handle<Script> script, int line) {
    1541      129822 :   if (line < 0) return -1;
    1542             : 
    1543      129822 :   if (script->type() == Script::TYPE_WASM) {
    1544             :     return WasmCompiledModule::cast(script->wasm_compiled_module())
    1545          36 :         ->GetFunctionOffset(line);
    1546             :   }
    1547             : 
    1548      129804 :   Script::InitLineEnds(script);
    1549             : 
    1550             :   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
    1551             :   const int line_count = line_ends_array->length();
    1552             :   DCHECK_LT(0, line_count);
    1553             : 
    1554      129804 :   if (line == 0) return 0;
    1555             :   // If line == line_count, we return the first position beyond the last line.
    1556      107250 :   if (line > line_count) return -1;
    1557      214500 :   return Smi::ToInt(line_ends_array->get(line - 1)) + 1;
    1558             : }
    1559             : 
    1560             : }  // namespace
    1561             : 
    1562             : // TODO(5530): Remove once uses in debug.js are gone.
    1563           0 : RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
    1564           0 :   HandleScope scope(isolate);
    1565             :   DCHECK_EQ(2, args.length());
    1566           0 :   CONVERT_ARG_CHECKED(JSValue, script, 0);
    1567           0 :   CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
    1568             : 
    1569           0 :   CHECK(script->value()->IsScript());
    1570           0 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1571             : 
    1572           0 :   return Smi::FromInt(ScriptLinePosition(script_handle, line));
    1573             : }
    1574             : 
    1575             : // TODO(5530): Remove once uses in debug.js are gone.
    1576           0 : RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
    1577           0 :   HandleScope scope(isolate);
    1578             :   DCHECK_EQ(2, args.length());
    1579           0 :   CONVERT_ARG_CHECKED(JSValue, script, 0);
    1580           0 :   CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
    1581             : 
    1582           0 :   CHECK(script->value()->IsScript());
    1583           0 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1584             : 
    1585           0 :   if (script_handle->type() == Script::TYPE_WASM) {
    1586             :     // Return zero for now; this function will disappear soon anyway.
    1587           0 :     return Smi::FromInt(0);
    1588             :   }
    1589             : 
    1590           0 :   Script::InitLineEnds(script_handle);
    1591             : 
    1592           0 :   FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
    1593           0 :   const int line_count = line_ends_array->length();
    1594             : 
    1595           0 :   if (line < 0 || line >= line_count) {
    1596           0 :     return Smi::FromInt(-1);
    1597             :   } else {
    1598           0 :     return Smi::cast(line_ends_array->get(line));
    1599           0 :   }
    1600             : }
    1601             : 
    1602      132763 : static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
    1603             :                                         Script::OffsetFlag offset_flag,
    1604             :                                         Isolate* isolate) {
    1605             :   Script::PositionInfo info;
    1606      132763 :   if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
    1607           9 :     return isolate->factory()->null_value();
    1608             :   }
    1609             : 
    1610      132754 :   Handle<String> source = handle(String::cast(script->source()), isolate);
    1611             :   Handle<String> sourceText = script->type() == Script::TYPE_WASM
    1612             :                                   ? isolate->factory()->empty_string()
    1613             :                                   : isolate->factory()->NewSubString(
    1614      265490 :                                         source, info.line_start, info.line_end);
    1615             : 
    1616             :   Handle<JSObject> jsinfo =
    1617      132754 :       isolate->factory()->NewJSObject(isolate->object_function());
    1618             : 
    1619             :   JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
    1620      132754 :                         NONE);
    1621             :   JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
    1622      132754 :                         handle(Smi::FromInt(position), isolate), NONE);
    1623             :   JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
    1624      265508 :                         handle(Smi::FromInt(info.line), isolate), NONE);
    1625             :   JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
    1626      265508 :                         handle(Smi::FromInt(info.column), isolate), NONE);
    1627             :   JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
    1628      132754 :                         sourceText, NONE);
    1629             : 
    1630      132754 :   return jsinfo;
    1631             : }
    1632             : 
    1633             : namespace {
    1634             : 
    1635      129822 : int ScriptLinePositionWithOffset(Handle<Script> script, int line, int offset) {
    1636      129822 :   if (line < 0 || offset < 0) return -1;
    1637             : 
    1638      129822 :   if (line == 0 || offset == 0)
    1639      129033 :     return ScriptLinePosition(script, line) + offset;
    1640             : 
    1641             :   Script::PositionInfo info;
    1642         789 :   if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET)) {
    1643             :     return -1;
    1644             :   }
    1645             : 
    1646         789 :   const int total_line = info.line + line;
    1647         789 :   return ScriptLinePosition(script, total_line);
    1648             : }
    1649             : 
    1650      129822 : Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script,
    1651             :                                       Handle<Object> opt_line,
    1652             :                                       Handle<Object> opt_column,
    1653             :                                       int32_t offset) {
    1654             :   // Line and column are possibly undefined and we need to handle these cases,
    1655             :   // additionally subtracting corresponding offsets.
    1656             : 
    1657             :   int32_t line = 0;
    1658      129822 :   if (!opt_line->IsNullOrUndefined(isolate)) {
    1659      129634 :     CHECK(opt_line->IsNumber());
    1660      259268 :     line = NumberToInt32(*opt_line) - script->line_offset();
    1661             :   }
    1662             : 
    1663             :   int32_t column = 0;
    1664      129822 :   if (!opt_column->IsNullOrUndefined(isolate)) {
    1665      129179 :     CHECK(opt_column->IsNumber());
    1666      129179 :     column = NumberToInt32(*opt_column);
    1667      151464 :     if (line == 0) column -= script->column_offset();
    1668             :   }
    1669             : 
    1670      129822 :   int line_position = ScriptLinePositionWithOffset(script, line, offset);
    1671      129822 :   if (line_position < 0 || column < 0) return isolate->factory()->null_value();
    1672             : 
    1673             :   return GetJSPositionInfo(script, line_position + column, Script::NO_OFFSET,
    1674      129822 :                            isolate);
    1675             : }
    1676             : 
    1677             : // Slow traversal over all scripts on the heap.
    1678      129251 : bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) {
    1679      129251 :   Script::Iterator iterator(isolate);
    1680             :   Script* script = nullptr;
    1681      129251 :   while ((script = iterator.Next()) != nullptr) {
    1682     2689005 :     if (script->id() == needle) {
    1683      129251 :       *result = handle(script);
    1684      129251 :       return true;
    1685             :     }
    1686             :   }
    1687             : 
    1688             :   return false;
    1689             : }
    1690             : 
    1691             : }  // namespace
    1692             : 
    1693             : // Get information on a specific source line and column possibly offset by a
    1694             : // fixed source position. This function is used to find a source position from
    1695             : // a line and column position. The fixed source position offset is typically
    1696             : // used to find a source position in a function based on a line and column in
    1697             : // the source for the function alone. The offset passed will then be the
    1698             : // start position of the source for the function within the full script source.
    1699             : // Note that incoming line and column parameters may be undefined, and are
    1700             : // assumed to be passed *with* offsets.
    1701             : // TODO(5530): Remove once uses in debug.js are gone.
    1702        1178 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
    1703         589 :   HandleScope scope(isolate);
    1704             :   DCHECK_EQ(4, args.length());
    1705        1178 :   CONVERT_ARG_HANDLE_CHECKED(JSValue, script, 0);
    1706         589 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
    1707         589 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
    1708        1178 :   CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
    1709             : 
    1710        1178 :   CHECK(script->value()->IsScript());
    1711         589 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1712             : 
    1713             :   return *ScriptLocationFromLine(isolate, script_handle, opt_line, opt_column,
    1714        1178 :                                  offset);
    1715             : }
    1716             : 
    1717             : // TODO(5530): Rename once conflicting function has been deleted.
    1718      258466 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
    1719      129233 :   HandleScope scope(isolate);
    1720             :   DCHECK_EQ(4, args.length());
    1721      258466 :   CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
    1722      129233 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
    1723      129233 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
    1724      258466 :   CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
    1725             : 
    1726             :   Handle<Script> script;
    1727      129233 :   CHECK(GetScriptById(isolate, scriptid, &script));
    1728             : 
    1729      258466 :   return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset);
    1730             : }
    1731             : 
    1732             : // TODO(5530): Remove once uses in debug.js are gone.
    1733        5846 : RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
    1734        2923 :   HandleScope scope(isolate);
    1735             :   DCHECK_EQ(3, args.length());
    1736        5846 :   CONVERT_ARG_CHECKED(JSValue, script, 0);
    1737        5846 :   CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
    1738        5846 :   CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
    1739             : 
    1740        5846 :   CHECK(script->value()->IsScript());
    1741        2923 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1742             : 
    1743             :   const Script::OffsetFlag offset_flag =
    1744        2923 :       with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
    1745        5846 :   return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
    1746             : }
    1747             : 
    1748             : // TODO(5530): Rename once conflicting function has been deleted.
    1749          36 : RUNTIME_FUNCTION(Runtime_ScriptPositionInfo2) {
    1750          18 :   HandleScope scope(isolate);
    1751             :   DCHECK_EQ(3, args.length());
    1752          36 :   CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
    1753          36 :   CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
    1754          36 :   CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
    1755             : 
    1756             :   Handle<Script> script;
    1757          18 :   CHECK(GetScriptById(isolate, scriptid, &script));
    1758             : 
    1759             :   const Script::OffsetFlag offset_flag =
    1760          18 :       with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
    1761          36 :   return *GetJSPositionInfo(script, position, offset_flag, isolate);
    1762             : }
    1763             : 
    1764             : // Returns the given line as a string, or null if line is out of bounds.
    1765             : // The parameter line is expected to include the script's line offset.
    1766             : // TODO(5530): Remove once uses in debug.js are gone.
    1767         100 : RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
    1768          50 :   HandleScope scope(isolate);
    1769             :   DCHECK_EQ(2, args.length());
    1770         100 :   CONVERT_ARG_CHECKED(JSValue, script, 0);
    1771         100 :   CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
    1772             : 
    1773         100 :   CHECK(script->value()->IsScript());
    1774          50 :   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
    1775             : 
    1776          50 :   if (script_handle->type() == Script::TYPE_WASM) {
    1777             :     // Return null for now; this function will disappear soon anyway.
    1778           0 :     return isolate->heap()->null_value();
    1779             :   }
    1780             : 
    1781          50 :   Script::InitLineEnds(script_handle);
    1782             : 
    1783          50 :   FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
    1784          50 :   const int line_count = line_ends_array->length();
    1785             : 
    1786          50 :   line -= script_handle->line_offset();
    1787          50 :   if (line < 0 || line_count <= line) {
    1788           0 :     return isolate->heap()->null_value();
    1789             :   }
    1790             : 
    1791             :   const int start =
    1792          50 :       (line == 0) ? 0 : Smi::ToInt(line_ends_array->get(line - 1)) + 1;
    1793          50 :   const int end = Smi::ToInt(line_ends_array->get(line));
    1794             : 
    1795             :   Handle<String> source =
    1796         100 :       handle(String::cast(script_handle->source()), isolate);
    1797          50 :   Handle<String> str = isolate->factory()->NewSubString(source, start, end);
    1798             : 
    1799          50 :   return *str;
    1800             : }
    1801             : 
    1802             : // On function call, depending on circumstances, prepare for stepping in,
    1803             : // or perform a side effect check.
    1804     2313745 : RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
    1805      462749 :   HandleScope scope(isolate);
    1806             :   DCHECK_EQ(1, args.length());
    1807      925498 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
    1808      462749 :   if (isolate->debug()->last_step_action() >= StepIn) {
    1809      456792 :     isolate->debug()->PrepareStepIn(fun);
    1810             :   }
    1811      468706 :   if (isolate->needs_side_effect_check() &&
    1812        5957 :       !isolate->debug()->PerformSideEffectCheck(fun)) {
    1813         715 :     return isolate->heap()->exception();
    1814             :   }
    1815      462034 :   return isolate->heap()->undefined_value();
    1816             : }
    1817             : 
    1818             : // Set one shot breakpoints for the suspended generator object.
    1819         514 : RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
    1820         257 :   HandleScope scope(isolate);
    1821             :   DCHECK_EQ(0, args.length());
    1822         257 :   isolate->debug()->PrepareStepInSuspendedGenerator();
    1823         257 :   return isolate->heap()->undefined_value();
    1824             : }
    1825             : 
    1826        1200 : RUNTIME_FUNCTION(Runtime_DebugRecordGenerator) {
    1827         300 :   HandleScope scope(isolate);
    1828             :   DCHECK_EQ(1, args.length());
    1829         600 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
    1830         300 :   CHECK(isolate->debug()->last_step_action() >= StepNext);
    1831         300 :   isolate->debug()->RecordGenerator(generator);
    1832         300 :   return isolate->heap()->undefined_value();
    1833             : }
    1834             : 
    1835       29968 : RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
    1836             :   DCHECK_EQ(1, args.length());
    1837       14984 :   HandleScope scope(isolate);
    1838       29968 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
    1839       14984 :   isolate->PushPromise(promise);
    1840       14984 :   return isolate->heap()->undefined_value();
    1841             : }
    1842             : 
    1843             : 
    1844       39054 : RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
    1845             :   DCHECK_EQ(0, args.length());
    1846             :   SealHandleScope shs(isolate);
    1847       19527 :   isolate->PopPromise();
    1848       19527 :   return isolate->heap()->undefined_value();
    1849             : }
    1850             : 
    1851       18324 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionPromiseCreated) {
    1852             :   DCHECK_EQ(1, args.length());
    1853        4581 :   HandleScope scope(isolate);
    1854        9162 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
    1855        4581 :   isolate->PushPromise(promise);
    1856        4581 :   int id = isolate->debug()->NextAsyncTaskId(promise);
    1857             :   Handle<Symbol> async_stack_id_symbol =
    1858        4581 :       isolate->factory()->promise_async_stack_id_symbol();
    1859             :   JSObject::SetProperty(promise, async_stack_id_symbol,
    1860             :                         handle(Smi::FromInt(id), isolate),
    1861        9162 :                         LanguageMode::kStrict)
    1862        4581 :       .Assert();
    1863        4581 :   isolate->debug()->OnAsyncTaskEvent(debug::kDebugEnqueueAsyncFunction, id, 0);
    1864        4581 :   return isolate->heap()->undefined_value();
    1865             : }
    1866             : 
    1867        1527 : RUNTIME_FUNCTION(Runtime_DebugPromiseReject) {
    1868         509 :   HandleScope scope(isolate);
    1869             :   DCHECK_EQ(2, args.length());
    1870        1018 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, rejected_promise, 0);
    1871         509 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
    1872             : 
    1873         509 :   isolate->debug()->OnPromiseReject(rejected_promise, value);
    1874         509 :   return isolate->heap()->undefined_value();
    1875             : }
    1876             : 
    1877      212875 : RUNTIME_FUNCTION(Runtime_DebugAsyncEventEnqueueRecurring) {
    1878       42575 :   HandleScope scope(isolate);
    1879             :   DCHECK_EQ(2, args.length());
    1880       85150 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
    1881       85150 :   CONVERT_SMI_ARG_CHECKED(status, 1);
    1882       42575 :   if (isolate->debug()->is_active()) {
    1883             :     isolate->debug()->OnAsyncTaskEvent(
    1884             :         status == v8::Promise::kFulfilled ? debug::kDebugEnqueuePromiseResolve
    1885             :                                           : debug::kDebugEnqueuePromiseReject,
    1886       85150 :         isolate->debug()->NextAsyncTaskId(promise), 0);
    1887             :   }
    1888       42575 :   return isolate->heap()->undefined_value();
    1889             : }
    1890             : 
    1891           0 : RUNTIME_FUNCTION(Runtime_DebugIsActive) {
    1892             :   SealHandleScope shs(isolate);
    1893           0 :   return Smi::FromInt(isolate->debug()->is_active());
    1894             : }
    1895             : 
    1896           0 : RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
    1897           0 :   UNIMPLEMENTED();
    1898             :   return nullptr;
    1899             : }
    1900             : 
    1901             : namespace {
    1902        6878 : Handle<JSObject> MakeRangeObject(Isolate* isolate, const CoverageBlock& range) {
    1903             :   Factory* factory = isolate->factory();
    1904             : 
    1905        6878 :   Handle<String> start_string = factory->InternalizeUtf8String("start");
    1906        6878 :   Handle<String> end_string = factory->InternalizeUtf8String("end");
    1907        6878 :   Handle<String> count_string = factory->InternalizeUtf8String("count");
    1908             : 
    1909        6878 :   Handle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
    1910             :   JSObject::AddProperty(range_obj, start_string,
    1911       13756 :                         factory->NewNumberFromInt(range.start), NONE);
    1912             :   JSObject::AddProperty(range_obj, end_string,
    1913       13756 :                         factory->NewNumberFromInt(range.end), NONE);
    1914             :   JSObject::AddProperty(range_obj, count_string,
    1915       13756 :                         factory->NewNumberFromUint(range.count), NONE);
    1916             : 
    1917        6878 :   return range_obj;
    1918             : }
    1919             : }  // namespace
    1920             : 
    1921         516 : RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
    1922         258 :   HandleScope scope(isolate);
    1923             :   DCHECK_EQ(0, args.length());
    1924             :   // Collect coverage data.
    1925         516 :   std::unique_ptr<Coverage> coverage;
    1926         258 :   if (isolate->is_best_effort_code_coverage()) {
    1927          36 :     coverage = Coverage::CollectBestEffort(isolate);
    1928             :   } else {
    1929         222 :     coverage = Coverage::CollectPrecise(isolate);
    1930             :   }
    1931         258 :   Factory* factory = isolate->factory();
    1932             :   // Turn the returned data structure into JavaScript.
    1933             :   // Create an array of scripts.
    1934         258 :   int num_scripts = static_cast<int>(coverage->size());
    1935             :   // Prepare property keys.
    1936         258 :   Handle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
    1937         258 :   Handle<String> script_string = factory->NewStringFromStaticChars("script");
    1938         798 :   for (int i = 0; i < num_scripts; i++) {
    1939         798 :     const auto& script_data = coverage->at(i);
    1940         798 :     HandleScope inner_scope(isolate);
    1941             : 
    1942        1596 :     std::vector<CoverageBlock> ranges;
    1943         798 :     int num_functions = static_cast<int>(script_data.functions.size());
    1944        3980 :     for (int j = 0; j < num_functions; j++) {
    1945        3980 :       const auto& function_data = script_data.functions[j];
    1946             :       ranges.emplace_back(function_data.start, function_data.end,
    1947        3980 :                           function_data.count);
    1948        2898 :       for (size_t k = 0; k < function_data.blocks.size(); k++) {
    1949        2898 :         const auto& block_data = function_data.blocks[k];
    1950        2898 :         ranges.emplace_back(block_data.start, block_data.end, block_data.count);
    1951             :       }
    1952             :     }
    1953             : 
    1954         798 :     int num_ranges = static_cast<int>(ranges.size());
    1955         798 :     Handle<FixedArray> ranges_array = factory->NewFixedArray(num_ranges);
    1956        6878 :     for (int j = 0; j < num_ranges; j++) {
    1957        6878 :       Handle<JSObject> range_object = MakeRangeObject(isolate, ranges[j]);
    1958        6878 :       ranges_array->set(j, *range_object);
    1959             :     }
    1960             : 
    1961             :     Handle<JSArray> script_obj =
    1962         798 :         factory->NewJSArrayWithElements(ranges_array, PACKED_ELEMENTS);
    1963         798 :     Handle<JSObject> wrapper = Script::GetWrapper(script_data.script);
    1964         798 :     JSObject::AddProperty(script_obj, script_string, wrapper, NONE);
    1965         798 :     scripts_array->set(i, *script_obj);
    1966         798 :   }
    1967         774 :   return *factory->NewJSArrayWithElements(scripts_array, PACKED_ELEMENTS);
    1968             : }
    1969             : 
    1970          24 : RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
    1971             :   SealHandleScope shs(isolate);
    1972          24 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
    1973             :   Coverage::SelectMode(isolate, enable ? debug::Coverage::kPreciseCount
    1974          12 :                                        : debug::Coverage::kBestEffort);
    1975          12 :   return isolate->heap()->undefined_value();
    1976             : }
    1977             : 
    1978          72 : RUNTIME_FUNCTION(Runtime_DebugToggleBlockCoverage) {
    1979             :   SealHandleScope shs(isolate);
    1980          72 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
    1981             :   Coverage::SelectMode(isolate, enable ? debug::Coverage::kBlockCount
    1982          36 :                                        : debug::Coverage::kBestEffort);
    1983          36 :   return isolate->heap()->undefined_value();
    1984             : }
    1985             : 
    1986      449290 : RUNTIME_FUNCTION(Runtime_IncBlockCounter) {
    1987             :   SealHandleScope scope(isolate);
    1988             :   DCHECK_EQ(2, args.length());
    1989      449290 :   CONVERT_ARG_CHECKED(JSFunction, function, 0);
    1990      449290 :   CONVERT_SMI_ARG_CHECKED(coverage_array_slot_index, 1);
    1991             : 
    1992             :   // It's quite possible that a function contains IncBlockCounter bytecodes, but
    1993             :   // no coverage info exists. This happens e.g. by selecting the best-effort
    1994             :   // coverage collection mode, which triggers deletion of all coverage infos in
    1995             :   // order to avoid memory leaks.
    1996             : 
    1997      224645 :   SharedFunctionInfo* shared = function->shared();
    1998      224645 :   if (shared->HasCoverageInfo()) {
    1999      224645 :     CoverageInfo* coverage_info = shared->GetCoverageInfo();
    2000      224645 :     coverage_info->IncrementBlockCount(coverage_array_slot_index);
    2001             :   }
    2002             : 
    2003      224645 :   return isolate->heap()->undefined_value();
    2004             : }
    2005             : 
    2006             : }  // namespace internal
    2007             : }  // namespace v8

Generated by: LCOV version 1.10