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
16namespace v8 {
17namespace internal {
18
19RUNTIME_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
30RUNTIME_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
44RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
45  SealHandleScope shs(isolate);
46  DCHECK(args.length() == 2);
47  RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
48                 args[0]->IsNull());
49  CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
50  CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
51  isolate->debug()->SetEventListener(callback, data);
52
53  return isolate->heap()->undefined_value();
54}
55
56
57RUNTIME_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
65static Handle<Object> DebugGetProperty(LookupIterator* it,
66                                       bool* has_caught = NULL) {
67  for (; it->IsFound(); it->Next()) {
68    switch (it->state()) {
69      case LookupIterator::NOT_FOUND:
70      case LookupIterator::TRANSITION:
71        UNREACHABLE();
72      case LookupIterator::ACCESS_CHECK:
73        // Ignore access checks.
74        break;
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
104static Handle<Object> DebugGetProperty(Handle<Object> object,
105                                       Handle<Name> name) {
106  LookupIterator it(object, name);
107  return DebugGetProperty(&it);
108}
109
110
111template <class IteratorType>
112static MaybeHandle<JSArray> GetIteratorInternalProperties(
113    Isolate* isolate, Handle<IteratorType> object) {
114  Factory* factory = isolate->factory();
115  Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
116  RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
117  const char* kind = NULL;
118  switch (Smi::cast(iterator->kind())->value()) {
119    case IteratorType::kKindKeys:
120      kind = "keys";
121      break;
122    case IteratorType::kKindValues:
123      kind = "values";
124      break;
125    case IteratorType::kKindEntries:
126      kind = "entries";
127      break;
128    default:
129      RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
130  }
131
132  Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
133  Handle<String> has_more =
134      factory->NewStringFromAsciiChecked("[[IteratorHasMore]]");
135  result->set(0, *has_more);
136  result->set(1, isolate->heap()->ToBoolean(iterator->HasMore()));
137
138  Handle<String> index =
139      factory->NewStringFromAsciiChecked("[[IteratorIndex]]");
140  result->set(2, *index);
141  result->set(3, iterator->index());
142
143  Handle<String> iterator_kind =
144      factory->NewStringFromAsciiChecked("[[IteratorKind]]");
145  result->set(4, *iterator_kind);
146  Handle<String> kind_str = factory->NewStringFromAsciiChecked(kind);
147  result->set(5, *kind_str);
148  return factory->NewJSArrayWithElements(result);
149}
150
151
152MaybeHandle<JSArray> Runtime::GetInternalProperties(Isolate* isolate,
153                                                    Handle<Object> object) {
154  Factory* factory = isolate->factory();
155  if (object->IsJSBoundFunction()) {
156    Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object);
157
158    Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
159    Handle<String> target =
160        factory->NewStringFromAsciiChecked("[[TargetFunction]]");
161    result->set(0, *target);
162    result->set(1, function->bound_target_function());
163
164    Handle<String> bound_this =
165        factory->NewStringFromAsciiChecked("[[BoundThis]]");
166    result->set(2, *bound_this);
167    result->set(3, function->bound_this());
168
169    Handle<String> bound_args =
170        factory->NewStringFromAsciiChecked("[[BoundArgs]]");
171    result->set(4, *bound_args);
172    Handle<FixedArray> bound_arguments =
173        factory->CopyFixedArray(handle(function->bound_arguments(), isolate));
174    Handle<JSArray> arguments_array =
175        factory->NewJSArrayWithElements(bound_arguments);
176    result->set(5, *arguments_array);
177    return factory->NewJSArrayWithElements(result);
178  } else if (object->IsJSMapIterator()) {
179    Handle<JSMapIterator> iterator = Handle<JSMapIterator>::cast(object);
180    return GetIteratorInternalProperties(isolate, iterator);
181  } else if (object->IsJSSetIterator()) {
182    Handle<JSSetIterator> iterator = Handle<JSSetIterator>::cast(object);
183    return GetIteratorInternalProperties(isolate, iterator);
184  } else if (object->IsJSGeneratorObject()) {
185    Handle<JSGeneratorObject> generator =
186        Handle<JSGeneratorObject>::cast(object);
187
188    const char* status = "suspended";
189    if (generator->is_closed()) {
190      status = "closed";
191    } else if (generator->is_executing()) {
192      status = "running";
193    } else {
194      DCHECK(generator->is_suspended());
195    }
196
197    Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
198    Handle<String> generator_status =
199        factory->NewStringFromAsciiChecked("[[GeneratorStatus]]");
200    result->set(0, *generator_status);
201    Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
202    result->set(1, *status_str);
203
204    Handle<String> function =
205        factory->NewStringFromAsciiChecked("[[GeneratorFunction]]");
206    result->set(2, *function);
207    result->set(3, generator->function());
208
209    Handle<String> receiver =
210        factory->NewStringFromAsciiChecked("[[GeneratorReceiver]]");
211    result->set(4, *receiver);
212    result->set(5, generator->receiver());
213    return factory->NewJSArrayWithElements(result);
214  } else if (Object::IsPromise(object)) {
215    Handle<JSObject> promise = Handle<JSObject>::cast(object);
216
217    Handle<Object> status_obj =
218        DebugGetProperty(promise, isolate->factory()->promise_status_symbol());
219    RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
220    const char* status = "rejected";
221    int status_val = Handle<Smi>::cast(status_obj)->value();
222    switch (status_val) {
223      case +1:
224        status = "resolved";
225        break;
226      case 0:
227        status = "pending";
228        break;
229      default:
230        DCHECK_EQ(-1, status_val);
231    }
232
233    Handle<FixedArray> result = factory->NewFixedArray(2 * 2);
234    Handle<String> promise_status =
235        factory->NewStringFromAsciiChecked("[[PromiseStatus]]");
236    result->set(0, *promise_status);
237    Handle<String> status_str = factory->NewStringFromAsciiChecked(status);
238    result->set(1, *status_str);
239
240    Handle<Object> value_obj =
241        DebugGetProperty(promise, isolate->factory()->promise_value_symbol());
242    Handle<String> promise_value =
243        factory->NewStringFromAsciiChecked("[[PromiseValue]]");
244    result->set(2, *promise_value);
245    result->set(3, *value_obj);
246    return factory->NewJSArrayWithElements(result);
247  } else if (object->IsJSValue()) {
248    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
249
250    Handle<FixedArray> result = factory->NewFixedArray(2);
251    Handle<String> primitive_value =
252        factory->NewStringFromAsciiChecked("[[PrimitiveValue]]");
253    result->set(0, *primitive_value);
254    result->set(1, js_value->value());
255    return factory->NewJSArrayWithElements(result);
256  }
257  return factory->NewJSArray(0);
258}
259
260
261RUNTIME_FUNCTION(Runtime_DebugGetInternalProperties) {
262  HandleScope scope(isolate);
263  DCHECK(args.length() == 1);
264  CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
265  Handle<JSArray> result;
266  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
267      isolate, result, Runtime::GetInternalProperties(isolate, obj));
268  return *result;
269}
270
271
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.
279RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
280  HandleScope scope(isolate);
281
282  DCHECK(args.length() == 2);
283
284  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
285  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
286
287  // Make sure to set the current context to the context before the debugger was
288  // entered (if the debugger is entered). The reason for switching context here
289  // is that for some property lookups (accessors and interceptors) callbacks
290  // into the embedding application can occour, and the embedding application
291  // could have the assumption that its own native context is the current
292  // context and not some internal debugger context.
293  SaveContext save(isolate);
294  if (isolate->debug()->in_debug_scope()) {
295    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
296  }
297
298  // Check if the name is trivially convertible to an index and get the element
299  // if so.
300  uint32_t index;
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
347RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
348  HandleScope scope(isolate);
349
350  DCHECK(args.length() == 2);
351
352  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
353  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
354
355  LookupIterator it(obj, name);
356  return *DebugGetProperty(&it);
357}
358
359
360// Return the property type calculated from the property details.
361// args[0]: smi with property details.
362RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
363  SealHandleScope shs(isolate);
364  DCHECK(args.length() == 1);
365  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
366  return Smi::FromInt(static_cast<int>(details.type()));
367}
368
369
370// Return the property attribute calculated from the property details.
371// args[0]: smi with property details.
372RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
373  SealHandleScope shs(isolate);
374  DCHECK(args.length() == 1);
375  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
376  return Smi::FromInt(static_cast<int>(details.attributes()));
377}
378
379
380// Return the property insertion index calculated from the property details.
381// args[0]: smi with property details.
382RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
383  SealHandleScope shs(isolate);
384  DCHECK(args.length() == 1);
385  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
386  // TODO(verwaest): Works only for dictionary mode holders.
387  return Smi::FromInt(details.dictionary_index());
388}
389
390
391// Return property value from named interceptor.
392// args[0]: object
393// args[1]: property name
394RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
395  HandleScope scope(isolate);
396  DCHECK(args.length() == 2);
397  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
398  RUNTIME_ASSERT(obj->HasNamedInterceptor());
399  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
400
401  Handle<Object> result;
402  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
403                                     JSObject::GetProperty(obj, name));
404  return *result;
405}
406
407
408// Return element value from indexed interceptor.
409// args[0]: object
410// args[1]: index
411RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
412  HandleScope scope(isolate);
413  DCHECK(args.length() == 2);
414  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
415  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
416  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
417  Handle<Object> result;
418  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
419                                     Object::GetElement(isolate, obj, index));
420  return *result;
421}
422
423
424RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
425  SealHandleScope shs(isolate);
426  DCHECK(args.length() == 1);
427  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
428  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
429  return isolate->heap()->true_value();
430}
431
432
433RUNTIME_FUNCTION(Runtime_GetFrameCount) {
434  HandleScope scope(isolate);
435  DCHECK(args.length() == 1);
436  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
437  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
438
439  // Count all frames which are relevant to debugging stack trace.
440  int n = 0;
441  StackFrame::Id id = isolate->debug()->break_frame_id();
442  if (id == StackFrame::NO_ID) {
443    // If there is no JavaScript stack frame count is 0.
444    return Smi::FromInt(0);
445  }
446
447  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
448    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
449    it.frame()->Summarize(&frames);
450    for (int i = frames.length() - 1; i >= 0; i--) {
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
459static const int kFrameDetailsFrameIdIndex = 0;
460static const int kFrameDetailsReceiverIndex = 1;
461static const int kFrameDetailsFunctionIndex = 2;
462static const int kFrameDetailsArgumentCountIndex = 3;
463static const int kFrameDetailsLocalCountIndex = 4;
464static const int kFrameDetailsSourcePositionIndex = 5;
465static const int kFrameDetailsConstructCallIndex = 6;
466static const int kFrameDetailsAtReturnIndex = 7;
467static const int kFrameDetailsFlagsIndex = 8;
468static const int kFrameDetailsFirstDynamicIndex = 9;
469
470
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
488RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
489  HandleScope scope(isolate);
490  DCHECK(args.length() == 2);
491  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
492  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
493
494  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
495  Heap* heap = isolate->heap();
496
497  // Find the relevant frame with the requested index.
498  StackFrame::Id id = isolate->debug()->break_frame_id();
499  if (id == StackFrame::NO_ID) {
500    // If there are no JavaScript stack frames return undefined.
501    return heap->undefined_value();
502  }
503
504  JavaScriptFrameIterator it(isolate, id);
505  // Inlined frame index in optimized frame, starting from outer function.
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
733RUNTIME_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.
760RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
761  HandleScope scope(isolate);
762  DCHECK(args.length() == 2);
763  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
764  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
765
766  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
767
768  // Get the frame where the debugging is performed.
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
793RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
794  HandleScope scope(isolate);
795  DCHECK(args.length() == 4);
796  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
797  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
798
799  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
800  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
801  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
802
803  // Get the frame where the debugging is performed.
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
834RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
835  HandleScope scope(isolate);
836  DCHECK(args.length() == 3 || args.length() == 4);
837  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
838  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
839
840  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
841  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
842
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
872RUNTIME_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
892RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
893  HandleScope scope(isolate);
894  DCHECK(args.length() == 2);
895
896  // Check arguments.
897  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
898  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
899
900  // Find the requested scope.
901  int n = 0;
902  ScopeIterator it(isolate, fun);
903  for (; !it.Done() && n < index; it.Next()) {
904    n++;
905  }
906  if (it.Done()) {
907    return isolate->heap()->undefined_value();
908  }
909
910  Handle<JSObject> details;
911  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
912                                     it.MaterializeScopeDetails());
913  return *details;
914}
915
916
917static bool SetScopeVariableValue(ScopeIterator* it, int index,
918                                  Handle<String> variable_name,
919                                  Handle<Object> new_value) {
920  for (int n = 0; !it->Done() && n < index; it->Next()) {
921    n++;
922  }
923  if (it->Done()) {
924    return false;
925  }
926  return it->SetVariableValue(variable_name, new_value);
927}
928
929
930// Change variable value in closure or local scope
931// args[0]: number or JsFunction: break id or function
932// args[1]: number: frame index (when arg[0] is break id)
933// args[2]: number: inlined frame index (when arg[0] is break id)
934// args[3]: number: scope index
935// args[4]: string: variable name
936// args[5]: object: new value
937//
938// Return true if success and false otherwise
939RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
940  HandleScope scope(isolate);
941  DCHECK(args.length() == 6);
942
943  // Check arguments.
944  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
945  CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
946  CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
947
948  bool res;
949  if (args[0]->IsNumber()) {
950    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
951    RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
952
953    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
954    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
955
956    // Get the frame where the debugging is performed.
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
974RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
975  HandleScope scope(isolate);
976  DCHECK(args.length() == 0);
977
978#ifdef DEBUG
979  // Print the scopes for the top frame.
980  StackFrameLocator locator(isolate);
981  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
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
992RUNTIME_FUNCTION(Runtime_GetThreadCount) {
993  HandleScope scope(isolate);
994  DCHECK(args.length() == 1);
995  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
996  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
997
998  // Count all archived V8 threads.
999  int n = 0;
1000  for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1001       thread != NULL; thread = thread->Next()) {
1002    n++;
1003  }
1004
1005  // Total number of threads is current thread and archived threads.
1006  return Smi::FromInt(n + 1);
1007}
1008
1009
1010static const int kThreadDetailsCurrentThreadIndex = 0;
1011static const int kThreadDetailsThreadIdIndex = 1;
1012static const int kThreadDetailsSize = 2;
1013
1014// Return an array with thread details
1015// args[0]: number: break id
1016// args[1]: number: thread index
1017//
1018// The array returned contains the following information:
1019// 0: Is current thread?
1020// 1: Thread id
1021RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
1022  HandleScope scope(isolate);
1023  DCHECK(args.length() == 2);
1024  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1025  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1026
1027  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
1028
1029  // Allocate array for result.
1030  Handle<FixedArray> details =
1031      isolate->factory()->NewFixedArray(kThreadDetailsSize);
1032
1033  // Thread index 0 is current thread.
1034  if (index == 0) {
1035    // Fill the details.
1036    details->set(kThreadDetailsCurrentThreadIndex,
1037                 isolate->heap()->true_value());
1038    details->set(kThreadDetailsThreadIdIndex,
1039                 Smi::FromInt(ThreadId::Current().ToInteger()));
1040  } else {
1041    // Find the thread with the requested index.
1042    int n = 1;
1043    ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
1044    while (index != n && thread != NULL) {
1045      thread = thread->Next();
1046      n++;
1047    }
1048    if (thread == NULL) {
1049      return isolate->heap()->undefined_value();
1050    }
1051
1052    // Fill the details.
1053    details->set(kThreadDetailsCurrentThreadIndex,
1054                 isolate->heap()->false_value());
1055    details->set(kThreadDetailsThreadIdIndex,
1056                 Smi::FromInt(thread->id().ToInteger()));
1057  }
1058
1059  // Convert to JS array and return.
1060  return *isolate->factory()->NewJSArrayWithElements(details);
1061}
1062
1063
1064// Sets the disable break state
1065// args[0]: disable break state
1066RUNTIME_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
1075static bool IsPositionAlignmentCodeCorrect(int alignment) {
1076  return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
1077}
1078
1079
1080RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
1081  HandleScope scope(isolate);
1082  DCHECK(args.length() == 2);
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
1108RUNTIME_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
1133RUNTIME_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
1165RUNTIME_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.
1181RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
1182  HandleScope scope(isolate);
1183  DCHECK(args.length() == 2);
1184  CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1185  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
1186
1187  // If the number doesn't match an enum value, the ChangeBreakOnException
1188  // function will default to affecting caught exceptions.
1189  ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1190  // Update break point state.
1191  isolate->debug()->ChangeBreakOnException(type, enable);
1192  return isolate->heap()->undefined_value();
1193}
1194
1195
1196// Returns the state of break on exceptions
1197// args[0]: boolean indicating uncaught exceptions
1198RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
1199  HandleScope scope(isolate);
1200  DCHECK(args.length() == 1);
1201  CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
1202
1203  ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
1204  bool result = isolate->debug()->IsBreakOnException(type);
1205  return Smi::FromInt(result);
1206}
1207
1208
1209// Prepare for stepping
1210// args[0]: break id for checking execution state
1211// args[1]: step action from the enumeration StepAction
1212// args[2]: number of times to perform the step, for step out it is the number
1213//          of frames to step down.
1214RUNTIME_FUNCTION(Runtime_PrepareStep) {
1215  HandleScope scope(isolate);
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.
1241RUNTIME_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
1250RUNTIME_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
1276RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
1277  HandleScope scope(isolate);
1278
1279  // Check the execution state and decode arguments frame and source to be
1280  // evaluated.
1281  DCHECK(args.length() == 4);
1282  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
1283  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
1284
1285  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1286  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
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
1297RUNTIME_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
1333static 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
1348RUNTIME_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
1405RUNTIME_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.
1438RUNTIME_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).
1452RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
1453  HandleScope scope(isolate);
1454  DCHECK(args.length() == 2);
1455
1456  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
1457  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
1458
1459  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
1460  Handle<Script> script(Script::cast(script_wrapper->value()));
1461
1462  int compilation_state = script->compilation_state();
1463  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
1464  script->set_source(*source);
1465
1466  return isolate->heap()->undefined_value();
1467}
1468
1469
1470RUNTIME_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
1482RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
1483  HandleScope scope(isolate);
1484  DCHECK_EQ(1, args.length());
1485
1486  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
1487
1488  if (function->IsJSBoundFunction()) {
1489    return Handle<JSBoundFunction>::cast(function)->name();
1490  }
1491  Handle<Object> name =
1492      JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
1493  return *name;
1494}
1495
1496
1497// A testing entry. Returns statement position which is the closest to
1498// source_position.
1499RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
1500  HandleScope scope(isolate);
1501  CHECK(isolate->debug()->live_edit_enabled());
1502  DCHECK(args.length() == 2);
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.
1538RUNTIME_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
1558RUNTIME_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.
1578RUNTIME_FUNCTION(Runtime_CollectGarbage) {
1579  SealHandleScope shs(isolate);
1580  DCHECK(args.length() == 1);
1581  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
1582  return isolate->heap()->undefined_value();
1583}
1584
1585
1586// Gets the current heap usage.
1587RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
1588  SealHandleScope shs(isolate);
1589  DCHECK(args.length() == 0);
1590  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
1591  if (!Smi::IsValid(usage)) {
1592    return *isolate->factory()->NewNumberFromInt(usage);
1593  }
1594  return Smi::FromInt(usage);
1595}
1596
1597
1598// Finds the script object from the script data. NOTE: This operation uses
1599// heap traversal to find the function generated for the source position
1600// for the requested break point. For lazily compiled functions several heap
1601// traversals might be required rendering this operation as a rather slow
1602// operation. However for setting break points which is normally done through
1603// some kind of user interaction the performance is not crucial.
1604RUNTIME_FUNCTION(Runtime_GetScript) {
1605  HandleScope scope(isolate);
1606  DCHECK(args.length() == 1);
1607  CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
1608
1609  Handle<Script> found;
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.
1631RUNTIME_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
1649RUNTIME_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
1661RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
1662  DCHECK(args.length() == 0);
1663  SealHandleScope shs(isolate);
1664  isolate->PopPromise();
1665  return isolate->heap()->undefined_value();
1666}
1667
1668
1669RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) {
1670  DCHECK(args.length() == 1);
1671  HandleScope scope(isolate);
1672  CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1673  isolate->debug()->OnPromiseEvent(data);
1674  return isolate->heap()->undefined_value();
1675}
1676
1677
1678RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
1679  DCHECK(args.length() == 1);
1680  HandleScope scope(isolate);
1681  CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
1682  isolate->debug()->OnAsyncTaskEvent(data);
1683  return isolate->heap()->undefined_value();
1684}
1685
1686
1687RUNTIME_FUNCTION(Runtime_DebugIsActive) {
1688  SealHandleScope shs(isolate);
1689  return Smi::FromInt(isolate->debug()->is_active());
1690}
1691
1692
1693RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) {
1694  UNIMPLEMENTED();
1695  return NULL;
1696}
1697}  // namespace internal
1698}  // namespace v8
1699