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

Generated by: LCOV version 1.10