blob: ad8375a8d48225799dc3a6c23cbbd53c947c2a33 [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
45 // Return the handler from the original bytecode array.
46 DCHECK(it.frame()->is_interpreted());
47 InterpretedFrame* interpreted_frame =
48 reinterpret_cast<InterpretedFrame*>(it.frame());
49 SharedFunctionInfo* shared = interpreted_frame->function()->shared();
50 BytecodeArray* bytecode_array = shared->bytecode_array();
51 int bytecode_offset = interpreted_frame->GetBytecodeOffset();
52 interpreter::Bytecode bytecode =
53 interpreter::Bytecodes::FromByte(bytecode_array->get(bytecode_offset));
54 return isolate->interpreter()->GetBytecodeHandler(
55 bytecode, interpreter::OperandScale::kSingle);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056}
57
58
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
60 SealHandleScope shs(isolate);
61 DCHECK(args.length() == 0);
62 if (isolate->debug()->break_points_active()) {
63 isolate->debug()->HandleDebugBreak();
64 }
65 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040066}
67
68
69// Adds a JavaScript function as a debug event listener.
70// args[0]: debug event listener function to set or null or undefined for
71// clearing the event listener function
72// args[1]: object supplied during callback
73RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
74 SealHandleScope shs(isolate);
75 DCHECK(args.length() == 2);
76 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
77 args[0]->IsNull());
78 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
79 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
80 isolate->debug()->SetEventListener(callback, data);
81
82 return isolate->heap()->undefined_value();
83}
84
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040087 SealHandleScope shs(isolate);
88 DCHECK(args.length() == 0);
89 isolate->stack_guard()->RequestDebugBreak();
90 return isolate->heap()->undefined_value();
91}
92
93
94static Handle<Object> DebugGetProperty(LookupIterator* it,
95 bool* has_caught = NULL) {
96 for (; it->IsFound(); it->Next()) {
97 switch (it->state()) {
98 case LookupIterator::NOT_FOUND:
99 case LookupIterator::TRANSITION:
100 UNREACHABLE();
101 case LookupIterator::ACCESS_CHECK:
102 // Ignore access checks.
103 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105 case LookupIterator::INTERCEPTOR:
106 case LookupIterator::JSPROXY:
107 return it->isolate()->factory()->undefined_value();
108 case LookupIterator::ACCESSOR: {
109 Handle<Object> accessors = it->GetAccessors();
110 if (!accessors->IsAccessorInfo()) {
111 return it->isolate()->factory()->undefined_value();
112 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 MaybeHandle<Object> maybe_result =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100114 JSObject::GetPropertyWithAccessor(it);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115 Handle<Object> result;
116 if (!maybe_result.ToHandle(&result)) {
117 result = handle(it->isolate()->pending_exception(), it->isolate());
118 it->isolate()->clear_pending_exception();
119 if (has_caught != NULL) *has_caught = true;
120 }
121 return result;
122 }
123
124 case LookupIterator::DATA:
125 return it->GetDataValue();
126 }
127 }
128
129 return it->isolate()->factory()->undefined_value();
130}
131
132
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133static Handle<Object> DebugGetProperty(Handle<Object> object,
134 Handle<Name> name) {
135 LookupIterator it(object, name);
136 return DebugGetProperty(&it);
137}
138
139
140template <class IteratorType>
141static MaybeHandle<JSArray> GetIteratorInternalProperties(
142 Isolate* isolate, Handle<IteratorType> object) {
143 Factory* factory = isolate->factory();
144 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
145 RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
146 const char* kind = NULL;
147 switch (Smi::cast(iterator->kind())->value()) {
148 case IteratorType::kKindKeys:
149 kind = "keys";
150 break;
151 case IteratorType::kKindValues:
152 kind = "values";
153 break;
154 case IteratorType::kKindEntries:
155 kind = "entries";
156 break;
157 default:
158 RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
159 }
160
161 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
162 Handle<String> has_more =
163 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
164 result->set(0, *has_more);
165 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
166
167 Handle<String> index =
168 factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
169 result->set(2, *index);
170 result->set(3, iterator->index());
171
172 Handle<String> iterator_kind =
173 factory->NewStringFromAsciiChecked("[[IteratorKind]]");
174 result->set(4, *iterator_kind);
175 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
176 result->set(5, *kind_str);
177 return factory->NewJSArrayWithElements(result);
178}
179
180
181MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
182 Handle<Object> object) {
183 Factory* factory = isolate->factory();
184 if (object->IsJSBoundFunction()) {
185 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
186
187 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
188 Handle<String> target =
189 factory->NewStringFromAsciiChecked("[[TargetFunction]]");
190 result->set(0, *target);
191 result->set(1, function->bound_target_function());
192
193 Handle<String> bound_this =
194 factory->NewStringFromAsciiChecked("[[BoundThis]]");
195 result->set(2, *bound_this);
196 result->set(3, function->bound_this());
197
198 Handle<String> bound_args =
199 factory->NewStringFromAsciiChecked("[[BoundArgs]]");
200 result->set(4, *bound_args);
201 Handle<FixedArray> bound_arguments =
202 factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
203 Handle<JSArray> arguments_array =
204 factory->NewJSArrayWithElements(bound_arguments);
205 result->set(5, *arguments_array);
206 return factory->NewJSArrayWithElements(result);
207 } else if (object->IsJSMapIterator()) {
208 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
209 return GetIteratorInternalProperties(isolate, iterator);
210 } else if (object->IsJSSetIterator()) {
211 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
212 return GetIteratorInternalProperties(isolate, iterator);
213 } else if (object->IsJSGeneratorObject()) {
214 Handle<JSGeneratorObject> generator =
215 Handle<JSGeneratorObject>::cast(object);
216
217 const char* status = "suspended";
218 if (generator->is_closed()) {
219 status = "closed";
220 } else if (generator->is_executing()) {
221 status = "running";
222 } else {
223 DCHECK(generator->is_suspended());
224 }
225
226 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
227 Handle<String> generator_status =
228 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
229 result->set(0, *generator_status);
230 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
231 result->set(1, *status_str);
232
233 Handle<String> function =
234 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
235 result->set(2, *function);
236 result->set(3, generator->function());
237
238 Handle<String> receiver =
239 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
240 result->set(4, *receiver);
241 result->set(5, generator->receiver());
242 return factory->NewJSArrayWithElements(result);
243 } else if (Object::IsPromise(object)) {
244 Handle<JSObject> promise = Handle<JSObject>::cast(object);
245
246 Handle<Object> status_obj =
247 DebugGetProperty(promise, isolate->factory()->promise_status_symbol());
248 RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
249 const char* status = "rejected";
250 int status_val = Handle<Smi>::cast(status_obj)->value();
251 switch (status_val) {
252 case +1:
253 status = "resolved";
254 break;
255 case 0:
256 status = "pending";
257 break;
258 default:
259 DCHECK_EQ(-1, status_val);
260 }
261
262 Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
263 Handle<String> promise_status =
264 factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
265 result->set(0, *promise_status);
266 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
267 result->set(1, *status_str);
268
269 Handle<Object> value_obj =
270 DebugGetProperty(promise, isolate->factory()->promise_value_symbol());
271 Handle<String> promise_value =
272 factory->NewStringFromAsciiChecked("[[PromiseValue]]");
273 result->set(2, *promise_value);
274 result->set(3, *value_obj);
275 return factory->NewJSArrayWithElements(result);
276 } else if (object->IsJSValue()) {
277 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
278
279 Handle<FixedArray> result = factory->NewFixedArray(2);
280 Handle<String> primitive_value =
281 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
282 result->set(0, *primitive_value);
283 result->set(1, js_value->value());
284 return factory->NewJSArrayWithElements(result);
285 }
286 return factory->NewJSArray(0);
287}
288
289
290RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
291 HandleScope scope(isolate);
292 DCHECK(args.length() == 1);
293 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
294 Handle<JSArray> result;
295 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
296 isolate, result, Runtime::GetInternalProperties(isolate, obj));
297 return *result;
298}
299
300
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400301// Get debugger related details for an object property, in the following format:
302// 0: Property value
303// 1: Property details
304// 2: Property value is exception
305// 3: Getter function if defined
306// 4: Setter function if defined
307// Items 2-4 are only filled if the property has either a getter or a setter.
308RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
309 HandleScope scope(isolate);
310
311 DCHECK(args.length() == 2);
312
313 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
314 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
315
316 // Make sure to set the current context to the context before the debugger was
317 // entered (if the debugger is entered). The reason for switching context here
318 // is that for some property lookups (accessors and interceptors) callbacks
319 // into the embedding application can occour, and the embedding application
320 // could have the assumption that its own native context is the current
321 // context and not some internal debugger context.
322 SaveContext save(isolate);
323 if (isolate->debug()->in_debug_scope()) {
324 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
325 }
326
327 // Check if the name is trivially convertible to an index and get the element
328 // if so.
329 uint32_t index;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
331 // this special case.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332 if (name->AsArrayIndex(&index)) {
333 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
334 Handle<Object> element_or_char;
Ben Murdochda12d292016-06-02 14:46:10 +0100335 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
336 isolate, element_or_char, JSReceiver::GetElement(isolate, obj, index));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 details->set(0, *element_or_char);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 details->set(1, PropertyDetails::Empty().AsSmi());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400339 return *isolate->factory()->NewJSArrayWithElements(details);
340 }
341
342 LookupIterator it(obj, name, LookupIterator::HIDDEN);
343 bool has_caught = false;
344 Handle<Object> value = DebugGetProperty(&it, &has_caught);
345 if (!it.IsFound()) return isolate->heap()->undefined_value();
346
347 Handle<Object> maybe_pair;
348 if (it.state() == LookupIterator::ACCESSOR) {
349 maybe_pair = it.GetAccessors();
350 }
351
352 // If the callback object is a fixed array then it contains JavaScript
353 // getter and/or setter.
354 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
355 Handle<FixedArray> details =
356 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
357 details->set(0, *value);
358 // TODO(verwaest): Get rid of this random way of handling interceptors.
359 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 ? PropertyDetails::Empty()
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 : it.property_details();
362 details->set(1, d.AsSmi());
363 details->set(
364 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
365 if (has_js_accessors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_pair);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400367 details->set(3, isolate->heap()->ToBoolean(has_caught));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100368 Handle<Object> getter =
369 AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
370 Handle<Object> setter =
371 AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
372 details->set(4, *getter);
373 details->set(5, *setter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400374 }
375
376 return *isolate->factory()->NewJSArrayWithElements(details);
377}
378
379
380RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
381 HandleScope scope(isolate);
382
383 DCHECK(args.length() == 2);
384
385 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
386 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
387
388 LookupIterator it(obj, name);
389 return *DebugGetProperty(&it);
390}
391
392
393// Return the property type calculated from the property details.
394// args[0]: smi with property details.
395RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
396 SealHandleScope shs(isolate);
397 DCHECK(args.length() == 1);
398 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
399 return Smi::FromInt(static_cast<int>(details.type()));
400}
401
402
403// Return the property attribute calculated from the property details.
404// args[0]: smi with property details.
405RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
406 SealHandleScope shs(isolate);
407 DCHECK(args.length() == 1);
408 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
409 return Smi::FromInt(static_cast<int>(details.attributes()));
410}
411
412
413// Return the property insertion index calculated from the property details.
414// args[0]: smi with property details.
415RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
416 SealHandleScope shs(isolate);
417 DCHECK(args.length() == 1);
418 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
419 // TODO(verwaest): Works only for dictionary mode holders.
420 return Smi::FromInt(details.dictionary_index());
421}
422
423
424// Return property value from named interceptor.
425// args[0]: object
426// args[1]: property name
427RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
428 HandleScope scope(isolate);
429 DCHECK(args.length() == 2);
430 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
431 RUNTIME_ASSERT(obj->HasNamedInterceptor());
432 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
433
434 Handle<Object> result;
435 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
436 JSObject::GetProperty(obj, name));
437 return *result;
438}
439
440
441// Return element value from indexed interceptor.
442// args[0]: object
443// args[1]: index
444RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
445 HandleScope scope(isolate);
446 DCHECK(args.length() == 2);
447 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
448 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
449 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
450 Handle<Object> result;
Ben Murdochda12d292016-06-02 14:46:10 +0100451 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
452 isolate, result, JSReceiver::GetElement(isolate, obj, index));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 return *result;
454}
455
456
457RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
458 SealHandleScope shs(isolate);
459 DCHECK(args.length() == 1);
460 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
461 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
462 return isolate->heap()->true_value();
463}
464
465
466RUNTIME_FUNCTION(Runtime_GetFrameCount) {
467 HandleScope scope(isolate);
468 DCHECK(args.length() == 1);
469 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
470 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
471
472 // Count all frames which are relevant to debugging stack trace.
473 int n = 0;
474 StackFrame::Id id = isolate->debug()->break_frame_id();
475 if (id == StackFrame::NO_ID) {
476 // If there is no JavaScript stack frame count is 0.
477 return Smi::FromInt(0);
478 }
479
480 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
481 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
482 it.frame()->Summarize(&frames);
483 for (int i = frames.length() - 1; i >= 0; i--) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 // Omit functions from native and extension scripts.
485 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400486 }
487 }
488 return Smi::FromInt(n);
489}
490
491
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400492static const int kFrameDetailsFrameIdIndex = 0;
493static const int kFrameDetailsReceiverIndex = 1;
494static const int kFrameDetailsFunctionIndex = 2;
495static const int kFrameDetailsArgumentCountIndex = 3;
496static const int kFrameDetailsLocalCountIndex = 4;
497static const int kFrameDetailsSourcePositionIndex = 5;
498static const int kFrameDetailsConstructCallIndex = 6;
499static const int kFrameDetailsAtReturnIndex = 7;
500static const int kFrameDetailsFlagsIndex = 8;
501static const int kFrameDetailsFirstDynamicIndex = 9;
502
503
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504// Return an array with frame details
505// args[0]: number: break id
506// args[1]: number: frame index
507//
508// The array returned contains the following information:
509// 0: Frame id
510// 1: Receiver
511// 2: Function
512// 3: Argument count
513// 4: Local count
514// 5: Source position
515// 6: Constructor call
516// 7: Is at return
517// 8: Flags
518// Arguments name, value
519// Locals name, value
520// Return value if any
521RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
522 HandleScope scope(isolate);
523 DCHECK(args.length() == 2);
524 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
525 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
526
527 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
528 Heap* heap = isolate->heap();
529
530 // Find the relevant frame with the requested index.
531 StackFrame::Id id = isolate->debug()->break_frame_id();
532 if (id == StackFrame::NO_ID) {
533 // If there are no JavaScript stack frames return undefined.
534 return heap->undefined_value();
535 }
536
537 JavaScriptFrameIterator it(isolate, id);
538 // Inlined frame index in optimized frame, starting from outer function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 int inlined_jsframe_index =
540 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400541 if (inlined_jsframe_index == -1) return heap->undefined_value();
542
543 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
544 bool is_optimized = it.frame()->is_optimized();
545
546 // Traverse the saved contexts chain to find the active context for the
547 // selected frame.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 SaveContext* save =
549 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400550
551 // Get the frame id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
553 isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400554
555 // Find source position in unoptimized code.
556 int position = frame_inspector.GetSourcePosition();
557
558 // Check for constructor frame.
559 bool constructor = frame_inspector.IsConstructor();
560
561 // Get scope info and read from it for local variable information.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100562 Handle<JSFunction> function =
563 Handle<JSFunction>::cast(frame_inspector.GetFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400565 Handle<SharedFunctionInfo> shared(function->shared());
566 Handle<ScopeInfo> scope_info(shared->scope_info());
567 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
568
569 // Get the locals names and values into a temporary array.
570 int local_count = scope_info->LocalCount();
571 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
572 // Hide compiler-introduced temporary variables, whether on the stack or on
573 // the context.
574 if (scope_info->LocalIsSynthetic(slot)) local_count--;
575 }
576
577 Handle<FixedArray> locals =
578 isolate->factory()->NewFixedArray(local_count * 2);
579
580 // Fill in the values of the locals.
581 int local = 0;
582 int i = 0;
583 for (; i < scope_info->StackLocalCount(); ++i) {
584 // Use the value from the stack.
585 if (scope_info->LocalIsSynthetic(i)) continue;
586 locals->set(local * 2, scope_info->LocalName(i));
Ben Murdochda12d292016-06-02 14:46:10 +0100587 Handle<Object> value = frame_inspector.GetExpression(i);
588 // TODO(yangguo): We convert optimized out values to {undefined} when they
589 // are passed to the debugger. Eventually we should handle them somehow.
590 if (value->IsOptimizedOut()) value = isolate->factory()->undefined_value();
591 locals->set(local * 2 + 1, *value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592 local++;
593 }
594 if (local < local_count) {
595 // Get the context containing declarations.
596 Handle<Context> context(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100597 Handle<Context>::cast(frame_inspector.GetContext())->closure_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400598 for (; i < scope_info->LocalCount(); ++i) {
599 if (scope_info->LocalIsSynthetic(i)) continue;
600 Handle<String> name(scope_info->LocalName(i));
601 VariableMode mode;
602 InitializationFlag init_flag;
603 MaybeAssignedFlag maybe_assigned_flag;
604 locals->set(local * 2, *name);
605 int context_slot_index = ScopeInfo::ContextSlotIndex(
606 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
607 Object* value = context->get(context_slot_index);
608 locals->set(local * 2 + 1, value);
609 local++;
610 }
611 }
612
613 // Check whether this frame is positioned at return. If not top
614 // frame or if the frame is optimized it cannot be at a return.
615 bool at_return = false;
616 if (!is_optimized && index == 0) {
617 at_return = isolate->debug()->IsBreakAtReturn(it.frame());
618 }
619
620 // If positioned just before return find the value to be returned and add it
621 // to the frame information.
622 Handle<Object> return_value = isolate->factory()->undefined_value();
623 if (at_return) {
Ben Murdochda12d292016-06-02 14:46:10 +0100624 return_value = isolate->debug()->return_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400625 }
626
627 // Now advance to the arguments adapter frame (if any). It contains all
628 // the provided parameters whereas the function frame always have the number
629 // of arguments matching the functions parameters. The rest of the
630 // information (except for what is collected above) is the same.
631 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
632 it.AdvanceToArgumentsFrame();
633 frame_inspector.SetArgumentsFrame(it.frame());
634 }
635
636 // Find the number of arguments to fill. At least fill the number of
637 // parameters for the function and fill more if more parameters are provided.
638 int argument_count = scope_info->ParameterCount();
639 if (argument_count < frame_inspector.GetParametersCount()) {
640 argument_count = frame_inspector.GetParametersCount();
641 }
642
643 // Calculate the size of the result.
644 int details_size = kFrameDetailsFirstDynamicIndex +
645 2 * (argument_count + local_count) + (at_return ? 1 : 0);
646 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
647
648 // Add the frame id.
649 details->set(kFrameDetailsFrameIdIndex, *frame_id);
650
651 // Add the function (same as in function frame).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100652 details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400653
654 // Add the arguments count.
655 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
656
657 // Add the locals count
658 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
659
660 // Add the source position.
661 if (position != RelocInfo::kNoPosition) {
662 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
663 } else {
664 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
665 }
666
667 // Add the constructor information.
668 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
669
670 // Add the at return information.
671 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
672
673 // Add flags to indicate information on whether this frame is
674 // bit 0: invoked in the debugger context.
675 // bit 1: optimized frame.
676 // bit 2: inlined in optimized frame
677 int flags = 0;
678 if (*save->context() == *isolate->debug()->debug_context()) {
679 flags |= 1 << 0;
680 }
681 if (is_optimized) {
682 flags |= 1 << 1;
683 flags |= inlined_jsframe_index << 2;
684 }
685 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
686
687 // Fill the dynamic part.
688 int details_index = kFrameDetailsFirstDynamicIndex;
689
690 // Add arguments name and value.
691 for (int i = 0; i < argument_count; i++) {
692 // Name of the argument.
693 if (i < scope_info->ParameterCount()) {
694 details->set(details_index++, scope_info->ParameterName(i));
695 } else {
696 details->set(details_index++, heap->undefined_value());
697 }
698
699 // Parameter value.
700 if (i < frame_inspector.GetParametersCount()) {
701 // Get the value from the stack.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100702 details->set(details_index++, *(frame_inspector.GetParameter(i)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 } else {
704 details->set(details_index++, heap->undefined_value());
705 }
706 }
707
708 // Add locals name and value from the temporary copy from the function frame.
709 for (int i = 0; i < local_count * 2; i++) {
710 details->set(details_index++, locals->get(i));
711 }
712
713 // Add the value being returned.
714 if (at_return) {
715 details->set(details_index++, *return_value);
716 }
717
718 // Add the receiver (same as in function frame).
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400719 Handle<Object> receiver(it.frame()->receiver(), isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 DCHECK(!function->shared()->IsBuiltin());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100721 DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 details->set(kFrameDetailsReceiverIndex, *receiver);
723
724 DCHECK_EQ(details_size, details_index);
725 return *isolate->factory()->NewJSArrayWithElements(details);
726}
727
728
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400729RUNTIME_FUNCTION(Runtime_GetScopeCount) {
730 HandleScope scope(isolate);
731 DCHECK(args.length() == 2);
732 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
733 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
734
735 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
736
737 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400739 JavaScriptFrameIterator it(isolate, id);
740 JavaScriptFrame* frame = it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 FrameInspector frame_inspector(frame, 0, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400742
743 // Count the visible scopes.
744 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746 n++;
747 }
748
749 return Smi::FromInt(n);
750}
751
752
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400753// Return an array with scope details
754// args[0]: number: break id
755// args[1]: number: frame index
756// args[2]: number: inlined frame index
757// args[3]: number: scope index
758//
759// The array returned contains the following information:
760// 0: Scope type
761// 1: Scope object
762RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
763 HandleScope scope(isolate);
764 DCHECK(args.length() == 4);
765 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
766 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
767
768 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
769 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
770 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
771
772 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400774 JavaScriptFrameIterator frame_it(isolate, id);
775 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400777
778 // Find the requested scope.
779 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 ScopeIterator it(isolate, &frame_inspector);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400781 for (; !it.Done() && n < index; it.Next()) {
782 n++;
783 }
784 if (it.Done()) {
785 return isolate->heap()->undefined_value();
786 }
787 Handle<JSObject> details;
788 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400790 return *details;
791}
792
793
794// Return an array of scope details
795// args[0]: number: break id
796// args[1]: number: frame index
797// args[2]: number: inlined frame index
798// args[3]: boolean: ignore nested scopes
799//
800// The array returned contains arrays with the following information:
801// 0: Scope type
802// 1: Scope object
803RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
804 HandleScope scope(isolate);
805 DCHECK(args.length() == 3 || args.length() == 4);
806 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
807 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
808
809 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
810 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
811
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812 ScopeIterator::Option option = ScopeIterator::DEFAULT;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400813 if (args.length() == 4) {
814 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400816 }
817
818 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400820 JavaScriptFrameIterator frame_it(isolate, id);
821 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400823
824 List<Handle<JSObject> > result(4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 ScopeIterator it(isolate, &frame_inspector, option);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400826 for (; !it.Done(); it.Next()) {
827 Handle<JSObject> details;
828 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400830 result.Add(details);
831 }
832
833 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
834 for (int i = 0; i < result.length(); ++i) {
835 array->set(i, *result[i]);
836 }
837 return *isolate->factory()->NewJSArrayWithElements(array);
838}
839
840
841RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
842 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 DCHECK_EQ(1, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400844
845 // Check arguments.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400847
848 // Count the visible scopes.
849 int n = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850 if (function->IsJSFunction()) {
851 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
852 !it.Done(); it.Next()) {
853 n++;
854 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400855 }
856
857 return Smi::FromInt(n);
858}
859
860
861RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
862 HandleScope scope(isolate);
863 DCHECK(args.length() == 2);
864
865 // Check arguments.
866 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
867 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
868
869 // Find the requested scope.
870 int n = 0;
871 ScopeIterator it(isolate, fun);
872 for (; !it.Done() && n < index; it.Next()) {
873 n++;
874 }
875 if (it.Done()) {
876 return isolate->heap()->undefined_value();
877 }
878
879 Handle<JSObject> details;
880 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 it.MaterializeScopeDetails());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400882 return *details;
883}
884
885
886static bool SetScopeVariableValue(ScopeIterator* it, int index,
887 Handle<String> variable_name,
888 Handle<Object> new_value) {
889 for (int n = 0; !it->Done() && n < index; it->Next()) {
890 n++;
891 }
892 if (it->Done()) {
893 return false;
894 }
895 return it->SetVariableValue(variable_name, new_value);
896}
897
898
899// Change variable value in closure or local scope
900// args[0]: number or JsFunction: break id or function
901// args[1]: number: frame index (when arg[0] is break id)
902// args[2]: number: inlined frame index (when arg[0] is break id)
903// args[3]: number: scope index
904// args[4]: string: variable name
905// args[5]: object: new value
906//
907// Return true if success and false otherwise
908RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
909 HandleScope scope(isolate);
910 DCHECK(args.length() == 6);
911
912 // Check arguments.
913 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
914 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
915 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
916
917 bool res;
918 if (args[0]->IsNumber()) {
919 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
920 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
921
922 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
923 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
924
925 // Get the frame where the debugging is performed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 JavaScriptFrameIterator frame_it(isolate, id);
928 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 ScopeIterator it(isolate, &frame_inspector);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400932 res = SetScopeVariableValue(&it, index, variable_name, new_value);
933 } else {
934 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
935 ScopeIterator it(isolate, fun);
936 res = SetScopeVariableValue(&it, index, variable_name, new_value);
937 }
938
939 return isolate->heap()->ToBoolean(res);
940}
941
942
943RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
944 HandleScope scope(isolate);
945 DCHECK(args.length() == 0);
946
947#ifdef DEBUG
948 // Print the scopes for the top frame.
949 StackFrameLocator locator(isolate);
950 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 FrameInspector frame_inspector(frame, 0, isolate);
952
953 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400954 it.DebugPrint();
955 }
956#endif
957 return isolate->heap()->undefined_value();
958}
959
960
961RUNTIME_FUNCTION(Runtime_GetThreadCount) {
962 HandleScope scope(isolate);
963 DCHECK(args.length() == 1);
964 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
965 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
966
967 // Count all archived V8 threads.
968 int n = 0;
969 for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
970 thread != NULL; thread = thread->Next()) {
971 n++;
972 }
973
974 // Total number of threads is current thread and archived threads.
975 return Smi::FromInt(n + 1);
976}
977
978
979static const int kThreadDetailsCurrentThreadIndex = 0;
980static const int kThreadDetailsThreadIdIndex = 1;
981static const int kThreadDetailsSize = 2;
982
983// Return an array with thread details
984// args[0]: number: break id
985// args[1]: number: thread index
986//
987// The array returned contains the following information:
988// 0: Is current thread?
989// 1: Thread id
990RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
991 HandleScope scope(isolate);
992 DCHECK(args.length() == 2);
993 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
994 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
995
996 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
997
998 // Allocate array for result.
999 Handle<FixedArray> details =
1000 isolate->factory()->NewFixedArray(kThreadDetailsSize);
1001
1002 // Thread index 0 is current thread.
1003 if (index == 0) {
1004 // Fill the details.
1005 details->set(kThreadDetailsCurrentThreadIndex,
1006 isolate->heap()->true_value());
1007 details->set(kThreadDetailsThreadIdIndex,
1008 Smi::FromInt(ThreadId::Current().ToInteger()));
1009 } else {
1010 // Find the thread with the requested index.
1011 int n = 1;
1012 ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1013 while (index != n && thread != NULL) {
1014 thread = thread->Next();
1015 n++;
1016 }
1017 if (thread == NULL) {
1018 return isolate->heap()->undefined_value();
1019 }
1020
1021 // Fill the details.
1022 details->set(kThreadDetailsCurrentThreadIndex,
1023 isolate->heap()->false_value());
1024 details->set(kThreadDetailsThreadIdIndex,
1025 Smi::FromInt(thread->id().ToInteger()));
1026 }
1027
1028 // Convert to JS array and return.
1029 return *isolate->factory()->NewJSArrayWithElements(details);
1030}
1031
1032
1033// Sets the disable break state
1034// args[0]: disable break state
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036 HandleScope scope(isolate);
1037 DCHECK(args.length() == 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1039 isolate->debug()->set_break_points_active(active);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001040 return isolate->heap()->undefined_value();
1041}
1042
1043
1044static bool IsPositionAlignmentCodeCorrect(int alignment) {
1045 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1046}
1047
1048
1049RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1050 HandleScope scope(isolate);
1051 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1054 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1055
1056 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1057 return isolate->ThrowIllegalOperation();
1058 }
1059 BreakPositionAlignment alignment =
1060 static_cast<BreakPositionAlignment>(statement_aligned_code);
1061
1062 Handle<SharedFunctionInfo> shared(fun->shared());
1063 // Find the number of break points
1064 Handle<Object> break_locations =
1065 Debug::GetSourceBreakLocations(shared, alignment);
1066 if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
1067 // Return array as JS array
1068 return *isolate->factory()->NewJSArrayWithElements(
1069 Handle<FixedArray>::cast(break_locations));
1070}
1071
1072
1073// Set a break point in a function.
1074// args[0]: function
1075// args[1]: number: break source position (within the function source)
1076// args[2]: number: break point object
1077RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1078 HandleScope scope(isolate);
1079 DCHECK(args.length() == 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1082 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1083 RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
1084 source_position <= function->shared()->end_position());
1085 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1086
1087 // Set break point.
1088 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
1089 function, break_point_object_arg, &source_position));
1090
1091 return Smi::FromInt(source_position);
1092}
1093
1094
1095// Changes the state of a break point in a script and returns source position
1096// where break point was set. NOTE: Regarding performance see the NOTE for
1097// GetScriptFromScriptData.
1098// args[0]: script to set break point in
1099// args[1]: number: break source position (within the script source)
1100// args[2]: number, breakpoint position alignment
1101// args[3]: number: break point object
1102RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1103 HandleScope scope(isolate);
1104 DCHECK(args.length() == 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001106 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1107 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1108 RUNTIME_ASSERT(source_position >= 0);
1109 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1110 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1111
1112 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1113 return isolate->ThrowIllegalOperation();
1114 }
1115 BreakPositionAlignment alignment =
1116 static_cast<BreakPositionAlignment>(statement_aligned_code);
1117
1118 // Get the script from the script wrapper.
1119 RUNTIME_ASSERT(wrapper->value()->IsScript());
1120 Handle<Script> script(Script::cast(wrapper->value()));
1121
1122 // Set break point.
1123 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1124 &source_position, alignment)) {
1125 return isolate->heap()->undefined_value();
1126 }
1127
1128 return Smi::FromInt(source_position);
1129}
1130
1131
1132// Clear a break point
1133// args[0]: number: break point object
1134RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1135 HandleScope scope(isolate);
1136 DCHECK(args.length() == 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001138 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1139
1140 // Clear break point.
1141 isolate->debug()->ClearBreakPoint(break_point_object_arg);
1142
1143 return isolate->heap()->undefined_value();
1144}
1145
1146
1147// Change the state of break on exceptions.
1148// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1149// args[1]: Boolean indicating on/off.
1150RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1151 HandleScope scope(isolate);
1152 DCHECK(args.length() == 2);
1153 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1154 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1155
1156 // If the number doesn't match an enum value, the ChangeBreakOnException
1157 // function will default to affecting caught exceptions.
1158 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1159 // Update break point state.
1160 isolate->debug()->ChangeBreakOnException(type, enable);
1161 return isolate->heap()->undefined_value();
1162}
1163
1164
1165// Returns the state of break on exceptions
1166// args[0]: boolean indicating uncaught exceptions
1167RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1168 HandleScope scope(isolate);
1169 DCHECK(args.length() == 1);
1170 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1171
1172 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1173 bool result = isolate->debug()->IsBreakOnException(type);
1174 return Smi::FromInt(result);
1175}
1176
1177
1178// Prepare for stepping
1179// args[0]: break id for checking execution state
1180// args[1]: step action from the enumeration StepAction
1181// args[2]: number of times to perform the step, for step out it is the number
1182// of frames to step down.
1183RUNTIME_FUNCTION(Runtime_PrepareStep) {
1184 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001186 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1187 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001189 if (!args[1]->IsNumber()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001190 return isolate->Throw(isolate->heap()->illegal_argument_string());
1191 }
1192
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 // Get the step action and check validity.
1194 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1195 if (step_action != StepIn && step_action != StepNext &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 step_action != StepOut && step_action != StepFrame) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001197 return isolate->Throw(isolate->heap()->illegal_argument_string());
1198 }
1199
1200 // Clear all current stepping setup.
1201 isolate->debug()->ClearStepping();
1202
1203 // Prepare step.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001204 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205 return isolate->heap()->undefined_value();
1206}
1207
1208
1209// Clear all stepping set by PrepareStep.
1210RUNTIME_FUNCTION(Runtime_ClearStepping) {
1211 HandleScope scope(isolate);
1212 DCHECK(args.length() == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001214 isolate->debug()->ClearStepping();
1215 return isolate->heap()->undefined_value();
1216}
1217
1218
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001219RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1220 HandleScope scope(isolate);
1221
1222 // Check the execution state and decode arguments frame and source to be
1223 // evaluated.
1224 DCHECK(args.length() == 6);
1225 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1226 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1227
1228 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1229 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1230 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1231 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001235
1236 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1238 isolate, result,
1239 DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1240 disable_break, context_extension));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001241 return *result;
1242}
1243
1244
1245RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1246 HandleScope scope(isolate);
1247
1248 // Check the execution state and decode arguments frame and source to be
1249 // evaluated.
1250 DCHECK(args.length() == 4);
1251 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1252 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1253
1254 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1255 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001257
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258 Handle<Object> result;
1259 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 isolate, result,
1261 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001262 return *result;
1263}
1264
1265
1266RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1267 HandleScope scope(isolate);
1268 DCHECK(args.length() == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 Handle<FixedArray> instances;
1272 {
1273 DebugScope debug_scope(isolate->debug());
1274 if (debug_scope.failed()) {
1275 DCHECK(isolate->has_pending_exception());
1276 return isolate->heap()->exception();
1277 }
1278 // Fill the script objects.
1279 instances = isolate->debug()->GetLoadedScripts();
1280 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001281
1282 // Convert the script objects to proper JS objects.
1283 for (int i = 0; i < instances->length(); i++) {
1284 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1285 // Get the script wrapper in a local handle before calling GetScriptWrapper,
1286 // because using
1287 // instances->set(i, *GetScriptWrapper(script))
1288 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1289 // already have dereferenced the instances handle.
1290 Handle<JSObject> wrapper = Script::GetWrapper(script);
1291 instances->set(i, *wrapper);
1292 }
1293
1294 // Return result as a JS array.
1295 Handle<JSObject> result =
1296 isolate->factory()->NewJSObject(isolate->array_function());
1297 JSArray::SetContent(Handle<JSArray>::cast(result), instances);
1298 return *result;
1299}
1300
Ben Murdoch097c5b22016-05-18 11:27:45 +01001301static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
1302 JSObject* object,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303 Object* proto) {
1304 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
1305 while (true) {
1306 iter.AdvanceIgnoringProxies();
1307 if (iter.IsAtEnd()) return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001308 if (iter.GetCurrent() == proto) return true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001310}
1311
1312
1313// Scan the heap for objects with direct references to an object
1314// args[0]: the object to find references to
1315// args[1]: constructor function for instances to exclude (Mirror)
1316// args[2]: the the maximum number of objects to return
1317RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1318 HandleScope scope(isolate);
1319 DCHECK(args.length() == 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001320 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1322 RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001323 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1324 RUNTIME_ASSERT(max_references >= 0);
1325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326 List<Handle<JSObject> > instances;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001327 Heap* heap = isolate->heap();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001328 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001329 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1330 // Get the constructor function for context extension and arguments array.
1331 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1332 HeapObject* heap_obj;
1333 while ((heap_obj = iterator.next())) {
1334 if (!heap_obj->IsJSObject()) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001335 JSObject* obj = JSObject::cast(heap_obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 if (obj->IsJSContextExtensionObject()) continue;
1337 if (obj->map()->GetConstructor() == arguments_fun) continue;
1338 if (!obj->ReferencesObject(*target)) continue;
1339 // Check filter if supplied. This is normally used to avoid
1340 // references from mirror objects.
1341 if (!filter->IsUndefined() &&
1342 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1343 continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001344 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001345 if (obj->IsJSGlobalObject()) {
1346 obj = JSGlobalObject::cast(obj)->global_proxy();
1347 }
1348 instances.Add(Handle<JSObject>(obj));
1349 if (instances.length() == max_references) break;
1350 }
1351 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1352 while (iterator.next()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001353 }
1354 }
1355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 Handle<FixedArray> result;
1357 if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1358 // Check for circular reference only. This can happen when the object is
1359 // only referenced from mirrors and has a circular reference in which case
1360 // the object is not really alive and would have been garbage collected if
1361 // not referenced from the mirror.
1362 result = isolate->factory()->empty_fixed_array();
1363 } else {
1364 result = isolate->factory()->NewFixedArray(instances.length());
1365 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1366 }
1367 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368}
1369
1370
1371// Scan the heap for objects constructed by a specific function.
1372// args[0]: the constructor to find instances of
1373// args[1]: the the maximum number of objects to return
1374RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1375 HandleScope scope(isolate);
1376 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001377 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1378 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
1379 RUNTIME_ASSERT(max_references >= 0);
1380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 List<Handle<JSObject> > instances;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001382 Heap* heap = isolate->heap();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001383 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1385 HeapObject* heap_obj;
1386 while ((heap_obj = iterator.next())) {
1387 if (!heap_obj->IsJSObject()) continue;
1388 JSObject* obj = JSObject::cast(heap_obj);
1389 if (obj->map()->GetConstructor() != *constructor) continue;
1390 instances.Add(Handle<JSObject>(obj));
1391 if (instances.length() == max_references) break;
1392 }
1393 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1394 while (iterator.next()) {
1395 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001396 }
1397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001398 Handle<FixedArray> result =
1399 isolate->factory()->NewFixedArray(instances.length());
1400 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1401 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001402}
1403
1404
1405// Find the effective prototype object as returned by __proto__.
1406// args[0]: the object to find the prototype for.
1407RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1408 HandleScope shs(isolate);
1409 DCHECK(args.length() == 1);
1410 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 Handle<Object> prototype;
1412 // TODO(1543): Come up with a solution for clients to handle potential errors
1413 // thrown by an intermediate proxy.
1414 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001415 JSReceiver::GetPrototype(isolate, obj));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 return *prototype;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001417}
1418
1419
1420// Patches script source (should be called upon BeforeCompile event).
1421RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1422 HandleScope scope(isolate);
1423 DCHECK(args.length() == 2);
1424
1425 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1426 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1427
1428 RUNTIME_ASSERT(script_wrapper->value()->IsScript());
1429 Handle<Script> script(Script::cast(script_wrapper->value()));
1430
1431 int compilation_state = script->compilation_state();
1432 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
1433 script->set_source(*source);
1434
1435 return isolate->heap()->undefined_value();
1436}
1437
1438
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1440 SealHandleScope shs(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001441 DCHECK_EQ(1, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 CONVERT_ARG_CHECKED(Object, f, 0);
1444 if (f->IsJSFunction()) {
1445 return JSFunction::cast(f)->shared()->inferred_name();
1446 }
1447 return isolate->heap()->empty_string();
1448}
1449
1450
1451RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1452 HandleScope scope(isolate);
1453 DCHECK_EQ(1, args.length());
1454
1455 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1456
1457 if (function->IsJSBoundFunction()) {
1458 return Handle<JSBoundFunction>::cast(function)->name();
1459 }
1460 Handle<Object> name =
1461 JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
1462 return *name;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001463}
1464
1465
1466// A testing entry. Returns statement position which is the closest to
1467// source_position.
1468RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
1469 HandleScope scope(isolate);
1470 CHECK(isolate->debug()->live_edit_enabled());
1471 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001473 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1474 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1475
1476 Handle<Code> code(function->code(), isolate);
1477
1478 if (code->kind() != Code::FUNCTION &&
1479 code->kind() != Code::OPTIMIZED_FUNCTION) {
1480 return isolate->heap()->undefined_value();
1481 }
1482
1483 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
1484 int closest_pc = 0;
1485 int distance = kMaxInt;
1486 while (!it.done()) {
1487 int statement_position = static_cast<int>(it.rinfo()->data());
1488 // Check if this break point is closer that what was previously found.
1489 if (source_position <= statement_position &&
1490 statement_position - source_position < distance) {
1491 closest_pc =
1492 static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1493 distance = statement_position - source_position;
1494 // Check whether we can't get any closer.
1495 if (distance == 0) break;
1496 }
1497 it.next();
1498 }
1499
1500 return Smi::FromInt(closest_pc);
1501}
1502
1503
1504// Calls specified function with or without entering the debugger.
1505// This is used in unit tests to run code as if debugger is entered or simply
1506// to have a stack with C++ frame in the middle.
1507RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1508 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001510 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 DebugScope debug_scope(isolate->debug());
1513 if (debug_scope.failed()) {
1514 DCHECK(isolate->has_pending_exception());
1515 return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001516 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001517
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001518 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1520 isolate, result,
1521 Execution::Call(isolate, function, handle(function->global_proxy()), 0,
1522 NULL));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001523 return *result;
1524}
1525
1526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1528 HandleScope scope(isolate);
1529 DCHECK(args.length() == 0);
1530 Handle<Context> context;
1531 {
1532 DebugScope debug_scope(isolate->debug());
1533 if (debug_scope.failed()) {
1534 DCHECK(isolate->has_pending_exception());
1535 return isolate->heap()->exception();
1536 }
1537 context = isolate->debug()->GetDebugContext();
1538 }
1539 if (context.is_null()) return isolate->heap()->undefined_value();
1540 context->set_security_token(isolate->native_context()->security_token());
1541 return context->global_proxy();
1542}
1543
1544
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001545// Performs a GC.
1546// Presently, it only does a full GC.
1547RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1548 SealHandleScope shs(isolate);
1549 DCHECK(args.length() == 1);
1550 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
1551 return isolate->heap()->undefined_value();
1552}
1553
1554
1555// Gets the current heap usage.
1556RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1557 SealHandleScope shs(isolate);
1558 DCHECK(args.length() == 0);
1559 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1560 if (!Smi::IsValid(usage)) {
1561 return *isolate->factory()->NewNumberFromInt(usage);
1562 }
1563 return Smi::FromInt(usage);
1564}
1565
1566
1567// Finds the script object from the script data. NOTE: This operation uses
1568// heap traversal to find the function generated for the source position
1569// for the requested break point. For lazily compiled functions several heap
1570// traversals might be required rendering this operation as a rather slow
1571// operation. However for setting break points which is normally done through
1572// some kind of user interaction the performance is not crucial.
1573RUNTIME_FUNCTION(Runtime_GetScript) {
1574 HandleScope scope(isolate);
1575 DCHECK(args.length() == 1);
1576 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1577
1578 Handle<Script> found;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001579 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 Script::Iterator iterator(isolate);
1581 Script* script = NULL;
1582 while ((script = iterator.Next()) != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001583 if (!script->name()->IsString()) continue;
1584 String* name = String::cast(script->name());
1585 if (name->Equals(*script_name)) {
1586 found = Handle<Script>(script, isolate);
1587 break;
1588 }
1589 }
1590 }
1591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 if (found.is_null()) return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001593 return *Script::GetWrapper(found);
1594}
1595
1596
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001597// Set one shot breakpoints for the callback function that is passed to a
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598// built-in function such as Array.forEach to enable stepping into the callback,
1599// if we are indeed stepping and the callback is subject to debugging.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001600RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
1601 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001602 HandleScope scope(isolate);
1603 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1604 RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
1605 Handle<JSFunction> fun;
1606 if (object->IsJSFunction()) {
1607 fun = Handle<JSFunction>::cast(object);
1608 } else {
1609 fun = Handle<JSFunction>(
1610 Handle<JSGeneratorObject>::cast(object)->function(), isolate);
1611 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612
1613 isolate->debug()->PrepareStepIn(fun);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001614 return isolate->heap()->undefined_value();
1615}
1616
1617
1618RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001619 DCHECK(args.length() == 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001620 HandleScope scope(isolate);
1621 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001622 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
1623 isolate->PushPromise(promise, function);
1624 // If we are in step-in mode, flood the handler.
1625 isolate->debug()->EnableStepIn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001626 return isolate->heap()->undefined_value();
1627}
1628
1629
1630RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1631 DCHECK(args.length() == 0);
1632 SealHandleScope shs(isolate);
1633 isolate->PopPromise();
1634 return isolate->heap()->undefined_value();
1635}
1636
1637
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001638RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1639 DCHECK(args.length() == 1);
1640 HandleScope scope(isolate);
1641 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1642 isolate->debug()->OnAsyncTaskEvent(data);
1643 return isolate->heap()->undefined_value();
1644}
1645
1646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647RUNTIME_FUNCTION(Runtime_DebugIsActive) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001648 SealHandleScope shs(isolate);
1649 return Smi::FromInt(isolate->debug()->is_active());
1650}
1651
1652
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001654 UNIMPLEMENTED();
1655 return NULL;
1656}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657} // namespace internal
1658} // namespace v8