blob: e3f3beb6976da53443707168c427ff0247e525ed [file] [log] [blame]
Emily Bernierd0a1eb72015-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 Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/runtime/runtime-utils.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/arguments.h"
Ben Murdoch4a90d5f2016-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 Murdochda12d292016-06-02 14:46:10 +010011#include "src/debug/debug.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/frames-inl.h"
Ben Murdochda12d292016-06-02 14:46:10 +010013#include "src/interpreter/bytecodes.h"
14#include "src/interpreter/interpreter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/isolate-inl.h"
16#include "src/runtime/runtime.h"
17
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018namespace v8 {
19namespace internal {
20
21RUNTIME_FUNCTION(Runtime_DebugBreak) {
22 SealHandleScope shs(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010023 DCHECK(args.length() == 1);
24 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
25 isolate->debug()->set_return_value(value);
26
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027 // Get the top-most JavaScript frame.
28 JavaScriptFrameIterator it(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010029 isolate->debug()->Break(it.frame());
30
31 isolate->debug()->SetAfterBreakTarget(it.frame());
32 return *isolate->debug()->return_value();
33}
34
35RUNTIME_FUNCTION(Runtime_DebugBreakOnBytecode) {
36 SealHandleScope shs(isolate);
37 DCHECK(args.length() == 1);
38 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
39 isolate->debug()->set_return_value(value);
40
41 // Get the top-most JavaScript frame.
42 JavaScriptFrameIterator it(isolate);
43 isolate->debug()->Break(it.frame());
44
Ben Murdochc5610432016-08-08 18:44:38 +010045 // If live-edit has dropped frames, we are not going back to dispatch.
46 if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0);
47
Ben Murdochda12d292016-06-02 14:46:10 +010048 // Return the handler from the original bytecode array.
49 DCHECK(it.frame()->is_interpreted());
50 InterpretedFrame* interpreted_frame =
51 reinterpret_cast<InterpretedFrame*>(it.frame());
52 SharedFunctionInfo* shared = interpreted_frame->function()->shared();
53 BytecodeArray* bytecode_array = shared->bytecode_array();
54 int bytecode_offset = interpreted_frame->GetBytecodeOffset();
55 interpreter::Bytecode bytecode =
56 interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
57 return isolate->interpreter()->GetBytecodeHandler(
58 bytecode, interpreter::OperandScale::kSingle);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059}
60
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
63 SealHandleScope shs(isolate);
64 DCHECK(args.length() == 0);
65 if (isolate->debug()->break_points_active()) {
66 isolate->debug()->HandleDebugBreak();
67 }
68 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069}
70
71
72// Adds a JavaScript function as a debug event listener.
73// args[0]: debug event listener function to set or null or undefined for
74// clearing the event listener function
75// args[1]: object supplied during callback
76RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
77 SealHandleScope shs(isolate);
78 DCHECK(args.length() == 2);
79 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
80 args[0]->IsNull());
81 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
82 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
83 isolate->debug()->SetEventListener(callback, data);
84
85 return isolate->heap()->undefined_value();
86}
87
88
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090 SealHandleScope shs(isolate);
91 DCHECK(args.length() == 0);
92 isolate->stack_guard()->RequestDebugBreak();
93 return isolate->heap()->undefined_value();
94}
95
96
97static Handle<Object> DebugGetProperty(LookupIterator* it,
98 bool* has_caught = NULL) {
99 for (; it->IsFound(); it->Next()) {
100 switch (it->state()) {
101 case LookupIterator::NOT_FOUND:
102 case LookupIterator::TRANSITION:
103 UNREACHABLE();
104 case LookupIterator::ACCESS_CHECK:
105 // Ignore access checks.
106 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108 case LookupIterator::INTERCEPTOR:
109 case LookupIterator::JSPROXY:
110 return it->isolate()->factory()->undefined_value();
111 case LookupIterator::ACCESSOR: {
112 Handle<Object> accessors = it->GetAccessors();
113 if (!accessors->IsAccessorInfo()) {
114 return it->isolate()->factory()->undefined_value();
115 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 MaybeHandle<Object> maybe_result =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100117 JSObject::GetPropertyWithAccessor(it);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118 Handle<Object> result;
119 if (!maybe_result.ToHandle(&result)) {
120 result = handle(it->isolate()->pending_exception(), it->isolate());
121 it->isolate()->clear_pending_exception();
122 if (has_caught != NULL) *has_caught = true;
123 }
124 return result;
125 }
126
127 case LookupIterator::DATA:
128 return it->GetDataValue();
129 }
130 }
131
132 return it->isolate()->factory()->undefined_value();
133}
134
135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136static Handle<Object> DebugGetProperty(Handle<Object> object,
137 Handle<Name> name) {
138 LookupIterator it(object, name);
139 return DebugGetProperty(&it);
140}
141
142
143template <class IteratorType>
144static MaybeHandle<JSArray> GetIteratorInternalProperties(
145 Isolate* isolate, Handle<IteratorType> object) {
146 Factory* factory = isolate->factory();
147 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
148 RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
149 const char* kind = NULL;
150 switch (Smi::cast(iterator->kind())->value()) {
151 case IteratorType::kKindKeys:
152 kind = "keys";
153 break;
154 case IteratorType::kKindValues:
155 kind = "values";
156 break;
157 case IteratorType::kKindEntries:
158 kind = "entries";
159 break;
160 default:
161 RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
162 }
163
164 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
165 Handle<String> has_more =
166 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
167 result->set(0, *has_more);
168 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
169
170 Handle<String> index =
171 factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
172 result->set(2, *index);
173 result->set(3, iterator->index());
174
175 Handle<String> iterator_kind =
176 factory->NewStringFromAsciiChecked("[[IteratorKind]]");
177 result->set(4, *iterator_kind);
178 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
179 result->set(5, *kind_str);
180 return factory->NewJSArrayWithElements(result);
181}
182
183
184MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
185 Handle<Object> object) {
186 Factory* factory = isolate->factory();
187 if (object->IsJSBoundFunction()) {
188 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
189
190 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
191 Handle<String> target =
192 factory->NewStringFromAsciiChecked("[[TargetFunction]]");
193 result->set(0, *target);
194 result->set(1, function->bound_target_function());
195
196 Handle<String> bound_this =
197 factory->NewStringFromAsciiChecked("[[BoundThis]]");
198 result->set(2, *bound_this);
199 result->set(3, function->bound_this());
200
201 Handle<String> bound_args =
202 factory->NewStringFromAsciiChecked("[[BoundArgs]]");
203 result->set(4, *bound_args);
204 Handle<FixedArray> bound_arguments =
205 factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
206 Handle<JSArray> arguments_array =
207 factory->NewJSArrayWithElements(bound_arguments);
208 result->set(5, *arguments_array);
209 return factory->NewJSArrayWithElements(result);
210 } else if (object->IsJSMapIterator()) {
211 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
212 return GetIteratorInternalProperties(isolate, iterator);
213 } else if (object->IsJSSetIterator()) {
214 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
215 return GetIteratorInternalProperties(isolate, iterator);
216 } else if (object->IsJSGeneratorObject()) {
217 Handle<JSGeneratorObject> generator =
218 Handle<JSGeneratorObject>::cast(object);
219
220 const char* status = "suspended";
221 if (generator->is_closed()) {
222 status = "closed";
223 } else if (generator->is_executing()) {
224 status = "running";
225 } else {
226 DCHECK(generator->is_suspended());
227 }
228
229 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
230 Handle<String> generator_status =
231 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
232 result->set(0, *generator_status);
233 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
234 result->set(1, *status_str);
235
236 Handle<String> function =
237 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
238 result->set(2, *function);
239 result->set(3, generator->function());
240
241 Handle<String> receiver =
242 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
243 result->set(4, *receiver);
244 result->set(5, generator->receiver());
245 return factory->NewJSArrayWithElements(result);
246 } else if (Object::IsPromise(object)) {
247 Handle<JSObject> promise = Handle<JSObject>::cast(object);
248
249 Handle<Object> status_obj =
Ben Murdochc5610432016-08-08 18:44:38 +0100250 DebugGetProperty(promise, isolate->factory()->promise_state_symbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
252 const char* status = "rejected";
253 int status_val = Handle<Smi>::cast(status_obj)->value();
254 switch (status_val) {
255 case +1:
256 status = "resolved";
257 break;
258 case 0:
259 status = "pending";
260 break;
261 default:
262 DCHECK_EQ(-1, status_val);
263 }
264
265 Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
266 Handle<String> promise_status =
267 factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
268 result->set(0, *promise_status);
269 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
270 result->set(1, *status_str);
271
272 Handle<Object> value_obj =
Ben Murdochc5610432016-08-08 18:44:38 +0100273 DebugGetProperty(promise, isolate->factory()->promise_result_symbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 Handle<String> promise_value =
275 factory->NewStringFromAsciiChecked("[[PromiseValue]]");
276 result->set(2, *promise_value);
277 result->set(3, *value_obj);
278 return factory->NewJSArrayWithElements(result);
Ben Murdochc5610432016-08-08 18:44:38 +0100279 } else if (object->IsJSProxy()) {
280 Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
281 Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
282
283 Handle<String> handler_str =
284 factory->NewStringFromAsciiChecked("[[Handler]]");
285 result->set(0, *handler_str);
286 result->set(1, js_proxy->handler());
287
288 Handle<String> target_str =
289 factory->NewStringFromAsciiChecked("[[Target]]");
290 result->set(2, *target_str);
291 result->set(3, js_proxy->target());
292
293 Handle<String> is_revoked_str =
294 factory->NewStringFromAsciiChecked("[[IsRevoked]]");
295 result->set(4, *is_revoked_str);
296 result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
297 return factory->NewJSArrayWithElements(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 } else if (object->IsJSValue()) {
299 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
300
301 Handle<FixedArray> result = factory->NewFixedArray(2);
302 Handle<String> primitive_value =
303 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
304 result->set(0, *primitive_value);
305 result->set(1, js_value->value());
306 return factory->NewJSArrayWithElements(result);
307 }
308 return factory->NewJSArray(0);
309}
310
311
312RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
313 HandleScope scope(isolate);
314 DCHECK(args.length() == 1);
315 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
316 Handle<JSArray> result;
317 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
318 isolate, result, Runtime::GetInternalProperties(isolate, obj));
319 return *result;
320}
321
322
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323// Get debugger related details for an object property, in the following format:
324// 0: Property value
325// 1: Property details
326// 2: Property value is exception
327// 3: Getter function if defined
328// 4: Setter function if defined
329// Items 2-4 are only filled if the property has either a getter or a setter.
330RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
331 HandleScope scope(isolate);
332
333 DCHECK(args.length() == 2);
334
335 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
336 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
337
338 // Make sure to set the current context to the context before the debugger was
339 // entered (if the debugger is entered). The reason for switching context here
340 // is that for some property lookups (accessors and interceptors) callbacks
341 // into the embedding application can occour, and the embedding application
342 // could have the assumption that its own native context is the current
343 // context and not some internal debugger context.
344 SaveContext save(isolate);
345 if (isolate->debug()->in_debug_scope()) {
346 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
347 }
348
349 // Check if the name is trivially convertible to an index and get the element
350 // if so.
351 uint32_t index;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
353 // this special case.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354 if (name->AsArrayIndex(&index)) {
355 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
356 Handle<Object> element_or_char;
Ben Murdochda12d292016-06-02 14:46:10 +0100357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
358 isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400359 details->set(0, *element_or_char);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 details->set(1, PropertyDetails::Empty().AsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 return *isolate->factory()->NewJSArrayWithElements(details);
362 }
363
Ben Murdochc5610432016-08-08 18:44:38 +0100364 LookupIterator it(obj, name, LookupIterator::OWN);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365 bool has_caught = false;
366 Handle<Object> value = DebugGetProperty(&it, &has_caught);
367 if (!it.IsFound()) return isolate->heap()->undefined_value();
368
369 Handle<Object> maybe_pair;
370 if (it.state() == LookupIterator::ACCESSOR) {
371 maybe_pair = it.GetAccessors();
372 }
373
374 // If the callback object is a fixed array then it contains JavaScript
375 // getter and/or setter.
376 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
377 Handle<FixedArray> details =
378 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
379 details->set(0, *value);
380 // TODO(verwaest): Get rid of this random way of handling interceptors.
381 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 ? PropertyDetails::Empty()
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383 : it.property_details();
384 details->set(1, d.AsSmi());
385 details->set(
386 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
387 if (has_js_accessors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100388 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 details->set(3, isolate->heap()->ToBoolean(has_caught));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100390 Handle<Object> getter =
391 AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
392 Handle<Object> setter =
393 AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
394 details->set(4, *getter);
395 details->set(5, *setter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400396 }
397
398 return *isolate->factory()->NewJSArrayWithElements(details);
399}
400
401
402RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
403 HandleScope scope(isolate);
404
405 DCHECK(args.length() == 2);
406
407 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
408 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
409
410 LookupIterator it(obj, name);
411 return *DebugGetProperty(&it);
412}
413
414
415// Return the property type calculated from the property details.
416// args[0]: smi with property details.
417RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
418 SealHandleScope shs(isolate);
419 DCHECK(args.length() == 1);
420 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
421 return Smi::FromInt(static_cast<int>(details.type()));
422}
423
424
425// Return the property attribute calculated from the property details.
426// args[0]: smi with property details.
427RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
428 SealHandleScope shs(isolate);
429 DCHECK(args.length() == 1);
430 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
431 return Smi::FromInt(static_cast<int>(details.attributes()));
432}
433
434
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400435RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
436 SealHandleScope shs(isolate);
437 DCHECK(args.length() == 1);
438 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
439 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
440 return isolate->heap()->true_value();
441}
442
443
444RUNTIME_FUNCTION(Runtime_GetFrameCount) {
445 HandleScope scope(isolate);
446 DCHECK(args.length() == 1);
447 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
448 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
449
450 // Count all frames which are relevant to debugging stack trace.
451 int n = 0;
452 StackFrame::Id id = isolate->debug()->break_frame_id();
453 if (id == StackFrame::NO_ID) {
454 // If there is no JavaScript stack frame count is 0.
455 return Smi::FromInt(0);
456 }
457
458 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
459 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
460 it.frame()->Summarize(&frames);
461 for (int i = frames.length() - 1; i >= 0; i--) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000462 // Omit functions from native and extension scripts.
463 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464 }
465 }
466 return Smi::FromInt(n);
467}
468
469
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470static const int kFrameDetailsFrameIdIndex = 0;
471static const int kFrameDetailsReceiverIndex = 1;
472static const int kFrameDetailsFunctionIndex = 2;
473static const int kFrameDetailsArgumentCountIndex = 3;
474static const int kFrameDetailsLocalCountIndex = 4;
475static const int kFrameDetailsSourcePositionIndex = 5;
476static const int kFrameDetailsConstructCallIndex = 6;
477static const int kFrameDetailsAtReturnIndex = 7;
478static const int kFrameDetailsFlagsIndex = 8;
479static const int kFrameDetailsFirstDynamicIndex = 9;
480
481
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400482// Return an array with frame details
483// args[0]: number: break id
484// args[1]: number: frame index
485//
486// The array returned contains the following information:
487// 0: Frame id
488// 1: Receiver
489// 2: Function
490// 3: Argument count
491// 4: Local count
492// 5: Source position
493// 6: Constructor call
494// 7: Is at return
495// 8: Flags
496// Arguments name, value
497// Locals name, value
498// Return value if any
499RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
500 HandleScope scope(isolate);
501 DCHECK(args.length() == 2);
502 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
503 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
504
505 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
506 Heap* heap = isolate->heap();
507
508 // Find the relevant frame with the requested index.
509 StackFrame::Id id = isolate->debug()->break_frame_id();
510 if (id == StackFrame::NO_ID) {
511 // If there are no JavaScript stack frames return undefined.
512 return heap->undefined_value();
513 }
514
515 JavaScriptFrameIterator it(isolate, id);
516 // Inlined frame index in optimized frame, starting from outer function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517 int inlined_jsframe_index =
518 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 if (inlined_jsframe_index == -1) return heap->undefined_value();
520
521 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
522 bool is_optimized = it.frame()->is_optimized();
523
524 // Traverse the saved contexts chain to find the active context for the
525 // selected frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 SaveContext* save =
527 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400528
529 // Get the frame id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
531 isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400532
533 // Find source position in unoptimized code.
534 int position = frame_inspector.GetSourcePosition();
535
536 // Check for constructor frame.
537 bool constructor = frame_inspector.IsConstructor();
538
539 // Get scope info and read from it for local variable information.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100540 Handle<JSFunction> function =
541 Handle<JSFunction>::cast(frame_inspector.GetFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400543 Handle<SharedFunctionInfo> shared(function->shared());
544 Handle<ScopeInfo> scope_info(shared->scope_info());
545 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
546
547 // Get the locals names and values into a temporary array.
548 int local_count = scope_info->LocalCount();
549 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
550 // Hide compiler-introduced temporary variables, whether on the stack or on
551 // the context.
Ben Murdochc5610432016-08-08 18:44:38 +0100552 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
553 local_count--;
554 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 }
556
557 Handle<FixedArray> locals =
558 isolate->factory()->NewFixedArray(local_count * 2);
559
560 // Fill in the values of the locals.
561 int local = 0;
562 int i = 0;
563 for (; i < scope_info->StackLocalCount(); ++i) {
564 // Use the value from the stack.
Ben Murdochc5610432016-08-08 18:44:38 +0100565 if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400566 locals->set(local * 2, scope_info->LocalName(i));
Ben Murdochda12d292016-06-02 14:46:10 +0100567 Handle<Object> value = frame_inspector.GetExpression(i);
568 // TODO(yangguo): We convert optimized out values to {undefined} when they
569 // are passed to the debugger. Eventually we should handle them somehow.
570 if (value->IsOptimizedOut()) value = isolate->factory()->undefined_value();
571 locals->set(local * 2 + 1, *value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572 local++;
573 }
574 if (local < local_count) {
575 // Get the context containing declarations.
576 Handle<Context> context(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100577 Handle<Context>::cast(frame_inspector.GetContext())->closure_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400578 for (; i < scope_info->LocalCount(); ++i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579 Handle<String> name(scope_info->LocalName(i));
Ben Murdochc5610432016-08-08 18:44:38 +0100580 if (ScopeInfo::VariableIsSynthetic(*name)) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400581 VariableMode mode;
582 InitializationFlag init_flag;
583 MaybeAssignedFlag maybe_assigned_flag;
584 locals->set(local * 2, *name);
585 int context_slot_index = ScopeInfo::ContextSlotIndex(
586 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
587 Object* value = context->get(context_slot_index);
588 locals->set(local * 2 + 1, value);
589 local++;
590 }
591 }
592
593 // Check whether this frame is positioned at return. If not top
594 // frame or if the frame is optimized it cannot be at a return.
595 bool at_return = false;
596 if (!is_optimized && index == 0) {
597 at_return = isolate->debug()->IsBreakAtReturn(it.frame());
598 }
599
600 // If positioned just before return find the value to be returned and add it
601 // to the frame information.
602 Handle<Object> return_value = isolate->factory()->undefined_value();
603 if (at_return) {
Ben Murdochda12d292016-06-02 14:46:10 +0100604 return_value = isolate->debug()->return_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400605 }
606
607 // Now advance to the arguments adapter frame (if any). It contains all
608 // the provided parameters whereas the function frame always have the number
609 // of arguments matching the functions parameters. The rest of the
610 // information (except for what is collected above) is the same.
611 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
612 it.AdvanceToArgumentsFrame();
613 frame_inspector.SetArgumentsFrame(it.frame());
614 }
615
616 // Find the number of arguments to fill. At least fill the number of
617 // parameters for the function and fill more if more parameters are provided.
618 int argument_count = scope_info->ParameterCount();
619 if (argument_count < frame_inspector.GetParametersCount()) {
620 argument_count = frame_inspector.GetParametersCount();
621 }
622
623 // Calculate the size of the result.
624 int details_size = kFrameDetailsFirstDynamicIndex +
625 2 * (argument_count + local_count) + (at_return ? 1 : 0);
626 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
627
628 // Add the frame id.
629 details->set(kFrameDetailsFrameIdIndex, *frame_id);
630
631 // Add the function (same as in function frame).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100632 details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400633
634 // Add the arguments count.
635 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
636
637 // Add the locals count
638 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
639
640 // Add the source position.
641 if (position != RelocInfo::kNoPosition) {
642 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
643 } else {
644 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
645 }
646
647 // Add the constructor information.
648 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
649
650 // Add the at return information.
651 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
652
653 // Add flags to indicate information on whether this frame is
654 // bit 0: invoked in the debugger context.
655 // bit 1: optimized frame.
656 // bit 2: inlined in optimized frame
657 int flags = 0;
658 if (*save->context() == *isolate->debug()->debug_context()) {
659 flags |= 1 << 0;
660 }
661 if (is_optimized) {
662 flags |= 1 << 1;
663 flags |= inlined_jsframe_index << 2;
664 }
665 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
666
667 // Fill the dynamic part.
668 int details_index = kFrameDetailsFirstDynamicIndex;
669
670 // Add arguments name and value.
671 for (int i = 0; i < argument_count; i++) {
672 // Name of the argument.
673 if (i < scope_info->ParameterCount()) {
674 details->set(details_index++, scope_info->ParameterName(i));
675 } else {
676 details->set(details_index++, heap->undefined_value());
677 }
678
679 // Parameter value.
680 if (i < frame_inspector.GetParametersCount()) {
681 // Get the value from the stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100682 details->set(details_index++, *(frame_inspector.GetParameter(i)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683 } else {
684 details->set(details_index++, heap->undefined_value());
685 }
686 }
687
688 // Add locals name and value from the temporary copy from the function frame.
689 for (int i = 0; i < local_count * 2; i++) {
690 details->set(details_index++, locals->get(i));
691 }
692
693 // Add the value being returned.
694 if (at_return) {
695 details->set(details_index++, *return_value);
696 }
697
698 // Add the receiver (same as in function frame).
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400699 Handle<Object> receiver(it.frame()->receiver(), isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 DCHECK(!function->shared()->IsBuiltin());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100701 DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400702 details->set(kFrameDetailsReceiverIndex, *receiver);
703
704 DCHECK_EQ(details_size, details_index);
705 return *isolate->factory()->NewJSArrayWithElements(details);
706}
707
708
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709RUNTIME_FUNCTION(Runtime_GetScopeCount) {
710 HandleScope scope(isolate);
711 DCHECK(args.length() == 2);
712 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
713 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
714
715 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
716
717 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400719 JavaScriptFrameIterator it(isolate, id);
720 JavaScriptFrame* frame = it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 FrameInspector frame_inspector(frame, 0, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722
723 // Count the visible scopes.
724 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000725 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726 n++;
727 }
728
729 return Smi::FromInt(n);
730}
731
732
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400733// Return an array with scope details
734// args[0]: number: break id
735// args[1]: number: frame index
736// args[2]: number: inlined frame index
737// args[3]: number: scope index
738//
739// The array returned contains the following information:
740// 0: Scope type
741// 1: Scope object
742RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
743 HandleScope scope(isolate);
744 DCHECK(args.length() == 4);
745 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
746 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
747
748 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
749 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
750 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
751
752 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000753 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400754 JavaScriptFrameIterator frame_it(isolate, id);
755 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400757
758 // Find the requested scope.
759 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760 ScopeIterator it(isolate, &frame_inspector);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400761 for (; !it.Done() && n < index; it.Next()) {
762 n++;
763 }
764 if (it.Done()) {
765 return isolate->heap()->undefined_value();
766 }
767 Handle<JSObject> details;
768 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400770 return *details;
771}
772
773
774// Return an array of scope details
775// args[0]: number: break id
776// args[1]: number: frame index
777// args[2]: number: inlined frame index
778// args[3]: boolean: ignore nested scopes
779//
780// The array returned contains arrays with the following information:
781// 0: Scope type
782// 1: Scope object
783RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
784 HandleScope scope(isolate);
785 DCHECK(args.length() == 3 || args.length() == 4);
786 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
787 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
788
789 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
790 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
791
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 ScopeIterator::Option option = ScopeIterator::DEFAULT;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400793 if (args.length() == 4) {
794 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400796 }
797
798 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400800 JavaScriptFrameIterator frame_it(isolate, id);
801 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400803
804 List<Handle<JSObject> > result(4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 ScopeIterator it(isolate, &frame_inspector, option);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400806 for (; !it.Done(); it.Next()) {
807 Handle<JSObject> details;
808 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810 result.Add(details);
811 }
812
813 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
814 for (int i = 0; i < result.length(); ++i) {
815 array->set(i, *result[i]);
816 }
817 return *isolate->factory()->NewJSArrayWithElements(array);
818}
819
820
821RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
822 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823 DCHECK_EQ(1, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400824
825 // Check arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400827
828 // Count the visible scopes.
829 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 if (function->IsJSFunction()) {
831 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
832 !it.Done(); it.Next()) {
833 n++;
834 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400835 }
836
837 return Smi::FromInt(n);
838}
839
840
841RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
842 HandleScope scope(isolate);
843 DCHECK(args.length() == 2);
844
845 // Check arguments.
846 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
847 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
848
849 // Find the requested scope.
850 int n = 0;
851 ScopeIterator it(isolate, fun);
852 for (; !it.Done() && n < index; it.Next()) {
853 n++;
854 }
855 if (it.Done()) {
856 return isolate->heap()->undefined_value();
857 }
858
859 Handle<JSObject> details;
860 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862 return *details;
863}
864
865
866static bool SetScopeVariableValue(ScopeIterator* it, int index,
867 Handle<String> variable_name,
868 Handle<Object> new_value) {
869 for (int n = 0; !it->Done() && n < index; it->Next()) {
870 n++;
871 }
872 if (it->Done()) {
873 return false;
874 }
875 return it->SetVariableValue(variable_name, new_value);
876}
877
878
879// Change variable value in closure or local scope
880// args[0]: number or JsFunction: break id or function
881// args[1]: number: frame index (when arg[0] is break id)
882// args[2]: number: inlined frame index (when arg[0] is break id)
883// args[3]: number: scope index
884// args[4]: string: variable name
885// args[5]: object: new value
886//
887// Return true if success and false otherwise
888RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
889 HandleScope scope(isolate);
890 DCHECK(args.length() == 6);
891
892 // Check arguments.
893 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
894 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
895 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
896
897 bool res;
898 if (args[0]->IsNumber()) {
899 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
900 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
901
902 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
903 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
904
905 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400907 JavaScriptFrameIterator frame_it(isolate, id);
908 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400910
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 ScopeIterator it(isolate, &frame_inspector);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400912 res = SetScopeVariableValue(&it, index, variable_name, new_value);
913 } else {
914 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
915 ScopeIterator it(isolate, fun);
916 res = SetScopeVariableValue(&it, index, variable_name, new_value);
917 }
918
919 return isolate->heap()->ToBoolean(res);
920}
921
922
923RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
924 HandleScope scope(isolate);
925 DCHECK(args.length() == 0);
926
927#ifdef DEBUG
928 // Print the scopes for the top frame.
929 StackFrameLocator locator(isolate);
930 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 FrameInspector frame_inspector(frame, 0, isolate);
932
933 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400934 it.DebugPrint();
935 }
936#endif
937 return isolate->heap()->undefined_value();
938}
939
940
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400941// Sets the disable break state
942// args[0]: disable break state
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400944 HandleScope scope(isolate);
945 DCHECK(args.length() == 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000946 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
947 isolate->debug()->set_break_points_active(active);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400948 return isolate->heap()->undefined_value();
949}
950
951
952static bool IsPositionAlignmentCodeCorrect(int alignment) {
953 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
954}
955
956
957RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
958 HandleScope scope(isolate);
959 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400961 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
962 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
963
964 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
965 return isolate->ThrowIllegalOperation();
966 }
967 BreakPositionAlignment alignment =
968 static_cast<BreakPositionAlignment>(statement_aligned_code);
969
970 Handle<SharedFunctionInfo> shared(fun->shared());
971 // Find the number of break points
972 Handle<Object> break_locations =
973 Debug::GetSourceBreakLocations(shared, alignment);
974 if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
975 // Return array as JS array
976 return *isolate->factory()->NewJSArrayWithElements(
977 Handle<FixedArray>::cast(break_locations));
978}
979
980
981// Set a break point in a function.
982// args[0]: function
983// args[1]: number: break source position (within the function source)
984// args[2]: number: break point object
985RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
986 HandleScope scope(isolate);
987 DCHECK(args.length() == 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
990 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
991 RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
992 source_position <= function->shared()->end_position());
993 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
994
995 // Set break point.
996 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
997 function, break_point_object_arg, &source_position));
998
999 return Smi::FromInt(source_position);
1000}
1001
1002
1003// Changes the state of a break point in a script and returns source position
1004// where break point was set. NOTE: Regarding performance see the NOTE for
1005// GetScriptFromScriptData.
1006// args[0]: script to set break point in
1007// args[1]: number: break source position (within the script source)
1008// args[2]: number, breakpoint position alignment
1009// args[3]: number: break point object
1010RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1011 HandleScope scope(isolate);
1012 DCHECK(args.length() == 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001014 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1015 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1016 RUNTIME_ASSERT(source_position >= 0);
1017 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1018 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1019
1020 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1021 return isolate->ThrowIllegalOperation();
1022 }
1023 BreakPositionAlignment alignment =
1024 static_cast<BreakPositionAlignment>(statement_aligned_code);
1025
1026 // Get the script from the script wrapper.
1027 RUNTIME_ASSERT(wrapper->value()->IsScript());
1028 Handle<Script> script(Script::cast(wrapper->value()));
1029
1030 // Set break point.
1031 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1032 &source_position, alignment)) {
1033 return isolate->heap()->undefined_value();
1034 }
1035
1036 return Smi::FromInt(source_position);
1037}
1038
1039
1040// Clear a break point
1041// args[0]: number: break point object
1042RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1043 HandleScope scope(isolate);
1044 DCHECK(args.length() == 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001046 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1047
1048 // Clear break point.
1049 isolate->debug()->ClearBreakPoint(break_point_object_arg);
1050
1051 return isolate->heap()->undefined_value();
1052}
1053
1054
1055// Change the state of break on exceptions.
1056// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1057// args[1]: Boolean indicating on/off.
1058RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1059 HandleScope scope(isolate);
1060 DCHECK(args.length() == 2);
1061 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1062 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1063
1064 // If the number doesn't match an enum value, the ChangeBreakOnException
1065 // function will default to affecting caught exceptions.
1066 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1067 // Update break point state.
1068 isolate->debug()->ChangeBreakOnException(type, enable);
1069 return isolate->heap()->undefined_value();
1070}
1071
1072
1073// Returns the state of break on exceptions
1074// args[0]: boolean indicating uncaught exceptions
1075RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1076 HandleScope scope(isolate);
1077 DCHECK(args.length() == 1);
1078 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1079
1080 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1081 bool result = isolate->debug()->IsBreakOnException(type);
1082 return Smi::FromInt(result);
1083}
1084
1085
1086// Prepare for stepping
1087// args[0]: break id for checking execution state
1088// args[1]: step action from the enumeration StepAction
1089// args[2]: number of times to perform the step, for step out it is the number
1090// of frames to step down.
1091RUNTIME_FUNCTION(Runtime_PrepareStep) {
1092 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001094 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1095 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1096
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097 if (!args[1]->IsNumber()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001098 return isolate->Throw(isolate->heap()->illegal_argument_string());
1099 }
1100
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001101 // Get the step action and check validity.
1102 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1103 if (step_action != StepIn && step_action != StepNext &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 step_action != StepOut && step_action != StepFrame) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105 return isolate->Throw(isolate->heap()->illegal_argument_string());
1106 }
1107
1108 // Clear all current stepping setup.
1109 isolate->debug()->ClearStepping();
1110
1111 // Prepare step.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001113 return isolate->heap()->undefined_value();
1114}
1115
1116
1117// Clear all stepping set by PrepareStep.
1118RUNTIME_FUNCTION(Runtime_ClearStepping) {
1119 HandleScope scope(isolate);
1120 DCHECK(args.length() == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001122 isolate->debug()->ClearStepping();
1123 return isolate->heap()->undefined_value();
1124}
1125
1126
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001127RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1128 HandleScope scope(isolate);
1129
1130 // Check the execution state and decode arguments frame and source to be
1131 // evaluated.
1132 DCHECK(args.length() == 6);
1133 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1134 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1135
1136 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1137 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1138 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1139 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143
1144 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1146 isolate, result,
1147 DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1148 disable_break, context_extension));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001149 return *result;
1150}
1151
1152
1153RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1154 HandleScope scope(isolate);
1155
1156 // Check the execution state and decode arguments frame and source to be
1157 // evaluated.
1158 DCHECK(args.length() == 4);
1159 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1160 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1161
1162 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1163 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001165
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001166 Handle<Object> result;
1167 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 isolate, result,
1169 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001170 return *result;
1171}
1172
1173
1174RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1175 HandleScope scope(isolate);
1176 DCHECK(args.length() == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001177 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 Handle<FixedArray> instances;
1180 {
1181 DebugScope debug_scope(isolate->debug());
1182 if (debug_scope.failed()) {
1183 DCHECK(isolate->has_pending_exception());
1184 return isolate->heap()->exception();
1185 }
1186 // Fill the script objects.
1187 instances = isolate->debug()->GetLoadedScripts();
1188 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001189
1190 // Convert the script objects to proper JS objects.
1191 for (int i = 0; i < instances->length(); i++) {
1192 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1193 // Get the script wrapper in a local handle before calling GetScriptWrapper,
1194 // because using
1195 // instances->set(i, *GetScriptWrapper(script))
1196 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1197 // already have dereferenced the instances handle.
1198 Handle<JSObject> wrapper = Script::GetWrapper(script);
1199 instances->set(i, *wrapper);
1200 }
1201
1202 // Return result as a JS array.
Ben Murdochc5610432016-08-08 18:44:38 +01001203 return *isolate->factory()->NewJSArrayWithElements(instances);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204}
1205
Ben Murdoch097c5b22016-05-18 11:27:45 +01001206static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1207 JSObject* object,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 Object* proto) {
1209 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
1210 while (true) {
1211 iter.AdvanceIgnoringProxies();
1212 if (iter.IsAtEnd()) return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001213 if (iter.GetCurrent() == proto) return true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001214 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001215}
1216
1217
1218// Scan the heap for objects with direct references to an object
1219// args[0]: the object to find references to
1220// args[1]: constructor function for instances to exclude (Mirror)
1221// args[2]: the the maximum number of objects to return
1222RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1223 HandleScope scope(isolate);
1224 DCHECK(args.length() == 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001225 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1227 RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001228 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1229 RUNTIME_ASSERT(max_references >= 0);
1230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001231 List<Handle<JSObject> > instances;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001232 Heap* heap = isolate->heap();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001233 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1235 // Get the constructor function for context extension and arguments array.
1236 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1237 HeapObject* heap_obj;
1238 while ((heap_obj = iterator.next())) {
1239 if (!heap_obj->IsJSObject()) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001240 JSObject* obj = JSObject::cast(heap_obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 if (obj->IsJSContextExtensionObject()) continue;
1242 if (obj->map()->GetConstructor() == arguments_fun) continue;
1243 if (!obj->ReferencesObject(*target)) continue;
1244 // Check filter if supplied. This is normally used to avoid
1245 // references from mirror objects.
1246 if (!filter->IsUndefined() &&
1247 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1248 continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001249 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 if (obj->IsJSGlobalObject()) {
1251 obj = JSGlobalObject::cast(obj)->global_proxy();
1252 }
1253 instances.Add(Handle<JSObject>(obj));
1254 if (instances.length() == max_references) break;
1255 }
1256 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1257 while (iterator.next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258 }
1259 }
1260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 Handle<FixedArray> result;
1262 if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1263 // Check for circular reference only. This can happen when the object is
1264 // only referenced from mirrors and has a circular reference in which case
1265 // the object is not really alive and would have been garbage collected if
1266 // not referenced from the mirror.
1267 result = isolate->factory()->empty_fixed_array();
1268 } else {
1269 result = isolate->factory()->NewFixedArray(instances.length());
1270 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1271 }
1272 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001273}
1274
1275
1276// Scan the heap for objects constructed by a specific function.
1277// args[0]: the constructor to find instances of
1278// args[1]: the the maximum number of objects to return
1279RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1280 HandleScope scope(isolate);
1281 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001282 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1283 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
1284 RUNTIME_ASSERT(max_references >= 0);
1285
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 List<Handle<JSObject> > instances;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001287 Heap* heap = isolate->heap();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001288 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1290 HeapObject* heap_obj;
1291 while ((heap_obj = iterator.next())) {
1292 if (!heap_obj->IsJSObject()) continue;
1293 JSObject* obj = JSObject::cast(heap_obj);
1294 if (obj->map()->GetConstructor() != *constructor) continue;
1295 instances.Add(Handle<JSObject>(obj));
1296 if (instances.length() == max_references) break;
1297 }
1298 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1299 while (iterator.next()) {
1300 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301 }
1302
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303 Handle<FixedArray> result =
1304 isolate->factory()->NewFixedArray(instances.length());
1305 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1306 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001307}
1308
1309
1310// Find the effective prototype object as returned by __proto__.
1311// args[0]: the object to find the prototype for.
1312RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1313 HandleScope shs(isolate);
1314 DCHECK(args.length() == 1);
1315 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 Handle<Object> prototype;
1317 // TODO(1543): Come up with a solution for clients to handle potential errors
1318 // thrown by an intermediate proxy.
1319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001320 JSReceiver::GetPrototype(isolate, obj));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 return *prototype;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001322}
1323
1324
1325// Patches script source (should be called upon BeforeCompile event).
1326RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1327 HandleScope scope(isolate);
1328 DCHECK(args.length() == 2);
1329
1330 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1331 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1332
1333 RUNTIME_ASSERT(script_wrapper->value()->IsScript());
1334 Handle<Script> script(Script::cast(script_wrapper->value()));
1335
1336 int compilation_state = script->compilation_state();
1337 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
1338 script->set_source(*source);
1339
1340 return isolate->heap()->undefined_value();
1341}
1342
1343
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001344RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1345 SealHandleScope shs(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 DCHECK_EQ(1, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001348 CONVERT_ARG_CHECKED(Object, f, 0);
1349 if (f->IsJSFunction()) {
1350 return JSFunction::cast(f)->shared()->inferred_name();
1351 }
1352 return isolate->heap()->empty_string();
1353}
1354
1355
1356RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1357 HandleScope scope(isolate);
1358 DCHECK_EQ(1, args.length());
1359
1360 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1361
Ben Murdochc5610432016-08-08 18:44:38 +01001362 Handle<Object> name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 if (function->IsJSBoundFunction()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001364 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1365 isolate, name, JSBoundFunction::GetName(
1366 isolate, Handle<JSBoundFunction>::cast(function)));
1367 } else {
1368 name = JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001370 return *name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001371}
1372
1373
1374// A testing entry. Returns statement position which is the closest to
1375// source_position.
1376RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
1377 HandleScope scope(isolate);
1378 CHECK(isolate->debug()->live_edit_enabled());
1379 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001381 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1382 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1383
1384 Handle<Code> code(function->code(), isolate);
1385
1386 if (code->kind() != Code::FUNCTION &&
1387 code->kind() != Code::OPTIMIZED_FUNCTION) {
1388 return isolate->heap()->undefined_value();
1389 }
1390
1391 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
1392 int closest_pc = 0;
1393 int distance = kMaxInt;
1394 while (!it.done()) {
1395 int statement_position = static_cast<int>(it.rinfo()->data());
1396 // Check if this break point is closer that what was previously found.
1397 if (source_position <= statement_position &&
1398 statement_position - source_position < distance) {
1399 closest_pc =
1400 static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1401 distance = statement_position - source_position;
1402 // Check whether we can't get any closer.
1403 if (distance == 0) break;
1404 }
1405 it.next();
1406 }
1407
1408 return Smi::FromInt(closest_pc);
1409}
1410
1411
1412// Calls specified function with or without entering the debugger.
1413// This is used in unit tests to run code as if debugger is entered or simply
1414// to have a stack with C++ frame in the middle.
1415RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1416 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001417 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001418 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420 DebugScope debug_scope(isolate->debug());
1421 if (debug_scope.failed()) {
1422 DCHECK(isolate->has_pending_exception());
1423 return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001424 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001426 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001427 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1428 isolate, result,
1429 Execution::Call(isolate, function, handle(function->global_proxy()), 0,
1430 NULL));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001431 return *result;
1432}
1433
1434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1436 HandleScope scope(isolate);
1437 DCHECK(args.length() == 0);
1438 Handle<Context> context;
1439 {
1440 DebugScope debug_scope(isolate->debug());
1441 if (debug_scope.failed()) {
1442 DCHECK(isolate->has_pending_exception());
1443 return isolate->heap()->exception();
1444 }
1445 context = isolate->debug()->GetDebugContext();
1446 }
1447 if (context.is_null()) return isolate->heap()->undefined_value();
1448 context->set_security_token(isolate->native_context()->security_token());
1449 return context->global_proxy();
1450}
1451
1452
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001453// Performs a GC.
1454// Presently, it only does a full GC.
1455RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1456 SealHandleScope shs(isolate);
1457 DCHECK(args.length() == 1);
1458 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
1459 return isolate->heap()->undefined_value();
1460}
1461
1462
1463// Gets the current heap usage.
1464RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1465 SealHandleScope shs(isolate);
1466 DCHECK(args.length() == 0);
1467 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1468 if (!Smi::IsValid(usage)) {
1469 return *isolate->factory()->NewNumberFromInt(usage);
1470 }
1471 return Smi::FromInt(usage);
1472}
1473
1474
1475// Finds the script object from the script data. NOTE: This operation uses
1476// heap traversal to find the function generated for the source position
1477// for the requested break point. For lazily compiled functions several heap
1478// traversals might be required rendering this operation as a rather slow
1479// operation. However for setting break points which is normally done through
1480// some kind of user interaction the performance is not crucial.
1481RUNTIME_FUNCTION(Runtime_GetScript) {
1482 HandleScope scope(isolate);
1483 DCHECK(args.length() == 1);
1484 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1485
1486 Handle<Script> found;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001487 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001488 Script::Iterator iterator(isolate);
1489 Script* script = NULL;
1490 while ((script = iterator.Next()) != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001491 if (!script->name()->IsString()) continue;
1492 String* name = String::cast(script->name());
1493 if (name->Equals(*script_name)) {
1494 found = Handle<Script>(script, isolate);
1495 break;
1496 }
1497 }
1498 }
1499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500 if (found.is_null()) return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001501 return *Script::GetWrapper(found);
1502}
1503
1504
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001505// Set one shot breakpoints for the callback function that is passed to a
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506// built-in function such as Array.forEach to enable stepping into the callback,
1507// if we are indeed stepping and the callback is subject to debugging.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001508RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001509 HandleScope scope(isolate);
Ben Murdochc5610432016-08-08 18:44:38 +01001510 DCHECK_EQ(1, args.length());
1511 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 isolate->debug()->PrepareStepIn(fun);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001513 return isolate->heap()->undefined_value();
1514}
1515
1516
1517RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001519 HandleScope scope(isolate);
1520 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001521 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
1522 isolate->PushPromise(promise, function);
1523 // If we are in step-in mode, flood the handler.
1524 isolate->debug()->EnableStepIn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001525 return isolate->heap()->undefined_value();
1526}
1527
1528
1529RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1530 DCHECK(args.length() == 0);
1531 SealHandleScope shs(isolate);
1532 isolate->PopPromise();
1533 return isolate->heap()->undefined_value();
1534}
1535
1536
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001537RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1538 DCHECK(args.length() == 1);
1539 HandleScope scope(isolate);
1540 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1541 isolate->debug()->OnAsyncTaskEvent(data);
1542 return isolate->heap()->undefined_value();
1543}
1544
1545
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546RUNTIME_FUNCTION(Runtime_DebugIsActive) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001547 SealHandleScope shs(isolate);
1548 return Smi::FromInt(isolate->debug()->is_active());
1549}
1550
1551
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001553 UNIMPLEMENTED();
1554 return NULL;
1555}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556} // namespace internal
1557} // namespace v8