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