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 "src/runtime/runtime-utils.h"
6 :
7 : #include "src/arguments.h"
8 : #include "src/compiler.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/frames-inl.h"
16 : #include "src/globals.h"
17 : #include "src/interpreter/bytecodes.h"
18 : #include "src/interpreter/interpreter.h"
19 : #include "src/isolate-inl.h"
20 : #include "src/runtime/runtime.h"
21 : #include "src/wasm/wasm-module.h"
22 : #include "src/wasm/wasm-objects.h"
23 :
24 : namespace v8 {
25 : namespace internal {
26 :
27 151614 : RUNTIME_FUNCTION(Runtime_DebugBreak) {
28 : SealHandleScope shs(isolate);
29 : DCHECK_EQ(1, args.length());
30 25269 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
31 50538 : HandleScope scope(isolate);
32 50538 : ReturnValueScope result_scope(isolate->debug());
33 25269 : isolate->debug()->set_return_value(*value);
34 :
35 : // Get the top-most JavaScript frame.
36 50538 : JavaScriptFrameIterator it(isolate);
37 50538 : isolate->debug()->Break(it.frame());
38 25269 : return isolate->debug()->return_value();
39 : }
40 :
41 393318 : RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
42 : SealHandleScope shs(isolate);
43 : DCHECK_EQ(1, args.length());
44 65553 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
45 131106 : HandleScope scope(isolate);
46 131106 : ReturnValueScope result_scope(isolate->debug());
47 65553 : isolate->debug()->set_return_value(*value);
48 :
49 : // Get the top-most JavaScript frame.
50 131106 : JavaScriptFrameIterator it(isolate);
51 131106 : isolate->debug()->Break(it.frame());
52 :
53 : // Return the handler from the original bytecode array.
54 : DCHECK(it.frame()->is_interpreted());
55 : InterpretedFrame* interpreted_frame =
56 65553 : reinterpret_cast<InterpretedFrame*>(it.frame());
57 65553 : SharedFunctionInfo* shared = interpreted_frame->function()->shared();
58 65553 : BytecodeArray* bytecode_array = shared->bytecode_array();
59 65553 : int bytecode_offset = interpreted_frame->GetBytecodeOffset();
60 : interpreter::Bytecode bytecode =
61 65553 : interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
62 : return isolate->interpreter()->GetBytecodeHandler(
63 65553 : bytecode, interpreter::OperandScale::kSingle);
64 : }
65 :
66 :
67 24068 : RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
68 : SealHandleScope shs(isolate);
69 : DCHECK_EQ(0, args.length());
70 12034 : if (isolate->debug()->break_points_active()) {
71 12028 : isolate->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
72 : }
73 12034 : return isolate->heap()->undefined_value();
74 : }
75 :
76 :
77 : // Adds a JavaScript function as a debug event listener.
78 : // args[0]: debug event listener function to set or null or undefined for
79 : // clearing the event listener function
80 : // args[1]: object supplied during callback
81 483 : RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
82 : SealHandleScope shs(isolate);
83 : DCHECK_EQ(2, args.length());
84 378 : CHECK(args[0]->IsJSFunction() || args[0]->IsNullOrUndefined(isolate));
85 161 : CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
86 161 : CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
87 161 : if (callback->IsJSFunction()) {
88 : JavaScriptDebugDelegate* delegate = new JavaScriptDebugDelegate(
89 105 : isolate, Handle<JSFunction>::cast(callback), data);
90 105 : isolate->debug()->SetDebugDelegate(delegate, true);
91 : } else {
92 56 : isolate->debug()->SetDebugDelegate(nullptr, false);
93 : }
94 161 : return isolate->heap()->undefined_value();
95 : }
96 :
97 :
98 394 : RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
99 : SealHandleScope shs(isolate);
100 : DCHECK_EQ(0, args.length());
101 197 : isolate->stack_guard()->RequestDebugBreak();
102 197 : return isolate->heap()->undefined_value();
103 : }
104 :
105 :
106 10752064 : static Handle<Object> DebugGetProperty(LookupIterator* it,
107 : bool* has_caught = NULL) {
108 10751962 : for (; it->IsFound(); it->Next()) {
109 5375975 : switch (it->state()) {
110 : case LookupIterator::NOT_FOUND:
111 : case LookupIterator::TRANSITION:
112 0 : UNREACHABLE();
113 : case LookupIterator::ACCESS_CHECK:
114 : // Ignore access checks.
115 : break;
116 : case LookupIterator::INTEGER_INDEXED_EXOTIC:
117 : case LookupIterator::INTERCEPTOR:
118 : case LookupIterator::JSPROXY:
119 72 : return it->isolate()->factory()->undefined_value();
120 : case LookupIterator::ACCESSOR: {
121 30 : Handle<Object> accessors = it->GetAccessors();
122 30 : if (!accessors->IsAccessorInfo()) {
123 0 : return it->isolate()->factory()->undefined_value();
124 : }
125 : MaybeHandle<Object> maybe_result =
126 30 : JSObject::GetPropertyWithAccessor(it);
127 : Handle<Object> result;
128 30 : if (!maybe_result.ToHandle(&result)) {
129 12 : result = handle(it->isolate()->pending_exception(), it->isolate());
130 : it->isolate()->clear_pending_exception();
131 12 : if (has_caught != NULL) *has_caught = true;
132 : }
133 30 : return result;
134 : }
135 :
136 : case LookupIterator::DATA:
137 5375873 : return it->GetDataValue();
138 : }
139 : }
140 :
141 6 : return it->isolate()->factory()->undefined_value();
142 : }
143 :
144 : template <class IteratorType>
145 126 : static MaybeHandle<JSArray> GetIteratorInternalProperties(
146 : Isolate* isolate, Handle<IteratorType> object) {
147 : Factory* factory = isolate->factory();
148 : Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
149 126 : CHECK(iterator->kind()->IsSmi());
150 : const char* kind = NULL;
151 126 : switch (Smi::cast(iterator->kind())->value()) {
152 : case IteratorType::kKindKeys:
153 : kind = "keys";
154 : break;
155 : case IteratorType::kKindValues:
156 : kind = "values";
157 44 : break;
158 : case IteratorType::kKindEntries:
159 : kind = "entries";
160 62 : break;
161 : default:
162 0 : UNREACHABLE();
163 : }
164 :
165 126 : Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
166 : Handle<String> has_more =
167 126 : factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
168 126 : result->set(0, *has_more);
169 252 : result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
170 :
171 : Handle<String> index =
172 126 : factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
173 126 : result->set(2, *index);
174 126 : result->set(3, iterator->index());
175 :
176 : Handle<String> iterator_kind =
177 126 : factory->NewStringFromAsciiChecked("[[IteratorKind]]");
178 126 : result->set(4, *iterator_kind);
179 126 : Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
180 126 : result->set(5, *kind_str);
181 126 : return factory->NewJSArrayWithElements(result);
182 : }
183 :
184 :
185 106344 : MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
186 : Handle<Object> object) {
187 : Factory* factory = isolate->factory();
188 106344 : if (object->IsJSBoundFunction()) {
189 : Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
190 :
191 6 : Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
192 : Handle<String> target =
193 6 : factory->NewStringFromAsciiChecked("[[TargetFunction]]");
194 6 : result->set(0, *target);
195 6 : result->set(1, function->bound_target_function());
196 :
197 : Handle<String> bound_this =
198 6 : factory->NewStringFromAsciiChecked("[[BoundThis]]");
199 6 : result->set(2, *bound_this);
200 6 : result->set(3, function->bound_this());
201 :
202 : Handle<String> bound_args =
203 6 : factory->NewStringFromAsciiChecked("[[BoundArgs]]");
204 6 : result->set(4, *bound_args);
205 : Handle<FixedArray> bound_arguments =
206 6 : factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
207 : Handle<JSArray> arguments_array =
208 : factory->NewJSArrayWithElements(bound_arguments);
209 6 : result->set(5, *arguments_array);
210 : return factory->NewJSArrayWithElements(result);
211 106338 : } else if (object->IsJSMapIterator()) {
212 84 : Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
213 84 : return GetIteratorInternalProperties(isolate, iterator);
214 106254 : } else if (object->IsJSSetIterator()) {
215 42 : Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
216 42 : return GetIteratorInternalProperties(isolate, iterator);
217 106212 : } else if (object->IsJSGeneratorObject()) {
218 : Handle<JSGeneratorObject> generator =
219 : Handle<JSGeneratorObject>::cast(object);
220 :
221 : const char* status = "suspended";
222 54 : if (generator->is_closed()) {
223 : status = "closed";
224 42 : } else if (generator->is_executing()) {
225 : status = "running";
226 : } else {
227 : DCHECK(generator->is_suspended());
228 : }
229 :
230 54 : Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
231 : Handle<String> generator_status =
232 54 : factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
233 54 : result->set(0, *generator_status);
234 54 : Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
235 54 : result->set(1, *status_str);
236 :
237 : Handle<String> function =
238 54 : factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
239 54 : result->set(2, *function);
240 54 : result->set(3, generator->function());
241 :
242 : Handle<String> receiver =
243 54 : factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
244 54 : result->set(4, *receiver);
245 54 : result->set(5, generator->receiver());
246 : return factory->NewJSArrayWithElements(result);
247 106158 : } else if (object->IsJSPromise()) {
248 : Handle<JSPromise> promise = Handle<JSPromise>::cast(object);
249 30 : const char* status = JSPromise::Status(promise->status());
250 30 : Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
251 : Handle<String> promise_status =
252 30 : factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
253 30 : result->set(0, *promise_status);
254 30 : Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
255 30 : result->set(1, *status_str);
256 :
257 : Handle<Object> value_obj(promise->result(), isolate);
258 : Handle<String> promise_value =
259 30 : factory->NewStringFromAsciiChecked("[[PromiseValue]]");
260 30 : result->set(2, *promise_value);
261 30 : result->set(3, *value_obj);
262 : return factory->NewJSArrayWithElements(result);
263 106128 : } else if (object->IsJSProxy()) {
264 : Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
265 0 : Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
266 :
267 : Handle<String> handler_str =
268 0 : factory->NewStringFromAsciiChecked("[[Handler]]");
269 0 : result->set(0, *handler_str);
270 0 : result->set(1, js_proxy->handler());
271 :
272 : Handle<String> target_str =
273 0 : factory->NewStringFromAsciiChecked("[[Target]]");
274 0 : result->set(2, *target_str);
275 0 : result->set(3, js_proxy->target());
276 :
277 : Handle<String> is_revoked_str =
278 0 : factory->NewStringFromAsciiChecked("[[IsRevoked]]");
279 0 : result->set(4, *is_revoked_str);
280 0 : result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
281 : return factory->NewJSArrayWithElements(result);
282 106128 : } else if (object->IsJSValue()) {
283 : Handle<JSValue> js_value = Handle<JSValue>::cast(object);
284 :
285 152 : Handle<FixedArray> result = factory->NewFixedArray(2);
286 : Handle<String> primitive_value =
287 152 : factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
288 152 : result->set(0, *primitive_value);
289 152 : result->set(1, js_value->value());
290 : return factory->NewJSArrayWithElements(result);
291 : }
292 105976 : return factory->NewJSArray(0);
293 : }
294 :
295 :
296 0 : RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
297 0 : HandleScope scope(isolate);
298 : DCHECK_EQ(1, args.length());
299 0 : CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
300 0 : RETURN_RESULT_OR_FAILURE(isolate,
301 0 : Runtime::GetInternalProperties(isolate, obj));
302 : }
303 :
304 :
305 : // Get debugger related details for an object property, in the following format:
306 : // 0: Property value
307 : // 1: Property details
308 : // 2: Property value is exception
309 : // 3: Getter function if defined
310 : // 4: Setter function if defined
311 : // Items 2-4 are only filled if the property has either a getter or a setter.
312 21503888 : RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
313 5376029 : HandleScope scope(isolate);
314 : DCHECK_EQ(2, args.length());
315 10752058 : CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
316 5376029 : CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
317 :
318 : // Convert the {name_obj} to a Name.
319 : Handle<Name> name;
320 10752058 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
321 : Object::ToName(isolate, name_obj));
322 :
323 : // Make sure to set the current context to the context before the debugger was
324 : // entered (if the debugger is entered). The reason for switching context here
325 : // is that for some property lookups (accessors and interceptors) callbacks
326 : // into the embedding application can occour, and the embedding application
327 : // could have the assumption that its own native context is the current
328 : // context and not some internal debugger context.
329 10752058 : SaveContext save(isolate);
330 5376029 : if (isolate->debug()->in_debug_scope()) {
331 10751602 : isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
332 : }
333 :
334 : // Check if the name is trivially convertible to an index and get the element
335 : // if so.
336 : uint32_t index;
337 : // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
338 : // this special case.
339 5376029 : if (name->AsArrayIndex(&index)) {
340 48 : Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
341 : Handle<Object> element_or_char;
342 144 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
343 : isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
344 48 : details->set(0, *element_or_char);
345 96 : details->set(1, PropertyDetails::Empty().AsSmi());
346 96 : return *isolate->factory()->NewJSArrayWithElements(details);
347 : }
348 :
349 5375981 : LookupIterator it(obj, name, LookupIterator::OWN);
350 5375981 : bool has_caught = false;
351 5375981 : Handle<Object> value = DebugGetProperty(&it, &has_caught);
352 5375981 : if (!it.IsFound()) return isolate->heap()->undefined_value();
353 :
354 : Handle<Object> maybe_pair;
355 5375975 : if (it.state() == LookupIterator::ACCESSOR) {
356 30 : maybe_pair = it.GetAccessors();
357 : }
358 :
359 : // If the callback object is a fixed array then it contains JavaScript
360 : // getter and/or setter.
361 5376005 : bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
362 : Handle<FixedArray> details =
363 5375975 : isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
364 5375975 : details->set(0, *value);
365 : // TODO(verwaest): Get rid of this random way of handling interceptors.
366 5375975 : PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
367 : ? PropertyDetails::Empty()
368 5375975 : : it.property_details();
369 10751950 : details->set(1, d.AsSmi());
370 : details->set(
371 10751950 : 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
372 5375975 : if (has_js_accessors) {
373 0 : Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
374 0 : details->set(3, isolate->heap()->ToBoolean(has_caught));
375 : Handle<Object> getter =
376 0 : AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
377 : Handle<Object> setter =
378 0 : AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
379 0 : details->set(4, *getter);
380 0 : details->set(5, *setter);
381 : }
382 :
383 16127979 : return *isolate->factory()->NewJSArrayWithElements(details);
384 : }
385 :
386 :
387 0 : RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
388 0 : HandleScope scope(isolate);
389 :
390 : DCHECK_EQ(2, args.length());
391 :
392 0 : CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
393 0 : CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
394 :
395 0 : LookupIterator it(obj, name);
396 0 : return *DebugGetProperty(&it);
397 : }
398 :
399 : // Return the property kind calculated from the property details.
400 : // args[0]: smi with property details.
401 0 : RUNTIME_FUNCTION(Runtime_DebugPropertyKindFromDetails) {
402 : SealHandleScope shs(isolate);
403 : DCHECK_EQ(1, args.length());
404 0 : CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
405 0 : return Smi::FromInt(static_cast<int>(details.kind()));
406 : }
407 :
408 :
409 : // Return the property attribute calculated from the property details.
410 : // args[0]: smi with property details.
411 0 : RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
412 : SealHandleScope shs(isolate);
413 : DCHECK_EQ(1, args.length());
414 0 : CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
415 0 : return Smi::FromInt(static_cast<int>(details.attributes()));
416 : }
417 :
418 :
419 16520943 : RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
420 : SealHandleScope shs(isolate);
421 : DCHECK_EQ(1, args.length());
422 11013962 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
423 5506981 : CHECK(isolate->debug()->CheckExecutionState(break_id));
424 5506981 : return isolate->heap()->true_value();
425 : }
426 :
427 :
428 1853056 : RUNTIME_FUNCTION(Runtime_GetFrameCount) {
429 463264 : HandleScope scope(isolate);
430 : DCHECK_EQ(1, args.length());
431 926528 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
432 463264 : CHECK(isolate->debug()->CheckExecutionState(break_id));
433 :
434 : // Count all frames which are relevant to debugging stack trace.
435 : int n = 0;
436 463264 : StackFrame::Id id = isolate->debug()->break_frame_id();
437 463264 : if (id == StackFrame::NO_ID) {
438 : // If there is no JavaScript stack frame count is 0.
439 : return Smi::kZero;
440 : }
441 :
442 463234 : List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
443 5384654 : for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
444 : frames.Clear();
445 4921420 : it.frame()->Summarize(&frames);
446 9851013 : for (int i = frames.length() - 1; i >= 0; i--) {
447 : // Omit functions from native and extension scripts.
448 4929593 : if (frames[i].is_subject_to_debugging()) n++;
449 : }
450 463234 : }
451 926498 : return Smi::FromInt(n);
452 : }
453 :
454 : static const int kFrameDetailsFrameIdIndex = 0;
455 : static const int kFrameDetailsReceiverIndex = 1;
456 : static const int kFrameDetailsFunctionIndex = 2;
457 : static const int kFrameDetailsScriptIndex = 3;
458 : static const int kFrameDetailsArgumentCountIndex = 4;
459 : static const int kFrameDetailsLocalCountIndex = 5;
460 : static const int kFrameDetailsSourcePositionIndex = 6;
461 : static const int kFrameDetailsConstructCallIndex = 7;
462 : static const int kFrameDetailsAtReturnIndex = 8;
463 : static const int kFrameDetailsFlagsIndex = 9;
464 : static const int kFrameDetailsFirstDynamicIndex = 10;
465 :
466 : // Return an array with frame details
467 : // args[0]: number: break id
468 : // args[1]: number: frame index
469 : //
470 : // The array returned contains the following information:
471 : // 0: Frame id
472 : // 1: Receiver
473 : // 2: Function
474 : // 3: Script
475 : // 4: Argument count
476 : // 5: Local count
477 : // 6: Source position
478 : // 7: Constructor call
479 : // 8: Is at return
480 : // 9: Flags
481 : // Arguments name, value
482 : // Locals name, value
483 : // Return value if any
484 1257201 : RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
485 229547 : HandleScope scope(isolate);
486 : DCHECK_EQ(2, args.length());
487 459094 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
488 229547 : CHECK(isolate->debug()->CheckExecutionState(break_id));
489 :
490 459094 : CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
491 250801 : Heap* heap = isolate->heap();
492 :
493 : // Find the relevant frame with the requested index.
494 229547 : StackFrame::Id id = isolate->debug()->break_frame_id();
495 229547 : if (id == StackFrame::NO_ID) {
496 : // If there are no JavaScript stack frames return undefined.
497 0 : return heap->undefined_value();
498 : }
499 :
500 459094 : StackTraceFrameIterator it(isolate, id);
501 : // Inlined frame index in optimized frame, starting from outer function.
502 : int inlined_frame_index =
503 229547 : DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
504 229547 : if (inlined_frame_index == -1) return heap->undefined_value();
505 :
506 459094 : FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
507 :
508 : // Traverse the saved contexts chain to find the active context for the
509 : // selected frame.
510 : SaveContext* save =
511 229547 : DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
512 :
513 : // Get the frame id.
514 229547 : Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
515 : isolate);
516 :
517 229547 : if (frame_inspector.summary().IsWasm()) {
518 : // Create the details array (no dynamic information for wasm).
519 : Handle<FixedArray> details =
520 374 : isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
521 :
522 : // Add the frame id.
523 374 : details->set(kFrameDetailsFrameIdIndex, *frame_id);
524 :
525 : // Add the function name.
526 374 : Handle<String> func_name = frame_inspector.summary().FunctionName();
527 374 : details->set(kFrameDetailsFunctionIndex, *func_name);
528 :
529 : // Add the script wrapper
530 : Handle<Object> script_wrapper =
531 374 : Script::GetWrapper(frame_inspector.GetScript());
532 374 : details->set(kFrameDetailsScriptIndex, *script_wrapper);
533 :
534 : // Add the arguments count.
535 374 : details->set(kFrameDetailsArgumentCountIndex, Smi::kZero);
536 :
537 : // Add the locals count
538 374 : details->set(kFrameDetailsLocalCountIndex, Smi::kZero);
539 :
540 : // Add the source position.
541 374 : int position = frame_inspector.summary().SourcePosition();
542 748 : details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
543 :
544 : // Add the constructor information.
545 748 : details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
546 :
547 : // Add the at return information.
548 748 : details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
549 :
550 : // Add flags to indicate information on whether this frame is
551 : // bit 0: invoked in the debugger context.
552 : // bit 1: optimized frame.
553 : // bit 2: inlined in optimized frame
554 374 : int flags = inlined_frame_index << 2;
555 1122 : if (*save->context() == *isolate->debug()->debug_context()) {
556 0 : flags |= 1 << 0;
557 : }
558 748 : details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
559 :
560 748 : return *isolate->factory()->NewJSArrayWithElements(details);
561 : }
562 :
563 : // Find source position in unoptimized code.
564 229173 : int position = frame_inspector.GetSourcePosition();
565 :
566 : // Handle JavaScript frames.
567 229173 : bool is_optimized = it.frame()->is_optimized();
568 :
569 : // Check for constructor frame.
570 229173 : bool constructor = frame_inspector.IsConstructor();
571 :
572 : // Get scope info and read from it for local variable information.
573 : Handle<JSFunction> function =
574 229173 : Handle<JSFunction>::cast(frame_inspector.GetFunction());
575 229173 : CHECK(function->shared()->IsSubjectToDebugging());
576 229173 : Handle<SharedFunctionInfo> shared(function->shared());
577 229173 : Handle<ScopeInfo> scope_info(shared->scope_info());
578 : DCHECK(*scope_info != ScopeInfo::Empty(isolate));
579 :
580 : // Get the locals names and values into a temporary array.
581 229173 : Handle<Object> maybe_context = frame_inspector.GetContext();
582 : const int local_count_with_synthetic = maybe_context->IsContext()
583 : ? scope_info->LocalCount()
584 458346 : : scope_info->StackLocalCount();
585 : int local_count = local_count_with_synthetic;
586 5214620 : for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
587 : // Hide compiler-introduced temporary variables, whether on the stack or on
588 : // the context.
589 5214620 : if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
590 229024 : local_count--;
591 : }
592 : }
593 :
594 229173 : List<Handle<Object>> locals;
595 : // Fill in the values of the locals.
596 : int i = 0;
597 10412011 : for (; i < scope_info->StackLocalCount(); ++i) {
598 : // Use the value from the stack.
599 5278551 : if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
600 9808574 : locals.Add(Handle<String>(scope_info->LocalName(i), isolate));
601 : Handle<Object> value =
602 4904287 : frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
603 : // TODO(yangguo): We convert optimized out values to {undefined} when they
604 : // are passed to the debugger. Eventually we should handle them somehow.
605 4904287 : if (value->IsOptimizedOut(isolate)) {
606 4217 : value = isolate->factory()->undefined_value();
607 : }
608 4904287 : locals.Add(value);
609 : }
610 229173 : if (locals.length() < local_count * 2) {
611 : // Get the context containing declarations.
612 : DCHECK(maybe_context->IsContext());
613 18918 : Handle<Context> context(Context::cast(*maybe_context)->closure_context());
614 :
615 250224 : for (; i < scope_info->LocalCount(); ++i) {
616 115653 : Handle<String> name(scope_info->LocalName(i));
617 149997 : if (ScopeInfo::VariableIsSynthetic(*name)) continue;
618 : VariableMode mode;
619 : InitializationFlag init_flag;
620 : MaybeAssignedFlag maybe_assigned_flag;
621 81309 : locals.Add(name);
622 : int context_slot_index = ScopeInfo::ContextSlotIndex(
623 81309 : scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
624 81309 : Object* value = context->get(context_slot_index);
625 81309 : locals.Add(Handle<Object>(value, isolate));
626 : }
627 : }
628 :
629 : // Check whether this frame is positioned at return. If not top
630 : // frame or if the frame is optimized it cannot be at a return.
631 : bool at_return = false;
632 229173 : if (!is_optimized && index == 0) {
633 198364 : at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
634 : }
635 :
636 : // If positioned just before return find the value to be returned and add it
637 : // to the frame information.
638 229173 : Handle<Object> return_value = isolate->factory()->undefined_value();
639 229173 : if (at_return) {
640 10284 : return_value = handle(isolate->debug()->return_value(), isolate);
641 : }
642 :
643 : // Now advance to the arguments adapter frame (if any). It contains all
644 : // the provided parameters whereas the function frame always have the number
645 : // of arguments matching the functions parameters. The rest of the
646 : // information (except for what is collected above) is the same.
647 457570 : if ((inlined_frame_index == 0) &&
648 228397 : it.javascript_frame()->has_adapted_arguments()) {
649 16015 : it.AdvanceToArgumentsFrame();
650 16015 : frame_inspector.SetArgumentsFrame(it.frame());
651 : }
652 :
653 : // Find the number of arguments to fill. At least fill the number of
654 : // parameters for the function and fill more if more parameters are provided.
655 229173 : int argument_count = scope_info->ParameterCount();
656 229173 : if (argument_count < frame_inspector.GetParametersCount()) {
657 13640 : argument_count = frame_inspector.GetParametersCount();
658 : }
659 :
660 : // Calculate the size of the result.
661 229173 : int details_size = kFrameDetailsFirstDynamicIndex +
662 458346 : 2 * (argument_count + local_count) + (at_return ? 1 : 0);
663 229173 : Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
664 :
665 : // Add the frame id.
666 229173 : details->set(kFrameDetailsFrameIdIndex, *frame_id);
667 :
668 : // Add the function (same as in function frame).
669 458346 : details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
670 :
671 : // Add the script wrapper
672 : Handle<Object> script_wrapper =
673 229173 : Script::GetWrapper(frame_inspector.GetScript());
674 229173 : details->set(kFrameDetailsScriptIndex, *script_wrapper);
675 :
676 : // Add the arguments count.
677 458346 : details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
678 :
679 : // Add the locals count
680 458346 : details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
681 :
682 : // Add the source position.
683 229173 : if (position != kNoSourcePosition) {
684 458346 : details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
685 : } else {
686 0 : details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
687 : }
688 :
689 : // Add the constructor information.
690 458346 : details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
691 :
692 : // Add the at return information.
693 458346 : details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
694 :
695 : // Add flags to indicate information on whether this frame is
696 : // bit 0: invoked in the debugger context.
697 : // bit 1: optimized frame.
698 : // bit 2: inlined in optimized frame
699 : int flags = 0;
700 687519 : if (*save->context() == *isolate->debug()->debug_context()) {
701 : flags |= 1 << 0;
702 : }
703 229173 : if (is_optimized) {
704 24888 : flags |= 1 << 1;
705 24888 : flags |= inlined_frame_index << 2;
706 : }
707 458346 : details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
708 :
709 : // Fill the dynamic part.
710 : int details_index = kFrameDetailsFirstDynamicIndex;
711 :
712 : // Add arguments name and value.
713 62544 : for (int i = 0; i < argument_count; i++) {
714 : // Name of the argument.
715 62544 : if (i < scope_info->ParameterCount()) {
716 89076 : details->set(details_index++, scope_info->ParameterName(i));
717 : } else {
718 36012 : details->set(details_index++, heap->undefined_value());
719 : }
720 :
721 : // Parameter value.
722 62544 : if (i < frame_inspector.GetParametersCount()) {
723 : // Get the value from the stack.
724 177888 : details->set(details_index++, *(frame_inspector.GetParameter(i)));
725 : } else {
726 6496 : details->set(details_index++, heap->undefined_value());
727 : }
728 : }
729 :
730 : // Add locals name and value from the temporary copy from the function frame.
731 20171557 : for (const auto& local : locals) details->set(details_index++, *local);
732 :
733 : // Add the value being returned.
734 229173 : if (at_return) {
735 10284 : details->set(details_index++, *return_value);
736 : }
737 :
738 : // Add the receiver (same as in function frame).
739 229173 : Handle<Object> receiver = frame_inspector.summary().receiver();
740 : DCHECK(function->shared()->IsUserJavaScript());
741 : // Optimized frames only restore the receiver as best-effort (see
742 : // OptimizedFrame::Summarize).
743 : DCHECK_IMPLIES(!is_optimized && is_sloppy(shared->language_mode()),
744 : receiver->IsJSReceiver());
745 229173 : details->set(kFrameDetailsReceiverIndex, *receiver);
746 :
747 : DCHECK_EQ(details_size, details_index);
748 687893 : return *isolate->factory()->NewJSArrayWithElements(details);
749 : }
750 :
751 :
752 0 : RUNTIME_FUNCTION(Runtime_GetScopeCount) {
753 0 : HandleScope scope(isolate);
754 : DCHECK_EQ(2, args.length());
755 0 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
756 0 : CHECK(isolate->debug()->CheckExecutionState(break_id));
757 :
758 0 : CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
759 :
760 : // Get the frame where the debugging is performed.
761 0 : StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
762 0 : StackTraceFrameIterator it(isolate, id);
763 0 : StandardFrame* frame = it.frame();
764 0 : if (it.frame()->is_wasm()) return 0;
765 :
766 0 : FrameInspector frame_inspector(frame, 0, isolate);
767 :
768 : // Count the visible scopes.
769 : int n = 0;
770 0 : for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
771 0 : n++;
772 0 : }
773 :
774 0 : return Smi::FromInt(n);
775 : }
776 :
777 :
778 : // Return an array with scope details
779 : // args[0]: number: break id
780 : // args[1]: number: frame index
781 : // args[2]: number: inlined frame index
782 : // args[3]: number: scope index
783 : //
784 : // The array returned contains the following information:
785 : // 0: Scope type
786 : // 1: Scope object
787 510 : RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
788 170 : HandleScope scope(isolate);
789 : DCHECK_EQ(4, args.length());
790 340 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
791 170 : CHECK(isolate->debug()->CheckExecutionState(break_id));
792 :
793 340 : CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
794 340 : CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
795 340 : CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
796 :
797 : // Get the frame where the debugging is performed.
798 170 : StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
799 340 : StackTraceFrameIterator frame_it(isolate, id);
800 : // Wasm has no scopes, this must be javascript.
801 170 : JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
802 340 : FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
803 :
804 : // Find the requested scope.
805 : int n = 0;
806 340 : ScopeIterator it(isolate, &frame_inspector);
807 60 : for (; !it.Done() && n < index; it.Next()) {
808 60 : n++;
809 : }
810 170 : if (it.Done()) {
811 0 : return isolate->heap()->undefined_value();
812 : }
813 510 : RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
814 : }
815 :
816 :
817 : // Return an array of scope details
818 : // args[0]: number: break id
819 : // args[1]: number: frame index
820 : // args[2]: number: inlined frame index
821 : // args[3]: boolean: ignore nested scopes
822 : //
823 : // The array returned contains arrays with the following information:
824 : // 0: Scope type
825 : // 1: Scope object
826 575694 : RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
827 191898 : HandleScope scope(isolate);
828 : DCHECK(args.length() == 3 || args.length() == 4);
829 383796 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
830 191898 : CHECK(isolate->debug()->CheckExecutionState(break_id));
831 :
832 383796 : CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
833 383796 : CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
834 :
835 : ScopeIterator::Option option = ScopeIterator::DEFAULT;
836 191898 : if (args.length() == 4) {
837 383796 : CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
838 191898 : if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
839 : }
840 :
841 : // Get the frame where the debugging is performed.
842 191898 : StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
843 383796 : StackTraceFrameIterator frame_it(isolate, id);
844 191898 : StandardFrame* frame = frame_it.frame();
845 :
846 : // Handle wasm frames specially. They provide exactly two scopes (global /
847 : // local).
848 192174 : if (frame->is_wasm_interpreter_entry()) {
849 : Handle<WasmDebugInfo> debug_info(
850 : WasmInterpreterEntryFrame::cast(frame)->wasm_instance()->debug_info(),
851 276 : isolate);
852 : return *WasmDebugInfo::GetScopeDetails(debug_info, frame->fp(),
853 552 : inlined_frame_index);
854 : }
855 :
856 383244 : FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
857 : List<Handle<JSObject>> result(4);
858 383244 : ScopeIterator it(isolate, &frame_inspector, option);
859 512512 : for (; !it.Done(); it.Next()) {
860 : Handle<JSObject> details;
861 1025024 : ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
862 : it.MaterializeScopeDetails());
863 512512 : result.Add(details);
864 : }
865 :
866 191622 : Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
867 512512 : for (int i = 0; i < result.length(); ++i) {
868 1025024 : array->set(i, *result[i]);
869 : }
870 575142 : return *isolate->factory()->NewJSArrayWithElements(array);
871 : }
872 :
873 :
874 48 : RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
875 24 : HandleScope scope(isolate);
876 : DCHECK_EQ(1, args.length());
877 :
878 : // Check arguments.
879 48 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
880 :
881 : // Count the visible scopes.
882 : int n = 0;
883 24 : if (function->IsJSFunction()) {
884 96 : for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
885 48 : !it.Done(); it.Next()) {
886 48 : n++;
887 24 : }
888 : }
889 :
890 24 : return Smi::FromInt(n);
891 : }
892 :
893 :
894 96 : RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
895 48 : HandleScope scope(isolate);
896 : DCHECK_EQ(2, args.length());
897 :
898 : // Check arguments.
899 96 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
900 96 : CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
901 :
902 : // Find the requested scope.
903 : int n = 0;
904 96 : ScopeIterator it(isolate, fun);
905 24 : for (; !it.Done() && n < index; it.Next()) {
906 24 : n++;
907 : }
908 48 : if (it.Done()) {
909 0 : return isolate->heap()->undefined_value();
910 : }
911 :
912 144 : RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
913 : }
914 :
915 968 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
916 484 : HandleScope scope(isolate);
917 : DCHECK_EQ(1, args.length());
918 :
919 968 : if (!args[0]->IsJSGeneratorObject()) return Smi::kZero;
920 :
921 : // Check arguments.
922 968 : CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
923 :
924 : // Count the visible scopes.
925 : int n = 0;
926 2300 : for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
927 1816 : n++;
928 484 : }
929 :
930 484 : return Smi::FromInt(n);
931 : }
932 :
933 3212 : RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
934 1606 : HandleScope scope(isolate);
935 : DCHECK_EQ(2, args.length());
936 :
937 3212 : if (!args[0]->IsJSGeneratorObject()) {
938 0 : return isolate->heap()->undefined_value();
939 : }
940 :
941 : // Check arguments.
942 3212 : CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
943 3212 : CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
944 :
945 : // Find the requested scope.
946 : int n = 0;
947 3212 : ScopeIterator it(isolate, gen);
948 1620 : for (; !it.Done() && n < index; it.Next()) {
949 1620 : n++;
950 : }
951 1606 : if (it.Done()) {
952 0 : return isolate->heap()->undefined_value();
953 : }
954 :
955 4818 : RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
956 : }
957 :
958 376 : static bool SetScopeVariableValue(ScopeIterator* it, int index,
959 : Handle<String> variable_name,
960 : Handle<Object> new_value) {
961 1096 : for (int n = 0; !it->Done() && n < index; it->Next()) {
962 172 : n++;
963 : }
964 376 : if (it->Done()) {
965 : return false;
966 : }
967 376 : return it->SetVariableValue(variable_name, new_value);
968 : }
969 :
970 :
971 : // Change variable value in closure or local scope
972 : // args[0]: number or JsFunction: break id or function
973 : // args[1]: number: frame index (when arg[0] is break id)
974 : // args[2]: number: inlined frame index (when arg[0] is break id)
975 : // args[3]: number: scope index
976 : // args[4]: string: variable name
977 : // args[5]: object: new value
978 : //
979 : // Return true if success and false otherwise
980 946 : RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
981 376 : HandleScope scope(isolate);
982 : DCHECK_EQ(6, args.length());
983 :
984 : // Check arguments.
985 752 : CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
986 752 : CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
987 376 : CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
988 :
989 : bool res;
990 752 : if (args[0]->IsNumber()) {
991 388 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
992 194 : CHECK(isolate->debug()->CheckExecutionState(break_id));
993 :
994 388 : CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
995 388 : CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
996 :
997 : // Get the frame where the debugging is performed.
998 194 : StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
999 194 : StackTraceFrameIterator frame_it(isolate, id);
1000 : // Wasm has no scopes, this must be javascript.
1001 194 : JavaScriptFrame* frame = JavaScriptFrame::cast(frame_it.frame());
1002 388 : FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
1003 :
1004 388 : ScopeIterator it(isolate, &frame_inspector);
1005 388 : res = SetScopeVariableValue(&it, index, variable_name, new_value);
1006 364 : } else if (args[0]->IsJSFunction()) {
1007 0 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1008 0 : ScopeIterator it(isolate, fun);
1009 0 : res = SetScopeVariableValue(&it, index, variable_name, new_value);
1010 : } else {
1011 364 : CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
1012 182 : ScopeIterator it(isolate, gen);
1013 182 : res = SetScopeVariableValue(&it, index, variable_name, new_value);
1014 : }
1015 :
1016 376 : return isolate->heap()->ToBoolean(res);
1017 : }
1018 :
1019 :
1020 0 : RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
1021 0 : HandleScope scope(isolate);
1022 : DCHECK_EQ(0, args.length());
1023 :
1024 : #ifdef DEBUG
1025 : // Print the scopes for the top frame.
1026 : StackFrameLocator locator(isolate);
1027 : JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
1028 : FrameInspector frame_inspector(frame, 0, isolate);
1029 :
1030 : for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
1031 : it.DebugPrint();
1032 : }
1033 : #endif
1034 0 : return isolate->heap()->undefined_value();
1035 : }
1036 :
1037 :
1038 : // Sets the disable break state
1039 : // args[0]: disable break state
1040 0 : RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
1041 0 : HandleScope scope(isolate);
1042 : DCHECK_EQ(1, args.length());
1043 0 : CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1044 0 : isolate->debug()->set_break_points_active(active);
1045 0 : return isolate->heap()->undefined_value();
1046 : }
1047 :
1048 :
1049 3111 : static bool IsPositionAlignmentCodeCorrect(int alignment) {
1050 3111 : return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1051 : }
1052 :
1053 :
1054 1176 : RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1055 392 : HandleScope scope(isolate);
1056 : DCHECK_EQ(2, args.length());
1057 392 : CHECK(isolate->debug()->is_active());
1058 784 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1059 784 : CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1060 :
1061 392 : if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1062 0 : return isolate->ThrowIllegalOperation();
1063 : }
1064 : BreakPositionAlignment alignment =
1065 392 : static_cast<BreakPositionAlignment>(statement_aligned_code);
1066 :
1067 392 : Handle<SharedFunctionInfo> shared(fun->shared());
1068 : // Find the number of break points
1069 : Handle<Object> break_locations =
1070 392 : Debug::GetSourceBreakLocations(shared, alignment);
1071 392 : if (break_locations->IsUndefined(isolate)) {
1072 56 : return isolate->heap()->undefined_value();
1073 : }
1074 : // Return array as JS array
1075 : return *isolate->factory()->NewJSArrayWithElements(
1076 1008 : Handle<FixedArray>::cast(break_locations));
1077 : }
1078 :
1079 :
1080 : // Set a break point in a function.
1081 : // args[0]: function
1082 : // args[1]: number: break source position (within the function source)
1083 : // args[2]: number: break point object
1084 0 : RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1085 0 : HandleScope scope(isolate);
1086 : DCHECK_EQ(3, args.length());
1087 0 : CHECK(isolate->debug()->is_active());
1088 0 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1089 0 : CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1090 0 : CHECK(source_position >= function->shared()->start_position() &&
1091 : source_position <= function->shared()->end_position());
1092 0 : CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1093 :
1094 : // Set break point.
1095 0 : CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
1096 : &source_position));
1097 :
1098 0 : return Smi::FromInt(source_position);
1099 : }
1100 :
1101 :
1102 : // Changes the state of a break point in a script and returns source position
1103 : // where break point was set. NOTE: Regarding performance see the NOTE for
1104 : // GetScriptFromScriptData.
1105 : // args[0]: script to set break point in
1106 : // args[1]: number: break source position (within the script source)
1107 : // args[2]: number, breakpoint position alignment
1108 : // args[3]: number: break point object
1109 10876 : RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1110 2719 : HandleScope scope(isolate);
1111 : DCHECK_EQ(4, args.length());
1112 2719 : CHECK(isolate->debug()->is_active());
1113 5438 : CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1114 5438 : CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1115 2719 : CHECK(source_position >= 0);
1116 5438 : CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1117 2719 : CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1118 :
1119 2719 : if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1120 0 : return isolate->ThrowIllegalOperation();
1121 : }
1122 : BreakPositionAlignment alignment =
1123 2719 : static_cast<BreakPositionAlignment>(statement_aligned_code);
1124 :
1125 : // Get the script from the script wrapper.
1126 5438 : CHECK(wrapper->value()->IsScript());
1127 2719 : Handle<Script> script(Script::cast(wrapper->value()));
1128 :
1129 : // Set break point.
1130 2719 : if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1131 2719 : &source_position, alignment)) {
1132 6 : return isolate->heap()->undefined_value();
1133 : }
1134 :
1135 2713 : return Smi::FromInt(source_position);
1136 : }
1137 :
1138 :
1139 : // Clear a break point
1140 : // args[0]: number: break point object
1141 5552 : RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1142 2776 : HandleScope scope(isolate);
1143 : DCHECK_EQ(1, args.length());
1144 2776 : CHECK(isolate->debug()->is_active());
1145 2776 : CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1146 :
1147 : // Clear break point.
1148 2776 : isolate->debug()->ClearBreakPoint(break_point_object_arg);
1149 :
1150 2776 : return isolate->heap()->undefined_value();
1151 : }
1152 :
1153 :
1154 : // Change the state of break on exceptions.
1155 : // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1156 : // args[1]: Boolean indicating on/off.
1157 144 : RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1158 48 : HandleScope scope(isolate);
1159 : DCHECK_EQ(2, args.length());
1160 96 : CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1161 96 : CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1162 :
1163 : // If the number doesn't match an enum value, the ChangeBreakOnException
1164 : // function will default to affecting caught exceptions.
1165 : ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1166 : // Update break point state.
1167 96 : isolate->debug()->ChangeBreakOnException(type, enable);
1168 48 : return isolate->heap()->undefined_value();
1169 : }
1170 :
1171 :
1172 : // Returns the state of break on exceptions
1173 : // args[0]: boolean indicating uncaught exceptions
1174 15372 : RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1175 5124 : HandleScope scope(isolate);
1176 : DCHECK_EQ(1, args.length());
1177 10248 : CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1178 :
1179 : ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1180 5124 : bool result = isolate->debug()->IsBreakOnException(type);
1181 5124 : return Smi::FromInt(result);
1182 : }
1183 :
1184 :
1185 : // Prepare for stepping
1186 : // args[0]: break id for checking execution state
1187 : // args[1]: step action from the enumeration StepAction
1188 : // args[2]: number of times to perform the step, for step out it is the number
1189 : // of frames to step down.
1190 390 : RUNTIME_FUNCTION(Runtime_PrepareStep) {
1191 78 : HandleScope scope(isolate);
1192 : DCHECK_EQ(2, args.length());
1193 156 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1194 78 : CHECK(isolate->debug()->CheckExecutionState(break_id));
1195 :
1196 156 : if (!args[1]->IsNumber()) {
1197 0 : return isolate->Throw(isolate->heap()->illegal_argument_string());
1198 : }
1199 :
1200 : // Get the step action and check validity.
1201 78 : StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1202 78 : if (step_action != StepIn && step_action != StepNext &&
1203 : step_action != StepOut) {
1204 0 : return isolate->Throw(isolate->heap()->illegal_argument_string());
1205 : }
1206 :
1207 : // Clear all current stepping setup.
1208 78 : isolate->debug()->ClearStepping();
1209 :
1210 : // Prepare step.
1211 156 : isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
1212 78 : return isolate->heap()->undefined_value();
1213 : }
1214 :
1215 : // Clear all stepping set by PrepareStep.
1216 56 : RUNTIME_FUNCTION(Runtime_ClearStepping) {
1217 28 : HandleScope scope(isolate);
1218 : DCHECK_EQ(0, args.length());
1219 28 : CHECK(isolate->debug()->is_active());
1220 28 : isolate->debug()->ClearStepping();
1221 28 : return isolate->heap()->undefined_value();
1222 : }
1223 :
1224 :
1225 46737 : RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1226 15579 : HandleScope scope(isolate);
1227 :
1228 : // Check the execution state and decode arguments frame and source to be
1229 : // evaluated.
1230 : DCHECK_EQ(5, args.length());
1231 31158 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1232 15579 : CHECK(isolate->debug()->CheckExecutionState(break_id));
1233 :
1234 31158 : CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1235 31158 : CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1236 31158 : CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1237 31158 : CONVERT_BOOLEAN_ARG_CHECKED(throw_on_side_effect, 4);
1238 :
1239 15579 : StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
1240 :
1241 31158 : RETURN_RESULT_OR_FAILURE(
1242 : isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1243 15579 : throw_on_side_effect));
1244 : }
1245 :
1246 :
1247 18 : RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1248 6 : HandleScope scope(isolate);
1249 :
1250 : // Check the execution state and decode arguments frame and source to be
1251 : // evaluated.
1252 : DCHECK_EQ(2, args.length());
1253 12 : CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1254 6 : CHECK(isolate->debug()->CheckExecutionState(break_id));
1255 :
1256 12 : CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1257 :
1258 18 : RETURN_RESULT_OR_FAILURE(isolate, DebugEvaluate::Global(isolate, source));
1259 : }
1260 :
1261 :
1262 11580 : RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1263 2920 : HandleScope scope(isolate);
1264 : DCHECK_EQ(0, args.length());
1265 :
1266 : Handle<FixedArray> instances;
1267 : {
1268 2920 : DebugScope debug_scope(isolate->debug());
1269 2920 : if (debug_scope.failed()) {
1270 : DCHECK(isolate->has_pending_exception());
1271 100 : return isolate->heap()->exception();
1272 : }
1273 : // Fill the script objects.
1274 2820 : instances = isolate->debug()->GetLoadedScripts();
1275 : }
1276 :
1277 : // Convert the script objects to proper JS objects.
1278 153796 : for (int i = 0; i < instances->length(); i++) {
1279 75488 : Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1280 : // Get the script wrapper in a local handle before calling GetScriptWrapper,
1281 : // because using
1282 : // instances->set(i, *GetScriptWrapper(script))
1283 : // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1284 : // already have dereferenced the instances handle.
1285 75488 : Handle<JSObject> wrapper = Script::GetWrapper(script);
1286 75488 : instances->set(i, *wrapper);
1287 : }
1288 :
1289 : // Return result as a JS array.
1290 5640 : return *isolate->factory()->NewJSArrayWithElements(instances);
1291 : }
1292 :
1293 0 : static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1294 : JSObject* object,
1295 : Object* proto) {
1296 : PrototypeIterator iter(isolate, object, kStartAtReceiver);
1297 : while (true) {
1298 0 : iter.AdvanceIgnoringProxies();
1299 0 : if (iter.IsAtEnd()) return false;
1300 0 : if (iter.GetCurrent() == proto) return true;
1301 : }
1302 : }
1303 :
1304 :
1305 : // Scan the heap for objects with direct references to an object
1306 : // args[0]: the object to find references to
1307 : // args[1]: constructor function for instances to exclude (Mirror)
1308 : // args[2]: the the maximum number of objects to return
1309 0 : RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1310 0 : HandleScope scope(isolate);
1311 : DCHECK_EQ(3, args.length());
1312 0 : CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
1313 0 : CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1314 0 : CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
1315 0 : CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1316 0 : CHECK(max_references >= 0);
1317 :
1318 0 : List<Handle<JSObject> > instances;
1319 0 : Heap* heap = isolate->heap();
1320 : {
1321 0 : HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1322 : // Get the constructor function for context extension and arguments array.
1323 0 : Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1324 : HeapObject* heap_obj;
1325 0 : while ((heap_obj = iterator.next()) != nullptr) {
1326 0 : if (!heap_obj->IsJSObject()) continue;
1327 : JSObject* obj = JSObject::cast(heap_obj);
1328 0 : if (obj->IsJSContextExtensionObject()) continue;
1329 0 : if (obj->map()->GetConstructor() == arguments_fun) continue;
1330 0 : if (!obj->ReferencesObject(*target)) continue;
1331 : // Check filter if supplied. This is normally used to avoid
1332 : // references from mirror objects.
1333 0 : if (!filter->IsUndefined(isolate) &&
1334 0 : HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1335 : continue;
1336 : }
1337 0 : if (obj->IsJSGlobalObject()) {
1338 0 : obj = JSGlobalObject::cast(obj)->global_proxy();
1339 : }
1340 0 : instances.Add(Handle<JSObject>(obj));
1341 0 : if (instances.length() == max_references) break;
1342 : }
1343 : // Iterate the rest of the heap to satisfy HeapIterator constraints.
1344 0 : while (iterator.next()) {
1345 0 : }
1346 : }
1347 :
1348 : Handle<FixedArray> result;
1349 0 : if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1350 : // Check for circular reference only. This can happen when the object is
1351 : // only referenced from mirrors and has a circular reference in which case
1352 : // the object is not really alive and would have been garbage collected if
1353 : // not referenced from the mirror.
1354 0 : result = isolate->factory()->empty_fixed_array();
1355 : } else {
1356 0 : result = isolate->factory()->NewFixedArray(instances.length());
1357 0 : for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1358 : }
1359 0 : return *isolate->factory()->NewJSArrayWithElements(result);
1360 : }
1361 :
1362 :
1363 : // Scan the heap for objects constructed by a specific function.
1364 : // args[0]: the constructor to find instances of
1365 : // args[1]: the the maximum number of objects to return
1366 0 : RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1367 0 : HandleScope scope(isolate);
1368 : DCHECK_EQ(2, args.length());
1369 0 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1370 0 : CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
1371 0 : CHECK(max_references >= 0);
1372 :
1373 0 : List<Handle<JSObject> > instances;
1374 0 : Heap* heap = isolate->heap();
1375 : {
1376 0 : HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1377 : HeapObject* heap_obj;
1378 0 : while ((heap_obj = iterator.next()) != nullptr) {
1379 0 : if (!heap_obj->IsJSObject()) continue;
1380 : JSObject* obj = JSObject::cast(heap_obj);
1381 0 : if (obj->map()->GetConstructor() != *constructor) continue;
1382 0 : instances.Add(Handle<JSObject>(obj));
1383 0 : if (instances.length() == max_references) break;
1384 : }
1385 : // Iterate the rest of the heap to satisfy HeapIterator constraints.
1386 0 : while (iterator.next()) {
1387 0 : }
1388 : }
1389 :
1390 : Handle<FixedArray> result =
1391 0 : isolate->factory()->NewFixedArray(instances.length());
1392 0 : for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1393 0 : return *isolate->factory()->NewJSArrayWithElements(result);
1394 : }
1395 :
1396 :
1397 : // Find the effective prototype object as returned by __proto__.
1398 : // args[0]: the object to find the prototype for.
1399 12 : RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1400 6 : HandleScope shs(isolate);
1401 : DCHECK_EQ(1, args.length());
1402 12 : CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1403 : // TODO(1543): Come up with a solution for clients to handle potential errors
1404 : // thrown by an intermediate proxy.
1405 18 : RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
1406 : }
1407 :
1408 :
1409 : // Patches script source (should be called upon BeforeCompile event).
1410 : // TODO(5530): Remove once uses in debug.js are gone.
1411 0 : RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1412 0 : HandleScope scope(isolate);
1413 : DCHECK_EQ(2, args.length());
1414 :
1415 0 : CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1416 0 : CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1417 :
1418 0 : CHECK(script_wrapper->value()->IsScript());
1419 0 : Handle<Script> script(Script::cast(script_wrapper->value()));
1420 :
1421 : // The following condition is not guaranteed to hold and a failure is also
1422 : // propagated to callers. Hence we fail gracefully here and don't crash.
1423 0 : if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
1424 0 : return isolate->ThrowIllegalOperation();
1425 : }
1426 :
1427 0 : script->set_source(*source);
1428 :
1429 0 : return isolate->heap()->undefined_value();
1430 : }
1431 :
1432 :
1433 174 : RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1434 : SealHandleScope shs(isolate);
1435 : DCHECK_EQ(1, args.length());
1436 :
1437 87 : CONVERT_ARG_CHECKED(Object, f, 0);
1438 87 : if (f->IsJSFunction()) {
1439 72 : return JSFunction::cast(f)->shared()->inferred_name();
1440 : }
1441 15 : return isolate->heap()->empty_string();
1442 : }
1443 :
1444 :
1445 382088 : RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1446 191044 : HandleScope scope(isolate);
1447 : DCHECK_EQ(1, args.length());
1448 :
1449 382088 : CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1450 :
1451 191044 : if (function->IsJSBoundFunction()) {
1452 0 : RETURN_RESULT_OR_FAILURE(
1453 : isolate, JSBoundFunction::GetName(
1454 : isolate, Handle<JSBoundFunction>::cast(function)));
1455 : } else {
1456 382088 : return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
1457 191044 : }
1458 : }
1459 :
1460 :
1461 11176 : RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1462 3169 : HandleScope scope(isolate);
1463 : DCHECK_EQ(0, args.length());
1464 : Handle<Context> context;
1465 : {
1466 3169 : DebugScope debug_scope(isolate->debug());
1467 3169 : if (debug_scope.failed()) {
1468 : DCHECK(isolate->has_pending_exception());
1469 1500 : return isolate->heap()->exception();
1470 : }
1471 1669 : context = isolate->debug()->GetDebugContext();
1472 : }
1473 1669 : if (context.is_null()) return isolate->heap()->undefined_value();
1474 5007 : context->set_security_token(isolate->native_context()->security_token());
1475 1669 : return context->global_proxy();
1476 : }
1477 :
1478 :
1479 : // Performs a GC.
1480 : // Presently, it only does a full GC.
1481 56 : RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1482 : SealHandleScope shs(isolate);
1483 : DCHECK_EQ(1, args.length());
1484 : isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1485 28 : GarbageCollectionReason::kRuntime);
1486 28 : return isolate->heap()->undefined_value();
1487 : }
1488 :
1489 :
1490 : // Gets the current heap usage.
1491 0 : RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1492 : SealHandleScope shs(isolate);
1493 : DCHECK_EQ(0, args.length());
1494 0 : int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1495 0 : if (!Smi::IsValid(usage)) {
1496 0 : return *isolate->factory()->NewNumberFromInt(usage);
1497 : }
1498 0 : return Smi::FromInt(usage);
1499 : }
1500 :
1501 :
1502 : // Finds the script object from the script data. NOTE: This operation uses
1503 : // heap traversal to find the function generated for the source position
1504 : // for the requested break point. For lazily compiled functions several heap
1505 : // traversals might be required rendering this operation as a rather slow
1506 : // operation. However for setting break points which is normally done through
1507 : // some kind of user interaction the performance is not crucial.
1508 108 : RUNTIME_FUNCTION(Runtime_GetScript) {
1509 54 : HandleScope scope(isolate);
1510 : DCHECK_EQ(1, args.length());
1511 108 : CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1512 :
1513 : Handle<Script> found;
1514 : {
1515 54 : Script::Iterator iterator(isolate);
1516 : Script* script = NULL;
1517 1056 : while ((script = iterator.Next()) != NULL) {
1518 2070 : if (!script->name()->IsString()) continue;
1519 921 : String* name = String::cast(script->name());
1520 921 : if (name->Equals(*script_name)) {
1521 : found = Handle<Script>(script, isolate);
1522 : break;
1523 : }
1524 : }
1525 : }
1526 :
1527 54 : if (found.is_null()) return isolate->heap()->undefined_value();
1528 66 : return *Script::GetWrapper(found);
1529 : }
1530 :
1531 : // TODO(5530): Remove once uses in debug.js are gone.
1532 7716 : RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
1533 3858 : HandleScope scope(isolate);
1534 : DCHECK_EQ(1, args.length());
1535 7716 : CONVERT_ARG_CHECKED(JSValue, script, 0);
1536 :
1537 7716 : CHECK(script->value()->IsScript());
1538 3858 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1539 :
1540 3858 : if (script_handle->type() == Script::TYPE_WASM) {
1541 : // Return 0 for now; this function will disappear soon anyway.
1542 0 : return Smi::FromInt(0);
1543 : }
1544 :
1545 3858 : Script::InitLineEnds(script_handle);
1546 :
1547 3858 : FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1548 3858 : return Smi::FromInt(line_ends_array->length());
1549 : }
1550 :
1551 : namespace {
1552 :
1553 208314 : int ScriptLinePosition(Handle<Script> script, int line) {
1554 208314 : if (line < 0) return -1;
1555 :
1556 208314 : if (script->type() == Script::TYPE_WASM) {
1557 : return WasmCompiledModule::cast(script->wasm_compiled_module())
1558 212 : ->GetFunctionOffset(line);
1559 : }
1560 :
1561 208208 : Script::InitLineEnds(script);
1562 :
1563 : FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
1564 : const int line_count = line_ends_array->length();
1565 : DCHECK_LT(0, line_count);
1566 :
1567 208208 : if (line == 0) return 0;
1568 : // If line == line_count, we return the first position beyond the last line.
1569 172909 : if (line > line_count) return -1;
1570 345818 : return Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1571 : }
1572 :
1573 : } // namespace
1574 :
1575 : // TODO(5530): Remove once uses in debug.js are gone.
1576 0 : RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
1577 0 : HandleScope scope(isolate);
1578 : DCHECK_EQ(2, args.length());
1579 0 : CONVERT_ARG_CHECKED(JSValue, script, 0);
1580 0 : CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1581 :
1582 0 : CHECK(script->value()->IsScript());
1583 0 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1584 :
1585 0 : return Smi::FromInt(ScriptLinePosition(script_handle, line));
1586 : }
1587 :
1588 : // TODO(5530): Remove once uses in debug.js are gone.
1589 0 : RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
1590 0 : HandleScope scope(isolate);
1591 : DCHECK_EQ(2, args.length());
1592 0 : CONVERT_ARG_CHECKED(JSValue, script, 0);
1593 0 : CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1594 :
1595 0 : CHECK(script->value()->IsScript());
1596 0 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1597 :
1598 0 : if (script_handle->type() == Script::TYPE_WASM) {
1599 : // Return zero for now; this function will disappear soon anyway.
1600 0 : return Smi::FromInt(0);
1601 : }
1602 :
1603 0 : Script::InitLineEnds(script_handle);
1604 :
1605 0 : FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1606 0 : const int line_count = line_ends_array->length();
1607 :
1608 0 : if (line < 0 || line >= line_count) {
1609 0 : return Smi::FromInt(-1);
1610 : } else {
1611 0 : return Smi::cast(line_ends_array->get(line));
1612 0 : }
1613 : }
1614 :
1615 857290 : static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
1616 : Script::OffsetFlag offset_flag,
1617 : Isolate* isolate) {
1618 : Script::PositionInfo info;
1619 857290 : if (!Script::GetPositionInfo(script, position, &info, offset_flag)) {
1620 14 : return isolate->factory()->null_value();
1621 : }
1622 :
1623 857276 : Handle<String> source = handle(String::cast(script->source()), isolate);
1624 : Handle<String> sourceText = script->type() == Script::TYPE_WASM
1625 : ? isolate->factory()->empty_string()
1626 : : isolate->factory()->NewSubString(
1627 1714034 : source, info.line_start, info.line_end);
1628 :
1629 : Handle<JSObject> jsinfo =
1630 857276 : isolate->factory()->NewJSObject(isolate->object_function());
1631 :
1632 : JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
1633 857276 : NONE);
1634 : JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
1635 857276 : handle(Smi::FromInt(position), isolate), NONE);
1636 : JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
1637 1714552 : handle(Smi::FromInt(info.line), isolate), NONE);
1638 : JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
1639 1714552 : handle(Smi::FromInt(info.column), isolate), NONE);
1640 : JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
1641 857276 : sourceText, NONE);
1642 :
1643 857276 : return jsinfo;
1644 : }
1645 :
1646 : namespace {
1647 :
1648 208314 : int ScriptLinePositionWithOffset(Handle<Script> script, int line, int offset) {
1649 208314 : if (line < 0 || offset < 0) return -1;
1650 :
1651 208314 : if (line == 0 || offset == 0)
1652 207110 : return ScriptLinePosition(script, line) + offset;
1653 :
1654 : Script::PositionInfo info;
1655 1204 : if (!Script::GetPositionInfo(script, offset, &info, Script::NO_OFFSET)) {
1656 : return -1;
1657 : }
1658 :
1659 1204 : const int total_line = info.line + line;
1660 1204 : return ScriptLinePosition(script, total_line);
1661 : }
1662 :
1663 208314 : Handle<Object> ScriptLocationFromLine(Isolate* isolate, Handle<Script> script,
1664 : Handle<Object> opt_line,
1665 : Handle<Object> opt_column,
1666 : int32_t offset) {
1667 : // Line and column are possibly undefined and we need to handle these cases,
1668 : // additionally subtracting corresponding offsets.
1669 :
1670 : int32_t line = 0;
1671 208314 : if (!opt_line->IsNullOrUndefined(isolate)) {
1672 208034 : CHECK(opt_line->IsNumber());
1673 416068 : line = NumberToInt32(*opt_line) - script->line_offset();
1674 : }
1675 :
1676 : int32_t column = 0;
1677 208314 : if (!opt_column->IsNullOrUndefined(isolate)) {
1678 207346 : CHECK(opt_column->IsNumber());
1679 207346 : column = NumberToInt32(*opt_column);
1680 242269 : if (line == 0) column -= script->column_offset();
1681 : }
1682 :
1683 208314 : int line_position = ScriptLinePositionWithOffset(script, line, offset);
1684 208314 : if (line_position < 0 || column < 0) return isolate->factory()->null_value();
1685 :
1686 : return GetJSPositionInfo(script, line_position + column, Script::NO_OFFSET,
1687 208314 : isolate);
1688 : }
1689 :
1690 : // Slow traversal over all scripts on the heap.
1691 205044 : bool GetScriptById(Isolate* isolate, int needle, Handle<Script>* result) {
1692 205044 : Script::Iterator iterator(isolate);
1693 : Script* script = NULL;
1694 205044 : while ((script = iterator.Next()) != NULL) {
1695 5536910 : if (script->id() == needle) {
1696 205044 : *result = handle(script);
1697 205044 : return true;
1698 : }
1699 : }
1700 :
1701 : return false;
1702 : }
1703 :
1704 : } // namespace
1705 :
1706 : // Get information on a specific source line and column possibly offset by a
1707 : // fixed source position. This function is used to find a source position from
1708 : // a line and column position. The fixed source position offset is typically
1709 : // used to find a source position in a function based on a line and column in
1710 : // the source for the function alone. The offset passed will then be the
1711 : // start position of the source for the function within the full script source.
1712 : // Note that incoming line and column parameters may be undefined, and are
1713 : // assumed to be passed *with* offsets.
1714 : // TODO(5530): Remove once uses in debug.js are gone.
1715 6596 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
1716 3298 : HandleScope scope(isolate);
1717 : DCHECK_EQ(4, args.length());
1718 6596 : CONVERT_ARG_HANDLE_CHECKED(JSValue, script, 0);
1719 3298 : CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
1720 3298 : CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
1721 6596 : CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
1722 :
1723 6596 : CHECK(script->value()->IsScript());
1724 3298 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1725 :
1726 : return *ScriptLocationFromLine(isolate, script_handle, opt_line, opt_column,
1727 6596 : offset);
1728 : }
1729 :
1730 : // TODO(5530): Rename once conflicting function has been deleted.
1731 410032 : RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine2) {
1732 205016 : HandleScope scope(isolate);
1733 : DCHECK_EQ(4, args.length());
1734 410032 : CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
1735 205016 : CONVERT_ARG_HANDLE_CHECKED(Object, opt_line, 1);
1736 205016 : CONVERT_ARG_HANDLE_CHECKED(Object, opt_column, 2);
1737 410032 : CONVERT_NUMBER_CHECKED(int32_t, offset, Int32, args[3]);
1738 :
1739 : Handle<Script> script;
1740 205016 : CHECK(GetScriptById(isolate, scriptid, &script));
1741 :
1742 410032 : return *ScriptLocationFromLine(isolate, script, opt_line, opt_column, offset);
1743 : }
1744 :
1745 : // TODO(5530): Remove once uses in debug.js are gone.
1746 1297896 : RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
1747 648948 : HandleScope scope(isolate);
1748 : DCHECK_EQ(3, args.length());
1749 1297896 : CONVERT_ARG_CHECKED(JSValue, script, 0);
1750 1297896 : CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1751 1297896 : CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1752 :
1753 1297896 : CHECK(script->value()->IsScript());
1754 648948 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1755 :
1756 : const Script::OffsetFlag offset_flag =
1757 648948 : with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1758 1297896 : return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
1759 : }
1760 :
1761 : // TODO(5530): Rename once conflicting function has been deleted.
1762 56 : RUNTIME_FUNCTION(Runtime_ScriptPositionInfo2) {
1763 28 : HandleScope scope(isolate);
1764 : DCHECK_EQ(3, args.length());
1765 56 : CONVERT_NUMBER_CHECKED(int32_t, scriptid, Int32, args[0]);
1766 56 : CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1767 56 : CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1768 :
1769 : Handle<Script> script;
1770 28 : CHECK(GetScriptById(isolate, scriptid, &script));
1771 :
1772 : const Script::OffsetFlag offset_flag =
1773 28 : with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1774 56 : return *GetJSPositionInfo(script, position, offset_flag, isolate);
1775 : }
1776 :
1777 : // Returns the given line as a string, or null if line is out of bounds.
1778 : // The parameter line is expected to include the script's line offset.
1779 : // TODO(5530): Remove once uses in debug.js are gone.
1780 120 : RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
1781 60 : HandleScope scope(isolate);
1782 : DCHECK_EQ(2, args.length());
1783 120 : CONVERT_ARG_CHECKED(JSValue, script, 0);
1784 120 : CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1785 :
1786 120 : CHECK(script->value()->IsScript());
1787 60 : Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1788 :
1789 60 : if (script_handle->type() == Script::TYPE_WASM) {
1790 : // Return null for now; this function will disappear soon anyway.
1791 0 : return isolate->heap()->null_value();
1792 : }
1793 :
1794 60 : Script::InitLineEnds(script_handle);
1795 :
1796 60 : FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1797 60 : const int line_count = line_ends_array->length();
1798 :
1799 60 : line -= script_handle->line_offset();
1800 60 : if (line < 0 || line_count <= line) {
1801 0 : return isolate->heap()->null_value();
1802 : }
1803 :
1804 : const int start =
1805 60 : (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1806 60 : const int end = Smi::cast(line_ends_array->get(line))->value();
1807 :
1808 : Handle<String> source =
1809 120 : handle(String::cast(script_handle->source()), isolate);
1810 60 : Handle<String> str = isolate->factory()->NewSubString(source, start, end);
1811 :
1812 60 : return *str;
1813 : }
1814 :
1815 : // On function call, depending on circumstances, prepare for stepping in,
1816 : // or perform a side effect check.
1817 6888300 : RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
1818 1377660 : HandleScope scope(isolate);
1819 : DCHECK_EQ(1, args.length());
1820 2755320 : CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1821 1377660 : if (isolate->debug()->last_step_action() >= StepIn) {
1822 1368204 : isolate->debug()->PrepareStepIn(fun);
1823 : }
1824 1387116 : if (isolate->needs_side_effect_check() &&
1825 9456 : !isolate->debug()->PerformSideEffectCheck(fun)) {
1826 1110 : return isolate->heap()->exception();
1827 : }
1828 1376550 : return isolate->heap()->undefined_value();
1829 : }
1830 :
1831 : // Set one shot breakpoints for the suspended generator object.
1832 432 : RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
1833 216 : HandleScope scope(isolate);
1834 : DCHECK_EQ(0, args.length());
1835 216 : isolate->debug()->PrepareStepInSuspendedGenerator();
1836 216 : return isolate->heap()->undefined_value();
1837 : }
1838 :
1839 1000 : RUNTIME_FUNCTION(Runtime_DebugRecordGenerator) {
1840 250 : HandleScope scope(isolate);
1841 : DCHECK_EQ(1, args.length());
1842 500 : CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
1843 250 : CHECK(isolate->debug()->last_step_action() >= StepNext);
1844 250 : isolate->debug()->RecordGenerator(generator);
1845 250 : return isolate->heap()->undefined_value();
1846 : }
1847 :
1848 42324 : RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
1849 : DCHECK_EQ(1, args.length());
1850 21162 : HandleScope scope(isolate);
1851 42324 : CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
1852 21162 : isolate->PushPromise(promise);
1853 21162 : return isolate->heap()->undefined_value();
1854 : }
1855 :
1856 :
1857 56916 : RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1858 : DCHECK_EQ(0, args.length());
1859 : SealHandleScope shs(isolate);
1860 28458 : isolate->PopPromise();
1861 28458 : return isolate->heap()->undefined_value();
1862 : }
1863 :
1864 29296 : RUNTIME_FUNCTION(Runtime_DebugAsyncFunctionPromiseCreated) {
1865 : DCHECK_EQ(1, args.length());
1866 7324 : HandleScope scope(isolate);
1867 14648 : CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
1868 7324 : isolate->PushPromise(promise);
1869 7324 : int id = isolate->debug()->NextAsyncTaskId(promise);
1870 : Handle<Symbol> async_stack_id_symbol =
1871 7324 : isolate->factory()->promise_async_stack_id_symbol();
1872 : JSObject::SetProperty(promise, async_stack_id_symbol,
1873 : handle(Smi::FromInt(id), isolate), STRICT)
1874 14648 : .Assert();
1875 7324 : isolate->debug()->OnAsyncTaskEvent(debug::kDebugEnqueueAsyncFunction, id, 0);
1876 7324 : return isolate->heap()->undefined_value();
1877 : }
1878 :
1879 2304 : RUNTIME_FUNCTION(Runtime_DebugPromiseReject) {
1880 768 : HandleScope scope(isolate);
1881 : DCHECK_EQ(2, args.length());
1882 1536 : CONVERT_ARG_HANDLE_CHECKED(JSPromise, rejected_promise, 0);
1883 768 : CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1884 :
1885 768 : isolate->debug()->OnPromiseReject(rejected_promise, value);
1886 768 : return isolate->heap()->undefined_value();
1887 : }
1888 :
1889 184660 : RUNTIME_FUNCTION(Runtime_DebugAsyncEventEnqueueRecurring) {
1890 36932 : HandleScope scope(isolate);
1891 : DCHECK_EQ(2, args.length());
1892 73864 : CONVERT_ARG_HANDLE_CHECKED(JSPromise, promise, 0);
1893 73864 : CONVERT_SMI_ARG_CHECKED(status, 1);
1894 36932 : if (isolate->debug()->is_active()) {
1895 : isolate->debug()->OnAsyncTaskEvent(
1896 : status == v8::Promise::kFulfilled ? debug::kDebugEnqueuePromiseResolve
1897 : : debug::kDebugEnqueuePromiseReject,
1898 73864 : isolate->debug()->NextAsyncTaskId(promise), 0);
1899 : }
1900 36932 : return isolate->heap()->undefined_value();
1901 : }
1902 :
1903 1644 : RUNTIME_FUNCTION(Runtime_DebugIsActive) {
1904 : SealHandleScope shs(isolate);
1905 822 : return Smi::FromInt(isolate->debug()->is_active());
1906 : }
1907 :
1908 0 : RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
1909 0 : UNIMPLEMENTED();
1910 : return NULL;
1911 : }
1912 :
1913 112 : RUNTIME_FUNCTION(Runtime_DebugCollectCoverage) {
1914 56 : HandleScope scope(isolate);
1915 : DCHECK_EQ(0, args.length());
1916 : // Collect coverage data.
1917 112 : std::unique_ptr<Coverage> coverage;
1918 56 : if (isolate->is_best_effort_code_coverage()) {
1919 42 : coverage.reset(Coverage::CollectBestEffort(isolate));
1920 : } else {
1921 14 : coverage.reset(Coverage::CollectPrecise(isolate));
1922 : }
1923 56 : Factory* factory = isolate->factory();
1924 : // Turn the returned data structure into JavaScript.
1925 : // Create an array of scripts.
1926 56 : int num_scripts = static_cast<int>(coverage->size());
1927 : // Prepare property keys.
1928 56 : Handle<FixedArray> scripts_array = factory->NewFixedArray(num_scripts);
1929 56 : Handle<String> script_string = factory->NewStringFromStaticChars("script");
1930 56 : Handle<String> start_string = factory->NewStringFromStaticChars("start");
1931 56 : Handle<String> end_string = factory->NewStringFromStaticChars("end");
1932 56 : Handle<String> count_string = factory->NewStringFromStaticChars("count");
1933 196 : for (int i = 0; i < num_scripts; i++) {
1934 196 : const auto& script_data = coverage->at(i);
1935 196 : HandleScope inner_scope(isolate);
1936 196 : int num_functions = static_cast<int>(script_data.functions.size());
1937 196 : Handle<FixedArray> functions_array = factory->NewFixedArray(num_functions);
1938 2205 : for (int j = 0; j < num_functions; j++) {
1939 2205 : const auto& function_data = script_data.functions[j];
1940 2205 : Handle<JSObject> range_obj = factory->NewJSObjectWithNullProto();
1941 : JSObject::AddProperty(range_obj, start_string,
1942 : factory->NewNumberFromInt(function_data.start),
1943 4410 : NONE);
1944 : JSObject::AddProperty(range_obj, end_string,
1945 4410 : factory->NewNumberFromInt(function_data.end), NONE);
1946 : JSObject::AddProperty(range_obj, count_string,
1947 : factory->NewNumberFromUint(function_data.count),
1948 4410 : NONE);
1949 2205 : functions_array->set(j, *range_obj);
1950 : }
1951 : Handle<JSArray> script_obj =
1952 196 : factory->NewJSArrayWithElements(functions_array, FAST_ELEMENTS);
1953 196 : Handle<JSObject> wrapper = Script::GetWrapper(script_data.script);
1954 196 : JSObject::AddProperty(script_obj, script_string, wrapper, NONE);
1955 196 : scripts_array->set(i, *script_obj);
1956 196 : }
1957 168 : return *factory->NewJSArrayWithElements(scripts_array, FAST_ELEMENTS);
1958 : }
1959 :
1960 28 : RUNTIME_FUNCTION(Runtime_DebugTogglePreciseCoverage) {
1961 : SealHandleScope shs(isolate);
1962 28 : CONVERT_BOOLEAN_ARG_CHECKED(enable, 0);
1963 : Coverage::SelectMode(isolate, enable ? debug::Coverage::kPreciseCount
1964 14 : : debug::Coverage::kBestEffort);
1965 14 : return isolate->heap()->undefined_value();
1966 : }
1967 :
1968 : } // namespace internal
1969 : } // namespace v8
|