LCOV - code coverage report
Current view: top level - src/runtime - runtime-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 314 327 96.0 %
Date: 2019-04-17 Functions: 38 68 55.9 %

          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 <vector>
       6             : 
       7             : #include "src/arguments-inl.h"
       8             : #include "src/compiler.h"
       9             : #include "src/counters.h"
      10             : #include "src/debug/debug-coverage.h"
      11             : #include "src/debug/debug-evaluate.h"
      12             : #include "src/debug/debug-frames.h"
      13             : #include "src/debug/debug-scopes.h"
      14             : #include "src/debug/debug.h"
      15             : #include "src/debug/liveedit.h"
      16             : #include "src/frames-inl.h"
      17             : #include "src/globals.h"
      18             : #include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
      19             : #include "src/interpreter/bytecode-array-accessor.h"
      20             : #include "src/interpreter/bytecodes.h"
      21             : #include "src/interpreter/interpreter.h"
      22             : #include "src/isolate-inl.h"
      23             : #include "src/objects/debug-objects-inl.h"
      24             : #include "src/objects/heap-object-inl.h"
      25             : #include "src/objects/js-collection-inl.h"
      26             : #include "src/objects/js-generator-inl.h"
      27             : #include "src/objects/js-promise-inl.h"
      28             : #include "src/runtime/runtime-utils.h"
      29             : #include "src/runtime/runtime.h"
      30             : #include "src/snapshot/snapshot.h"
      31             : #include "src/wasm/wasm-objects-inl.h"
      32             : 
      33             : namespace v8 {
      34             : namespace internal {
      35             : 
      36      133388 : RUNTIME_FUNCTION_RETURN_PAIR(Runtime_DebugBreakOnBytecode) {
      37             :   using interpreter::Bytecode;
      38             :   using interpreter::Bytecodes;
      39             :   using interpreter::OperandScale;
      40             : 
      41             :   SealHandleScope shs(isolate);
      42             :   DCHECK_EQ(1, args.length());
      43             :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
      44             :   HandleScope scope(isolate);
      45             : 
      46             :   // Return value can be changed by debugger. Last set value will be used as
      47             :   // return value.
      48      133388 :   ReturnValueScope result_scope(isolate->debug());
      49             :   isolate->debug()->set_return_value(*value);
      50             : 
      51             :   // Get the top-most JavaScript frame.
      52       66694 :   JavaScriptFrameIterator it(isolate);
      53       66694 :   if (isolate->debug_execution_mode() == DebugInfo::kBreakpoints) {
      54       64361 :     isolate->debug()->Break(it.frame(),
      55      128722 :                             handle(it.frame()->function(), isolate));
      56             :   }
      57             : 
      58             :   // If we are dropping frames, there is no need to get a return value or
      59             :   // bytecode, since we will be restarting execution at a different frame.
      60       66694 :   if (isolate->debug()->will_restart()) {
      61             :     return MakePair(ReadOnlyRoots(isolate).undefined_value(),
      62             :                     Smi::FromInt(static_cast<uint8_t>(Bytecode::kIllegal)));
      63             :   }
      64             : 
      65             :   // Return the handler from the original bytecode array.
      66             :   DCHECK(it.frame()->is_interpreted());
      67             :   InterpretedFrame* interpreted_frame =
      68             :       reinterpret_cast<InterpretedFrame*>(it.frame());
      69       66671 :   SharedFunctionInfo shared = interpreted_frame->function()->shared();
      70       66671 :   BytecodeArray bytecode_array = shared->GetBytecodeArray();
      71       66671 :   int bytecode_offset = interpreted_frame->GetBytecodeOffset();
      72             :   Bytecode bytecode = Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
      73             : 
      74             :   bool side_effect_check_failed = false;
      75       66671 :   if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
      76             :     side_effect_check_failed =
      77        2333 :         !isolate->debug()->PerformSideEffectCheckAtBytecode(interpreted_frame);
      78             :   }
      79             : 
      80       66671 :   if (Bytecodes::Returns(bytecode)) {
      81             :     // If we are returning (or suspending), reset the bytecode array on the
      82             :     // interpreted stack frame to the non-debug variant so that the interpreter
      83             :     // entry trampoline sees the return/suspend bytecode rather than the
      84             :     // DebugBreak.
      85        7247 :     interpreted_frame->PatchBytecodeArray(bytecode_array);
      86             :   }
      87             : 
      88             :   // We do not have to deal with operand scale here. If the bytecode at the
      89             :   // break is prefixed by operand scaling, we would have patched over the
      90             :   // scaling prefix. We now simply dispatch to the handler for the prefix.
      91             :   // We need to deserialize now to ensure we don't hit the debug break again
      92             :   // after deserializing.
      93             :   OperandScale operand_scale = OperandScale::kSingle;
      94       66671 :   isolate->interpreter()->GetBytecodeHandler(bytecode, operand_scale);
      95             : 
      96       66671 :   if (side_effect_check_failed) {
      97             :     return MakePair(ReadOnlyRoots(isolate).exception(),
      98             :                     Smi::FromInt(static_cast<uint8_t>(bytecode)));
      99             :   }
     100       66503 :   Object interrupt_object = isolate->stack_guard()->HandleInterrupts();
     101       66503 :   if (interrupt_object->IsException(isolate)) {
     102             :     return MakePair(interrupt_object,
     103             :                     Smi::FromInt(static_cast<uint8_t>(bytecode)));
     104             :   }
     105             :   return MakePair(isolate->debug()->return_value(),
     106             :                   Smi::FromInt(static_cast<uint8_t>(bytecode)));
     107             : }
     108             : 
     109         960 : RUNTIME_FUNCTION(Runtime_DebugBreakAtEntry) {
     110             :   HandleScope scope(isolate);
     111             :   DCHECK_EQ(1, args.length());
     112         480 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     113         480 :   USE(function);
     114             : 
     115             :   DCHECK(function->shared()->HasDebugInfo());
     116             :   DCHECK(function->shared()->GetDebugInfo()->BreakAtEntry());
     117             : 
     118             :   // Get the top-most JavaScript frame.
     119         480 :   JavaScriptFrameIterator it(isolate);
     120             :   DCHECK_EQ(*function, it.frame()->function());
     121         480 :   isolate->debug()->Break(it.frame(), function);
     122             : 
     123             :   return ReadOnlyRoots(isolate).undefined_value();
     124             : }
     125             : 
     126       17016 : RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
     127             :   SealHandleScope shs(isolate);
     128             :   DCHECK_EQ(0, args.length());
     129        8508 :   if (isolate->debug()->break_points_active()) {
     130        8450 :     isolate->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
     131             :   }
     132        8508 :   return isolate->stack_guard()->HandleInterrupts();
     133             : }
     134             : 
     135         252 : RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
     136             :   SealHandleScope shs(isolate);
     137             :   DCHECK_EQ(0, args.length());
     138             :   isolate->RequestInterrupt(
     139         121 :       [](v8::Isolate* isolate, void*) { v8::debug::BreakRightNow(isolate); },
     140         126 :       nullptr);
     141             :   return ReadOnlyRoots(isolate).undefined_value();
     142             : }
     143             : 
     144             : template <class IteratorType>
     145         159 : static MaybeHandle<JSArray> GetIteratorInternalProperties(
     146             :     Isolate* isolate, Handle<IteratorType> object) {
     147             :   Factory* factory = isolate->factory();
     148             :   Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
     149             :   const char* kind = nullptr;
     150         159 :   switch (iterator->map()->instance_type()) {
     151             :     case JS_MAP_KEY_ITERATOR_TYPE:
     152             :       kind = "keys";
     153             :       break;
     154             :     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
     155             :     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
     156             :       kind = "entries";
     157          73 :       break;
     158             :     case JS_MAP_VALUE_ITERATOR_TYPE:
     159             :     case JS_SET_VALUE_ITERATOR_TYPE:
     160             :       kind = "values";
     161          72 :       break;
     162             :     default:
     163           0 :       UNREACHABLE();
     164             :   }
     165             : 
     166         159 :   Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     167             :   Handle<String> has_more =
     168         159 :       factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
     169         318 :   result->set(0, *has_more);
     170         477 :   result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
     171             : 
     172             :   Handle<String> index =
     173         159 :       factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
     174         318 :   result->set(2, *index);
     175         159 :   result->set(3, iterator->index());
     176             : 
     177             :   Handle<String> iterator_kind =
     178         159 :       factory->NewStringFromAsciiChecked("[[IteratorKind]]");
     179         318 :   result->set(4, *iterator_kind);
     180         159 :   Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
     181         318 :   result->set(5, *kind_str);
     182         159 :   return factory->NewJSArrayWithElements(result);
     183             : }
     184             : 
     185             : 
     186       79258 : MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
     187             :                                                     Handle<Object> object) {
     188             :   Factory* factory = isolate->factory();
     189       79258 :   if (object->IsJSBoundFunction()) {
     190             :     Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
     191             : 
     192          10 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     193             :     Handle<String> target =
     194          10 :         factory->NewStringFromAsciiChecked("[[TargetFunction]]");
     195          20 :     result->set(0, *target);
     196          20 :     result->set(1, function->bound_target_function());
     197             : 
     198             :     Handle<String> bound_this =
     199          10 :         factory->NewStringFromAsciiChecked("[[BoundThis]]");
     200          20 :     result->set(2, *bound_this);
     201          10 :     result->set(3, function->bound_this());
     202             : 
     203             :     Handle<String> bound_args =
     204          10 :         factory->NewStringFromAsciiChecked("[[BoundArgs]]");
     205          20 :     result->set(4, *bound_args);
     206             :     Handle<FixedArray> bound_arguments =
     207          10 :         factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
     208             :     Handle<JSArray> arguments_array =
     209             :         factory->NewJSArrayWithElements(bound_arguments);
     210          20 :     result->set(5, *arguments_array);
     211          10 :     return factory->NewJSArrayWithElements(result);
     212       79248 :   } else if (object->IsJSMapIterator()) {
     213          87 :     Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
     214          87 :     return GetIteratorInternalProperties(isolate, iterator);
     215       79161 :   } else if (object->IsJSSetIterator()) {
     216          72 :     Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
     217          72 :     return GetIteratorInternalProperties(isolate, iterator);
     218       79089 :   } else if (object->IsJSGeneratorObject()) {
     219             :     Handle<JSGeneratorObject> generator =
     220             :         Handle<JSGeneratorObject>::cast(object);
     221             : 
     222             :     const char* status = "suspended";
     223          50 :     if (generator->is_closed()) {
     224             :       status = "closed";
     225          40 :     } else if (generator->is_executing()) {
     226             :       status = "running";
     227             :     } else {
     228             :       DCHECK(generator->is_suspended());
     229             :     }
     230             : 
     231          50 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     232             :     Handle<String> generator_status =
     233          50 :         factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
     234         100 :     result->set(0, *generator_status);
     235          50 :     Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
     236         100 :     result->set(1, *status_str);
     237             : 
     238             :     Handle<String> function =
     239          50 :         factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
     240         100 :     result->set(2, *function);
     241         100 :     result->set(3, generator->function());
     242             : 
     243             :     Handle<String> receiver =
     244          50 :         factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
     245         100 :     result->set(4, *receiver);
     246          50 :     result->set(5, generator->receiver());
     247          50 :     return factory->NewJSArrayWithElements(result);
     248       79039 :   } else if (object->IsJSPromise()) {
     249             :     Handle<JSPromise> promise = Handle<JSPromise>::cast(object);
     250          40 :     const char* status = JSPromise::Status(promise->status());
     251          40 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
     252             :     Handle<String> promise_status =
     253          40 :         factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
     254          80 :     result->set(0, *promise_status);
     255          40 :     Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
     256          80 :     result->set(1, *status_str);
     257             : 
     258          80 :     Handle<Object> value_obj(promise->status() == Promise::kPending
     259             :                                  ? ReadOnlyRoots(isolate).undefined_value()
     260             :                                  : promise->result(),
     261          40 :                              isolate);
     262             :     Handle<String> promise_value =
     263          40 :         factory->NewStringFromAsciiChecked("[[PromiseValue]]");
     264          80 :     result->set(2, *promise_value);
     265          40 :     result->set(3, *value_obj);
     266          40 :     return factory->NewJSArrayWithElements(result);
     267       78999 :   } else if (object->IsJSProxy()) {
     268             :     Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
     269          20 :     Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
     270             : 
     271             :     Handle<String> handler_str =
     272          20 :         factory->NewStringFromAsciiChecked("[[Handler]]");
     273          40 :     result->set(0, *handler_str);
     274          20 :     result->set(1, js_proxy->handler());
     275             : 
     276             :     Handle<String> target_str =
     277          20 :         factory->NewStringFromAsciiChecked("[[Target]]");
     278          40 :     result->set(2, *target_str);
     279          20 :     result->set(3, js_proxy->target());
     280             : 
     281             :     Handle<String> is_revoked_str =
     282          20 :         factory->NewStringFromAsciiChecked("[[IsRevoked]]");
     283          40 :     result->set(4, *is_revoked_str);
     284          40 :     result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
     285          20 :     return factory->NewJSArrayWithElements(result);
     286       78979 :   } else if (object->IsJSValue()) {
     287             :     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
     288             : 
     289         123 :     Handle<FixedArray> result = factory->NewFixedArray(2);
     290             :     Handle<String> primitive_value =
     291         123 :         factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
     292         246 :     result->set(0, *primitive_value);
     293         123 :     result->set(1, js_value->value());
     294         123 :     return factory->NewJSArrayWithElements(result);
     295             :   }
     296       78856 :   return factory->NewJSArray(0);
     297             : }
     298             : 
     299         576 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
     300             :   HandleScope scope(isolate);
     301             :   DCHECK_EQ(1, args.length());
     302             : 
     303         288 :   if (!args[0]->IsJSGeneratorObject()) return Smi::kZero;
     304             : 
     305             :   // Check arguments.
     306         288 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     307             : 
     308             :   // Only inspect suspended generator scopes.
     309         288 :   if (!gen->is_suspended()) {
     310             :     return Smi::kZero;
     311             :   }
     312             : 
     313             :   // Count the visible scopes.
     314             :   int n = 0;
     315        2736 :   for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
     316        1080 :     n++;
     317             :   }
     318             : 
     319             :   return Smi::FromInt(n);
     320             : }
     321             : 
     322        1890 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
     323             :   HandleScope scope(isolate);
     324             :   DCHECK_EQ(2, args.length());
     325             : 
     326         945 :   if (!args[0]->IsJSGeneratorObject()) {
     327             :     return ReadOnlyRoots(isolate).undefined_value();
     328             :   }
     329             : 
     330             :   // Check arguments.
     331         945 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     332        1890 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     333             : 
     334             :   // Only inspect suspended generator scopes.
     335         945 :   if (!gen->is_suspended()) {
     336             :     return ReadOnlyRoots(isolate).undefined_value();
     337             :   }
     338             : 
     339             :   // Find the requested scope.
     340             :   int n = 0;
     341        1890 :   ScopeIterator it(isolate, gen);
     342        2799 :   for (; !it.Done() && n < index; it.Next()) {
     343         927 :     n++;
     344             :   }
     345         945 :   if (it.Done()) {
     346             :     return ReadOnlyRoots(isolate).undefined_value();
     347             :   }
     348             : 
     349        1890 :   return *it.MaterializeScopeDetails();
     350             : }
     351             : 
     352         117 : static bool SetScopeVariableValue(ScopeIterator* it, int index,
     353             :                                   Handle<String> variable_name,
     354             :                                   Handle<Object> new_value) {
     355         261 :   for (int n = 0; !it->Done() && n < index; it->Next()) {
     356          72 :     n++;
     357             :   }
     358         117 :   if (it->Done()) {
     359             :     return false;
     360             :   }
     361         117 :   return it->SetVariableValue(variable_name, new_value);
     362             : }
     363             : 
     364             : // Change variable value in closure or local scope
     365             : // args[0]: number or JsFunction: break id or function
     366             : // args[1]: number: scope index
     367             : // args[2]: string: variable name
     368             : // args[3]: object: new value
     369             : //
     370             : // Return true if success and false otherwise
     371         234 : RUNTIME_FUNCTION(Runtime_SetGeneratorScopeVariableValue) {
     372             :   HandleScope scope(isolate);
     373             :   DCHECK_EQ(4, args.length());
     374         117 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     375         234 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     376         117 :   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 2);
     377             :   CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 3);
     378         234 :   ScopeIterator it(isolate, gen);
     379         117 :   bool res = SetScopeVariableValue(&it, index, variable_name, new_value);
     380             :   return isolate->heap()->ToBoolean(res);
     381             : }
     382             : 
     383             : 
     384        1134 : RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
     385             :   HandleScope scope(isolate);
     386             :   DCHECK_EQ(1, args.length());
     387         567 :   CHECK(isolate->debug()->is_active());
     388         567 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
     389             : 
     390        1134 :   Handle<SharedFunctionInfo> shared(fun->shared(), isolate);
     391             :   // Find the number of break points
     392             :   Handle<Object> break_locations =
     393         567 :       Debug::GetSourceBreakLocations(isolate, shared);
     394         567 :   if (break_locations->IsUndefined(isolate)) {
     395             :     return ReadOnlyRoots(isolate).undefined_value();
     396             :   }
     397             :   // Return array as JS array
     398             :   return *isolate->factory()->NewJSArrayWithElements(
     399         414 :       Handle<FixedArray>::cast(break_locations));
     400             : }
     401             : 
     402             : 
     403             : // Returns the state of break on exceptions
     404             : // args[0]: boolean indicating uncaught exceptions
     405        6642 : RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
     406             :   HandleScope scope(isolate);
     407             :   DCHECK_EQ(1, args.length());
     408        6642 :   CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
     409             : 
     410             :   ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
     411        3321 :   bool result = isolate->debug()->IsBreakOnException(type);
     412             :   return Smi::FromInt(result);
     413             : }
     414             : 
     415             : // Clear all stepping set by PrepareStep.
     416          36 : RUNTIME_FUNCTION(Runtime_ClearStepping) {
     417             :   HandleScope scope(isolate);
     418             :   DCHECK_EQ(0, args.length());
     419          18 :   CHECK(isolate->debug()->is_active());
     420          18 :   isolate->debug()->ClearStepping();
     421             :   return ReadOnlyRoots(isolate).undefined_value();
     422             : }
     423             : 
     424         226 : RUNTIME_FUNCTION(Runtime_DebugGetLoadedScriptIds) {
     425             :   HandleScope scope(isolate);
     426             :   DCHECK_EQ(0, args.length());
     427             : 
     428             :   Handle<FixedArray> instances;
     429             :   {
     430         226 :     DebugScope debug_scope(isolate->debug());
     431             :     // Fill the script objects.
     432         113 :     instances = isolate->debug()->GetLoadedScripts();
     433             :   }
     434             : 
     435             :   // Convert the script objects to proper JS objects.
     436        1329 :   for (int i = 0; i < instances->length(); i++) {
     437             :     Handle<Script> script(Script::cast(instances->get(i)), isolate);
     438             :     instances->set(i, Smi::FromInt(script->id()));
     439             :   }
     440             : 
     441             :   // Return result as a JS array.
     442             :   return *isolate->factory()->NewJSArrayWithElements(instances);
     443             : }
     444             : 
     445             : 
     446         138 : RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
     447             :   SealHandleScope shs(isolate);
     448             :   DCHECK_EQ(1, args.length());
     449             : 
     450             :   CONVERT_ARG_CHECKED(Object, f, 0);
     451          69 :   if (f->IsJSFunction()) {
     452          60 :     return JSFunction::cast(f)->shared()->inferred_name();
     453             :   }
     454             :   return ReadOnlyRoots(isolate).empty_string();
     455             : }
     456             : 
     457             : 
     458             : // Performs a GC.
     459             : // Presently, it only does a full GC.
     460         536 : RUNTIME_FUNCTION(Runtime_CollectGarbage) {
     461             :   SealHandleScope shs(isolate);
     462             :   DCHECK_EQ(1, args.length());
     463             :   isolate->heap()->PreciseCollectAllGarbage(Heap::kNoGCFlags,
     464         268 :                                             GarbageCollectionReason::kRuntime);
     465             :   return ReadOnlyRoots(isolate).undefined_value();
     466             : }
     467             : 
     468             : 
     469             : // Gets the current heap usage.
     470           0 : RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
     471             :   SealHandleScope shs(isolate);
     472             :   DCHECK_EQ(0, args.length());
     473           0 :   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
     474             :   if (!Smi::IsValid(usage)) {
     475             :     return *isolate->factory()->NewNumberFromInt(usage);
     476             :   }
     477             :   return Smi::FromInt(usage);
     478             : }
     479             : 
     480             : namespace {
     481             : 
     482      131542 : int ScriptLinePosition(Handle<Script> script, int line) {
     483      131542 :   if (line < 0) return -1;
     484             : 
     485      131542 :   if (script->type() == Script::TYPE_WASM) {
     486          32 :     return WasmModuleObject::cast(script->wasm_module_object())
     487          32 :         ->GetFunctionOffset(line);
     488             :   }
     489             : 
     490      131526 :   Script::InitLineEnds(script);
     491             : 
     492             :   FixedArray line_ends_array = FixedArray::cast(script->line_ends());
     493             :   const int line_count = line_ends_array->length();
     494             :   DCHECK_LT(0, line_count);
     495             : 
     496      131526 :   if (line == 0) return 0;
     497             :   // If line == line_count, we return the first position beyond the last line.
     498      109515 :   if (line > line_count) return -1;
     499      219030 :   return Smi::ToInt(line_ends_array->get(line - 1)) + 1;
     500             : }
     501             : 
     502      131542 : int ScriptLinePositionWithOffset(Handle<Script> script, int line, int offset) {
     503      131542 :   if (line < 0 || offset < 0) return -1;
     504             : 
     505      131542 :   if (line == 0 || offset == 0)
     506      130881 :     return ScriptLinePosition(script, line) + offset;
     507             : 
     508             :   Script::PositionInfo info;
     509         661 :   if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET)) {
     510             :     return -1;
     511             :   }
     512             : 
     513         661 :   const int total_line = info.line + line;
     514         661 :   return ScriptLinePosition(script, total_line);
     515             : }
     516             : 
     517      131542 : Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
     518             :                                  Script::OffsetFlag offset_flag,
     519             :                                  Isolate* isolate) {
     520             :   Script::PositionInfo info;
     521      131542 :   if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
     522           0 :     return isolate->factory()->null_value();
     523             :   }
     524             : 
     525      131542 :   Handle<String> source = handle(String::cast(script->source()), isolate);
     526             :   Handle<String> sourceText = script->type() == Script::TYPE_WASM
     527             :                                   ? isolate->factory()->empty_string()
     528             :                                   : isolate->factory()->NewSubString(
     529      263068 :                                         source, info.line_start, info.line_end);
     530             : 
     531             :   Handle<JSObject> jsinfo =
     532      131542 :       isolate->factory()->NewJSObject(isolate->object_function());
     533             : 
     534      131542 :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->script_string(),
     535      131542 :                         script, NONE);
     536      131542 :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->position_string(),
     537      131542 :                         handle(Smi::FromInt(position), isolate), NONE);
     538      263084 :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->line_string(),
     539      131542 :                         handle(Smi::FromInt(info.line), isolate), NONE);
     540      263084 :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->column_string(),
     541      131542 :                         handle(Smi::FromInt(info.column), isolate), NONE);
     542      131542 :   JSObject::AddProperty(isolate, jsinfo,
     543             :                         isolate->factory()->sourceText_string(), sourceText,
     544      131542 :                         NONE);
     545             : 
     546      131542 :   return jsinfo;
     547             : }
     548             : 
     549      131542 : Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script,
     550             :                                       Handle<Object> opt_line,
     551             :                                       Handle<Object> opt_column,
     552             :                                       int32_t offset) {
     553             :   // Line and column are possibly undefined and we need to handle these cases,
     554             :   // additionally subtracting corresponding offsets.
     555             : 
     556             :   int32_t line = 0;
     557      131542 :   if (!opt_line->IsNullOrUndefined(isolate)) {
     558      131403 :     CHECK(opt_line->IsNumber());
     559      262806 :     line = NumberToInt32(*opt_line) - script->line_offset();
     560             :   }
     561             : 
     562             :   int32_t column = 0;
     563      131542 :   if (!opt_column->IsNullOrUndefined(isolate)) {
     564      131017 :     CHECK(opt_column->IsNumber());
     565      131017 :     column = NumberToInt32(*opt_column);
     566      152808 :     if (line == 0) column -= script->column_offset();
     567             :   }
     568             : 
     569      131542 :   int line_position = ScriptLinePositionWithOffset(script, line, offset);
     570      131542 :   if (line_position < 0 || column < 0) return isolate->factory()->null_value();
     571             : 
     572             :   return GetJSPositionInfo(script, line_position + column, Script::NO_OFFSET,
     573      131542 :                            isolate);
     574             : }
     575             : 
     576             : // Slow traversal over all scripts on the heap.
     577      131542 : bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) {
     578      131542 :   Script::Iterator iterator(isolate);
     579     5150097 :   for (Script script = iterator.Next(); !script.is_null();
     580             :        script = iterator.Next()) {
     581     5150097 :     if (script->id() == needle) {
     582      131542 :       *result = handle(script, isolate);
     583             :       return true;
     584             :     }
     585             :   }
     586             : 
     587             :   return false;
     588             : }
     589             : 
     590             : }  // namespace
     591             : 
     592             : // TODO(5530): Rename once conflicting function has been deleted.
     593      263084 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
     594             :   HandleScope scope(isolate);
     595             :   DCHECK_EQ(4, args.length());
     596      263084 :   CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
     597             :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
     598             :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
     599      263084 :   CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
     600             : 
     601             :   Handle<Script> script;
     602      131542 :   CHECK(GetScriptById(isolate, scriptid, &script));
     603             : 
     604      263084 :   return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset);
     605             : }
     606             : 
     607             : // On function call, depending on circumstances, prepare for stepping in,
     608             : // or perform a side effect check.
     609     1077872 : RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
     610             :   HandleScope scope(isolate);
     611             :   DCHECK_EQ(2, args.length());
     612      538936 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
     613             :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
     614      538936 :   if (isolate->debug()->needs_check_on_function_call()) {
     615             :     // Ensure that the callee will perform debug check on function call too.
     616      538936 :     Deoptimizer::DeoptimizeFunction(*fun);
     617      538936 :     if (isolate->debug()->last_step_action() >= StepIn ||
     618             :         isolate->debug()->break_on_next_function_call()) {
     619             :       DCHECK_EQ(isolate->debug_execution_mode(), DebugInfo::kBreakpoints);
     620      528275 :       isolate->debug()->PrepareStepIn(fun);
     621             :     }
     622      549597 :     if (isolate->debug_execution_mode() == DebugInfo::kSideEffects &&
     623       10661 :         !isolate->debug()->PerformSideEffectCheck(fun, receiver)) {
     624             :       return ReadOnlyRoots(isolate).exception();
     625             :     }
     626             :   }
     627             :   return ReadOnlyRoots(isolate).undefined_value();
     628             : }
     629             : 
     630             : // Set one shot breakpoints for the suspended generator object.
     631         524 : RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
     632             :   HandleScope scope(isolate);
     633             :   DCHECK_EQ(0, args.length());
     634         262 :   isolate->debug()->PrepareStepInSuspendedGenerator();
     635             :   return ReadOnlyRoots(isolate).undefined_value();
     636             : }
     637             : 
     638        3506 : RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
     639             :   DCHECK_EQ(1, args.length());
     640             :   HandleScope scope(isolate);
     641        1753 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
     642        1753 :   isolate->PushPromise(promise);
     643             :   return ReadOnlyRoots(isolate).undefined_value();
     644             : }
     645             : 
     646             : 
     647        3488 : RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
     648             :   DCHECK_EQ(0, args.length());
     649             :   SealHandleScope shs(isolate);
     650        1744 :   isolate->PopPromise();
     651             :   return ReadOnlyRoots(isolate).undefined_value();
     652             : }
     653             : 
     654             : namespace {
     655        7251 : Handle<JSObject> MakeRangeObject(Isolate* isolate, const CoverageBlock& range) {
     656             :   Factory* factory = isolate->factory();
     657             : 
     658        7251 :   Handle<String> start_string = factory->InternalizeUtf8String("start");
     659        7251 :   Handle<String> end_string = factory->InternalizeUtf8String("end");
     660        7251 :   Handle<String> count_string = factory->InternalizeUtf8String("count");
     661             : 
     662        7251 :   Handle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
     663       14502 :   JSObject::AddProperty(isolate, range_obj, start_string,
     664       14502 :                         factory->NewNumberFromInt(range.start), NONE);
     665       14502 :   JSObject::AddProperty(isolate, range_obj, end_string,
     666       14502 :                         factory->NewNumberFromInt(range.end), NONE);
     667       14502 :   JSObject::AddProperty(isolate, range_obj, count_string,
     668       14502 :                         factory->NewNumberFromUint(range.count), NONE);
     669             : 
     670        7251 :   return range_obj;
     671             : }
     672             : }  // namespace
     673             : 
     674         592 : RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
     675             :   HandleScope scope(isolate);
     676             :   DCHECK_EQ(0, args.length());
     677             :   // Collect coverage data.
     678         592 :   std::unique_ptr<Coverage> coverage;
     679         296 :   if (isolate->is_best_effort_code_coverage()) {
     680          28 :     coverage = Coverage::CollectBestEffort(isolate);
     681             :   } else {
     682         268 :     coverage = Coverage::CollectPrecise(isolate);
     683             :   }
     684             :   Factory* factory = isolate->factory();
     685             :   // Turn the returned data structure into JavaScript.
     686             :   // Create an array of scripts.
     687         592 :   int num_scripts = static_cast<int>(coverage->size());
     688             :   // Prepare property keys.
     689         296 :   Handle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
     690         296 :   Handle<String> script_string = factory->NewStringFromStaticChars("script");
     691        2136 :   for (int i = 0; i < num_scripts; i++) {
     692         920 :     const auto& script_data = coverage->at(i);
     693             :     HandleScope inner_scope(isolate);
     694             : 
     695        1840 :     std::vector<CoverageBlock> ranges;
     696         920 :     int num_functions = static_cast<int>(script_data.functions.size());
     697        8454 :     for (int j = 0; j < num_functions; j++) {
     698        3767 :       const auto& function_data = script_data.functions[j];
     699        3767 :       ranges.emplace_back(function_data.start, function_data.end,
     700        3767 :                           function_data.count);
     701       10735 :       for (size_t k = 0; k < function_data.blocks.size(); k++) {
     702             :         const auto& block_data = function_data.blocks[k];
     703        3484 :         ranges.emplace_back(block_data.start, block_data.end, block_data.count);
     704             :       }
     705             :     }
     706             : 
     707         920 :     int num_ranges = static_cast<int>(ranges.size());
     708         920 :     Handle<FixedArray> ranges_array = factory->NewFixedArray(num_ranges);
     709       15422 :     for (int j = 0; j < num_ranges; j++) {
     710       14502 :       Handle<JSObject> range_object = MakeRangeObject(isolate, ranges[j]);
     711       14502 :       ranges_array->set(j, *range_object);
     712             :     }
     713             : 
     714             :     Handle<JSArray> script_obj =
     715             :         factory->NewJSArrayWithElements(ranges_array, PACKED_ELEMENTS);
     716         920 :     JSObject::AddProperty(isolate, script_obj, script_string,
     717         920 :                           handle(script_data.script->source(), isolate), NONE);
     718        1840 :     scripts_array->set(i, *script_obj);
     719             :   }
     720             :   return *factory->NewJSArrayWithElements(scripts_array, PACKED_ELEMENTS);
     721             : }
     722             : 
     723          16 : RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
     724             :   SealHandleScope shs(isolate);
     725           8 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
     726           8 :   Coverage::SelectMode(isolate, enable ? debug::CoverageMode::kPreciseCount
     727           8 :                                        : debug::CoverageMode::kBestEffort);
     728             :   return ReadOnlyRoots(isolate).undefined_value();
     729             : }
     730             : 
     731          74 : RUNTIME_FUNCTION(Runtime_DebugToggleBlockCoverage) {
     732             :   SealHandleScope shs(isolate);
     733          37 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
     734          37 :   Coverage::SelectMode(isolate, enable ? debug::CoverageMode::kBlockCount
     735          37 :                                        : debug::CoverageMode::kBestEffort);
     736             :   return ReadOnlyRoots(isolate).undefined_value();
     737             : }
     738             : 
     739      359000 : RUNTIME_FUNCTION(Runtime_IncBlockCounter) {
     740             :   SealHandleScope scope(isolate);
     741             :   DCHECK_EQ(2, args.length());
     742      359000 :   CONVERT_ARG_CHECKED(JSFunction, function, 0);
     743      179500 :   CONVERT_SMI_ARG_CHECKED(coverage_array_slot_index, 1);
     744             : 
     745             :   // It's quite possible that a function contains IncBlockCounter bytecodes, but
     746             :   // no coverage info exists. This happens e.g. by selecting the best-effort
     747             :   // coverage collection mode, which triggers deletion of all coverage infos in
     748             :   // order to avoid memory leaks.
     749             : 
     750      179500 :   SharedFunctionInfo shared = function->shared();
     751      179500 :   if (shared->HasCoverageInfo()) {
     752      179500 :     CoverageInfo coverage_info = shared->GetCoverageInfo();
     753      179500 :     coverage_info->IncrementBlockCount(coverage_array_slot_index);
     754             :   }
     755             : 
     756             :   return ReadOnlyRoots(isolate).undefined_value();
     757             : }
     758             : 
     759        9548 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionEntered) {
     760             :   DCHECK_EQ(1, args.length());
     761             :   HandleScope scope(isolate);
     762        4774 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     763        4774 :   isolate->RunPromiseHook(PromiseHookType::kInit, promise,
     764        4774 :                           isolate->factory()->undefined_value());
     765        9483 :   if (isolate->debug()->is_active()) isolate->PushPromise(promise);
     766             :   return ReadOnlyRoots(isolate).undefined_value();
     767             : }
     768             : 
     769        9418 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
     770             :   DCHECK_EQ(2, args.length());
     771             :   HandleScope scope(isolate);
     772        4709 :   CONVERT_BOOLEAN_ARG_CHECKED(has_suspend, 0);
     773        4709 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 1);
     774        4709 :   isolate->PopPromise();
     775        4709 :   if (has_suspend) {
     776             :     isolate->OnAsyncFunctionStateChanged(promise,
     777        3417 :                                          debug::kAsyncFunctionFinished);
     778             :   }
     779             :   return *promise;
     780             : }
     781             : 
     782         550 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
     783             :   DCHECK_EQ(1, args.length());
     784             :   HandleScope scope(isolate);
     785         275 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     786         275 :   isolate->OnAsyncFunctionStateChanged(promise, debug::kAsyncFunctionSuspended);
     787             :   return ReadOnlyRoots(isolate).undefined_value();
     788             : }
     789             : 
     790        1122 : RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
     791             :   HandleScope scope(isolate);
     792             :   DCHECK_EQ(2, args.length());
     793         561 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, script_function, 0);
     794         561 :   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
     795             : 
     796        1122 :   Handle<Script> script(Script::cast(script_function->shared()->script()),
     797         561 :                         isolate);
     798         561 :   v8::debug::LiveEditResult result;
     799         561 :   LiveEdit::PatchScript(isolate, script, new_source, false, &result);
     800         561 :   switch (result.status) {
     801             :     case v8::debug::LiveEditResult::COMPILE_ERROR:
     802          18 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     803           9 :           "LiveEdit failed: COMPILE_ERROR"));
     804             :     case v8::debug::LiveEditResult::BLOCKED_BY_RUNNING_GENERATOR:
     805          36 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     806          18 :           "LiveEdit failed: BLOCKED_BY_RUNNING_GENERATOR"));
     807             :     case v8::debug::LiveEditResult::BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME:
     808           0 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     809           0 :           "LiveEdit failed: BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME"));
     810             :     case v8::debug::LiveEditResult::
     811             :         BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME:
     812         108 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     813          54 :           "LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME"));
     814             :     case v8::debug::LiveEditResult::BLOCKED_BY_ACTIVE_FUNCTION:
     815           0 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     816           0 :           "LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION"));
     817             :     case v8::debug::LiveEditResult::BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME:
     818          72 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     819          36 :           "LiveEdit failed: BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME"));
     820             :     case v8::debug::LiveEditResult::FRAME_RESTART_IS_NOT_SUPPORTED:
     821           0 :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     822           0 :           "LiveEdit failed: FRAME_RESTART_IS_NOT_SUPPORTED"));
     823             :     case v8::debug::LiveEditResult::OK:
     824             :       return ReadOnlyRoots(isolate).undefined_value();
     825             :   }
     826             :   return ReadOnlyRoots(isolate).undefined_value();
     827             : }
     828             : 
     829           0 : RUNTIME_FUNCTION(Runtime_PerformSideEffectCheckForObject) {
     830             :   HandleScope scope(isolate);
     831             :   DCHECK_EQ(1, args.length());
     832           0 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
     833             : 
     834             :   DCHECK_EQ(isolate->debug_execution_mode(), DebugInfo::kSideEffects);
     835           0 :   if (!isolate->debug()->PerformSideEffectCheckForObject(object)) {
     836             :     DCHECK(isolate->has_pending_exception());
     837             :     return ReadOnlyRoots(isolate).exception();
     838             :   }
     839             :   return ReadOnlyRoots(isolate).undefined_value();
     840             : }
     841             : 
     842             : }  // namespace internal
     843      122004 : }  // namespace v8

Generated by: LCOV version 1.10