blob: 80791dea768908b6d6dbed908abca7f3d2b797fd [file] [log] [blame]
Emily Bernier958fae72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Emily Bernier958fae72015-03-24 16:35:39 -04005#include "src/runtime/runtime-utils.h"
6
Ben Murdoch014dc512016-03-22 12:00:34 +00007#include "src/arguments.h"
8#include "src/debug/debug.h"
9#include "src/debug/debug-evaluate.h"
10#include "src/debug/debug-frames.h"
11#include "src/debug/debug-scopes.h"
12#include "src/frames-inl.h"
13#include "src/isolate-inl.h"
14#include "src/runtime/runtime.h"
15
Emily Bernier958fae72015-03-24 16:35:39 -040016namespace v8 {
17namespace internal {
18
19RUNTIME_FUNCTION(Runtime_DebugBreak) {
20 SealHandleScope shs(isolate);
21 DCHECK(args.length() == 0);
Ben Murdoch014dc512016-03-22 12:00:34 +000022 // Get the top-most JavaScript frame.
23 JavaScriptFrameIterator it(isolate);
24 isolate->debug()->Break(args, it.frame());
25 isolate->debug()->SetAfterBreakTarget(it.frame());
Emily Bernier958fae72015-03-24 16:35:39 -040026 return isolate->heap()->undefined_value();
27}
28
29
Ben Murdoch014dc512016-03-22 12:00:34 +000030RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
31 SealHandleScope shs(isolate);
32 DCHECK(args.length() == 0);
33 if (isolate->debug()->break_points_active()) {
34 isolate->debug()->HandleDebugBreak();
35 }
36 return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -040037}
38
39
40// Adds a JavaScript function as a debug event listener.
41// args[0]: debug event listener function to set or null or undefined for
42// clearing the event listener function
43// args[1]: object supplied during callback
44RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
45 SealHandleScope shs(isolate);
46 DCHECK(args.length() == 2);
47 RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
48 args[0]->IsNull());
49 CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
50 CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
51 isolate->debug()->SetEventListener(callback, data);
52
53 return isolate->heap()->undefined_value();
54}
55
56
Ben Murdoch014dc512016-03-22 12:00:34 +000057RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
Emily Bernier958fae72015-03-24 16:35:39 -040058 SealHandleScope shs(isolate);
59 DCHECK(args.length() == 0);
60 isolate->stack_guard()->RequestDebugBreak();
61 return isolate->heap()->undefined_value();
62}
63
64
65static Handle<Object> DebugGetProperty(LookupIterator* it,
66 bool* has_caught = NULL) {
67 for (; it->IsFound(); it->Next()) {
68 switch (it->state()) {
69 case LookupIterator::NOT_FOUND:
70 case LookupIterator::TRANSITION:
71 UNREACHABLE();
72 case LookupIterator::ACCESS_CHECK:
73 // Ignore access checks.
74 break;
Ben Murdoch014dc512016-03-22 12:00:34 +000075 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Emily Bernier958fae72015-03-24 16:35:39 -040076 case LookupIterator::INTERCEPTOR:
77 case LookupIterator::JSPROXY:
78 return it->isolate()->factory()->undefined_value();
79 case LookupIterator::ACCESSOR: {
80 Handle<Object> accessors = it->GetAccessors();
81 if (!accessors->IsAccessorInfo()) {
82 return it->isolate()->factory()->undefined_value();
83 }
Ben Murdoch014dc512016-03-22 12:00:34 +000084 MaybeHandle<Object> maybe_result =
85 JSObject::GetPropertyWithAccessor(it, SLOPPY);
Emily Bernier958fae72015-03-24 16:35:39 -040086 Handle<Object> result;
87 if (!maybe_result.ToHandle(&result)) {
88 result = handle(it->isolate()->pending_exception(), it->isolate());
89 it->isolate()->clear_pending_exception();
90 if (has_caught != NULL) *has_caught = true;
91 }
92 return result;
93 }
94
95 case LookupIterator::DATA:
96 return it->GetDataValue();
97 }
98 }
99
100 return it->isolate()->factory()->undefined_value();
101}
102
103
Ben Murdoch014dc512016-03-22 12:00:34 +0000104static Handle<Object> DebugGetProperty(Handle<Object> object,
105 Handle<Name> name) {
106 LookupIterator it(object, name);
107 return DebugGetProperty(&it);
108}
109
110
111template <class IteratorType>
112static MaybeHandle<JSArray> GetIteratorInternalProperties(
113 Isolate* isolate, Handle<IteratorType> object) {
114 Factory* factory = isolate->factory();
115 Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
116 RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
117 const char* kind = NULL;
118 switch (Smi::cast(iterator->kind())->value()) {
119 case IteratorType::kKindKeys:
120 kind = "keys";
121 break;
122 case IteratorType::kKindValues:
123 kind = "values";
124 break;
125 case IteratorType::kKindEntries:
126 kind = "entries";
127 break;
128 default:
129 RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
130 }
131
132 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
133 Handle<String> has_more =
134 factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
135 result->set(0, *has_more);
136 result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
137
138 Handle<String> index =
139 factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
140 result->set(2, *index);
141 result->set(3, iterator->index());
142
143 Handle<String> iterator_kind =
144 factory->NewStringFromAsciiChecked("[[IteratorKind]]");
145 result->set(4, *iterator_kind);
146 Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
147 result->set(5, *kind_str);
148 return factory->NewJSArrayWithElements(result);
149}
150
151
152MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
153 Handle<Object> object) {
154 Factory* factory = isolate->factory();
155 if (object->IsJSBoundFunction()) {
156 Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
157
158 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
159 Handle<String> target =
160 factory->NewStringFromAsciiChecked("[[TargetFunction]]");
161 result->set(0, *target);
162 result->set(1, function->bound_target_function());
163
164 Handle<String> bound_this =
165 factory->NewStringFromAsciiChecked("[[BoundThis]]");
166 result->set(2, *bound_this);
167 result->set(3, function->bound_this());
168
169 Handle<String> bound_args =
170 factory->NewStringFromAsciiChecked("[[BoundArgs]]");
171 result->set(4, *bound_args);
172 Handle<FixedArray> bound_arguments =
173 factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
174 Handle<JSArray> arguments_array =
175 factory->NewJSArrayWithElements(bound_arguments);
176 result->set(5, *arguments_array);
177 return factory->NewJSArrayWithElements(result);
178 } else if (object->IsJSMapIterator()) {
179 Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
180 return GetIteratorInternalProperties(isolate, iterator);
181 } else if (object->IsJSSetIterator()) {
182 Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
183 return GetIteratorInternalProperties(isolate, iterator);
184 } else if (object->IsJSGeneratorObject()) {
185 Handle<JSGeneratorObject> generator =
186 Handle<JSGeneratorObject>::cast(object);
187
188 const char* status = "suspended";
189 if (generator->is_closed()) {
190 status = "closed";
191 } else if (generator->is_executing()) {
192 status = "running";
193 } else {
194 DCHECK(generator->is_suspended());
195 }
196
197 Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
198 Handle<String> generator_status =
199 factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
200 result->set(0, *generator_status);
201 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
202 result->set(1, *status_str);
203
204 Handle<String> function =
205 factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
206 result->set(2, *function);
207 result->set(3, generator->function());
208
209 Handle<String> receiver =
210 factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
211 result->set(4, *receiver);
212 result->set(5, generator->receiver());
213 return factory->NewJSArrayWithElements(result);
214 } else if (Object::IsPromise(object)) {
215 Handle<JSObject> promise = Handle<JSObject>::cast(object);
216
217 Handle<Object> status_obj =
218 DebugGetProperty(promise, isolate->factory()->promise_status_symbol());
219 RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
220 const char* status = "rejected";
221 int status_val = Handle<Smi>::cast(status_obj)->value();
222 switch (status_val) {
223 case +1:
224 status = "resolved";
225 break;
226 case 0:
227 status = "pending";
228 break;
229 default:
230 DCHECK_EQ(-1, status_val);
231 }
232
233 Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
234 Handle<String> promise_status =
235 factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
236 result->set(0, *promise_status);
237 Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
238 result->set(1, *status_str);
239
240 Handle<Object> value_obj =
241 DebugGetProperty(promise, isolate->factory()->promise_value_symbol());
242 Handle<String> promise_value =
243 factory->NewStringFromAsciiChecked("[[PromiseValue]]");
244 result->set(2, *promise_value);
245 result->set(3, *value_obj);
246 return factory->NewJSArrayWithElements(result);
247 } else if (object->IsJSValue()) {
248 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
249
250 Handle<FixedArray> result = factory->NewFixedArray(2);
251 Handle<String> primitive_value =
252 factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
253 result->set(0, *primitive_value);
254 result->set(1, js_value->value());
255 return factory->NewJSArrayWithElements(result);
256 }
257 return factory->NewJSArray(0);
258}
259
260
261RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
262 HandleScope scope(isolate);
263 DCHECK(args.length() == 1);
264 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
265 Handle<JSArray> result;
266 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
267 isolate, result, Runtime::GetInternalProperties(isolate, obj));
268 return *result;
269}
270
271
Emily Bernier958fae72015-03-24 16:35:39 -0400272// Get debugger related details for an object property, in the following format:
273// 0: Property value
274// 1: Property details
275// 2: Property value is exception
276// 3: Getter function if defined
277// 4: Setter function if defined
278// Items 2-4 are only filled if the property has either a getter or a setter.
279RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
280 HandleScope scope(isolate);
281
282 DCHECK(args.length() == 2);
283
284 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
285 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
286
287 // Make sure to set the current context to the context before the debugger was
288 // entered (if the debugger is entered). The reason for switching context here
289 // is that for some property lookups (accessors and interceptors) callbacks
290 // into the embedding application can occour, and the embedding application
291 // could have the assumption that its own native context is the current
292 // context and not some internal debugger context.
293 SaveContext save(isolate);
294 if (isolate->debug()->in_debug_scope()) {
295 isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
296 }
297
298 // Check if the name is trivially convertible to an index and get the element
299 // if so.
300 uint32_t index;
Ben Murdoch014dc512016-03-22 12:00:34 +0000301 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
302 // this special case.
Emily Bernier958fae72015-03-24 16:35:39 -0400303 if (name->AsArrayIndex(&index)) {
304 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
305 Handle<Object> element_or_char;
Ben Murdoch014dc512016-03-22 12:00:34 +0000306 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_or_char,
307 Object::GetElement(isolate, obj, index));
Emily Bernier958fae72015-03-24 16:35:39 -0400308 details->set(0, *element_or_char);
Ben Murdoch014dc512016-03-22 12:00:34 +0000309 details->set(1, PropertyDetails::Empty().AsSmi());
Emily Bernier958fae72015-03-24 16:35:39 -0400310 return *isolate->factory()->NewJSArrayWithElements(details);
311 }
312
313 LookupIterator it(obj, name, LookupIterator::HIDDEN);
314 bool has_caught = false;
315 Handle<Object> value = DebugGetProperty(&it, &has_caught);
316 if (!it.IsFound()) return isolate->heap()->undefined_value();
317
318 Handle<Object> maybe_pair;
319 if (it.state() == LookupIterator::ACCESSOR) {
320 maybe_pair = it.GetAccessors();
321 }
322
323 // If the callback object is a fixed array then it contains JavaScript
324 // getter and/or setter.
325 bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
326 Handle<FixedArray> details =
327 isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
328 details->set(0, *value);
329 // TODO(verwaest): Get rid of this random way of handling interceptors.
330 PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
Ben Murdoch014dc512016-03-22 12:00:34 +0000331 ? PropertyDetails::Empty()
Emily Bernier958fae72015-03-24 16:35:39 -0400332 : it.property_details();
333 details->set(1, d.AsSmi());
334 details->set(
335 2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
336 if (has_js_accessors) {
337 AccessorPair* accessors = AccessorPair::cast(*maybe_pair);
338 details->set(3, isolate->heap()->ToBoolean(has_caught));
339 details->set(4, accessors->GetComponent(ACCESSOR_GETTER));
340 details->set(5, accessors->GetComponent(ACCESSOR_SETTER));
341 }
342
343 return *isolate->factory()->NewJSArrayWithElements(details);
344}
345
346
347RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
348 HandleScope scope(isolate);
349
350 DCHECK(args.length() == 2);
351
352 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
353 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
354
355 LookupIterator it(obj, name);
356 return *DebugGetProperty(&it);
357}
358
359
360// Return the property type calculated from the property details.
361// args[0]: smi with property details.
362RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
363 SealHandleScope shs(isolate);
364 DCHECK(args.length() == 1);
365 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
366 return Smi::FromInt(static_cast<int>(details.type()));
367}
368
369
370// Return the property attribute calculated from the property details.
371// args[0]: smi with property details.
372RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
373 SealHandleScope shs(isolate);
374 DCHECK(args.length() == 1);
375 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
376 return Smi::FromInt(static_cast<int>(details.attributes()));
377}
378
379
380// Return the property insertion index calculated from the property details.
381// args[0]: smi with property details.
382RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
383 SealHandleScope shs(isolate);
384 DCHECK(args.length() == 1);
385 CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
386 // TODO(verwaest): Works only for dictionary mode holders.
387 return Smi::FromInt(details.dictionary_index());
388}
389
390
391// Return property value from named interceptor.
392// args[0]: object
393// args[1]: property name
394RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
395 HandleScope scope(isolate);
396 DCHECK(args.length() == 2);
397 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
398 RUNTIME_ASSERT(obj->HasNamedInterceptor());
399 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
400
401 Handle<Object> result;
402 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
403 JSObject::GetProperty(obj, name));
404 return *result;
405}
406
407
408// Return element value from indexed interceptor.
409// args[0]: object
410// args[1]: index
411RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
412 HandleScope scope(isolate);
413 DCHECK(args.length() == 2);
414 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
415 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
416 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
417 Handle<Object> result;
Ben Murdoch014dc512016-03-22 12:00:34 +0000418 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
419 Object::GetElement(isolate, obj, index));
Emily Bernier958fae72015-03-24 16:35:39 -0400420 return *result;
421}
422
423
424RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
425 SealHandleScope shs(isolate);
426 DCHECK(args.length() == 1);
427 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
428 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
429 return isolate->heap()->true_value();
430}
431
432
433RUNTIME_FUNCTION(Runtime_GetFrameCount) {
434 HandleScope scope(isolate);
435 DCHECK(args.length() == 1);
436 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
437 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
438
439 // Count all frames which are relevant to debugging stack trace.
440 int n = 0;
441 StackFrame::Id id = isolate->debug()->break_frame_id();
442 if (id == StackFrame::NO_ID) {
443 // If there is no JavaScript stack frame count is 0.
444 return Smi::FromInt(0);
445 }
446
447 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
448 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
449 it.frame()->Summarize(&frames);
450 for (int i = frames.length() - 1; i >= 0; i--) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000451 // Omit functions from native and extension scripts.
452 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
Emily Bernier958fae72015-03-24 16:35:39 -0400453 }
454 }
455 return Smi::FromInt(n);
456}
457
458
Emily Bernier958fae72015-03-24 16:35:39 -0400459static const int kFrameDetailsFrameIdIndex = 0;
460static const int kFrameDetailsReceiverIndex = 1;
461static const int kFrameDetailsFunctionIndex = 2;
462static const int kFrameDetailsArgumentCountIndex = 3;
463static const int kFrameDetailsLocalCountIndex = 4;
464static const int kFrameDetailsSourcePositionIndex = 5;
465static const int kFrameDetailsConstructCallIndex = 6;
466static const int kFrameDetailsAtReturnIndex = 7;
467static const int kFrameDetailsFlagsIndex = 8;
468static const int kFrameDetailsFirstDynamicIndex = 9;
469
470
Emily Bernier958fae72015-03-24 16:35:39 -0400471// Return an array with frame details
472// args[0]: number: break id
473// args[1]: number: frame index
474//
475// The array returned contains the following information:
476// 0: Frame id
477// 1: Receiver
478// 2: Function
479// 3: Argument count
480// 4: Local count
481// 5: Source position
482// 6: Constructor call
483// 7: Is at return
484// 8: Flags
485// Arguments name, value
486// Locals name, value
487// Return value if any
488RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
489 HandleScope scope(isolate);
490 DCHECK(args.length() == 2);
491 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
492 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
493
494 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
495 Heap* heap = isolate->heap();
496
497 // Find the relevant frame with the requested index.
498 StackFrame::Id id = isolate->debug()->break_frame_id();
499 if (id == StackFrame::NO_ID) {
500 // If there are no JavaScript stack frames return undefined.
501 return heap->undefined_value();
502 }
503
504 JavaScriptFrameIterator it(isolate, id);
505 // Inlined frame index in optimized frame, starting from outer function.
Ben Murdoch014dc512016-03-22 12:00:34 +0000506 int inlined_jsframe_index =
507 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
Emily Bernier958fae72015-03-24 16:35:39 -0400508 if (inlined_jsframe_index == -1) return heap->undefined_value();
509
510 FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
511 bool is_optimized = it.frame()->is_optimized();
512
513 // Traverse the saved contexts chain to find the active context for the
514 // selected frame.
Ben Murdoch014dc512016-03-22 12:00:34 +0000515 SaveContext* save =
516 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
Emily Bernier958fae72015-03-24 16:35:39 -0400517
518 // Get the frame id.
Ben Murdoch014dc512016-03-22 12:00:34 +0000519 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
520 isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400521
522 // Find source position in unoptimized code.
523 int position = frame_inspector.GetSourcePosition();
524
525 // Check for constructor frame.
526 bool constructor = frame_inspector.IsConstructor();
527
528 // Get scope info and read from it for local variable information.
529 Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
Ben Murdoch014dc512016-03-22 12:00:34 +0000530 RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging());
Emily Bernier958fae72015-03-24 16:35:39 -0400531 Handle<SharedFunctionInfo> shared(function->shared());
532 Handle<ScopeInfo> scope_info(shared->scope_info());
533 DCHECK(*scope_info != ScopeInfo::Empty(isolate));
534
535 // Get the locals names and values into a temporary array.
536 int local_count = scope_info->LocalCount();
537 for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
538 // Hide compiler-introduced temporary variables, whether on the stack or on
539 // the context.
540 if (scope_info->LocalIsSynthetic(slot)) local_count--;
541 }
542
543 Handle<FixedArray> locals =
544 isolate->factory()->NewFixedArray(local_count * 2);
545
546 // Fill in the values of the locals.
547 int local = 0;
548 int i = 0;
549 for (; i < scope_info->StackLocalCount(); ++i) {
550 // Use the value from the stack.
551 if (scope_info->LocalIsSynthetic(i)) continue;
552 locals->set(local * 2, scope_info->LocalName(i));
553 locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
554 local++;
555 }
556 if (local < local_count) {
557 // Get the context containing declarations.
558 Handle<Context> context(
559 Context::cast(frame_inspector.GetContext())->declaration_context());
560 for (; i < scope_info->LocalCount(); ++i) {
561 if (scope_info->LocalIsSynthetic(i)) continue;
562 Handle<String> name(scope_info->LocalName(i));
563 VariableMode mode;
564 InitializationFlag init_flag;
565 MaybeAssignedFlag maybe_assigned_flag;
566 locals->set(local * 2, *name);
567 int context_slot_index = ScopeInfo::ContextSlotIndex(
568 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
569 Object* value = context->get(context_slot_index);
570 locals->set(local * 2 + 1, value);
571 local++;
572 }
573 }
574
575 // Check whether this frame is positioned at return. If not top
576 // frame or if the frame is optimized it cannot be at a return.
577 bool at_return = false;
578 if (!is_optimized && index == 0) {
579 at_return = isolate->debug()->IsBreakAtReturn(it.frame());
580 }
581
582 // If positioned just before return find the value to be returned and add it
583 // to the frame information.
584 Handle<Object> return_value = isolate->factory()->undefined_value();
585 if (at_return) {
586 StackFrameIterator it2(isolate);
587 Address internal_frame_sp = NULL;
588 while (!it2.done()) {
589 if (it2.frame()->is_internal()) {
590 internal_frame_sp = it2.frame()->sp();
591 } else {
592 if (it2.frame()->is_java_script()) {
593 if (it2.frame()->id() == it.frame()->id()) {
594 // The internal frame just before the JavaScript frame contains the
595 // value to return on top. A debug break at return will create an
596 // internal frame to store the return value (eax/rax/r0) before
597 // entering the debug break exit frame.
598 if (internal_frame_sp != NULL) {
599 return_value =
600 Handle<Object>(Memory::Object_at(internal_frame_sp), isolate);
601 break;
602 }
603 }
604 }
605
606 // Indicate that the previous frame was not an internal frame.
607 internal_frame_sp = NULL;
608 }
609 it2.Advance();
610 }
611 }
612
613 // Now advance to the arguments adapter frame (if any). It contains all
614 // the provided parameters whereas the function frame always have the number
615 // of arguments matching the functions parameters. The rest of the
616 // information (except for what is collected above) is the same.
617 if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
618 it.AdvanceToArgumentsFrame();
619 frame_inspector.SetArgumentsFrame(it.frame());
620 }
621
622 // Find the number of arguments to fill. At least fill the number of
623 // parameters for the function and fill more if more parameters are provided.
624 int argument_count = scope_info->ParameterCount();
625 if (argument_count < frame_inspector.GetParametersCount()) {
626 argument_count = frame_inspector.GetParametersCount();
627 }
628
629 // Calculate the size of the result.
630 int details_size = kFrameDetailsFirstDynamicIndex +
631 2 * (argument_count + local_count) + (at_return ? 1 : 0);
632 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
633
634 // Add the frame id.
635 details->set(kFrameDetailsFrameIdIndex, *frame_id);
636
637 // Add the function (same as in function frame).
638 details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
639
640 // Add the arguments count.
641 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
642
643 // Add the locals count
644 details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count));
645
646 // Add the source position.
647 if (position != RelocInfo::kNoPosition) {
648 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
649 } else {
650 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
651 }
652
653 // Add the constructor information.
654 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
655
656 // Add the at return information.
657 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
658
659 // Add flags to indicate information on whether this frame is
660 // bit 0: invoked in the debugger context.
661 // bit 1: optimized frame.
662 // bit 2: inlined in optimized frame
663 int flags = 0;
664 if (*save->context() == *isolate->debug()->debug_context()) {
665 flags |= 1 << 0;
666 }
667 if (is_optimized) {
668 flags |= 1 << 1;
669 flags |= inlined_jsframe_index << 2;
670 }
671 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
672
673 // Fill the dynamic part.
674 int details_index = kFrameDetailsFirstDynamicIndex;
675
676 // Add arguments name and value.
677 for (int i = 0; i < argument_count; i++) {
678 // Name of the argument.
679 if (i < scope_info->ParameterCount()) {
680 details->set(details_index++, scope_info->ParameterName(i));
681 } else {
682 details->set(details_index++, heap->undefined_value());
683 }
684
685 // Parameter value.
686 if (i < frame_inspector.GetParametersCount()) {
687 // Get the value from the stack.
688 details->set(details_index++, frame_inspector.GetParameter(i));
689 } else {
690 details->set(details_index++, heap->undefined_value());
691 }
692 }
693
694 // Add locals name and value from the temporary copy from the function frame.
695 for (int i = 0; i < local_count * 2; i++) {
696 details->set(details_index++, locals->get(i));
697 }
698
699 // Add the value being returned.
700 if (at_return) {
701 details->set(details_index++, *return_value);
702 }
703
704 // Add the receiver (same as in function frame).
Emily Bernier958fae72015-03-24 16:35:39 -0400705 Handle<Object> receiver(it.frame()->receiver(), isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000706 DCHECK(!function->shared()->IsBuiltin());
707 if (!receiver->IsJSObject() && is_sloppy(shared->language_mode())) {
708 // If the receiver is not a JSObject and the function is not a builtin or
709 // strict-mode we have hit an optimization where a value object is not
710 // converted into a wrapped JS objects. To hide this optimization from the
711 // debugger, we wrap the receiver by creating correct wrapper object based
712 // on the function's native context.
713 // See ECMA-262 6.0, 9.2.1.2, 6 b iii.
Emily Bernier958fae72015-03-24 16:35:39 -0400714 if (receiver->IsUndefined()) {
715 receiver = handle(function->global_proxy());
716 } else {
Ben Murdoch014dc512016-03-22 12:00:34 +0000717 Context* context = function->context();
Emily Bernier958fae72015-03-24 16:35:39 -0400718 Handle<Context> native_context(Context::cast(context->native_context()));
719 if (!Object::ToObject(isolate, receiver, native_context)
720 .ToHandle(&receiver)) {
721 // This only happens if the receiver is forcibly set in %_CallFunction.
722 return heap->undefined_value();
723 }
724 }
725 }
726 details->set(kFrameDetailsReceiverIndex, *receiver);
727
728 DCHECK_EQ(details_size, details_index);
729 return *isolate->factory()->NewJSArrayWithElements(details);
730}
731
732
Emily Bernier958fae72015-03-24 16:35:39 -0400733RUNTIME_FUNCTION(Runtime_GetScopeCount) {
734 HandleScope scope(isolate);
735 DCHECK(args.length() == 2);
736 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
737 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
738
739 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
740
741 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000742 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400743 JavaScriptFrameIterator it(isolate, id);
744 JavaScriptFrame* frame = it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000745 FrameInspector frame_inspector(frame, 0, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400746
747 // Count the visible scopes.
748 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000749 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400750 n++;
751 }
752
753 return Smi::FromInt(n);
754}
755
756
757// Returns the list of step-in positions (text offset) in a function of the
758// stack frame in a range from the current debug break position to the end
759// of the corresponding statement.
760RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
761 HandleScope scope(isolate);
762 DCHECK(args.length() == 2);
763 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
764 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
765
766 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
767
768 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000769 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400770 JavaScriptFrameIterator frame_it(isolate, id);
771 RUNTIME_ASSERT(!frame_it.done());
772
Ben Murdoch014dc512016-03-22 12:00:34 +0000773 List<int> positions;
774 isolate->debug()->GetStepinPositions(frame_it.frame(), id, &positions);
775 Factory* factory = isolate->factory();
776 Handle<FixedArray> array = factory->NewFixedArray(positions.length());
777 for (int i = 0; i < positions.length(); ++i) {
778 array->set(i, Smi::FromInt(positions[i]));
Emily Bernier958fae72015-03-24 16:35:39 -0400779 }
Ben Murdoch014dc512016-03-22 12:00:34 +0000780 return *factory->NewJSArrayWithElements(array, FAST_SMI_ELEMENTS);
Emily Bernier958fae72015-03-24 16:35:39 -0400781}
782
783
784// Return an array with scope details
785// args[0]: number: break id
786// args[1]: number: frame index
787// args[2]: number: inlined frame index
788// args[3]: number: scope index
789//
790// The array returned contains the following information:
791// 0: Scope type
792// 1: Scope object
793RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
794 HandleScope scope(isolate);
795 DCHECK(args.length() == 4);
796 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
797 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
798
799 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
800 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
801 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
802
803 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000804 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400805 JavaScriptFrameIterator frame_it(isolate, id);
806 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000807 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400808
809 // Find the requested scope.
810 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000811 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -0400812 for (; !it.Done() && n < index; it.Next()) {
813 n++;
814 }
815 if (it.Done()) {
816 return isolate->heap()->undefined_value();
817 }
818 Handle<JSObject> details;
819 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch014dc512016-03-22 12:00:34 +0000820 it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400821 return *details;
822}
823
824
825// Return an array of scope details
826// args[0]: number: break id
827// args[1]: number: frame index
828// args[2]: number: inlined frame index
829// args[3]: boolean: ignore nested scopes
830//
831// The array returned contains arrays with the following information:
832// 0: Scope type
833// 1: Scope object
834RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
835 HandleScope scope(isolate);
836 DCHECK(args.length() == 3 || args.length() == 4);
837 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
838 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
839
840 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
841 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
842
Ben Murdoch014dc512016-03-22 12:00:34 +0000843 ScopeIterator::Option option = ScopeIterator::DEFAULT;
Emily Bernier958fae72015-03-24 16:35:39 -0400844 if (args.length() == 4) {
845 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
Ben Murdoch014dc512016-03-22 12:00:34 +0000846 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
Emily Bernier958fae72015-03-24 16:35:39 -0400847 }
848
849 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000850 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400851 JavaScriptFrameIterator frame_it(isolate, id);
852 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000853 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400854
855 List<Handle<JSObject> > result(4);
Ben Murdoch014dc512016-03-22 12:00:34 +0000856 ScopeIterator it(isolate, &frame_inspector, option);
Emily Bernier958fae72015-03-24 16:35:39 -0400857 for (; !it.Done(); it.Next()) {
858 Handle<JSObject> details;
859 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch014dc512016-03-22 12:00:34 +0000860 it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400861 result.Add(details);
862 }
863
864 Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
865 for (int i = 0; i < result.length(); ++i) {
866 array->set(i, *result[i]);
867 }
868 return *isolate->factory()->NewJSArrayWithElements(array);
869}
870
871
872RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
873 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +0000874 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -0400875
876 // Check arguments.
Ben Murdoch014dc512016-03-22 12:00:34 +0000877 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -0400878
879 // Count the visible scopes.
880 int n = 0;
Ben Murdoch014dc512016-03-22 12:00:34 +0000881 if (function->IsJSFunction()) {
882 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
883 !it.Done(); it.Next()) {
884 n++;
885 }
Emily Bernier958fae72015-03-24 16:35:39 -0400886 }
887
888 return Smi::FromInt(n);
889}
890
891
892RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
893 HandleScope scope(isolate);
894 DCHECK(args.length() == 2);
895
896 // Check arguments.
897 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
898 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
899
900 // Find the requested scope.
901 int n = 0;
902 ScopeIterator it(isolate, fun);
903 for (; !it.Done() && n < index; it.Next()) {
904 n++;
905 }
906 if (it.Done()) {
907 return isolate->heap()->undefined_value();
908 }
909
910 Handle<JSObject> details;
911 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
Ben Murdoch014dc512016-03-22 12:00:34 +0000912 it.MaterializeScopeDetails());
Emily Bernier958fae72015-03-24 16:35:39 -0400913 return *details;
914}
915
916
917static bool SetScopeVariableValue(ScopeIterator* it, int index,
918 Handle<String> variable_name,
919 Handle<Object> new_value) {
920 for (int n = 0; !it->Done() && n < index; it->Next()) {
921 n++;
922 }
923 if (it->Done()) {
924 return false;
925 }
926 return it->SetVariableValue(variable_name, new_value);
927}
928
929
930// Change variable value in closure or local scope
931// args[0]: number or JsFunction: break id or function
932// args[1]: number: frame index (when arg[0] is break id)
933// args[2]: number: inlined frame index (when arg[0] is break id)
934// args[3]: number: scope index
935// args[4]: string: variable name
936// args[5]: object: new value
937//
938// Return true if success and false otherwise
939RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
940 HandleScope scope(isolate);
941 DCHECK(args.length() == 6);
942
943 // Check arguments.
944 CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
945 CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
946 CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
947
948 bool res;
949 if (args[0]->IsNumber()) {
950 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
951 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
952
953 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
954 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
955
956 // Get the frame where the debugging is performed.
Ben Murdoch014dc512016-03-22 12:00:34 +0000957 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -0400958 JavaScriptFrameIterator frame_it(isolate, id);
959 JavaScriptFrame* frame = frame_it.frame();
Ben Murdoch014dc512016-03-22 12:00:34 +0000960 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Emily Bernier958fae72015-03-24 16:35:39 -0400961
Ben Murdoch014dc512016-03-22 12:00:34 +0000962 ScopeIterator it(isolate, &frame_inspector);
Emily Bernier958fae72015-03-24 16:35:39 -0400963 res = SetScopeVariableValue(&it, index, variable_name, new_value);
964 } else {
965 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
966 ScopeIterator it(isolate, fun);
967 res = SetScopeVariableValue(&it, index, variable_name, new_value);
968 }
969
970 return isolate->heap()->ToBoolean(res);
971}
972
973
974RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
975 HandleScope scope(isolate);
976 DCHECK(args.length() == 0);
977
978#ifdef DEBUG
979 // Print the scopes for the top frame.
980 StackFrameLocator locator(isolate);
981 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
Ben Murdoch014dc512016-03-22 12:00:34 +0000982 FrameInspector frame_inspector(frame, 0, isolate);
983
984 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
Emily Bernier958fae72015-03-24 16:35:39 -0400985 it.DebugPrint();
986 }
987#endif
988 return isolate->heap()->undefined_value();
989}
990
991
992RUNTIME_FUNCTION(Runtime_GetThreadCount) {
993 HandleScope scope(isolate);
994 DCHECK(args.length() == 1);
995 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
996 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
997
998 // Count all archived V8 threads.
999 int n = 0;
1000 for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1001 thread != NULL; thread = thread->Next()) {
1002 n++;
1003 }
1004
1005 // Total number of threads is current thread and archived threads.
1006 return Smi::FromInt(n + 1);
1007}
1008
1009
1010static const int kThreadDetailsCurrentThreadIndex = 0;
1011static const int kThreadDetailsThreadIdIndex = 1;
1012static const int kThreadDetailsSize = 2;
1013
1014// Return an array with thread details
1015// args[0]: number: break id
1016// args[1]: number: thread index
1017//
1018// The array returned contains the following information:
1019// 0: Is current thread?
1020// 1: Thread id
1021RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
1022 HandleScope scope(isolate);
1023 DCHECK(args.length() == 2);
1024 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1025 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1026
1027 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
1028
1029 // Allocate array for result.
1030 Handle<FixedArray> details =
1031 isolate->factory()->NewFixedArray(kThreadDetailsSize);
1032
1033 // Thread index 0 is current thread.
1034 if (index == 0) {
1035 // Fill the details.
1036 details->set(kThreadDetailsCurrentThreadIndex,
1037 isolate->heap()->true_value());
1038 details->set(kThreadDetailsThreadIdIndex,
1039 Smi::FromInt(ThreadId::Current().ToInteger()));
1040 } else {
1041 // Find the thread with the requested index.
1042 int n = 1;
1043 ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1044 while (index != n && thread != NULL) {
1045 thread = thread->Next();
1046 n++;
1047 }
1048 if (thread == NULL) {
1049 return isolate->heap()->undefined_value();
1050 }
1051
1052 // Fill the details.
1053 details->set(kThreadDetailsCurrentThreadIndex,
1054 isolate->heap()->false_value());
1055 details->set(kThreadDetailsThreadIdIndex,
1056 Smi::FromInt(thread->id().ToInteger()));
1057 }
1058
1059 // Convert to JS array and return.
1060 return *isolate->factory()->NewJSArrayWithElements(details);
1061}
1062
1063
1064// Sets the disable break state
1065// args[0]: disable break state
Ben Murdoch014dc512016-03-22 12:00:34 +00001066RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001067 HandleScope scope(isolate);
1068 DCHECK(args.length() == 1);
Ben Murdoch014dc512016-03-22 12:00:34 +00001069 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1070 isolate->debug()->set_break_points_active(active);
Emily Bernier958fae72015-03-24 16:35:39 -04001071 return isolate->heap()->undefined_value();
1072}
1073
1074
1075static bool IsPositionAlignmentCodeCorrect(int alignment) {
1076 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1077}
1078
1079
1080RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1081 HandleScope scope(isolate);
1082 DCHECK(args.length() == 2);
Ben Murdoch014dc512016-03-22 12:00:34 +00001083 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001084 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
1085 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
1086
1087 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1088 return isolate->ThrowIllegalOperation();
1089 }
1090 BreakPositionAlignment alignment =
1091 static_cast<BreakPositionAlignment>(statement_aligned_code);
1092
1093 Handle<SharedFunctionInfo> shared(fun->shared());
1094 // Find the number of break points
1095 Handle<Object> break_locations =
1096 Debug::GetSourceBreakLocations(shared, alignment);
1097 if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
1098 // Return array as JS array
1099 return *isolate->factory()->NewJSArrayWithElements(
1100 Handle<FixedArray>::cast(break_locations));
1101}
1102
1103
1104// Set a break point in a function.
1105// args[0]: function
1106// args[1]: number: break source position (within the function source)
1107// args[2]: number: break point object
1108RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1109 HandleScope scope(isolate);
1110 DCHECK(args.length() == 3);
Ben Murdoch014dc512016-03-22 12:00:34 +00001111 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001112 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1113 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1114 RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
1115 source_position <= function->shared()->end_position());
1116 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
1117
1118 // Set break point.
1119 RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
1120 function, break_point_object_arg, &source_position));
1121
1122 return Smi::FromInt(source_position);
1123}
1124
1125
1126// Changes the state of a break point in a script and returns source position
1127// where break point was set. NOTE: Regarding performance see the NOTE for
1128// GetScriptFromScriptData.
1129// args[0]: script to set break point in
1130// args[1]: number: break source position (within the script source)
1131// args[2]: number, breakpoint position alignment
1132// args[3]: number: break point object
1133RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1134 HandleScope scope(isolate);
1135 DCHECK(args.length() == 4);
Ben Murdoch014dc512016-03-22 12:00:34 +00001136 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001137 CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
1138 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1139 RUNTIME_ASSERT(source_position >= 0);
1140 CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
1141 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
1142
1143 if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
1144 return isolate->ThrowIllegalOperation();
1145 }
1146 BreakPositionAlignment alignment =
1147 static_cast<BreakPositionAlignment>(statement_aligned_code);
1148
1149 // Get the script from the script wrapper.
1150 RUNTIME_ASSERT(wrapper->value()->IsScript());
1151 Handle<Script> script(Script::cast(wrapper->value()));
1152
1153 // Set break point.
1154 if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
1155 &source_position, alignment)) {
1156 return isolate->heap()->undefined_value();
1157 }
1158
1159 return Smi::FromInt(source_position);
1160}
1161
1162
1163// Clear a break point
1164// args[0]: number: break point object
1165RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1166 HandleScope scope(isolate);
1167 DCHECK(args.length() == 1);
Ben Murdoch014dc512016-03-22 12:00:34 +00001168 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001169 CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
1170
1171 // Clear break point.
1172 isolate->debug()->ClearBreakPoint(break_point_object_arg);
1173
1174 return isolate->heap()->undefined_value();
1175}
1176
1177
1178// Change the state of break on exceptions.
1179// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
1180// args[1]: Boolean indicating on/off.
1181RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1182 HandleScope scope(isolate);
1183 DCHECK(args.length() == 2);
1184 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1185 CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1186
1187 // If the number doesn't match an enum value, the ChangeBreakOnException
1188 // function will default to affecting caught exceptions.
1189 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1190 // Update break point state.
1191 isolate->debug()->ChangeBreakOnException(type, enable);
1192 return isolate->heap()->undefined_value();
1193}
1194
1195
1196// Returns the state of break on exceptions
1197// args[0]: boolean indicating uncaught exceptions
1198RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1199 HandleScope scope(isolate);
1200 DCHECK(args.length() == 1);
1201 CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1202
1203 ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1204 bool result = isolate->debug()->IsBreakOnException(type);
1205 return Smi::FromInt(result);
1206}
1207
1208
1209// Prepare for stepping
1210// args[0]: break id for checking execution state
1211// args[1]: step action from the enumeration StepAction
1212// args[2]: number of times to perform the step, for step out it is the number
1213// of frames to step down.
1214RUNTIME_FUNCTION(Runtime_PrepareStep) {
1215 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001216 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001217 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1218 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1219
Ben Murdoch014dc512016-03-22 12:00:34 +00001220 if (!args[1]->IsNumber()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001221 return isolate->Throw(isolate->heap()->illegal_argument_string());
1222 }
1223
Emily Bernier958fae72015-03-24 16:35:39 -04001224 // Get the step action and check validity.
1225 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
1226 if (step_action != StepIn && step_action != StepNext &&
Ben Murdoch014dc512016-03-22 12:00:34 +00001227 step_action != StepOut && step_action != StepFrame) {
Emily Bernier958fae72015-03-24 16:35:39 -04001228 return isolate->Throw(isolate->heap()->illegal_argument_string());
1229 }
1230
1231 // Clear all current stepping setup.
1232 isolate->debug()->ClearStepping();
1233
1234 // Prepare step.
Ben Murdoch014dc512016-03-22 12:00:34 +00001235 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
Emily Bernier958fae72015-03-24 16:35:39 -04001236 return isolate->heap()->undefined_value();
1237}
1238
1239
1240// Clear all stepping set by PrepareStep.
1241RUNTIME_FUNCTION(Runtime_ClearStepping) {
1242 HandleScope scope(isolate);
1243 DCHECK(args.length() == 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001244 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001245 isolate->debug()->ClearStepping();
1246 return isolate->heap()->undefined_value();
1247}
1248
1249
Emily Bernier958fae72015-03-24 16:35:39 -04001250RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
1251 HandleScope scope(isolate);
1252
1253 // Check the execution state and decode arguments frame and source to be
1254 // evaluated.
1255 DCHECK(args.length() == 6);
1256 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1257 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1258
1259 CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
1260 CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
1261 CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
1262 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
Ben Murdoch014dc512016-03-22 12:00:34 +00001263 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
Emily Bernier958fae72015-03-24 16:35:39 -04001264
Ben Murdoch014dc512016-03-22 12:00:34 +00001265 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
Emily Bernier958fae72015-03-24 16:35:39 -04001266
1267 Handle<Object> result;
Ben Murdoch014dc512016-03-22 12:00:34 +00001268 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1269 isolate, result,
1270 DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1271 disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001272 return *result;
1273}
1274
1275
1276RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1277 HandleScope scope(isolate);
1278
1279 // Check the execution state and decode arguments frame and source to be
1280 // evaluated.
1281 DCHECK(args.length() == 4);
1282 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1283 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1284
1285 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1286 CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
Ben Murdoch014dc512016-03-22 12:00:34 +00001287 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001288
Emily Bernier958fae72015-03-24 16:35:39 -04001289 Handle<Object> result;
1290 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch014dc512016-03-22 12:00:34 +00001291 isolate, result,
1292 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
Emily Bernier958fae72015-03-24 16:35:39 -04001293 return *result;
1294}
1295
1296
1297RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1298 HandleScope scope(isolate);
1299 DCHECK(args.length() == 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001300 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001301
Ben Murdoch014dc512016-03-22 12:00:34 +00001302 Handle<FixedArray> instances;
1303 {
1304 DebugScope debug_scope(isolate->debug());
1305 if (debug_scope.failed()) {
1306 DCHECK(isolate->has_pending_exception());
1307 return isolate->heap()->exception();
1308 }
1309 // Fill the script objects.
1310 instances = isolate->debug()->GetLoadedScripts();
1311 }
Emily Bernier958fae72015-03-24 16:35:39 -04001312
1313 // Convert the script objects to proper JS objects.
1314 for (int i = 0; i < instances->length(); i++) {
1315 Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
1316 // Get the script wrapper in a local handle before calling GetScriptWrapper,
1317 // because using
1318 // instances->set(i, *GetScriptWrapper(script))
1319 // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
1320 // already have dereferenced the instances handle.
1321 Handle<JSObject> wrapper = Script::GetWrapper(script);
1322 instances->set(i, *wrapper);
1323 }
1324
1325 // Return result as a JS array.
1326 Handle<JSObject> result =
1327 isolate->factory()->NewJSObject(isolate->array_function());
1328 JSArray::SetContent(Handle<JSArray>::cast(result), instances);
1329 return *result;
1330}
1331
1332
Ben Murdoch014dc512016-03-22 12:00:34 +00001333static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate, Object* object,
1334 Object* proto) {
1335 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
1336 while (true) {
1337 iter.AdvanceIgnoringProxies();
1338 if (iter.IsAtEnd()) return false;
1339 if (iter.IsAtEnd(proto)) return true;
Emily Bernier958fae72015-03-24 16:35:39 -04001340 }
Emily Bernier958fae72015-03-24 16:35:39 -04001341}
1342
1343
1344// Scan the heap for objects with direct references to an object
1345// args[0]: the object to find references to
1346// args[1]: constructor function for instances to exclude (Mirror)
1347// args[2]: the the maximum number of objects to return
1348RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1349 HandleScope scope(isolate);
1350 DCHECK(args.length() == 3);
Emily Bernier958fae72015-03-24 16:35:39 -04001351 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001352 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1353 RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
Emily Bernier958fae72015-03-24 16:35:39 -04001354 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1355 RUNTIME_ASSERT(max_references >= 0);
1356
Ben Murdoch014dc512016-03-22 12:00:34 +00001357 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001358 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001359 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001360 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1361 // Get the constructor function for context extension and arguments array.
1362 Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1363 HeapObject* heap_obj;
1364 while ((heap_obj = iterator.next())) {
1365 if (!heap_obj->IsJSObject()) continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001366 JSObject* obj = JSObject::cast(heap_obj);
Ben Murdoch014dc512016-03-22 12:00:34 +00001367 if (obj->IsJSContextExtensionObject()) continue;
1368 if (obj->map()->GetConstructor() == arguments_fun) continue;
1369 if (!obj->ReferencesObject(*target)) continue;
1370 // Check filter if supplied. This is normally used to avoid
1371 // references from mirror objects.
1372 if (!filter->IsUndefined() &&
1373 HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
1374 continue;
Emily Bernier958fae72015-03-24 16:35:39 -04001375 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001376 if (obj->IsJSGlobalObject()) {
1377 obj = JSGlobalObject::cast(obj)->global_proxy();
1378 }
1379 instances.Add(Handle<JSObject>(obj));
1380 if (instances.length() == max_references) break;
1381 }
1382 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1383 while (iterator.next()) {
Emily Bernier958fae72015-03-24 16:35:39 -04001384 }
1385 }
1386
Ben Murdoch014dc512016-03-22 12:00:34 +00001387 Handle<FixedArray> result;
1388 if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1389 // Check for circular reference only. This can happen when the object is
1390 // only referenced from mirrors and has a circular reference in which case
1391 // the object is not really alive and would have been garbage collected if
1392 // not referenced from the mirror.
1393 result = isolate->factory()->empty_fixed_array();
1394 } else {
1395 result = isolate->factory()->NewFixedArray(instances.length());
1396 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1397 }
1398 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001399}
1400
1401
1402// Scan the heap for objects constructed by a specific function.
1403// args[0]: the constructor to find instances of
1404// args[1]: the the maximum number of objects to return
1405RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1406 HandleScope scope(isolate);
1407 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001408 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
1409 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
1410 RUNTIME_ASSERT(max_references >= 0);
1411
Ben Murdoch014dc512016-03-22 12:00:34 +00001412 List<Handle<JSObject> > instances;
Emily Bernier958fae72015-03-24 16:35:39 -04001413 Heap* heap = isolate->heap();
Emily Bernier958fae72015-03-24 16:35:39 -04001414 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001415 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1416 HeapObject* heap_obj;
1417 while ((heap_obj = iterator.next())) {
1418 if (!heap_obj->IsJSObject()) continue;
1419 JSObject* obj = JSObject::cast(heap_obj);
1420 if (obj->map()->GetConstructor() != *constructor) continue;
1421 instances.Add(Handle<JSObject>(obj));
1422 if (instances.length() == max_references) break;
1423 }
1424 // Iterate the rest of the heap to satisfy HeapIterator constraints.
1425 while (iterator.next()) {
1426 }
Emily Bernier958fae72015-03-24 16:35:39 -04001427 }
1428
Ben Murdoch014dc512016-03-22 12:00:34 +00001429 Handle<FixedArray> result =
1430 isolate->factory()->NewFixedArray(instances.length());
1431 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1432 return *isolate->factory()->NewJSArrayWithElements(result);
Emily Bernier958fae72015-03-24 16:35:39 -04001433}
1434
1435
1436// Find the effective prototype object as returned by __proto__.
1437// args[0]: the object to find the prototype for.
1438RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1439 HandleScope shs(isolate);
1440 DCHECK(args.length() == 1);
1441 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001442 Handle<Object> prototype;
1443 // TODO(1543): Come up with a solution for clients to handle potential errors
1444 // thrown by an intermediate proxy.
1445 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
1446 Object::GetPrototype(isolate, obj));
1447 return *prototype;
Emily Bernier958fae72015-03-24 16:35:39 -04001448}
1449
1450
1451// Patches script source (should be called upon BeforeCompile event).
1452RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1453 HandleScope scope(isolate);
1454 DCHECK(args.length() == 2);
1455
1456 CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1457 CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1458
1459 RUNTIME_ASSERT(script_wrapper->value()->IsScript());
1460 Handle<Script> script(Script::cast(script_wrapper->value()));
1461
1462 int compilation_state = script->compilation_state();
1463 RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
1464 script->set_source(*source);
1465
1466 return isolate->heap()->undefined_value();
1467}
1468
1469
Emily Bernier958fae72015-03-24 16:35:39 -04001470RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1471 SealHandleScope shs(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001472 DCHECK_EQ(1, args.length());
Emily Bernier958fae72015-03-24 16:35:39 -04001473
Ben Murdoch014dc512016-03-22 12:00:34 +00001474 CONVERT_ARG_CHECKED(Object, f, 0);
1475 if (f->IsJSFunction()) {
1476 return JSFunction::cast(f)->shared()->inferred_name();
1477 }
1478 return isolate->heap()->empty_string();
1479}
1480
1481
1482RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1483 HandleScope scope(isolate);
1484 DCHECK_EQ(1, args.length());
1485
1486 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1487
1488 if (function->IsJSBoundFunction()) {
1489 return Handle<JSBoundFunction>::cast(function)->name();
1490 }
1491 Handle<Object> name =
1492 JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
1493 return *name;
Emily Bernier958fae72015-03-24 16:35:39 -04001494}
1495
1496
1497// A testing entry. Returns statement position which is the closest to
1498// source_position.
1499RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
1500 HandleScope scope(isolate);
1501 CHECK(isolate->debug()->live_edit_enabled());
1502 DCHECK(args.length() == 2);
Ben Murdoch014dc512016-03-22 12:00:34 +00001503 RUNTIME_ASSERT(isolate->debug()->is_active());
Emily Bernier958fae72015-03-24 16:35:39 -04001504 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1505 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
1506
1507 Handle<Code> code(function->code(), isolate);
1508
1509 if (code->kind() != Code::FUNCTION &&
1510 code->kind() != Code::OPTIMIZED_FUNCTION) {
1511 return isolate->heap()->undefined_value();
1512 }
1513
1514 RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
1515 int closest_pc = 0;
1516 int distance = kMaxInt;
1517 while (!it.done()) {
1518 int statement_position = static_cast<int>(it.rinfo()->data());
1519 // Check if this break point is closer that what was previously found.
1520 if (source_position <= statement_position &&
1521 statement_position - source_position < distance) {
1522 closest_pc =
1523 static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1524 distance = statement_position - source_position;
1525 // Check whether we can't get any closer.
1526 if (distance == 0) break;
1527 }
1528 it.next();
1529 }
1530
1531 return Smi::FromInt(closest_pc);
1532}
1533
1534
1535// Calls specified function with or without entering the debugger.
1536// This is used in unit tests to run code as if debugger is entered or simply
1537// to have a stack with C++ frame in the middle.
1538RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1539 HandleScope scope(isolate);
Ben Murdoch014dc512016-03-22 12:00:34 +00001540 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001541 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
Emily Bernier958fae72015-03-24 16:35:39 -04001542
Ben Murdoch014dc512016-03-22 12:00:34 +00001543 DebugScope debug_scope(isolate->debug());
1544 if (debug_scope.failed()) {
1545 DCHECK(isolate->has_pending_exception());
1546 return isolate->heap()->exception();
Emily Bernier958fae72015-03-24 16:35:39 -04001547 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001548
Emily Bernier958fae72015-03-24 16:35:39 -04001549 Handle<Object> result;
Ben Murdoch014dc512016-03-22 12:00:34 +00001550 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1551 isolate, result,
1552 Execution::Call(isolate, function, handle(function->global_proxy()), 0,
1553 NULL));
Emily Bernier958fae72015-03-24 16:35:39 -04001554 return *result;
1555}
1556
1557
Ben Murdoch014dc512016-03-22 12:00:34 +00001558RUNTIME_FUNCTION(Runtime_GetDebugContext) {
1559 HandleScope scope(isolate);
1560 DCHECK(args.length() == 0);
1561 Handle<Context> context;
1562 {
1563 DebugScope debug_scope(isolate->debug());
1564 if (debug_scope.failed()) {
1565 DCHECK(isolate->has_pending_exception());
1566 return isolate->heap()->exception();
1567 }
1568 context = isolate->debug()->GetDebugContext();
1569 }
1570 if (context.is_null()) return isolate->heap()->undefined_value();
1571 context->set_security_token(isolate->native_context()->security_token());
1572 return context->global_proxy();
1573}
1574
1575
Emily Bernier958fae72015-03-24 16:35:39 -04001576// Performs a GC.
1577// Presently, it only does a full GC.
1578RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1579 SealHandleScope shs(isolate);
1580 DCHECK(args.length() == 1);
1581 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
1582 return isolate->heap()->undefined_value();
1583}
1584
1585
1586// Gets the current heap usage.
1587RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1588 SealHandleScope shs(isolate);
1589 DCHECK(args.length() == 0);
1590 int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1591 if (!Smi::IsValid(usage)) {
1592 return *isolate->factory()->NewNumberFromInt(usage);
1593 }
1594 return Smi::FromInt(usage);
1595}
1596
1597
1598// Finds the script object from the script data. NOTE: This operation uses
1599// heap traversal to find the function generated for the source position
1600// for the requested break point. For lazily compiled functions several heap
1601// traversals might be required rendering this operation as a rather slow
1602// operation. However for setting break points which is normally done through
1603// some kind of user interaction the performance is not crucial.
1604RUNTIME_FUNCTION(Runtime_GetScript) {
1605 HandleScope scope(isolate);
1606 DCHECK(args.length() == 1);
1607 CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1608
1609 Handle<Script> found;
Emily Bernier958fae72015-03-24 16:35:39 -04001610 {
Ben Murdoch014dc512016-03-22 12:00:34 +00001611 Script::Iterator iterator(isolate);
1612 Script* script = NULL;
1613 while ((script = iterator.Next()) != NULL) {
Emily Bernier958fae72015-03-24 16:35:39 -04001614 if (!script->name()->IsString()) continue;
1615 String* name = String::cast(script->name());
1616 if (name->Equals(*script_name)) {
1617 found = Handle<Script>(script, isolate);
1618 break;
1619 }
1620 }
1621 }
1622
Ben Murdoch014dc512016-03-22 12:00:34 +00001623 if (found.is_null()) return isolate->heap()->undefined_value();
Emily Bernier958fae72015-03-24 16:35:39 -04001624 return *Script::GetWrapper(found);
1625}
1626
1627
Emily Bernier958fae72015-03-24 16:35:39 -04001628// Set one shot breakpoints for the callback function that is passed to a
Ben Murdoch014dc512016-03-22 12:00:34 +00001629// built-in function such as Array.forEach to enable stepping into the callback,
1630// if we are indeed stepping and the callback is subject to debugging.
Emily Bernier958fae72015-03-24 16:35:39 -04001631RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
1632 DCHECK(args.length() == 1);
Emily Bernier958fae72015-03-24 16:35:39 -04001633 HandleScope scope(isolate);
1634 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1635 RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
1636 Handle<JSFunction> fun;
1637 if (object->IsJSFunction()) {
1638 fun = Handle<JSFunction>::cast(object);
1639 } else {
1640 fun = Handle<JSFunction>(
1641 Handle<JSGeneratorObject>::cast(object)->function(), isolate);
1642 }
Ben Murdoch014dc512016-03-22 12:00:34 +00001643
1644 isolate->debug()->PrepareStepIn(fun);
Emily Bernier958fae72015-03-24 16:35:39 -04001645 return isolate->heap()->undefined_value();
1646}
1647
1648
1649RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
Ben Murdoch014dc512016-03-22 12:00:34 +00001650 DCHECK(args.length() == 2);
Emily Bernier958fae72015-03-24 16:35:39 -04001651 HandleScope scope(isolate);
1652 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
Ben Murdoch014dc512016-03-22 12:00:34 +00001653 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
1654 isolate->PushPromise(promise, function);
1655 // If we are in step-in mode, flood the handler.
1656 isolate->debug()->EnableStepIn();
Emily Bernier958fae72015-03-24 16:35:39 -04001657 return isolate->heap()->undefined_value();
1658}
1659
1660
1661RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1662 DCHECK(args.length() == 0);
1663 SealHandleScope shs(isolate);
1664 isolate->PopPromise();
1665 return isolate->heap()->undefined_value();
1666}
1667
1668
1669RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) {
1670 DCHECK(args.length() == 1);
1671 HandleScope scope(isolate);
1672 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1673 isolate->debug()->OnPromiseEvent(data);
1674 return isolate->heap()->undefined_value();
1675}
1676
1677
1678RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1679 DCHECK(args.length() == 1);
1680 HandleScope scope(isolate);
1681 CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1682 isolate->debug()->OnAsyncTaskEvent(data);
1683 return isolate->heap()->undefined_value();
1684}
1685
1686
Ben Murdoch014dc512016-03-22 12:00:34 +00001687RUNTIME_FUNCTION(Runtime_DebugIsActive) {
Emily Bernier958fae72015-03-24 16:35:39 -04001688 SealHandleScope shs(isolate);
1689 return Smi::FromInt(isolate->debug()->is_active());
1690}
1691
1692
Ben Murdoch014dc512016-03-22 12:00:34 +00001693RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
Emily Bernier958fae72015-03-24 16:35:39 -04001694 UNIMPLEMENTED();
1695 return NULL;
1696}
Ben Murdoch014dc512016-03-22 12:00:34 +00001697} // namespace internal
1698} // namespace v8