v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-debug.cc
Go to the documentation of this file.
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
10#include "src/debug/debug.h"
11#include "src/debug/liveedit.h"
14#include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
23#include "src/runtime/runtime.h"
26
27#if V8_ENABLE_WEBASSEMBLY
30#endif // V8_ENABLE_WEBASSEMBLY
31
32namespace v8 {
33namespace internal {
34
35RUNTIME_FUNCTION_RETURN_PAIR(Runtime_DebugBreakOnBytecode) {
39
40 SealHandleScope shs(isolate);
41 DCHECK_EQ(1, args.length());
42 DirectHandle<Object> value = args.at(0);
43 HandleScope scope(isolate);
44
45 // Return value can be changed by debugger. Last set value will be used as
46 // return value.
47 ReturnValueScope result_scope(isolate->debug());
48 isolate->debug()->set_return_value(*value);
49
50 // Get the top-most JavaScript frame.
52 if (isolate->debug_execution_mode() == DebugInfo::kBreakpoints) {
53 isolate->debug()->Break(it.frame(),
54 direct_handle(it.frame()->function(), isolate));
55 }
56
57 // If the user requested to restart a frame, there is no need
58 // to get the return value or check the bytecode for side-effects.
59 if (isolate->debug()->IsRestartFrameScheduled()) {
60 Tagged<Object> exception = isolate->TerminateExecution();
61 return MakePair(exception,
62 Smi::FromInt(static_cast<uint8_t>(Bytecode::kIllegal)));
63 }
64
65 // Return the handler from the original bytecode array.
66 DCHECK(it.frame()->is_interpreted());
67 InterpretedFrame* interpreted_frame =
68 reinterpret_cast<InterpretedFrame*>(it.frame());
69
70 bool side_effect_check_failed = false;
71 if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
72 side_effect_check_failed =
73 !isolate->debug()->PerformSideEffectCheckAtBytecode(interpreted_frame);
74 }
75
76 // Make sure to only access these objects after the side effect check, as the
77 // check can allocate on failure.
78 Tagged<SharedFunctionInfo> shared = interpreted_frame->function()->shared();
79 Tagged<BytecodeArray> bytecode_array = shared->GetBytecodeArray(isolate);
80 int bytecode_offset = interpreted_frame->GetBytecodeOffset();
81 Bytecode bytecode = Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
82
83 if (Bytecodes::Returns(bytecode)) {
84 // If we are returning (or suspending), reset the bytecode array on the
85 // interpreted stack frame to the non-debug variant so that the interpreter
86 // entry trampoline sees the return/suspend bytecode rather than the
87 // DebugBreak.
88 interpreted_frame->PatchBytecodeArray(bytecode_array);
89 }
90
91 // We do not have to deal with operand scale here. If the bytecode at the
92 // break is prefixed by operand scaling, we would have patched over the
93 // scaling prefix. We now simply dispatch to the handler for the prefix.
94 // We need to deserialize now to ensure we don't hit the debug break again
95 // after deserializing.
96 OperandScale operand_scale = OperandScale::kSingle;
97 isolate->interpreter()->GetBytecodeHandler(bytecode, operand_scale);
98
99 if (side_effect_check_failed) {
100 return MakePair(ReadOnlyRoots(isolate).exception(),
101 Smi::FromInt(static_cast<uint8_t>(bytecode)));
102 }
103 Tagged<Object> interrupt_object = isolate->stack_guard()->HandleInterrupts();
104 if (IsException(interrupt_object, isolate)) {
105 return MakePair(interrupt_object,
106 Smi::FromInt(static_cast<uint8_t>(bytecode)));
107 }
108 return MakePair(isolate->debug()->return_value(),
109 Smi::FromInt(static_cast<uint8_t>(bytecode)));
110}
111
112RUNTIME_FUNCTION(Runtime_DebugBreakAtEntry) {
113 HandleScope scope(isolate);
114 DCHECK_EQ(1, args.length());
115 DirectHandle<JSFunction> function = args.at<JSFunction>(0);
116
117 DCHECK(function->shared()->BreakAtEntry(isolate));
118
119 // Get the top-most JavaScript frame. This is the debug target function.
121 DCHECK_EQ(*function, it.frame()->function());
122 // Check whether the next JS frame is closer than the last API entry.
123 // if yes, then the call to the debug target came from JavaScript. Otherwise,
124 // the call to the debug target came from API. Do not break for the latter.
125 it.Advance();
126 if (!it.done() &&
127 it.frame()->fp() < isolate->thread_local_top()->last_api_entry_) {
128 isolate->debug()->Break(it.frame(), function);
129 }
130
131 return ReadOnlyRoots(isolate).undefined_value();
132}
133
134RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
135 SealHandleScope shs(isolate);
136 DCHECK_EQ(0, args.length());
137 if (isolate->debug()->break_points_active()) {
138 isolate->debug()->HandleDebugBreak(
141 if (isolate->debug()->IsRestartFrameScheduled()) {
142 return isolate->TerminateExecution();
143 }
144 }
145 return isolate->stack_guard()->HandleInterrupts();
146}
147
148RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
149 SealHandleScope shs(isolate);
150 DCHECK_EQ(0, args.length());
151 isolate->RequestInterrupt(
152 [](v8::Isolate* isolate, void*) {
154 isolate,
156 },
157 nullptr);
158 return ReadOnlyRoots(isolate).undefined_value();
159}
160
161namespace {
162
163template <class IteratorType>
164static DirectHandle<ArrayList> AddIteratorInternalProperties(
165 Isolate* isolate, DirectHandle<ArrayList> result,
166 DirectHandle<IteratorType> iterator) {
167 const char* kind = nullptr;
168 switch (iterator->map()->instance_type()) {
169 case JS_MAP_KEY_ITERATOR_TYPE:
170 kind = "keys";
171 break;
172 case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
173 case JS_SET_KEY_VALUE_ITERATOR_TYPE:
174 kind = "entries";
175 break;
176 case JS_MAP_VALUE_ITERATOR_TYPE:
177 case JS_SET_VALUE_ITERATOR_TYPE:
178 kind = "values";
179 break;
180 default:
181 UNREACHABLE();
182 }
183
185 isolate, result,
186 isolate->factory()->NewStringFromAsciiChecked("[[IteratorHasMore]]"),
187 isolate->factory()->ToBoolean(iterator->HasMore()));
189 isolate, result,
190 isolate->factory()->NewStringFromAsciiChecked("[[IteratorIndex]]"),
191 direct_handle(iterator->index(), isolate));
193 isolate, result,
194 isolate->factory()->NewStringFromAsciiChecked("[[IteratorKind]]"),
195 isolate->factory()->NewStringFromAsciiChecked(kind));
196 return result;
197}
198
199} // namespace
200
202 Isolate* isolate, DirectHandle<Object> object) {
204 if (IsJSObject(*object)) {
205 PrototypeIterator iter(isolate, Cast<JSObject>(object), kStartAtReceiver);
206 if (iter.HasAccess()) {
207 iter.Advance();
209 if (!iter.IsAtEnd() && iter.HasAccess() && IsJSGlobalProxy(*object)) {
210 // Skip JSGlobalObject as the [[Prototype]].
211 DCHECK(IsJSGlobalObject(*prototype));
212 iter.Advance();
213 prototype = PrototypeIterator::GetCurrent(iter);
214 }
215 if (!IsNull(*prototype, isolate)) {
217 isolate, result,
218 isolate->factory()->NewStringFromStaticChars("[[Prototype]]"),
219 prototype);
220 }
221 }
222 }
223 if (IsJSBoundFunction(*object)) {
224 auto function = Cast<JSBoundFunction>(object);
225
227 isolate, result,
228 isolate->factory()->NewStringFromAsciiChecked("[[TargetFunction]]"),
229 direct_handle(function->bound_target_function(), isolate));
231 isolate, result,
232 isolate->factory()->NewStringFromAsciiChecked("[[BoundThis]]"),
233 direct_handle(function->bound_this(), isolate));
235 isolate, result,
236 isolate->factory()->NewStringFromAsciiChecked("[[BoundArgs]]"),
237 isolate->factory()->NewJSArrayWithElements(
238 isolate->factory()->CopyFixedArray(
239 handle(function->bound_arguments(), isolate))));
240 } else if (IsJSMapIterator(*object)) {
242 result = AddIteratorInternalProperties(isolate, result, iterator);
243 } else if (IsJSSetIterator(*object)) {
245 result = AddIteratorInternalProperties(isolate, result, iterator);
246 } else if (IsJSGeneratorObject(*object)) {
247 auto generator = Cast<JSGeneratorObject>(object);
248
249 const char* status = "suspended";
250 if (generator->is_closed()) {
251 status = "closed";
252 } else if (generator->is_executing()) {
253 status = "running";
254 } else {
255 DCHECK(generator->is_suspended());
256 }
257
259 isolate, result,
260 isolate->factory()->NewStringFromAsciiChecked("[[GeneratorState]]"),
261 isolate->factory()->NewStringFromAsciiChecked(status));
263 isolate, result,
264 isolate->factory()->NewStringFromAsciiChecked("[[GeneratorFunction]]"),
265 direct_handle(generator->function(), isolate));
267 isolate, result,
268 isolate->factory()->NewStringFromAsciiChecked("[[GeneratorReceiver]]"),
269 direct_handle(generator->receiver(), isolate));
270 } else if (IsJSPromise(*object)) {
271 auto promise = Cast<JSPromise>(object);
272
274 isolate, result,
275 isolate->factory()->NewStringFromAsciiChecked("[[PromiseState]]"),
276 isolate->factory()->NewStringFromAsciiChecked(
277 JSPromise::Status(promise->status())));
279 isolate, result,
280 isolate->factory()->NewStringFromAsciiChecked("[[PromiseResult]]"),
281 promise->status() == Promise::kPending
282 ? isolate->factory()->undefined_value()
283 : direct_handle(promise->result(), isolate));
284 } else if (IsJSProxy(*object)) {
285 auto js_proxy = Cast<JSProxy>(object);
286
288 isolate, result,
289 isolate->factory()->NewStringFromAsciiChecked("[[Handler]]"),
290 direct_handle(js_proxy->handler(), isolate));
292 isolate, result,
293 isolate->factory()->NewStringFromAsciiChecked("[[Target]]"),
294 direct_handle(js_proxy->target(), isolate));
296 isolate, result,
297 isolate->factory()->NewStringFromAsciiChecked("[[IsRevoked]]"),
298 isolate->factory()->ToBoolean(js_proxy->IsRevoked()));
299 } else if (IsJSPrimitiveWrapper(*object)) {
300 auto js_value = Cast<JSPrimitiveWrapper>(object);
301
303 isolate, result,
304 isolate->factory()->NewStringFromAsciiChecked("[[PrimitiveValue]]"),
305 direct_handle(js_value->value(), isolate));
306 } else if (IsJSWeakRef(*object)) {
307 auto js_weak_ref = Cast<JSWeakRef>(object);
308
310 isolate, result,
311 isolate->factory()->NewStringFromAsciiChecked("[[WeakRefTarget]]"),
312 direct_handle(js_weak_ref->target(), isolate));
313 } else if (IsJSArrayBuffer(*object)) {
314 DirectHandle<JSArrayBuffer> js_array_buffer = Cast<JSArrayBuffer>(object);
315 if (js_array_buffer->was_detached()) {
316 // Mark a detached JSArrayBuffer and such and don't even try to
317 // create views for it, since the TypedArray constructors will
318 // throw a TypeError when the underlying buffer is detached.
320 isolate, result,
321 isolate->factory()->NewStringFromAsciiChecked("[[IsDetached]]"),
322 isolate->factory()->true_value());
323 } else {
324 const size_t byte_length = js_array_buffer->byte_length();
325 static_assert(JSTypedArray::kMaxByteLength ==
327 using DataView = std::tuple<const char*, ExternalArrayType, size_t>;
328 for (auto [name, type, elem_size] :
329 {DataView{"[[Int8Array]]", kExternalInt8Array, 1},
330 DataView{"[[Uint8Array]]", kExternalUint8Array, 1},
331 DataView{"[[Int16Array]]", kExternalInt16Array, 2},
332 DataView{"[[Int32Array]]", kExternalInt32Array, 4}}) {
333 if ((byte_length % elem_size) != 0) continue;
334 size_t length = byte_length / elem_size;
335 result =
336 ArrayList::Add(isolate, result,
337 isolate->factory()->NewStringFromAsciiChecked(name),
338 isolate->factory()->NewJSTypedArray(
339 type, js_array_buffer, 0, length));
340 }
341 result =
342 ArrayList::Add(isolate, result,
343 isolate->factory()->NewStringFromAsciiChecked(
344 "[[ArrayBufferByteLength]]"),
345 isolate->factory()->NewNumberFromSize(byte_length));
346
347 auto backing_store = js_array_buffer->GetBackingStore();
348 DirectHandle<Object> array_buffer_data;
349 if (backing_store) {
350 array_buffer_data =
351 isolate->factory()->NewNumberFromUint(backing_store->id());
352 } else {
353 array_buffer_data = isolate->factory()->null_value();
354 }
356 isolate, result,
357 isolate->factory()->NewStringFromAsciiChecked("[[ArrayBufferData]]"),
358 array_buffer_data);
359
360 DirectHandle<Symbol> memory_symbol =
361 isolate->factory()->array_buffer_wasm_memory_symbol();
362 DirectHandle<Object> memory_object =
363 JSObject::GetDataProperty(isolate, js_array_buffer, memory_symbol);
364 if (!IsUndefined(*memory_object, isolate)) {
365 result = ArrayList::Add(isolate, result,
366 isolate->factory()->NewStringFromAsciiChecked(
367 "[[WebAssemblyMemory]]"),
368 memory_object);
369 }
370 }
371#if V8_ENABLE_WEBASSEMBLY
372 } else if (IsWasmInstanceObject(*object)) {
374 isolate, result, Cast<WasmInstanceObject>(object));
375 } else if (IsWasmModuleObject(*object)) {
377 isolate, result, Cast<WasmModuleObject>(object));
378 } else if (IsWasmTableObject(*object)) {
380 isolate, result, Cast<WasmTableObject>(object));
381#endif // V8_ENABLE_WEBASSEMBLY
382 }
383 return isolate->factory()->NewJSArrayWithElements(
385}
386
387RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
388 HandleScope scope(isolate);
389 DCHECK_EQ(1, args.length());
390
391 if (!IsJSGeneratorObject(args[0])) return Smi::zero();
392
393 // Check arguments.
395
396 // Only inspect suspended generator scopes.
397 if (!gen->is_suspended()) {
398 return Smi::zero();
399 }
400
401 // Count the visible scopes.
402 int n = 0;
403 for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
404 n++;
405 }
406
407 return Smi::FromInt(n);
408}
409
410RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
411 HandleScope scope(isolate);
412 DCHECK_EQ(2, args.length());
413
414 if (!IsJSGeneratorObject(args[0])) {
415 return ReadOnlyRoots(isolate).undefined_value();
416 }
417
418 // Check arguments.
420 int index = NumberToInt32(args[1]);
421
422 // Only inspect suspended generator scopes.
423 if (!gen->is_suspended()) {
424 return ReadOnlyRoots(isolate).undefined_value();
425 }
426
427 // Find the requested scope.
428 int n = 0;
429 ScopeIterator it(isolate, gen);
430 for (; !it.Done() && n < index; it.Next()) {
431 n++;
432 }
433 if (it.Done()) {
434 return ReadOnlyRoots(isolate).undefined_value();
435 }
436
437 return *it.MaterializeScopeDetails();
438}
439
440static bool SetScopeVariableValue(ScopeIterator* it, int index,
441 Handle<String> variable_name,
442 DirectHandle<Object> new_value) {
443 for (int n = 0; !it->Done() && n < index; it->Next()) {
444 n++;
445 }
446 if (it->Done()) {
447 return false;
448 }
449 return it->SetVariableValue(variable_name, new_value);
450}
451
452// Change variable value in closure or local scope
453// args[0]: number or JsFunction: break id or function
454// args[1]: number: scope index
455// args[2]: string: variable name
456// args[3]: object: new value
457//
458// Return true if success and false otherwise
459RUNTIME_FUNCTION(Runtime_SetGeneratorScopeVariableValue) {
460 HandleScope scope(isolate);
461 DCHECK_EQ(4, args.length());
463 int index = NumberToInt32(args[1]);
464 Handle<String> variable_name = args.at<String>(2);
465 DirectHandle<Object> new_value = args.at(3);
466 ScopeIterator it(isolate, gen);
467 bool res = SetScopeVariableValue(&it, index, variable_name, new_value);
468 return isolate->heap()->ToBoolean(res);
469}
470
471RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
472 HandleScope scope(isolate);
473 DCHECK_EQ(1, args.length());
474 CHECK(isolate->debug()->is_active());
476
477 DirectHandle<SharedFunctionInfo> shared(fun->shared(), isolate);
478 // Find the number of break points
479 DirectHandle<Object> break_locations =
480 Debug::GetSourceBreakLocations(isolate, shared);
481 if (IsUndefined(*break_locations, isolate)) {
482 return ReadOnlyRoots(isolate).undefined_value();
483 }
484 // Return array as JS array
485 return *isolate->factory()->NewJSArrayWithElements(
486 Cast<FixedArray>(break_locations));
487}
488
489// Returns the state of break on exceptions
490// args[0]: boolean indicating uncaught exceptions
491RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
492 HandleScope scope(isolate);
493 DCHECK_EQ(1, args.length());
494 uint32_t type_arg = NumberToUint32(args[0]);
495
496 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
497 bool result = isolate->debug()->IsBreakOnException(type);
498 return Smi::FromInt(result);
499}
500
501// Clear all stepping set by PrepareStep.
502RUNTIME_FUNCTION(Runtime_ClearStepping) {
503 HandleScope scope(isolate);
504 DCHECK_EQ(0, args.length());
505 CHECK(isolate->debug()->is_active());
506 isolate->debug()->ClearStepping();
507 return ReadOnlyRoots(isolate).undefined_value();
508}
509
510RUNTIME_FUNCTION(Runtime_DebugGetLoadedScriptIds) {
511 HandleScope scope(isolate);
512 DCHECK_EQ(0, args.length());
513
514 DirectHandle<FixedArray> instances;
515 {
516 DebugScope debug_scope(isolate->debug());
517 // Fill the script objects.
518 instances = isolate->debug()->GetLoadedScripts();
519 }
520
521 // Convert the script objects to proper JS objects.
522 for (int i = 0; i < instances->length(); i++) {
523 DirectHandle<Script> script(Cast<Script>(instances->get(i)), isolate);
524 instances->set(i, Smi::FromInt(script->id()));
525 }
526
527 // Return result as a JS array.
528 return *isolate->factory()->NewJSArrayWithElements(instances);
529}
530
531RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
532 SealHandleScope shs(isolate);
533 DCHECK_EQ(1, args.length());
534
535 Tagged<Object> f = args[0];
536 if (IsJSFunction(f)) {
537 return Cast<JSFunction>(f)->shared()->inferred_name();
538 }
539 return ReadOnlyRoots(isolate).empty_string();
540}
541
542// Performs a GC.
543// Presently, it only does a full GC.
544RUNTIME_FUNCTION(Runtime_CollectGarbage) {
545 SealHandleScope shs(isolate);
546 DCHECK_EQ(1, args.length());
547 isolate->heap()->PreciseCollectAllGarbage(GCFlag::kNoFlags,
549 return ReadOnlyRoots(isolate).undefined_value();
550}
551
552namespace {
553
554int ScriptLinePosition(DirectHandle<Script> script, int line) {
555 if (line < 0) return -1;
556
557#if V8_ENABLE_WEBASSEMBLY
558 if (script->type() == Script::Type::kWasm) {
559 // Wasm positions are relative to the start of the module.
560 return 0;
561 }
562#endif // V8_ENABLE_WEBASSEMBLY
563
564 Script::InitLineEnds(script->GetIsolate(), script);
565
566 Tagged<FixedArray> line_ends_array = Cast<FixedArray>(script->line_ends());
567 const int line_count = line_ends_array->length();
568 DCHECK_LT(0, line_count);
569
570 if (line == 0) return 0;
571 // If line == line_count, we return the first position beyond the last line.
572 if (line > line_count) return -1;
573 return Smi::ToInt(line_ends_array->get(line - 1)) + 1;
574}
575
576int ScriptLinePositionWithOffset(DirectHandle<Script> script, int line,
577 int offset) {
578 if (line < 0 || offset < 0) return -1;
579
580 if (line == 0 || offset == 0)
581 return ScriptLinePosition(script, line) + offset;
582
583 Script::PositionInfo info;
584 if (!Script::GetPositionInfo(script, offset, &info,
586 return -1;
587 }
588
589 const int total_line = info.line + line;
590 return ScriptLinePosition(script, total_line);
591}
592
593DirectHandle<Object> GetJSPositionInfo(DirectHandle<Script> script,
594 int position,
595 Script::OffsetFlag offset_flag,
596 Isolate* isolate) {
597 Script::PositionInfo info;
598 if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
599 return isolate->factory()->null_value();
600 }
601
602#if V8_ENABLE_WEBASSEMBLY
603 const bool is_wasm_script = script->type() == Script::Type::kWasm;
604#else
605 const bool is_wasm_script = false;
606#endif // V8_ENABLE_WEBASSEMBLY
607 DirectHandle<String> sourceText =
608 is_wasm_script ? isolate->factory()->empty_string()
609 : isolate->factory()->NewSubString(
610 handle(Cast<String>(script->source()), isolate),
611 info.line_start, info.line_end);
612
613 DirectHandle<JSObject> jsinfo =
614 isolate->factory()->NewJSObject(isolate->object_function());
615
616 JSObject::AddProperty(isolate, jsinfo, isolate->factory()->script_string(),
617 script, NONE);
618 JSObject::AddProperty(isolate, jsinfo, isolate->factory()->position_string(),
620 JSObject::AddProperty(isolate, jsinfo, isolate->factory()->line_string(),
621 direct_handle(Smi::FromInt(info.line), isolate), NONE);
622 JSObject::AddProperty(isolate, jsinfo, isolate->factory()->column_string(),
623 direct_handle(Smi::FromInt(info.column), isolate),
624 NONE);
625 JSObject::AddProperty(isolate, jsinfo,
626 isolate->factory()->sourceText_string(), sourceText,
627 NONE);
628
629 return jsinfo;
630}
631
632DirectHandle<Object> ScriptLocationFromLine(Isolate* isolate,
633 DirectHandle<Script> script,
634 DirectHandle<Object> opt_line,
635 DirectHandle<Object> opt_column,
636 int32_t offset) {
637 // Line and column are possibly undefined and we need to handle these cases,
638 // additionally subtracting corresponding offsets.
639
640 int32_t line = 0;
641 if (!IsNullOrUndefined(*opt_line, isolate)) {
642 CHECK(IsNumber(*opt_line));
643 line = NumberToInt32(*opt_line) - script->line_offset();
644 }
645
646 int32_t column = 0;
647 if (!IsNullOrUndefined(*opt_column, isolate)) {
648 CHECK(IsNumber(*opt_column));
649 column = NumberToInt32(*opt_column);
650 if (line == 0) column -= script->column_offset();
651 }
652
653 int line_position = ScriptLinePositionWithOffset(script, line, offset);
654 if (line_position < 0 || column < 0) return isolate->factory()->null_value();
655
656 return GetJSPositionInfo(script, line_position + column,
658}
659
660// Slow traversal over all scripts on the heap.
661bool GetScriptById(Isolate* isolate, int needle, DirectHandle<Script>* result) {
662 Script::Iterator iterator(isolate);
663 for (Tagged<Script> script = iterator.Next(); !script.is_null();
664 script = iterator.Next()) {
665 if (script->id() == needle) {
666 *result = direct_handle(script, isolate);
667 return true;
668 }
669 }
670
671 return false;
672}
673
674} // namespace
675
676// TODO(5530): Rename once conflicting function has been deleted.
677RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
678 HandleScope scope(isolate);
679 DCHECK_EQ(4, args.length());
680 int32_t scriptid = NumberToInt32(args[0]);
681 DirectHandle<Object> opt_line = args.at(1);
682 DirectHandle<Object> opt_column = args.at(2);
683 int32_t offset = NumberToInt32(args[3]);
684
686 CHECK(GetScriptById(isolate, scriptid, &script));
687
688 return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset);
689}
690
691// On function call, depending on circumstances, prepare for stepping in,
692// or perform a side effect check.
693RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
694 HandleScope scope(isolate);
695 DCHECK_EQ(2, args.length());
698 if (isolate->debug()->needs_check_on_function_call()) {
699 // Ensure that the callee will perform debug check on function call too.
700 DirectHandle<SharedFunctionInfo> shared(fun->shared(), isolate);
701 isolate->debug()->DeoptimizeFunction(shared);
702 if (isolate->debug()->last_step_action() >= StepInto ||
703 isolate->debug()->break_on_next_function_call()) {
704 DCHECK_EQ(isolate->debug_execution_mode(), DebugInfo::kBreakpoints);
705 isolate->debug()->PrepareStepIn(fun);
706 }
707 if (isolate->debug_execution_mode() == DebugInfo::kSideEffects &&
708 !isolate->debug()->PerformSideEffectCheck(fun, receiver)) {
709 return ReadOnlyRoots(isolate).exception();
710 }
711 }
712 return ReadOnlyRoots(isolate).undefined_value();
713}
714
715// Set one shot breakpoints for the suspended generator object.
716RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
717 HandleScope scope(isolate);
718 DCHECK_EQ(0, args.length());
719 isolate->debug()->PrepareStepInSuspendedGenerator();
720 return ReadOnlyRoots(isolate).undefined_value();
721}
722
723namespace {
724DirectHandle<JSObject> MakeRangeObject(Isolate* isolate,
725 const CoverageBlock& range) {
726 Factory* factory = isolate->factory();
727
728 DirectHandle<String> start_string = factory->InternalizeUtf8String("start");
729 DirectHandle<String> end_string = factory->InternalizeUtf8String("end");
730 DirectHandle<String> count_string = factory->InternalizeUtf8String("count");
731
732 DirectHandle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
733 JSObject::AddProperty(isolate, range_obj, start_string,
734 factory->NewNumberFromInt(range.start), NONE);
735 JSObject::AddProperty(isolate, range_obj, end_string,
736 factory->NewNumberFromInt(range.end), NONE);
737 JSObject::AddProperty(isolate, range_obj, count_string,
738 factory->NewNumberFromUint(range.count), NONE);
739
740 return range_obj;
741}
742} // namespace
743
744RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
745 HandleScope scope(isolate);
746 DCHECK_EQ(0, args.length());
747 // Collect coverage data.
748 std::unique_ptr<Coverage> coverage;
749 if (isolate->is_best_effort_code_coverage()) {
750 coverage = Coverage::CollectBestEffort(isolate);
751 } else {
752 coverage = Coverage::CollectPrecise(isolate);
753 }
754 Factory* factory = isolate->factory();
755 // Turn the returned data structure into JavaScript.
756 // Create an array of scripts.
757 int num_scripts = static_cast<int>(coverage->size());
758 // Prepare property keys.
759 DirectHandle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
760 DirectHandle<String> script_string = factory->script_string();
761 for (int i = 0; i < num_scripts; i++) {
762 const auto& script_data = coverage->at(i);
763 HandleScope inner_scope(isolate);
764
765 std::vector<CoverageBlock> ranges;
766 int num_functions = static_cast<int>(script_data.functions.size());
767 for (int j = 0; j < num_functions; j++) {
768 const auto& function_data = script_data.functions[j];
769 ranges.emplace_back(function_data.start, function_data.end,
770 function_data.count);
771 for (size_t k = 0; k < function_data.blocks.size(); k++) {
772 const auto& block_data = function_data.blocks[k];
773 ranges.emplace_back(block_data.start, block_data.end, block_data.count);
774 }
775 }
776
777 int num_ranges = static_cast<int>(ranges.size());
778 DirectHandle<FixedArray> ranges_array = factory->NewFixedArray(num_ranges);
779 for (int j = 0; j < num_ranges; j++) {
780 DirectHandle<JSObject> range_object = MakeRangeObject(isolate, ranges[j]);
781 ranges_array->set(j, *range_object);
782 }
783
784 DirectHandle<JSArray> script_obj =
785 factory->NewJSArrayWithElements(ranges_array, PACKED_ELEMENTS);
786 JSObject::AddProperty(isolate, script_obj, script_string,
787 direct_handle(script_data.script->source(), isolate),
788 NONE);
789 scripts_array->set(i, *script_obj);
790 }
791 return *factory->NewJSArrayWithElements(scripts_array, PACKED_ELEMENTS);
792}
793
794RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
795 SealHandleScope shs(isolate);
796 bool enable = Cast<Boolean>(args[0])->ToBool(isolate);
799 return ReadOnlyRoots(isolate).undefined_value();
800}
801
802RUNTIME_FUNCTION(Runtime_DebugToggleBlockCoverage) {
803 SealHandleScope shs(isolate);
804 bool enable = Cast<Boolean>(args[0])->ToBool(isolate);
807 return ReadOnlyRoots(isolate).undefined_value();
808}
809
810RUNTIME_FUNCTION(Runtime_IncBlockCounter) {
811 UNREACHABLE(); // Never called. See the IncBlockCounter builtin instead.
812}
813
814RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionSuspended) {
815 DCHECK_EQ(4, args.length());
816 HandleScope scope(isolate);
817 DirectHandle<JSPromise> promise = args.at<JSPromise>(0);
818 DirectHandle<JSPromise> outer_promise = args.at<JSPromise>(1);
819 DirectHandle<JSFunction> reject_handler = args.at<JSFunction>(2);
821
822 // Allocate the throwaway promise and fire the appropriate init
823 // hook for the throwaway promise (passing the {promise} as its
824 // parent).
825 DirectHandle<JSPromise> throwaway =
826 isolate->factory()->NewJSPromiseWithoutHook();
827 isolate->OnAsyncFunctionSuspended(throwaway, promise);
828
829 // The Promise will be thrown away and not handled, but it
830 // shouldn't trigger unhandled reject events as its work is done
831 throwaway->set_has_handler(true);
832
833 // Enable proper debug support for promises.
834 if (isolate->debug()->is_active()) {
835 Object::SetProperty(isolate, reject_handler,
836 isolate->factory()->promise_forwarding_handler_symbol(),
837 isolate->factory()->true_value(),
840 .Check();
841
842 // Mark the dependency to {outer_promise} in case the {throwaway}
843 // Promise is found on the Promise stack
844 Object::SetProperty(isolate, throwaway,
845 isolate->factory()->promise_handled_by_symbol(),
846 outer_promise, StoreOrigin::kMaybeKeyed,
848 .Check();
849
850 DirectHandle<WeakFixedArray> awaited_by_holder(
851 isolate->factory()->NewWeakFixedArray(1));
852 awaited_by_holder->set(0, MakeWeak(*generator));
853 Object::SetProperty(isolate, promise,
854 isolate->factory()->promise_awaited_by_symbol(),
855 awaited_by_holder, StoreOrigin::kMaybeKeyed,
857 .Check();
858 }
859
860 return *throwaway;
861}
862
863RUNTIME_FUNCTION(Runtime_DebugPromiseThen) {
864 DCHECK_EQ(1, args.length());
865 HandleScope scope(isolate);
867 if (IsJSPromise(*promise)) {
868 isolate->OnPromiseThen(Cast<JSPromise>(promise));
869 }
870 return *promise;
871}
872
873RUNTIME_FUNCTION(Runtime_LiveEditPatchScript) {
874 HandleScope scope(isolate);
875 DCHECK_EQ(2, args.length());
876 DirectHandle<JSFunction> script_function = args.at<JSFunction>(0);
877 Handle<String> new_source = args.at<String>(1);
878
879 Handle<Script> script(Cast<Script>(script_function->shared()->script()),
880 isolate);
882 LiveEdit::PatchScript(isolate, script, new_source, /* preview */ false,
883 /* allow_top_frame_live_editing */ false, &result);
884 switch (result.status) {
886 return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
887 "LiveEdit failed: COMPILE_ERROR"));
889 return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
890 "LiveEdit failed: BLOCKED_BY_RUNNING_GENERATOR"));
892 return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
893 "LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION"));
895 return isolate->Throw(*isolate->factory()->NewStringFromAsciiChecked(
896 "LiveEdit failed: BLOCKED_BY_TOP_LEVEL_ES_MODULE_CHANGE"));
898 return ReadOnlyRoots(isolate).undefined_value();
899 }
900 return ReadOnlyRoots(isolate).undefined_value();
901}
902
903RUNTIME_FUNCTION(Runtime_ProfileCreateSnapshotDataBlob) {
904 HandleScope scope(isolate);
905 DCHECK_EQ(0, args.length());
906
907 // Used only by the test/memory/Memory.json benchmark. This creates a snapshot
908 // blob and outputs various statistics around it.
909
910 DCHECK(v8_flags.profile_deserialization && v8_flags.serialization_statistics);
911
913
914 static constexpr char* kNoEmbeddedSource = nullptr;
915 // We use this flag to tell the serializer not to finalize/seal RO space -
916 // this already happened after deserializing the main Isolate.
917 static constexpr Snapshot::SerializerFlags kSerializerFlags =
921 kSerializerFlags);
922 delete[] blob.data;
923
924 // Track the embedded blob size as well.
925 {
926 i::EmbeddedData d = i::EmbeddedData::FromBlob(isolate);
927 PrintF("Embedded blob is %d bytes\n",
928 static_cast<int>(d.code_size() + d.data_size()));
929 }
930
932
933 return ReadOnlyRoots(isolate).undefined_value();
934}
935
936} // namespace internal
937} // namespace v8
Builtins::Kind kind
Definition builtins.cc:40
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE DirectHandle< FixedArray > ToFixedArray(Isolate *isolate, DirectHandle< ArrayList > array, AllocationType allocation=AllocationType::kYoung)
static DirectHandle< ArrayList > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
static std::unique_ptr< Coverage > CollectPrecise(Isolate *isolate)
static V8_EXPORT_PRIVATE void SelectMode(Isolate *isolate, debug::CoverageMode mode)
static std::unique_ptr< Coverage > CollectBestEffort(Isolate *isolate)
static DirectHandle< Object > GetSourceBreakLocations(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
Definition debug.cc:1614
Handle< FixedArray > NewFixedArray(int length, AllocationType allocation=AllocationType::kYoung)
Handle< JSArray > NewJSArrayWithElements(DirectHandle< FixedArrayBase > elements, ElementsKind elements_kind, int length, AllocationType allocation=AllocationType::kYoung)
Definition factory.cc:3228
void PatchBytecodeArray(Tagged< BytecodeArray > bytecode_array)
Definition frames.cc:3344
int GetBytecodeOffset() const override
Definition frames.cc:3326
static constexpr size_t kMaxByteLength
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static const char * Status(Promise::PromiseState status)
Definition objects.cc:5005
static constexpr size_t kMaxByteLength
Tagged< JSFunction > function() const override
Definition frames.cc:2492
static void PatchScript(Isolate *isolate, Handle< Script > script, Handle< String > source, bool preview, bool allow_top_frame_live_editing, debug::LiveEditResult *result)
Definition liveedit.cc:834
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > SetProperty(LookupIterator *it, DirectHandle< Object > value, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
Definition objects.cc:2439
Tagged< T > GetCurrent() const
Definition prototype.h:52
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< JSArray > GetInternalProperties(Isolate *isolate, DirectHandle< Object >)
static void InitLineEnds(Isolate *isolate, DirectHandle< Script > script)
Definition script-inl.h:201
static bool GetPositionInfo(DirectHandle< Script > script, int position, PositionInfo *info, OffsetFlag offset_flag=OffsetFlag::kWithOffset)
Definition objects.cc:4367
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
Handle< SharedFunctionInfo > info
#define RUNTIME_FUNCTION_RETURN_PAIR(Name)
Definition arguments.h:166
#define RUNTIME_FUNCTION(Name)
Definition arguments.h:162
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
int32_t offset
TNode< Object > receiver
SharedFunctionInfoRef shared
ZoneVector< RpoNumber > & result
int position
Definition liveedit.cc:290
int n
Definition mul-fft.cc:296
int int32_t
Definition unicode.cc:40
void BreakRightNow(Isolate *v8_isolate, base::EnumSet< debug::BreakReason > break_reasons)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
@ kIgnoreIfTopFrameBlackboxed
Definition debug.h:66
void FreeCurrentEmbeddedBlob()
Definition isolate.cc:286
DirectHandle< ArrayList > AddWasmModuleObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmModuleObject > module_object)
bool IsNumber(Tagged< Object > obj)
void PrintF(const char *format,...)
Definition utils.cc:39
Tagged(T object) -> Tagged< T >
static ObjectPair MakePair(Tagged< Object > x, Tagged< Object > y)
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
ExceptionBreakType
Definition debug.h:47
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
bool IsNullOrUndefined(Tagged< Object > obj, Isolate *isolate)
uint32_t NumberToUint32(Tagged< Object > number)
DirectHandle< ArrayList > AddWasmInstanceObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmInstanceObject > instance)
int32_t NumberToInt32(Tagged< Object > number)
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
Definition tagged.h:893
DirectHandle< ArrayList > AddWasmTableObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmTableObject > table)
static bool SetScopeVariableValue(ScopeIterator *it, int index, Handle< String > variable_name, DirectHandle< Object > new_value)
V8_EXPORT_PRIVATE FlagValues v8_flags
void DisableEmbeddedBlobRefcounting()
Definition isolate.cc:281
@ kExternalInt32Array
Definition globals.h:2457
@ kExternalInt8Array
Definition globals.h:2453
@ kExternalUint8Array
Definition globals.h:2454
@ kExternalInt16Array
Definition globals.h:2455
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
v8::StartupData CreateSnapshotDataBlobInternal(v8::SnapshotCreator::FunctionCodeHandling function_code_handling, const char *embedded_source, SnapshotCreator &snapshot_creator, Snapshot::SerializerFlags serializer_flags)
Definition snapshot.cc:784
kInterpreterTrampolineOffset script
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
BodyGen * gen
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485