LCOV - code coverage report
Current view: top level - src/runtime - runtime-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 356 371 96.0 %
Date: 2019-02-19 Functions: 40 70 57.1 %

          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      599752 : 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       66666 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
      44       66666 :   HandleScope scope(isolate);
      45             : 
      46             :   // Return value can be changed by debugger. Last set value will be used as
      47             :   // return value.
      48      133332 :   ReturnValueScope result_scope(isolate->debug());
      49       66666 :   isolate->debug()->set_return_value(*value);
      50             : 
      51             :   // Get the top-most JavaScript frame.
      52      133332 :   JavaScriptFrameIterator it(isolate);
      53       66666 :   if (isolate->debug_execution_mode() == DebugInfo::kBreakpoints) {
      54             :     isolate->debug()->Break(it.frame(),
      55      192999 :                             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       66666 :   if (isolate->debug()->will_restart()) {
      61             :     return MakePair(ReadOnlyRoots(isolate).undefined_value(),
      62          46 :                     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       66643 :       reinterpret_cast<InterpretedFrame*>(it.frame());
      69       66643 :   SharedFunctionInfo shared = interpreted_frame->function()->shared();
      70       66643 :   BytecodeArray bytecode_array = shared->GetBytecodeArray();
      71       66643 :   int bytecode_offset = interpreted_frame->GetBytecodeOffset();
      72       66643 :   Bytecode bytecode = Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
      73             : 
      74             :   bool side_effect_check_failed = false;
      75       66643 :   if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
      76             :     side_effect_check_failed =
      77        2333 :         !isolate->debug()->PerformSideEffectCheckAtBytecode(interpreted_frame);
      78             :   }
      79             : 
      80       66643 :   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       66643 :   isolate->interpreter()->GetBytecodeHandler(bytecode, operand_scale);
      95             : 
      96       66643 :   if (side_effect_check_failed) {
      97             :     return MakePair(ReadOnlyRoots(isolate).exception(),
      98         336 :                     Smi::FromInt(static_cast<uint8_t>(bytecode)));
      99             :   }
     100       66475 :   Object interrupt_object = isolate->stack_guard()->HandleInterrupts();
     101      132950 :   if (interrupt_object->IsException(isolate)) {
     102             :     return MakePair(interrupt_object,
     103           5 :                     Smi::FromInt(static_cast<uint8_t>(bytecode)));
     104             :   }
     105             :   return MakePair(isolate->debug()->return_value(),
     106      199606 :                   Smi::FromInt(static_cast<uint8_t>(bytecode)));
     107             : }
     108             : 
     109         940 : RUNTIME_FUNCTION(Runtime_DebugBreakAtEntry) {
     110         470 :   HandleScope scope(isolate);
     111             :   DCHECK_EQ(1, args.length());
     112         940 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     113         470 :   USE(function);
     114             : 
     115             :   DCHECK(function->shared()->HasDebugInfo());
     116             :   DCHECK(function->shared()->GetDebugInfo()->BreakAtEntry());
     117             : 
     118             :   // Get the top-most JavaScript frame.
     119         940 :   JavaScriptFrameIterator it(isolate);
     120             :   DCHECK_EQ(*function, it.frame()->function());
     121         940 :   isolate->debug()->Break(it.frame(), function);
     122             : 
     123         470 :   return ReadOnlyRoots(isolate).undefined_value();
     124             : }
     125             : 
     126        8493 : RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
     127             :   SealHandleScope shs(isolate);
     128             :   DCHECK_EQ(0, args.length());
     129        8493 :   if (isolate->debug()->break_points_active()) {
     130        8435 :     isolate->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
     131             :   }
     132        8493 :   return isolate->stack_guard()->HandleInterrupts();
     133             : }
     134             : 
     135         126 : RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
     136             :   SealHandleScope shs(isolate);
     137             :   DCHECK_EQ(0, args.length());
     138             :   isolate->RequestInterrupt(
     139         247 :       [](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         159 :   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         318 :   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       79153 : MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
     187             :                                                     Handle<Object> object) {
     188             :   Factory* factory = isolate->factory();
     189      158306 :   if (object->IsJSBoundFunction()) {
     190           5 :     Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
     191             : 
     192           5 :     Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
     193             :     Handle<String> target =
     194           5 :         factory->NewStringFromAsciiChecked("[[TargetFunction]]");
     195          10 :     result->set(0, *target);
     196          10 :     result->set(1, function->bound_target_function());
     197             : 
     198             :     Handle<String> bound_this =
     199           5 :         factory->NewStringFromAsciiChecked("[[BoundThis]]");
     200          10 :     result->set(2, *bound_this);
     201           5 :     result->set(3, function->bound_this());
     202             : 
     203             :     Handle<String> bound_args =
     204           5 :         factory->NewStringFromAsciiChecked("[[BoundArgs]]");
     205          10 :     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           5 :         factory->NewJSArrayWithElements(bound_arguments);
     210          10 :     result->set(5, *arguments_array);
     211           5 :     return factory->NewJSArrayWithElements(result);
     212      158296 :   } else if (object->IsJSMapIterator()) {
     213          87 :     Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
     214          87 :     return GetIteratorInternalProperties(isolate, iterator);
     215      158122 :   } else if (object->IsJSSetIterator()) {
     216          72 :     Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
     217          72 :     return GetIteratorInternalProperties(isolate, iterator);
     218      157978 :   } else if (object->IsJSGeneratorObject()) {
     219             :     Handle<JSGeneratorObject> generator =
     220          50 :         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      157878 :   } else if (object->IsJSPromise()) {
     249          40 :     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      157798 :   } else if (object->IsJSProxy()) {
     268          15 :     Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
     269          15 :     Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
     270             : 
     271             :     Handle<String> handler_str =
     272          15 :         factory->NewStringFromAsciiChecked("[[Handler]]");
     273          30 :     result->set(0, *handler_str);
     274          15 :     result->set(1, js_proxy->handler());
     275             : 
     276             :     Handle<String> target_str =
     277          15 :         factory->NewStringFromAsciiChecked("[[Target]]");
     278          30 :     result->set(2, *target_str);
     279          15 :     result->set(3, js_proxy->target());
     280             : 
     281             :     Handle<String> is_revoked_str =
     282          15 :         factory->NewStringFromAsciiChecked("[[IsRevoked]]");
     283          30 :     result->set(4, *is_revoked_str);
     284          45 :     result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
     285          15 :     return factory->NewJSArrayWithElements(result);
     286      157768 :   } else if (object->IsJSValue()) {
     287         118 :     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
     288             : 
     289         118 :     Handle<FixedArray> result = factory->NewFixedArray(2);
     290             :     Handle<String> primitive_value =
     291         118 :         factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
     292         236 :     result->set(0, *primitive_value);
     293         118 :     result->set(1, js_value->value());
     294         118 :     return factory->NewJSArrayWithElements(result);
     295             :   }
     296       78766 :   return factory->NewJSArray(0);
     297             : }
     298             : 
     299         288 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
     300         288 :   HandleScope scope(isolate);
     301             :   DCHECK_EQ(1, args.length());
     302             : 
     303         576 :   if (!args[0]->IsJSGeneratorObject()) return Smi::kZero;
     304             : 
     305             :   // Check arguments.
     306         576 :   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        1368 :   for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
     316        1080 :     n++;
     317         288 :   }
     318             : 
     319         288 :   return Smi::FromInt(n);
     320             : }
     321             : 
     322         945 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
     323         945 :   HandleScope scope(isolate);
     324             :   DCHECK_EQ(2, args.length());
     325             : 
     326        1890 :   if (!args[0]->IsJSGeneratorObject()) {
     327             :     return ReadOnlyRoots(isolate).undefined_value();
     328             :   }
     329             : 
     330             :   // Check arguments.
     331        1890 :   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         927 :   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        2835 :   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         378 :   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         117 : RUNTIME_FUNCTION(Runtime_SetGeneratorScopeVariableValue) {
     372         117 :   HandleScope scope(isolate);
     373             :   DCHECK_EQ(4, args.length());
     374         234 :   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
     375         234 :   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
     376         234 :   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 2);
     377         117 :   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         234 :   return isolate->heap()->ToBoolean(res);
     381             : }
     382             : 
     383             : 
     384        1134 : RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
     385         567 :   HandleScope scope(isolate);
     386             :   DCHECK_EQ(1, args.length());
     387         567 :   CHECK(isolate->debug()->is_active());
     388        1134 :   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        1134 :   if (break_locations->IsUndefined(isolate)) {
     395             :     return ReadOnlyRoots(isolate).undefined_value();
     396             :   }
     397             :   // Return array as JS array
     398             :   return *isolate->factory()->NewJSArrayWithElements(
     399        1242 :       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        3321 :   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        3321 :   return Smi::FromInt(result);
     413             : }
     414             : 
     415             : // Clear all stepping set by PrepareStep.
     416          54 : RUNTIME_FUNCTION(Runtime_ClearStepping) {
     417          18 :   HandleScope scope(isolate);
     418             :   DCHECK_EQ(0, args.length());
     419          18 :   CHECK(isolate->debug()->is_active());
     420          18 :   isolate->debug()->ClearStepping();
     421          18 :   return ReadOnlyRoots(isolate).undefined_value();
     422             : }
     423             : 
     424         339 : RUNTIME_FUNCTION(Runtime_DebugGetLoadedScriptIds) {
     425         113 :   HandleScope scope(isolate);
     426             :   DCHECK_EQ(0, args.length());
     427             : 
     428             :   Handle<FixedArray> instances;
     429             :   {
     430         113 :     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        1216 :     Handle<Script> script(Script::cast(instances->get(i)), isolate);
     438        1216 :     instances->set(i, Smi::FromInt(script->id()));
     439             :   }
     440             : 
     441             :   // Return result as a JS array.
     442         226 :   return *isolate->factory()->NewJSArrayWithElements(instances);
     443             : }
     444             : 
     445             : 
     446          69 : RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
     447             :   SealHandleScope shs(isolate);
     448             :   DCHECK_EQ(1, args.length());
     449             : 
     450          69 :   CONVERT_ARG_CHECKED(Object, f, 0);
     451         138 :   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         264 : RUNTIME_FUNCTION(Runtime_CollectGarbage) {
     461             :   SealHandleScope shs(isolate);
     462             :   DCHECK_EQ(1, args.length());
     463             :   isolate->heap()->PreciseCollectAllGarbage(Heap::kNoGCFlags,
     464         264 :                                             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           0 :   if (!Smi::IsValid(usage)) {
     475           0 :     return *isolate->factory()->NewNumberFromInt(usage);
     476             :   }
     477           0 :   return Smi::FromInt(usage);
     478             : }
     479             : 
     480             : namespace {
     481             : 
     482      131478 : int ScriptLinePosition(Handle<Script> script, int line) {
     483      131478 :   if (line < 0) return -1;
     484             : 
     485      131478 :   if (script->type() == Script::TYPE_WASM) {
     486             :     return WasmModuleObject::cast(script->wasm_module_object())
     487          32 :         ->GetFunctionOffset(line);
     488             :   }
     489             : 
     490      131462 :   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      131462 :   if (line == 0) return 0;
     497             :   // If line == line_count, we return the first position beyond the last line.
     498      109460 :   if (line > line_count) return -1;
     499      218920 :   return Smi::ToInt(line_ends_array->get(line - 1)) + 1;
     500             : }
     501             : 
     502      131478 : int ScriptLinePositionWithOffset(Handle<Script> script, int line, int offset) {
     503      131478 :   if (line < 0 || offset < 0) return -1;
     504             : 
     505      131478 :   if (line == 0 || offset == 0)
     506      130817 :     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      131478 : Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
     518             :                                  Script::OffsetFlag offset_flag,
     519             :                                  Isolate* isolate) {
     520             :   Script::PositionInfo info;
     521      131478 :   if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
     522           0 :     return isolate->factory()->null_value();
     523             :   }
     524             : 
     525      131478 :   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      262940 :                                         source, info.line_start, info.line_end);
     530             : 
     531             :   Handle<JSObject> jsinfo =
     532      131478 :       isolate->factory()->NewJSObject(isolate->object_function());
     533             : 
     534             :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->script_string(),
     535      131478 :                         script, NONE);
     536             :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->position_string(),
     537      131478 :                         handle(Smi::FromInt(position), isolate), NONE);
     538             :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->line_string(),
     539      262956 :                         handle(Smi::FromInt(info.line), isolate), NONE);
     540             :   JSObject::AddProperty(isolate, jsinfo, isolate->factory()->column_string(),
     541      262956 :                         handle(Smi::FromInt(info.column), isolate), NONE);
     542             :   JSObject::AddProperty(isolate, jsinfo,
     543             :                         isolate->factory()->sourceText_string(), sourceText,
     544      131478 :                         NONE);
     545             : 
     546      131478 :   return jsinfo;
     547             : }
     548             : 
     549      131478 : 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      262956 :   if (!opt_line->IsNullOrUndefined(isolate)) {
     558      262678 :     CHECK(opt_line->IsNumber());
     559      262678 :     line = NumberToInt32(*opt_line) - script->line_offset();
     560             :   }
     561             : 
     562             :   int32_t column = 0;
     563      262956 :   if (!opt_column->IsNullOrUndefined(isolate)) {
     564      261906 :     CHECK(opt_column->IsNumber());
     565      130953 :     column = NumberToInt32(*opt_column);
     566      152735 :     if (line == 0) column -= script->column_offset();
     567             :   }
     568             : 
     569      131478 :   int line_position = ScriptLinePositionWithOffset(script, line, offset);
     570      131478 :   if (line_position < 0 || column < 0) return isolate->factory()->null_value();
     571             : 
     572             :   return GetJSPositionInfo(script, line_position + column, Script::NO_OFFSET,
     573      131478 :                            isolate);
     574             : }
     575             : 
     576             : // Slow traversal over all scripts on the heap.
     577      131478 : bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) {
     578      131478 :   Script::Iterator iterator(isolate);
     579     5140715 :   for (Script script = iterator.Next(); !script.is_null();
     580             :        script = iterator.Next()) {
     581     5140715 :     if (script->id() == needle) {
     582      131478 :       *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      131478 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
     594      131478 :   HandleScope scope(isolate);
     595             :   DCHECK_EQ(4, args.length());
     596      262956 :   CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
     597      131478 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
     598      131478 :   CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
     599      262956 :   CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
     600             : 
     601             :   Handle<Script> script;
     602      131478 :   CHECK(GetScriptById(isolate, scriptid, &script));
     603             : 
     604      262956 :   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     2711637 : RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
     610      538837 :   HandleScope scope(isolate);
     611             :   DCHECK_EQ(2, args.length());
     612     1077674 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
     613      538837 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
     614      538837 :   if (isolate->debug()->needs_check_on_function_call()) {
     615             :     // Ensure that the callee will perform debug check on function call too.
     616     1077674 :     Deoptimizer::DeoptimizeFunction(*fun);
     617      556289 :     if (isolate->debug()->last_step_action() >= StepIn ||
     618       17452 :         isolate->debug()->break_on_next_function_call()) {
     619             :       DCHECK_EQ(isolate->debug_execution_mode(), DebugInfo::kBreakpoints);
     620      528275 :       isolate->debug()->PrepareStepIn(fun);
     621             :     }
     622      549399 :     if (isolate->debug_execution_mode() == DebugInfo::kSideEffects &&
     623       10562 :         !isolate->debug()->PerformSideEffectCheck(fun, receiver)) {
     624             :       return ReadOnlyRoots(isolate).exception();
     625             :     }
     626             :   }
     627      538837 :   return ReadOnlyRoots(isolate).undefined_value();
     628             : }
     629             : 
     630             : // Set one shot breakpoints for the suspended generator object.
     631         524 : RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
     632         262 :   HandleScope scope(isolate);
     633             :   DCHECK_EQ(0, args.length());
     634         262 :   isolate->debug()->PrepareStepInSuspendedGenerator();
     635         262 :   return ReadOnlyRoots(isolate).undefined_value();
     636             : }
     637             : 
     638        1753 : RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
     639             :   DCHECK_EQ(1, args.length());
     640        1753 :   HandleScope scope(isolate);
     641        3506 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
     642        1753 :   isolate->PushPromise(promise);
     643        1753 :   return ReadOnlyRoots(isolate).undefined_value();
     644             : }
     645             : 
     646             : 
     647        1744 : 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        7159 : Handle<JSObject> MakeRangeObject(Isolate* isolate, const CoverageBlock& range) {
     656             :   Factory* factory = isolate->factory();
     657             : 
     658        7159 :   Handle<String> start_string = factory->InternalizeUtf8String("start");
     659        7159 :   Handle<String> end_string = factory->InternalizeUtf8String("end");
     660        7159 :   Handle<String> count_string = factory->InternalizeUtf8String("count");
     661             : 
     662        7159 :   Handle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
     663             :   JSObject::AddProperty(isolate, range_obj, start_string,
     664       14318 :                         factory->NewNumberFromInt(range.start), NONE);
     665             :   JSObject::AddProperty(isolate, range_obj, end_string,
     666       14318 :                         factory->NewNumberFromInt(range.end), NONE);
     667             :   JSObject::AddProperty(isolate, range_obj, count_string,
     668       14318 :                         factory->NewNumberFromUint(range.count), NONE);
     669             : 
     670        7159 :   return range_obj;
     671             : }
     672             : }  // namespace
     673             : 
     674         292 : RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
     675         292 :   HandleScope scope(isolate);
     676             :   DCHECK_EQ(0, args.length());
     677             :   // Collect coverage data.
     678         584 :   std::unique_ptr<Coverage> coverage;
     679         292 :   if (isolate->is_best_effort_code_coverage()) {
     680          28 :     coverage = Coverage::CollectBestEffort(isolate);
     681             :   } else {
     682         264 :     coverage = Coverage::CollectPrecise(isolate);
     683             :   }
     684         292 :   Factory* factory = isolate->factory();
     685             :   // Turn the returned data structure into JavaScript.
     686             :   // Create an array of scripts.
     687         292 :   int num_scripts = static_cast<int>(coverage->size());
     688             :   // Prepare property keys.
     689         292 :   Handle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
     690         292 :   Handle<String> script_string = factory->NewStringFromStaticChars("script");
     691         908 :   for (int i = 0; i < num_scripts; i++) {
     692         908 :     const auto& script_data = coverage->at(i);
     693         908 :     HandleScope inner_scope(isolate);
     694             : 
     695        1816 :     std::vector<CoverageBlock> ranges;
     696        4643 :     int num_functions = static_cast<int>(script_data.functions.size());
     697        3735 :     for (int j = 0; j < num_functions; j++) {
     698        7470 :       const auto& function_data = script_data.functions[j];
     699             :       ranges.emplace_back(function_data.start, function_data.end,
     700        3735 :                           function_data.count);
     701       10583 :       for (size_t k = 0; k < function_data.blocks.size(); k++) {
     702       10583 :         const auto& block_data = function_data.blocks[k];
     703        3424 :         ranges.emplace_back(block_data.start, block_data.end, block_data.count);
     704             :       }
     705             :     }
     706             : 
     707         908 :     int num_ranges = static_cast<int>(ranges.size());
     708         908 :     Handle<FixedArray> ranges_array = factory->NewFixedArray(num_ranges);
     709        7159 :     for (int j = 0; j < num_ranges; j++) {
     710        7159 :       Handle<JSObject> range_object = MakeRangeObject(isolate, ranges[j]);
     711       14318 :       ranges_array->set(j, *range_object);
     712             :     }
     713             : 
     714             :     Handle<JSArray> script_obj =
     715         908 :         factory->NewJSArrayWithElements(ranges_array, PACKED_ELEMENTS);
     716             :     JSObject::AddProperty(isolate, script_obj, script_string,
     717        1816 :                           handle(script_data.script->source(), isolate), NONE);
     718        1816 :     scripts_array->set(i, *script_obj);
     719         908 :   }
     720         876 :   return *factory->NewJSArrayWithElements(scripts_array, PACKED_ELEMENTS);
     721             : }
     722             : 
     723           8 : RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
     724             :   SealHandleScope shs(isolate);
     725          24 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
     726             :   Coverage::SelectMode(isolate, enable ? debug::Coverage::kPreciseCount
     727           8 :                                        : debug::Coverage::kBestEffort);
     728             :   return ReadOnlyRoots(isolate).undefined_value();
     729             : }
     730             : 
     731          37 : RUNTIME_FUNCTION(Runtime_DebugToggleBlockCoverage) {
     732             :   SealHandleScope shs(isolate);
     733         111 :   CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
     734             :   Coverage::SelectMode(isolate, enable ? debug::Coverage::kBlockCount
     735          37 :                                        : debug::Coverage::kBestEffort);
     736             :   return ReadOnlyRoots(isolate).undefined_value();
     737             : }
     738             : 
     739      179448 : RUNTIME_FUNCTION(Runtime_IncBlockCounter) {
     740             :   SealHandleScope scope(isolate);
     741             :   DCHECK_EQ(2, args.length());
     742      538344 :   CONVERT_ARG_CHECKED(JSFunction, function, 0);
     743      358896 :   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      179448 :   SharedFunctionInfo shared = function->shared();
     751      179448 :   if (shared->HasCoverageInfo()) {
     752      179448 :     CoverageInfo coverage_info = shared->GetCoverageInfo();
     753      179448 :     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        4774 :   HandleScope scope(isolate);
     762        9548 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     763             :   isolate->RunPromiseHook(PromiseHookType::kInit, promise,
     764        9548 :                           isolate->factory()->undefined_value());
     765        9483 :   if (isolate->debug()->is_active()) isolate->PushPromise(promise);
     766        4774 :   return ReadOnlyRoots(isolate).undefined_value();
     767             : }
     768             : 
     769        4709 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionFinished) {
     770             :   DCHECK_EQ(2, args.length());
     771        4709 :   HandleScope scope(isolate);
     772       14127 :   CONVERT_BOOLEAN_ARG_CHECKED(has_suspend, 0);
     773        9418 :   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        4709 :   return *promise;
     780             : }
     781             : 
     782         275 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
     783             :   DCHECK_EQ(1, args.length());
     784         275 :   HandleScope scope(isolate);
     785         550 :   CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
     786         275 :   isolate->OnAsyncFunctionStateChanged(promise, debug::kAsyncFunctionSuspended);
     787         275 :   return ReadOnlyRoots(isolate).undefined_value();
     788             : }
     789             : 
     790         561 : RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
     791         561 :   HandleScope scope(isolate);
     792             :   DCHECK_EQ(2, args.length());
     793        1122 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, script_function, 0);
     794        1122 :   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
     795             : 
     796        1122 :   Handle<Script> script(Script::cast(script_function->shared()->script()),
     797        1122 :                         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             :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     803          18 :           "LiveEdit failed: COMPILE_ERROR"));
     804             :     case v8::debug::LiveEditResult::BLOCKED_BY_RUNNING_GENERATOR:
     805             :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     806          36 :           "LiveEdit failed: BLOCKED_BY_RUNNING_GENERATOR"));
     807             :     case v8::debug::LiveEditResult::BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME:
     808             :       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             :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     813         108 :           "LiveEdit failed: BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME"));
     814             :     case v8::debug::LiveEditResult::BLOCKED_BY_ACTIVE_FUNCTION:
     815             :       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             :       return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
     819          72 :           "LiveEdit failed: BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME"));
     820             :     case v8::debug::LiveEditResult::FRAME_RESTART_IS_NOT_SUPPORTED:
     821             :       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         561 :   return ReadOnlyRoots(isolate).undefined_value();
     827             : }
     828             : 
     829           0 : RUNTIME_FUNCTION(Runtime_PerformSideEffectCheckForObject) {
     830           0 :   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           0 :   return ReadOnlyRoots(isolate).undefined_value();
     840             : }
     841             : 
     842             : }  // namespace internal
     843      178779 : }  // namespace v8

Generated by: LCOV version 1.10