1 // 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
5 #include "src/runtime/runtime-utils.h"
6
7 #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
16 namespace v8 {
17 namespace internal {
18
RUNTIME_FUNCTION(Runtime_DebugBreak)19 RUNTIME_FUNCTION(Runtime_DebugBreak) {
20 SealHandleScope shs(isolate);
21 DCHECK(args.length() == 0);
22 // Get the top-most JavaScript frame.
23 JavaScriptFrameIterator it(isolate);
24 isolate->debug()->Break(args, it.frame());
25 isolate->debug()->SetAfterBreakTarget(it.frame());
26 return isolate->heap()->undefined_value();
27 }
28
29
RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement)30 RUNTIME_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();
37 }
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
RUNTIME_FUNCTION(Runtime_SetDebugEventListener)44 RUNTIME_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
RUNTIME_FUNCTION(Runtime_ScheduleBreak)57 RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
58 SealHandleScope shs(isolate);
59 DCHECK(args.length() == 0);
60 isolate->stack_guard()->RequestDebugBreak();
61 return isolate->heap()->undefined_value();
62 }
63
64
DebugGetProperty(LookupIterator * it,bool * has_caught=NULL)65 static 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;
75 case LookupIterator::INTEGER_INDEXED_EXOTIC:
76 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 }
84 MaybeHandle<Object> maybe_result =
85 JSObject::GetPropertyWithAccessor(it, SLOPPY);
86 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
DebugGetProperty(Handle<Object> object,Handle<Name> name)104 static Handle<Object> DebugGetProperty(Handle<Object> object,
105 Handle<Name> name) {
106 LookupIterator it(object, name);
107 return DebugGetProperty(&it);
108 }
109
110
111 template <class IteratorType>
GetIteratorInternalProperties(Isolate * isolate,Handle<IteratorType> object)112 static 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
GetInternalProperties(Isolate * isolate,Handle<Object> object)152 MaybeHandle<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
RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties)261 RUNTIME_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
272 // 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.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails)279 RUNTIME_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;
301 // TODO(verwaest): Make sure DebugGetProperty can handle arrays, and remove
302 // this special case.
303 if (name->AsArrayIndex(&index)) {
304 Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
305 Handle<Object> element_or_char;
306 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element_or_char,
307 Object::GetElement(isolate, obj, index));
308 details->set(0, *element_or_char);
309 details->set(1, PropertyDetails::Empty().AsSmi());
310 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
331 ? PropertyDetails::Empty()
332 : 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
RUNTIME_FUNCTION(Runtime_DebugGetProperty)347 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails)362 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails)372 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails)382 RUNTIME_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
RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue)394 RUNTIME_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
RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue)411 RUNTIME_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;
418 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
419 Object::GetElement(isolate, obj, index));
420 return *result;
421 }
422
423
RUNTIME_FUNCTION(Runtime_CheckExecutionState)424 RUNTIME_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
RUNTIME_FUNCTION(Runtime_GetFrameCount)433 RUNTIME_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--) {
451 // Omit functions from native and extension scripts.
452 if (frames[i].function()->shared()->IsSubjectToDebugging()) n++;
453 }
454 }
455 return Smi::FromInt(n);
456 }
457
458
459 static const int kFrameDetailsFrameIdIndex = 0;
460 static const int kFrameDetailsReceiverIndex = 1;
461 static const int kFrameDetailsFunctionIndex = 2;
462 static const int kFrameDetailsArgumentCountIndex = 3;
463 static const int kFrameDetailsLocalCountIndex = 4;
464 static const int kFrameDetailsSourcePositionIndex = 5;
465 static const int kFrameDetailsConstructCallIndex = 6;
466 static const int kFrameDetailsAtReturnIndex = 7;
467 static const int kFrameDetailsFlagsIndex = 8;
468 static const int kFrameDetailsFirstDynamicIndex = 9;
469
470
471 // 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
RUNTIME_FUNCTION(Runtime_GetFrameDetails)488 RUNTIME_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.
506 int inlined_jsframe_index =
507 DebugFrameHelper::FindIndexedNonNativeFrame(&it, index);
508 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.
515 SaveContext* save =
516 DebugFrameHelper::FindSavedContextForFrame(isolate, it.frame());
517
518 // Get the frame id.
519 Handle<Object> frame_id(DebugFrameHelper::WrapFrameId(it.frame()->id()),
520 isolate);
521
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()));
530 RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging());
531 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).
705 Handle<Object> receiver(it.frame()->receiver(), isolate);
706 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.
714 if (receiver->IsUndefined()) {
715 receiver = handle(function->global_proxy());
716 } else {
717 Context* context = function->context();
718 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
RUNTIME_FUNCTION(Runtime_GetScopeCount)733 RUNTIME_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.
742 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
743 JavaScriptFrameIterator it(isolate, id);
744 JavaScriptFrame* frame = it.frame();
745 FrameInspector frame_inspector(frame, 0, isolate);
746
747 // Count the visible scopes.
748 int n = 0;
749 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
750 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.
RUNTIME_FUNCTION(Runtime_GetStepInPositions)760 RUNTIME_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.
769 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
770 JavaScriptFrameIterator frame_it(isolate, id);
771 RUNTIME_ASSERT(!frame_it.done());
772
773 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]));
779 }
780 return *factory->NewJSArrayWithElements(array, FAST_SMI_ELEMENTS);
781 }
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
RUNTIME_FUNCTION(Runtime_GetScopeDetails)793 RUNTIME_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.
804 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
805 JavaScriptFrameIterator frame_it(isolate, id);
806 JavaScriptFrame* frame = frame_it.frame();
807 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
808
809 // Find the requested scope.
810 int n = 0;
811 ScopeIterator it(isolate, &frame_inspector);
812 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,
820 it.MaterializeScopeDetails());
821 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
RUNTIME_FUNCTION(Runtime_GetAllScopesDetails)834 RUNTIME_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
843 ScopeIterator::Option option = ScopeIterator::DEFAULT;
844 if (args.length() == 4) {
845 CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
846 if (flag) option = ScopeIterator::IGNORE_NESTED_SCOPES;
847 }
848
849 // Get the frame where the debugging is performed.
850 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
851 JavaScriptFrameIterator frame_it(isolate, id);
852 JavaScriptFrame* frame = frame_it.frame();
853 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
854
855 List<Handle<JSObject> > result(4);
856 ScopeIterator it(isolate, &frame_inspector, option);
857 for (; !it.Done(); it.Next()) {
858 Handle<JSObject> details;
859 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
860 it.MaterializeScopeDetails());
861 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
RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount)872 RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
873 HandleScope scope(isolate);
874 DCHECK_EQ(1, args.length());
875
876 // Check arguments.
877 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
878
879 // Count the visible scopes.
880 int n = 0;
881 if (function->IsJSFunction()) {
882 for (ScopeIterator it(isolate, Handle<JSFunction>::cast(function));
883 !it.Done(); it.Next()) {
884 n++;
885 }
886 }
887
888 return Smi::FromInt(n);
889 }
890
891
RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails)892 RUNTIME_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,
912 it.MaterializeScopeDetails());
913 return *details;
914 }
915
916
SetScopeVariableValue(ScopeIterator * it,int index,Handle<String> variable_name,Handle<Object> new_value)917 static 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
RUNTIME_FUNCTION(Runtime_SetScopeVariableValue)939 RUNTIME_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.
957 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
958 JavaScriptFrameIterator frame_it(isolate, id);
959 JavaScriptFrame* frame = frame_it.frame();
960 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
961
962 ScopeIterator it(isolate, &frame_inspector);
963 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
RUNTIME_FUNCTION(Runtime_DebugPrintScopes)974 RUNTIME_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);
982 FrameInspector frame_inspector(frame, 0, isolate);
983
984 for (ScopeIterator it(isolate, &frame_inspector); !it.Done(); it.Next()) {
985 it.DebugPrint();
986 }
987 #endif
988 return isolate->heap()->undefined_value();
989 }
990
991
RUNTIME_FUNCTION(Runtime_GetThreadCount)992 RUNTIME_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
1010 static const int kThreadDetailsCurrentThreadIndex = 0;
1011 static const int kThreadDetailsThreadIdIndex = 1;
1012 static 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
RUNTIME_FUNCTION(Runtime_GetThreadDetails)1021 RUNTIME_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
RUNTIME_FUNCTION(Runtime_SetBreakPointsActive)1066 RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
1067 HandleScope scope(isolate);
1068 DCHECK(args.length() == 1);
1069 CONVERT_BOOLEAN_ARG_CHECKED(active, 0);
1070 isolate->debug()->set_break_points_active(active);
1071 return isolate->heap()->undefined_value();
1072 }
1073
1074
IsPositionAlignmentCodeCorrect(int alignment)1075 static bool IsPositionAlignmentCodeCorrect(int alignment) {
1076 return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1077 }
1078
1079
RUNTIME_FUNCTION(Runtime_GetBreakLocations)1080 RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1081 HandleScope scope(isolate);
1082 DCHECK(args.length() == 2);
1083 RUNTIME_ASSERT(isolate->debug()->is_active());
1084 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
RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint)1108 RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
1109 HandleScope scope(isolate);
1110 DCHECK(args.length() == 3);
1111 RUNTIME_ASSERT(isolate->debug()->is_active());
1112 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
RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint)1133 RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
1134 HandleScope scope(isolate);
1135 DCHECK(args.length() == 4);
1136 RUNTIME_ASSERT(isolate->debug()->is_active());
1137 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
RUNTIME_FUNCTION(Runtime_ClearBreakPoint)1165 RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
1166 HandleScope scope(isolate);
1167 DCHECK(args.length() == 1);
1168 RUNTIME_ASSERT(isolate->debug()->is_active());
1169 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.
RUNTIME_FUNCTION(Runtime_ChangeBreakOnException)1181 RUNTIME_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
RUNTIME_FUNCTION(Runtime_IsBreakOnException)1198 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_PrepareStep)1214 RUNTIME_FUNCTION(Runtime_PrepareStep) {
1215 HandleScope scope(isolate);
1216 DCHECK(args.length() == 2);
1217 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1218 RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1219
1220 if (!args[1]->IsNumber()) {
1221 return isolate->Throw(isolate->heap()->illegal_argument_string());
1222 }
1223
1224 // 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 &&
1227 step_action != StepOut && step_action != StepFrame) {
1228 return isolate->Throw(isolate->heap()->illegal_argument_string());
1229 }
1230
1231 // Clear all current stepping setup.
1232 isolate->debug()->ClearStepping();
1233
1234 // Prepare step.
1235 isolate->debug()->PrepareStep(static_cast<StepAction>(step_action));
1236 return isolate->heap()->undefined_value();
1237 }
1238
1239
1240 // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(Runtime_ClearStepping)1241 RUNTIME_FUNCTION(Runtime_ClearStepping) {
1242 HandleScope scope(isolate);
1243 DCHECK(args.length() == 0);
1244 RUNTIME_ASSERT(isolate->debug()->is_active());
1245 isolate->debug()->ClearStepping();
1246 return isolate->heap()->undefined_value();
1247 }
1248
1249
RUNTIME_FUNCTION(Runtime_DebugEvaluate)1250 RUNTIME_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);
1263 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 5);
1264
1265 StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
1266
1267 Handle<Object> result;
1268 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1269 isolate, result,
1270 DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
1271 disable_break, context_extension));
1272 return *result;
1273 }
1274
1275
RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal)1276 RUNTIME_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);
1287 CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
1288
1289 Handle<Object> result;
1290 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1291 isolate, result,
1292 DebugEvaluate::Global(isolate, source, disable_break, context_extension));
1293 return *result;
1294 }
1295
1296
RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts)1297 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
1298 HandleScope scope(isolate);
1299 DCHECK(args.length() == 0);
1300 RUNTIME_ASSERT(isolate->debug()->is_active());
1301
1302 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 }
1312
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
HasInPrototypeChainIgnoringProxies(Isolate * isolate,Object * object,Object * proto)1333 static 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;
1340 }
1341 }
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
RUNTIME_FUNCTION(Runtime_DebugReferencedBy)1348 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
1349 HandleScope scope(isolate);
1350 DCHECK(args.length() == 3);
1351 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
1352 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1353 RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
1354 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
1355 RUNTIME_ASSERT(max_references >= 0);
1356
1357 List<Handle<JSObject> > instances;
1358 Heap* heap = isolate->heap();
1359 {
1360 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;
1366 JSObject* obj = JSObject::cast(heap_obj);
1367 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;
1375 }
1376 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()) {
1384 }
1385 }
1386
1387 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);
1399 }
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
RUNTIME_FUNCTION(Runtime_DebugConstructedBy)1405 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
1406 HandleScope scope(isolate);
1407 DCHECK(args.length() == 2);
1408 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
1412 List<Handle<JSObject> > instances;
1413 Heap* heap = isolate->heap();
1414 {
1415 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 }
1427 }
1428
1429 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);
1433 }
1434
1435
1436 // Find the effective prototype object as returned by __proto__.
1437 // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(Runtime_DebugGetPrototype)1438 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
1439 HandleScope shs(isolate);
1440 DCHECK(args.length() == 1);
1441 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1442 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;
1448 }
1449
1450
1451 // Patches script source (should be called upon BeforeCompile event).
RUNTIME_FUNCTION(Runtime_DebugSetScriptSource)1452 RUNTIME_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
RUNTIME_FUNCTION(Runtime_FunctionGetInferredName)1470 RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
1471 SealHandleScope shs(isolate);
1472 DCHECK_EQ(1, args.length());
1473
1474 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
RUNTIME_FUNCTION(Runtime_FunctionGetDebugName)1482 RUNTIME_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;
1494 }
1495
1496
1497 // A testing entry. Returns statement position which is the closest to
1498 // source_position.
RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource)1499 RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
1500 HandleScope scope(isolate);
1501 CHECK(isolate->debug()->live_edit_enabled());
1502 DCHECK(args.length() == 2);
1503 RUNTIME_ASSERT(isolate->debug()->is_active());
1504 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.
RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext)1538 RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
1539 HandleScope scope(isolate);
1540 DCHECK(args.length() == 1);
1541 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
1542
1543 DebugScope debug_scope(isolate->debug());
1544 if (debug_scope.failed()) {
1545 DCHECK(isolate->has_pending_exception());
1546 return isolate->heap()->exception();
1547 }
1548
1549 Handle<Object> result;
1550 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1551 isolate, result,
1552 Execution::Call(isolate, function, handle(function->global_proxy()), 0,
1553 NULL));
1554 return *result;
1555 }
1556
1557
RUNTIME_FUNCTION(Runtime_GetDebugContext)1558 RUNTIME_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
1576 // Performs a GC.
1577 // Presently, it only does a full GC.
RUNTIME_FUNCTION(Runtime_CollectGarbage)1578 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_GetHeapUsage)1587 RUNTIME_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.
RUNTIME_FUNCTION(Runtime_GetScript)1604 RUNTIME_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;
1610 {
1611 Script::Iterator iterator(isolate);
1612 Script* script = NULL;
1613 while ((script = iterator.Next()) != NULL) {
1614 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
1623 if (found.is_null()) return isolate->heap()->undefined_value();
1624 return *Script::GetWrapper(found);
1625 }
1626
1627
1628 // Set one shot breakpoints for the callback function that is passed to a
1629 // 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.
RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping)1631 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
1632 DCHECK(args.length() == 1);
1633 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 }
1643
1644 isolate->debug()->PrepareStepIn(fun);
1645 return isolate->heap()->undefined_value();
1646 }
1647
1648
RUNTIME_FUNCTION(Runtime_DebugPushPromise)1649 RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
1650 DCHECK(args.length() == 2);
1651 HandleScope scope(isolate);
1652 CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
1653 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();
1657 return isolate->heap()->undefined_value();
1658 }
1659
1660
RUNTIME_FUNCTION(Runtime_DebugPopPromise)1661 RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1662 DCHECK(args.length() == 0);
1663 SealHandleScope shs(isolate);
1664 isolate->PopPromise();
1665 return isolate->heap()->undefined_value();
1666 }
1667
1668
RUNTIME_FUNCTION(Runtime_DebugPromiseEvent)1669 RUNTIME_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
RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent)1678 RUNTIME_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
RUNTIME_FUNCTION(Runtime_DebugIsActive)1687 RUNTIME_FUNCTION(Runtime_DebugIsActive) {
1688 SealHandleScope shs(isolate);
1689 return Smi::FromInt(isolate->debug()->is_active());
1690 }
1691
1692
RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode)1693 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
1694 UNIMPLEMENTED();
1695 return NULL;
1696 }
1697 } // namespace internal
1698 } // namespace v8
1699