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