blob: a8c465a38064a6d8da4f2c9fa05393ffc1a0e5c2 [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 Murdoch014dc512016-03-22 12:00:34 +000012#include "src/frames-inl.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000013#include "src/globals.h"
Ben Murdoch3b9bc312016-06-02 14:46:10 +010014#include "src/interpreter/bytecodes.h"
15#include "src/interpreter/interpreter.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000016#include "src/isolate-inl.h"
17#include "src/runtime/runtime.h"
Ben Murdochf91f0612016-11-29 16:50:11 +000018#include "src/wasm/wasm-debug.h"
19#include "src/wasm/wasm-module.h"
Ben Murdoch014dc512016-03-22 12:00:34 +000020
Emily Bernier958fae72015-03-24 16:35:39 -040021namespace v8 {
22namespace internal {
23
24RUNTIME_FUNCTION(Runtime_DebugBreak) {
25 SealHandleScope shs(isolate);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010026 DCHECK(args.length() == 1);
27 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
28 isolate->debug()->set_return_value(value);
29
Ben Murdoch014dc512016-03-22 12:00:34 +000030 // Get the top-most JavaScript frame.
31 JavaScriptFrameIterator it(isolate);
Ben Murdoch3b9bc312016-06-02 14:46:10 +010032 isolate->debug()->Break(it.frame());
33
34 isolate->debug()->SetAfterBreakTarget(it.frame());
35 return *isolate->debug()->return_value();
36}
37
38RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
39 SealHandleScope shs(isolate);
40 DCHECK(args.length() == 1);
41 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
42 isolate->debug()->set_return_value(value);
43
44 // Get the top-most JavaScript frame.
45 JavaScriptFrameIterator it(isolate);
46 isolate->debug()->Break(it.frame());
47
Ben Murdochbcf72ee2016-08-08 18:44:38 +010048 // If live-edit has dropped frames, we are not going back to dispatch.
49 if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0);
50
Ben Murdoch3b9bc312016-06-02 14:46:10 +010051 // Return the handler from the original bytecode array.
52 DCHECK(it.frame()->is_interpreted());
53 InterpretedFrame* interpreted_frame =
54 reinterpret_cast<InterpretedFrame*>(it.frame());
55 SharedFunctionInfo* shared = interpreted_frame->function()->shared();
56 BytecodeArray* bytecode_array = shared->bytecode_array();
57 int bytecode_offset = interpreted_frame->GetBytecodeOffset();
58 interpreter::Bytecode bytecode =
59 interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
60 return isolate->interpreter()->GetBytecodeHandler(
61 bytecode, interpreter::OperandScale::kSingle);
Emily Bernier958fae72015-03-24 16:35:39 -040062}
63
64
Ben Murdoch014dc512016-03-22 12:00:34 +000065RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
66 SealHandleScope shs(isolate);
67 DCHECK(args.length() == 0);
68 if (isolate->debug()->break_points_active()) {
69 isolate->debug()->HandleDebugBreak();
70 }
71 return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -040072}
73
74
75// Adds a JavaScript function as a debug event listener.
76// args[0]: debug event listener function to set or null or undefined for
77// clearing the event listener function
78// args[1]: object supplied during callback
79RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
80 SealHandleScope shs(isolate);
81 DCHECK(args.length() == 2);
Ben Murdochf91f0612016-11-29 16:50:11 +000082 CHECK(args[0]->IsJSFunction() || args[0]->IsUndefined(isolate) ||
83 args[0]->IsNull(isolate));
Emily Bernier958fae72015-03-24 16:35:39 -040084 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
85 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
86 isolate->debug()->SetEventListener(callback, data);
87
88 return isolate->heap()->undefined_value();
89}
90
91
Ben Murdoch014dc512016-03-22 12:00:34 +000092RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
Emily Bernier958fae72015-03-24 16:35:39 -040093 SealHandleScope shs(isolate);
94 DCHECK(args.length() == 0);
95 isolate->stack_guard()->RequestDebugBreak();
96 return isolate->heap()->undefined_value();
97}
98
99
100static Handle<Object> DebugGetProperty(LookupIterator* it,
101 bool* has_caught = NULL) {
102 for (; it->IsFound(); it->Next()) {
103 switch (it->state()) {
104 case LookupIterator::NOT_FOUND:
105 case LookupIterator::TRANSITION:
106 UNREACHABLE();
107 case LookupIterator::ACCESS_CHECK:
108 // Ignore access checks.
109 break;
Ben Murdoch014dc512016-03-22 12:00:34 +0000110 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Emily Bernier958fae72015-03-24 16:35:39 -0400111 case LookupIterator::INTERCEPTOR:
112 case LookupIterator::JSPROXY:
113 return it->isolate()->factory()->undefined_value();
114 case LookupIterator::ACCESSOR: {
115 Handle<Object> accessors = it->GetAccessors();
116 if (!accessors->IsAccessorInfo()) {
117 return it->isolate()->factory()->undefined_value();
118 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000119 MaybeHandle<Object> maybe_result =
Ben Murdoch109988c2016-05-18 11:27:45 +0100120 JSObject::GetPropertyWithAccessor(it);
Emily Bernier958fae72015-03-24 16:35:39 -0400121 Handle<Object> result;
122 if (!maybe_result.ToHandle(&result)) {
123 result = handle(it->isolate()->pending_exception(), it->isolate());
124 it->isolate()->clear_pending_exception();
125 if (has_caught != NULL) *has_caught = true;
126 }
127 return result;
128 }
129
130 case LookupIterator::DATA:
131 return it->GetDataValue();
132 }
133 }
134
135 return it->isolate()->factory()->undefined_value();
136}
137
138
Ben Murdoch014dc512016-03-22 12:00:34 +0000139static Handle<Object> DebugGetProperty(Handle<Object> object,
140 Handle<Name> name) {
141 LookupIterator it(object, name);
142 return DebugGetProperty(&it);
143}
144
145
146template <class IteratorType>
147static MaybeHandle<JSArray> GetIteratorInternalProperties(
148 Isolate* isolate, Handle<IteratorType> object) {
149 Factory* factory = isolate->factory();
150 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100151 CHECK(iterator->kind()->IsSmi());
Ben Murdoch014dc512016-03-22 12:00:34 +0000152 const char* kind = NULL;
153 switch (Smi::cast(iterator->kind())->value()) {
154 case IteratorType::kKindKeys:
155 kind = "keys";
156 break;
157 case IteratorType::kKindValues:
158 kind = "values";
159 break;
160 case IteratorType::kKindEntries:
161 kind = "entries";
162 break;
163 default:
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100164 UNREACHABLE();
Ben Murdoch014dc512016-03-22 12:00:34 +0000165 }
166
167 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
168 Handle<String> has_more =
169 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
170 result->set(0, *has_more);
171 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
172
173 Handle<String> index =
174 factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
175 result->set(2, *index);
176 result->set(3, iterator->index());
177
178 Handle<String> iterator_kind =
179 factory->NewStringFromAsciiChecked("[[IteratorKind]]");
180 result->set(4, *iterator_kind);
181 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
182 result->set(5, *kind_str);
183 return factory->NewJSArrayWithElements(result);
184}
185
186
187MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
188 Handle<Object> object) {
189 Factory* factory = isolate->factory();
190 if (object->IsJSBoundFunction()) {
191 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
192
193 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
194 Handle<String> target =
195 factory->NewStringFromAsciiChecked("[[TargetFunction]]");
196 result->set(0, *target);
197 result->set(1, function->bound_target_function());
198
199 Handle<String> bound_this =
200 factory->NewStringFromAsciiChecked("[[BoundThis]]");
201 result->set(2, *bound_this);
202 result->set(3, function->bound_this());
203
204 Handle<String> bound_args =
205 factory->NewStringFromAsciiChecked("[[BoundArgs]]");
206 result->set(4, *bound_args);
207 Handle<FixedArray> bound_arguments =
208 factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
209 Handle<JSArray> arguments_array =
210 factory->NewJSArrayWithElements(bound_arguments);
211 result->set(5, *arguments_array);
212 return factory->NewJSArrayWithElements(result);
213 } else if (object->IsJSMapIterator()) {
214 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
215 return GetIteratorInternalProperties(isolate, iterator);
216 } else if (object->IsJSSetIterator()) {
217 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
218 return GetIteratorInternalProperties(isolate, iterator);
219 } else if (object->IsJSGeneratorObject()) {
220 Handle<JSGeneratorObject> generator =
221 Handle<JSGeneratorObject>::cast(object);
222
223 const char* status = "suspended";
224 if (generator->is_closed()) {
225 status = "closed";
226 } else if (generator->is_executing()) {
227 status = "running";
228 } else {
229 DCHECK(generator->is_suspended());
230 }
231
232 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
233 Handle<String> generator_status =
234 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
235 result->set(0, *generator_status);
236 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
237 result->set(1, *status_str);
238
239 Handle<String> function =
240 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
241 result->set(2, *function);
242 result->set(3, generator->function());
243
244 Handle<String> receiver =
245 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
246 result->set(4, *receiver);
247 result->set(5, generator->receiver());
248 return factory->NewJSArrayWithElements(result);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100249 } else if (object->IsJSPromise()) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000250 Handle<JSObject> promise = Handle<JSObject>::cast(object);
251
252 Handle<Object> status_obj =
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100253 DebugGetProperty(promise, isolate->factory()->promise_state_symbol());
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100254 CHECK(status_obj->IsSmi());
Ben Murdoch014dc512016-03-22 12:00:34 +0000255 const char* status = "rejected";
256 int status_val = Handle<Smi>::cast(status_obj)->value();
257 switch (status_val) {
258 case +1:
259 status = "resolved";
260 break;
261 case 0:
262 status = "pending";
263 break;
264 default:
265 DCHECK_EQ(-1, status_val);
266 }
267
268 Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
269 Handle<String> promise_status =
270 factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
271 result->set(0, *promise_status);
272 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
273 result->set(1, *status_str);
274
275 Handle<Object> value_obj =
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100276 DebugGetProperty(promise, isolate->factory()->promise_result_symbol());
Ben Murdoch014dc512016-03-22 12:00:34 +0000277 Handle<String> promise_value =
278 factory->NewStringFromAsciiChecked("[[PromiseValue]]");
279 result->set(2, *promise_value);
280 result->set(3, *value_obj);
281 return factory->NewJSArrayWithElements(result);
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100282 } else if (object->IsJSProxy()) {
283 Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
284 Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
285
286 Handle<String> handler_str =
287 factory->NewStringFromAsciiChecked("[[Handler]]");
288 result->set(0, *handler_str);
289 result->set(1, js_proxy->handler());
290
291 Handle<String> target_str =
292 factory->NewStringFromAsciiChecked("[[Target]]");
293 result->set(2, *target_str);
294 result->set(3, js_proxy->target());
295
296 Handle<String> is_revoked_str =
297 factory->NewStringFromAsciiChecked("[[IsRevoked]]");
298 result->set(4, *is_revoked_str);
299 result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
300 return factory->NewJSArrayWithElements(result);
Ben Murdoch014dc512016-03-22 12:00:34 +0000301 } else if (object->IsJSValue()) {
302 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
303
304 Handle<FixedArray> result = factory->NewFixedArray(2);
305 Handle<String> primitive_value =
306 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
307 result->set(0, *primitive_value);
308 result->set(1, js_value->value());
309 return factory->NewJSArrayWithElements(result);
310 }
311 return factory->NewJSArray(0);
312}
313
314
315RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
316 HandleScope scope(isolate);
317 DCHECK(args.length() == 1);
318 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100319 RETURN_RESULT_OR_FAILURE(isolate,
320 Runtime::GetInternalProperties(isolate, obj));
Ben Murdoch014dc512016-03-22 12:00:34 +0000321}
322
323
Emily Bernier958fae72015-03-24 16:35:39 -0400324// Get debugger related details for an object property, in the following format:
325// 0: Property value
326// 1: Property details
327// 2: Property value is exception
328// 3: Getter function if defined
329// 4: Setter function if defined
330// Items 2-4 are only filled if the property has either a getter or a setter.
331RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
332 HandleScope scope(isolate);
Ben Murdochf91f0612016-11-29 16:50:11 +0000333 DCHECK_EQ(2, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -0400334 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdochf91f0612016-11-29 16:50:11 +0000335 CONVERT_ARG_HANDLE_CHECKED(Object, name_obj, 1);
336
337 // Convert the {name_obj} to a Name.
338 Handle<Name> name;
339 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
340 Object::ToName(isolate, name_obj));
Emily Bernier958fae72015-03-24 16:35:39 -0400341
342 // Make sure to set the current context to the context before the debugger was
343 // entered (if the debugger is entered). The reason for switching context here
344 // is that for some property lookups (accessors and interceptors) callbacks
345 // into the embedding application can occour, and the embedding application
346 // could have the assumption that its own native context is the current
347 // context and not some internal debugger context.
348 SaveContext save(isolate);
349 if (isolate->debug()->in_debug_scope()) {
350 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
351 }
352
353 // Check if the name is trivially convertible to an index and get the element
354 // if so.
355 uint32_t index;
Ben Murdoch014dc512016-03-22 12:00:34 +0000356 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
357 // this special case.
Emily Bernier958fae72015-03-24 16:35:39 -0400358 if (name->AsArrayIndex(&index)) {
359 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
360 Handle<Object> element_or_char;
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100361 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
362 isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
Emily Bernier958fae72015-03-24 16:35:39 -0400363 details->set(0, *element_or_char);
Ben Murdoch014dc512016-03-22 12:00:34 +0000364 details->set(1, PropertyDetails::Empty().AsSmi());
Emily Bernier958fae72015-03-24 16:35:39 -0400365 return *isolate->factory()->NewJSArrayWithElements(details);
366 }
367
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100368 LookupIterator it(obj, name, LookupIterator::OWN);
Emily Bernier958fae72015-03-24 16:35:39 -0400369 bool has_caught = false;
370 Handle<Object> value = DebugGetProperty(&it, &has_caught);
371 if (!it.IsFound()) return isolate->heap()->undefined_value();
372
373 Handle<Object> maybe_pair;
374 if (it.state() == LookupIterator::ACCESSOR) {
375 maybe_pair = it.GetAccessors();
376 }
377
378 // If the callback object is a fixed array then it contains JavaScript
379 // getter and/or setter.
380 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
381 Handle<FixedArray> details =
382 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
383 details->set(0, *value);
384 // TODO(verwaest): Get rid of this random way of handling interceptors.
385 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
Ben Murdoch014dc512016-03-22 12:00:34 +0000386 ? PropertyDetails::Empty()
Emily Bernier958fae72015-03-24 16:35:39 -0400387 : it.property_details();
388 details->set(1, d.AsSmi());
389 details->set(
390 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
391 if (has_js_accessors) {
Ben Murdoch109988c2016-05-18 11:27:45 +0100392 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
Emily Bernier958fae72015-03-24 16:35:39 -0400393 details->set(3, isolate->heap()->ToBoolean(has_caught));
Ben Murdoch109988c2016-05-18 11:27:45 +0100394 Handle<Object> getter =
395 AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
396 Handle<Object> setter =
397 AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
398 details->set(4, *getter);
399 details->set(5, *setter);
Emily Bernier958fae72015-03-24 16:35:39 -0400400 }
401
402 return *isolate->factory()->NewJSArrayWithElements(details);
403}
404
405
406RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
407 HandleScope scope(isolate);
408
409 DCHECK(args.length() == 2);
410
Ben Murdochf91f0612016-11-29 16:50:11 +0000411 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Emily Bernier958fae72015-03-24 16:35:39 -0400412 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
413
414 LookupIterator it(obj, name);
415 return *DebugGetProperty(&it);
416}
417
418
419// Return the property type calculated from the property details.
420// args[0]: smi with property details.
421RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
422 SealHandleScope shs(isolate);
423 DCHECK(args.length() == 1);
424 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
425 return Smi::FromInt(static_cast<int>(details.type()));
426}
427
428
429// Return the property attribute calculated from the property details.
430// args[0]: smi with property details.
431RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
432 SealHandleScope shs(isolate);
433 DCHECK(args.length() == 1);
434 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
435 return Smi::FromInt(static_cast<int>(details.attributes()));
436}
437
438
Emily Bernier958fae72015-03-24 16:35:39 -0400439RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
440 SealHandleScope shs(isolate);
441 DCHECK(args.length() == 1);
442 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000443 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400444 return isolate->heap()->true_value();
445}
446
447
448RUNTIME_FUNCTION(Runtime_GetFrameCount) {
449 HandleScope scope(isolate);
450 DCHECK(args.length() == 1);
451 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000452 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400453
454 // Count all frames which are relevant to debugging stack trace.
455 int n = 0;
456 StackFrame::Id id = isolate->debug()->break_frame_id();
457 if (id == StackFrame::NO_ID) {
458 // If there is no JavaScript stack frame count is 0.
459 return Smi::FromInt(0);
460 }
461
Ben Murdochf91f0612016-11-29 16:50:11 +0000462 for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400463 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
Ben Murdochf91f0612016-11-29 16:50:11 +0000464 if (it.is_wasm()) {
465 n++;
466 } else {
467 it.javascript_frame()->Summarize(&frames);
468 for (int i = frames.length() - 1; i >= 0; i--) {
469 // Omit functions from native and extension scripts.
470 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
471 }
Emily Bernier958fae72015-03-24 16:35:39 -0400472 }
473 }
474 return Smi::FromInt(n);
475}
476
477
Emily Bernier958fae72015-03-24 16:35:39 -0400478static const int kFrameDetailsFrameIdIndex = 0;
479static const int kFrameDetailsReceiverIndex = 1;
480static const int kFrameDetailsFunctionIndex = 2;
Ben Murdochf91f0612016-11-29 16:50:11 +0000481static const int kFrameDetailsScriptIndex = 3;
482static const int kFrameDetailsArgumentCountIndex = 4;
483static const int kFrameDetailsLocalCountIndex = 5;
484static const int kFrameDetailsSourcePositionIndex = 6;
485static const int kFrameDetailsConstructCallIndex = 7;
486static const int kFrameDetailsAtReturnIndex = 8;
487static const int kFrameDetailsFlagsIndex = 9;
488static const int kFrameDetailsFirstDynamicIndex = 10;
Emily Bernier958fae72015-03-24 16:35:39 -0400489
Emily Bernier958fae72015-03-24 16:35:39 -0400490// Return an array with frame details
491// args[0]: number: break id
492// args[1]: number: frame index
493//
494// The array returned contains the following information:
495// 0: Frame id
496// 1: Receiver
497// 2: Function
Ben Murdochf91f0612016-11-29 16:50:11 +0000498// 3: Script
499// 4: Argument count
500// 5: Local count
501// 6: Source position
502// 7: Constructor call
503// 8: Is at return
504// 9: Flags
Emily Bernier958fae72015-03-24 16:35:39 -0400505// Arguments name, value
506// Locals name, value
507// Return value if any
508RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
509 HandleScope scope(isolate);
510 DCHECK(args.length() == 2);
511 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000512 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400513
514 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
515 Heap* heap = isolate->heap();
516
517 // Find the relevant frame with the requested index.
518 StackFrame::Id id = isolate->debug()->break_frame_id();
519 if (id == StackFrame::NO_ID) {
520 // If there are no JavaScript stack frames return undefined.
521 return heap->undefined_value();
522 }
523
Ben Murdochf91f0612016-11-29 16:50:11 +0000524 StackTraceFrameIterator it(isolate, id);
Emily Bernier958fae72015-03-24 16:35:39 -0400525 // Inlined frame index in optimized frame, starting from outer function.
Ben Murdoch014dc512016-03-22 12:00:34 +0000526 int inlined_jsframe_index =
527 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
Emily Bernier958fae72015-03-24 16:35:39 -0400528 if (inlined_jsframe_index == -1) return heap->undefined_value();
529
530 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400531
532 // Traverse the saved contexts chain to find the active context for the
533 // selected frame.
Ben Murdoch014dc512016-03-22 12:00:34 +0000534 SaveContext* save =
535 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
Emily Bernier958fae72015-03-24 16:35:39 -0400536
537 // Get the frame id.
Ben Murdoch014dc512016-03-22 12:00:34 +0000538 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
539 isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400540
541 // Find source position in unoptimized code.
542 int position = frame_inspector.GetSourcePosition();
543
Ben Murdochf91f0612016-11-29 16:50:11 +0000544 if (it.is_wasm()) {
545 // Create the details array (no dynamic information for wasm).
546 Handle<FixedArray> details =
547 isolate->factory()->NewFixedArray(kFrameDetailsFirstDynamicIndex);
548
549 // Add the frame id.
550 details->set(kFrameDetailsFrameIdIndex, *frame_id);
551
552 // Add the function name.
553 Handle<Object> wasm_obj(it.wasm_frame()->wasm_obj(), isolate);
554 int func_index = it.wasm_frame()->function_index();
555 Handle<String> func_name =
556 wasm::GetWasmFunctionName(isolate, wasm_obj, func_index);
557 details->set(kFrameDetailsFunctionIndex, *func_name);
558
559 // Add the script wrapper
560 Handle<Object> script_wrapper =
561 Script::GetWrapper(frame_inspector.GetScript());
562 details->set(kFrameDetailsScriptIndex, *script_wrapper);
563
564 // Add the arguments count.
565 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(0));
566
567 // Add the locals count
568 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(0));
569
570 // Add the source position.
571 if (position != kNoSourcePosition) {
572 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
573 }
574
575 // Add the constructor information.
576 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(false));
577
578 // Add the at return information.
579 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(false));
580
581 // Add flags to indicate information on whether this frame is
582 // bit 0: invoked in the debugger context.
583 // bit 1: optimized frame.
584 // bit 2: inlined in optimized frame
585 int flags = 0;
586 if (*save->context() == *isolate->debug()->debug_context()) {
587 flags |= 1 << 0;
588 }
589 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
590
591 return *isolate->factory()->NewJSArrayWithElements(details);
592 }
593
594 // Handle JavaScript frames.
595 bool is_optimized = it.frame()->is_optimized();
596
Emily Bernier958fae72015-03-24 16:35:39 -0400597 // Check for constructor frame.
598 bool constructor = frame_inspector.IsConstructor();
599
600 // Get scope info and read from it for local variable information.
Ben Murdoch109988c2016-05-18 11:27:45 +0100601 Handle<JSFunction> function =
602 Handle<JSFunction>::cast(frame_inspector.GetFunction());
Ben Murdochf91f0612016-11-29 16:50:11 +0000603 CHECK(function->shared()->IsSubjectToDebugging());
Emily Bernier958fae72015-03-24 16:35:39 -0400604 Handle<SharedFunctionInfo> shared(function->shared());
605 Handle<ScopeInfo> scope_info(shared->scope_info());
606 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
607
608 // Get the locals names and values into a temporary array.
Ben Murdochf91f0612016-11-29 16:50:11 +0000609 Handle<Object> maybe_context = frame_inspector.GetContext();
610 const int local_count_with_synthetic = maybe_context->IsContext()
611 ? scope_info->LocalCount()
612 : scope_info->StackLocalCount();
613 int local_count = local_count_with_synthetic;
614 for (int slot = 0; slot < local_count_with_synthetic; ++slot) {
Emily Bernier958fae72015-03-24 16:35:39 -0400615 // Hide compiler-introduced temporary variables, whether on the stack or on
616 // the context.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100617 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
618 local_count--;
619 }
Emily Bernier958fae72015-03-24 16:35:39 -0400620 }
621
Ben Murdochf91f0612016-11-29 16:50:11 +0000622 List<Handle<Object>> locals;
Emily Bernier958fae72015-03-24 16:35:39 -0400623 // Fill in the values of the locals.
Emily Bernier958fae72015-03-24 16:35:39 -0400624 int i = 0;
625 for (; i < scope_info->StackLocalCount(); ++i) {
626 // Use the value from the stack.
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100627 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
Ben Murdochf91f0612016-11-29 16:50:11 +0000628 locals.Add(Handle<String>(scope_info->LocalName(i), isolate));
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100629 Handle<Object> value =
630 frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100631 // TODO(yangguo): We convert optimized out values to {undefined} when they
632 // are passed to the debugger. Eventually we should handle them somehow.
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100633 if (value->IsOptimizedOut(isolate)) {
634 value = isolate->factory()->undefined_value();
635 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000636 locals.Add(value);
Emily Bernier958fae72015-03-24 16:35:39 -0400637 }
Ben Murdochf91f0612016-11-29 16:50:11 +0000638 if (locals.length() < local_count * 2) {
Emily Bernier958fae72015-03-24 16:35:39 -0400639 // Get the context containing declarations.
Ben Murdochf91f0612016-11-29 16:50:11 +0000640 DCHECK(maybe_context->IsContext());
641 Handle<Context> context(Context::cast(*maybe_context)->closure_context());
642
Emily Bernier958fae72015-03-24 16:35:39 -0400643 for (; i < scope_info->LocalCount(); ++i) {
Emily Bernier958fae72015-03-24 16:35:39 -0400644 Handle<String> name(scope_info->LocalName(i));
Ben Murdochbcf72ee2016-08-08 18:44:38 +0100645 if (ScopeInfo::VariableIsSynthetic(*name)) continue;
Emily Bernier958fae72015-03-24 16:35:39 -0400646 VariableMode mode;
647 InitializationFlag init_flag;
648 MaybeAssignedFlag maybe_assigned_flag;
Ben Murdochf91f0612016-11-29 16:50:11 +0000649 locals.Add(name);
Emily Bernier958fae72015-03-24 16:35:39 -0400650 int context_slot_index = ScopeInfo::ContextSlotIndex(
651 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
652 Object* value = context->get(context_slot_index);
Ben Murdochf91f0612016-11-29 16:50:11 +0000653 locals.Add(Handle<Object>(value, isolate));
Emily Bernier958fae72015-03-24 16:35:39 -0400654 }
655 }
656
657 // Check whether this frame is positioned at return. If not top
658 // frame or if the frame is optimized it cannot be at a return.
659 bool at_return = false;
660 if (!is_optimized && index == 0) {
Ben Murdochf91f0612016-11-29 16:50:11 +0000661 at_return = isolate->debug()->IsBreakAtReturn(it.javascript_frame());
Emily Bernier958fae72015-03-24 16:35:39 -0400662 }
663
664 // If positioned just before return find the value to be returned and add it
665 // to the frame information.
666 Handle<Object> return_value = isolate->factory()->undefined_value();
667 if (at_return) {
Ben Murdoch3b9bc312016-06-02 14:46:10 +0100668 return_value = isolate->debug()->return_value();
Emily Bernier958fae72015-03-24 16:35:39 -0400669 }
670
671 // Now advance to the arguments adapter frame (if any). It contains all
672 // the provided parameters whereas the function frame always have the number
673 // of arguments matching the functions parameters. The rest of the
674 // information (except for what is collected above) is the same.
Ben Murdochf91f0612016-11-29 16:50:11 +0000675 if ((inlined_jsframe_index == 0) &&
676 it.javascript_frame()->has_adapted_arguments()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400677 it.AdvanceToArgumentsFrame();
678 frame_inspector.SetArgumentsFrame(it.frame());
679 }
680
681 // Find the number of arguments to fill. At least fill the number of
682 // parameters for the function and fill more if more parameters are provided.
683 int argument_count = scope_info->ParameterCount();
684 if (argument_count < frame_inspector.GetParametersCount()) {
685 argument_count = frame_inspector.GetParametersCount();
686 }
687
688 // Calculate the size of the result.
689 int details_size = kFrameDetailsFirstDynamicIndex +
690 2 * (argument_count + local_count) + (at_return ? 1 : 0);
691 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
692
693 // Add the frame id.
694 details->set(kFrameDetailsFrameIdIndex, *frame_id);
695
696 // Add the function (same as in function frame).
Ben Murdoch109988c2016-05-18 11:27:45 +0100697 details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
Emily Bernier958fae72015-03-24 16:35:39 -0400698
Ben Murdochf91f0612016-11-29 16:50:11 +0000699 // Add the script wrapper
700 Handle<Object> script_wrapper =
701 Script::GetWrapper(frame_inspector.GetScript());
702 details->set(kFrameDetailsScriptIndex, *script_wrapper);
703
Emily Bernier958fae72015-03-24 16:35:39 -0400704 // Add the arguments count.
705 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
706
707 // Add the locals count
708 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
709
710 // Add the source position.
Ben Murdochf91f0612016-11-29 16:50:11 +0000711 if (position != kNoSourcePosition) {
Emily Bernier958fae72015-03-24 16:35:39 -0400712 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
713 } else {
714 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
715 }
716
717 // Add the constructor information.
718 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
719
720 // Add the at return information.
721 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
722
723 // Add flags to indicate information on whether this frame is
724 // bit 0: invoked in the debugger context.
725 // bit 1: optimized frame.
726 // bit 2: inlined in optimized frame
727 int flags = 0;
728 if (*save->context() == *isolate->debug()->debug_context()) {
729 flags |= 1 << 0;
730 }
731 if (is_optimized) {
732 flags |= 1 << 1;
733 flags |= inlined_jsframe_index << 2;
734 }
735 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
736
737 // Fill the dynamic part.
738 int details_index = kFrameDetailsFirstDynamicIndex;
739
740 // Add arguments name and value.
741 for (int i = 0; i < argument_count; i++) {
742 // Name of the argument.
743 if (i < scope_info->ParameterCount()) {
744 details->set(details_index++, scope_info->ParameterName(i));
745 } else {
746 details->set(details_index++, heap->undefined_value());
747 }
748
749 // Parameter value.
750 if (i < frame_inspector.GetParametersCount()) {
751 // Get the value from the stack.
Ben Murdoch109988c2016-05-18 11:27:45 +0100752 details->set(details_index++, *(frame_inspector.GetParameter(i)));
Emily Bernier958fae72015-03-24 16:35:39 -0400753 } else {
754 details->set(details_index++, heap->undefined_value());
755 }
756 }
757
758 // Add locals name and value from the temporary copy from the function frame.
Ben Murdochf91f0612016-11-29 16:50:11 +0000759 for (const auto& local : locals) details->set(details_index++, *local);
Emily Bernier958fae72015-03-24 16:35:39 -0400760
761 // Add the value being returned.
762 if (at_return) {
763 details->set(details_index++, *return_value);
764 }
765
766 // Add the receiver (same as in function frame).
Emily Bernier958fae72015-03-24 16:35:39 -0400767 Handle<Object> receiver(it.frame()->receiver(), isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000768 DCHECK(!function->shared()->IsBuiltin());
Ben Murdoch109988c2016-05-18 11:27:45 +0100769 DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver());
Emily Bernier958fae72015-03-24 16:35:39 -0400770 details->set(kFrameDetailsReceiverIndex, *receiver);
771
772 DCHECK_EQ(details_size, details_index);
773 return *isolate->factory()->NewJSArrayWithElements(details);
774}
775
776
Emily Bernier958fae72015-03-24 16:35:39 -0400777RUNTIME_FUNCTION(Runtime_GetScopeCount) {
778 HandleScope scope(isolate);
779 DCHECK(args.length() == 2);
780 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000781 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400782
783 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
784
785 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000786 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400787 JavaScriptFrameIterator it(isolate, id);
788 JavaScriptFrame* frame = it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000789 FrameInspector frame_inspector(frame, 0, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400790
791 // Count the visible scopes.
792 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000793 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400794 n++;
795 }
796
797 return Smi::FromInt(n);
798}
799
800
Emily Bernier958fae72015-03-24 16:35:39 -0400801// Return an array with scope details
802// args[0]: number: break id
803// args[1]: number: frame index
804// args[2]: number: inlined frame index
805// args[3]: number: scope index
806//
807// The array returned contains the following information:
808// 0: Scope type
809// 1: Scope object
810RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
811 HandleScope scope(isolate);
812 DCHECK(args.length() == 4);
813 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000814 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400815
816 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
817 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
818 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
819
820 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000821 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400822 JavaScriptFrameIterator frame_it(isolate, id);
823 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000824 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400825
826 // Find the requested scope.
827 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000828 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -0400829 for (; !it.Done() && n < index; it.Next()) {
830 n++;
831 }
832 if (it.Done()) {
833 return isolate->heap()->undefined_value();
834 }
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100835 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400836}
837
838
839// Return an array of scope details
840// args[0]: number: break id
841// args[1]: number: frame index
842// args[2]: number: inlined frame index
843// args[3]: boolean: ignore nested scopes
844//
845// The array returned contains arrays with the following information:
846// 0: Scope type
847// 1: Scope object
848RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
849 HandleScope scope(isolate);
850 DCHECK(args.length() == 3 || args.length() == 4);
851 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +0000852 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -0400853
854 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
855 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
856
Ben Murdoch014dc512016-03-22 12:00:34 +0000857 ScopeIterator::Option option = ScopeIterator::DEFAULT;
Emily Bernier958fae72015-03-24 16:35:39 -0400858 if (args.length() == 4) {
859 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
Ben Murdoch014dc512016-03-22 12:00:34 +0000860 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
Emily Bernier958fae72015-03-24 16:35:39 -0400861 }
862
863 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000864 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Ben Murdochf91f0612016-11-29 16:50:11 +0000865 StackTraceFrameIterator frame_it(isolate, id);
866 StandardFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000867 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400868
869 List<Handle<JSObject> > result(4);
Ben Murdoch014dc512016-03-22 12:00:34 +0000870 ScopeIterator it(isolate, &frame_inspector, option);
Emily Bernier958fae72015-03-24 16:35:39 -0400871 for (; !it.Done(); it.Next()) {
872 Handle<JSObject> details;
873 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch014dc512016-03-22 12:00:34 +0000874 it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400875 result.Add(details);
876 }
877
878 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
879 for (int i = 0; i < result.length(); ++i) {
880 array->set(i, *result[i]);
881 }
882 return *isolate->factory()->NewJSArrayWithElements(array);
883}
884
885
886RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
887 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000888 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -0400889
890 // Check arguments.
Ben Murdoch014dc512016-03-22 12:00:34 +0000891 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -0400892
893 // Count the visible scopes.
894 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000895 if (function->IsJSFunction()) {
896 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
897 !it.Done(); it.Next()) {
898 n++;
899 }
Emily Bernier958fae72015-03-24 16:35:39 -0400900 }
901
902 return Smi::FromInt(n);
903}
904
905
906RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
907 HandleScope scope(isolate);
908 DCHECK(args.length() == 2);
909
910 // Check arguments.
911 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
912 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
913
914 // Find the requested scope.
915 int n = 0;
916 ScopeIterator it(isolate, fun);
917 for (; !it.Done() && n < index; it.Next()) {
918 n++;
919 }
920 if (it.Done()) {
921 return isolate->heap()->undefined_value();
922 }
923
Ben Murdoch13e2dad2016-09-16 13:49:30 +0100924 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400925}
926
Ben Murdochf91f0612016-11-29 16:50:11 +0000927RUNTIME_FUNCTION(Runtime_GetGeneratorScopeCount) {
928 HandleScope scope(isolate);
929 DCHECK_EQ(1, args.length());
930
931 if (!args[0]->IsJSGeneratorObject()) return Smi::FromInt(0);
932
933 // Check arguments.
934 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
935
936 // Count the visible scopes.
937 int n = 0;
938 for (ScopeIterator it(isolate, gen); !it.Done(); it.Next()) {
939 n++;
940 }
941
942 return Smi::FromInt(n);
943}
944
945RUNTIME_FUNCTION(Runtime_GetGeneratorScopeDetails) {
946 HandleScope scope(isolate);
947 DCHECK(args.length() == 2);
948
949 if (!args[0]->IsJSGeneratorObject()) {
950 return *isolate->factory()->undefined_value();
951 }
952
953 // Check arguments.
954 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
955 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
956
957 // Find the requested scope.
958 int n = 0;
959 ScopeIterator it(isolate, gen);
960 for (; !it.Done() && n < index; it.Next()) {
961 n++;
962 }
963 if (it.Done()) {
964 return isolate->heap()->undefined_value();
965 }
966
967 RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
968}
Emily Bernier958fae72015-03-24 16:35:39 -0400969
970static bool SetScopeVariableValue(ScopeIterator* it, int index,
971 Handle<String> variable_name,
972 Handle<Object> new_value) {
973 for (int n = 0; !it->Done() && n < index; it->Next()) {
974 n++;
975 }
976 if (it->Done()) {
977 return false;
978 }
979 return it->SetVariableValue(variable_name, new_value);
980}
981
982
983// Change variable value in closure or local scope
984// args[0]: number or JsFunction: break id or function
985// args[1]: number: frame index (when arg[0] is break id)
986// args[2]: number: inlined frame index (when arg[0] is break id)
987// args[3]: number: scope index
988// args[4]: string: variable name
989// args[5]: object: new value
990//
991// Return true if success and false otherwise
992RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
993 HandleScope scope(isolate);
994 DCHECK(args.length() == 6);
995
996 // Check arguments.
997 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
998 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
999 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
1000
1001 bool res;
1002 if (args[0]->IsNumber()) {
1003 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001004 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001005
1006 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1007 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1008
1009 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +00001010 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -04001011 JavaScriptFrameIterator frame_it(isolate, id);
1012 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +00001013 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -04001014
Ben Murdoch014dc512016-03-22 12:00:34 +00001015 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -04001016 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001017 } else if (args[0]->IsJSFunction()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001018 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1019 ScopeIterator it(isolate, fun);
1020 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Ben Murdochf91f0612016-11-29 16:50:11 +00001021 } else {
1022 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, gen, 0);
1023 ScopeIterator it(isolate, gen);
1024 res = SetScopeVariableValue(&it, index, variable_name, new_value);
Emily Bernier958fae72015-03-24 16:35:39 -04001025 }
1026
1027 return isolate->heap()->ToBoolean(res);
1028}
1029
1030
1031RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
1032 HandleScope scope(isolate);
1033 DCHECK(args.length() == 0);
1034
1035#ifdef DEBUG
1036 // Print the scopes for the top frame.
1037 StackFrameLocator locator(isolate);
1038 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001039 FrameInspector frame_inspector(frame, 0, isolate);
1040
1041 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001042 it.DebugPrint();
1043 }
1044#endif
1045 return isolate->heap()->undefined_value();
1046}
1047
1048
Emily Bernier958fae72015-03-24 16:35:39 -04001049// Sets the disable break state
1050// args[0]: disable break state
Ben Murdoch014dc512016-03-22 12:00:34 +00001051RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001052 HandleScope scope(isolate);
1053 DCHECK(args.length() == 1);
Ben Murdoch014dc512016-03-22 12:00:34 +00001054 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1055 isolate->debug()->set_break_points_active(active);
Emily Bernier958fae72015-03-24 16:35:39 -04001056 return isolate->heap()->undefined_value();
1057}
1058
1059
1060static bool IsPositionAlignmentCodeCorrect(int alignment) {
1061 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1062}
1063
1064
1065RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1066 HandleScope scope(isolate);
1067 DCHECK(args.length() == 2);
Ben Murdochf91f0612016-11-29 16:50:11 +00001068 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001069 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1070 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1071
1072 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1073 return isolate->ThrowIllegalOperation();
1074 }
1075 BreakPositionAlignment alignment =
1076 static_cast<BreakPositionAlignment>(statement_aligned_code);
1077
1078 Handle<SharedFunctionInfo> shared(fun->shared());
1079 // Find the number of break points
1080 Handle<Object> break_locations =
1081 Debug::GetSourceBreakLocations(shared, alignment);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001082 if (break_locations->IsUndefined(isolate)) {
1083 return isolate->heap()->undefined_value();
1084 }
Emily Bernier958fae72015-03-24 16:35:39 -04001085 // Return array as JS array
1086 return *isolate->factory()->NewJSArrayWithElements(
1087 Handle<FixedArray>::cast(break_locations));
1088}
1089
1090
1091// Set a break point in a function.
1092// args[0]: function
1093// args[1]: number: break source position (within the function source)
1094// args[2]: number: break point object
1095RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1096 HandleScope scope(isolate);
1097 DCHECK(args.length() == 3);
Ben Murdochf91f0612016-11-29 16:50:11 +00001098 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001099 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1100 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001101 CHECK(source_position >= function->shared()->start_position() &&
1102 source_position <= function->shared()->end_position());
Emily Bernier958fae72015-03-24 16:35:39 -04001103 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1104
1105 // Set break point.
Ben Murdochf91f0612016-11-29 16:50:11 +00001106 CHECK(isolate->debug()->SetBreakPoint(function, break_point_object_arg,
1107 &source_position));
Emily Bernier958fae72015-03-24 16:35:39 -04001108
1109 return Smi::FromInt(source_position);
1110}
1111
1112
1113// Changes the state of a break point in a script and returns source position
1114// where break point was set. NOTE: Regarding performance see the NOTE for
1115// GetScriptFromScriptData.
1116// args[0]: script to set break point in
1117// args[1]: number: break source position (within the script source)
1118// args[2]: number, breakpoint position alignment
1119// args[3]: number: break point object
1120RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1121 HandleScope scope(isolate);
1122 DCHECK(args.length() == 4);
Ben Murdochf91f0612016-11-29 16:50:11 +00001123 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001124 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1125 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001126 CHECK(source_position >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001127 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1128 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1129
1130 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1131 return isolate->ThrowIllegalOperation();
1132 }
1133 BreakPositionAlignment alignment =
1134 static_cast<BreakPositionAlignment>(statement_aligned_code);
1135
1136 // Get the script from the script wrapper.
Ben Murdochf91f0612016-11-29 16:50:11 +00001137 CHECK(wrapper->value()->IsScript());
Emily Bernier958fae72015-03-24 16:35:39 -04001138 Handle<Script> script(Script::cast(wrapper->value()));
1139
1140 // Set break point.
1141 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1142 &source_position, alignment)) {
1143 return isolate->heap()->undefined_value();
1144 }
1145
1146 return Smi::FromInt(source_position);
1147}
1148
1149
1150// Clear a break point
1151// args[0]: number: break point object
1152RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1153 HandleScope scope(isolate);
1154 DCHECK(args.length() == 1);
Ben Murdochf91f0612016-11-29 16:50:11 +00001155 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001156 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1157
1158 // Clear break point.
1159 isolate->debug()->ClearBreakPoint(break_point_object_arg);
1160
1161 return isolate->heap()->undefined_value();
1162}
1163
1164
1165// Change the state of break on exceptions.
1166// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1167// args[1]: Boolean indicating on/off.
1168RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1169 HandleScope scope(isolate);
1170 DCHECK(args.length() == 2);
1171 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1172 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1173
1174 // If the number doesn't match an enum value, the ChangeBreakOnException
1175 // function will default to affecting caught exceptions.
1176 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1177 // Update break point state.
1178 isolate->debug()->ChangeBreakOnException(type, enable);
1179 return isolate->heap()->undefined_value();
1180}
1181
1182
1183// Returns the state of break on exceptions
1184// args[0]: boolean indicating uncaught exceptions
1185RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1186 HandleScope scope(isolate);
1187 DCHECK(args.length() == 1);
1188 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1189
1190 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1191 bool result = isolate->debug()->IsBreakOnException(type);
1192 return Smi::FromInt(result);
1193}
1194
1195
1196// Prepare for stepping
1197// args[0]: break id for checking execution state
1198// args[1]: step action from the enumeration StepAction
1199// args[2]: number of times to perform the step, for step out it is the number
1200// of frames to step down.
1201RUNTIME_FUNCTION(Runtime_PrepareStep) {
1202 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001203 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001204 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001205 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001206
Ben Murdoch014dc512016-03-22 12:00:34 +00001207 if (!args[1]->IsNumber()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001208 return isolate->Throw(isolate->heap()->illegal_argument_string());
1209 }
1210
Emily Bernier958fae72015-03-24 16:35:39 -04001211 // Get the step action and check validity.
1212 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1213 if (step_action != StepIn && step_action != StepNext &&
Ben Murdoch014dc512016-03-22 12:00:34 +00001214 step_action != StepOut && step_action != StepFrame) {
Emily Bernier958fae72015-03-24 16:35:39 -04001215 return isolate->Throw(isolate->heap()->illegal_argument_string());
1216 }
1217
1218 // Clear all current stepping setup.
1219 isolate->debug()->ClearStepping();
1220
1221 // Prepare step.
Ben Murdoch014dc512016-03-22 12:00:34 +00001222 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
Emily Bernier958fae72015-03-24 16:35:39 -04001223 return isolate->heap()->undefined_value();
1224}
1225
1226
1227// Clear all stepping set by PrepareStep.
1228RUNTIME_FUNCTION(Runtime_ClearStepping) {
1229 HandleScope scope(isolate);
1230 DCHECK(args.length() == 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001231 CHECK(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001232 isolate->debug()->ClearStepping();
1233 return isolate->heap()->undefined_value();
1234}
1235
1236
Emily Bernier958fae72015-03-24 16:35:39 -04001237RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1238 HandleScope scope(isolate);
1239
1240 // Check the execution state and decode arguments frame and source to be
1241 // evaluated.
1242 DCHECK(args.length() == 6);
1243 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001244 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001245
1246 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1247 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1248 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1249 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
Ben Murdoch014dc512016-03-22 12:00:34 +00001250 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
Emily Bernier958fae72015-03-24 16:35:39 -04001251
Ben Murdoch014dc512016-03-22 12:00:34 +00001252 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -04001253
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001254 RETURN_RESULT_OR_FAILURE(
1255 isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1256 disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001257}
1258
1259
1260RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1261 HandleScope scope(isolate);
1262
1263 // Check the execution state and decode arguments frame and source to be
1264 // evaluated.
1265 DCHECK(args.length() == 4);
1266 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001267 CHECK(isolate->debug()->CheckExecutionState(break_id));
Emily Bernier958fae72015-03-24 16:35:39 -04001268
1269 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1270 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
Ben Murdoch014dc512016-03-22 12:00:34 +00001271 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001272
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001273 RETURN_RESULT_OR_FAILURE(
1274 isolate,
Ben Murdoch014dc512016-03-22 12:00:34 +00001275 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001276}
1277
1278
1279RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1280 HandleScope scope(isolate);
1281 DCHECK(args.length() == 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001282
1283 // This runtime function is used by the debugger to determine whether the
1284 // debugger is active or not. Hence we fail gracefully here and don't crash.
1285 if (!isolate->debug()->is_active()) return isolate->ThrowIllegalOperation();
Emily Bernier958fae72015-03-24 16:35:39 -04001286
Ben Murdoch014dc512016-03-22 12:00:34 +00001287 Handle<FixedArray> instances;
1288 {
1289 DebugScope debug_scope(isolate->debug());
1290 if (debug_scope.failed()) {
1291 DCHECK(isolate->has_pending_exception());
1292 return isolate->heap()->exception();
1293 }
1294 // Fill the script objects.
1295 instances = isolate->debug()->GetLoadedScripts();
1296 }
Emily Bernier958fae72015-03-24 16:35:39 -04001297
1298 // Convert the script objects to proper JS objects.
1299 for (int i = 0; i < instances->length(); i++) {
1300 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1301 // Get the script wrapper in a local handle before calling GetScriptWrapper,
1302 // because using
1303 // instances->set(i, *GetScriptWrapper(script))
1304 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1305 // already have dereferenced the instances handle.
1306 Handle<JSObject> wrapper = Script::GetWrapper(script);
1307 instances->set(i, *wrapper);
1308 }
1309
1310 // Return result as a JS array.
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001311 return *isolate->factory()->NewJSArrayWithElements(instances);
Emily Bernier958fae72015-03-24 16:35:39 -04001312}
1313
Ben Murdoch109988c2016-05-18 11:27:45 +01001314static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1315 JSObject* object,
Ben Murdoch014dc512016-03-22 12:00:34 +00001316 Object* proto) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001317 PrototypeIterator iter(isolate, object, kStartAtReceiver);
Ben Murdoch014dc512016-03-22 12:00:34 +00001318 while (true) {
1319 iter.AdvanceIgnoringProxies();
1320 if (iter.IsAtEnd()) return false;
Ben Murdoch109988c2016-05-18 11:27:45 +01001321 if (iter.GetCurrent() == proto) return true;
Emily Bernier958fae72015-03-24 16:35:39 -04001322 }
Emily Bernier958fae72015-03-24 16:35:39 -04001323}
1324
1325
1326// Scan the heap for objects with direct references to an object
1327// args[0]: the object to find references to
1328// args[1]: constructor function for instances to exclude (Mirror)
1329// args[2]: the the maximum number of objects to return
1330RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1331 HandleScope scope(isolate);
1332 DCHECK(args.length() == 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001333 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001334 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
Ben Murdochf91f0612016-11-29 16:50:11 +00001335 CHECK(filter->IsUndefined(isolate) || filter->IsJSObject());
Emily Bernier958fae72015-03-24 16:35:39 -04001336 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001337 CHECK(max_references >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001338
Ben Murdoch014dc512016-03-22 12:00:34 +00001339 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001340 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001341 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001342 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1343 // Get the constructor function for context extension and arguments array.
1344 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1345 HeapObject* heap_obj;
1346 while ((heap_obj = iterator.next())) {
1347 if (!heap_obj->IsJSObject()) continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001348 JSObject* obj = JSObject::cast(heap_obj);
Ben Murdoch014dc512016-03-22 12:00:34 +00001349 if (obj->IsJSContextExtensionObject()) continue;
1350 if (obj->map()->GetConstructor() == arguments_fun) continue;
1351 if (!obj->ReferencesObject(*target)) continue;
1352 // Check filter if supplied. This is normally used to avoid
1353 // references from mirror objects.
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001354 if (!filter->IsUndefined(isolate) &&
Ben Murdoch014dc512016-03-22 12:00:34 +00001355 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1356 continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001357 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001358 if (obj->IsJSGlobalObject()) {
1359 obj = JSGlobalObject::cast(obj)->global_proxy();
1360 }
1361 instances.Add(Handle<JSObject>(obj));
1362 if (instances.length() == max_references) break;
1363 }
1364 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1365 while (iterator.next()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001366 }
1367 }
1368
Ben Murdoch014dc512016-03-22 12:00:34 +00001369 Handle<FixedArray> result;
1370 if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1371 // Check for circular reference only. This can happen when the object is
1372 // only referenced from mirrors and has a circular reference in which case
1373 // the object is not really alive and would have been garbage collected if
1374 // not referenced from the mirror.
1375 result = isolate->factory()->empty_fixed_array();
1376 } else {
1377 result = isolate->factory()->NewFixedArray(instances.length());
1378 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1379 }
1380 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001381}
1382
1383
1384// Scan the heap for objects constructed by a specific function.
1385// args[0]: the constructor to find instances of
1386// args[1]: the the maximum number of objects to return
1387RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1388 HandleScope scope(isolate);
1389 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001390 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1391 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
Ben Murdochf91f0612016-11-29 16:50:11 +00001392 CHECK(max_references >= 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001393
Ben Murdoch014dc512016-03-22 12:00:34 +00001394 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001395 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001396 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001397 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1398 HeapObject* heap_obj;
1399 while ((heap_obj = iterator.next())) {
1400 if (!heap_obj->IsJSObject()) continue;
1401 JSObject* obj = JSObject::cast(heap_obj);
1402 if (obj->map()->GetConstructor() != *constructor) continue;
1403 instances.Add(Handle<JSObject>(obj));
1404 if (instances.length() == max_references) break;
1405 }
1406 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1407 while (iterator.next()) {
1408 }
Emily Bernier958fae72015-03-24 16:35:39 -04001409 }
1410
Ben Murdoch014dc512016-03-22 12:00:34 +00001411 Handle<FixedArray> result =
1412 isolate->factory()->NewFixedArray(instances.length());
1413 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1414 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001415}
1416
1417
1418// Find the effective prototype object as returned by __proto__.
1419// args[0]: the object to find the prototype for.
1420RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1421 HandleScope shs(isolate);
1422 DCHECK(args.length() == 1);
1423 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001424 // TODO(1543): Come up with a solution for clients to handle potential errors
1425 // thrown by an intermediate proxy.
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001426 RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
Emily Bernier958fae72015-03-24 16:35:39 -04001427}
1428
1429
1430// Patches script source (should be called upon BeforeCompile event).
1431RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1432 HandleScope scope(isolate);
1433 DCHECK(args.length() == 2);
1434
1435 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1436 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1437
Ben Murdochf91f0612016-11-29 16:50:11 +00001438 CHECK(script_wrapper->value()->IsScript());
Emily Bernier958fae72015-03-24 16:35:39 -04001439 Handle<Script> script(Script::cast(script_wrapper->value()));
1440
Ben Murdochf91f0612016-11-29 16:50:11 +00001441 // The following condition is not guaranteed to hold and a failure is also
1442 // propagated to callers. Hence we fail gracefully here and don't crash.
1443 if (script->compilation_state() != Script::COMPILATION_STATE_INITIAL) {
1444 return isolate->ThrowIllegalOperation();
1445 }
1446
Emily Bernier958fae72015-03-24 16:35:39 -04001447 script->set_source(*source);
1448
1449 return isolate->heap()->undefined_value();
1450}
1451
1452
Emily Bernier958fae72015-03-24 16:35:39 -04001453RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1454 SealHandleScope shs(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001455 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -04001456
Ben Murdoch014dc512016-03-22 12:00:34 +00001457 CONVERT_ARG_CHECKED(Object, f, 0);
1458 if (f->IsJSFunction()) {
1459 return JSFunction::cast(f)->shared()->inferred_name();
1460 }
1461 return isolate->heap()->empty_string();
1462}
1463
1464
1465RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1466 HandleScope scope(isolate);
1467 DCHECK_EQ(1, args.length());
1468
1469 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1470
1471 if (function->IsJSBoundFunction()) {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001472 RETURN_RESULT_OR_FAILURE(
1473 isolate, JSBoundFunction::GetName(
1474 isolate, Handle<JSBoundFunction>::cast(function)));
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001475 } else {
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001476 return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
Ben Murdoch014dc512016-03-22 12:00:34 +00001477 }
Emily Bernier958fae72015-03-24 16:35:39 -04001478}
1479
1480
Emily Bernier958fae72015-03-24 16:35:39 -04001481// Calls specified function with or without entering the debugger.
1482// This is used in unit tests to run code as if debugger is entered or simply
1483// to have a stack with C++ frame in the middle.
1484RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1485 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001486 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001487 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001488
Ben Murdoch014dc512016-03-22 12:00:34 +00001489 DebugScope debug_scope(isolate->debug());
1490 if (debug_scope.failed()) {
1491 DCHECK(isolate->has_pending_exception());
1492 return isolate->heap()->exception();
Emily Bernier958fae72015-03-24 16:35:39 -04001493 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001494
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001495 RETURN_RESULT_OR_FAILURE(
1496 isolate, Execution::Call(isolate, function,
1497 handle(function->global_proxy()), 0, NULL));
Emily Bernier958fae72015-03-24 16:35:39 -04001498}
1499
1500
Ben Murdoch014dc512016-03-22 12:00:34 +00001501RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1502 HandleScope scope(isolate);
1503 DCHECK(args.length() == 0);
1504 Handle<Context> context;
1505 {
1506 DebugScope debug_scope(isolate->debug());
1507 if (debug_scope.failed()) {
1508 DCHECK(isolate->has_pending_exception());
1509 return isolate->heap()->exception();
1510 }
1511 context = isolate->debug()->GetDebugContext();
1512 }
1513 if (context.is_null()) return isolate->heap()->undefined_value();
1514 context->set_security_token(isolate->native_context()->security_token());
1515 return context->global_proxy();
1516}
1517
1518
Emily Bernier958fae72015-03-24 16:35:39 -04001519// Performs a GC.
1520// Presently, it only does a full GC.
1521RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1522 SealHandleScope shs(isolate);
1523 DCHECK(args.length() == 1);
1524 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
1525 return isolate->heap()->undefined_value();
1526}
1527
1528
1529// Gets the current heap usage.
1530RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1531 SealHandleScope shs(isolate);
1532 DCHECK(args.length() == 0);
1533 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1534 if (!Smi::IsValid(usage)) {
1535 return *isolate->factory()->NewNumberFromInt(usage);
1536 }
1537 return Smi::FromInt(usage);
1538}
1539
1540
1541// Finds the script object from the script data. NOTE: This operation uses
1542// heap traversal to find the function generated for the source position
1543// for the requested break point. For lazily compiled functions several heap
1544// traversals might be required rendering this operation as a rather slow
1545// operation. However for setting break points which is normally done through
1546// some kind of user interaction the performance is not crucial.
1547RUNTIME_FUNCTION(Runtime_GetScript) {
1548 HandleScope scope(isolate);
1549 DCHECK(args.length() == 1);
1550 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1551
1552 Handle<Script> found;
Emily Bernier958fae72015-03-24 16:35:39 -04001553 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001554 Script::Iterator iterator(isolate);
1555 Script* script = NULL;
1556 while ((script = iterator.Next()) != NULL) {
Emily Bernier958fae72015-03-24 16:35:39 -04001557 if (!script->name()->IsString()) continue;
1558 String* name = String::cast(script->name());
1559 if (name->Equals(*script_name)) {
1560 found = Handle<Script>(script, isolate);
1561 break;
1562 }
1563 }
1564 }
1565
Ben Murdoch014dc512016-03-22 12:00:34 +00001566 if (found.is_null()) return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -04001567 return *Script::GetWrapper(found);
1568}
1569
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001570RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
1571 HandleScope scope(isolate);
1572 DCHECK(args.length() == 1);
1573 CONVERT_ARG_CHECKED(JSValue, script, 0);
1574
Ben Murdochf91f0612016-11-29 16:50:11 +00001575 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001576 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1577
1578 Script::InitLineEnds(script_handle);
1579
1580 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1581 return Smi::FromInt(line_ends_array->length());
1582}
1583
1584RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
1585 HandleScope scope(isolate);
1586 DCHECK(args.length() == 2);
1587 CONVERT_ARG_CHECKED(JSValue, script, 0);
1588 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1589
Ben Murdochf91f0612016-11-29 16:50:11 +00001590 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001591 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1592
1593 Script::InitLineEnds(script_handle);
1594
1595 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1596 const int line_count = line_ends_array->length();
1597
1598 // If line == line_count, we return the first position beyond the last line.
1599 if (line < 0 || line > line_count) {
1600 return Smi::FromInt(-1);
1601 } else if (line == 0) {
1602 return Smi::FromInt(0);
1603 } else {
1604 DCHECK(0 < line && line <= line_count);
1605 const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1606 return Smi::FromInt(pos);
1607 }
1608}
1609
1610RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
1611 HandleScope scope(isolate);
1612 DCHECK(args.length() == 2);
1613 CONVERT_ARG_CHECKED(JSValue, script, 0);
1614 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1615
Ben Murdochf91f0612016-11-29 16:50:11 +00001616 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001617 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1618
1619 Script::InitLineEnds(script_handle);
1620
1621 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1622 const int line_count = line_ends_array->length();
1623
1624 if (line < 0 || line >= line_count) {
1625 return Smi::FromInt(-1);
1626 } else {
1627 return Smi::cast(line_ends_array->get(line));
1628 }
1629}
1630
1631static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
1632 Script::OffsetFlag offset_flag,
1633 Isolate* isolate) {
1634 Script::PositionInfo info;
1635 if (!script->GetPositionInfo(position, &info, offset_flag)) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001636 return isolate->factory()->null_value();
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001637 }
1638
1639 Handle<String> source = handle(String::cast(script->source()), isolate);
Ben Murdochf91f0612016-11-29 16:50:11 +00001640 Handle<String> sourceText = script->type() == Script::TYPE_WASM
1641 ? isolate->factory()->empty_string()
1642 : isolate->factory()->NewSubString(
1643 source, info.line_start, info.line_end);
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001644
1645 Handle<JSObject> jsinfo =
1646 isolate->factory()->NewJSObject(isolate->object_function());
1647
1648 JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
1649 NONE);
1650 JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
1651 handle(Smi::FromInt(position), isolate), NONE);
1652 JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
1653 handle(Smi::FromInt(info.line), isolate), NONE);
1654 JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
1655 handle(Smi::FromInt(info.column), isolate), NONE);
1656 JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
1657 sourceText, NONE);
1658
1659 return jsinfo;
1660}
1661
1662// Get information on a specific source line and column possibly offset by a
1663// fixed source position. This function is used to find a source position from
1664// a line and column position. The fixed source position offset is typically
1665// used to find a source position in a function based on a line and column in
1666// the source for the function alone. The offset passed will then be the
1667// start position of the source for the function within the full script source.
1668// Note that incoming line and column parameters may be undefined, and are
1669// assumed to be passed *with* offsets.
1670RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
1671 HandleScope scope(isolate);
1672 DCHECK(args.length() == 4);
1673 CONVERT_ARG_CHECKED(JSValue, script, 0);
1674
Ben Murdochf91f0612016-11-29 16:50:11 +00001675 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001676 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1677
1678 // Line and column are possibly undefined and we need to handle these cases,
1679 // additionally subtracting corresponding offsets.
1680
1681 int32_t line;
1682 if (args[1]->IsNull(isolate) || args[1]->IsUndefined(isolate)) {
1683 line = 0;
1684 } else {
Ben Murdochf91f0612016-11-29 16:50:11 +00001685 CHECK(args[1]->IsNumber());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001686 line = NumberToInt32(args[1]) - script_handle->line_offset();
1687 }
1688
1689 int32_t column;
1690 if (args[2]->IsNull(isolate) || args[2]->IsUndefined(isolate)) {
1691 column = 0;
1692 } else {
Ben Murdochf91f0612016-11-29 16:50:11 +00001693 CHECK(args[2]->IsNumber());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001694 column = NumberToInt32(args[2]);
1695 if (line == 0) column -= script_handle->column_offset();
1696 }
1697
1698 CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]);
1699
1700 if (line < 0 || column < 0 || offset_position < 0) {
1701 return isolate->heap()->null_value();
1702 }
1703
1704 Script::InitLineEnds(script_handle);
1705
1706 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1707 const int line_count = line_ends_array->length();
1708
1709 int position;
1710 if (line == 0) {
1711 position = offset_position + column;
1712 } else {
1713 Script::PositionInfo info;
1714 if (!script_handle->GetPositionInfo(offset_position, &info,
1715 Script::NO_OFFSET) ||
1716 info.line + line >= line_count) {
1717 return isolate->heap()->null_value();
1718 }
1719
1720 const int offset_line = info.line + line;
1721 const int offset_line_position =
1722 (offset_line == 0)
1723 ? 0
1724 : Smi::cast(line_ends_array->get(offset_line - 1))->value() + 1;
1725 position = offset_line_position + column;
1726 }
1727
1728 return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET,
1729 isolate);
1730}
1731
1732RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
1733 HandleScope scope(isolate);
1734 DCHECK(args.length() == 3);
1735 CONVERT_ARG_CHECKED(JSValue, script, 0);
1736 CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
1737 CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
1738
Ben Murdochf91f0612016-11-29 16:50:11 +00001739 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001740 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1741
1742 const Script::OffsetFlag offset_flag =
1743 with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
1744 return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
1745}
1746
1747// Returns the given line as a string, or null if line is out of bounds.
1748// The parameter line is expected to include the script's line offset.
1749RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
1750 HandleScope scope(isolate);
1751 DCHECK(args.length() == 2);
1752 CONVERT_ARG_CHECKED(JSValue, script, 0);
1753 CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
1754
Ben Murdochf91f0612016-11-29 16:50:11 +00001755 CHECK(script->value()->IsScript());
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001756 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
1757
1758 Script::InitLineEnds(script_handle);
1759
1760 FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
1761 const int line_count = line_ends_array->length();
1762
1763 line -= script_handle->line_offset();
1764 if (line < 0 || line_count <= line) {
1765 return isolate->heap()->null_value();
1766 }
1767
1768 const int start =
1769 (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
1770 const int end = Smi::cast(line_ends_array->get(line))->value();
1771
1772 Handle<String> source =
1773 handle(String::cast(script_handle->source()), isolate);
1774 Handle<String> str = isolate->factory()->NewSubString(source, start, end);
1775
1776 return *str;
1777}
Emily Bernier958fae72015-03-24 16:35:39 -04001778
Emily Bernier958fae72015-03-24 16:35:39 -04001779// Set one shot breakpoints for the callback function that is passed to a
Ben Murdoch014dc512016-03-22 12:00:34 +00001780// built-in function such as Array.forEach to enable stepping into the callback,
1781// if we are indeed stepping and the callback is subject to debugging.
Emily Bernier958fae72015-03-24 16:35:39 -04001782RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
Emily Bernier958fae72015-03-24 16:35:39 -04001783 HandleScope scope(isolate);
Ben Murdochbcf72ee2016-08-08 18:44:38 +01001784 DCHECK_EQ(1, args.length());
1785 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001786 isolate->debug()->PrepareStepIn(fun);
Emily Bernier958fae72015-03-24 16:35:39 -04001787 return isolate->heap()->undefined_value();
1788}
1789
Ben Murdoch13e2dad2016-09-16 13:49:30 +01001790// Set one shot breakpoints for the suspended generator object.
1791RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
1792 HandleScope scope(isolate);
1793 DCHECK_EQ(0, args.length());
1794 isolate->debug()->PrepareStepInSuspendedGenerator();
1795 return isolate->heap()->undefined_value();
1796}
1797
1798RUNTIME_FUNCTION(Runtime_DebugRecordAsyncFunction) {
1799 HandleScope scope(isolate);
1800 DCHECK_EQ(1, args.length());
1801 CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
1802 CHECK(isolate->debug()->last_step_action() >= StepNext);
1803 isolate->debug()->RecordAsyncFunction(generator);
1804 return isolate->heap()->undefined_value();
1805}
Emily Bernier958fae72015-03-24 16:35:39 -04001806
1807RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
Ben Murdochf91f0612016-11-29 16:50:11 +00001808 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001809 HandleScope scope(isolate);
1810 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
Ben Murdochf91f0612016-11-29 16:50:11 +00001811 isolate->PushPromise(promise);
Emily Bernier958fae72015-03-24 16:35:39 -04001812 return isolate->heap()->undefined_value();
1813}
1814
1815
1816RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1817 DCHECK(args.length() == 0);
1818 SealHandleScope shs(isolate);
1819 isolate->PopPromise();
1820 return isolate->heap()->undefined_value();
1821}
1822
1823
Emily Bernier958fae72015-03-24 16:35:39 -04001824RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1825 DCHECK(args.length() == 1);
1826 HandleScope scope(isolate);
1827 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1828 isolate->debug()->OnAsyncTaskEvent(data);
1829 return isolate->heap()->undefined_value();
1830}
1831
1832
Ben Murdoch014dc512016-03-22 12:00:34 +00001833RUNTIME_FUNCTION(Runtime_DebugIsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001834 SealHandleScope shs(isolate);
1835 return Smi::FromInt(isolate->debug()->is_active());
1836}
1837
1838
Ben Murdoch014dc512016-03-22 12:00:34 +00001839RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
Emily Bernier958fae72015-03-24 16:35:39 -04001840 UNIMPLEMENTED();
1841 return NULL;
1842}
Ben Murdochf91f0612016-11-29 16:50:11 +00001843
1844RUNTIME_FUNCTION(Runtime_GetWasmFunctionOffsetTable) {
1845 DCHECK(args.length() == 1);
1846 HandleScope scope(isolate);
1847 CONVERT_ARG_CHECKED(JSValue, script_val, 0);
1848
1849 CHECK(script_val->value()->IsScript());
1850 Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
1851
1852 Handle<wasm::WasmDebugInfo> debug_info =
1853 wasm::GetDebugInfo(handle(script->wasm_object(), isolate));
1854 Handle<FixedArray> elements = wasm::WasmDebugInfo::GetFunctionOffsetTable(
1855 debug_info, script->wasm_function_index());
1856 return *isolate->factory()->NewJSArrayWithElements(elements);
1857}
1858
1859RUNTIME_FUNCTION(Runtime_DisassembleWasmFunction) {
1860 DCHECK(args.length() == 1);
1861 HandleScope scope(isolate);
1862 CONVERT_ARG_CHECKED(JSValue, script_val, 0);
1863
1864 CHECK(script_val->value()->IsScript());
1865 Handle<Script> script = Handle<Script>(Script::cast(script_val->value()));
1866
1867 Handle<wasm::WasmDebugInfo> debug_info =
1868 wasm::GetDebugInfo(handle(script->wasm_object(), isolate));
1869 return *wasm::WasmDebugInfo::DisassembleFunction(
1870 debug_info, script->wasm_function_index());
1871}
1872
Ben Murdoch014dc512016-03-22 12:00:34 +00001873} // namespace internal
1874} // namespace v8