blob: 2d217b83f7fc8d3ddd0b60f7355794994aeb09e8 [file] [log] [blame]
Emily Bernier958fae72015-03-24 16:35:39 -04001// 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
Emily Bernier958fae72015-03-24 16:35:39 -04005#include "src/runtime/runtime-utils.h"
6
Ben Murdoch014dc512016-03-22 12:00:34 +00007#include "src/arguments.h"
Ben Murdoch014dc512016-03-22 12:00:34 +00008#include "src/debug/debug-evaluate.h"
9#include "src/debug/debug-frames.h"
10#include "src/debug/debug-scopes.h"
Ben Murdoch3b9bc312016-06-02 14:46:10 +010011#include "src/debug/debug.h"
Ben Murdochf3b273f2017-01-17 12:11:28 +000012#include "src/debug/liveedit.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000013#include "src/frames-inl.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000014#include "src/globals.h"
Ben Murdoch3b9bc312016-06-02 14:46:10 +010015#include "src/interpreter/bytecodes.h"
16#include "src/interpreter/interpreter.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000017#include "src/isolate-inl.h"
18#include "src/runtime/runtime.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000019#include "src/wasm/wasm-debug.h"
20#include "src/wasm/wasm-module.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000021
Emily Bernier958fae72015-03-24 16:35:39 -040022namespace v8 {
23namespace internal {
24
25RUNTIME_FUNCTION(Runtime_DebugBreak) {
26 SealHandleScope shs(isolate);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010027 DCHECK(args.length() == 1);
28 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
29 isolate->debug()->set_return_value(value);
30
Ben Murdoch014dc512016-03-22 12:00:34 +000031 // Get the top-most JavaScript frame.
32 JavaScriptFrameIterator it(isolate);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010033 isolate->debug()->Break(it.frame());
34
35 isolate->debug()->SetAfterBreakTarget(it.frame());
36 return *isolate->debug()->return_value();
37}
38
39RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
40 SealHandleScope shs(isolate);
41 DCHECK(args.length() == 1);
42 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
43 isolate->debug()->set_return_value(value);
44
45 // Get the top-most JavaScript frame.
46 JavaScriptFrameIterator it(isolate);
47 isolate->debug()->Break(it.frame());
48
Ben Murdochbcf72ee2016-08-08 18:44:38 +010049 // If live-edit has dropped frames, we are not going back to dispatch.
50 if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0);
51
Ben Murdoch3b9bc312016-06-02 14:46:10 +010052 // Return the handler from the original bytecode array.
53 DCHECK(it.frame()->is_interpreted());
54 InterpretedFrame* interpreted_frame =
55 reinterpret_cast<InterpretedFrame*>(it.frame());
56 SharedFunctionInfo* shared = interpreted_frame->function()->shared();
57 BytecodeArray* bytecode_array = shared->bytecode_array();
58 int bytecode_offset = interpreted_frame->GetBytecodeOffset();
59 interpreter::Bytecode bytecode =
60 interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
61 return isolate->interpreter()->GetBytecodeHandler(
62 bytecode, interpreter::OperandScale::kSingle);
Emily Bernier958fae72015-03-24 16:35:39 -040063}
64
65
Ben Murdoch014dc512016-03-22 12:00:34 +000066RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
67 SealHandleScope shs(isolate);
68 DCHECK(args.length() == 0);
69 if (isolate->debug()->break_points_active()) {
70 isolate->debug()->HandleDebugBreak();
71 }
72 return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -040073}
74
75
76// Adds a JavaScript function as a debug event listener.
77// args[0]: debug event listener function to set or null or undefined for
78// clearing the event listener function
79// args[1]: object supplied during callback
80RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
81 SealHandleScope shs(isolate);
82 DCHECK(args.length() == 2);
Ben Murdochf91f0612016-11-29 16:50:11 +000083 CHECK(args[0]->IsJSFunction() || args[0]->IsUndefined(isolate) ||
84 args[0]->IsNull(isolate));
Emily Bernier958fae72015-03-24 16:35:39 -040085 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
86 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
87 isolate->debug()->SetEventListener(callback, data);
88
89 return isolate->heap()->undefined_value();
90}
91
92
Ben Murdoch014dc512016-03-22 12:00:34 +000093RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
Emily Bernier958fae72015-03-24 16:35:39 -040094 SealHandleScope shs(isolate);
95 DCHECK(args.length() == 0);
96 isolate->stack_guard()->RequestDebugBreak();
97 return isolate->heap()->undefined_value();
98}
99
100
101static Handle<Object> DebugGetProperty(LookupIterator* it,
102 bool* has_caught = NULL) {
103 for (; it->IsFound(); it->Next()) {
104 switch (it->state()) {
105 case LookupIterator::NOT_FOUND:
106 case LookupIterator::TRANSITION:
107 UNREACHABLE();
108 case LookupIterator::ACCESS_CHECK:
109 // Ignore access checks.
110 break;
Ben Murdoch014dc512016-03-22 12:00:34 +0000111 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Emily Bernier958fae72015-03-24 16:35:39 -0400112 case LookupIterator::INTERCEPTOR:
113 case LookupIterator::JSPROXY:
114 return it->isolate()->factory()->undefined_value();
115 case LookupIterator::ACCESSOR: {
116 Handle<Object> accessors = it->GetAccessors();
117 if (!accessors->IsAccessorInfo()) {
118 return it->isolate()->factory()->undefined_value();
119 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000120 MaybeHandle<Object> maybe_result =
Ben Murdoch109988c2016-05-18 11:27:45 +0100121 JSObject::GetPropertyWithAccessor(it);
Emily Bernier958fae72015-03-24 16:35:39 -0400122 Handle<Object> result;
123 if (!maybe_result.ToHandle(&result)) {
124 result = handle(it->isolate()->pending_exception(), it->isolate());
125 it->isolate()->clear_pending_exception();
126 if (has_caught != NULL) *has_caught = true;
127 }
128 return result;
129 }
130
131 case LookupIterator::DATA:
132 return it->GetDataValue();
133 }
134 }
135
136 return it->isolate()->factory()->undefined_value();
137}
138
139
Ben Murdoch014dc512016-03-22 12:00:34 +0000140static Handle<Object> DebugGetProperty(Handle<Object> object,
141 Handle<Name> name) {
142 LookupIterator it(object, name);
143 return DebugGetProperty(&it);
144}
145
146
147template <class IteratorType>
148static MaybeHandle<JSArray> GetIteratorInternalProperties(
149 Isolate* isolate, Handle<IteratorType> object) {
150 Factory* factory = isolate->factory();
151 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100152 CHECK(iterator->kind()->IsSmi());
Ben Murdoch014dc512016-03-22 12:00:34 +0000153 const char* kind = NULL;
154 switch (Smi::cast(iterator->kind())->value()) {
155 case IteratorType::kKindKeys:
156 kind = "keys";
157 break;
158 case IteratorType::kKindValues:
159 kind = "values";
160 break;
161 case IteratorType::kKindEntries:
162 kind = "entries";
163 break;
164 default:
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100165 UNREACHABLE();
Ben Murdoch014dc512016-03-22 12:00:34 +0000166 }
167
168 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
169 Handle<String> has_more =
170 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
171 result->set(0, *has_more);
172 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
173
174 Handle<String> index =
175 factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
176 result->set(2, *index);
177 result->set(3, iterator->index());
178
179 Handle<String> iterator_kind =
180 factory->NewStringFromAsciiChecked("[[IteratorKind]]");
181 result->set(4, *iterator_kind);
182 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
183 result->set(5, *kind_str);
184 return factory->NewJSArrayWithElements(result);
185}
186
187
188MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
189 Handle<Object> object) {
190 Factory* factory = isolate->factory();
191 if (object->IsJSBoundFunction()) {
192 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
193
194 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
195 Handle<String> target =
196 factory->NewStringFromAsciiChecked("[[TargetFunction]]");
197 result->set(0, *target);
198 result->set(1, function->bound_target_function());
199
200 Handle<String> bound_this =
201 factory->NewStringFromAsciiChecked("[[BoundThis]]");
202 result->set(2, *bound_this);
203 result->set(3, function->bound_this());
204
205 Handle<String> bound_args =
206 factory->NewStringFromAsciiChecked("[[BoundArgs]]");
207 result->set(4, *bound_args);
208 Handle<FixedArray> bound_arguments =
209 factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
210 Handle<JSArray> arguments_array =
211 factory->NewJSArrayWithElements(bound_arguments);
212 result->set(5, *arguments_array);
213 return factory->NewJSArrayWithElements(result);
214 } else if (object->IsJSMapIterator()) {
215 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
216 return GetIteratorInternalProperties(isolate, iterator);
217 } else if (object->IsJSSetIterator()) {
218 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
219 return GetIteratorInternalProperties(isolate, iterator);
220 } else if (object->IsJSGeneratorObject()) {
221 Handle<JSGeneratorObject> generator =
222 Handle<JSGeneratorObject>::cast(object);
223
224 const char* status = "suspended";
225 if (generator->is_closed()) {
226 status = "closed";
227 } else if (generator->is_executing()) {
228 status = "running";
229 } else {
230 DCHECK(generator->is_suspended());
231 }
232
233 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
234 Handle<String> generator_status =
235 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
236 result->set(0, *generator_status);
237 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
238 result->set(1, *status_str);
239
240 Handle<String> function =
241 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
242 result->set(2, *function);
243 result->set(3, generator->function());
244
245 Handle<String> receiver =
246 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
247 result->set(4, *receiver);
248 result->set(5, generator->receiver());
249 return factory->NewJSArrayWithElements(result);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100250 } else if (object->IsJSPromise()) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000251 Handle<JSObject> promise = Handle<JSObject>::cast(object);
252
253 Handle<Object> status_obj =
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100254 DebugGetProperty(promise, isolate->factory()->promise_state_symbol());
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100255 CHECK(status_obj->IsSmi());
Ben Murdoch014dc512016-03-22 12:00:34 +0000256 const char* status = "rejected";
257 int status_val = Handle<Smi>::cast(status_obj)->value();
258 switch (status_val) {
259 case +1:
260 status = "resolved";
261 break;
262 case 0:
263 status = "pending";
264 break;
265 default:
266 DCHECK_EQ(-1, status_val);
267 }
268
269 Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
270 Handle<String> promise_status =
271 factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
272 result->set(0, *promise_status);
273 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
274 result->set(1, *status_str);
275
276 Handle<Object> value_obj =
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100277 DebugGetProperty(promise, isolate->factory()->promise_result_symbol());
Ben Murdoch014dc512016-03-22 12:00:34 +0000278 Handle<String> promise_value =
279 factory->NewStringFromAsciiChecked("[[PromiseValue]]");
280 result->set(2, *promise_value);
281 result->set(3, *value_obj);
282 return factory->NewJSArrayWithElements(result);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100283 } else if (object->IsJSProxy()) {
284 Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
285 Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
286
287 Handle<String> handler_str =
288 factory->NewStringFromAsciiChecked("[[Handler]]");
289 result->set(0, *handler_str);
290 result->set(1, js_proxy->handler());
291
292 Handle<String> target_str =
293 factory->NewStringFromAsciiChecked("[[Target]]");
294 result->set(2, *target_str);
295 result->set(3, js_proxy->target());
296
297 Handle<String> is_revoked_str =
298 factory->NewStringFromAsciiChecked("[[IsRevoked]]");
299 result->set(4, *is_revoked_str);
300 result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
301 return factory->NewJSArrayWithElements(result);
Ben Murdoch014dc512016-03-22 12:00:34 +0000302 } else if (object->IsJSValue()) {
303 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
304
305 Handle<FixedArray> result = factory->NewFixedArray(2);
306 Handle<String> primitive_value =
307 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
308 result->set(0, *primitive_value);
309 result->set(1, js_value->value());
310 return factory->NewJSArrayWithElements(result);
311 }
312 return factory->NewJSArray(0);
313}
314
315
316RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
317 HandleScope scope(isolate);
318 DCHECK(args.length() == 1);
319 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100320 RETURN_RESULT_OR_FAILURE(isolate,
321 Runtime::GetInternalProperties(isolate, obj));
Ben Murdoch014dc512016-03-22 12:00:34 +0000322}
323
324
Emily Bernier958fae72015-03-24 16:35:39 -0400325// Get debugger related details for an object property, in the following format:
326// 0: Property value
327// 1: Property details
328// 2: Property value is exception
329// 3: Getter function if defined
330// 4: Setter function if defined
331// Items 2-4 are only filled if the property has either a getter or a setter.
332RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
333 HandleScope scope(isolate);
Ben Murdochf91f0612016-11-29 16:50:11 +0000334 DCHECK_EQ(2, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -0400335 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdochf91f0612016-11-29 16:50:11 +0000336 CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
337
338 // Convert the {name_obj} to a Name.
339 Handle<Name> name;
340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
341 Object::ToName(isolate, name_obj));
Emily Bernier958fae72015-03-24 16:35:39 -0400342
343 // Make sure to set the current context to the context before the debugger was
344 // entered (if the debugger is entered). The reason for switching context here
345 // is that for some property lookups (accessors and interceptors) callbacks
346 // into the embedding application can occour, and the embedding application
347 // could have the assumption that its own native context is the current
348 // context and not some internal debugger context.
349 SaveContext save(isolate);
350 if (isolate->debug()->in_debug_scope()) {
351 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
352 }
353
354 // Check if the name is trivially convertible to an index and get the element
355 // if so.
356 uint32_t index;
Ben Murdoch014dc512016-03-22 12:00:34 +0000357 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
358 // this special case.
Emily Bernier958fae72015-03-24 16:35:39 -0400359 if (name->AsArrayIndex(&index)) {
360 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
361 Handle<Object> element_or_char;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100362 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
363 isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
Emily Bernier958fae72015-03-24 16:35:39 -0400364 details->set(0, *element_or_char);
Ben Murdoch014dc512016-03-22 12:00:34 +0000365 details->set(1, PropertyDetails::Empty().AsSmi());
Emily Bernier958fae72015-03-24 16:35:39 -0400366 return *isolate->factory()->NewJSArrayWithElements(details);
367 }
368
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100369 LookupIterator it(obj, name, LookupIterator::OWN);
Emily Bernier958fae72015-03-24 16:35:39 -0400370 bool has_caught = false;
371 Handle<Object> value = DebugGetProperty(&it, &has_caught);
372 if (!it.IsFound()) return isolate->heap()->undefined_value();
373
374 Handle<Object> maybe_pair;
375 if (it.state() == LookupIterator::ACCESSOR) {
376 maybe_pair = it.GetAccessors();
377 }
378
379 // If the callback object is a fixed array then it contains JavaScript
380 // getter and/or setter.
381 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
382 Handle<FixedArray> details =
383 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
384 details->set(0, *value);
385 // TODO(verwaest): Get rid of this random way of handling interceptors.
386 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
Ben Murdoch014dc512016-03-22 12:00:34 +0000387 ? PropertyDetails::Empty()
Emily Bernier958fae72015-03-24 16:35:39 -0400388 : it.property_details();
389 details->set(1, d.AsSmi());
390 details->set(
391 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
392 if (has_js_accessors) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100393 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
Emily Bernier958fae72015-03-24 16:35:39 -0400394 details->set(3, isolate->heap()->ToBoolean(has_caught));
Ben Murdoch109988c2016-05-18 11:27:45 +0100395 Handle<Object> getter =
396 AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
397 Handle<Object> setter =
398 AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
399 details->set(4, *getter);
400 details->set(5, *setter);
Emily Bernier958fae72015-03-24 16:35:39 -0400401 }
402
403 return *isolate->factory()->NewJSArrayWithElements(details);
404}
405
406
407RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
408 HandleScope scope(isolate);
409
410 DCHECK(args.length() == 2);
411
Ben Murdochf91f0612016-11-29 16:50:11 +0000412 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Emily Bernier958fae72015-03-24 16:35:39 -0400413 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
414
415 LookupIterator it(obj, name);
416 return *DebugGetProperty(&it);
417}
418
419
420// Return the property type calculated from the property details.
421// args[0]: smi with property details.
422RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
423 SealHandleScope shs(isolate);
424 DCHECK(args.length() == 1);
425 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
426 return Smi::FromInt(static_cast<int>(details.type()));
427}
428
429
430// Return the property attribute calculated from the property details.
431// args[0]: smi with property details.
432RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
433 SealHandleScope shs(isolate);
434 DCHECK(args.length() == 1);
435 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
436 return Smi::FromInt(static_cast<int>(details.attributes()));
437}
438
439
Emily Bernier958fae72015-03-24 16:35:39 -0400440RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
441 SealHandleScope shs(isolate);
442 DCHECK(args.length() == 1);
443 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000444 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400445 return isolate->heap()->true_value();
446}
447
448
449RUNTIME_FUNCTION(Runtime_GetFrameCount) {
450 HandleScope scope(isolate);
451 DCHECK(args.length() == 1);
452 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000453 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400454
455 // Count all frames which are relevant to debugging stack trace.
456 int n = 0;
457 StackFrame::Id id = isolate->debug()->break_frame_id();
458 if (id == StackFrame::NO_ID) {
459 // If there is no JavaScript stack frame count is 0.
460 return Smi::FromInt(0);
461 }
462
Ben Murdochf91f0612016-11-29 16:50:11 +0000463 for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400464 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
Ben Murdochf91f0612016-11-29 16:50:11 +0000465 if (it.is_wasm()) {
466 n++;
467 } else {
468 it.javascript_frame()->Summarize(&frames);
469 for (int i = frames.length() - 1; i >= 0; i--) {
470 // Omit functions from native and extension scripts.
471 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
472 }
Emily Bernier958fae72015-03-24 16:35:39 -0400473 }
474 }
475 return Smi::FromInt(n);
476}
477
478
Emily Bernier958fae72015-03-24 16:35:39 -0400479static const int kFrameDetailsFrameIdIndex = 0;
480static const int kFrameDetailsReceiverIndex = 1;
481static const int kFrameDetailsFunctionIndex = 2;
Ben Murdochf91f0612016-11-29 16:50:11 +0000482static const int kFrameDetailsScriptIndex = 3;
483static const int kFrameDetailsArgumentCountIndex = 4;
484static const int kFrameDetailsLocalCountIndex = 5;
485static const int kFrameDetailsSourcePositionIndex = 6;
486static const int kFrameDetailsConstructCallIndex = 7;
487static const int kFrameDetailsAtReturnIndex = 8;
488static const int kFrameDetailsFlagsIndex = 9;
489static const int kFrameDetailsFirstDynamicIndex = 10;
Emily Bernier958fae72015-03-24 16:35:39 -0400490
Emily Bernier958fae72015-03-24 16:35:39 -0400491// Return an array with frame details
492// args[0]: number: break id
493// args[1]: number: frame index
494//
495// The array returned contains the following information:
496// 0: Frame id
497// 1: Receiver
498// 2: Function
Ben Murdochf91f0612016-11-29 16:50:11 +0000499// 3: Script
500// 4: Argument count
501// 5: Local count
502// 6: Source position
503// 7: Constructor call
504// 8: Is at return
505// 9: Flags
Emily Bernier958fae72015-03-24 16:35:39 -0400506// Arguments name, value
507// Locals name, value
508// Return value if any
509RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
510 HandleScope scope(isolate);
511 DCHECK(args.length() == 2);
512 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000513 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400514
515 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
516 Heap* heap = isolate->heap();
517
518 // Find the relevant frame with the requested index.
519 StackFrame::Id id = isolate->debug()->break_frame_id();
520 if (id == StackFrame::NO_ID) {
521 // If there are no JavaScript stack frames return undefined.
522 return heap->undefined_value();
523 }
524
Ben Murdochf91f0612016-11-29 16:50:11 +0000525 StackTraceFrameIterator it(isolate, id);
Emily Bernier958fae72015-03-24 16:35:39 -0400526 // Inlined frame index in optimized frame, starting from outer function.
Ben Murdoch014dc512016-03-22 12:00:34 +0000527 int inlined_jsframe_index =
528 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
Emily Bernier958fae72015-03-24 16:35:39 -0400529 if (inlined_jsframe_index == -1) return heap->undefined_value();
530
531 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400532
533 // Traverse the saved contexts chain to find the active context for the
534 // selected frame.
Ben Murdoch014dc512016-03-22 12:00:34 +0000535 SaveContext* save =
536 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
Emily Bernier958fae72015-03-24 16:35:39 -0400537
538 // Get the frame id.
Ben Murdoch014dc512016-03-22 12:00:34 +0000539 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
540 isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400541
542 // Find source position in unoptimized code.
543 int position = frame_inspector.GetSourcePosition();
544
Ben Murdochf91f0612016-11-29 16:50:11 +0000545 if (it.is_wasm()) {
546 // Create the details array (no dynamic information for wasm).
547 Handle<FixedArray> details =
548 isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
549
550 // Add the frame id.
551 details->set(kFrameDetailsFrameIdIndex, *frame_id);
552
553 // Add the function name.
554 Handle<Object> wasm_obj(it.wasm_frame()->wasm_obj(), isolate);
555 int func_index = it.wasm_frame()->function_index();
556 Handle<String> func_name =
557 wasm::GetWasmFunctionName(isolate, wasm_obj, func_index);
558 details->set(kFrameDetailsFunctionIndex, *func_name);
559
560 // Add the script wrapper
561 Handle<Object> script_wrapper =
562 Script::GetWrapper(frame_inspector.GetScript());
563 details->set(kFrameDetailsScriptIndex, *script_wrapper);
564
565 // Add the arguments count.
566 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(0));
567
568 // Add the locals count
569 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(0));
570
571 // Add the source position.
572 if (position != kNoSourcePosition) {
573 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
574 }
575
576 // Add the constructor information.
577 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
578
579 // Add the at return information.
580 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
581
582 // Add flags to indicate information on whether this frame is
583 // bit 0: invoked in the debugger context.
584 // bit 1: optimized frame.
585 // bit 2: inlined in optimized frame
586 int flags = 0;
587 if (*save->context() == *isolate->debug()->debug_context()) {
588 flags |= 1 << 0;
589 }
590 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
591
592 return *isolate->factory()->NewJSArrayWithElements(details);
593 }
594
595 // Handle JavaScript frames.
596 bool is_optimized = it.frame()->is_optimized();
597
Emily Bernier958fae72015-03-24 16:35:39 -0400598 // Check for constructor frame.
599 bool constructor = frame_inspector.IsConstructor();
600
601 // Get scope info and read from it for local variable information.
Ben Murdoch109988c2016-05-18 11:27:45 +0100602 Handle<JSFunction> function =
603 Handle<JSFunction>::cast(frame_inspector.GetFunction());
Ben Murdochf91f0612016-11-29 16:50:11 +0000604 CHECK(function->shared()->IsSubjectToDebugging());
Emily Bernier958fae72015-03-24 16:35:39 -0400605 Handle<SharedFunctionInfo> shared(function->shared());
606 Handle<ScopeInfo> scope_info(shared->scope_info());
607 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
608
609 // Get the locals names and values into a temporary array.
Ben Murdochf91f0612016-11-29 16:50:11 +0000610 Handle<Object> maybe_context = frame_inspector.GetContext();
611 const int local_count_with_synthetic = maybe_context->IsContext()
612 ? scope_info->LocalCount()
613 : scope_info->StackLocalCount();
614 int local_count = local_count_with_synthetic;
615 for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
Emily Bernier958fae72015-03-24 16:35:39 -0400616 // Hide compiler-introduced temporary variables, whether on the stack or on
617 // the context.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100618 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
619 local_count--;
620 }
Emily Bernier958fae72015-03-24 16:35:39 -0400621 }
622
Ben Murdochf91f0612016-11-29 16:50:11 +0000623 List<Handle<Object>> locals;
Emily Bernier958fae72015-03-24 16:35:39 -0400624 // Fill in the values of the locals.
Emily Bernier958fae72015-03-24 16:35:39 -0400625 int i = 0;
626 for (; i < scope_info->StackLocalCount(); ++i) {
627 // Use the value from the stack.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100628 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
Ben Murdochf91f0612016-11-29 16:50:11 +0000629 locals.Add(Handle<String>(scope_info->LocalName(i), isolate));
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100630 Handle<Object> value =
631 frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100632 // TODO(yangguo): We convert optimized out values to {undefined} when they
633 // are passed to the debugger. Eventually we should handle them somehow.
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100634 if (value->IsOptimizedOut(isolate)) {
635 value = isolate->factory()->undefined_value();
636 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000637 locals.Add(value);
Emily Bernier958fae72015-03-24 16:35:39 -0400638 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000639 if (locals.length() < local_count * 2) {
Emily Bernier958fae72015-03-24 16:35:39 -0400640 // Get the context containing declarations.
Ben Murdochf91f0612016-11-29 16:50:11 +0000641 DCHECK(maybe_context->IsContext());
642 Handle<Context> context(Context::cast(*maybe_context)->closure_context());
643
Emily Bernier958fae72015-03-24 16:35:39 -0400644 for (; i < scope_info->LocalCount(); ++i) {
Emily Bernier958fae72015-03-24 16:35:39 -0400645 Handle<String> name(scope_info->LocalName(i));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100646 if (ScopeInfo::VariableIsSynthetic(*name)) continue;
Emily Bernier958fae72015-03-24 16:35:39 -0400647 VariableMode mode;
648 InitializationFlag init_flag;
649 MaybeAssignedFlag maybe_assigned_flag;
Ben Murdochf91f0612016-11-29 16:50:11 +0000650 locals.Add(name);
Emily Bernier958fae72015-03-24 16:35:39 -0400651 int context_slot_index = ScopeInfo::ContextSlotIndex(
652 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
653 Object* value = context->get(context_slot_index);
Ben Murdochf91f0612016-11-29 16:50:11 +0000654 locals.Add(Handle<Object>(value, isolate));
Emily Bernier958fae72015-03-24 16:35:39 -0400655 }
656 }
657
658 // Check whether this frame is positioned at return. If not top
659 // frame or if the frame is optimized it cannot be at a return.
660 bool at_return = false;
661 if (!is_optimized && index == 0) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000662 at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
Emily Bernier958fae72015-03-24 16:35:39 -0400663 }
664
665 // If positioned just before return find the value to be returned and add it
666 // to the frame information.
667 Handle<Object> return_value = isolate->factory()->undefined_value();
668 if (at_return) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100669 return_value = isolate->debug()->return_value();
Emily Bernier958fae72015-03-24 16:35:39 -0400670 }
671
672 // Now advance to the arguments adapter frame (if any). It contains all
673 // the provided parameters whereas the function frame always have the number
674 // of arguments matching the functions parameters. The rest of the
675 // information (except for what is collected above) is the same.
Ben Murdochf91f0612016-11-29 16:50:11 +0000676 if ((inlined_jsframe_index == 0) &&
677 it.javascript_frame()->has_adapted_arguments()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400678 it.AdvanceToArgumentsFrame();
679 frame_inspector.SetArgumentsFrame(it.frame());
680 }
681
682 // Find the number of arguments to fill. At least fill the number of
683 // parameters for the function and fill more if more parameters are provided.
684 int argument_count = scope_info->ParameterCount();
685 if (argument_count < frame_inspector.GetParametersCount()) {
686 argument_count = frame_inspector.GetParametersCount();
687 }
688
689 // Calculate the size of the result.
690 int details_size = kFrameDetailsFirstDynamicIndex +
691 2 * (argument_count + local_count) + (at_return ? 1 : 0);
692 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
693
694 // Add the frame id.
695 details->set(kFrameDetailsFrameIdIndex, *frame_id);
696
697 // Add the function (same as in function frame).
Ben Murdoch109988c2016-05-18 11:27:45 +0100698 details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
Emily Bernier958fae72015-03-24 16:35:39 -0400699
Ben Murdochf91f0612016-11-29 16:50:11 +0000700 // Add the script wrapper
701 Handle<Object> script_wrapper =
702 Script::GetWrapper(frame_inspector.GetScript());
703 details->set(kFrameDetailsScriptIndex, *script_wrapper);
704
Emily Bernier958fae72015-03-24 16:35:39 -0400705 // Add the arguments count.
706 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
707
708 // Add the locals count
709 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
710
711 // Add the source position.
Ben Murdochf91f0612016-11-29 16:50:11 +0000712 if (position != kNoSourcePosition) {
Emily Bernier958fae72015-03-24 16:35:39 -0400713 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
714 } else {
715 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
716 }
717
718 // Add the constructor information.
719 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
720
721 // Add the at return information.
722 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
723
724 // Add flags to indicate information on whether this frame is
725 // bit 0: invoked in the debugger context.
726 // bit 1: optimized frame.
727 // bit 2: inlined in optimized frame
728 int flags = 0;
729 if (*save->context() == *isolate->debug()->debug_context()) {
730 flags |= 1 << 0;
731 }
732 if (is_optimized) {
733 flags |= 1 << 1;
734 flags |= inlined_jsframe_index << 2;
735 }
736 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
737
738 // Fill the dynamic part.
739 int details_index = kFrameDetailsFirstDynamicIndex;
740
741 // Add arguments name and value.
742 for (int i = 0; i < argument_count; i++) {
743 // Name of the argument.
744 if (i < scope_info->ParameterCount()) {
745 details->set(details_index++, scope_info->ParameterName(i));
746 } else {
747 details->set(details_index++, heap->undefined_value());
748 }
749
750 // Parameter value.
751 if (i < frame_inspector.GetParametersCount()) {
752 // Get the value from the stack.
Ben Murdoch109988c2016-05-18 11:27:45 +0100753 details->set(details_index++, *(frame_inspector.GetParameter(i)));
Emily Bernier958fae72015-03-24 16:35:39 -0400754 } else {
755 details->set(details_index++, heap->undefined_value());
756 }
757 }
758
759 // Add locals name and value from the temporary copy from the function frame.
Ben Murdochf91f0612016-11-29 16:50:11 +0000760 for (const auto& local : locals) details->set(details_index++, *local);
Emily Bernier958fae72015-03-24 16:35:39 -0400761
762 // Add the value being returned.
763 if (at_return) {
764 details->set(details_index++, *return_value);
765 }
766
767 // Add the receiver (same as in function frame).
Emily Bernier958fae72015-03-24 16:35:39 -0400768 Handle<Object> receiver(it.frame()->receiver(), isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000769 DCHECK(!function->shared()->IsBuiltin());
Ben Murdoch109988c2016-05-18 11:27:45 +0100770 DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver());
Emily Bernier958fae72015-03-24 16:35:39 -0400771 details->set(kFrameDetailsReceiverIndex, *receiver);
772
773 DCHECK_EQ(details_size, details_index);
774 return *isolate->factory()->NewJSArrayWithElements(details);
775}
776
777
Emily Bernier958fae72015-03-24 16:35:39 -0400778RUNTIME_FUNCTION(Runtime_GetScopeCount) {
779 HandleScope scope(isolate);
780 DCHECK(args.length() == 2);
781 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000782 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400783
784 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
785
786 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000787 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400788 JavaScriptFrameIterator it(isolate, id);
789 JavaScriptFrame* frame = it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000790 FrameInspector frame_inspector(frame, 0, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400791
792 // Count the visible scopes.
793 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000794 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400795 n++;
796 }
797
798 return Smi::FromInt(n);
799}
800
801
Emily Bernier958fae72015-03-24 16:35:39 -0400802// Return an array with scope details
803// args[0]: number: break id
804// args[1]: number: frame index
805// args[2]: number: inlined frame index
806// args[3]: number: scope index
807//
808// The array returned contains the following information:
809// 0: Scope type
810// 1: Scope object
811RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
812 HandleScope scope(isolate);
813 DCHECK(args.length() == 4);
814 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000815 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400816
817 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
818 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
819 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
820
821 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000822 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400823 JavaScriptFrameIterator frame_it(isolate, id);
824 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000825 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400826
827 // Find the requested scope.
828 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000829 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -0400830 for (; !it.Done() && n < index; it.Next()) {
831 n++;
832 }
833 if (it.Done()) {
834 return isolate->heap()->undefined_value();
835 }
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100836 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400837}
838
839
840// Return an array of scope details
841// args[0]: number: break id
842// args[1]: number: frame index
843// args[2]: number: inlined frame index
844// args[3]: boolean: ignore nested scopes
845//
846// The array returned contains arrays with the following information:
847// 0: Scope type
848// 1: Scope object
849RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
850 HandleScope scope(isolate);
851 DCHECK(args.length() == 3 || args.length() == 4);
852 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000853 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400854
855 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
856 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
857
Ben Murdoch014dc512016-03-22 12:00:34 +0000858 ScopeIterator::Option option = ScopeIterator::DEFAULT;
Emily Bernier958fae72015-03-24 16:35:39 -0400859 if (args.length() == 4) {
860 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
Ben Murdoch014dc512016-03-22 12:00:34 +0000861 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
Emily Bernier958fae72015-03-24 16:35:39 -0400862 }
863
864 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000865 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Ben Murdochf91f0612016-11-29 16:50:11 +0000866 StackTraceFrameIterator frame_it(isolate, id);
867 StandardFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000868 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400869
870 List<Handle<JSObject> > result(4);
Ben Murdoch014dc512016-03-22 12:00:34 +0000871 ScopeIterator it(isolate, &frame_inspector, option);
Emily Bernier958fae72015-03-24 16:35:39 -0400872 for (; !it.Done(); it.Next()) {
873 Handle<JSObject> details;
874 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch014dc512016-03-22 12:00:34 +0000875 it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400876 result.Add(details);
877 }
878
879 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
880 for (int i = 0; i < result.length(); ++i) {
881 array->set(i, *result[i]);
882 }
883 return *isolate->factory()->NewJSArrayWithElements(array);
884}
885
886
887RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
888 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000889 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -0400890
891 // Check arguments.
Ben Murdoch014dc512016-03-22 12:00:34 +0000892 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -0400893
894 // Count the visible scopes.
895 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000896 if (function->IsJSFunction()) {
897 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
898 !it.Done(); it.Next()) {
899 n++;
900 }
Emily Bernier958fae72015-03-24 16:35:39 -0400901 }
902
903 return Smi::FromInt(n);
904}
905
906
907RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
908 HandleScope scope(isolate);
909 DCHECK(args.length() == 2);
910
911 // Check arguments.
912 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
913 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
914
915 // Find the requested scope.
916 int n = 0;
917 ScopeIterator it(isolate, fun);
918 for (; !it.Done() && n < index; it.Next()) {
919 n++;
920 }
921 if (it.Done()) {
922 return isolate->heap()->undefined_value();
923 }
924
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100925 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400926}
927
Ben Murdochf91f0612016-11-29 16:50:11 +0000928RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
929 HandleScope scope(isolate);
930 DCHECK_EQ(1, args.length());
931
932 if (!args[0]->IsJSGeneratorObject()) return Smi::FromInt(0);
933
934 // Check arguments.
935 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
936
937 // Count the visible scopes.
938 int n = 0;
939 for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
940 n++;
941 }
942
943 return Smi::FromInt(n);
944}
945
946RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
947 HandleScope scope(isolate);
948 DCHECK(args.length() == 2);
949
950 if (!args[0]->IsJSGeneratorObject()) {
951 return *isolate->factory()->undefined_value();
952 }
953
954 // Check arguments.
955 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
956 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
957
958 // Find the requested scope.
959 int n = 0;
960 ScopeIterator it(isolate, gen);
961 for (; !it.Done() && n < index; it.Next()) {
962 n++;
963 }
964 if (it.Done()) {
965 return isolate->heap()->undefined_value();
966 }
967
968 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
969}
Emily Bernier958fae72015-03-24 16:35:39 -0400970
971static bool SetScopeVariableValue(ScopeIterator* it, int index,
972 Handle<String> variable_name,
973 Handle<Object> new_value) {
974 for (int n = 0; !it->Done() && n < index; it->Next()) {
975 n++;
976 }
977 if (it->Done()) {
978 return false;
979 }
980 return it->SetVariableValue(variable_name, new_value);
981}
982
983
984// Change variable value in closure or local scope
985// args[0]: number or JsFunction: break id or function
986// args[1]: number: frame index (when arg[0] is break id)
987// args[2]: number: inlined frame index (when arg[0] is break id)
988// args[3]: number: scope index
989// args[4]: string: variable name
990// args[5]: object: new value
991//
992// Return true if success and false otherwise
993RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
994 HandleScope scope(isolate);
995 DCHECK(args.length() == 6);
996
997 // Check arguments.
998 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
999 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
1000 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
1001
1002 bool res;
1003 if (args[0]->IsNumber()) {
1004 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001005 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001006
1007 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1008 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1009
1010 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +00001011 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -04001012 JavaScriptFrameIterator frame_it(isolate, id);
1013 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +00001014 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -04001015
Ben Murdoch014dc512016-03-22 12:00:34 +00001016 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -04001017 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001018 } else if (args[0]->IsJSFunction()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001019 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1020 ScopeIterator it(isolate, fun);
1021 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001022 } else {
1023 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
1024 ScopeIterator it(isolate, gen);
1025 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Emily Bernier958fae72015-03-24 16:35:39 -04001026 }
1027
1028 return isolate->heap()->ToBoolean(res);
1029}
1030
1031
1032RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
1033 HandleScope scope(isolate);
1034 DCHECK(args.length() == 0);
1035
1036#ifdef DEBUG
1037 // Print the scopes for the top frame.
1038 StackFrameLocator locator(isolate);
1039 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001040 FrameInspector frame_inspector(frame, 0, isolate);
1041
1042 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001043 it.DebugPrint();
1044 }
1045#endif
1046 return isolate->heap()->undefined_value();
1047}
1048
1049
Emily Bernier958fae72015-03-24 16:35:39 -04001050// Sets the disable break state
1051// args[0]: disable break state
Ben Murdoch014dc512016-03-22 12:00:34 +00001052RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001053 HandleScope scope(isolate);
1054 DCHECK(args.length() == 1);
Ben Murdoch014dc512016-03-22 12:00:34 +00001055 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1056 isolate->debug()->set_break_points_active(active);
Emily Bernier958fae72015-03-24 16:35:39 -04001057 return isolate->heap()->undefined_value();
1058}
1059
1060
1061static bool IsPositionAlignmentCodeCorrect(int alignment) {
1062 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1063}
1064
1065
1066RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1067 HandleScope scope(isolate);
1068 DCHECK(args.length() == 2);
Ben Murdochf91f0612016-11-29 16:50:11 +00001069 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001070 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1071 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1072
1073 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1074 return isolate->ThrowIllegalOperation();
1075 }
1076 BreakPositionAlignment alignment =
1077 static_cast<BreakPositionAlignment>(statement_aligned_code);
1078
1079 Handle<SharedFunctionInfo> shared(fun->shared());
1080 // Find the number of break points
1081 Handle<Object> break_locations =
1082 Debug::GetSourceBreakLocations(shared, alignment);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001083 if (break_locations->IsUndefined(isolate)) {
1084 return isolate->heap()->undefined_value();
1085 }
Emily Bernier958fae72015-03-24 16:35:39 -04001086 // Return array as JS array
1087 return *isolate->factory()->NewJSArrayWithElements(
1088 Handle<FixedArray>::cast(break_locations));
1089}
1090
1091
1092// Set a break point in a function.
1093// args[0]: function
1094// args[1]: number: break source position (within the function source)
1095// args[2]: number: break point object
1096RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1097 HandleScope scope(isolate);
1098 DCHECK(args.length() == 3);
Ben Murdochf91f0612016-11-29 16:50:11 +00001099 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001100 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1101 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001102 CHECK(source_position >= function->shared()->start_position() &&
1103 source_position <= function->shared()->end_position());
Emily Bernier958fae72015-03-24 16:35:39 -04001104 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1105
1106 // Set break point.
Ben Murdochf91f0612016-11-29 16:50:11 +00001107 CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
1108 &source_position));
Emily Bernier958fae72015-03-24 16:35:39 -04001109
1110 return Smi::FromInt(source_position);
1111}
1112
1113
1114// Changes the state of a break point in a script and returns source position
1115// where break point was set. NOTE: Regarding performance see the NOTE for
1116// GetScriptFromScriptData.
1117// args[0]: script to set break point in
1118// args[1]: number: break source position (within the script source)
1119// args[2]: number, breakpoint position alignment
1120// args[3]: number: break point object
1121RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1122 HandleScope scope(isolate);
1123 DCHECK(args.length() == 4);
Ben Murdochf91f0612016-11-29 16:50:11 +00001124 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001125 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1126 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001127 CHECK(source_position >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001128 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1129 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1130
1131 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1132 return isolate->ThrowIllegalOperation();
1133 }
1134 BreakPositionAlignment alignment =
1135 static_cast<BreakPositionAlignment>(statement_aligned_code);
1136
1137 // Get the script from the script wrapper.
Ben Murdochf91f0612016-11-29 16:50:11 +00001138 CHECK(wrapper->value()->IsScript());
Emily Bernier958fae72015-03-24 16:35:39 -04001139 Handle<Script> script(Script::cast(wrapper->value()));
1140
1141 // Set break point.
1142 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1143 &source_position, alignment)) {
1144 return isolate->heap()->undefined_value();
1145 }
1146
1147 return Smi::FromInt(source_position);
1148}
1149
1150
1151// Clear a break point
1152// args[0]: number: break point object
1153RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1154 HandleScope scope(isolate);
1155 DCHECK(args.length() == 1);
Ben Murdochf91f0612016-11-29 16:50:11 +00001156 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001157 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1158
1159 // Clear break point.
1160 isolate->debug()->ClearBreakPoint(break_point_object_arg);
1161
1162 return isolate->heap()->undefined_value();
1163}
1164
1165
1166// Change the state of break on exceptions.
1167// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1168// args[1]: Boolean indicating on/off.
1169RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1170 HandleScope scope(isolate);
1171 DCHECK(args.length() == 2);
1172 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1173 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1174
1175 // If the number doesn't match an enum value, the ChangeBreakOnException
1176 // function will default to affecting caught exceptions.
1177 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1178 // Update break point state.
1179 isolate->debug()->ChangeBreakOnException(type, enable);
1180 return isolate->heap()->undefined_value();
1181}
1182
1183
1184// Returns the state of break on exceptions
1185// args[0]: boolean indicating uncaught exceptions
1186RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1187 HandleScope scope(isolate);
1188 DCHECK(args.length() == 1);
1189 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1190
1191 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1192 bool result = isolate->debug()->IsBreakOnException(type);
1193 return Smi::FromInt(result);
1194}
1195
1196
1197// Prepare for stepping
1198// args[0]: break id for checking execution state
1199// args[1]: step action from the enumeration StepAction
1200// args[2]: number of times to perform the step, for step out it is the number
1201// of frames to step down.
1202RUNTIME_FUNCTION(Runtime_PrepareStep) {
1203 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001204 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001205 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001206 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001207
Ben Murdoch014dc512016-03-22 12:00:34 +00001208 if (!args[1]->IsNumber()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001209 return isolate->Throw(isolate->heap()->illegal_argument_string());
1210 }
1211
Emily Bernier958fae72015-03-24 16:35:39 -04001212 // Get the step action and check validity.
1213 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1214 if (step_action != StepIn && step_action != StepNext &&
Ben Murdoch014dc512016-03-22 12:00:34 +00001215 step_action != StepOut && step_action != StepFrame) {
Emily Bernier958fae72015-03-24 16:35:39 -04001216 return isolate->Throw(isolate->heap()->illegal_argument_string());
1217 }
1218
1219 // Clear all current stepping setup.
1220 isolate->debug()->ClearStepping();
1221
1222 // Prepare step.
Ben Murdoch014dc512016-03-22 12:00:34 +00001223 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
Emily Bernier958fae72015-03-24 16:35:39 -04001224 return isolate->heap()->undefined_value();
1225}
1226
1227
1228// Clear all stepping set by PrepareStep.
1229RUNTIME_FUNCTION(Runtime_ClearStepping) {
1230 HandleScope scope(isolate);
1231 DCHECK(args.length() == 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001232 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001233 isolate->debug()->ClearStepping();
1234 return isolate->heap()->undefined_value();
1235}
1236
1237
Emily Bernier958fae72015-03-24 16:35:39 -04001238RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1239 HandleScope scope(isolate);
1240
1241 // Check the execution state and decode arguments frame and source to be
1242 // evaluated.
1243 DCHECK(args.length() == 6);
1244 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001245 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001246
1247 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1248 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1249 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1250 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
Ben Murdoch014dc512016-03-22 12:00:34 +00001251 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
Emily Bernier958fae72015-03-24 16:35:39 -04001252
Ben Murdoch014dc512016-03-22 12:00:34 +00001253 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -04001254
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001255 RETURN_RESULT_OR_FAILURE(
1256 isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1257 disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001258}
1259
1260
1261RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1262 HandleScope scope(isolate);
1263
1264 // Check the execution state and decode arguments frame and source to be
1265 // evaluated.
1266 DCHECK(args.length() == 4);
1267 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001268 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001269
1270 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1271 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
Ben Murdoch014dc512016-03-22 12:00:34 +00001272 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001273
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001274 RETURN_RESULT_OR_FAILURE(
1275 isolate,
Ben Murdoch014dc512016-03-22 12:00:34 +00001276 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001277}
1278
1279
1280RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1281 HandleScope scope(isolate);
1282 DCHECK(args.length() == 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001283
1284 // This runtime function is used by the debugger to determine whether the
1285 // debugger is active or not. Hence we fail gracefully here and don't crash.
1286 if (!isolate->debug()->is_active()) return isolate->ThrowIllegalOperation();
Emily Bernier958fae72015-03-24 16:35:39 -04001287
Ben Murdoch014dc512016-03-22 12:00:34 +00001288 Handle<FixedArray> instances;
1289 {
1290 DebugScope debug_scope(isolate->debug());
1291 if (debug_scope.failed()) {
1292 DCHECK(isolate->has_pending_exception());
1293 return isolate->heap()->exception();
1294 }
1295 // Fill the script objects.
1296 instances = isolate->debug()->GetLoadedScripts();
1297 }
Emily Bernier958fae72015-03-24 16:35:39 -04001298
1299 // Convert the script objects to proper JS objects.
1300 for (int i = 0; i < instances->length(); i++) {
1301 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1302 // Get the script wrapper in a local handle before calling GetScriptWrapper,
1303 // because using
1304 // instances->set(i, *GetScriptWrapper(script))
1305 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1306 // already have dereferenced the instances handle.
1307 Handle<JSObject> wrapper = Script::GetWrapper(script);
1308 instances->set(i, *wrapper);
1309 }
1310
1311 // Return result as a JS array.
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001312 return *isolate->factory()->NewJSArrayWithElements(instances);
Emily Bernier958fae72015-03-24 16:35:39 -04001313}
1314
Ben Murdoch109988c2016-05-18 11:27:45 +01001315static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1316 JSObject* object,
Ben Murdoch014dc512016-03-22 12:00:34 +00001317 Object* proto) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001318 PrototypeIterator iter(isolate, object, kStartAtReceiver);
Ben Murdoch014dc512016-03-22 12:00:34 +00001319 while (true) {
1320 iter.AdvanceIgnoringProxies();
1321 if (iter.IsAtEnd()) return false;
Ben Murdoch109988c2016-05-18 11:27:45 +01001322 if (iter.GetCurrent() == proto) return true;
Emily Bernier958fae72015-03-24 16:35:39 -04001323 }
Emily Bernier958fae72015-03-24 16:35:39 -04001324}
1325
1326
1327// Scan the heap for objects with direct references to an object
1328// args[0]: the object to find references to
1329// args[1]: constructor function for instances to exclude (Mirror)
1330// args[2]: the the maximum number of objects to return
1331RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1332 HandleScope scope(isolate);
1333 DCHECK(args.length() == 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001334 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001335 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
Ben Murdochf91f0612016-11-29 16:50:11 +00001336 CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
Emily Bernier958fae72015-03-24 16:35:39 -04001337 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001338 CHECK(max_references >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001339
Ben Murdoch014dc512016-03-22 12:00:34 +00001340 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001341 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001342 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001343 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1344 // Get the constructor function for context extension and arguments array.
1345 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1346 HeapObject* heap_obj;
1347 while ((heap_obj = iterator.next())) {
1348 if (!heap_obj->IsJSObject()) continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001349 JSObject* obj = JSObject::cast(heap_obj);
Ben Murdoch014dc512016-03-22 12:00:34 +00001350 if (obj->IsJSContextExtensionObject()) continue;
1351 if (obj->map()->GetConstructor() == arguments_fun) continue;
1352 if (!obj->ReferencesObject(*target)) continue;
1353 // Check filter if supplied. This is normally used to avoid
1354 // references from mirror objects.
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001355 if (!filter->IsUndefined(isolate) &&
Ben Murdoch014dc512016-03-22 12:00:34 +00001356 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1357 continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001358 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001359 if (obj->IsJSGlobalObject()) {
1360 obj = JSGlobalObject::cast(obj)->global_proxy();
1361 }
1362 instances.Add(Handle<JSObject>(obj));
1363 if (instances.length() == max_references) break;
1364 }
1365 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1366 while (iterator.next()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001367 }
1368 }
1369
Ben Murdoch014dc512016-03-22 12:00:34 +00001370 Handle<FixedArray> result;
1371 if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1372 // Check for circular reference only. This can happen when the object is
1373 // only referenced from mirrors and has a circular reference in which case
1374 // the object is not really alive and would have been garbage collected if
1375 // not referenced from the mirror.
1376 result = isolate->factory()->empty_fixed_array();
1377 } else {
1378 result = isolate->factory()->NewFixedArray(instances.length());
1379 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1380 }
1381 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001382}
1383
1384
1385// Scan the heap for objects constructed by a specific function.
1386// args[0]: the constructor to find instances of
1387// args[1]: the the maximum number of objects to return
1388RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1389 HandleScope scope(isolate);
1390 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001391 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1392 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001393 CHECK(max_references >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001394
Ben Murdoch014dc512016-03-22 12:00:34 +00001395 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001396 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001397 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001398 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1399 HeapObject* heap_obj;
1400 while ((heap_obj = iterator.next())) {
1401 if (!heap_obj->IsJSObject()) continue;
1402 JSObject* obj = JSObject::cast(heap_obj);
1403 if (obj->map()->GetConstructor() != *constructor) continue;
1404 instances.Add(Handle<JSObject>(obj));
1405 if (instances.length() == max_references) break;
1406 }
1407 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1408 while (iterator.next()) {
1409 }
Emily Bernier958fae72015-03-24 16:35:39 -04001410 }
1411
Ben Murdoch014dc512016-03-22 12:00:34 +00001412 Handle<FixedArray> result =
1413 isolate->factory()->NewFixedArray(instances.length());
1414 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1415 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001416}
1417
1418
1419// Find the effective prototype object as returned by __proto__.
1420// args[0]: the object to find the prototype for.
1421RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1422 HandleScope shs(isolate);
1423 DCHECK(args.length() == 1);
1424 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001425 // TODO(1543): Come up with a solution for clients to handle potential errors
1426 // thrown by an intermediate proxy.
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001427 RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
Emily Bernier958fae72015-03-24 16:35:39 -04001428}
1429
1430
1431// Patches script source (should be called upon BeforeCompile event).
1432RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1433 HandleScope scope(isolate);
1434 DCHECK(args.length() == 2);
1435
1436 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1437 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1438
Ben Murdochf91f0612016-11-29 16:50:11 +00001439 CHECK(script_wrapper->value()->IsScript());
Emily Bernier958fae72015-03-24 16:35:39 -04001440 Handle<Script> script(Script::cast(script_wrapper->value()));
1441
Ben Murdochf91f0612016-11-29 16:50:11 +00001442 // The following condition is not guaranteed to hold and a failure is also
1443 // propagated to callers. Hence we fail gracefully here and don't crash.
1444 if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
1445 return isolate->ThrowIllegalOperation();
1446 }
1447
Emily Bernier958fae72015-03-24 16:35:39 -04001448 script->set_source(*source);
1449
1450 return isolate->heap()->undefined_value();
1451}
1452
1453
Emily Bernier958fae72015-03-24 16:35:39 -04001454RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1455 SealHandleScope shs(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001456 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -04001457
Ben Murdoch014dc512016-03-22 12:00:34 +00001458 CONVERT_ARG_CHECKED(Object, f, 0);
1459 if (f->IsJSFunction()) {
1460 return JSFunction::cast(f)->shared()->inferred_name();
1461 }
1462 return isolate->heap()->empty_string();
1463}
1464
1465
1466RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1467 HandleScope scope(isolate);
1468 DCHECK_EQ(1, args.length());
1469
1470 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1471
1472 if (function->IsJSBoundFunction()) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001473 RETURN_RESULT_OR_FAILURE(
1474 isolate, JSBoundFunction::GetName(
1475 isolate, Handle<JSBoundFunction>::cast(function)));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001476 } else {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001477 return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
Ben Murdoch014dc512016-03-22 12:00:34 +00001478 }
Emily Bernier958fae72015-03-24 16:35:39 -04001479}
1480
1481
Emily Bernier958fae72015-03-24 16:35:39 -04001482// Calls specified function with or without entering the debugger.
1483// This is used in unit tests to run code as if debugger is entered or simply
1484// to have a stack with C++ frame in the middle.
1485RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1486 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001487 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001488 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001489
Ben Murdoch014dc512016-03-22 12:00:34 +00001490 DebugScope debug_scope(isolate->debug());
1491 if (debug_scope.failed()) {
1492 DCHECK(isolate->has_pending_exception());
1493 return isolate->heap()->exception();
Emily Bernier958fae72015-03-24 16:35:39 -04001494 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001495
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001496 RETURN_RESULT_OR_FAILURE(
1497 isolate, Execution::Call(isolate, function,
1498 handle(function->global_proxy()), 0, NULL));
Emily Bernier958fae72015-03-24 16:35:39 -04001499}
1500
1501
Ben Murdoch014dc512016-03-22 12:00:34 +00001502RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1503 HandleScope scope(isolate);
1504 DCHECK(args.length() == 0);
1505 Handle<Context> context;
1506 {
1507 DebugScope debug_scope(isolate->debug());
1508 if (debug_scope.failed()) {
1509 DCHECK(isolate->has_pending_exception());
1510 return isolate->heap()->exception();
1511 }
1512 context = isolate->debug()->GetDebugContext();
1513 }
1514 if (context.is_null()) return isolate->heap()->undefined_value();
1515 context->set_security_token(isolate->native_context()->security_token());
1516 return context->global_proxy();
1517}
1518
1519
Emily Bernier958fae72015-03-24 16:35:39 -04001520// Performs a GC.
1521// Presently, it only does a full GC.
1522RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1523 SealHandleScope shs(isolate);
1524 DCHECK(args.length() == 1);
Ben Murdochf3b273f2017-01-17 12:11:28 +00001525 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1526 GarbageCollectionReason::kRuntime);
Emily Bernier958fae72015-03-24 16:35:39 -04001527 return isolate->heap()->undefined_value();
1528}
1529
1530
1531// Gets the current heap usage.
1532RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1533 SealHandleScope shs(isolate);
1534 DCHECK(args.length() == 0);
1535 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1536 if (!Smi::IsValid(usage)) {
1537 return *isolate->factory()->NewNumberFromInt(usage);
1538 }
1539 return Smi::FromInt(usage);
1540}
1541
1542
1543// Finds the script object from the script data. NOTE: This operation uses
1544// heap traversal to find the function generated for the source position
1545// for the requested break point. For lazily compiled functions several heap
1546// traversals might be required rendering this operation as a rather slow
1547// operation. However for setting break points which is normally done through
1548// some kind of user interaction the performance is not crucial.
1549RUNTIME_FUNCTION(Runtime_GetScript) {
1550 HandleScope scope(isolate);
1551 DCHECK(args.length() == 1);
1552 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1553
1554 Handle<Script> found;
Emily Bernier958fae72015-03-24 16:35:39 -04001555 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001556 Script::Iterator iterator(isolate);
1557 Script* script = NULL;
1558 while ((script = iterator.Next()) != NULL) {
Emily Bernier958fae72015-03-24 16:35:39 -04001559 if (!script->name()->IsString()) continue;
1560 String* name = String::cast(script->name());
1561 if (name->Equals(*script_name)) {
1562 found = Handle<Script>(script, isolate);
1563 break;
1564 }
1565 }
1566 }
1567
Ben Murdoch014dc512016-03-22 12:00:34 +00001568 if (found.is_null()) return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -04001569 return *Script::GetWrapper(found);
1570}
1571
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001572RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
1573 HandleScope scope(isolate);
1574 DCHECK(args.length() == 1);
1575 CONVERT_ARG_CHECKED(JSValue, script, 0);
1576
Ben Murdochf91f0612016-11-29 16:50:11 +00001577 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001578 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1579
1580 Script::InitLineEnds(script_handle);
1581
1582 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1583 return Smi::FromInt(line_ends_array->length());
1584}
1585
1586RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
1587 HandleScope scope(isolate);
1588 DCHECK(args.length() == 2);
1589 CONVERT_ARG_CHECKED(JSValue, script, 0);
1590 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1591
Ben Murdochf91f0612016-11-29 16:50:11 +00001592 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001593 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1594
1595 Script::InitLineEnds(script_handle);
1596
1597 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1598 const int line_count = line_ends_array->length();
1599
1600 // If line == line_count, we return the first position beyond the last line.
1601 if (line < 0 || line > line_count) {
1602 return Smi::FromInt(-1);
1603 } else if (line == 0) {
1604 return Smi::FromInt(0);
1605 } else {
1606 DCHECK(0 < line && line <= line_count);
1607 const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1608 return Smi::FromInt(pos);
1609 }
1610}
1611
1612RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
1613 HandleScope scope(isolate);
1614 DCHECK(args.length() == 2);
1615 CONVERT_ARG_CHECKED(JSValue, script, 0);
1616 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1617
Ben Murdochf91f0612016-11-29 16:50:11 +00001618 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001619 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1620
1621 Script::InitLineEnds(script_handle);
1622
1623 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1624 const int line_count = line_ends_array->length();
1625
1626 if (line < 0 || line >= line_count) {
1627 return Smi::FromInt(-1);
1628 } else {
1629 return Smi::cast(line_ends_array->get(line));
1630 }
1631}
1632
1633static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
1634 Script::OffsetFlag offset_flag,
1635 Isolate* isolate) {
1636 Script::PositionInfo info;
1637 if (!script->GetPositionInfo(position, &info, offset_flag)) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001638 return isolate->factory()->null_value();
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001639 }
1640
1641 Handle<String> source = handle(String::cast(script->source()), isolate);
Ben Murdochf91f0612016-11-29 16:50:11 +00001642 Handle<String> sourceText = script->type() == Script::TYPE_WASM
1643 ? isolate->factory()->empty_string()
1644 : isolate->factory()->NewSubString(
1645 source, info.line_start, info.line_end);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001646
1647 Handle<JSObject> jsinfo =
1648 isolate->factory()->NewJSObject(isolate->object_function());
1649
1650 JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
1651 NONE);
1652 JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
1653 handle(Smi::FromInt(position), isolate), NONE);
1654 JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
1655 handle(Smi::FromInt(info.line), isolate), NONE);
1656 JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
1657 handle(Smi::FromInt(info.column), isolate), NONE);
1658 JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
1659 sourceText, NONE);
1660
1661 return jsinfo;
1662}
1663
1664// Get information on a specific source line and column possibly offset by a
1665// fixed source position. This function is used to find a source position from
1666// a line and column position. The fixed source position offset is typically
1667// used to find a source position in a function based on a line and column in
1668// the source for the function alone. The offset passed will then be the
1669// start position of the source for the function within the full script source.
1670// Note that incoming line and column parameters may be undefined, and are
1671// assumed to be passed *with* offsets.
1672RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
1673 HandleScope scope(isolate);
1674 DCHECK(args.length() == 4);
1675 CONVERT_ARG_CHECKED(JSValue, script, 0);
1676
Ben Murdochf91f0612016-11-29 16:50:11 +00001677 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001678 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1679
1680 // Line and column are possibly undefined and we need to handle these cases,
1681 // additionally subtracting corresponding offsets.
1682
1683 int32_t line;
1684 if (args[1]->IsNull(isolate) || args[1]->IsUndefined(isolate)) {
1685 line = 0;
1686 } else {
Ben Murdochf91f0612016-11-29 16:50:11 +00001687 CHECK(args[1]->IsNumber());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001688 line = NumberToInt32(args[1]) - script_handle->line_offset();
1689 }
1690
1691 int32_t column;
1692 if (args[2]->IsNull(isolate) || args[2]->IsUndefined(isolate)) {
1693 column = 0;
1694 } else {
Ben Murdochf91f0612016-11-29 16:50:11 +00001695 CHECK(args[2]->IsNumber());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001696 column = NumberToInt32(args[2]);
1697 if (line == 0) column -= script_handle->column_offset();
1698 }
1699
1700 CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]);
1701
1702 if (line < 0 || column < 0 || offset_position < 0) {
1703 return isolate->heap()->null_value();
1704 }
1705
1706 Script::InitLineEnds(script_handle);
1707
1708 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1709 const int line_count = line_ends_array->length();
1710
1711 int position;
1712 if (line == 0) {
1713 position = offset_position + column;
1714 } else {
1715 Script::PositionInfo info;
1716 if (!script_handle->GetPositionInfo(offset_position, &info,
1717 Script::NO_OFFSET) ||
1718 info.line + line >= line_count) {
1719 return isolate->heap()->null_value();
1720 }
1721
1722 const int offset_line = info.line + line;
1723 const int offset_line_position =
1724 (offset_line == 0)
1725 ? 0
1726 : Smi::cast(line_ends_array->get(offset_line - 1))->value() + 1;
1727 position = offset_line_position + column;
1728 }
1729
1730 return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET,
1731 isolate);
1732}
1733
1734RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
1735 HandleScope scope(isolate);
1736 DCHECK(args.length() == 3);
1737 CONVERT_ARG_CHECKED(JSValue, script, 0);
1738 CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1739 CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1740
Ben Murdochf91f0612016-11-29 16:50:11 +00001741 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001742 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1743
1744 const Script::OffsetFlag offset_flag =
1745 with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1746 return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
1747}
1748
1749// Returns the given line as a string, or null if line is out of bounds.
1750// The parameter line is expected to include the script's line offset.
1751RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
1752 HandleScope scope(isolate);
1753 DCHECK(args.length() == 2);
1754 CONVERT_ARG_CHECKED(JSValue, script, 0);
1755 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1756
Ben Murdochf91f0612016-11-29 16:50:11 +00001757 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001758 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1759
1760 Script::InitLineEnds(script_handle);
1761
1762 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1763 const int line_count = line_ends_array->length();
1764
1765 line -= script_handle->line_offset();
1766 if (line < 0 || line_count <= line) {
1767 return isolate->heap()->null_value();
1768 }
1769
1770 const int start =
1771 (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1772 const int end = Smi::cast(line_ends_array->get(line))->value();
1773
1774 Handle<String> source =
1775 handle(String::cast(script_handle->source()), isolate);
1776 Handle<String> str = isolate->factory()->NewSubString(source, start, end);
1777
1778 return *str;
1779}
Emily Bernier958fae72015-03-24 16:35:39 -04001780
Emily Bernier958fae72015-03-24 16:35:39 -04001781// Set one shot breakpoints for the callback function that is passed to a
Ben Murdoch014dc512016-03-22 12:00:34 +00001782// built-in function such as Array.forEach to enable stepping into the callback,
1783// if we are indeed stepping and the callback is subject to debugging.
Emily Bernier958fae72015-03-24 16:35:39 -04001784RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
Emily Bernier958fae72015-03-24 16:35:39 -04001785 HandleScope scope(isolate);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001786 DCHECK_EQ(1, args.length());
1787 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001788 isolate->debug()->PrepareStepIn(fun);
Emily Bernier958fae72015-03-24 16:35:39 -04001789 return isolate->heap()->undefined_value();
1790}
1791
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001792// Set one shot breakpoints for the suspended generator object.
1793RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
1794 HandleScope scope(isolate);
1795 DCHECK_EQ(0, args.length());
1796 isolate->debug()->PrepareStepInSuspendedGenerator();
1797 return isolate->heap()->undefined_value();
1798}
1799
1800RUNTIME_FUNCTION(Runtime_DebugRecordAsyncFunction) {
1801 HandleScope scope(isolate);
1802 DCHECK_EQ(1, args.length());
1803 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
1804 CHECK(isolate->debug()->last_step_action() >= StepNext);
1805 isolate->debug()->RecordAsyncFunction(generator);
1806 return isolate->heap()->undefined_value();
1807}
Emily Bernier958fae72015-03-24 16:35:39 -04001808
1809RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001810 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001811 HandleScope scope(isolate);
1812 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001813 isolate->PushPromise(promise);
Emily Bernier958fae72015-03-24 16:35:39 -04001814 return isolate->heap()->undefined_value();
1815}
1816
1817
1818RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1819 DCHECK(args.length() == 0);
1820 SealHandleScope shs(isolate);
1821 isolate->PopPromise();
1822 return isolate->heap()->undefined_value();
1823}
1824
1825
Emily Bernier958fae72015-03-24 16:35:39 -04001826RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1827 DCHECK(args.length() == 1);
1828 HandleScope scope(isolate);
1829 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1830 isolate->debug()->OnAsyncTaskEvent(data);
1831 return isolate->heap()->undefined_value();
1832}
1833
1834
Ben Murdoch014dc512016-03-22 12:00:34 +00001835RUNTIME_FUNCTION(Runtime_DebugIsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001836 SealHandleScope shs(isolate);
1837 return Smi::FromInt(isolate->debug()->is_active());
1838}
1839
1840
Ben Murdoch014dc512016-03-22 12:00:34 +00001841RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
Emily Bernier958fae72015-03-24 16:35:39 -04001842 UNIMPLEMENTED();
1843 return NULL;
1844}
Ben Murdochf91f0612016-11-29 16:50:11 +00001845
1846RUNTIME_FUNCTION(Runtime_GetWasmFunctionOffsetTable) {
1847 DCHECK(args.length() == 1);
1848 HandleScope scope(isolate);
1849 CONVERT_ARG_CHECKED(JSValue, script_val, 0);
1850
1851 CHECK(script_val->value()->IsScript());
1852 Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
1853
1854 Handle<wasm::WasmDebugInfo> debug_info =
1855 wasm::GetDebugInfo(handle(script->wasm_object(), isolate));
1856 Handle<FixedArray> elements = wasm::WasmDebugInfo::GetFunctionOffsetTable(
1857 debug_info, script->wasm_function_index());
1858 return *isolate->factory()->NewJSArrayWithElements(elements);
1859}
1860
1861RUNTIME_FUNCTION(Runtime_DisassembleWasmFunction) {
1862 DCHECK(args.length() == 1);
1863 HandleScope scope(isolate);
1864 CONVERT_ARG_CHECKED(JSValue, script_val, 0);
1865
1866 CHECK(script_val->value()->IsScript());
1867 Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
1868
1869 Handle<wasm::WasmDebugInfo> debug_info =
1870 wasm::GetDebugInfo(handle(script->wasm_object(), isolate));
1871 return *wasm::WasmDebugInfo::DisassembleFunction(
1872 debug_info, script->wasm_function_index());
1873}
1874
Ben Murdoch014dc512016-03-22 12:00:34 +00001875} // namespace internal
1876} // namespace v8