1// Copyright 2012 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 <stdlib.h>
6#include <limits>
7
8#include "src/v8.h"
9
10#include "src/accessors.h"
11#include "src/allocation-site-scopes.h"
12#include "src/api.h"
13#include "src/arguments.h"
14#include "src/bailout-reason.h"
15#include "src/base/cpu.h"
16#include "src/base/platform/platform.h"
17#include "src/bootstrapper.h"
18#include "src/codegen.h"
19#include "src/compilation-cache.h"
20#include "src/compiler.h"
21#include "src/conversions.h"
22#include "src/cpu-profiler.h"
23#include "src/date.h"
24#include "src/dateparser-inl.h"
25#include "src/debug.h"
26#include "src/deoptimizer.h"
27#include "src/execution.h"
28#include "src/full-codegen.h"
29#include "src/global-handles.h"
30#include "src/isolate-inl.h"
31#include "src/json-parser.h"
32#include "src/json-stringifier.h"
33#include "src/jsregexp-inl.h"
34#include "src/jsregexp.h"
35#include "src/liveedit.h"
36#include "src/misc-intrinsics.h"
37#include "src/parser.h"
38#include "src/prototype.h"
39#include "src/runtime.h"
40#include "src/runtime-profiler.h"
41#include "src/scopeinfo.h"
42#include "src/smart-pointers.h"
43#include "src/string-search.h"
44#include "src/uri.h"
45#include "src/utils.h"
46#include "src/v8threads.h"
47#include "src/vm-state-inl.h"
48#include "third_party/fdlibm/fdlibm.h"
49
50#ifdef V8_I18N_SUPPORT
51#include "src/i18n.h"
52#include "unicode/brkiter.h"
53#include "unicode/calendar.h"
54#include "unicode/coll.h"
55#include "unicode/curramt.h"
56#include "unicode/datefmt.h"
57#include "unicode/dcfmtsym.h"
58#include "unicode/decimfmt.h"
59#include "unicode/dtfmtsym.h"
60#include "unicode/dtptngen.h"
61#include "unicode/locid.h"
62#include "unicode/numfmt.h"
63#include "unicode/numsys.h"
64#include "unicode/rbbi.h"
65#include "unicode/smpdtfmt.h"
66#include "unicode/timezone.h"
67#include "unicode/uchar.h"
68#include "unicode/ucol.h"
69#include "unicode/ucurr.h"
70#include "unicode/uloc.h"
71#include "unicode/unum.h"
72#include "unicode/uversion.h"
73#endif
74
75#ifndef _STLP_VENDOR_CSTD
76// STLPort doesn't import fpclassify and isless into the std namespace.
77using std::fpclassify;
78using std::isless;
79#endif
80
81namespace v8 {
82namespace internal {
83
84
85#define RUNTIME_ASSERT(value) \
86  if (!(value)) return isolate->ThrowIllegalOperation();
87
88#define RUNTIME_ASSERT_HANDLIFIED(value, T)                          \
89  if (!(value)) {                                                    \
90    isolate->ThrowIllegalOperation();                                \
91    return MaybeHandle<T>();                                         \
92  }
93
94// Cast the given object to a value of the specified type and store
95// it in a variable with the given name.  If the object is not of the
96// expected type call IllegalOperation and return.
97#define CONVERT_ARG_CHECKED(Type, name, index)                       \
98  RUNTIME_ASSERT(args[index]->Is##Type());                           \
99  Type* name = Type::cast(args[index]);
100
101#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
102  RUNTIME_ASSERT(args[index]->Is##Type());                           \
103  Handle<Type> name = args.at<Type>(index);
104
105#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index)               \
106  RUNTIME_ASSERT(args[index]->IsNumber());                           \
107  Handle<Object> name = args.at<Object>(index);
108
109// Cast the given object to a boolean and store it in a variable with
110// the given name.  If the object is not a boolean call IllegalOperation
111// and return.
112#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
113  RUNTIME_ASSERT(args[index]->IsBoolean());                          \
114  bool name = args[index]->IsTrue();
115
116// Cast the given argument to a Smi and store its value in an int variable
117// with the given name.  If the argument is not a Smi call IllegalOperation
118// and return.
119#define CONVERT_SMI_ARG_CHECKED(name, index)                         \
120  RUNTIME_ASSERT(args[index]->IsSmi());                              \
121  int name = args.smi_at(index);
122
123// Cast the given argument to a double and store it in a variable with
124// the given name.  If the argument is not a number (as opposed to
125// the number not-a-number) call IllegalOperation and return.
126#define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
127  RUNTIME_ASSERT(args[index]->IsNumber());                           \
128  double name = args.number_at(index);
129
130// Call the specified converter on the object *comand store the result in
131// a variable of the specified type with the given name.  If the
132// object is not a Number call IllegalOperation and return.
133#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
134  RUNTIME_ASSERT(obj->IsNumber());                                   \
135  type name = NumberTo##Type(obj);
136
137
138// Cast the given argument to PropertyDetails and store its value in a
139// variable with the given name.  If the argument is not a Smi call
140// IllegalOperation and return.
141#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
142  RUNTIME_ASSERT(args[index]->IsSmi());                              \
143  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
144
145
146// Assert that the given argument has a valid value for a StrictMode
147// and store it in a StrictMode variable with the given name.
148#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
149  RUNTIME_ASSERT(args[index]->IsSmi());                              \
150  RUNTIME_ASSERT(args.smi_at(index) == STRICT ||                     \
151                 args.smi_at(index) == SLOPPY);                      \
152  StrictMode name = static_cast<StrictMode>(args.smi_at(index));
153
154
155// Assert that the given argument is a number within the Int32 range
156// and convert it to int32_t.  If the argument is not an Int32 call
157// IllegalOperation and return.
158#define CONVERT_INT32_ARG_CHECKED(name, index)                       \
159  RUNTIME_ASSERT(args[index]->IsNumber());                           \
160  int32_t name = 0;                                                  \
161  RUNTIME_ASSERT(args[index]->ToInt32(&name));
162
163
164static Handle<Map> ComputeObjectLiteralMap(
165    Handle<Context> context,
166    Handle<FixedArray> constant_properties,
167    bool* is_result_from_cache) {
168  Isolate* isolate = context->GetIsolate();
169  int properties_length = constant_properties->length();
170  int number_of_properties = properties_length / 2;
171  // Check that there are only internal strings and array indices among keys.
172  int number_of_string_keys = 0;
173  for (int p = 0; p != properties_length; p += 2) {
174    Object* key = constant_properties->get(p);
175    uint32_t element_index = 0;
176    if (key->IsInternalizedString()) {
177      number_of_string_keys++;
178    } else if (key->ToArrayIndex(&element_index)) {
179      // An index key does not require space in the property backing store.
180      number_of_properties--;
181    } else {
182      // Bail out as a non-internalized-string non-index key makes caching
183      // impossible.
184      // DCHECK to make sure that the if condition after the loop is false.
185      DCHECK(number_of_string_keys != number_of_properties);
186      break;
187    }
188  }
189  // If we only have internalized strings and array indices among keys then we
190  // can use the map cache in the native context.
191  const int kMaxKeys = 10;
192  if ((number_of_string_keys == number_of_properties) &&
193      (number_of_string_keys < kMaxKeys)) {
194    // Create the fixed array with the key.
195    Handle<FixedArray> keys =
196        isolate->factory()->NewFixedArray(number_of_string_keys);
197    if (number_of_string_keys > 0) {
198      int index = 0;
199      for (int p = 0; p < properties_length; p += 2) {
200        Object* key = constant_properties->get(p);
201        if (key->IsInternalizedString()) {
202          keys->set(index++, key);
203        }
204      }
205      DCHECK(index == number_of_string_keys);
206    }
207    *is_result_from_cache = true;
208    return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
209  }
210  *is_result_from_cache = false;
211  return Map::Create(isolate, number_of_properties);
212}
213
214
215MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
216    Isolate* isolate,
217    Handle<FixedArray> literals,
218    Handle<FixedArray> constant_properties);
219
220
221MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
222    Isolate* isolate,
223    Handle<FixedArray> literals,
224    Handle<FixedArray> constant_properties,
225    bool should_have_fast_elements,
226    bool has_function_literal) {
227  // Get the native context from the literals array.  This is the
228  // context in which the function was created and we use the object
229  // function from this context to create the object literal.  We do
230  // not use the object function from the current native context
231  // because this might be the object function from another context
232  // which we should not have access to.
233  Handle<Context> context =
234      Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
235
236  // In case we have function literals, we want the object to be in
237  // slow properties mode for now. We don't go in the map cache because
238  // maps with constant functions can't be shared if the functions are
239  // not the same (which is the common case).
240  bool is_result_from_cache = false;
241  Handle<Map> map = has_function_literal
242      ? Handle<Map>(context->object_function()->initial_map())
243      : ComputeObjectLiteralMap(context,
244                                constant_properties,
245                                &is_result_from_cache);
246
247  PretenureFlag pretenure_flag =
248      isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
249
250  Handle<JSObject> boilerplate =
251      isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
252
253  // Normalize the elements of the boilerplate to save space if needed.
254  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
255
256  // Add the constant properties to the boilerplate.
257  int length = constant_properties->length();
258  bool should_transform =
259      !is_result_from_cache && boilerplate->HasFastProperties();
260  bool should_normalize = should_transform || has_function_literal;
261  if (should_normalize) {
262    // TODO(verwaest): We might not want to ever normalize here.
263    JSObject::NormalizeProperties(
264        boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
265  }
266  // TODO(verwaest): Support tracking representations in the boilerplate.
267  for (int index = 0; index < length; index +=2) {
268    Handle<Object> key(constant_properties->get(index+0), isolate);
269    Handle<Object> value(constant_properties->get(index+1), isolate);
270    if (value->IsFixedArray()) {
271      // The value contains the constant_properties of a
272      // simple object or array literal.
273      Handle<FixedArray> array = Handle<FixedArray>::cast(value);
274      ASSIGN_RETURN_ON_EXCEPTION(
275          isolate, value,
276          CreateLiteralBoilerplate(isolate, literals, array),
277          Object);
278    }
279    MaybeHandle<Object> maybe_result;
280    uint32_t element_index = 0;
281    if (key->IsInternalizedString()) {
282      if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
283        // Array index as string (uint32).
284        if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate);
285        maybe_result =
286            JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY);
287      } else {
288        Handle<String> name(String::cast(*key));
289        DCHECK(!name->AsArrayIndex(&element_index));
290        maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
291            boilerplate, name, value, NONE);
292      }
293    } else if (key->ToArrayIndex(&element_index)) {
294      // Array index (uint32).
295      if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate);
296      maybe_result =
297          JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY);
298    } else {
299      // Non-uint32 number.
300      DCHECK(key->IsNumber());
301      double num = key->Number();
302      char arr[100];
303      Vector<char> buffer(arr, arraysize(arr));
304      const char* str = DoubleToCString(num, buffer);
305      Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
306      maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name,
307                                                              value, NONE);
308    }
309    // If setting the property on the boilerplate throws an
310    // exception, the exception is converted to an empty handle in
311    // the handle based operations.  In that case, we need to
312    // convert back to an exception.
313    RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
314  }
315
316  // Transform to fast properties if necessary. For object literals with
317  // containing function literals we defer this operation until after all
318  // computed properties have been assigned so that we can generate
319  // constant function properties.
320  if (should_transform && !has_function_literal) {
321    JSObject::MigrateSlowToFast(
322        boilerplate, boilerplate->map()->unused_property_fields());
323  }
324
325  return boilerplate;
326}
327
328
329MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
330    Handle<Object> object,
331    ElementsKind to_kind,
332    Isolate* isolate) {
333  HandleScope scope(isolate);
334  if (!object->IsJSObject()) {
335    isolate->ThrowIllegalOperation();
336    return MaybeHandle<Object>();
337  }
338  ElementsKind from_kind =
339      Handle<JSObject>::cast(object)->map()->elements_kind();
340  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
341    JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
342    return object;
343  }
344  isolate->ThrowIllegalOperation();
345  return MaybeHandle<Object>();
346}
347
348
349MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
350    Isolate* isolate,
351    Handle<FixedArray> literals,
352    Handle<FixedArray> elements) {
353  // Create the JSArray.
354  Handle<JSFunction> constructor(
355      JSFunction::NativeContextFromLiterals(*literals)->array_function());
356
357  PretenureFlag pretenure_flag =
358      isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
359
360  Handle<JSArray> object = Handle<JSArray>::cast(
361      isolate->factory()->NewJSObject(constructor, pretenure_flag));
362
363  ElementsKind constant_elements_kind =
364      static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
365  Handle<FixedArrayBase> constant_elements_values(
366      FixedArrayBase::cast(elements->get(1)));
367
368  { DisallowHeapAllocation no_gc;
369    DCHECK(IsFastElementsKind(constant_elements_kind));
370    Context* native_context = isolate->context()->native_context();
371    Object* maps_array = native_context->js_array_maps();
372    DCHECK(!maps_array->IsUndefined());
373    Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind);
374    object->set_map(Map::cast(map));
375  }
376
377  Handle<FixedArrayBase> copied_elements_values;
378  if (IsFastDoubleElementsKind(constant_elements_kind)) {
379    copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
380        Handle<FixedDoubleArray>::cast(constant_elements_values));
381  } else {
382    DCHECK(IsFastSmiOrObjectElementsKind(constant_elements_kind));
383    const bool is_cow =
384        (constant_elements_values->map() ==
385         isolate->heap()->fixed_cow_array_map());
386    if (is_cow) {
387      copied_elements_values = constant_elements_values;
388#if DEBUG
389      Handle<FixedArray> fixed_array_values =
390          Handle<FixedArray>::cast(copied_elements_values);
391      for (int i = 0; i < fixed_array_values->length(); i++) {
392        DCHECK(!fixed_array_values->get(i)->IsFixedArray());
393      }
394#endif
395    } else {
396      Handle<FixedArray> fixed_array_values =
397          Handle<FixedArray>::cast(constant_elements_values);
398      Handle<FixedArray> fixed_array_values_copy =
399          isolate->factory()->CopyFixedArray(fixed_array_values);
400      copied_elements_values = fixed_array_values_copy;
401      for (int i = 0; i < fixed_array_values->length(); i++) {
402        if (fixed_array_values->get(i)->IsFixedArray()) {
403          // The value contains the constant_properties of a
404          // simple object or array literal.
405          Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
406          Handle<Object> result;
407          ASSIGN_RETURN_ON_EXCEPTION(
408              isolate, result,
409              CreateLiteralBoilerplate(isolate, literals, fa),
410              Object);
411          fixed_array_values_copy->set(i, *result);
412        }
413      }
414    }
415  }
416  object->set_elements(*copied_elements_values);
417  object->set_length(Smi::FromInt(copied_elements_values->length()));
418
419  JSObject::ValidateElements(object);
420  return object;
421}
422
423
424MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
425    Isolate* isolate,
426    Handle<FixedArray> literals,
427    Handle<FixedArray> array) {
428  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
429  const bool kHasNoFunctionLiteral = false;
430  switch (CompileTimeValue::GetLiteralType(array)) {
431    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
432      return CreateObjectLiteralBoilerplate(isolate,
433                                            literals,
434                                            elements,
435                                            true,
436                                            kHasNoFunctionLiteral);
437    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
438      return CreateObjectLiteralBoilerplate(isolate,
439                                            literals,
440                                            elements,
441                                            false,
442                                            kHasNoFunctionLiteral);
443    case CompileTimeValue::ARRAY_LITERAL:
444      return Runtime::CreateArrayLiteralBoilerplate(
445          isolate, literals, elements);
446    default:
447      UNREACHABLE();
448      return MaybeHandle<Object>();
449  }
450}
451
452
453RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
454  HandleScope scope(isolate);
455  DCHECK(args.length() == 4);
456  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
457  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
458  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
459  CONVERT_SMI_ARG_CHECKED(flags, 3);
460  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
461  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
462
463  RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
464
465  // Check if boilerplate exists. If not, create it first.
466  Handle<Object> literal_site(literals->get(literals_index), isolate);
467  Handle<AllocationSite> site;
468  Handle<JSObject> boilerplate;
469  if (*literal_site == isolate->heap()->undefined_value()) {
470    Handle<Object> raw_boilerplate;
471    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
472        isolate, raw_boilerplate,
473        CreateObjectLiteralBoilerplate(
474            isolate,
475            literals,
476            constant_properties,
477            should_have_fast_elements,
478            has_function_literal));
479    boilerplate = Handle<JSObject>::cast(raw_boilerplate);
480
481    AllocationSiteCreationContext creation_context(isolate);
482    site = creation_context.EnterNewScope();
483    RETURN_FAILURE_ON_EXCEPTION(
484        isolate,
485        JSObject::DeepWalk(boilerplate, &creation_context));
486    creation_context.ExitScope(site, boilerplate);
487
488    // Update the functions literal and return the boilerplate.
489    literals->set(literals_index, *site);
490  } else {
491    site = Handle<AllocationSite>::cast(literal_site);
492    boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
493                                   isolate);
494  }
495
496  AllocationSiteUsageContext usage_context(isolate, site, true);
497  usage_context.EnterNewScope();
498  MaybeHandle<Object> maybe_copy = JSObject::DeepCopy(
499      boilerplate, &usage_context);
500  usage_context.ExitScope(site, boilerplate);
501  Handle<Object> copy;
502  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy);
503  return *copy;
504}
505
506
507MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
508    Isolate* isolate,
509    Handle<FixedArray> literals,
510    int literals_index,
511    Handle<FixedArray> elements) {
512  // Check if boilerplate exists. If not, create it first.
513  Handle<Object> literal_site(literals->get(literals_index), isolate);
514  Handle<AllocationSite> site;
515  if (*literal_site == isolate->heap()->undefined_value()) {
516    DCHECK(*elements != isolate->heap()->empty_fixed_array());
517    Handle<Object> boilerplate;
518    ASSIGN_RETURN_ON_EXCEPTION(
519        isolate, boilerplate,
520        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements),
521        AllocationSite);
522
523    AllocationSiteCreationContext creation_context(isolate);
524    site = creation_context.EnterNewScope();
525    if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
526                           &creation_context).is_null()) {
527      return Handle<AllocationSite>::null();
528    }
529    creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
530
531    literals->set(literals_index, *site);
532  } else {
533    site = Handle<AllocationSite>::cast(literal_site);
534  }
535
536  return site;
537}
538
539
540static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* isolate,
541                                           Handle<FixedArray> literals,
542                                           int literals_index,
543                                           Handle<FixedArray> elements,
544                                           int flags) {
545  RUNTIME_ASSERT_HANDLIFIED(literals_index >= 0 &&
546                            literals_index < literals->length(), JSObject);
547  Handle<AllocationSite> site;
548  ASSIGN_RETURN_ON_EXCEPTION(
549      isolate, site,
550      GetLiteralAllocationSite(isolate, literals, literals_index, elements),
551      JSObject);
552
553  bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
554  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
555  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
556  usage_context.EnterNewScope();
557  JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
558                                      ? JSObject::kNoHints
559                                      : JSObject::kObjectIsShallow;
560  MaybeHandle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
561                                                  hints);
562  usage_context.ExitScope(site, boilerplate);
563  return copy;
564}
565
566
567RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
568  HandleScope scope(isolate);
569  DCHECK(args.length() == 4);
570  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
571  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
572  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
573  CONVERT_SMI_ARG_CHECKED(flags, 3);
574
575  Handle<JSObject> result;
576  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
577      CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
578                             flags));
579  return *result;
580}
581
582
583RUNTIME_FUNCTION(Runtime_CreateArrayLiteralStubBailout) {
584  HandleScope scope(isolate);
585  DCHECK(args.length() == 3);
586  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
587  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
588  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
589
590  Handle<JSObject> result;
591  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
592     CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
593                            ArrayLiteral::kShallowElements));
594  return *result;
595}
596
597
598RUNTIME_FUNCTION(Runtime_CreateSymbol) {
599  HandleScope scope(isolate);
600  DCHECK(args.length() == 1);
601  CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
602  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
603  Handle<Symbol> symbol = isolate->factory()->NewSymbol();
604  if (name->IsString()) symbol->set_name(*name);
605  return *symbol;
606}
607
608
609RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol) {
610  HandleScope scope(isolate);
611  DCHECK(args.length() == 1);
612  CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
613  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
614  Handle<Symbol> symbol = isolate->factory()->NewPrivateSymbol();
615  if (name->IsString()) symbol->set_name(*name);
616  return *symbol;
617}
618
619
620RUNTIME_FUNCTION(Runtime_CreatePrivateOwnSymbol) {
621  HandleScope scope(isolate);
622  DCHECK(args.length() == 1);
623  CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
624  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
625  Handle<Symbol> symbol = isolate->factory()->NewPrivateOwnSymbol();
626  if (name->IsString()) symbol->set_name(*name);
627  return *symbol;
628}
629
630
631RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateOwnSymbol) {
632  HandleScope scope(isolate);
633  DCHECK(args.length() == 1);
634  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
635  Handle<JSObject> registry = isolate->GetSymbolRegistry();
636  Handle<String> part = isolate->factory()->private_intern_string();
637  Handle<Object> privates;
638  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
639      isolate, privates, Object::GetPropertyOrElement(registry, part));
640  Handle<Object> symbol;
641  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
642      isolate, symbol, Object::GetPropertyOrElement(privates, name));
643  if (!symbol->IsSymbol()) {
644    DCHECK(symbol->IsUndefined());
645    symbol = isolate->factory()->NewPrivateSymbol();
646    Handle<Symbol>::cast(symbol)->set_name(*name);
647    Handle<Symbol>::cast(symbol)->set_is_own(true);
648    JSObject::SetProperty(Handle<JSObject>::cast(privates), name, symbol,
649                          STRICT).Assert();
650  }
651  return *symbol;
652}
653
654
655RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
656  HandleScope scope(isolate);
657  DCHECK(args.length() == 1);
658  CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
659  return *Object::ToObject(isolate, symbol).ToHandleChecked();
660}
661
662
663RUNTIME_FUNCTION(Runtime_SymbolDescription) {
664  SealHandleScope shs(isolate);
665  DCHECK(args.length() == 1);
666  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
667  return symbol->name();
668}
669
670
671RUNTIME_FUNCTION(Runtime_SymbolRegistry) {
672  HandleScope scope(isolate);
673  DCHECK(args.length() == 0);
674  return *isolate->GetSymbolRegistry();
675}
676
677
678RUNTIME_FUNCTION(Runtime_SymbolIsPrivate) {
679  SealHandleScope shs(isolate);
680  DCHECK(args.length() == 1);
681  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
682  return isolate->heap()->ToBoolean(symbol->is_private());
683}
684
685
686RUNTIME_FUNCTION(Runtime_CreateJSProxy) {
687  HandleScope scope(isolate);
688  DCHECK(args.length() == 2);
689  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
690  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
691  if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
692  return *isolate->factory()->NewJSProxy(handler, prototype);
693}
694
695
696RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy) {
697  HandleScope scope(isolate);
698  DCHECK(args.length() == 4);
699  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
700  CONVERT_ARG_HANDLE_CHECKED(Object, call_trap, 1);
701  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
702  CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 2);
703  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 3);
704  if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
705  return *isolate->factory()->NewJSFunctionProxy(
706      handler, call_trap, construct_trap, prototype);
707}
708
709
710RUNTIME_FUNCTION(Runtime_IsJSProxy) {
711  SealHandleScope shs(isolate);
712  DCHECK(args.length() == 1);
713  CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
714  return isolate->heap()->ToBoolean(obj->IsJSProxy());
715}
716
717
718RUNTIME_FUNCTION(Runtime_IsJSFunctionProxy) {
719  SealHandleScope shs(isolate);
720  DCHECK(args.length() == 1);
721  CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
722  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
723}
724
725
726RUNTIME_FUNCTION(Runtime_GetHandler) {
727  SealHandleScope shs(isolate);
728  DCHECK(args.length() == 1);
729  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
730  return proxy->handler();
731}
732
733
734RUNTIME_FUNCTION(Runtime_GetCallTrap) {
735  SealHandleScope shs(isolate);
736  DCHECK(args.length() == 1);
737  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
738  return proxy->call_trap();
739}
740
741
742RUNTIME_FUNCTION(Runtime_GetConstructTrap) {
743  SealHandleScope shs(isolate);
744  DCHECK(args.length() == 1);
745  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
746  return proxy->construct_trap();
747}
748
749
750RUNTIME_FUNCTION(Runtime_Fix) {
751  HandleScope scope(isolate);
752  DCHECK(args.length() == 1);
753  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
754  JSProxy::Fix(proxy);
755  return isolate->heap()->undefined_value();
756}
757
758
759void Runtime::FreeArrayBuffer(Isolate* isolate,
760                              JSArrayBuffer* phantom_array_buffer) {
761  if (phantom_array_buffer->should_be_freed()) {
762    DCHECK(phantom_array_buffer->is_external());
763    free(phantom_array_buffer->backing_store());
764  }
765  if (phantom_array_buffer->is_external()) return;
766
767  size_t allocated_length = NumberToSize(
768      isolate, phantom_array_buffer->byte_length());
769
770  reinterpret_cast<v8::Isolate*>(isolate)
771      ->AdjustAmountOfExternalAllocatedMemory(
772          -static_cast<int64_t>(allocated_length));
773  CHECK(V8::ArrayBufferAllocator() != NULL);
774  V8::ArrayBufferAllocator()->Free(
775      phantom_array_buffer->backing_store(),
776      allocated_length);
777}
778
779
780void Runtime::SetupArrayBuffer(Isolate* isolate,
781                               Handle<JSArrayBuffer> array_buffer,
782                               bool is_external,
783                               void* data,
784                               size_t allocated_length) {
785  DCHECK(array_buffer->GetInternalFieldCount() ==
786      v8::ArrayBuffer::kInternalFieldCount);
787  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
788    array_buffer->SetInternalField(i, Smi::FromInt(0));
789  }
790  array_buffer->set_backing_store(data);
791  array_buffer->set_flag(Smi::FromInt(0));
792  array_buffer->set_is_external(is_external);
793
794  Handle<Object> byte_length =
795      isolate->factory()->NewNumberFromSize(allocated_length);
796  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
797  array_buffer->set_byte_length(*byte_length);
798
799  array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
800  isolate->heap()->set_array_buffers_list(*array_buffer);
801  array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
802}
803
804
805bool Runtime::SetupArrayBufferAllocatingData(
806    Isolate* isolate,
807    Handle<JSArrayBuffer> array_buffer,
808    size_t allocated_length,
809    bool initialize) {
810  void* data;
811  CHECK(V8::ArrayBufferAllocator() != NULL);
812  if (allocated_length != 0) {
813    if (initialize) {
814      data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
815    } else {
816      data =
817          V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
818    }
819    if (data == NULL) return false;
820  } else {
821    data = NULL;
822  }
823
824  SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
825
826  reinterpret_cast<v8::Isolate*>(isolate)
827      ->AdjustAmountOfExternalAllocatedMemory(allocated_length);
828
829  return true;
830}
831
832
833void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
834  Isolate* isolate = array_buffer->GetIsolate();
835  for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
836       !view_obj->IsUndefined();) {
837    Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
838    if (view->IsJSTypedArray()) {
839      JSTypedArray::cast(*view)->Neuter();
840    } else if (view->IsJSDataView()) {
841      JSDataView::cast(*view)->Neuter();
842    } else {
843      UNREACHABLE();
844    }
845    view_obj = handle(view->weak_next(), isolate);
846  }
847  array_buffer->Neuter();
848}
849
850
851RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
852  HandleScope scope(isolate);
853  DCHECK(args.length() == 2);
854  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
855  CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
856  if (!holder->byte_length()->IsUndefined()) {
857    // ArrayBuffer is already initialized; probably a fuzz test.
858    return *holder;
859  }
860  size_t allocated_length = 0;
861  if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
862    THROW_NEW_ERROR_RETURN_FAILURE(
863        isolate, NewRangeError("invalid_array_buffer_length",
864                               HandleVector<Object>(NULL, 0)));
865  }
866  if (!Runtime::SetupArrayBufferAllocatingData(isolate,
867                                               holder, allocated_length)) {
868    THROW_NEW_ERROR_RETURN_FAILURE(
869        isolate, NewRangeError("invalid_array_buffer_length",
870                               HandleVector<Object>(NULL, 0)));
871  }
872  return *holder;
873}
874
875
876RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
877  SealHandleScope shs(isolate);
878  DCHECK(args.length() == 1);
879  CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
880  return holder->byte_length();
881}
882
883
884RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
885  HandleScope scope(isolate);
886  DCHECK(args.length() == 3);
887  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
888  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
889  CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
890  RUNTIME_ASSERT(!source.is_identical_to(target));
891  size_t start = 0;
892  RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
893  size_t target_length = NumberToSize(isolate, target->byte_length());
894
895  if (target_length == 0) return isolate->heap()->undefined_value();
896
897  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
898  RUNTIME_ASSERT(start <= source_byte_length);
899  RUNTIME_ASSERT(source_byte_length - start >= target_length);
900  uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
901  uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
902  CopyBytes(target_data, source_data + start, target_length);
903  return isolate->heap()->undefined_value();
904}
905
906
907RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
908  HandleScope scope(isolate);
909  DCHECK(args.length() == 1);
910  CONVERT_ARG_CHECKED(Object, object, 0);
911  return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
912}
913
914
915RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
916  HandleScope scope(isolate);
917  DCHECK(args.length() == 1);
918  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
919  if (array_buffer->backing_store() == NULL) {
920    CHECK(Smi::FromInt(0) == array_buffer->byte_length());
921    return isolate->heap()->undefined_value();
922  }
923  DCHECK(!array_buffer->is_external());
924  void* backing_store = array_buffer->backing_store();
925  size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
926  array_buffer->set_is_external(true);
927  Runtime::NeuterArrayBuffer(array_buffer);
928  V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
929  return isolate->heap()->undefined_value();
930}
931
932
933void Runtime::ArrayIdToTypeAndSize(
934    int arrayId,
935    ExternalArrayType* array_type,
936    ElementsKind* external_elements_kind,
937    ElementsKind* fixed_elements_kind,
938    size_t* element_size) {
939  switch (arrayId) {
940#define ARRAY_ID_CASE(Type, type, TYPE, ctype, size)                           \
941    case ARRAY_ID_##TYPE:                                                      \
942      *array_type = kExternal##Type##Array;                                    \
943      *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS;                    \
944      *fixed_elements_kind = TYPE##_ELEMENTS;                                  \
945      *element_size = size;                                                    \
946      break;
947
948    TYPED_ARRAYS(ARRAY_ID_CASE)
949#undef ARRAY_ID_CASE
950
951    default:
952      UNREACHABLE();
953  }
954}
955
956
957RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
958  HandleScope scope(isolate);
959  DCHECK(args.length() == 5);
960  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
961  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
962  CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
963  CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
964  CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
965
966  RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
967                 arrayId <= Runtime::ARRAY_ID_LAST);
968
969  ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
970  size_t element_size = 1;  // Bogus initialization.
971  ElementsKind external_elements_kind =
972      EXTERNAL_INT8_ELEMENTS;  // Bogus initialization.
973  ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
974  Runtime::ArrayIdToTypeAndSize(arrayId,
975      &array_type,
976      &external_elements_kind,
977      &fixed_elements_kind,
978      &element_size);
979  RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
980
981  size_t byte_offset = 0;
982  size_t byte_length = 0;
983  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
984  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
985
986  if (maybe_buffer->IsJSArrayBuffer()) {
987    Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
988    size_t array_buffer_byte_length =
989        NumberToSize(isolate, buffer->byte_length());
990    RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length);
991    RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length);
992  } else {
993    RUNTIME_ASSERT(maybe_buffer->IsNull());
994  }
995
996  RUNTIME_ASSERT(byte_length % element_size == 0);
997  size_t length = byte_length / element_size;
998
999  if (length > static_cast<unsigned>(Smi::kMaxValue)) {
1000    THROW_NEW_ERROR_RETURN_FAILURE(
1001        isolate, NewRangeError("invalid_typed_array_length",
1002                               HandleVector<Object>(NULL, 0)));
1003  }
1004
1005  // All checks are done, now we can modify objects.
1006
1007  DCHECK(holder->GetInternalFieldCount() ==
1008      v8::ArrayBufferView::kInternalFieldCount);
1009  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1010    holder->SetInternalField(i, Smi::FromInt(0));
1011  }
1012  Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
1013  holder->set_length(*length_obj);
1014  holder->set_byte_offset(*byte_offset_object);
1015  holder->set_byte_length(*byte_length_object);
1016
1017  if (!maybe_buffer->IsNull()) {
1018    Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
1019    holder->set_buffer(*buffer);
1020    holder->set_weak_next(buffer->weak_first_view());
1021    buffer->set_weak_first_view(*holder);
1022
1023    Handle<ExternalArray> elements =
1024        isolate->factory()->NewExternalArray(
1025            static_cast<int>(length), array_type,
1026            static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
1027    Handle<Map> map =
1028        JSObject::GetElementsTransitionMap(holder, external_elements_kind);
1029    JSObject::SetMapAndElements(holder, map, elements);
1030    DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind()));
1031  } else {
1032    holder->set_buffer(Smi::FromInt(0));
1033    holder->set_weak_next(isolate->heap()->undefined_value());
1034    Handle<FixedTypedArrayBase> elements =
1035        isolate->factory()->NewFixedTypedArray(
1036            static_cast<int>(length), array_type);
1037    holder->set_elements(*elements);
1038  }
1039  return isolate->heap()->undefined_value();
1040}
1041
1042
1043// Initializes a typed array from an array-like object.
1044// If an array-like object happens to be a typed array of the same type,
1045// initializes backing store using memove.
1046//
1047// Returns true if backing store was initialized or false otherwise.
1048RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
1049  HandleScope scope(isolate);
1050  DCHECK(args.length() == 4);
1051  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
1052  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
1053  CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
1054  CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3);
1055
1056  RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
1057                 arrayId <= Runtime::ARRAY_ID_LAST);
1058
1059  ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
1060  size_t element_size = 1;  // Bogus initialization.
1061  ElementsKind external_elements_kind =
1062      EXTERNAL_INT8_ELEMENTS;  // Bogus intialization.
1063  ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
1064  Runtime::ArrayIdToTypeAndSize(arrayId,
1065      &array_type,
1066      &external_elements_kind,
1067      &fixed_elements_kind,
1068      &element_size);
1069
1070  RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
1071
1072  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
1073  if (source->IsJSTypedArray() &&
1074      JSTypedArray::cast(*source)->type() == array_type) {
1075    length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
1076  }
1077  size_t length = 0;
1078  RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
1079
1080  if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
1081      (length > (kMaxInt / element_size))) {
1082    THROW_NEW_ERROR_RETURN_FAILURE(
1083        isolate, NewRangeError("invalid_typed_array_length",
1084                               HandleVector<Object>(NULL, 0)));
1085  }
1086  size_t byte_length = length * element_size;
1087
1088  DCHECK(holder->GetInternalFieldCount() ==
1089      v8::ArrayBufferView::kInternalFieldCount);
1090  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1091    holder->SetInternalField(i, Smi::FromInt(0));
1092  }
1093
1094  // NOTE: not initializing backing store.
1095  // We assume that the caller of this function will initialize holder
1096  // with the loop
1097  //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
1098  // We assume that the caller of this function is always a typed array
1099  // constructor.
1100  // If source is a typed array, this loop will always run to completion,
1101  // so we are sure that the backing store will be initialized.
1102  // Otherwise, the indexing operation might throw, so the loop will not
1103  // run to completion and the typed array might remain partly initialized.
1104  // However we further assume that the caller of this function is a typed array
1105  // constructor, and the exception will propagate out of the constructor,
1106  // therefore uninitialized memory will not be accessible by a user program.
1107  //
1108  // TODO(dslomov): revise this once we support subclassing.
1109
1110  if (!Runtime::SetupArrayBufferAllocatingData(
1111        isolate, buffer, byte_length, false)) {
1112    THROW_NEW_ERROR_RETURN_FAILURE(
1113        isolate, NewRangeError("invalid_array_buffer_length",
1114                               HandleVector<Object>(NULL, 0)));
1115  }
1116
1117  holder->set_buffer(*buffer);
1118  holder->set_byte_offset(Smi::FromInt(0));
1119  Handle<Object> byte_length_obj(
1120      isolate->factory()->NewNumberFromSize(byte_length));
1121  holder->set_byte_length(*byte_length_obj);
1122  holder->set_length(*length_obj);
1123  holder->set_weak_next(buffer->weak_first_view());
1124  buffer->set_weak_first_view(*holder);
1125
1126  Handle<ExternalArray> elements =
1127      isolate->factory()->NewExternalArray(
1128          static_cast<int>(length), array_type,
1129          static_cast<uint8_t*>(buffer->backing_store()));
1130  Handle<Map> map = JSObject::GetElementsTransitionMap(
1131      holder, external_elements_kind);
1132  JSObject::SetMapAndElements(holder, map, elements);
1133
1134  if (source->IsJSTypedArray()) {
1135    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1136
1137    if (typed_array->type() == holder->type()) {
1138      uint8_t* backing_store =
1139        static_cast<uint8_t*>(
1140          typed_array->GetBuffer()->backing_store());
1141      size_t source_byte_offset =
1142          NumberToSize(isolate, typed_array->byte_offset());
1143      memcpy(
1144          buffer->backing_store(),
1145          backing_store + source_byte_offset,
1146          byte_length);
1147      return isolate->heap()->true_value();
1148    }
1149  }
1150
1151  return isolate->heap()->false_value();
1152}
1153
1154
1155#define BUFFER_VIEW_GETTER(Type, getter, accessor) \
1156  RUNTIME_FUNCTION(Runtime_##Type##Get##getter) {                    \
1157    HandleScope scope(isolate);                                               \
1158    DCHECK(args.length() == 1);                                               \
1159    CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0);                          \
1160    return holder->accessor();                                                \
1161  }
1162
1163BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length)
1164BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset)
1165BUFFER_VIEW_GETTER(TypedArray, Length, length)
1166BUFFER_VIEW_GETTER(DataView, Buffer, buffer)
1167
1168#undef BUFFER_VIEW_GETTER
1169
1170RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
1171  HandleScope scope(isolate);
1172  DCHECK(args.length() == 1);
1173  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
1174  return *holder->GetBuffer();
1175}
1176
1177
1178// Return codes for Runtime_TypedArraySetFastCases.
1179// Should be synchronized with typedarray.js natives.
1180enum TypedArraySetResultCodes {
1181  // Set from typed array of the same type.
1182  // This is processed by TypedArraySetFastCases
1183  TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1184  // Set from typed array of the different type, overlapping in memory.
1185  TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1186  // Set from typed array of the different type, non-overlapping.
1187  TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1188  // Set from non-typed array.
1189  TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1190};
1191
1192
1193RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
1194  HandleScope scope(isolate);
1195  DCHECK(args.length() == 3);
1196  if (!args[0]->IsJSTypedArray()) {
1197    THROW_NEW_ERROR_RETURN_FAILURE(
1198        isolate,
1199        NewTypeError("not_typed_array", HandleVector<Object>(NULL, 0)));
1200  }
1201
1202  if (!args[1]->IsJSTypedArray())
1203    return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1204
1205  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0);
1206  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1);
1207  CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2);
1208
1209  Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1210  Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1211  size_t offset = 0;
1212  RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset));
1213  size_t target_length = NumberToSize(isolate, target->length());
1214  size_t source_length = NumberToSize(isolate, source->length());
1215  size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1216  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1217  if (offset > target_length || offset + source_length > target_length ||
1218      offset + source_length < offset) {  // overflow
1219    THROW_NEW_ERROR_RETURN_FAILURE(
1220        isolate, NewRangeError("typed_array_set_source_too_large",
1221                               HandleVector<Object>(NULL, 0)));
1222  }
1223
1224  size_t target_offset = NumberToSize(isolate, target->byte_offset());
1225  size_t source_offset = NumberToSize(isolate, source->byte_offset());
1226  uint8_t* target_base =
1227      static_cast<uint8_t*>(
1228        target->GetBuffer()->backing_store()) + target_offset;
1229  uint8_t* source_base =
1230      static_cast<uint8_t*>(
1231        source->GetBuffer()->backing_store()) + source_offset;
1232
1233  // Typed arrays of the same type: use memmove.
1234  if (target->type() == source->type()) {
1235    memmove(target_base + offset * target->element_size(),
1236        source_base, source_byte_length);
1237    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1238  }
1239
1240  // Typed arrays of different types over the same backing store
1241  if ((source_base <= target_base &&
1242        source_base + source_byte_length > target_base) ||
1243      (target_base <= source_base &&
1244        target_base + target_byte_length > source_base)) {
1245    // We do not support overlapping ArrayBuffers
1246    DCHECK(
1247      target->GetBuffer()->backing_store() ==
1248      source->GetBuffer()->backing_store());
1249    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1250  } else {  // Non-overlapping typed arrays
1251    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1252  }
1253}
1254
1255
1256RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) {
1257  DCHECK(args.length() == 0);
1258  DCHECK_OBJECT_SIZE(
1259      FLAG_typed_array_max_size_in_heap + FixedTypedArrayBase::kDataOffset);
1260  return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
1261}
1262
1263
1264RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
1265  HandleScope scope(isolate);
1266  DCHECK(args.length() == 4);
1267  CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1268  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1269  CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset, 2);
1270  CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length, 3);
1271
1272  DCHECK(holder->GetInternalFieldCount() ==
1273      v8::ArrayBufferView::kInternalFieldCount);
1274  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1275    holder->SetInternalField(i, Smi::FromInt(0));
1276  }
1277  size_t buffer_length = 0;
1278  size_t offset = 0;
1279  size_t length = 0;
1280  RUNTIME_ASSERT(
1281      TryNumberToSize(isolate, buffer->byte_length(), &buffer_length));
1282  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset, &offset));
1283  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length, &length));
1284
1285  // TODO(jkummerow): When we have a "safe numerics" helper class, use it here.
1286  // Entire range [offset, offset + length] must be in bounds.
1287  RUNTIME_ASSERT(offset <= buffer_length);
1288  RUNTIME_ASSERT(offset + length <= buffer_length);
1289  // No overflow.
1290  RUNTIME_ASSERT(offset + length >= offset);
1291
1292  holder->set_buffer(*buffer);
1293  holder->set_byte_offset(*byte_offset);
1294  holder->set_byte_length(*byte_length);
1295
1296  holder->set_weak_next(buffer->weak_first_view());
1297  buffer->set_weak_first_view(*holder);
1298
1299  return isolate->heap()->undefined_value();
1300}
1301
1302
1303inline static bool NeedToFlipBytes(bool is_little_endian) {
1304#ifdef V8_TARGET_LITTLE_ENDIAN
1305  return !is_little_endian;
1306#else
1307  return is_little_endian;
1308#endif
1309}
1310
1311
1312template<int n>
1313inline void CopyBytes(uint8_t* target, uint8_t* source) {
1314  for (int i = 0; i < n; i++) {
1315    *(target++) = *(source++);
1316  }
1317}
1318
1319
1320template<int n>
1321inline void FlipBytes(uint8_t* target, uint8_t* source) {
1322  source = source + (n-1);
1323  for (int i = 0; i < n; i++) {
1324    *(target++) = *(source--);
1325  }
1326}
1327
1328
1329template<typename T>
1330inline static bool DataViewGetValue(
1331    Isolate* isolate,
1332    Handle<JSDataView> data_view,
1333    Handle<Object> byte_offset_obj,
1334    bool is_little_endian,
1335    T* result) {
1336  size_t byte_offset = 0;
1337  if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1338    return false;
1339  }
1340  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1341
1342  size_t data_view_byte_offset =
1343      NumberToSize(isolate, data_view->byte_offset());
1344  size_t data_view_byte_length =
1345      NumberToSize(isolate, data_view->byte_length());
1346  if (byte_offset + sizeof(T) > data_view_byte_length ||
1347      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1348    return false;
1349  }
1350
1351  union Value {
1352    T data;
1353    uint8_t bytes[sizeof(T)];
1354  };
1355
1356  Value value;
1357  size_t buffer_offset = data_view_byte_offset + byte_offset;
1358  DCHECK(
1359      NumberToSize(isolate, buffer->byte_length())
1360      >= buffer_offset + sizeof(T));
1361  uint8_t* source =
1362        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1363  if (NeedToFlipBytes(is_little_endian)) {
1364    FlipBytes<sizeof(T)>(value.bytes, source);
1365  } else {
1366    CopyBytes<sizeof(T)>(value.bytes, source);
1367  }
1368  *result = value.data;
1369  return true;
1370}
1371
1372
1373template<typename T>
1374static bool DataViewSetValue(
1375    Isolate* isolate,
1376    Handle<JSDataView> data_view,
1377    Handle<Object> byte_offset_obj,
1378    bool is_little_endian,
1379    T data) {
1380  size_t byte_offset = 0;
1381  if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1382    return false;
1383  }
1384  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1385
1386  size_t data_view_byte_offset =
1387      NumberToSize(isolate, data_view->byte_offset());
1388  size_t data_view_byte_length =
1389      NumberToSize(isolate, data_view->byte_length());
1390  if (byte_offset + sizeof(T) > data_view_byte_length ||
1391      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1392    return false;
1393  }
1394
1395  union Value {
1396    T data;
1397    uint8_t bytes[sizeof(T)];
1398  };
1399
1400  Value value;
1401  value.data = data;
1402  size_t buffer_offset = data_view_byte_offset + byte_offset;
1403  DCHECK(
1404      NumberToSize(isolate, buffer->byte_length())
1405      >= buffer_offset + sizeof(T));
1406  uint8_t* target =
1407        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1408  if (NeedToFlipBytes(is_little_endian)) {
1409    FlipBytes<sizeof(T)>(target, value.bytes);
1410  } else {
1411    CopyBytes<sizeof(T)>(target, value.bytes);
1412  }
1413  return true;
1414}
1415
1416
1417#define DATA_VIEW_GETTER(TypeName, Type, Converter)                   \
1418  RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) {                   \
1419    HandleScope scope(isolate);                                       \
1420    DCHECK(args.length() == 3);                                       \
1421    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                \
1422    CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1);                     \
1423    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                 \
1424    Type result;                                                      \
1425    if (DataViewGetValue(isolate, holder, offset, is_little_endian,   \
1426                         &result)) {                                  \
1427      return *isolate->factory()->Converter(result);                  \
1428    } else {                                                          \
1429      THROW_NEW_ERROR_RETURN_FAILURE(                                 \
1430          isolate, NewRangeError("invalid_data_view_accessor_offset", \
1431                                 HandleVector<Object>(NULL, 0)));     \
1432    }                                                                 \
1433  }
1434
1435DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint)
1436DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt)
1437DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint)
1438DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt)
1439DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint)
1440DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt)
1441DATA_VIEW_GETTER(Float32, float, NewNumber)
1442DATA_VIEW_GETTER(Float64, double, NewNumber)
1443
1444#undef DATA_VIEW_GETTER
1445
1446
1447template <typename T>
1448static T DataViewConvertValue(double value);
1449
1450
1451template <>
1452int8_t DataViewConvertValue<int8_t>(double value) {
1453  return static_cast<int8_t>(DoubleToInt32(value));
1454}
1455
1456
1457template <>
1458int16_t DataViewConvertValue<int16_t>(double value) {
1459  return static_cast<int16_t>(DoubleToInt32(value));
1460}
1461
1462
1463template <>
1464int32_t DataViewConvertValue<int32_t>(double value) {
1465  return DoubleToInt32(value);
1466}
1467
1468
1469template <>
1470uint8_t DataViewConvertValue<uint8_t>(double value) {
1471  return static_cast<uint8_t>(DoubleToUint32(value));
1472}
1473
1474
1475template <>
1476uint16_t DataViewConvertValue<uint16_t>(double value) {
1477  return static_cast<uint16_t>(DoubleToUint32(value));
1478}
1479
1480
1481template <>
1482uint32_t DataViewConvertValue<uint32_t>(double value) {
1483  return DoubleToUint32(value);
1484}
1485
1486
1487template <>
1488float DataViewConvertValue<float>(double value) {
1489  return static_cast<float>(value);
1490}
1491
1492
1493template <>
1494double DataViewConvertValue<double>(double value) {
1495  return value;
1496}
1497
1498
1499#define DATA_VIEW_SETTER(TypeName, Type)                                  \
1500  RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) {                       \
1501    HandleScope scope(isolate);                                           \
1502    DCHECK(args.length() == 4);                                           \
1503    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                    \
1504    CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1);                         \
1505    CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);                          \
1506    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                     \
1507    Type v = DataViewConvertValue<Type>(value->Number());                 \
1508    if (DataViewSetValue(isolate, holder, offset, is_little_endian, v)) { \
1509      return isolate->heap()->undefined_value();                          \
1510    } else {                                                              \
1511      THROW_NEW_ERROR_RETURN_FAILURE(                                     \
1512          isolate, NewRangeError("invalid_data_view_accessor_offset",     \
1513                                 HandleVector<Object>(NULL, 0)));         \
1514    }                                                                     \
1515  }
1516
1517DATA_VIEW_SETTER(Uint8, uint8_t)
1518DATA_VIEW_SETTER(Int8, int8_t)
1519DATA_VIEW_SETTER(Uint16, uint16_t)
1520DATA_VIEW_SETTER(Int16, int16_t)
1521DATA_VIEW_SETTER(Uint32, uint32_t)
1522DATA_VIEW_SETTER(Int32, int32_t)
1523DATA_VIEW_SETTER(Float32, float)
1524DATA_VIEW_SETTER(Float64, double)
1525
1526#undef DATA_VIEW_SETTER
1527
1528
1529RUNTIME_FUNCTION(Runtime_SetInitialize) {
1530  HandleScope scope(isolate);
1531  DCHECK(args.length() == 1);
1532  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1533  Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
1534  holder->set_table(*table);
1535  return *holder;
1536}
1537
1538
1539RUNTIME_FUNCTION(Runtime_SetAdd) {
1540  HandleScope scope(isolate);
1541  DCHECK(args.length() == 2);
1542  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1543  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1544  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1545  table = OrderedHashSet::Add(table, key);
1546  holder->set_table(*table);
1547  return *holder;
1548}
1549
1550
1551RUNTIME_FUNCTION(Runtime_SetHas) {
1552  HandleScope scope(isolate);
1553  DCHECK(args.length() == 2);
1554  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1555  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1556  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1557  return isolate->heap()->ToBoolean(table->Contains(key));
1558}
1559
1560
1561RUNTIME_FUNCTION(Runtime_SetDelete) {
1562  HandleScope scope(isolate);
1563  DCHECK(args.length() == 2);
1564  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1565  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1566  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1567  bool was_present = false;
1568  table = OrderedHashSet::Remove(table, key, &was_present);
1569  holder->set_table(*table);
1570  return isolate->heap()->ToBoolean(was_present);
1571}
1572
1573
1574RUNTIME_FUNCTION(Runtime_SetClear) {
1575  HandleScope scope(isolate);
1576  DCHECK(args.length() == 1);
1577  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1578  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1579  table = OrderedHashSet::Clear(table);
1580  holder->set_table(*table);
1581  return isolate->heap()->undefined_value();
1582}
1583
1584
1585RUNTIME_FUNCTION(Runtime_SetGetSize) {
1586  HandleScope scope(isolate);
1587  DCHECK(args.length() == 1);
1588  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1589  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1590  return Smi::FromInt(table->NumberOfElements());
1591}
1592
1593
1594RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
1595  HandleScope scope(isolate);
1596  DCHECK(args.length() == 3);
1597  CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
1598  CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
1599  CONVERT_SMI_ARG_CHECKED(kind, 2)
1600  RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
1601                 kind == JSSetIterator::kKindEntries);
1602  Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
1603  holder->set_table(*table);
1604  holder->set_index(Smi::FromInt(0));
1605  holder->set_kind(Smi::FromInt(kind));
1606  return isolate->heap()->undefined_value();
1607}
1608
1609
1610RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
1611  SealHandleScope shs(isolate);
1612  DCHECK(args.length() == 2);
1613  CONVERT_ARG_CHECKED(JSSetIterator, holder, 0);
1614  CONVERT_ARG_CHECKED(JSArray, value_array, 1);
1615  return holder->Next(value_array);
1616}
1617
1618
1619RUNTIME_FUNCTION(Runtime_MapInitialize) {
1620  HandleScope scope(isolate);
1621  DCHECK(args.length() == 1);
1622  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1623  Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
1624  holder->set_table(*table);
1625  return *holder;
1626}
1627
1628
1629RUNTIME_FUNCTION(Runtime_MapGet) {
1630  HandleScope scope(isolate);
1631  DCHECK(args.length() == 2);
1632  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1633  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1634  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1635  Handle<Object> lookup(table->Lookup(key), isolate);
1636  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1637}
1638
1639
1640RUNTIME_FUNCTION(Runtime_MapHas) {
1641  HandleScope scope(isolate);
1642  DCHECK(args.length() == 2);
1643  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1644  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1645  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1646  Handle<Object> lookup(table->Lookup(key), isolate);
1647  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1648}
1649
1650
1651RUNTIME_FUNCTION(Runtime_MapDelete) {
1652  HandleScope scope(isolate);
1653  DCHECK(args.length() == 2);
1654  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1655  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1656  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1657  bool was_present = false;
1658  Handle<OrderedHashMap> new_table =
1659      OrderedHashMap::Remove(table, key, &was_present);
1660  holder->set_table(*new_table);
1661  return isolate->heap()->ToBoolean(was_present);
1662}
1663
1664
1665RUNTIME_FUNCTION(Runtime_MapClear) {
1666  HandleScope scope(isolate);
1667  DCHECK(args.length() == 1);
1668  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1669  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1670  table = OrderedHashMap::Clear(table);
1671  holder->set_table(*table);
1672  return isolate->heap()->undefined_value();
1673}
1674
1675
1676RUNTIME_FUNCTION(Runtime_MapSet) {
1677  HandleScope scope(isolate);
1678  DCHECK(args.length() == 3);
1679  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1680  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1681  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1682  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1683  Handle<OrderedHashMap> new_table = OrderedHashMap::Put(table, key, value);
1684  holder->set_table(*new_table);
1685  return *holder;
1686}
1687
1688
1689RUNTIME_FUNCTION(Runtime_MapGetSize) {
1690  HandleScope scope(isolate);
1691  DCHECK(args.length() == 1);
1692  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1693  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1694  return Smi::FromInt(table->NumberOfElements());
1695}
1696
1697
1698RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
1699  HandleScope scope(isolate);
1700  DCHECK(args.length() == 3);
1701  CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
1702  CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
1703  CONVERT_SMI_ARG_CHECKED(kind, 2)
1704  RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys
1705      || kind == JSMapIterator::kKindValues
1706      || kind == JSMapIterator::kKindEntries);
1707  Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
1708  holder->set_table(*table);
1709  holder->set_index(Smi::FromInt(0));
1710  holder->set_kind(Smi::FromInt(kind));
1711  return isolate->heap()->undefined_value();
1712}
1713
1714
1715RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
1716  HandleScope scope(isolate);
1717  DCHECK(args.length() == 1);
1718  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
1719  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1720  Handle<FixedArray> entries =
1721      isolate->factory()->NewFixedArray(table->NumberOfElements() * 2);
1722  {
1723    DisallowHeapAllocation no_gc;
1724    int number_of_non_hole_elements = 0;
1725    for (int i = 0; i < table->Capacity(); i++) {
1726      Handle<Object> key(table->KeyAt(i), isolate);
1727      if (table->IsKey(*key)) {
1728        entries->set(number_of_non_hole_elements++, *key);
1729        Object* value = table->Lookup(key);
1730        entries->set(number_of_non_hole_elements++, value);
1731      }
1732    }
1733    DCHECK_EQ(table->NumberOfElements() * 2, number_of_non_hole_elements);
1734  }
1735  return *isolate->factory()->NewJSArrayWithElements(entries);
1736}
1737
1738
1739RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
1740  SealHandleScope shs(isolate);
1741  DCHECK(args.length() == 2);
1742  CONVERT_ARG_CHECKED(JSMapIterator, holder, 0);
1743  CONVERT_ARG_CHECKED(JSArray, value_array, 1);
1744  return holder->Next(value_array);
1745}
1746
1747
1748static Handle<JSWeakCollection> WeakCollectionInitialize(
1749    Isolate* isolate,
1750    Handle<JSWeakCollection> weak_collection) {
1751  DCHECK(weak_collection->map()->inobject_properties() == 0);
1752  Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
1753  weak_collection->set_table(*table);
1754  return weak_collection;
1755}
1756
1757
1758RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
1759  HandleScope scope(isolate);
1760  DCHECK(args.length() == 1);
1761  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1762  return *WeakCollectionInitialize(isolate, weak_collection);
1763}
1764
1765
1766RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
1767  HandleScope scope(isolate);
1768  DCHECK(args.length() == 2);
1769  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1770  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1771  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1772  Handle<ObjectHashTable> table(
1773      ObjectHashTable::cast(weak_collection->table()));
1774  RUNTIME_ASSERT(table->IsKey(*key));
1775  Handle<Object> lookup(table->Lookup(key), isolate);
1776  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1777}
1778
1779
1780RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
1781  HandleScope scope(isolate);
1782  DCHECK(args.length() == 2);
1783  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1784  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1785  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1786  Handle<ObjectHashTable> table(
1787      ObjectHashTable::cast(weak_collection->table()));
1788  RUNTIME_ASSERT(table->IsKey(*key));
1789  Handle<Object> lookup(table->Lookup(key), isolate);
1790  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1791}
1792
1793
1794RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
1795  HandleScope scope(isolate);
1796  DCHECK(args.length() == 2);
1797  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1798  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1799  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1800  Handle<ObjectHashTable> table(ObjectHashTable::cast(
1801      weak_collection->table()));
1802  RUNTIME_ASSERT(table->IsKey(*key));
1803  bool was_present = false;
1804  Handle<ObjectHashTable> new_table =
1805      ObjectHashTable::Remove(table, key, &was_present);
1806  weak_collection->set_table(*new_table);
1807  return isolate->heap()->ToBoolean(was_present);
1808}
1809
1810
1811RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
1812  HandleScope scope(isolate);
1813  DCHECK(args.length() == 3);
1814  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1815  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1816  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1817  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1818  Handle<ObjectHashTable> table(
1819      ObjectHashTable::cast(weak_collection->table()));
1820  RUNTIME_ASSERT(table->IsKey(*key));
1821  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1822  weak_collection->set_table(*new_table);
1823  return *weak_collection;
1824}
1825
1826
1827RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
1828  HandleScope scope(isolate);
1829  DCHECK(args.length() == 1);
1830  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
1831  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1832  Handle<FixedArray> values =
1833      isolate->factory()->NewFixedArray(table->NumberOfElements());
1834  {
1835    DisallowHeapAllocation no_gc;
1836    int number_of_non_hole_elements = 0;
1837    for (int i = 0; i < table->Capacity(); i++) {
1838      Handle<Object> key(table->KeyAt(i), isolate);
1839      if (table->IsKey(*key)) {
1840        values->set(number_of_non_hole_elements++, *key);
1841      }
1842    }
1843    DCHECK_EQ(table->NumberOfElements(), number_of_non_hole_elements);
1844  }
1845  return *isolate->factory()->NewJSArrayWithElements(values);
1846}
1847
1848
1849RUNTIME_FUNCTION(Runtime_GetPrototype) {
1850  HandleScope scope(isolate);
1851  DCHECK(args.length() == 1);
1852  CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1853  // We don't expect access checks to be needed on JSProxy objects.
1854  DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1855  PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
1856  do {
1857    if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
1858        !isolate->MayNamedAccess(
1859            Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
1860            isolate->factory()->proto_string(), v8::ACCESS_GET)) {
1861      isolate->ReportFailedAccessCheck(
1862          Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
1863          v8::ACCESS_GET);
1864      RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1865      return isolate->heap()->undefined_value();
1866    }
1867    iter.AdvanceIgnoringProxies();
1868    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1869      return *PrototypeIterator::GetCurrent(iter);
1870    }
1871  } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
1872  return *PrototypeIterator::GetCurrent(iter);
1873}
1874
1875
1876static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
1877    Isolate* isolate, Handle<Object> receiver) {
1878  PrototypeIterator iter(isolate, receiver);
1879  while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
1880    if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1881      return PrototypeIterator::GetCurrent(iter);
1882    }
1883    iter.Advance();
1884  }
1885  return PrototypeIterator::GetCurrent(iter);
1886}
1887
1888
1889RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
1890  HandleScope scope(isolate);
1891  DCHECK(args.length() == 2);
1892  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1893  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1894  DCHECK(!obj->IsAccessCheckNeeded());
1895  DCHECK(!obj->map()->is_observed());
1896  Handle<Object> result;
1897  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1898      isolate, result, JSObject::SetPrototype(obj, prototype, false));
1899  return *result;
1900}
1901
1902
1903RUNTIME_FUNCTION(Runtime_SetPrototype) {
1904  HandleScope scope(isolate);
1905  DCHECK(args.length() == 2);
1906  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1907  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1908  if (obj->IsAccessCheckNeeded() &&
1909      !isolate->MayNamedAccess(
1910          obj, isolate->factory()->proto_string(), v8::ACCESS_SET)) {
1911    isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET);
1912    RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1913    return isolate->heap()->undefined_value();
1914  }
1915  if (obj->map()->is_observed()) {
1916    Handle<Object> old_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
1917    Handle<Object> result;
1918    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1919        isolate, result,
1920        JSObject::SetPrototype(obj, prototype, true));
1921
1922    Handle<Object> new_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
1923    if (!new_value->SameValue(*old_value)) {
1924      JSObject::EnqueueChangeRecord(obj, "setPrototype",
1925                                    isolate->factory()->proto_string(),
1926                                    old_value);
1927    }
1928    return *result;
1929  }
1930  Handle<Object> result;
1931  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1932      isolate, result,
1933      JSObject::SetPrototype(obj, prototype, true));
1934  return *result;
1935}
1936
1937
1938RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
1939  HandleScope shs(isolate);
1940  DCHECK(args.length() == 2);
1941  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1942  CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
1943  CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
1944  PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
1945  while (true) {
1946    iter.AdvanceIgnoringProxies();
1947    if (iter.IsAtEnd()) return isolate->heap()->false_value();
1948    if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
1949  }
1950}
1951
1952
1953// Enumerator used as indices into the array returned from GetOwnProperty
1954enum PropertyDescriptorIndices {
1955  IS_ACCESSOR_INDEX,
1956  VALUE_INDEX,
1957  GETTER_INDEX,
1958  SETTER_INDEX,
1959  WRITABLE_INDEX,
1960  ENUMERABLE_INDEX,
1961  CONFIGURABLE_INDEX,
1962  DESCRIPTOR_SIZE
1963};
1964
1965
1966MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
1967                                                          Handle<JSObject> obj,
1968                                                          Handle<Name> name) {
1969  Heap* heap = isolate->heap();
1970  Factory* factory = isolate->factory();
1971
1972  PropertyAttributes attrs;
1973  uint32_t index = 0;
1974  Handle<Object> value;
1975  MaybeHandle<AccessorPair> maybe_accessors;
1976  // TODO(verwaest): Unify once indexed properties can be handled by the
1977  // LookupIterator.
1978  if (name->AsArrayIndex(&index)) {
1979    // Get attributes.
1980    Maybe<PropertyAttributes> maybe =
1981        JSReceiver::GetOwnElementAttribute(obj, index);
1982    if (!maybe.has_value) return MaybeHandle<Object>();
1983    attrs = maybe.value;
1984    if (attrs == ABSENT) return factory->undefined_value();
1985
1986    // Get AccessorPair if present.
1987    maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index);
1988
1989    // Get value if not an AccessorPair.
1990    if (maybe_accessors.is_null()) {
1991      ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
1992          Runtime::GetElementOrCharAt(isolate, obj, index), Object);
1993    }
1994  } else {
1995    // Get attributes.
1996    LookupIterator it(obj, name, LookupIterator::HIDDEN);
1997    Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
1998    if (!maybe.has_value) return MaybeHandle<Object>();
1999    attrs = maybe.value;
2000    if (attrs == ABSENT) return factory->undefined_value();
2001
2002    // Get AccessorPair if present.
2003    if (it.state() == LookupIterator::ACCESSOR &&
2004        it.GetAccessors()->IsAccessorPair()) {
2005      maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors());
2006    }
2007
2008    // Get value if not an AccessorPair.
2009    if (maybe_accessors.is_null()) {
2010      ASSIGN_RETURN_ON_EXCEPTION(
2011          isolate, value, Object::GetProperty(&it), Object);
2012    }
2013  }
2014  DCHECK(!isolate->has_pending_exception());
2015  Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
2016  elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
2017  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
2018  elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null()));
2019
2020  Handle<AccessorPair> accessors;
2021  if (maybe_accessors.ToHandle(&accessors)) {
2022    Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
2023    Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
2024    elms->set(GETTER_INDEX, *getter);
2025    elms->set(SETTER_INDEX, *setter);
2026  } else {
2027    elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
2028    elms->set(VALUE_INDEX, *value);
2029  }
2030
2031  return factory->NewJSArrayWithElements(elms);
2032}
2033
2034
2035// Returns an array with the property description:
2036//  if args[1] is not a property on args[0]
2037//          returns undefined
2038//  if args[1] is a data property on args[0]
2039//         [false, value, Writeable, Enumerable, Configurable]
2040//  if args[1] is an accessor on args[0]
2041//         [true, GetFunction, SetFunction, Enumerable, Configurable]
2042RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
2043  HandleScope scope(isolate);
2044  DCHECK(args.length() == 2);
2045  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2046  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2047  Handle<Object> result;
2048  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2049      isolate, result, GetOwnProperty(isolate, obj, name));
2050  return *result;
2051}
2052
2053
2054RUNTIME_FUNCTION(Runtime_PreventExtensions) {
2055  HandleScope scope(isolate);
2056  DCHECK(args.length() == 1);
2057  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2058  Handle<Object> result;
2059  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2060      isolate, result, JSObject::PreventExtensions(obj));
2061  return *result;
2062}
2063
2064
2065RUNTIME_FUNCTION(Runtime_ToMethod) {
2066  HandleScope scope(isolate);
2067  DCHECK(args.length() == 2);
2068  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
2069  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
2070  Handle<JSFunction> clone = JSFunction::CloneClosure(fun);
2071  Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
2072  JSObject::SetOwnPropertyIgnoreAttributes(clone, home_object_symbol,
2073                                           home_object, DONT_ENUM).Assert();
2074  return *clone;
2075}
2076
2077
2078RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
2079  DCHECK(args.length() == 0);
2080  return isolate->heap()->home_object_symbol();
2081}
2082
2083
2084RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
2085  HandleScope scope(isolate);
2086  DCHECK(args.length() == 3);
2087  CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 0);
2088  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
2089  CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
2090
2091  if (home_object->IsAccessCheckNeeded() &&
2092      !isolate->MayNamedAccess(home_object, name, v8::ACCESS_GET)) {
2093    isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_GET);
2094    RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2095  }
2096
2097  PrototypeIterator iter(isolate, home_object);
2098  Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
2099  if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
2100
2101  LookupIterator it(receiver, name, Handle<JSReceiver>::cast(proto));
2102  Handle<Object> result;
2103  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
2104  return *result;
2105}
2106
2107
2108RUNTIME_FUNCTION(Runtime_IsExtensible) {
2109  SealHandleScope shs(isolate);
2110  DCHECK(args.length() == 1);
2111  CONVERT_ARG_CHECKED(JSObject, obj, 0);
2112  if (obj->IsJSGlobalProxy()) {
2113    PrototypeIterator iter(isolate, obj);
2114    if (iter.IsAtEnd()) return isolate->heap()->false_value();
2115    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
2116    obj = JSObject::cast(iter.GetCurrent());
2117  }
2118  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
2119}
2120
2121
2122RUNTIME_FUNCTION(Runtime_RegExpCompile) {
2123  HandleScope scope(isolate);
2124  DCHECK(args.length() == 3);
2125  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
2126  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
2127  CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
2128  Handle<Object> result;
2129  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2130      isolate, result, RegExpImpl::Compile(re, pattern, flags));
2131  return *result;
2132}
2133
2134
2135RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
2136  HandleScope scope(isolate);
2137  DCHECK(args.length() == 2);
2138  CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
2139  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
2140  return *isolate->factory()->CreateApiFunction(data, prototype);
2141}
2142
2143
2144RUNTIME_FUNCTION(Runtime_IsTemplate) {
2145  SealHandleScope shs(isolate);
2146  DCHECK(args.length() == 1);
2147  CONVERT_ARG_HANDLE_CHECKED(Object, arg, 0);
2148  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
2149  return isolate->heap()->ToBoolean(result);
2150}
2151
2152
2153RUNTIME_FUNCTION(Runtime_GetTemplateField) {
2154  SealHandleScope shs(isolate);
2155  DCHECK(args.length() == 2);
2156  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
2157  CONVERT_SMI_ARG_CHECKED(index, 1);
2158  int offset = index * kPointerSize + HeapObject::kHeaderSize;
2159  InstanceType type = templ->map()->instance_type();
2160  RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
2161                 type == OBJECT_TEMPLATE_INFO_TYPE);
2162  RUNTIME_ASSERT(offset > 0);
2163  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
2164    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
2165  } else {
2166    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
2167  }
2168  return *HeapObject::RawField(templ, offset);
2169}
2170
2171
2172RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
2173  HandleScope scope(isolate);
2174  DCHECK(args.length() == 1);
2175  CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
2176  Handle<Map> old_map(object->map());
2177  bool needs_access_checks = old_map->is_access_check_needed();
2178  if (needs_access_checks) {
2179    // Copy map so it won't interfere constructor's initial map.
2180    Handle<Map> new_map = Map::Copy(old_map);
2181    new_map->set_is_access_check_needed(false);
2182    JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
2183  }
2184  return isolate->heap()->ToBoolean(needs_access_checks);
2185}
2186
2187
2188RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
2189  HandleScope scope(isolate);
2190  DCHECK(args.length() == 1);
2191  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2192  Handle<Map> old_map(object->map());
2193  RUNTIME_ASSERT(!old_map->is_access_check_needed());
2194  // Copy map so it won't interfere constructor's initial map.
2195  Handle<Map> new_map = Map::Copy(old_map);
2196  new_map->set_is_access_check_needed(true);
2197  JSObject::MigrateToMap(object, new_map);
2198  return isolate->heap()->undefined_value();
2199}
2200
2201
2202static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
2203  HandleScope scope(isolate);
2204  Handle<Object> args[1] = { name };
2205  THROW_NEW_ERROR_RETURN_FAILURE(
2206      isolate, NewTypeError("var_redeclaration", HandleVector(args, 1)));
2207}
2208
2209
2210// May throw a RedeclarationError.
2211static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
2212                              Handle<String> name, Handle<Object> value,
2213                              PropertyAttributes attr, bool is_var,
2214                              bool is_const, bool is_function) {
2215  // Do the lookup own properties only, see ES5 erratum.
2216  LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
2217  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
2218  if (!maybe.has_value) return isolate->heap()->exception();
2219
2220  if (it.IsFound()) {
2221    PropertyAttributes old_attributes = maybe.value;
2222    // The name was declared before; check for conflicting re-declarations.
2223    if (is_const) return ThrowRedeclarationError(isolate, name);
2224
2225    // Skip var re-declarations.
2226    if (is_var) return isolate->heap()->undefined_value();
2227
2228    DCHECK(is_function);
2229    if ((old_attributes & DONT_DELETE) != 0) {
2230      // Only allow reconfiguring globals to functions in user code (no
2231      // natives, which are marked as read-only).
2232      DCHECK((attr & READ_ONLY) == 0);
2233
2234      // Check whether we can reconfigure the existing property into a
2235      // function.
2236      PropertyDetails old_details = it.property_details();
2237      // TODO(verwaest): CALLBACKS invalidly includes ExecutableAccessInfo,
2238      // which are actually data properties, not accessor properties.
2239      if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
2240          old_details.type() == CALLBACKS) {
2241        return ThrowRedeclarationError(isolate, name);
2242      }
2243      // If the existing property is not configurable, keep its attributes. Do
2244      attr = old_attributes;
2245    }
2246  }
2247
2248  // Define or redefine own property.
2249  RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2250                                           global, name, value, attr));
2251
2252  return isolate->heap()->undefined_value();
2253}
2254
2255
2256RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
2257  HandleScope scope(isolate);
2258  DCHECK(args.length() == 3);
2259  Handle<GlobalObject> global(isolate->global_object());
2260
2261  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
2262  CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2263  CONVERT_SMI_ARG_CHECKED(flags, 2);
2264
2265  // Traverse the name/value pairs and set the properties.
2266  int length = pairs->length();
2267  for (int i = 0; i < length; i += 2) {
2268    HandleScope scope(isolate);
2269    Handle<String> name(String::cast(pairs->get(i)));
2270    Handle<Object> initial_value(pairs->get(i + 1), isolate);
2271
2272    // We have to declare a global const property. To capture we only
2273    // assign to it when evaluating the assignment for "const x =
2274    // <expr>" the initial value is the hole.
2275    bool is_var = initial_value->IsUndefined();
2276    bool is_const = initial_value->IsTheHole();
2277    bool is_function = initial_value->IsSharedFunctionInfo();
2278    DCHECK(is_var + is_const + is_function == 1);
2279
2280    Handle<Object> value;
2281    if (is_function) {
2282      // Copy the function and update its context. Use it as value.
2283      Handle<SharedFunctionInfo> shared =
2284          Handle<SharedFunctionInfo>::cast(initial_value);
2285      Handle<JSFunction> function =
2286          isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
2287                                                                TENURED);
2288      value = function;
2289    } else {
2290      value = isolate->factory()->undefined_value();
2291    }
2292
2293    // Compute the property attributes. According to ECMA-262,
2294    // the property must be non-configurable except in eval.
2295    bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2296    bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2297    int attr = NONE;
2298    if (is_const) attr |= READ_ONLY;
2299    if (is_function && is_native) attr |= READ_ONLY;
2300    if (!is_const && !is_eval) attr |= DONT_DELETE;
2301
2302    Object* result = DeclareGlobals(isolate, global, name, value,
2303                                    static_cast<PropertyAttributes>(attr),
2304                                    is_var, is_const, is_function);
2305    if (isolate->has_pending_exception()) return result;
2306  }
2307
2308  return isolate->heap()->undefined_value();
2309}
2310
2311
2312RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
2313  HandleScope scope(isolate);
2314  // args[0] == name
2315  // args[1] == language_mode
2316  // args[2] == value (optional)
2317
2318  // Determine if we need to assign to the variable if it already
2319  // exists (based on the number of arguments).
2320  RUNTIME_ASSERT(args.length() == 3);
2321
2322  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2323  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
2324  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2325
2326  Handle<GlobalObject> global(isolate->context()->global_object());
2327  Handle<Object> result;
2328  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2329      isolate, result, Object::SetProperty(global, name, value, strict_mode));
2330  return *result;
2331}
2332
2333
2334RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
2335  HandleScope handle_scope(isolate);
2336  // All constants are declared with an initial value. The name
2337  // of the constant is the first argument and the initial value
2338  // is the second.
2339  RUNTIME_ASSERT(args.length() == 2);
2340  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2341  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2342
2343  Handle<GlobalObject> global = isolate->global_object();
2344
2345  // Lookup the property as own on the global object.
2346  LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
2347  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
2348  DCHECK(maybe.has_value);
2349  PropertyAttributes old_attributes = maybe.value;
2350
2351  PropertyAttributes attr =
2352      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2353  // Set the value if the property is either missing, or the property attributes
2354  // allow setting the value without invoking an accessor.
2355  if (it.IsFound()) {
2356    // Ignore if we can't reconfigure the value.
2357    if ((old_attributes & DONT_DELETE) != 0) {
2358      if ((old_attributes & READ_ONLY) != 0 ||
2359          it.state() == LookupIterator::ACCESSOR) {
2360        return *value;
2361      }
2362      attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
2363    }
2364  }
2365
2366  RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2367                                           global, name, value, attr));
2368
2369  return *value;
2370}
2371
2372
2373RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
2374  HandleScope scope(isolate);
2375  DCHECK(args.length() == 4);
2376
2377  // Declarations are always made in a function, native, or global context. In
2378  // the case of eval code, the context passed is the context of the caller,
2379  // which may be some nested context and not the declaration context.
2380  CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
2381  Handle<Context> context(context_arg->declaration_context());
2382  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
2383  CONVERT_SMI_ARG_CHECKED(attr_arg, 2);
2384  PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg);
2385  RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE);
2386  CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
2387
2388  // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
2389  bool is_var = *initial_value == NULL;
2390  bool is_const = initial_value->IsTheHole();
2391  bool is_function = initial_value->IsJSFunction();
2392  DCHECK(is_var + is_const + is_function == 1);
2393
2394  int index;
2395  PropertyAttributes attributes;
2396  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2397  BindingFlags binding_flags;
2398  Handle<Object> holder =
2399      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2400
2401  Handle<JSObject> object;
2402  Handle<Object> value =
2403      is_function ? initial_value
2404                  : Handle<Object>::cast(isolate->factory()->undefined_value());
2405
2406  // TODO(verwaest): This case should probably not be covered by this function,
2407  // but by DeclareGlobals instead.
2408  if ((attributes != ABSENT && holder->IsJSGlobalObject()) ||
2409      (context_arg->has_extension() &&
2410       context_arg->extension()->IsJSGlobalObject())) {
2411    return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
2412                          value, attr, is_var, is_const, is_function);
2413  }
2414
2415  if (attributes != ABSENT) {
2416    // The name was declared before; check for conflicting re-declarations.
2417    if (is_const || (attributes & READ_ONLY) != 0) {
2418      return ThrowRedeclarationError(isolate, name);
2419    }
2420
2421    // Skip var re-declarations.
2422    if (is_var) return isolate->heap()->undefined_value();
2423
2424    DCHECK(is_function);
2425    if (index >= 0) {
2426      DCHECK(holder.is_identical_to(context));
2427      context->set(index, *initial_value);
2428      return isolate->heap()->undefined_value();
2429    }
2430
2431    object = Handle<JSObject>::cast(holder);
2432
2433  } else if (context->has_extension()) {
2434    object = handle(JSObject::cast(context->extension()));
2435    DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
2436  } else {
2437    DCHECK(context->IsFunctionContext());
2438    object =
2439        isolate->factory()->NewJSObject(isolate->context_extension_function());
2440    context->set_extension(*object);
2441  }
2442
2443  RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2444                                           object, name, value, attr));
2445
2446  return isolate->heap()->undefined_value();
2447}
2448
2449
2450RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
2451  HandleScope scope(isolate);
2452  DCHECK(args.length() == 3);
2453
2454  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
2455  DCHECK(!value->IsTheHole());
2456  // Initializations are always done in a function or native context.
2457  CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
2458  Handle<Context> context(context_arg->declaration_context());
2459  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
2460
2461  int index;
2462  PropertyAttributes attributes;
2463  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2464  BindingFlags binding_flags;
2465  Handle<Object> holder =
2466      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2467
2468  if (index >= 0) {
2469    DCHECK(holder->IsContext());
2470    // Property was found in a context.  Perform the assignment if the constant
2471    // was uninitialized.
2472    Handle<Context> context = Handle<Context>::cast(holder);
2473    DCHECK((attributes & READ_ONLY) != 0);
2474    if (context->get(index)->IsTheHole()) context->set(index, *value);
2475    return *value;
2476  }
2477
2478  PropertyAttributes attr =
2479      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2480
2481  // Strict mode handling not needed (legacy const is disallowed in strict
2482  // mode).
2483
2484  // The declared const was configurable, and may have been deleted in the
2485  // meanwhile. If so, re-introduce the variable in the context extension.
2486  DCHECK(context_arg->has_extension());
2487  if (attributes == ABSENT) {
2488    holder = handle(context_arg->extension(), isolate);
2489  } else {
2490    // For JSContextExtensionObjects, the initializer can be run multiple times
2491    // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
2492    // first assignment should go through. For JSGlobalObjects, additionally any
2493    // code can run in between that modifies the declared property.
2494    DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
2495
2496    LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
2497    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
2498    if (!maybe.has_value) return isolate->heap()->exception();
2499    PropertyAttributes old_attributes = maybe.value;
2500
2501    // Ignore if we can't reconfigure the value.
2502    if ((old_attributes & DONT_DELETE) != 0) {
2503      if ((old_attributes & READ_ONLY) != 0 ||
2504          it.state() == LookupIterator::ACCESSOR) {
2505        return *value;
2506      }
2507      attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
2508    }
2509  }
2510
2511  RETURN_FAILURE_ON_EXCEPTION(
2512      isolate, JSObject::SetOwnPropertyIgnoreAttributes(
2513                   Handle<JSObject>::cast(holder), name, value, attr));
2514
2515  return *value;
2516}
2517
2518
2519RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
2520  HandleScope scope(isolate);
2521  DCHECK(args.length() == 2);
2522  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2523  CONVERT_SMI_ARG_CHECKED(properties, 1);
2524  // Conservative upper limit to prevent fuzz tests from going OOM.
2525  RUNTIME_ASSERT(properties <= 100000);
2526  if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
2527    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2528  }
2529  return *object;
2530}
2531
2532
2533RUNTIME_FUNCTION(Runtime_RegExpExecRT) {
2534  HandleScope scope(isolate);
2535  DCHECK(args.length() == 4);
2536  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2537  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2538  CONVERT_INT32_ARG_CHECKED(index, 2);
2539  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2540  // Due to the way the JS calls are constructed this must be less than the
2541  // length of a string, i.e. it is always a Smi.  We check anyway for security.
2542  RUNTIME_ASSERT(index >= 0);
2543  RUNTIME_ASSERT(index <= subject->length());
2544  isolate->counters()->regexp_entry_runtime()->Increment();
2545  Handle<Object> result;
2546  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2547      isolate, result,
2548      RegExpImpl::Exec(regexp, subject, index, last_match_info));
2549  return *result;
2550}
2551
2552
2553RUNTIME_FUNCTION(Runtime_RegExpConstructResult) {
2554  HandleScope handle_scope(isolate);
2555  DCHECK(args.length() == 3);
2556  CONVERT_SMI_ARG_CHECKED(size, 0);
2557  RUNTIME_ASSERT(size >= 0 && size <= FixedArray::kMaxLength);
2558  CONVERT_ARG_HANDLE_CHECKED(Object, index, 1);
2559  CONVERT_ARG_HANDLE_CHECKED(Object, input, 2);
2560  Handle<FixedArray> elements =  isolate->factory()->NewFixedArray(size);
2561  Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
2562  Handle<JSObject> object =
2563      isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false);
2564  Handle<JSArray> array = Handle<JSArray>::cast(object);
2565  array->set_elements(*elements);
2566  array->set_length(Smi::FromInt(size));
2567  // Write in-object properties after the length of the array.
2568  array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, *index);
2569  array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input);
2570  return *array;
2571}
2572
2573
2574RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) {
2575  HandleScope scope(isolate);
2576  DCHECK(args.length() == 6);
2577  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2578  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2579  // If source is the empty string we set it to "(?:)" instead as
2580  // suggested by ECMA-262, 5th, section 15.10.4.1.
2581  if (source->length() == 0) source = isolate->factory()->query_colon_string();
2582
2583  CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2584  if (!global->IsTrue()) global = isolate->factory()->false_value();
2585
2586  CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2587  if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2588
2589  CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2590  if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2591
2592  CONVERT_ARG_HANDLE_CHECKED(Object, sticky, 5);
2593  if (!sticky->IsTrue()) sticky = isolate->factory()->false_value();
2594
2595  Map* map = regexp->map();
2596  Object* constructor = map->constructor();
2597  if (!FLAG_harmony_regexps &&
2598      constructor->IsJSFunction() &&
2599      JSFunction::cast(constructor)->initial_map() == map) {
2600    // If we still have the original map, set in-object properties directly.
2601    regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2602    // Both true and false are immovable immortal objects so no need for write
2603    // barrier.
2604    regexp->InObjectPropertyAtPut(
2605        JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER);
2606    regexp->InObjectPropertyAtPut(
2607        JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER);
2608    regexp->InObjectPropertyAtPut(
2609        JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER);
2610    regexp->InObjectPropertyAtPut(
2611        JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2612    return *regexp;
2613  }
2614
2615  // Map has changed, so use generic, but slower, method.  We also end here if
2616  // the --harmony-regexp flag is set, because the initial map does not have
2617  // space for the 'sticky' flag, since it is from the snapshot, but must work
2618  // both with and without --harmony-regexp.  When sticky comes out from under
2619  // the flag, we will be able to use the fast initial map.
2620  PropertyAttributes final =
2621      static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2622  PropertyAttributes writable =
2623      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2624  Handle<Object> zero(Smi::FromInt(0), isolate);
2625  Factory* factory = isolate->factory();
2626  JSObject::SetOwnPropertyIgnoreAttributes(
2627      regexp, factory->source_string(), source, final).Check();
2628  JSObject::SetOwnPropertyIgnoreAttributes(
2629      regexp, factory->global_string(), global, final).Check();
2630  JSObject::SetOwnPropertyIgnoreAttributes(
2631      regexp, factory->ignore_case_string(), ignoreCase, final).Check();
2632  JSObject::SetOwnPropertyIgnoreAttributes(
2633      regexp, factory->multiline_string(), multiline, final).Check();
2634  if (FLAG_harmony_regexps) {
2635    JSObject::SetOwnPropertyIgnoreAttributes(
2636        regexp, factory->sticky_string(), sticky, final).Check();
2637  }
2638  JSObject::SetOwnPropertyIgnoreAttributes(
2639      regexp, factory->last_index_string(), zero, writable).Check();
2640  return *regexp;
2641}
2642
2643
2644RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
2645  HandleScope scope(isolate);
2646  DCHECK(args.length() == 1);
2647  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2648  Object* length = prototype->length();
2649  RUNTIME_ASSERT(length->IsSmi() && Smi::cast(length)->value() == 0);
2650  RUNTIME_ASSERT(prototype->HasFastSmiOrObjectElements());
2651  // This is necessary to enable fast checks for absence of elements
2652  // on Array.prototype and below.
2653  prototype->set_elements(isolate->heap()->empty_fixed_array());
2654  return Smi::FromInt(0);
2655}
2656
2657
2658static void InstallBuiltin(Isolate* isolate,
2659                           Handle<JSObject> holder,
2660                           const char* name,
2661                           Builtins::Name builtin_name) {
2662  Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2663  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2664  Handle<JSFunction> optimized =
2665      isolate->factory()->NewFunctionWithoutPrototype(key, code);
2666  optimized->shared()->DontAdaptArguments();
2667  JSObject::AddProperty(holder, key, optimized, NONE);
2668}
2669
2670
2671RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
2672  HandleScope scope(isolate);
2673  DCHECK(args.length() == 0);
2674  Handle<JSObject> holder =
2675      isolate->factory()->NewJSObject(isolate->object_function());
2676
2677  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2678  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2679  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2680  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2681  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2682  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2683  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2684
2685  return *holder;
2686}
2687
2688
2689RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction) {
2690  SealHandleScope shs(isolate);
2691  DCHECK(args.length() == 1);
2692  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2693  if (!callable->IsJSFunction()) {
2694    HandleScope scope(isolate);
2695    Handle<Object> delegate;
2696    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2697        isolate, delegate,
2698        Execution::TryGetFunctionDelegate(
2699            isolate, Handle<JSReceiver>(callable)));
2700    callable = JSFunction::cast(*delegate);
2701  }
2702  JSFunction* function = JSFunction::cast(callable);
2703  SharedFunctionInfo* shared = function->shared();
2704  return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
2705}
2706
2707
2708RUNTIME_FUNCTION(Runtime_GetDefaultReceiver) {
2709  SealHandleScope shs(isolate);
2710  DCHECK(args.length() == 1);
2711  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2712
2713  if (!callable->IsJSFunction()) {
2714    HandleScope scope(isolate);
2715    Handle<Object> delegate;
2716    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2717        isolate, delegate,
2718        Execution::TryGetFunctionDelegate(
2719            isolate, Handle<JSReceiver>(callable)));
2720    callable = JSFunction::cast(*delegate);
2721  }
2722  JSFunction* function = JSFunction::cast(callable);
2723
2724  SharedFunctionInfo* shared = function->shared();
2725  if (shared->native() || shared->strict_mode() == STRICT) {
2726    return isolate->heap()->undefined_value();
2727  }
2728  // Returns undefined for strict or native functions, or
2729  // the associated global receiver for "normal" functions.
2730
2731  return function->global_proxy();
2732}
2733
2734
2735RUNTIME_FUNCTION(Runtime_MaterializeRegExpLiteral) {
2736  HandleScope scope(isolate);
2737  DCHECK(args.length() == 4);
2738  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2739  CONVERT_SMI_ARG_CHECKED(index, 1);
2740  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
2741  CONVERT_ARG_HANDLE_CHECKED(String, flags, 3);
2742
2743  // Get the RegExp function from the context in the literals array.
2744  // This is the RegExp function from the context in which the
2745  // function was created.  We do not use the RegExp function from the
2746  // current native context because this might be the RegExp function
2747  // from another context which we should not have access to.
2748  Handle<JSFunction> constructor =
2749      Handle<JSFunction>(
2750          JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2751  // Compute the regular expression literal.
2752  Handle<Object> regexp;
2753  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2754      isolate, regexp,
2755      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags));
2756  literals->set(index, *regexp);
2757  return *regexp;
2758}
2759
2760
2761RUNTIME_FUNCTION(Runtime_FunctionGetName) {
2762  SealHandleScope shs(isolate);
2763  DCHECK(args.length() == 1);
2764
2765  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2766  return f->shared()->name();
2767}
2768
2769
2770RUNTIME_FUNCTION(Runtime_FunctionSetName) {
2771  SealHandleScope shs(isolate);
2772  DCHECK(args.length() == 2);
2773
2774  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2775  CONVERT_ARG_CHECKED(String, name, 1);
2776  f->shared()->set_name(name);
2777  return isolate->heap()->undefined_value();
2778}
2779
2780
2781RUNTIME_FUNCTION(Runtime_FunctionNameShouldPrintAsAnonymous) {
2782  SealHandleScope shs(isolate);
2783  DCHECK(args.length() == 1);
2784  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2785  return isolate->heap()->ToBoolean(
2786      f->shared()->name_should_print_as_anonymous());
2787}
2788
2789
2790RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2791  SealHandleScope shs(isolate);
2792  DCHECK(args.length() == 1);
2793  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2794  f->shared()->set_name_should_print_as_anonymous(true);
2795  return isolate->heap()->undefined_value();
2796}
2797
2798
2799RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) {
2800  SealHandleScope shs(isolate);
2801  DCHECK(args.length() == 1);
2802  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2803  return isolate->heap()->ToBoolean(f->shared()->is_generator());
2804}
2805
2806
2807RUNTIME_FUNCTION(Runtime_FunctionIsArrow) {
2808  SealHandleScope shs(isolate);
2809  DCHECK(args.length() == 1);
2810  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2811  return isolate->heap()->ToBoolean(f->shared()->is_arrow());
2812}
2813
2814
2815RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) {
2816  SealHandleScope shs(isolate);
2817  DCHECK(args.length() == 1);
2818  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2819  return isolate->heap()->ToBoolean(f->shared()->is_concise_method());
2820}
2821
2822
2823RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
2824  SealHandleScope shs(isolate);
2825  DCHECK(args.length() == 1);
2826
2827  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2828  RUNTIME_ASSERT(f->RemovePrototype());
2829
2830  return isolate->heap()->undefined_value();
2831}
2832
2833
2834RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
2835  HandleScope scope(isolate);
2836  DCHECK(args.length() == 1);
2837
2838  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2839  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2840  if (!script->IsScript()) return isolate->heap()->undefined_value();
2841
2842  return *Script::GetWrapper(Handle<Script>::cast(script));
2843}
2844
2845
2846RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
2847  HandleScope scope(isolate);
2848  DCHECK(args.length() == 1);
2849
2850  CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2851  Handle<SharedFunctionInfo> shared(f->shared());
2852  return *shared->GetSourceCode();
2853}
2854
2855
2856RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
2857  SealHandleScope shs(isolate);
2858  DCHECK(args.length() == 1);
2859
2860  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2861  int pos = fun->shared()->start_position();
2862  return Smi::FromInt(pos);
2863}
2864
2865
2866RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) {
2867  SealHandleScope shs(isolate);
2868  DCHECK(args.length() == 2);
2869
2870  CONVERT_ARG_CHECKED(Code, code, 0);
2871  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2872
2873  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2874
2875  Address pc = code->address() + offset;
2876  return Smi::FromInt(code->SourcePosition(pc));
2877}
2878
2879
2880RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
2881  SealHandleScope shs(isolate);
2882  DCHECK(args.length() == 2);
2883
2884  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2885  CONVERT_ARG_CHECKED(String, name, 1);
2886  fun->SetInstanceClassName(name);
2887  return isolate->heap()->undefined_value();
2888}
2889
2890
2891RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
2892  SealHandleScope shs(isolate);
2893  DCHECK(args.length() == 2);
2894
2895  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2896  CONVERT_SMI_ARG_CHECKED(length, 1);
2897  RUNTIME_ASSERT((length & 0xC0000000) == 0xC0000000 ||
2898                 (length & 0xC0000000) == 0x0);
2899  fun->shared()->set_length(length);
2900  return isolate->heap()->undefined_value();
2901}
2902
2903
2904RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
2905  HandleScope scope(isolate);
2906  DCHECK(args.length() == 2);
2907
2908  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
2909  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2910  RUNTIME_ASSERT(fun->should_have_prototype());
2911  Accessors::FunctionSetPrototype(fun, value);
2912  return args[0];  // return TOS
2913}
2914
2915
2916RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
2917  SealHandleScope shs(isolate);
2918  DCHECK(args.length() == 1);
2919
2920  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2921  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2922}
2923
2924
2925RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) {
2926  SealHandleScope shs(isolate);
2927  DCHECK(args.length() == 1);
2928
2929  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2930  return isolate->heap()->ToBoolean(f->IsBuiltin());
2931}
2932
2933
2934RUNTIME_FUNCTION(Runtime_SetCode) {
2935  HandleScope scope(isolate);
2936  DCHECK(args.length() == 2);
2937
2938  CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2939  CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
2940
2941  Handle<SharedFunctionInfo> target_shared(target->shared());
2942  Handle<SharedFunctionInfo> source_shared(source->shared());
2943  RUNTIME_ASSERT(!source_shared->bound());
2944
2945  if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
2946    return isolate->heap()->exception();
2947  }
2948
2949  // Mark both, the source and the target, as un-flushable because the
2950  // shared unoptimized code makes them impossible to enqueue in a list.
2951  DCHECK(target_shared->code()->gc_metadata() == NULL);
2952  DCHECK(source_shared->code()->gc_metadata() == NULL);
2953  target_shared->set_dont_flush(true);
2954  source_shared->set_dont_flush(true);
2955
2956  // Set the code, scope info, formal parameter count, and the length
2957  // of the target shared function info.
2958  target_shared->ReplaceCode(source_shared->code());
2959  target_shared->set_scope_info(source_shared->scope_info());
2960  target_shared->set_length(source_shared->length());
2961  target_shared->set_feedback_vector(source_shared->feedback_vector());
2962  target_shared->set_formal_parameter_count(
2963      source_shared->formal_parameter_count());
2964  target_shared->set_script(source_shared->script());
2965  target_shared->set_start_position_and_type(
2966      source_shared->start_position_and_type());
2967  target_shared->set_end_position(source_shared->end_position());
2968  bool was_native = target_shared->native();
2969  target_shared->set_compiler_hints(source_shared->compiler_hints());
2970  target_shared->set_native(was_native);
2971  target_shared->set_profiler_ticks(source_shared->profiler_ticks());
2972
2973  // Set the code of the target function.
2974  target->ReplaceCode(source_shared->code());
2975  DCHECK(target->next_function_link()->IsUndefined());
2976
2977  // Make sure we get a fresh copy of the literal vector to avoid cross
2978  // context contamination.
2979  Handle<Context> context(source->context());
2980  int number_of_literals = source->NumberOfLiterals();
2981  Handle<FixedArray> literals =
2982      isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2983  if (number_of_literals > 0) {
2984    literals->set(JSFunction::kLiteralNativeContextIndex,
2985                  context->native_context());
2986  }
2987  target->set_context(*context);
2988  target->set_literals(*literals);
2989
2990  if (isolate->logger()->is_logging_code_events() ||
2991      isolate->cpu_profiler()->is_profiling()) {
2992    isolate->logger()->LogExistingFunction(
2993        source_shared, Handle<Code>(source_shared->code()));
2994  }
2995
2996  return *target;
2997}
2998
2999
3000RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
3001  HandleScope scope(isolate);
3002  DCHECK(args.length() == 0);
3003
3004  JavaScriptFrameIterator it(isolate);
3005  JavaScriptFrame* frame = it.frame();
3006  Handle<JSFunction> function(frame->function());
3007  RUNTIME_ASSERT(function->shared()->is_generator());
3008
3009  Handle<JSGeneratorObject> generator;
3010  if (frame->IsConstructor()) {
3011    generator = handle(JSGeneratorObject::cast(frame->receiver()));
3012  } else {
3013    generator = isolate->factory()->NewJSGeneratorObject(function);
3014  }
3015  generator->set_function(*function);
3016  generator->set_context(Context::cast(frame->context()));
3017  generator->set_receiver(frame->receiver());
3018  generator->set_continuation(0);
3019  generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3020  generator->set_stack_handler_index(-1);
3021
3022  return *generator;
3023}
3024
3025
3026RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
3027  HandleScope handle_scope(isolate);
3028  DCHECK(args.length() == 1);
3029  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
3030
3031  JavaScriptFrameIterator stack_iterator(isolate);
3032  JavaScriptFrame* frame = stack_iterator.frame();
3033  RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3034  DCHECK_EQ(frame->function(), generator_object->function());
3035
3036  // The caller should have saved the context and continuation already.
3037  DCHECK_EQ(generator_object->context(), Context::cast(frame->context()));
3038  DCHECK_LT(0, generator_object->continuation());
3039
3040  // We expect there to be at least two values on the operand stack: the return
3041  // value of the yield expression, and the argument to this runtime call.
3042  // Neither of those should be saved.
3043  int operands_count = frame->ComputeOperandsCount();
3044  DCHECK_GE(operands_count, 2);
3045  operands_count -= 2;
3046
3047  if (operands_count == 0) {
3048    // Although it's semantically harmless to call this function with an
3049    // operands_count of zero, it is also unnecessary.
3050    DCHECK_EQ(generator_object->operand_stack(),
3051              isolate->heap()->empty_fixed_array());
3052    DCHECK_EQ(generator_object->stack_handler_index(), -1);
3053    // If there are no operands on the stack, there shouldn't be a handler
3054    // active either.
3055    DCHECK(!frame->HasHandler());
3056  } else {
3057    int stack_handler_index = -1;
3058    Handle<FixedArray> operand_stack =
3059        isolate->factory()->NewFixedArray(operands_count);
3060    frame->SaveOperandStack(*operand_stack, &stack_handler_index);
3061    generator_object->set_operand_stack(*operand_stack);
3062    generator_object->set_stack_handler_index(stack_handler_index);
3063  }
3064
3065  return isolate->heap()->undefined_value();
3066}
3067
3068
3069// Note that this function is the slow path for resuming generators.  It is only
3070// called if the suspended activation had operands on the stack, stack handlers
3071// needing rewinding, or if the resume should throw an exception.  The fast path
3072// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3073// inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3074// called in any case, as it needs to reconstruct the stack frame and make space
3075// for arguments and operands.
3076RUNTIME_FUNCTION(Runtime_ResumeJSGeneratorObject) {
3077  SealHandleScope shs(isolate);
3078  DCHECK(args.length() == 3);
3079  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3080  CONVERT_ARG_CHECKED(Object, value, 1);
3081  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3082  JavaScriptFrameIterator stack_iterator(isolate);
3083  JavaScriptFrame* frame = stack_iterator.frame();
3084
3085  DCHECK_EQ(frame->function(), generator_object->function());
3086  DCHECK(frame->function()->is_compiled());
3087
3088  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
3089  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
3090
3091  Address pc = generator_object->function()->code()->instruction_start();
3092  int offset = generator_object->continuation();
3093  DCHECK(offset > 0);
3094  frame->set_pc(pc + offset);
3095  if (FLAG_enable_ool_constant_pool) {
3096    frame->set_constant_pool(
3097        generator_object->function()->code()->constant_pool());
3098  }
3099  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3100
3101  FixedArray* operand_stack = generator_object->operand_stack();
3102  int operands_count = operand_stack->length();
3103  if (operands_count != 0) {
3104    frame->RestoreOperandStack(operand_stack,
3105                               generator_object->stack_handler_index());
3106    generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3107    generator_object->set_stack_handler_index(-1);
3108  }
3109
3110  JSGeneratorObject::ResumeMode resume_mode =
3111      static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3112  switch (resume_mode) {
3113    case JSGeneratorObject::NEXT:
3114      return value;
3115    case JSGeneratorObject::THROW:
3116      return isolate->Throw(value);
3117  }
3118
3119  UNREACHABLE();
3120  return isolate->ThrowIllegalOperation();
3121}
3122
3123
3124RUNTIME_FUNCTION(Runtime_ThrowGeneratorStateError) {
3125  HandleScope scope(isolate);
3126  DCHECK(args.length() == 1);
3127  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3128  int continuation = generator->continuation();
3129  const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3130      "generator_finished" : "generator_running";
3131  Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3132  THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewError(message, argv));
3133}
3134
3135
3136RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
3137  HandleScope scope(isolate);
3138  DCHECK(args.length() == 1);
3139  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
3140
3141  // %ObjectFreeze is a fast path and these cases are handled elsewhere.
3142  RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
3143                 !object->map()->is_observed() &&
3144                 !object->IsJSProxy());
3145
3146  Handle<Object> result;
3147  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
3148  return *result;
3149}
3150
3151
3152RUNTIME_FUNCTION(Runtime_StringCharCodeAtRT) {
3153  HandleScope handle_scope(isolate);
3154  DCHECK(args.length() == 2);
3155
3156  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3157  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3158
3159  // Flatten the string.  If someone wants to get a char at an index
3160  // in a cons string, it is likely that more indices will be
3161  // accessed.
3162  subject = String::Flatten(subject);
3163
3164  if (i >= static_cast<uint32_t>(subject->length())) {
3165    return isolate->heap()->nan_value();
3166  }
3167
3168  return Smi::FromInt(subject->Get(i));
3169}
3170
3171
3172RUNTIME_FUNCTION(Runtime_CharFromCode) {
3173  HandleScope handlescope(isolate);
3174  DCHECK(args.length() == 1);
3175  if (args[0]->IsNumber()) {
3176    CONVERT_NUMBER_CHECKED(uint32_t, code, Uint32, args[0]);
3177    code &= 0xffff;
3178    return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
3179  }
3180  return isolate->heap()->empty_string();
3181}
3182
3183
3184class FixedArrayBuilder {
3185 public:
3186  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3187      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3188        length_(0),
3189        has_non_smi_elements_(false) {
3190    // Require a non-zero initial size. Ensures that doubling the size to
3191    // extend the array will work.
3192    DCHECK(initial_capacity > 0);
3193  }
3194
3195  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3196      : array_(backing_store),
3197        length_(0),
3198        has_non_smi_elements_(false) {
3199    // Require a non-zero initial size. Ensures that doubling the size to
3200    // extend the array will work.
3201    DCHECK(backing_store->length() > 0);
3202  }
3203
3204  bool HasCapacity(int elements) {
3205    int length = array_->length();
3206    int required_length = length_ + elements;
3207    return (length >= required_length);
3208  }
3209
3210  void EnsureCapacity(int elements) {
3211    int length = array_->length();
3212    int required_length = length_ + elements;
3213    if (length < required_length) {
3214      int new_length = length;
3215      do {
3216        new_length *= 2;
3217      } while (new_length < required_length);
3218      Handle<FixedArray> extended_array =
3219          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3220      array_->CopyTo(0, *extended_array, 0, length_);
3221      array_ = extended_array;
3222    }
3223  }
3224
3225  void Add(Object* value) {
3226    DCHECK(!value->IsSmi());
3227    DCHECK(length_ < capacity());
3228    array_->set(length_, value);
3229    length_++;
3230    has_non_smi_elements_ = true;
3231  }
3232
3233  void Add(Smi* value) {
3234    DCHECK(value->IsSmi());
3235    DCHECK(length_ < capacity());
3236    array_->set(length_, value);
3237    length_++;
3238  }
3239
3240  Handle<FixedArray> array() {
3241    return array_;
3242  }
3243
3244  int length() {
3245    return length_;
3246  }
3247
3248  int capacity() {
3249    return array_->length();
3250  }
3251
3252  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3253    JSArray::SetContent(target_array, array_);
3254    target_array->set_length(Smi::FromInt(length_));
3255    return target_array;
3256  }
3257
3258
3259 private:
3260  Handle<FixedArray> array_;
3261  int length_;
3262  bool has_non_smi_elements_;
3263};
3264
3265
3266// Forward declarations.
3267const int kStringBuilderConcatHelperLengthBits = 11;
3268const int kStringBuilderConcatHelperPositionBits = 19;
3269
3270template <typename schar>
3271static inline void StringBuilderConcatHelper(String*,
3272                                             schar*,
3273                                             FixedArray*,
3274                                             int);
3275
3276typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3277    StringBuilderSubstringLength;
3278typedef BitField<int,
3279                 kStringBuilderConcatHelperLengthBits,
3280                 kStringBuilderConcatHelperPositionBits>
3281    StringBuilderSubstringPosition;
3282
3283
3284class ReplacementStringBuilder {
3285 public:
3286  ReplacementStringBuilder(Heap* heap, Handle<String> subject,
3287                           int estimated_part_count)
3288      : heap_(heap),
3289        array_builder_(heap->isolate(), estimated_part_count),
3290        subject_(subject),
3291        character_count_(0),
3292        is_one_byte_(subject->IsOneByteRepresentation()) {
3293    // Require a non-zero initial size. Ensures that doubling the size to
3294    // extend the array will work.
3295    DCHECK(estimated_part_count > 0);
3296  }
3297
3298  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3299                                     int from,
3300                                     int to) {
3301    DCHECK(from >= 0);
3302    int length = to - from;
3303    DCHECK(length > 0);
3304    if (StringBuilderSubstringLength::is_valid(length) &&
3305        StringBuilderSubstringPosition::is_valid(from)) {
3306      int encoded_slice = StringBuilderSubstringLength::encode(length) |
3307          StringBuilderSubstringPosition::encode(from);
3308      builder->Add(Smi::FromInt(encoded_slice));
3309    } else {
3310      // Otherwise encode as two smis.
3311      builder->Add(Smi::FromInt(-length));
3312      builder->Add(Smi::FromInt(from));
3313    }
3314  }
3315
3316
3317  void EnsureCapacity(int elements) {
3318    array_builder_.EnsureCapacity(elements);
3319  }
3320
3321
3322  void AddSubjectSlice(int from, int to) {
3323    AddSubjectSlice(&array_builder_, from, to);
3324    IncrementCharacterCount(to - from);
3325  }
3326
3327
3328  void AddString(Handle<String> string) {
3329    int length = string->length();
3330    DCHECK(length > 0);
3331    AddElement(*string);
3332    if (!string->IsOneByteRepresentation()) {
3333      is_one_byte_ = false;
3334    }
3335    IncrementCharacterCount(length);
3336  }
3337
3338
3339  MaybeHandle<String> ToString() {
3340    Isolate* isolate = heap_->isolate();
3341    if (array_builder_.length() == 0) {
3342      return isolate->factory()->empty_string();
3343    }
3344
3345    Handle<String> joined_string;
3346    if (is_one_byte_) {
3347      Handle<SeqOneByteString> seq;
3348      ASSIGN_RETURN_ON_EXCEPTION(
3349          isolate, seq,
3350          isolate->factory()->NewRawOneByteString(character_count_),
3351          String);
3352
3353      DisallowHeapAllocation no_gc;
3354      uint8_t* char_buffer = seq->GetChars();
3355      StringBuilderConcatHelper(*subject_,
3356                                char_buffer,
3357                                *array_builder_.array(),
3358                                array_builder_.length());
3359      joined_string = Handle<String>::cast(seq);
3360    } else {
3361      // Two-byte.
3362      Handle<SeqTwoByteString> seq;
3363      ASSIGN_RETURN_ON_EXCEPTION(
3364          isolate, seq,
3365          isolate->factory()->NewRawTwoByteString(character_count_),
3366          String);
3367
3368      DisallowHeapAllocation no_gc;
3369      uc16* char_buffer = seq->GetChars();
3370      StringBuilderConcatHelper(*subject_,
3371                                char_buffer,
3372                                *array_builder_.array(),
3373                                array_builder_.length());
3374      joined_string = Handle<String>::cast(seq);
3375    }
3376    return joined_string;
3377  }
3378
3379
3380  void IncrementCharacterCount(int by) {
3381    if (character_count_ > String::kMaxLength - by) {
3382      STATIC_ASSERT(String::kMaxLength < kMaxInt);
3383      character_count_ = kMaxInt;
3384    } else {
3385      character_count_ += by;
3386    }
3387  }
3388
3389 private:
3390  void AddElement(Object* element) {
3391    DCHECK(element->IsSmi() || element->IsString());
3392    DCHECK(array_builder_.capacity() > array_builder_.length());
3393    array_builder_.Add(element);
3394  }
3395
3396  Heap* heap_;
3397  FixedArrayBuilder array_builder_;
3398  Handle<String> subject_;
3399  int character_count_;
3400  bool is_one_byte_;
3401};
3402
3403
3404class CompiledReplacement {
3405 public:
3406  explicit CompiledReplacement(Zone* zone)
3407      : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3408
3409  // Return whether the replacement is simple.
3410  bool Compile(Handle<String> replacement,
3411               int capture_count,
3412               int subject_length);
3413
3414  // Use Apply only if Compile returned false.
3415  void Apply(ReplacementStringBuilder* builder,
3416             int match_from,
3417             int match_to,
3418             int32_t* match);
3419
3420  // Number of distinct parts of the replacement pattern.
3421  int parts() {
3422    return parts_.length();
3423  }
3424
3425  Zone* zone() const { return zone_; }
3426
3427 private:
3428  enum PartType {
3429    SUBJECT_PREFIX = 1,
3430    SUBJECT_SUFFIX,
3431    SUBJECT_CAPTURE,
3432    REPLACEMENT_SUBSTRING,
3433    REPLACEMENT_STRING,
3434
3435    NUMBER_OF_PART_TYPES
3436  };
3437
3438  struct ReplacementPart {
3439    static inline ReplacementPart SubjectMatch() {
3440      return ReplacementPart(SUBJECT_CAPTURE, 0);
3441    }
3442    static inline ReplacementPart SubjectCapture(int capture_index) {
3443      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3444    }
3445    static inline ReplacementPart SubjectPrefix() {
3446      return ReplacementPart(SUBJECT_PREFIX, 0);
3447    }
3448    static inline ReplacementPart SubjectSuffix(int subject_length) {
3449      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3450    }
3451    static inline ReplacementPart ReplacementString() {
3452      return ReplacementPart(REPLACEMENT_STRING, 0);
3453    }
3454    static inline ReplacementPart ReplacementSubString(int from, int to) {
3455      DCHECK(from >= 0);
3456      DCHECK(to > from);
3457      return ReplacementPart(-from, to);
3458    }
3459
3460    // If tag <= 0 then it is the negation of a start index of a substring of
3461    // the replacement pattern, otherwise it's a value from PartType.
3462    ReplacementPart(int tag, int data)
3463        : tag(tag), data(data) {
3464      // Must be non-positive or a PartType value.
3465      DCHECK(tag < NUMBER_OF_PART_TYPES);
3466    }
3467    // Either a value of PartType or a non-positive number that is
3468    // the negation of an index into the replacement string.
3469    int tag;
3470    // The data value's interpretation depends on the value of tag:
3471    // tag == SUBJECT_PREFIX ||
3472    // tag == SUBJECT_SUFFIX:  data is unused.
3473    // tag == SUBJECT_CAPTURE: data is the number of the capture.
3474    // tag == REPLACEMENT_SUBSTRING ||
3475    // tag == REPLACEMENT_STRING:    data is index into array of substrings
3476    //                               of the replacement string.
3477    // tag <= 0: Temporary representation of the substring of the replacement
3478    //           string ranging over -tag .. data.
3479    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3480    //           substring objects.
3481    int data;
3482  };
3483
3484  template<typename Char>
3485  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3486                               Vector<Char> characters,
3487                               int capture_count,
3488                               int subject_length,
3489                               Zone* zone) {
3490    int length = characters.length();
3491    int last = 0;
3492    for (int i = 0; i < length; i++) {
3493      Char c = characters[i];
3494      if (c == '$') {
3495        int next_index = i + 1;
3496        if (next_index == length) {  // No next character!
3497          break;
3498        }
3499        Char c2 = characters[next_index];
3500        switch (c2) {
3501        case '$':
3502          if (i > last) {
3503            // There is a substring before. Include the first "$".
3504            parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3505                       zone);
3506            last = next_index + 1;  // Continue after the second "$".
3507          } else {
3508            // Let the next substring start with the second "$".
3509            last = next_index;
3510          }
3511          i = next_index;
3512          break;
3513        case '`':
3514          if (i > last) {
3515            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3516          }
3517          parts->Add(ReplacementPart::SubjectPrefix(), zone);
3518          i = next_index;
3519          last = i + 1;
3520          break;
3521        case '\'':
3522          if (i > last) {
3523            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3524          }
3525          parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3526          i = next_index;
3527          last = i + 1;
3528          break;
3529        case '&':
3530          if (i > last) {
3531            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3532          }
3533          parts->Add(ReplacementPart::SubjectMatch(), zone);
3534          i = next_index;
3535          last = i + 1;
3536          break;
3537        case '0':
3538        case '1':
3539        case '2':
3540        case '3':
3541        case '4':
3542        case '5':
3543        case '6':
3544        case '7':
3545        case '8':
3546        case '9': {
3547          int capture_ref = c2 - '0';
3548          if (capture_ref > capture_count) {
3549            i = next_index;
3550            continue;
3551          }
3552          int second_digit_index = next_index + 1;
3553          if (second_digit_index < length) {
3554            // Peek ahead to see if we have two digits.
3555            Char c3 = characters[second_digit_index];
3556            if ('0' <= c3 && c3 <= '9') {  // Double digits.
3557              int double_digit_ref = capture_ref * 10 + c3 - '0';
3558              if (double_digit_ref <= capture_count) {
3559                next_index = second_digit_index;
3560                capture_ref = double_digit_ref;
3561              }
3562            }
3563          }
3564          if (capture_ref > 0) {
3565            if (i > last) {
3566              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3567            }
3568            DCHECK(capture_ref <= capture_count);
3569            parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3570            last = next_index + 1;
3571          }
3572          i = next_index;
3573          break;
3574        }
3575        default:
3576          i = next_index;
3577          break;
3578        }
3579      }
3580    }
3581    if (length > last) {
3582      if (last == 0) {
3583        // Replacement is simple.  Do not use Apply to do the replacement.
3584        return true;
3585      } else {
3586        parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3587      }
3588    }
3589    return false;
3590  }
3591
3592  ZoneList<ReplacementPart> parts_;
3593  ZoneList<Handle<String> > replacement_substrings_;
3594  Zone* zone_;
3595};
3596
3597
3598bool CompiledReplacement::Compile(Handle<String> replacement,
3599                                  int capture_count,
3600                                  int subject_length) {
3601  {
3602    DisallowHeapAllocation no_gc;
3603    String::FlatContent content = replacement->GetFlatContent();
3604    DCHECK(content.IsFlat());
3605    bool simple = false;
3606    if (content.IsOneByte()) {
3607      simple = ParseReplacementPattern(&parts_,
3608                                       content.ToOneByteVector(),
3609                                       capture_count,
3610                                       subject_length,
3611                                       zone());
3612    } else {
3613      DCHECK(content.IsTwoByte());
3614      simple = ParseReplacementPattern(&parts_,
3615                                       content.ToUC16Vector(),
3616                                       capture_count,
3617                                       subject_length,
3618                                       zone());
3619    }
3620    if (simple) return true;
3621  }
3622
3623  Isolate* isolate = replacement->GetIsolate();
3624  // Find substrings of replacement string and create them as String objects.
3625  int substring_index = 0;
3626  for (int i = 0, n = parts_.length(); i < n; i++) {
3627    int tag = parts_[i].tag;
3628    if (tag <= 0) {  // A replacement string slice.
3629      int from = -tag;
3630      int to = parts_[i].data;
3631      replacement_substrings_.Add(
3632          isolate->factory()->NewSubString(replacement, from, to), zone());
3633      parts_[i].tag = REPLACEMENT_SUBSTRING;
3634      parts_[i].data = substring_index;
3635      substring_index++;
3636    } else if (tag == REPLACEMENT_STRING) {
3637      replacement_substrings_.Add(replacement, zone());
3638      parts_[i].data = substring_index;
3639      substring_index++;
3640    }
3641  }
3642  return false;
3643}
3644
3645
3646void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3647                                int match_from,
3648                                int match_to,
3649                                int32_t* match) {
3650  DCHECK_LT(0, parts_.length());
3651  for (int i = 0, n = parts_.length(); i < n; i++) {
3652    ReplacementPart part = parts_[i];
3653    switch (part.tag) {
3654      case SUBJECT_PREFIX:
3655        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3656        break;
3657      case SUBJECT_SUFFIX: {
3658        int subject_length = part.data;
3659        if (match_to < subject_length) {
3660          builder->AddSubjectSlice(match_to, subject_length);
3661        }
3662        break;
3663      }
3664      case SUBJECT_CAPTURE: {
3665        int capture = part.data;
3666        int from = match[capture * 2];
3667        int to = match[capture * 2 + 1];
3668        if (from >= 0 && to > from) {
3669          builder->AddSubjectSlice(from, to);
3670        }
3671        break;
3672      }
3673      case REPLACEMENT_SUBSTRING:
3674      case REPLACEMENT_STRING:
3675        builder->AddString(replacement_substrings_[part.data]);
3676        break;
3677      default:
3678        UNREACHABLE();
3679    }
3680  }
3681}
3682
3683
3684void FindOneByteStringIndices(Vector<const uint8_t> subject, char pattern,
3685                              ZoneList<int>* indices, unsigned int limit,
3686                              Zone* zone) {
3687  DCHECK(limit > 0);
3688  // Collect indices of pattern in subject using memchr.
3689  // Stop after finding at most limit values.
3690  const uint8_t* subject_start = subject.start();
3691  const uint8_t* subject_end = subject_start + subject.length();
3692  const uint8_t* pos = subject_start;
3693  while (limit > 0) {
3694    pos = reinterpret_cast<const uint8_t*>(
3695        memchr(pos, pattern, subject_end - pos));
3696    if (pos == NULL) return;
3697    indices->Add(static_cast<int>(pos - subject_start), zone);
3698    pos++;
3699    limit--;
3700  }
3701}
3702
3703
3704void FindTwoByteStringIndices(const Vector<const uc16> subject,
3705                              uc16 pattern,
3706                              ZoneList<int>* indices,
3707                              unsigned int limit,
3708                              Zone* zone) {
3709  DCHECK(limit > 0);
3710  const uc16* subject_start = subject.start();
3711  const uc16* subject_end = subject_start + subject.length();
3712  for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3713    if (*pos == pattern) {
3714      indices->Add(static_cast<int>(pos - subject_start), zone);
3715      limit--;
3716    }
3717  }
3718}
3719
3720
3721template <typename SubjectChar, typename PatternChar>
3722void FindStringIndices(Isolate* isolate,
3723                       Vector<const SubjectChar> subject,
3724                       Vector<const PatternChar> pattern,
3725                       ZoneList<int>* indices,
3726                       unsigned int limit,
3727                       Zone* zone) {
3728  DCHECK(limit > 0);
3729  // Collect indices of pattern in subject.
3730  // Stop after finding at most limit values.
3731  int pattern_length = pattern.length();
3732  int index = 0;
3733  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3734  while (limit > 0) {
3735    index = search.Search(subject, index);
3736    if (index < 0) return;
3737    indices->Add(index, zone);
3738    index += pattern_length;
3739    limit--;
3740  }
3741}
3742
3743
3744void FindStringIndicesDispatch(Isolate* isolate,
3745                               String* subject,
3746                               String* pattern,
3747                               ZoneList<int>* indices,
3748                               unsigned int limit,
3749                               Zone* zone) {
3750  {
3751    DisallowHeapAllocation no_gc;
3752    String::FlatContent subject_content = subject->GetFlatContent();
3753    String::FlatContent pattern_content = pattern->GetFlatContent();
3754    DCHECK(subject_content.IsFlat());
3755    DCHECK(pattern_content.IsFlat());
3756    if (subject_content.IsOneByte()) {
3757      Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3758      if (pattern_content.IsOneByte()) {
3759        Vector<const uint8_t> pattern_vector =
3760            pattern_content.ToOneByteVector();
3761        if (pattern_vector.length() == 1) {
3762          FindOneByteStringIndices(subject_vector, pattern_vector[0], indices,
3763                                   limit, zone);
3764        } else {
3765          FindStringIndices(isolate,
3766                            subject_vector,
3767                            pattern_vector,
3768                            indices,
3769                            limit,
3770                            zone);
3771        }
3772      } else {
3773        FindStringIndices(isolate,
3774                          subject_vector,
3775                          pattern_content.ToUC16Vector(),
3776                          indices,
3777                          limit,
3778                          zone);
3779      }
3780    } else {
3781      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3782      if (pattern_content.IsOneByte()) {
3783        Vector<const uint8_t> pattern_vector =
3784            pattern_content.ToOneByteVector();
3785        if (pattern_vector.length() == 1) {
3786          FindTwoByteStringIndices(subject_vector,
3787                                   pattern_vector[0],
3788                                   indices,
3789                                   limit,
3790                                   zone);
3791        } else {
3792          FindStringIndices(isolate,
3793                            subject_vector,
3794                            pattern_vector,
3795                            indices,
3796                            limit,
3797                            zone);
3798        }
3799      } else {
3800        Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3801        if (pattern_vector.length() == 1) {
3802          FindTwoByteStringIndices(subject_vector,
3803                                   pattern_vector[0],
3804                                   indices,
3805                                   limit,
3806                                   zone);
3807        } else {
3808          FindStringIndices(isolate,
3809                            subject_vector,
3810                            pattern_vector,
3811                            indices,
3812                            limit,
3813                            zone);
3814        }
3815      }
3816    }
3817  }
3818}
3819
3820
3821template<typename ResultSeqString>
3822MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
3823    Isolate* isolate,
3824    Handle<String> subject,
3825    Handle<JSRegExp> pattern_regexp,
3826    Handle<String> replacement,
3827    Handle<JSArray> last_match_info) {
3828  DCHECK(subject->IsFlat());
3829  DCHECK(replacement->IsFlat());
3830
3831  ZoneScope zone_scope(isolate->runtime_zone());
3832  ZoneList<int> indices(8, zone_scope.zone());
3833  DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3834  String* pattern =
3835      String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3836  int subject_len = subject->length();
3837  int pattern_len = pattern->length();
3838  int replacement_len = replacement->length();
3839
3840  FindStringIndicesDispatch(
3841      isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3842
3843  int matches = indices.length();
3844  if (matches == 0) return *subject;
3845
3846  // Detect integer overflow.
3847  int64_t result_len_64 =
3848      (static_cast<int64_t>(replacement_len) -
3849       static_cast<int64_t>(pattern_len)) *
3850      static_cast<int64_t>(matches) +
3851      static_cast<int64_t>(subject_len);
3852  int result_len;
3853  if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3854    STATIC_ASSERT(String::kMaxLength < kMaxInt);
3855    result_len = kMaxInt;  // Provoke exception.
3856  } else {
3857    result_len = static_cast<int>(result_len_64);
3858  }
3859
3860  int subject_pos = 0;
3861  int result_pos = 0;
3862
3863  MaybeHandle<SeqString> maybe_res;
3864  if (ResultSeqString::kHasOneByteEncoding) {
3865    maybe_res = isolate->factory()->NewRawOneByteString(result_len);
3866  } else {
3867    maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
3868  }
3869  Handle<SeqString> untyped_res;
3870  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
3871  Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
3872
3873  for (int i = 0; i < matches; i++) {
3874    // Copy non-matched subject content.
3875    if (subject_pos < indices.at(i)) {
3876      String::WriteToFlat(*subject,
3877                          result->GetChars() + result_pos,
3878                          subject_pos,
3879                          indices.at(i));
3880      result_pos += indices.at(i) - subject_pos;
3881    }
3882
3883    // Replace match.
3884    if (replacement_len > 0) {
3885      String::WriteToFlat(*replacement,
3886                          result->GetChars() + result_pos,
3887                          0,
3888                          replacement_len);
3889      result_pos += replacement_len;
3890    }
3891
3892    subject_pos = indices.at(i) + pattern_len;
3893  }
3894  // Add remaining subject content at the end.
3895  if (subject_pos < subject_len) {
3896    String::WriteToFlat(*subject,
3897                        result->GetChars() + result_pos,
3898                        subject_pos,
3899                        subject_len);
3900  }
3901
3902  int32_t match_indices[] = { indices.at(matches - 1),
3903                              indices.at(matches - 1) + pattern_len };
3904  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3905
3906  return *result;
3907}
3908
3909
3910MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
3911    Isolate* isolate,
3912    Handle<String> subject,
3913    Handle<JSRegExp> regexp,
3914    Handle<String> replacement,
3915    Handle<JSArray> last_match_info) {
3916  DCHECK(subject->IsFlat());
3917  DCHECK(replacement->IsFlat());
3918
3919  int capture_count = regexp->CaptureCount();
3920  int subject_length = subject->length();
3921
3922  // CompiledReplacement uses zone allocation.
3923  ZoneScope zone_scope(isolate->runtime_zone());
3924  CompiledReplacement compiled_replacement(zone_scope.zone());
3925  bool simple_replace = compiled_replacement.Compile(replacement,
3926                                                     capture_count,
3927                                                     subject_length);
3928
3929  // Shortcut for simple non-regexp global replacements
3930  if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
3931    if (subject->HasOnlyOneByteChars() &&
3932        replacement->HasOnlyOneByteChars()) {
3933      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3934          isolate, subject, regexp, replacement, last_match_info);
3935    } else {
3936      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3937          isolate, subject, regexp, replacement, last_match_info);
3938    }
3939  }
3940
3941  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3942  if (global_cache.HasException()) return isolate->heap()->exception();
3943
3944  int32_t* current_match = global_cache.FetchNext();
3945  if (current_match == NULL) {
3946    if (global_cache.HasException()) return isolate->heap()->exception();
3947    return *subject;
3948  }
3949
3950  // Guessing the number of parts that the final result string is built
3951  // from. Global regexps can match any number of times, so we guess
3952  // conservatively.
3953  int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
3954  ReplacementStringBuilder builder(isolate->heap(),
3955                                   subject,
3956                                   expected_parts);
3957
3958  // Number of parts added by compiled replacement plus preceeding
3959  // string and possibly suffix after last match.  It is possible for
3960  // all components to use two elements when encoded as two smis.
3961  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3962
3963  int prev = 0;
3964
3965  do {
3966    builder.EnsureCapacity(parts_added_per_loop);
3967
3968    int start = current_match[0];
3969    int end = current_match[1];
3970
3971    if (prev < start) {
3972      builder.AddSubjectSlice(prev, start);
3973    }
3974
3975    if (simple_replace) {
3976      builder.AddString(replacement);
3977    } else {
3978      compiled_replacement.Apply(&builder,
3979                                 start,
3980                                 end,
3981                                 current_match);
3982    }
3983    prev = end;
3984
3985    current_match = global_cache.FetchNext();
3986  } while (current_match != NULL);
3987
3988  if (global_cache.HasException()) return isolate->heap()->exception();
3989
3990  if (prev < subject_length) {
3991    builder.EnsureCapacity(2);
3992    builder.AddSubjectSlice(prev, subject_length);
3993  }
3994
3995  RegExpImpl::SetLastMatchInfo(last_match_info,
3996                               subject,
3997                               capture_count,
3998                               global_cache.LastSuccessfulMatch());
3999
4000  Handle<String> result;
4001  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.ToString());
4002  return *result;
4003}
4004
4005
4006template <typename ResultSeqString>
4007MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
4008    Isolate* isolate,
4009    Handle<String> subject,
4010    Handle<JSRegExp> regexp,
4011    Handle<JSArray> last_match_info) {
4012  DCHECK(subject->IsFlat());
4013
4014  // Shortcut for simple non-regexp global replacements
4015  if (regexp->TypeTag() == JSRegExp::ATOM) {
4016    Handle<String> empty_string = isolate->factory()->empty_string();
4017    if (subject->IsOneByteRepresentation()) {
4018      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4019          isolate, subject, regexp, empty_string, last_match_info);
4020    } else {
4021      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4022          isolate, subject, regexp, empty_string, last_match_info);
4023    }
4024  }
4025
4026  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4027  if (global_cache.HasException()) return isolate->heap()->exception();
4028
4029  int32_t* current_match = global_cache.FetchNext();
4030  if (current_match == NULL) {
4031    if (global_cache.HasException()) return isolate->heap()->exception();
4032    return *subject;
4033  }
4034
4035  int start = current_match[0];
4036  int end = current_match[1];
4037  int capture_count = regexp->CaptureCount();
4038  int subject_length = subject->length();
4039
4040  int new_length = subject_length - (end - start);
4041  if (new_length == 0) return isolate->heap()->empty_string();
4042
4043  Handle<ResultSeqString> answer;
4044  if (ResultSeqString::kHasOneByteEncoding) {
4045    answer = Handle<ResultSeqString>::cast(
4046        isolate->factory()->NewRawOneByteString(new_length).ToHandleChecked());
4047  } else {
4048    answer = Handle<ResultSeqString>::cast(
4049        isolate->factory()->NewRawTwoByteString(new_length).ToHandleChecked());
4050  }
4051
4052  int prev = 0;
4053  int position = 0;
4054
4055  do {
4056    start = current_match[0];
4057    end = current_match[1];
4058    if (prev < start) {
4059      // Add substring subject[prev;start] to answer string.
4060      String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4061      position += start - prev;
4062    }
4063    prev = end;
4064
4065    current_match = global_cache.FetchNext();
4066  } while (current_match != NULL);
4067
4068  if (global_cache.HasException()) return isolate->heap()->exception();
4069
4070  RegExpImpl::SetLastMatchInfo(last_match_info,
4071                               subject,
4072                               capture_count,
4073                               global_cache.LastSuccessfulMatch());
4074
4075  if (prev < subject_length) {
4076    // Add substring subject[prev;length] to answer string.
4077    String::WriteToFlat(
4078        *subject, answer->GetChars() + position, prev, subject_length);
4079    position += subject_length - prev;
4080  }
4081
4082  if (position == 0) return isolate->heap()->empty_string();
4083
4084  // Shorten string and fill
4085  int string_size = ResultSeqString::SizeFor(position);
4086  int allocated_string_size = ResultSeqString::SizeFor(new_length);
4087  int delta = allocated_string_size - string_size;
4088
4089  answer->set_length(position);
4090  if (delta == 0) return *answer;
4091
4092  Address end_of_string = answer->address() + string_size;
4093  Heap* heap = isolate->heap();
4094
4095  // The trimming is performed on a newly allocated object, which is on a
4096  // fresly allocated page or on an already swept page. Hence, the sweeper
4097  // thread can not get confused with the filler creation. No synchronization
4098  // needed.
4099  heap->CreateFillerObjectAt(end_of_string, delta);
4100  heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR);
4101  return *answer;
4102}
4103
4104
4105RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
4106  HandleScope scope(isolate);
4107  DCHECK(args.length() == 4);
4108
4109  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4110  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4111  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4112  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4113
4114  RUNTIME_ASSERT(regexp->GetFlags().is_global());
4115  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
4116
4117  subject = String::Flatten(subject);
4118
4119  if (replacement->length() == 0) {
4120    if (subject->HasOnlyOneByteChars()) {
4121      return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4122          isolate, subject, regexp, last_match_info);
4123    } else {
4124      return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4125          isolate, subject, regexp, last_match_info);
4126    }
4127  }
4128
4129  replacement = String::Flatten(replacement);
4130
4131  return StringReplaceGlobalRegExpWithString(
4132      isolate, subject, regexp, replacement, last_match_info);
4133}
4134
4135
4136// This may return an empty MaybeHandle if an exception is thrown or
4137// we abort due to reaching the recursion limit.
4138MaybeHandle<String> StringReplaceOneCharWithString(Isolate* isolate,
4139                                                   Handle<String> subject,
4140                                                   Handle<String> search,
4141                                                   Handle<String> replace,
4142                                                   bool* found,
4143                                                   int recursion_limit) {
4144  StackLimitCheck stackLimitCheck(isolate);
4145  if (stackLimitCheck.HasOverflowed() || (recursion_limit == 0)) {
4146    return MaybeHandle<String>();
4147  }
4148  recursion_limit--;
4149  if (subject->IsConsString()) {
4150    ConsString* cons = ConsString::cast(*subject);
4151    Handle<String> first = Handle<String>(cons->first());
4152    Handle<String> second = Handle<String>(cons->second());
4153    Handle<String> new_first;
4154    if (!StringReplaceOneCharWithString(
4155            isolate, first, search, replace, found, recursion_limit)
4156            .ToHandle(&new_first)) {
4157      return MaybeHandle<String>();
4158    }
4159    if (*found) return isolate->factory()->NewConsString(new_first, second);
4160
4161    Handle<String> new_second;
4162    if (!StringReplaceOneCharWithString(
4163            isolate, second, search, replace, found, recursion_limit)
4164            .ToHandle(&new_second)) {
4165      return MaybeHandle<String>();
4166    }
4167    if (*found) return isolate->factory()->NewConsString(first, new_second);
4168
4169    return subject;
4170  } else {
4171    int index = Runtime::StringMatch(isolate, subject, search, 0);
4172    if (index == -1) return subject;
4173    *found = true;
4174    Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4175    Handle<String> cons1;
4176    ASSIGN_RETURN_ON_EXCEPTION(
4177        isolate, cons1,
4178        isolate->factory()->NewConsString(first, replace),
4179        String);
4180    Handle<String> second =
4181        isolate->factory()->NewSubString(subject, index + 1, subject->length());
4182    return isolate->factory()->NewConsString(cons1, second);
4183  }
4184}
4185
4186
4187RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
4188  HandleScope scope(isolate);
4189  DCHECK(args.length() == 3);
4190  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4191  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4192  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4193
4194  // If the cons string tree is too deep, we simply abort the recursion and
4195  // retry with a flattened subject string.
4196  const int kRecursionLimit = 0x1000;
4197  bool found = false;
4198  Handle<String> result;
4199  if (StringReplaceOneCharWithString(
4200          isolate, subject, search, replace, &found, kRecursionLimit)
4201          .ToHandle(&result)) {
4202    return *result;
4203  }
4204  if (isolate->has_pending_exception()) return isolate->heap()->exception();
4205
4206  subject = String::Flatten(subject);
4207  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4208      isolate, result,
4209      StringReplaceOneCharWithString(
4210          isolate, subject, search, replace, &found, kRecursionLimit));
4211  return *result;
4212}
4213
4214
4215// Perform string match of pattern on subject, starting at start index.
4216// Caller must ensure that 0 <= start_index <= sub->length(),
4217// and should check that pat->length() + start_index <= sub->length().
4218int Runtime::StringMatch(Isolate* isolate,
4219                         Handle<String> sub,
4220                         Handle<String> pat,
4221                         int start_index) {
4222  DCHECK(0 <= start_index);
4223  DCHECK(start_index <= sub->length());
4224
4225  int pattern_length = pat->length();
4226  if (pattern_length == 0) return start_index;
4227
4228  int subject_length = sub->length();
4229  if (start_index + pattern_length > subject_length) return -1;
4230
4231  sub = String::Flatten(sub);
4232  pat = String::Flatten(pat);
4233
4234  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4235  // Extract flattened substrings of cons strings before getting encoding.
4236  String::FlatContent seq_sub = sub->GetFlatContent();
4237  String::FlatContent seq_pat = pat->GetFlatContent();
4238
4239  // dispatch on type of strings
4240  if (seq_pat.IsOneByte()) {
4241    Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4242    if (seq_sub.IsOneByte()) {
4243      return SearchString(isolate,
4244                          seq_sub.ToOneByteVector(),
4245                          pat_vector,
4246                          start_index);
4247    }
4248    return SearchString(isolate,
4249                        seq_sub.ToUC16Vector(),
4250                        pat_vector,
4251                        start_index);
4252  }
4253  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4254  if (seq_sub.IsOneByte()) {
4255    return SearchString(isolate,
4256                        seq_sub.ToOneByteVector(),
4257                        pat_vector,
4258                        start_index);
4259  }
4260  return SearchString(isolate,
4261                      seq_sub.ToUC16Vector(),
4262                      pat_vector,
4263                      start_index);
4264}
4265
4266
4267RUNTIME_FUNCTION(Runtime_StringIndexOf) {
4268  HandleScope scope(isolate);
4269  DCHECK(args.length() == 3);
4270
4271  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4272  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4273  CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
4274
4275  uint32_t start_index;
4276  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4277
4278  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4279  int position = Runtime::StringMatch(isolate, sub, pat, start_index);
4280  return Smi::FromInt(position);
4281}
4282
4283
4284template <typename schar, typename pchar>
4285static int StringMatchBackwards(Vector<const schar> subject,
4286                                Vector<const pchar> pattern,
4287                                int idx) {
4288  int pattern_length = pattern.length();
4289  DCHECK(pattern_length >= 1);
4290  DCHECK(idx + pattern_length <= subject.length());
4291
4292  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4293    for (int i = 0; i < pattern_length; i++) {
4294      uc16 c = pattern[i];
4295      if (c > String::kMaxOneByteCharCode) {
4296        return -1;
4297      }
4298    }
4299  }
4300
4301  pchar pattern_first_char = pattern[0];
4302  for (int i = idx; i >= 0; i--) {
4303    if (subject[i] != pattern_first_char) continue;
4304    int j = 1;
4305    while (j < pattern_length) {
4306      if (pattern[j] != subject[i+j]) {
4307        break;
4308      }
4309      j++;
4310    }
4311    if (j == pattern_length) {
4312      return i;
4313    }
4314  }
4315  return -1;
4316}
4317
4318
4319RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
4320  HandleScope scope(isolate);
4321  DCHECK(args.length() == 3);
4322
4323  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4324  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4325  CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
4326
4327  uint32_t start_index;
4328  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4329
4330  uint32_t pat_length = pat->length();
4331  uint32_t sub_length = sub->length();
4332
4333  if (start_index + pat_length > sub_length) {
4334    start_index = sub_length - pat_length;
4335  }
4336
4337  if (pat_length == 0) {
4338    return Smi::FromInt(start_index);
4339  }
4340
4341  sub = String::Flatten(sub);
4342  pat = String::Flatten(pat);
4343
4344  int position = -1;
4345  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4346
4347  String::FlatContent sub_content = sub->GetFlatContent();
4348  String::FlatContent pat_content = pat->GetFlatContent();
4349
4350  if (pat_content.IsOneByte()) {
4351    Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4352    if (sub_content.IsOneByte()) {
4353      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4354                                      pat_vector,
4355                                      start_index);
4356    } else {
4357      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4358                                      pat_vector,
4359                                      start_index);
4360    }
4361  } else {
4362    Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4363    if (sub_content.IsOneByte()) {
4364      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4365                                      pat_vector,
4366                                      start_index);
4367    } else {
4368      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4369                                      pat_vector,
4370                                      start_index);
4371    }
4372  }
4373
4374  return Smi::FromInt(position);
4375}
4376
4377
4378RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
4379  HandleScope handle_scope(isolate);
4380  DCHECK(args.length() == 2);
4381
4382  CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
4383  CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
4384
4385  if (str1.is_identical_to(str2)) return Smi::FromInt(0);  // Equal.
4386  int str1_length = str1->length();
4387  int str2_length = str2->length();
4388
4389  // Decide trivial cases without flattening.
4390  if (str1_length == 0) {
4391    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4392    return Smi::FromInt(-str2_length);
4393  } else {
4394    if (str2_length == 0) return Smi::FromInt(str1_length);
4395  }
4396
4397  int end = str1_length < str2_length ? str1_length : str2_length;
4398
4399  // No need to flatten if we are going to find the answer on the first
4400  // character.  At this point we know there is at least one character
4401  // in each string, due to the trivial case handling above.
4402  int d = str1->Get(0) - str2->Get(0);
4403  if (d != 0) return Smi::FromInt(d);
4404
4405  str1 = String::Flatten(str1);
4406  str2 = String::Flatten(str2);
4407
4408  DisallowHeapAllocation no_gc;
4409  String::FlatContent flat1 = str1->GetFlatContent();
4410  String::FlatContent flat2 = str2->GetFlatContent();
4411
4412  for (int i = 0; i < end; i++) {
4413    if (flat1.Get(i) != flat2.Get(i)) {
4414      return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
4415    }
4416  }
4417
4418  return Smi::FromInt(str1_length - str2_length);
4419}
4420
4421
4422RUNTIME_FUNCTION(Runtime_SubString) {
4423  HandleScope scope(isolate);
4424  DCHECK(args.length() == 3);
4425
4426  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
4427  int start, end;
4428  // We have a fast integer-only case here to avoid a conversion to double in
4429  // the common case where from and to are Smis.
4430  if (args[1]->IsSmi() && args[2]->IsSmi()) {
4431    CONVERT_SMI_ARG_CHECKED(from_number, 1);
4432    CONVERT_SMI_ARG_CHECKED(to_number, 2);
4433    start = from_number;
4434    end = to_number;
4435  } else {
4436    CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4437    CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4438    start = FastD2IChecked(from_number);
4439    end = FastD2IChecked(to_number);
4440  }
4441  RUNTIME_ASSERT(end >= start);
4442  RUNTIME_ASSERT(start >= 0);
4443  RUNTIME_ASSERT(end <= string->length());
4444  isolate->counters()->sub_string_runtime()->Increment();
4445
4446  return *isolate->factory()->NewSubString(string, start, end);
4447}
4448
4449
4450RUNTIME_FUNCTION(Runtime_InternalizeString) {
4451  HandleScope handles(isolate);
4452  RUNTIME_ASSERT(args.length() == 1);
4453  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
4454  return *isolate->factory()->InternalizeString(string);
4455}
4456
4457
4458RUNTIME_FUNCTION(Runtime_StringMatch) {
4459  HandleScope handles(isolate);
4460  DCHECK(args.length() == 3);
4461
4462  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4463  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4464  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4465
4466  RUNTIME_ASSERT(regexp_info->HasFastObjectElements());
4467
4468  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4469  if (global_cache.HasException()) return isolate->heap()->exception();
4470
4471  int capture_count = regexp->CaptureCount();
4472
4473  ZoneScope zone_scope(isolate->runtime_zone());
4474  ZoneList<int> offsets(8, zone_scope.zone());
4475
4476  while (true) {
4477    int32_t* match = global_cache.FetchNext();
4478    if (match == NULL) break;
4479    offsets.Add(match[0], zone_scope.zone());  // start
4480    offsets.Add(match[1], zone_scope.zone());  // end
4481  }
4482
4483  if (global_cache.HasException()) return isolate->heap()->exception();
4484
4485  if (offsets.length() == 0) {
4486    // Not a single match.
4487    return isolate->heap()->null_value();
4488  }
4489
4490  RegExpImpl::SetLastMatchInfo(regexp_info,
4491                               subject,
4492                               capture_count,
4493                               global_cache.LastSuccessfulMatch());
4494
4495  int matches = offsets.length() / 2;
4496  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4497  Handle<String> substring =
4498      isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4499  elements->set(0, *substring);
4500  for (int i = 1; i < matches; i++) {
4501    HandleScope temp_scope(isolate);
4502    int from = offsets.at(i * 2);
4503    int to = offsets.at(i * 2 + 1);
4504    Handle<String> substring =
4505        isolate->factory()->NewProperSubString(subject, from, to);
4506    elements->set(i, *substring);
4507  }
4508  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4509  result->set_length(Smi::FromInt(matches));
4510  return *result;
4511}
4512
4513
4514// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4515// separate last match info.  See comment on that function.
4516template<bool has_capture>
4517static Object* SearchRegExpMultiple(
4518    Isolate* isolate,
4519    Handle<String> subject,
4520    Handle<JSRegExp> regexp,
4521    Handle<JSArray> last_match_array,
4522    Handle<JSArray> result_array) {
4523  DCHECK(subject->IsFlat());
4524  DCHECK_NE(has_capture, regexp->CaptureCount() == 0);
4525
4526  int capture_count = regexp->CaptureCount();
4527  int subject_length = subject->length();
4528
4529  static const int kMinLengthToCache = 0x1000;
4530
4531  if (subject_length > kMinLengthToCache) {
4532    Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4533        isolate->heap(),
4534        *subject,
4535        regexp->data(),
4536        RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4537    if (*cached_answer != Smi::FromInt(0)) {
4538      Handle<FixedArray> cached_fixed_array =
4539          Handle<FixedArray>(FixedArray::cast(*cached_answer));
4540      // The cache FixedArray is a COW-array and can therefore be reused.
4541      JSArray::SetContent(result_array, cached_fixed_array);
4542      // The actual length of the result array is stored in the last element of
4543      // the backing store (the backing FixedArray may have a larger capacity).
4544      Object* cached_fixed_array_last_element =
4545          cached_fixed_array->get(cached_fixed_array->length() - 1);
4546      Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4547      result_array->set_length(js_array_length);
4548      RegExpImpl::SetLastMatchInfo(
4549          last_match_array, subject, capture_count, NULL);
4550      return *result_array;
4551    }
4552  }
4553
4554  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4555  if (global_cache.HasException()) return isolate->heap()->exception();
4556
4557  // Ensured in Runtime_RegExpExecMultiple.
4558  DCHECK(result_array->HasFastObjectElements());
4559  Handle<FixedArray> result_elements(
4560      FixedArray::cast(result_array->elements()));
4561  if (result_elements->length() < 16) {
4562    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4563  }
4564
4565  FixedArrayBuilder builder(result_elements);
4566
4567  // Position to search from.
4568  int match_start = -1;
4569  int match_end = 0;
4570  bool first = true;
4571
4572  // Two smis before and after the match, for very long strings.
4573  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4574
4575  while (true) {
4576    int32_t* current_match = global_cache.FetchNext();
4577    if (current_match == NULL) break;
4578    match_start = current_match[0];
4579    builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4580    if (match_end < match_start) {
4581      ReplacementStringBuilder::AddSubjectSlice(&builder,
4582                                                match_end,
4583                                                match_start);
4584    }
4585    match_end = current_match[1];
4586    {
4587      // Avoid accumulating new handles inside loop.
4588      HandleScope temp_scope(isolate);
4589      Handle<String> match;
4590      if (!first) {
4591        match = isolate->factory()->NewProperSubString(subject,
4592                                                       match_start,
4593                                                       match_end);
4594      } else {
4595        match = isolate->factory()->NewSubString(subject,
4596                                                 match_start,
4597                                                 match_end);
4598        first = false;
4599      }
4600
4601      if (has_capture) {
4602        // Arguments array to replace function is match, captures, index and
4603        // subject, i.e., 3 + capture count in total.
4604        Handle<FixedArray> elements =
4605            isolate->factory()->NewFixedArray(3 + capture_count);
4606
4607        elements->set(0, *match);
4608        for (int i = 1; i <= capture_count; i++) {
4609          int start = current_match[i * 2];
4610          if (start >= 0) {
4611            int end = current_match[i * 2 + 1];
4612            DCHECK(start <= end);
4613            Handle<String> substring =
4614                isolate->factory()->NewSubString(subject, start, end);
4615            elements->set(i, *substring);
4616          } else {
4617            DCHECK(current_match[i * 2 + 1] < 0);
4618            elements->set(i, isolate->heap()->undefined_value());
4619          }
4620        }
4621        elements->set(capture_count + 1, Smi::FromInt(match_start));
4622        elements->set(capture_count + 2, *subject);
4623        builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4624      } else {
4625        builder.Add(*match);
4626      }
4627    }
4628  }
4629
4630  if (global_cache.HasException()) return isolate->heap()->exception();
4631
4632  if (match_start >= 0) {
4633    // Finished matching, with at least one match.
4634    if (match_end < subject_length) {
4635      ReplacementStringBuilder::AddSubjectSlice(&builder,
4636                                                match_end,
4637                                                subject_length);
4638    }
4639
4640    RegExpImpl::SetLastMatchInfo(
4641        last_match_array, subject, capture_count, NULL);
4642
4643    if (subject_length > kMinLengthToCache) {
4644      // Store the length of the result array into the last element of the
4645      // backing FixedArray.
4646      builder.EnsureCapacity(1);
4647      Handle<FixedArray> fixed_array = builder.array();
4648      fixed_array->set(fixed_array->length() - 1,
4649                       Smi::FromInt(builder.length()));
4650      // Cache the result and turn the FixedArray into a COW array.
4651      RegExpResultsCache::Enter(isolate,
4652                                subject,
4653                                handle(regexp->data(), isolate),
4654                                fixed_array,
4655                                RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4656    }
4657    return *builder.ToJSArray(result_array);
4658  } else {
4659    return isolate->heap()->null_value();  // No matches at all.
4660  }
4661}
4662
4663
4664// This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4665// lastMatchInfoOverride to maintain the last match info, so we don't need to
4666// set any other last match array info.
4667RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
4668  HandleScope handles(isolate);
4669  DCHECK(args.length() == 4);
4670
4671  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4672  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4673  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4674  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4675  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
4676  RUNTIME_ASSERT(result_array->HasFastObjectElements());
4677
4678  subject = String::Flatten(subject);
4679  RUNTIME_ASSERT(regexp->GetFlags().is_global());
4680
4681  if (regexp->CaptureCount() == 0) {
4682    return SearchRegExpMultiple<false>(
4683        isolate, subject, regexp, last_match_info, result_array);
4684  } else {
4685    return SearchRegExpMultiple<true>(
4686        isolate, subject, regexp, last_match_info, result_array);
4687  }
4688}
4689
4690
4691RUNTIME_FUNCTION(Runtime_NumberToRadixString) {
4692  HandleScope scope(isolate);
4693  DCHECK(args.length() == 2);
4694  CONVERT_SMI_ARG_CHECKED(radix, 1);
4695  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4696
4697  // Fast case where the result is a one character string.
4698  if (args[0]->IsSmi()) {
4699    int value = args.smi_at(0);
4700    if (value >= 0 && value < radix) {
4701      // Character array used for conversion.
4702      static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4703      return *isolate->factory()->
4704          LookupSingleCharacterStringFromCode(kCharTable[value]);
4705    }
4706  }
4707
4708  // Slow case.
4709  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4710  if (std::isnan(value)) {
4711    return isolate->heap()->nan_string();
4712  }
4713  if (std::isinf(value)) {
4714    if (value < 0) {
4715      return isolate->heap()->minus_infinity_string();
4716    }
4717    return isolate->heap()->infinity_string();
4718  }
4719  char* str = DoubleToRadixCString(value, radix);
4720  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4721  DeleteArray(str);
4722  return *result;
4723}
4724
4725
4726RUNTIME_FUNCTION(Runtime_NumberToFixed) {
4727  HandleScope scope(isolate);
4728  DCHECK(args.length() == 2);
4729
4730  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4731  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4732  int f = FastD2IChecked(f_number);
4733  // See DoubleToFixedCString for these constants:
4734  RUNTIME_ASSERT(f >= 0 && f <= 20);
4735  RUNTIME_ASSERT(!Double(value).IsSpecial());
4736  char* str = DoubleToFixedCString(value, f);
4737  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4738  DeleteArray(str);
4739  return *result;
4740}
4741
4742
4743RUNTIME_FUNCTION(Runtime_NumberToExponential) {
4744  HandleScope scope(isolate);
4745  DCHECK(args.length() == 2);
4746
4747  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4748  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4749  int f = FastD2IChecked(f_number);
4750  RUNTIME_ASSERT(f >= -1 && f <= 20);
4751  RUNTIME_ASSERT(!Double(value).IsSpecial());
4752  char* str = DoubleToExponentialCString(value, f);
4753  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4754  DeleteArray(str);
4755  return *result;
4756}
4757
4758
4759RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
4760  HandleScope scope(isolate);
4761  DCHECK(args.length() == 2);
4762
4763  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4764  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4765  int f = FastD2IChecked(f_number);
4766  RUNTIME_ASSERT(f >= 1 && f <= 21);
4767  RUNTIME_ASSERT(!Double(value).IsSpecial());
4768  char* str = DoubleToPrecisionCString(value, f);
4769  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4770  DeleteArray(str);
4771  return *result;
4772}
4773
4774
4775RUNTIME_FUNCTION(Runtime_IsValidSmi) {
4776  SealHandleScope shs(isolate);
4777  DCHECK(args.length() == 1);
4778
4779  CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4780  return isolate->heap()->ToBoolean(Smi::IsValid(number));
4781}
4782
4783
4784// Returns a single character string where first character equals
4785// string->Get(index).
4786static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4787  if (index < static_cast<uint32_t>(string->length())) {
4788    Factory* factory = string->GetIsolate()->factory();
4789    return factory->LookupSingleCharacterStringFromCode(
4790        String::Flatten(string)->Get(index));
4791  }
4792  return Execution::CharAt(string, index);
4793}
4794
4795
4796MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
4797                                                Handle<Object> object,
4798                                                uint32_t index) {
4799  // Handle [] indexing on Strings
4800  if (object->IsString()) {
4801    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4802    if (!result->IsUndefined()) return result;
4803  }
4804
4805  // Handle [] indexing on String objects
4806  if (object->IsStringObjectWithCharacterAt(index)) {
4807    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4808    Handle<Object> result =
4809        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4810    if (!result->IsUndefined()) return result;
4811  }
4812
4813  Handle<Object> result;
4814  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4815    PrototypeIterator iter(isolate, object);
4816    return Object::GetElement(isolate, PrototypeIterator::GetCurrent(iter),
4817                              index);
4818  } else {
4819    return Object::GetElement(isolate, object, index);
4820  }
4821}
4822
4823
4824MUST_USE_RESULT
4825static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
4826  if (key->IsName()) {
4827    return Handle<Name>::cast(key);
4828  } else {
4829    Handle<Object> converted;
4830    ASSIGN_RETURN_ON_EXCEPTION(
4831        isolate, converted, Execution::ToString(isolate, key), Name);
4832    return Handle<Name>::cast(converted);
4833  }
4834}
4835
4836
4837MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate,
4838                                               Handle<JSReceiver> object,
4839                                               Handle<Object> key) {
4840  Maybe<bool> maybe;
4841  // Check if the given key is an array index.
4842  uint32_t index;
4843  if (key->ToArrayIndex(&index)) {
4844    maybe = JSReceiver::HasElement(object, index);
4845  } else {
4846    // Convert the key to a name - possibly by calling back into JavaScript.
4847    Handle<Name> name;
4848    ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
4849
4850    maybe = JSReceiver::HasProperty(object, name);
4851  }
4852
4853  if (!maybe.has_value) return MaybeHandle<Object>();
4854  return isolate->factory()->ToBoolean(maybe.value);
4855}
4856
4857
4858MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
4859                                               Handle<Object> object,
4860                                               Handle<Object> key) {
4861  if (object->IsUndefined() || object->IsNull()) {
4862    Handle<Object> args[2] = { key, object };
4863    THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_load",
4864                                          HandleVector(args, 2)),
4865                    Object);
4866  }
4867
4868  // Check if the given key is an array index.
4869  uint32_t index;
4870  if (key->ToArrayIndex(&index)) {
4871    return GetElementOrCharAt(isolate, object, index);
4872  }
4873
4874  // Convert the key to a name - possibly by calling back into JavaScript.
4875  Handle<Name> name;
4876  ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
4877
4878  // Check if the name is trivially convertible to an index and get
4879  // the element if so.
4880  if (name->AsArrayIndex(&index)) {
4881    return GetElementOrCharAt(isolate, object, index);
4882  } else {
4883    return Object::GetProperty(object, name);
4884  }
4885}
4886
4887
4888RUNTIME_FUNCTION(Runtime_GetProperty) {
4889  HandleScope scope(isolate);
4890  DCHECK(args.length() == 2);
4891
4892  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
4893  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
4894  Handle<Object> result;
4895  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4896      isolate, result,
4897      Runtime::GetObjectProperty(isolate, object, key));
4898  return *result;
4899}
4900
4901
4902// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
4903RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
4904  HandleScope scope(isolate);
4905  DCHECK(args.length() == 2);
4906
4907  CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
4908  CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
4909
4910  // Fast cases for getting named properties of the receiver JSObject
4911  // itself.
4912  //
4913  // The global proxy objects has to be excluded since LookupOwn on
4914  // the global proxy object can return a valid result even though the
4915  // global proxy object never has properties.  This is the case
4916  // because the global proxy object forwards everything to its hidden
4917  // prototype including own lookups.
4918  //
4919  // Additionally, we need to make sure that we do not cache results
4920  // for objects that require access checks.
4921  if (receiver_obj->IsJSObject()) {
4922    if (!receiver_obj->IsJSGlobalProxy() &&
4923        !receiver_obj->IsAccessCheckNeeded() &&
4924        key_obj->IsName()) {
4925      DisallowHeapAllocation no_allocation;
4926      Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
4927      Handle<Name> key = Handle<Name>::cast(key_obj);
4928      if (receiver->HasFastProperties()) {
4929        // Attempt to use lookup cache.
4930        Handle<Map> receiver_map(receiver->map(), isolate);
4931        KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4932        int index = keyed_lookup_cache->Lookup(receiver_map, key);
4933        if (index != -1) {
4934          // Doubles are not cached, so raw read the value.
4935          return receiver->RawFastPropertyAt(
4936              FieldIndex::ForKeyedLookupCacheIndex(*receiver_map, index));
4937        }
4938        // Lookup cache miss.  Perform lookup and update the cache if
4939        // appropriate.
4940        LookupIterator it(receiver, key, LookupIterator::OWN);
4941        if (it.state() == LookupIterator::DATA &&
4942            it.property_details().type() == FIELD) {
4943          FieldIndex field_index = it.GetFieldIndex();
4944          // Do not track double fields in the keyed lookup cache. Reading
4945          // double values requires boxing.
4946          if (!it.representation().IsDouble()) {
4947            keyed_lookup_cache->Update(receiver_map, key,
4948                field_index.GetKeyedLookupCacheIndex());
4949          }
4950          AllowHeapAllocation allow_allocation;
4951          return *JSObject::FastPropertyAt(receiver, it.representation(),
4952                                           field_index);
4953        }
4954      } else {
4955        // Attempt dictionary lookup.
4956        NameDictionary* dictionary = receiver->property_dictionary();
4957        int entry = dictionary->FindEntry(key);
4958        if ((entry != NameDictionary::kNotFound) &&
4959            (dictionary->DetailsAt(entry).type() == NORMAL)) {
4960          Object* value = dictionary->ValueAt(entry);
4961          if (!receiver->IsGlobalObject()) return value;
4962          value = PropertyCell::cast(value)->value();
4963          if (!value->IsTheHole()) return value;
4964          // If value is the hole (meaning, absent) do the general lookup.
4965        }
4966      }
4967    } else if (key_obj->IsSmi()) {
4968      // JSObject without a name key. If the key is a Smi, check for a
4969      // definite out-of-bounds access to elements, which is a strong indicator
4970      // that subsequent accesses will also call the runtime. Proactively
4971      // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4972      // doubles for those future calls in the case that the elements would
4973      // become FAST_DOUBLE_ELEMENTS.
4974      Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
4975      ElementsKind elements_kind = js_object->GetElementsKind();
4976      if (IsFastDoubleElementsKind(elements_kind)) {
4977        Handle<Smi> key = Handle<Smi>::cast(key_obj);
4978        if (key->value() >= js_object->elements()->length()) {
4979          if (IsFastHoleyElementsKind(elements_kind)) {
4980            elements_kind = FAST_HOLEY_ELEMENTS;
4981          } else {
4982            elements_kind = FAST_ELEMENTS;
4983          }
4984          RETURN_FAILURE_ON_EXCEPTION(
4985              isolate, TransitionElements(js_object, elements_kind, isolate));
4986        }
4987      } else {
4988        DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
4989               !IsFastElementsKind(elements_kind));
4990      }
4991    }
4992  } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
4993    // Fast case for string indexing using [] with a smi index.
4994    Handle<String> str = Handle<String>::cast(receiver_obj);
4995    int index = args.smi_at(1);
4996    if (index >= 0 && index < str->length()) {
4997      return *GetCharAt(str, index);
4998    }
4999  }
5000
5001  // Fall back to GetObjectProperty.
5002  Handle<Object> result;
5003  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5004      isolate, result,
5005      Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
5006  return *result;
5007}
5008
5009
5010static bool IsValidAccessor(Handle<Object> obj) {
5011  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5012}
5013
5014
5015// Transform getter or setter into something DefineAccessor can handle.
5016static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
5017                                                   Handle<Object> component) {
5018  if (component->IsUndefined()) return isolate->factory()->undefined_value();
5019  Handle<FunctionTemplateInfo> info =
5020      Handle<FunctionTemplateInfo>::cast(component);
5021  return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
5022}
5023
5024
5025RUNTIME_FUNCTION(Runtime_DefineApiAccessorProperty) {
5026  HandleScope scope(isolate);
5027  DCHECK(args.length() == 5);
5028  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5029  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5030  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5031  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5032  CONVERT_SMI_ARG_CHECKED(attribute, 4);
5033  RUNTIME_ASSERT(getter->IsUndefined() || getter->IsFunctionTemplateInfo());
5034  RUNTIME_ASSERT(setter->IsUndefined() || setter->IsFunctionTemplateInfo());
5035  RUNTIME_ASSERT(PropertyDetails::AttributesField::is_valid(
5036      static_cast<PropertyAttributes>(attribute)));
5037  RETURN_FAILURE_ON_EXCEPTION(
5038      isolate, JSObject::DefineAccessor(
5039                   object, name, InstantiateAccessorComponent(isolate, getter),
5040                   InstantiateAccessorComponent(isolate, setter),
5041                   static_cast<PropertyAttributes>(attribute)));
5042  return isolate->heap()->undefined_value();
5043}
5044
5045
5046// Implements part of 8.12.9 DefineOwnProperty.
5047// There are 3 cases that lead here:
5048// Step 4b - define a new accessor property.
5049// Steps 9c & 12 - replace an existing data property with an accessor property.
5050// Step 12 - update an existing accessor property with an accessor or generic
5051//           descriptor.
5052RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
5053  HandleScope scope(isolate);
5054  DCHECK(args.length() == 5);
5055  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5056  RUNTIME_ASSERT(!obj->IsNull());
5057  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5058  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5059  RUNTIME_ASSERT(IsValidAccessor(getter));
5060  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5061  RUNTIME_ASSERT(IsValidAccessor(setter));
5062  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5063  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5064  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5065
5066  bool fast = obj->HasFastProperties();
5067  RETURN_FAILURE_ON_EXCEPTION(
5068      isolate, JSObject::DefineAccessor(obj, name, getter, setter, attr));
5069  if (fast) JSObject::MigrateSlowToFast(obj, 0);
5070  return isolate->heap()->undefined_value();
5071}
5072
5073
5074// Implements part of 8.12.9 DefineOwnProperty.
5075// There are 3 cases that lead here:
5076// Step 4a - define a new data property.
5077// Steps 9b & 12 - replace an existing accessor property with a data property.
5078// Step 12 - update an existing data property with a data or generic
5079//           descriptor.
5080RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
5081  HandleScope scope(isolate);
5082  DCHECK(args.length() == 4);
5083  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5084  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5085  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5086  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5087  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5088  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5089
5090  LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
5091  if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) {
5092    if (!isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) {
5093      return isolate->heap()->undefined_value();
5094    }
5095    it.Next();
5096  }
5097
5098  // Take special care when attributes are different and there is already
5099  // a property.
5100  if (it.state() == LookupIterator::ACCESSOR) {
5101    // Use IgnoreAttributes version since a readonly property may be
5102    // overridden and SetProperty does not allow this.
5103    Handle<Object> result;
5104    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5105        isolate, result,
5106        JSObject::SetOwnPropertyIgnoreAttributes(
5107            js_object, name, obj_value, attr,
5108            JSObject::DONT_FORCE_FIELD));
5109    return *result;
5110  }
5111
5112  Handle<Object> result;
5113  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5114      isolate, result,
5115      Runtime::DefineObjectProperty(js_object, name, obj_value, attr));
5116  return *result;
5117}
5118
5119
5120// Return property without being observable by accessors or interceptors.
5121RUNTIME_FUNCTION(Runtime_GetDataProperty) {
5122  HandleScope scope(isolate);
5123  DCHECK(args.length() == 2);
5124  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5125  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5126  return *JSObject::GetDataProperty(object, key);
5127}
5128
5129
5130MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
5131                                               Handle<Object> object,
5132                                               Handle<Object> key,
5133                                               Handle<Object> value,
5134                                               StrictMode strict_mode) {
5135  if (object->IsUndefined() || object->IsNull()) {
5136    Handle<Object> args[2] = { key, object };
5137    THROW_NEW_ERROR(isolate, NewTypeError("non_object_property_store",
5138                                          HandleVector(args, 2)),
5139                    Object);
5140  }
5141
5142  if (object->IsJSProxy()) {
5143    Handle<Object> name_object;
5144    if (key->IsSymbol()) {
5145      name_object = key;
5146    } else {
5147      ASSIGN_RETURN_ON_EXCEPTION(
5148          isolate, name_object, Execution::ToString(isolate, key), Object);
5149    }
5150    Handle<Name> name = Handle<Name>::cast(name_object);
5151    return Object::SetProperty(Handle<JSProxy>::cast(object), name, value,
5152                               strict_mode);
5153  }
5154
5155  // Check if the given key is an array index.
5156  uint32_t index;
5157  if (key->ToArrayIndex(&index)) {
5158    // TODO(verwaest): Support non-JSObject receivers.
5159    if (!object->IsJSObject()) return value;
5160    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5161
5162    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5163    // of a string using [] notation.  We need to support this too in
5164    // JavaScript.
5165    // In the case of a String object we just need to redirect the assignment to
5166    // the underlying string if the index is in range.  Since the underlying
5167    // string does nothing with the assignment then we can ignore such
5168    // assignments.
5169    if (js_object->IsStringObjectWithCharacterAt(index)) {
5170      return value;
5171    }
5172
5173    JSObject::ValidateElements(js_object);
5174    if (js_object->HasExternalArrayElements() ||
5175        js_object->HasFixedTypedArrayElements()) {
5176      if (!value->IsNumber() && !value->IsUndefined()) {
5177        ASSIGN_RETURN_ON_EXCEPTION(
5178            isolate, value, Execution::ToNumber(isolate, value), Object);
5179      }
5180    }
5181
5182    MaybeHandle<Object> result = JSObject::SetElement(
5183        js_object, index, value, NONE, strict_mode, true, SET_PROPERTY);
5184    JSObject::ValidateElements(js_object);
5185
5186    return result.is_null() ? result : value;
5187  }
5188
5189  if (key->IsName()) {
5190    Handle<Name> name = Handle<Name>::cast(key);
5191    if (name->AsArrayIndex(&index)) {
5192      // TODO(verwaest): Support non-JSObject receivers.
5193      if (!object->IsJSObject()) return value;
5194      Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5195      if (js_object->HasExternalArrayElements()) {
5196        if (!value->IsNumber() && !value->IsUndefined()) {
5197          ASSIGN_RETURN_ON_EXCEPTION(
5198              isolate, value, Execution::ToNumber(isolate, value), Object);
5199        }
5200      }
5201      return JSObject::SetElement(js_object, index, value, NONE, strict_mode,
5202                                  true, SET_PROPERTY);
5203    } else {
5204      if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5205      return Object::SetProperty(object, name, value, strict_mode);
5206    }
5207  }
5208
5209  // Call-back into JavaScript to convert the key to a string.
5210  Handle<Object> converted;
5211  ASSIGN_RETURN_ON_EXCEPTION(
5212      isolate, converted, Execution::ToString(isolate, key), Object);
5213  Handle<String> name = Handle<String>::cast(converted);
5214
5215  if (name->AsArrayIndex(&index)) {
5216    // TODO(verwaest): Support non-JSObject receivers.
5217    if (!object->IsJSObject()) return value;
5218    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5219    return JSObject::SetElement(js_object, index, value, NONE, strict_mode,
5220                                true, SET_PROPERTY);
5221  }
5222  return Object::SetProperty(object, name, value, strict_mode);
5223}
5224
5225
5226MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object,
5227                                                  Handle<Object> key,
5228                                                  Handle<Object> value,
5229                                                  PropertyAttributes attr) {
5230  Isolate* isolate = js_object->GetIsolate();
5231  // Check if the given key is an array index.
5232  uint32_t index;
5233  if (key->ToArrayIndex(&index)) {
5234    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5235    // of a string using [] notation.  We need to support this too in
5236    // JavaScript.
5237    // In the case of a String object we just need to redirect the assignment to
5238    // the underlying string if the index is in range.  Since the underlying
5239    // string does nothing with the assignment then we can ignore such
5240    // assignments.
5241    if (js_object->IsStringObjectWithCharacterAt(index)) {
5242      return value;
5243    }
5244
5245    return JSObject::SetElement(js_object, index, value, attr,
5246                                SLOPPY, false, DEFINE_PROPERTY);
5247  }
5248
5249  if (key->IsName()) {
5250    Handle<Name> name = Handle<Name>::cast(key);
5251    if (name->AsArrayIndex(&index)) {
5252      return JSObject::SetElement(js_object, index, value, attr,
5253                                  SLOPPY, false, DEFINE_PROPERTY);
5254    } else {
5255      if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5256      return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
5257                                                      attr);
5258    }
5259  }
5260
5261  // Call-back into JavaScript to convert the key to a string.
5262  Handle<Object> converted;
5263  ASSIGN_RETURN_ON_EXCEPTION(
5264      isolate, converted, Execution::ToString(isolate, key), Object);
5265  Handle<String> name = Handle<String>::cast(converted);
5266
5267  if (name->AsArrayIndex(&index)) {
5268    return JSObject::SetElement(js_object, index, value, attr,
5269                                SLOPPY, false, DEFINE_PROPERTY);
5270  } else {
5271    return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value,
5272                                                    attr);
5273  }
5274}
5275
5276
5277MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
5278                                                  Handle<JSReceiver> receiver,
5279                                                  Handle<Object> key,
5280                                                  JSReceiver::DeleteMode mode) {
5281  // Check if the given key is an array index.
5282  uint32_t index;
5283  if (key->ToArrayIndex(&index)) {
5284    // In Firefox/SpiderMonkey, Safari and Opera you can access the
5285    // characters of a string using [] notation.  In the case of a
5286    // String object we just need to redirect the deletion to the
5287    // underlying string if the index is in range.  Since the
5288    // underlying string does nothing with the deletion, we can ignore
5289    // such deletions.
5290    if (receiver->IsStringObjectWithCharacterAt(index)) {
5291      return isolate->factory()->true_value();
5292    }
5293
5294    return JSReceiver::DeleteElement(receiver, index, mode);
5295  }
5296
5297  Handle<Name> name;
5298  if (key->IsName()) {
5299    name = Handle<Name>::cast(key);
5300  } else {
5301    // Call-back into JavaScript to convert the key to a string.
5302    Handle<Object> converted;
5303    ASSIGN_RETURN_ON_EXCEPTION(
5304        isolate, converted, Execution::ToString(isolate, key), Object);
5305    name = Handle<String>::cast(converted);
5306  }
5307
5308  if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5309  return JSReceiver::DeleteProperty(receiver, name, mode);
5310}
5311
5312
5313RUNTIME_FUNCTION(Runtime_SetHiddenProperty) {
5314  HandleScope scope(isolate);
5315  RUNTIME_ASSERT(args.length() == 3);
5316
5317  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5318  CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
5319  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5320  RUNTIME_ASSERT(key->IsUniqueName());
5321  return *JSObject::SetHiddenProperty(object, key, value);
5322}
5323
5324
5325RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
5326  HandleScope scope(isolate);
5327  RUNTIME_ASSERT(args.length() == 4);
5328
5329  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5330  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5331  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5332  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5333  RUNTIME_ASSERT(
5334      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5335  // Compute attributes.
5336  PropertyAttributes attributes =
5337      static_cast<PropertyAttributes>(unchecked_attributes);
5338
5339#ifdef DEBUG
5340  uint32_t index = 0;
5341  DCHECK(!key->ToArrayIndex(&index));
5342  LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
5343  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
5344  if (!maybe.has_value) return isolate->heap()->exception();
5345  RUNTIME_ASSERT(!it.IsFound());
5346#endif
5347
5348  Handle<Object> result;
5349  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5350      isolate, result,
5351      JSObject::SetOwnPropertyIgnoreAttributes(object, key, value, attributes));
5352  return *result;
5353}
5354
5355
5356RUNTIME_FUNCTION(Runtime_AddPropertyForTemplate) {
5357  HandleScope scope(isolate);
5358  RUNTIME_ASSERT(args.length() == 4);
5359
5360  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5361  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5362  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5363  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5364  RUNTIME_ASSERT(
5365      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5366  // Compute attributes.
5367  PropertyAttributes attributes =
5368      static_cast<PropertyAttributes>(unchecked_attributes);
5369
5370#ifdef DEBUG
5371  bool duplicate;
5372  if (key->IsName()) {
5373    LookupIterator it(object, Handle<Name>::cast(key),
5374                      LookupIterator::OWN_SKIP_INTERCEPTOR);
5375    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
5376    DCHECK(maybe.has_value);
5377    duplicate = it.IsFound();
5378  } else {
5379    uint32_t index = 0;
5380    RUNTIME_ASSERT(key->ToArrayIndex(&index));
5381    Maybe<bool> maybe = JSReceiver::HasOwnElement(object, index);
5382    if (!maybe.has_value) return isolate->heap()->exception();
5383    duplicate = maybe.value;
5384  }
5385  if (duplicate) {
5386    Handle<Object> args[1] = { key };
5387    THROW_NEW_ERROR_RETURN_FAILURE(
5388        isolate,
5389        NewTypeError("duplicate_template_property", HandleVector(args, 1)));
5390  }
5391#endif
5392
5393  Handle<Object> result;
5394  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5395      isolate, result,
5396      Runtime::DefineObjectProperty(object, key, value, attributes));
5397  return *result;
5398}
5399
5400
5401RUNTIME_FUNCTION(Runtime_SetProperty) {
5402  HandleScope scope(isolate);
5403  RUNTIME_ASSERT(args.length() == 4);
5404
5405  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5406  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5407  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5408  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 3);
5409  StrictMode strict_mode = strict_mode_arg;
5410
5411  Handle<Object> result;
5412  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5413      isolate, result,
5414      Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
5415  return *result;
5416}
5417
5418
5419// Adds an element to an array.
5420// This is used to create an indexed data property into an array.
5421RUNTIME_FUNCTION(Runtime_AddElement) {
5422  HandleScope scope(isolate);
5423  RUNTIME_ASSERT(args.length() == 4);
5424
5425  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5426  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5427  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5428  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5429  RUNTIME_ASSERT(
5430      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5431  // Compute attributes.
5432  PropertyAttributes attributes =
5433      static_cast<PropertyAttributes>(unchecked_attributes);
5434
5435  uint32_t index = 0;
5436  key->ToArrayIndex(&index);
5437
5438  Handle<Object> result;
5439  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5440      isolate, result, JSObject::SetElement(object, index, value, attributes,
5441                                            SLOPPY, false, DEFINE_PROPERTY));
5442  return *result;
5443}
5444
5445
5446RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
5447  HandleScope scope(isolate);
5448  RUNTIME_ASSERT(args.length() == 2);
5449  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5450  CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5451  JSObject::TransitionElementsKind(array, map->elements_kind());
5452  return *array;
5453}
5454
5455
5456// Set the native flag on the function.
5457// This is used to decide if we should transform null and undefined
5458// into the global object when doing call and apply.
5459RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
5460  SealHandleScope shs(isolate);
5461  RUNTIME_ASSERT(args.length() == 1);
5462
5463  CONVERT_ARG_CHECKED(Object, object, 0);
5464
5465  if (object->IsJSFunction()) {
5466    JSFunction* func = JSFunction::cast(object);
5467    func->shared()->set_native(true);
5468  }
5469  return isolate->heap()->undefined_value();
5470}
5471
5472
5473RUNTIME_FUNCTION(Runtime_SetInlineBuiltinFlag) {
5474  SealHandleScope shs(isolate);
5475  RUNTIME_ASSERT(args.length() == 1);
5476  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5477
5478  if (object->IsJSFunction()) {
5479    JSFunction* func = JSFunction::cast(*object);
5480    func->shared()->set_inline_builtin(true);
5481  }
5482  return isolate->heap()->undefined_value();
5483}
5484
5485
5486RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement) {
5487  HandleScope scope(isolate);
5488  RUNTIME_ASSERT(args.length() == 5);
5489  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5490  CONVERT_SMI_ARG_CHECKED(store_index, 1);
5491  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5492  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5493  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5494
5495  Object* raw_literal_cell = literals->get(literal_index);
5496  JSArray* boilerplate = NULL;
5497  if (raw_literal_cell->IsAllocationSite()) {
5498    AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5499    boilerplate = JSArray::cast(site->transition_info());
5500  } else {
5501    boilerplate = JSArray::cast(raw_literal_cell);
5502  }
5503  Handle<JSArray> boilerplate_object(boilerplate);
5504  ElementsKind elements_kind = object->GetElementsKind();
5505  DCHECK(IsFastElementsKind(elements_kind));
5506  // Smis should never trigger transitions.
5507  DCHECK(!value->IsSmi());
5508
5509  if (value->IsNumber()) {
5510    DCHECK(IsFastSmiElementsKind(elements_kind));
5511    ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5512        ? FAST_HOLEY_DOUBLE_ELEMENTS
5513        : FAST_DOUBLE_ELEMENTS;
5514    if (IsMoreGeneralElementsKindTransition(
5515            boilerplate_object->GetElementsKind(),
5516            transitioned_kind)) {
5517      JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5518    }
5519    JSObject::TransitionElementsKind(object, transitioned_kind);
5520    DCHECK(IsFastDoubleElementsKind(object->GetElementsKind()));
5521    FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5522    HeapNumber* number = HeapNumber::cast(*value);
5523    double_array->set(store_index, number->Number());
5524  } else {
5525    if (!IsFastObjectElementsKind(elements_kind)) {
5526      ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5527          ? FAST_HOLEY_ELEMENTS
5528          : FAST_ELEMENTS;
5529      JSObject::TransitionElementsKind(object, transitioned_kind);
5530      ElementsKind boilerplate_elements_kind =
5531          boilerplate_object->GetElementsKind();
5532      if (IsMoreGeneralElementsKindTransition(boilerplate_elements_kind,
5533                                              transitioned_kind)) {
5534        JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5535      }
5536    }
5537    FixedArray* object_array = FixedArray::cast(object->elements());
5538    object_array->set(store_index, *value);
5539  }
5540  return *object;
5541}
5542
5543
5544// Check whether debugger and is about to step into the callback that is passed
5545// to a built-in function such as Array.forEach.
5546RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
5547  DCHECK(args.length() == 1);
5548  if (!isolate->debug()->is_active() || !isolate->debug()->StepInActive()) {
5549    return isolate->heap()->false_value();
5550  }
5551  CONVERT_ARG_CHECKED(Object, callback, 0);
5552  // We do not step into the callback if it's a builtin or not even a function.
5553  return isolate->heap()->ToBoolean(
5554      callback->IsJSFunction() && !JSFunction::cast(callback)->IsBuiltin());
5555}
5556
5557
5558// Set one shot breakpoints for the callback function that is passed to a
5559// built-in function such as Array.forEach to enable stepping into the callback.
5560RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
5561  DCHECK(args.length() == 1);
5562  Debug* debug = isolate->debug();
5563  if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5564
5565  HandleScope scope(isolate);
5566  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5567  RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
5568  Handle<JSFunction> fun;
5569  if (object->IsJSFunction()) {
5570    fun = Handle<JSFunction>::cast(object);
5571  } else {
5572    fun = Handle<JSFunction>(
5573        Handle<JSGeneratorObject>::cast(object)->function(), isolate);
5574  }
5575  // When leaving the function, step out has been activated, but not performed
5576  // if we do not leave the builtin.  To be able to step into the function
5577  // again, we need to clear the step out at this point.
5578  debug->ClearStepOut();
5579  debug->FloodWithOneShot(fun);
5580  return isolate->heap()->undefined_value();
5581}
5582
5583
5584RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
5585  DCHECK(args.length() == 1);
5586  HandleScope scope(isolate);
5587  CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
5588  isolate->PushPromise(promise);
5589  return isolate->heap()->undefined_value();
5590}
5591
5592
5593RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
5594  DCHECK(args.length() == 0);
5595  SealHandleScope shs(isolate);
5596  isolate->PopPromise();
5597  return isolate->heap()->undefined_value();
5598}
5599
5600
5601RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) {
5602  DCHECK(args.length() == 1);
5603  HandleScope scope(isolate);
5604  CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
5605  isolate->debug()->OnPromiseEvent(data);
5606  return isolate->heap()->undefined_value();
5607}
5608
5609
5610RUNTIME_FUNCTION(Runtime_DebugPromiseRejectEvent) {
5611  DCHECK(args.length() == 2);
5612  HandleScope scope(isolate);
5613  CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
5614  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
5615  isolate->debug()->OnPromiseReject(promise, value);
5616  return isolate->heap()->undefined_value();
5617}
5618
5619
5620RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
5621  DCHECK(args.length() == 1);
5622  HandleScope scope(isolate);
5623  CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0);
5624  isolate->debug()->OnAsyncTaskEvent(data);
5625  return isolate->heap()->undefined_value();
5626}
5627
5628
5629RUNTIME_FUNCTION(Runtime_DeleteProperty) {
5630  HandleScope scope(isolate);
5631  DCHECK(args.length() == 3);
5632  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5633  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5634  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5635  JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
5636      ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5637  Handle<Object> result;
5638  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5639      isolate, result,
5640      JSReceiver::DeleteProperty(object, key, delete_mode));
5641  return *result;
5642}
5643
5644
5645static Object* HasOwnPropertyImplementation(Isolate* isolate,
5646                                            Handle<JSObject> object,
5647                                            Handle<Name> key) {
5648  Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
5649  if (!maybe.has_value) return isolate->heap()->exception();
5650  if (maybe.value) return isolate->heap()->true_value();
5651  // Handle hidden prototypes.  If there's a hidden prototype above this thing
5652  // then we have to check it for properties, because they are supposed to
5653  // look like they are on this object.
5654  PrototypeIterator iter(isolate, object);
5655  if (!iter.IsAtEnd() &&
5656      Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))
5657          ->map()
5658          ->is_hidden_prototype()) {
5659    // TODO(verwaest): The recursion is not necessary for keys that are array
5660    // indices. Removing this.
5661    return HasOwnPropertyImplementation(
5662        isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
5663        key);
5664  }
5665  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5666  return isolate->heap()->false_value();
5667}
5668
5669
5670RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
5671  HandleScope scope(isolate);
5672  DCHECK(args.length() == 2);
5673  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
5674  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5675
5676  uint32_t index;
5677  const bool key_is_array_index = key->AsArrayIndex(&index);
5678
5679  // Only JS objects can have properties.
5680  if (object->IsJSObject()) {
5681    Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5682    // Fast case: either the key is a real named property or it is not
5683    // an array index and there are no interceptors or hidden
5684    // prototypes.
5685    Maybe<bool> maybe = JSObject::HasRealNamedProperty(js_obj, key);
5686    if (!maybe.has_value) return isolate->heap()->exception();
5687    DCHECK(!isolate->has_pending_exception());
5688    if (maybe.value) {
5689      return isolate->heap()->true_value();
5690    }
5691    Map* map = js_obj->map();
5692    if (!key_is_array_index &&
5693        !map->has_named_interceptor() &&
5694        !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5695      return isolate->heap()->false_value();
5696    }
5697    // Slow case.
5698    return HasOwnPropertyImplementation(isolate,
5699                                        Handle<JSObject>(js_obj),
5700                                        Handle<Name>(key));
5701  } else if (object->IsString() && key_is_array_index) {
5702    // Well, there is one exception:  Handle [] on strings.
5703    Handle<String> string = Handle<String>::cast(object);
5704    if (index < static_cast<uint32_t>(string->length())) {
5705      return isolate->heap()->true_value();
5706    }
5707  }
5708  return isolate->heap()->false_value();
5709}
5710
5711
5712RUNTIME_FUNCTION(Runtime_HasProperty) {
5713  HandleScope scope(isolate);
5714  DCHECK(args.length() == 2);
5715  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5716  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5717
5718  Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key);
5719  if (!maybe.has_value) return isolate->heap()->exception();
5720  return isolate->heap()->ToBoolean(maybe.value);
5721}
5722
5723
5724RUNTIME_FUNCTION(Runtime_HasElement) {
5725  HandleScope scope(isolate);
5726  DCHECK(args.length() == 2);
5727  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5728  CONVERT_SMI_ARG_CHECKED(index, 1);
5729
5730  Maybe<bool> maybe = JSReceiver::HasElement(receiver, index);
5731  if (!maybe.has_value) return isolate->heap()->exception();
5732  return isolate->heap()->ToBoolean(maybe.value);
5733}
5734
5735
5736RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
5737  HandleScope scope(isolate);
5738  DCHECK(args.length() == 2);
5739
5740  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5741  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5742
5743  Maybe<PropertyAttributes> maybe =
5744      JSReceiver::GetOwnPropertyAttributes(object, key);
5745  if (!maybe.has_value) return isolate->heap()->exception();
5746  if (maybe.value == ABSENT) maybe.value = DONT_ENUM;
5747  return isolate->heap()->ToBoolean((maybe.value & DONT_ENUM) == 0);
5748}
5749
5750
5751RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
5752  HandleScope scope(isolate);
5753  DCHECK(args.length() == 1);
5754  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5755  Handle<JSArray> result;
5756
5757  isolate->counters()->for_in()->Increment();
5758  Handle<FixedArray> elements;
5759  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5760      isolate, elements,
5761      JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
5762  return *isolate->factory()->NewJSArrayWithElements(elements);
5763}
5764
5765
5766// Returns either a FixedArray as Runtime_GetPropertyNames,
5767// or, if the given object has an enum cache that contains
5768// all enumerable properties of the object and its prototypes
5769// have none, the map of the object. This is used to speed up
5770// the check for deletions during a for-in.
5771RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
5772  SealHandleScope shs(isolate);
5773  DCHECK(args.length() == 1);
5774
5775  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5776
5777  if (raw_object->IsSimpleEnum()) return raw_object->map();
5778
5779  HandleScope scope(isolate);
5780  Handle<JSReceiver> object(raw_object);
5781  Handle<FixedArray> content;
5782  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5783      isolate, content,
5784      JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
5785
5786  // Test again, since cache may have been built by preceding call.
5787  if (object->IsSimpleEnum()) return object->map();
5788
5789  return *content;
5790}
5791
5792
5793// Find the length of the prototype chain that is to be handled as one. If a
5794// prototype object is hidden it is to be viewed as part of the the object it
5795// is prototype for.
5796static int OwnPrototypeChainLength(JSObject* obj) {
5797  int count = 1;
5798  for (PrototypeIterator iter(obj->GetIsolate(), obj);
5799       !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
5800    count++;
5801  }
5802  return count;
5803}
5804
5805
5806// Return the names of the own named properties.
5807// args[0]: object
5808// args[1]: PropertyAttributes as int
5809RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
5810  HandleScope scope(isolate);
5811  DCHECK(args.length() == 2);
5812  if (!args[0]->IsJSObject()) {
5813    return isolate->heap()->undefined_value();
5814  }
5815  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5816  CONVERT_SMI_ARG_CHECKED(filter_value, 1);
5817  PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
5818
5819  // Skip the global proxy as it has no properties and always delegates to the
5820  // real global object.
5821  if (obj->IsJSGlobalProxy()) {
5822    // Only collect names if access is permitted.
5823    if (obj->IsAccessCheckNeeded() &&
5824        !isolate->MayNamedAccess(
5825            obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5826      isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
5827      RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5828      return *isolate->factory()->NewJSArray(0);
5829    }
5830    PrototypeIterator iter(isolate, obj);
5831    obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
5832  }
5833
5834  // Find the number of objects making up this.
5835  int length = OwnPrototypeChainLength(*obj);
5836
5837  // Find the number of own properties for each of the objects.
5838  ScopedVector<int> own_property_count(length);
5839  int total_property_count = 0;
5840  {
5841    PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
5842    for (int i = 0; i < length; i++) {
5843      DCHECK(!iter.IsAtEnd());
5844      Handle<JSObject> jsproto =
5845          Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
5846      // Only collect names if access is permitted.
5847      if (jsproto->IsAccessCheckNeeded() &&
5848          !isolate->MayNamedAccess(jsproto,
5849                                   isolate->factory()->undefined_value(),
5850                                   v8::ACCESS_KEYS)) {
5851        isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS);
5852        RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5853        return *isolate->factory()->NewJSArray(0);
5854      }
5855      int n;
5856      n = jsproto->NumberOfOwnProperties(filter);
5857      own_property_count[i] = n;
5858      total_property_count += n;
5859      iter.Advance();
5860    }
5861  }
5862
5863  // Allocate an array with storage for all the property names.
5864  Handle<FixedArray> names =
5865      isolate->factory()->NewFixedArray(total_property_count);
5866
5867  // Get the property names.
5868  int next_copy_index = 0;
5869  int hidden_strings = 0;
5870  {
5871    PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
5872    for (int i = 0; i < length; i++) {
5873      DCHECK(!iter.IsAtEnd());
5874      Handle<JSObject> jsproto =
5875          Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
5876      jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
5877      if (i > 0) {
5878        // Names from hidden prototypes may already have been added
5879        // for inherited function template instances. Count the duplicates
5880        // and stub them out; the final copy pass at the end ignores holes.
5881        for (int j = next_copy_index;
5882             j < next_copy_index + own_property_count[i]; j++) {
5883          Object* name_from_hidden_proto = names->get(j);
5884          for (int k = 0; k < next_copy_index; k++) {
5885            if (names->get(k) != isolate->heap()->hidden_string()) {
5886              Object* name = names->get(k);
5887              if (name_from_hidden_proto == name) {
5888                names->set(j, isolate->heap()->hidden_string());
5889                hidden_strings++;
5890                break;
5891              }
5892            }
5893          }
5894        }
5895      }
5896      next_copy_index += own_property_count[i];
5897
5898      // Hidden properties only show up if the filter does not skip strings.
5899      if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
5900        hidden_strings++;
5901      }
5902      iter.Advance();
5903    }
5904  }
5905
5906  // Filter out name of hidden properties object and
5907  // hidden prototype duplicates.
5908  if (hidden_strings > 0) {
5909    Handle<FixedArray> old_names = names;
5910    names = isolate->factory()->NewFixedArray(
5911        names->length() - hidden_strings);
5912    int dest_pos = 0;
5913    for (int i = 0; i < total_property_count; i++) {
5914      Object* name = old_names->get(i);
5915      if (name == isolate->heap()->hidden_string()) {
5916        hidden_strings--;
5917        continue;
5918      }
5919      names->set(dest_pos++, name);
5920    }
5921    DCHECK_EQ(0, hidden_strings);
5922  }
5923
5924  return *isolate->factory()->NewJSArrayWithElements(names);
5925}
5926
5927
5928// Return the names of the own indexed properties.
5929// args[0]: object
5930RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
5931  HandleScope scope(isolate);
5932  DCHECK(args.length() == 1);
5933  if (!args[0]->IsJSObject()) {
5934    return isolate->heap()->undefined_value();
5935  }
5936  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5937
5938  int n = obj->NumberOfOwnElements(static_cast<PropertyAttributes>(NONE));
5939  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5940  obj->GetOwnElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5941  return *isolate->factory()->NewJSArrayWithElements(names);
5942}
5943
5944
5945// Return information on whether an object has a named or indexed interceptor.
5946// args[0]: object
5947RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
5948  HandleScope scope(isolate);
5949  DCHECK(args.length() == 1);
5950  if (!args[0]->IsJSObject()) {
5951    return Smi::FromInt(0);
5952  }
5953  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5954
5955  int result = 0;
5956  if (obj->HasNamedInterceptor()) result |= 2;
5957  if (obj->HasIndexedInterceptor()) result |= 1;
5958
5959  return Smi::FromInt(result);
5960}
5961
5962
5963// Return property names from named interceptor.
5964// args[0]: object
5965RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
5966  HandleScope scope(isolate);
5967  DCHECK(args.length() == 1);
5968  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5969
5970  if (obj->HasNamedInterceptor()) {
5971    Handle<JSObject> result;
5972    if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
5973      return *result;
5974    }
5975  }
5976  return isolate->heap()->undefined_value();
5977}
5978
5979
5980// Return element names from indexed interceptor.
5981// args[0]: object
5982RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
5983  HandleScope scope(isolate);
5984  DCHECK(args.length() == 1);
5985  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5986
5987  if (obj->HasIndexedInterceptor()) {
5988    Handle<JSObject> result;
5989    if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
5990      return *result;
5991    }
5992  }
5993  return isolate->heap()->undefined_value();
5994}
5995
5996
5997RUNTIME_FUNCTION(Runtime_OwnKeys) {
5998  HandleScope scope(isolate);
5999  DCHECK(args.length() == 1);
6000  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
6001  Handle<JSObject> object(raw_object);
6002
6003  if (object->IsJSGlobalProxy()) {
6004    // Do access checks before going to the global object.
6005    if (object->IsAccessCheckNeeded() &&
6006        !isolate->MayNamedAccess(
6007            object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6008      isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
6009      RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
6010      return *isolate->factory()->NewJSArray(0);
6011    }
6012
6013    PrototypeIterator iter(isolate, object);
6014    // If proxy is detached we simply return an empty array.
6015    if (iter.IsAtEnd()) return *isolate->factory()->NewJSArray(0);
6016    object = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
6017  }
6018
6019  Handle<FixedArray> contents;
6020  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6021      isolate, contents,
6022      JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
6023
6024  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
6025  // property array and since the result is mutable we have to create
6026  // a fresh clone on each invocation.
6027  int length = contents->length();
6028  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
6029  for (int i = 0; i < length; i++) {
6030    Object* entry = contents->get(i);
6031    if (entry->IsString()) {
6032      copy->set(i, entry);
6033    } else {
6034      DCHECK(entry->IsNumber());
6035      HandleScope scope(isolate);
6036      Handle<Object> entry_handle(entry, isolate);
6037      Handle<Object> entry_str =
6038          isolate->factory()->NumberToString(entry_handle);
6039      copy->set(i, *entry_str);
6040    }
6041  }
6042  return *isolate->factory()->NewJSArrayWithElements(copy);
6043}
6044
6045
6046RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
6047  SealHandleScope shs(isolate);
6048  DCHECK(args.length() == 1);
6049  CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
6050
6051  // Compute the frame holding the arguments.
6052  JavaScriptFrameIterator it(isolate);
6053  it.AdvanceToArgumentsFrame();
6054  JavaScriptFrame* frame = it.frame();
6055
6056  // Get the actual number of provided arguments.
6057  const uint32_t n = frame->ComputeParametersCount();
6058
6059  // Try to convert the key to an index. If successful and within
6060  // index return the the argument from the frame.
6061  uint32_t index;
6062  if (raw_key->ToArrayIndex(&index) && index < n) {
6063    return frame->GetParameter(index);
6064  }
6065
6066  HandleScope scope(isolate);
6067  if (raw_key->IsSymbol()) {
6068    Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
6069    if (symbol->Equals(isolate->native_context()->iterator_symbol())) {
6070      return isolate->native_context()->array_values_iterator();
6071    }
6072    // Lookup in the initial Object.prototype object.
6073    Handle<Object> result;
6074    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6075        isolate, result,
6076        Object::GetProperty(isolate->initial_object_prototype(),
6077                            Handle<Symbol>::cast(raw_key)));
6078    return *result;
6079  }
6080
6081  // Convert the key to a string.
6082  Handle<Object> converted;
6083  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6084      isolate, converted, Execution::ToString(isolate, raw_key));
6085  Handle<String> key = Handle<String>::cast(converted);
6086
6087  // Try to convert the string key into an array index.
6088  if (key->AsArrayIndex(&index)) {
6089    if (index < n) {
6090      return frame->GetParameter(index);
6091    } else {
6092      Handle<Object> initial_prototype(isolate->initial_object_prototype());
6093      Handle<Object> result;
6094      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6095          isolate, result,
6096          Object::GetElement(isolate, initial_prototype, index));
6097      return *result;
6098    }
6099  }
6100
6101  // Handle special arguments properties.
6102  if (String::Equals(isolate->factory()->length_string(), key)) {
6103    return Smi::FromInt(n);
6104  }
6105  if (String::Equals(isolate->factory()->callee_string(), key)) {
6106    JSFunction* function = frame->function();
6107    if (function->shared()->strict_mode() == STRICT) {
6108      THROW_NEW_ERROR_RETURN_FAILURE(
6109          isolate, NewTypeError("strict_arguments_callee",
6110                                HandleVector<Object>(NULL, 0)));
6111    }
6112    return function;
6113  }
6114
6115  // Lookup in the initial Object.prototype object.
6116  Handle<Object> result;
6117  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6118      isolate, result,
6119      Object::GetProperty(isolate->initial_object_prototype(), key));
6120  return *result;
6121}
6122
6123
6124RUNTIME_FUNCTION(Runtime_ToFastProperties) {
6125  HandleScope scope(isolate);
6126  DCHECK(args.length() == 1);
6127  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6128  if (object->IsJSObject() && !object->IsGlobalObject()) {
6129    JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0);
6130  }
6131  return *object;
6132}
6133
6134
6135RUNTIME_FUNCTION(Runtime_ToBool) {
6136  SealHandleScope shs(isolate);
6137  DCHECK(args.length() == 1);
6138  CONVERT_ARG_CHECKED(Object, object, 0);
6139
6140  return isolate->heap()->ToBoolean(object->BooleanValue());
6141}
6142
6143
6144// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6145// Possible optimizations: put the type string into the oddballs.
6146RUNTIME_FUNCTION(Runtime_Typeof) {
6147  SealHandleScope shs(isolate);
6148  DCHECK(args.length() == 1);
6149  CONVERT_ARG_CHECKED(Object, obj, 0);
6150  if (obj->IsNumber()) return isolate->heap()->number_string();
6151  HeapObject* heap_obj = HeapObject::cast(obj);
6152
6153  // typeof an undetectable object is 'undefined'
6154  if (heap_obj->map()->is_undetectable()) {
6155    return isolate->heap()->undefined_string();
6156  }
6157
6158  InstanceType instance_type = heap_obj->map()->instance_type();
6159  if (instance_type < FIRST_NONSTRING_TYPE) {
6160    return isolate->heap()->string_string();
6161  }
6162
6163  switch (instance_type) {
6164    case ODDBALL_TYPE:
6165      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6166        return isolate->heap()->boolean_string();
6167      }
6168      if (heap_obj->IsNull()) {
6169        return isolate->heap()->object_string();
6170      }
6171      DCHECK(heap_obj->IsUndefined());
6172      return isolate->heap()->undefined_string();
6173    case SYMBOL_TYPE:
6174      return isolate->heap()->symbol_string();
6175    case JS_FUNCTION_TYPE:
6176    case JS_FUNCTION_PROXY_TYPE:
6177      return isolate->heap()->function_string();
6178    default:
6179      // For any kind of object not handled above, the spec rule for
6180      // host objects gives that it is okay to return "object"
6181      return isolate->heap()->object_string();
6182  }
6183}
6184
6185
6186RUNTIME_FUNCTION(Runtime_Booleanize) {
6187  SealHandleScope shs(isolate);
6188  DCHECK(args.length() == 2);
6189  CONVERT_ARG_CHECKED(Object, value_raw, 0);
6190  CONVERT_SMI_ARG_CHECKED(token_raw, 1);
6191  intptr_t value = reinterpret_cast<intptr_t>(value_raw);
6192  Token::Value token = static_cast<Token::Value>(token_raw);
6193  switch (token) {
6194    case Token::EQ:
6195    case Token::EQ_STRICT:
6196      return isolate->heap()->ToBoolean(value == 0);
6197    case Token::NE:
6198    case Token::NE_STRICT:
6199      return isolate->heap()->ToBoolean(value != 0);
6200    case Token::LT:
6201      return isolate->heap()->ToBoolean(value < 0);
6202    case Token::GT:
6203      return isolate->heap()->ToBoolean(value > 0);
6204    case Token::LTE:
6205      return isolate->heap()->ToBoolean(value <= 0);
6206    case Token::GTE:
6207      return isolate->heap()->ToBoolean(value >= 0);
6208    default:
6209      // This should only happen during natives fuzzing.
6210      return isolate->heap()->undefined_value();
6211  }
6212}
6213
6214
6215static bool AreDigits(const uint8_t*s, int from, int to) {
6216  for (int i = from; i < to; i++) {
6217    if (s[i] < '0' || s[i] > '9') return false;
6218  }
6219
6220  return true;
6221}
6222
6223
6224static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6225  DCHECK(to - from < 10);  // Overflow is not possible.
6226  DCHECK(from < to);
6227  int d = s[from] - '0';
6228
6229  for (int i = from + 1; i < to; i++) {
6230    d = 10 * d + (s[i] - '0');
6231  }
6232
6233  return d;
6234}
6235
6236
6237RUNTIME_FUNCTION(Runtime_StringToNumber) {
6238  HandleScope handle_scope(isolate);
6239  DCHECK(args.length() == 1);
6240  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6241  subject = String::Flatten(subject);
6242
6243  // Fast case: short integer or some sorts of junk values.
6244  if (subject->IsSeqOneByteString()) {
6245    int len = subject->length();
6246    if (len == 0) return Smi::FromInt(0);
6247
6248    DisallowHeapAllocation no_gc;
6249    uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
6250    bool minus = (data[0] == '-');
6251    int start_pos = (minus ? 1 : 0);
6252
6253    if (start_pos == len) {
6254      return isolate->heap()->nan_value();
6255    } else if (data[start_pos] > '9') {
6256      // Fast check for a junk value. A valid string may start from a
6257      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
6258      // or the 'I' character ('Infinity'). All of that have codes not greater
6259      // than '9' except 'I' and &nbsp;.
6260      if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6261        return isolate->heap()->nan_value();
6262      }
6263    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6264      // The maximal/minimal smi has 10 digits. If the string has less digits
6265      // we know it will fit into the smi-data type.
6266      int d = ParseDecimalInteger(data, start_pos, len);
6267      if (minus) {
6268        if (d == 0) return isolate->heap()->minus_zero_value();
6269        d = -d;
6270      } else if (!subject->HasHashCode() &&
6271                 len <= String::kMaxArrayIndexSize &&
6272                 (len == 1 || data[0] != '0')) {
6273        // String hash is not calculated yet but all the data are present.
6274        // Update the hash field to speed up sequential convertions.
6275        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6276#ifdef DEBUG
6277        subject->Hash();  // Force hash calculation.
6278        DCHECK_EQ(static_cast<int>(subject->hash_field()),
6279                  static_cast<int>(hash));
6280#endif
6281        subject->set_hash_field(hash);
6282      }
6283      return Smi::FromInt(d);
6284    }
6285  }
6286
6287  // Slower case.
6288  int flags = ALLOW_HEX;
6289  if (FLAG_harmony_numeric_literals) {
6290    // The current spec draft has not updated "ToNumber Applied to the String
6291    // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6292    flags |= ALLOW_OCTAL | ALLOW_BINARY;
6293  }
6294
6295  return *isolate->factory()->NewNumber(StringToDouble(
6296      isolate->unicode_cache(), *subject, flags));
6297}
6298
6299
6300RUNTIME_FUNCTION(Runtime_NewString) {
6301  HandleScope scope(isolate);
6302  DCHECK(args.length() == 2);
6303  CONVERT_INT32_ARG_CHECKED(length, 0);
6304  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6305  if (length == 0) return isolate->heap()->empty_string();
6306  Handle<String> result;
6307  if (is_one_byte) {
6308    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6309        isolate, result, isolate->factory()->NewRawOneByteString(length));
6310  } else {
6311    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6312        isolate, result, isolate->factory()->NewRawTwoByteString(length));
6313  }
6314  return *result;
6315}
6316
6317
6318RUNTIME_FUNCTION(Runtime_TruncateString) {
6319  HandleScope scope(isolate);
6320  DCHECK(args.length() == 2);
6321  CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6322  CONVERT_INT32_ARG_CHECKED(new_length, 1);
6323  RUNTIME_ASSERT(new_length >= 0);
6324  return *SeqString::Truncate(string, new_length);
6325}
6326
6327
6328RUNTIME_FUNCTION(Runtime_URIEscape) {
6329  HandleScope scope(isolate);
6330  DCHECK(args.length() == 1);
6331  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6332  Handle<String> string = String::Flatten(source);
6333  DCHECK(string->IsFlat());
6334  Handle<String> result;
6335  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6336      isolate, result,
6337      string->IsOneByteRepresentationUnderneath()
6338            ? URIEscape::Escape<uint8_t>(isolate, source)
6339            : URIEscape::Escape<uc16>(isolate, source));
6340  return *result;
6341}
6342
6343
6344RUNTIME_FUNCTION(Runtime_URIUnescape) {
6345  HandleScope scope(isolate);
6346  DCHECK(args.length() == 1);
6347  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6348  Handle<String> string = String::Flatten(source);
6349  DCHECK(string->IsFlat());
6350  Handle<String> result;
6351  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6352      isolate, result,
6353      string->IsOneByteRepresentationUnderneath()
6354            ? URIUnescape::Unescape<uint8_t>(isolate, source)
6355            : URIUnescape::Unescape<uc16>(isolate, source));
6356  return *result;
6357}
6358
6359
6360RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
6361  HandleScope scope(isolate);
6362  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6363  DCHECK(args.length() == 1);
6364  Handle<Object> result;
6365  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6366      isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
6367  return *result;
6368}
6369
6370
6371RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
6372  HandleScope scope(isolate);
6373  DCHECK(args.length() == 1);
6374  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6375  BasicJsonStringifier stringifier(isolate);
6376  Handle<Object> result;
6377  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6378      isolate, result, stringifier.Stringify(object));
6379  return *result;
6380}
6381
6382
6383RUNTIME_FUNCTION(Runtime_StringParseInt) {
6384  HandleScope handle_scope(isolate);
6385  DCHECK(args.length() == 2);
6386  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6387  CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
6388  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6389
6390  subject = String::Flatten(subject);
6391  double value;
6392
6393  { DisallowHeapAllocation no_gc;
6394    String::FlatContent flat = subject->GetFlatContent();
6395
6396    // ECMA-262 section 15.1.2.3, empty string is NaN
6397    if (flat.IsOneByte()) {
6398      value = StringToInt(
6399          isolate->unicode_cache(), flat.ToOneByteVector(), radix);
6400    } else {
6401      value = StringToInt(
6402          isolate->unicode_cache(), flat.ToUC16Vector(), radix);
6403    }
6404  }
6405
6406  return *isolate->factory()->NewNumber(value);
6407}
6408
6409
6410RUNTIME_FUNCTION(Runtime_StringParseFloat) {
6411  HandleScope shs(isolate);
6412  DCHECK(args.length() == 1);
6413  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6414
6415  subject = String::Flatten(subject);
6416  double value = StringToDouble(isolate->unicode_cache(), *subject,
6417                                ALLOW_TRAILING_JUNK, base::OS::nan_value());
6418
6419  return *isolate->factory()->NewNumber(value);
6420}
6421
6422
6423static inline bool ToUpperOverflows(uc32 character) {
6424  // y with umlauts and the micro sign are the only characters that stop
6425  // fitting into one-byte when converting to uppercase.
6426  static const uc32 yuml_code = 0xff;
6427  static const uc32 micro_code = 0xb5;
6428  return (character == yuml_code || character == micro_code);
6429}
6430
6431
6432template <class Converter>
6433MUST_USE_RESULT static Object* ConvertCaseHelper(
6434    Isolate* isolate,
6435    String* string,
6436    SeqString* result,
6437    int result_length,
6438    unibrow::Mapping<Converter, 128>* mapping) {
6439  DisallowHeapAllocation no_gc;
6440  // We try this twice, once with the assumption that the result is no longer
6441  // than the input and, if that assumption breaks, again with the exact
6442  // length.  This may not be pretty, but it is nicer than what was here before
6443  // and I hereby claim my vaffel-is.
6444  //
6445  // NOTE: This assumes that the upper/lower case of an ASCII
6446  // character is also ASCII.  This is currently the case, but it
6447  // might break in the future if we implement more context and locale
6448  // dependent upper/lower conversions.
6449  bool has_changed_character = false;
6450
6451  // Convert all characters to upper case, assuming that they will fit
6452  // in the buffer
6453  Access<ConsStringIteratorOp> op(
6454      isolate->runtime_state()->string_iterator());
6455  StringCharacterStream stream(string, op.value());
6456  unibrow::uchar chars[Converter::kMaxWidth];
6457  // We can assume that the string is not empty
6458  uc32 current = stream.GetNext();
6459  bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
6460  for (int i = 0; i < result_length;) {
6461    bool has_next = stream.HasMore();
6462    uc32 next = has_next ? stream.GetNext() : 0;
6463    int char_length = mapping->get(current, next, chars);
6464    if (char_length == 0) {
6465      // The case conversion of this character is the character itself.
6466      result->Set(i, current);
6467      i++;
6468    } else if (char_length == 1 &&
6469               (ignore_overflow || !ToUpperOverflows(current))) {
6470      // Common case: converting the letter resulted in one character.
6471      DCHECK(static_cast<uc32>(chars[0]) != current);
6472      result->Set(i, chars[0]);
6473      has_changed_character = true;
6474      i++;
6475    } else if (result_length == string->length()) {
6476      bool overflows = ToUpperOverflows(current);
6477      // We've assumed that the result would be as long as the
6478      // input but here is a character that converts to several
6479      // characters.  No matter, we calculate the exact length
6480      // of the result and try the whole thing again.
6481      //
6482      // Note that this leaves room for optimization.  We could just
6483      // memcpy what we already have to the result string.  Also,
6484      // the result string is the last object allocated we could
6485      // "realloc" it and probably, in the vast majority of cases,
6486      // extend the existing string to be able to hold the full
6487      // result.
6488      int next_length = 0;
6489      if (has_next) {
6490        next_length = mapping->get(next, 0, chars);
6491        if (next_length == 0) next_length = 1;
6492      }
6493      int current_length = i + char_length + next_length;
6494      while (stream.HasMore()) {
6495        current = stream.GetNext();
6496        overflows |= ToUpperOverflows(current);
6497        // NOTE: we use 0 as the next character here because, while
6498        // the next character may affect what a character converts to,
6499        // it does not in any case affect the length of what it convert
6500        // to.
6501        int char_length = mapping->get(current, 0, chars);
6502        if (char_length == 0) char_length = 1;
6503        current_length += char_length;
6504        if (current_length > String::kMaxLength) {
6505          AllowHeapAllocation allocate_error_and_return;
6506          THROW_NEW_ERROR_RETURN_FAILURE(isolate,
6507                                         NewInvalidStringLengthError());
6508        }
6509      }
6510      // Try again with the real length.  Return signed if we need
6511      // to allocate a two-byte string for to uppercase.
6512      return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
6513                                             : Smi::FromInt(current_length);
6514    } else {
6515      for (int j = 0; j < char_length; j++) {
6516        result->Set(i, chars[j]);
6517        i++;
6518      }
6519      has_changed_character = true;
6520    }
6521    current = next;
6522  }
6523  if (has_changed_character) {
6524    return result;
6525  } else {
6526    // If we didn't actually change anything in doing the conversion
6527    // we simple return the result and let the converted string
6528    // become garbage; there is no reason to keep two identical strings
6529    // alive.
6530    return string;
6531  }
6532}
6533
6534
6535namespace {
6536
6537static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6538static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6539
6540// Given a word and two range boundaries returns a word with high bit
6541// set in every byte iff the corresponding input byte was strictly in
6542// the range (m, n). All the other bits in the result are cleared.
6543// This function is only useful when it can be inlined and the
6544// boundaries are statically known.
6545// Requires: all bytes in the input word and the boundaries must be
6546// ASCII (less than 0x7F).
6547static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6548  // Use strict inequalities since in edge cases the function could be
6549  // further simplified.
6550  DCHECK(0 < m && m < n);
6551  // Has high bit set in every w byte less than n.
6552  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6553  // Has high bit set in every w byte greater than m.
6554  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6555  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6556}
6557
6558
6559#ifdef DEBUG
6560static bool CheckFastAsciiConvert(char* dst,
6561                                  const char* src,
6562                                  int length,
6563                                  bool changed,
6564                                  bool is_to_lower) {
6565  bool expected_changed = false;
6566  for (int i = 0; i < length; i++) {
6567    if (dst[i] == src[i]) continue;
6568    expected_changed = true;
6569    if (is_to_lower) {
6570      DCHECK('A' <= src[i] && src[i] <= 'Z');
6571      DCHECK(dst[i] == src[i] + ('a' - 'A'));
6572    } else {
6573      DCHECK('a' <= src[i] && src[i] <= 'z');
6574      DCHECK(dst[i] == src[i] - ('a' - 'A'));
6575    }
6576  }
6577  return (expected_changed == changed);
6578}
6579#endif
6580
6581
6582template<class Converter>
6583static bool FastAsciiConvert(char* dst,
6584                             const char* src,
6585                             int length,
6586                             bool* changed_out) {
6587#ifdef DEBUG
6588    char* saved_dst = dst;
6589    const char* saved_src = src;
6590#endif
6591  DisallowHeapAllocation no_gc;
6592  // We rely on the distance between upper and lower case letters
6593  // being a known power of 2.
6594  DCHECK('a' - 'A' == (1 << 5));
6595  // Boundaries for the range of input characters than require conversion.
6596  static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6597  static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6598  bool changed = false;
6599  uintptr_t or_acc = 0;
6600  const char* const limit = src + length;
6601
6602  // dst is newly allocated and always aligned.
6603  DCHECK(IsAligned(reinterpret_cast<intptr_t>(dst), sizeof(uintptr_t)));
6604  // Only attempt processing one word at a time if src is also aligned.
6605  if (IsAligned(reinterpret_cast<intptr_t>(src), sizeof(uintptr_t))) {
6606    // Process the prefix of the input that requires no conversion one aligned
6607    // (machine) word at a time.
6608    while (src <= limit - sizeof(uintptr_t)) {
6609      const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6610      or_acc |= w;
6611      if (AsciiRangeMask(w, lo, hi) != 0) {
6612        changed = true;
6613        break;
6614      }
6615      *reinterpret_cast<uintptr_t*>(dst) = w;
6616      src += sizeof(uintptr_t);
6617      dst += sizeof(uintptr_t);
6618    }
6619    // Process the remainder of the input performing conversion when
6620    // required one word at a time.
6621    while (src <= limit - sizeof(uintptr_t)) {
6622      const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6623      or_acc |= w;
6624      uintptr_t m = AsciiRangeMask(w, lo, hi);
6625      // The mask has high (7th) bit set in every byte that needs
6626      // conversion and we know that the distance between cases is
6627      // 1 << 5.
6628      *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6629      src += sizeof(uintptr_t);
6630      dst += sizeof(uintptr_t);
6631    }
6632  }
6633  // Process the last few bytes of the input (or the whole input if
6634  // unaligned access is not supported).
6635  while (src < limit) {
6636    char c = *src;
6637    or_acc |= c;
6638    if (lo < c && c < hi) {
6639      c ^= (1 << 5);
6640      changed = true;
6641    }
6642    *dst = c;
6643    ++src;
6644    ++dst;
6645  }
6646
6647  if ((or_acc & kAsciiMask) != 0) return false;
6648
6649  DCHECK(CheckFastAsciiConvert(
6650             saved_dst, saved_src, length, changed, Converter::kIsToLower));
6651
6652  *changed_out = changed;
6653  return true;
6654}
6655
6656}  // namespace
6657
6658
6659template <class Converter>
6660MUST_USE_RESULT static Object* ConvertCase(
6661    Handle<String> s,
6662    Isolate* isolate,
6663    unibrow::Mapping<Converter, 128>* mapping) {
6664  s = String::Flatten(s);
6665  int length = s->length();
6666  // Assume that the string is not empty; we need this assumption later
6667  if (length == 0) return *s;
6668
6669  // Simpler handling of ASCII strings.
6670  //
6671  // NOTE: This assumes that the upper/lower case of an ASCII
6672  // character is also ASCII.  This is currently the case, but it
6673  // might break in the future if we implement more context and locale
6674  // dependent upper/lower conversions.
6675  if (s->IsOneByteRepresentationUnderneath()) {
6676    // Same length as input.
6677    Handle<SeqOneByteString> result =
6678        isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
6679    DisallowHeapAllocation no_gc;
6680    String::FlatContent flat_content = s->GetFlatContent();
6681    DCHECK(flat_content.IsFlat());
6682    bool has_changed_character = false;
6683    bool is_ascii = FastAsciiConvert<Converter>(
6684        reinterpret_cast<char*>(result->GetChars()),
6685        reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6686        length,
6687        &has_changed_character);
6688    // If not ASCII, we discard the result and take the 2 byte path.
6689    if (is_ascii) return has_changed_character ? *result : *s;
6690  }
6691
6692  Handle<SeqString> result;  // Same length as input.
6693  if (s->IsOneByteRepresentation()) {
6694    result = isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
6695  } else {
6696    result = isolate->factory()->NewRawTwoByteString(length).ToHandleChecked();
6697  }
6698
6699  Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6700  if (answer->IsException() || answer->IsString()) return answer;
6701
6702  DCHECK(answer->IsSmi());
6703  length = Smi::cast(answer)->value();
6704  if (s->IsOneByteRepresentation() && length > 0) {
6705    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6706        isolate, result, isolate->factory()->NewRawOneByteString(length));
6707  } else {
6708    if (length < 0) length = -length;
6709    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6710        isolate, result, isolate->factory()->NewRawTwoByteString(length));
6711  }
6712  return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6713}
6714
6715
6716RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
6717  HandleScope scope(isolate);
6718  DCHECK(args.length() == 1);
6719  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6720  return ConvertCase(
6721      s, isolate, isolate->runtime_state()->to_lower_mapping());
6722}
6723
6724
6725RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
6726  HandleScope scope(isolate);
6727  DCHECK(args.length() == 1);
6728  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6729  return ConvertCase(
6730      s, isolate, isolate->runtime_state()->to_upper_mapping());
6731}
6732
6733
6734RUNTIME_FUNCTION(Runtime_StringTrim) {
6735  HandleScope scope(isolate);
6736  DCHECK(args.length() == 3);
6737
6738  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6739  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6740  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6741
6742  string = String::Flatten(string);
6743  int length = string->length();
6744
6745  int left = 0;
6746  UnicodeCache* unicode_cache = isolate->unicode_cache();
6747  if (trimLeft) {
6748    while (left < length &&
6749           unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
6750      left++;
6751    }
6752  }
6753
6754  int right = length;
6755  if (trimRight) {
6756    while (right > left &&
6757           unicode_cache->IsWhiteSpaceOrLineTerminator(
6758               string->Get(right - 1))) {
6759      right--;
6760    }
6761  }
6762
6763  return *isolate->factory()->NewSubString(string, left, right);
6764}
6765
6766
6767RUNTIME_FUNCTION(Runtime_StringSplit) {
6768  HandleScope handle_scope(isolate);
6769  DCHECK(args.length() == 3);
6770  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6771  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6772  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6773  RUNTIME_ASSERT(limit > 0);
6774
6775  int subject_length = subject->length();
6776  int pattern_length = pattern->length();
6777  RUNTIME_ASSERT(pattern_length > 0);
6778
6779  if (limit == 0xffffffffu) {
6780    Handle<Object> cached_answer(
6781        RegExpResultsCache::Lookup(isolate->heap(),
6782                                   *subject,
6783                                   *pattern,
6784                                   RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6785        isolate);
6786    if (*cached_answer != Smi::FromInt(0)) {
6787      // The cache FixedArray is a COW-array and can therefore be reused.
6788      Handle<JSArray> result =
6789          isolate->factory()->NewJSArrayWithElements(
6790              Handle<FixedArray>::cast(cached_answer));
6791      return *result;
6792    }
6793  }
6794
6795  // The limit can be very large (0xffffffffu), but since the pattern
6796  // isn't empty, we can never create more parts than ~half the length
6797  // of the subject.
6798
6799  subject = String::Flatten(subject);
6800  pattern = String::Flatten(pattern);
6801
6802  static const int kMaxInitialListCapacity = 16;
6803
6804  ZoneScope zone_scope(isolate->runtime_zone());
6805
6806  // Find (up to limit) indices of separator and end-of-string in subject
6807  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6808  ZoneList<int> indices(initial_capacity, zone_scope.zone());
6809
6810  FindStringIndicesDispatch(isolate, *subject, *pattern,
6811                            &indices, limit, zone_scope.zone());
6812
6813  if (static_cast<uint32_t>(indices.length()) < limit) {
6814    indices.Add(subject_length, zone_scope.zone());
6815  }
6816
6817  // The list indices now contains the end of each part to create.
6818
6819  // Create JSArray of substrings separated by separator.
6820  int part_count = indices.length();
6821
6822  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6823  JSObject::EnsureCanContainHeapObjectElements(result);
6824  result->set_length(Smi::FromInt(part_count));
6825
6826  DCHECK(result->HasFastObjectElements());
6827
6828  if (part_count == 1 && indices.at(0) == subject_length) {
6829    FixedArray::cast(result->elements())->set(0, *subject);
6830    return *result;
6831  }
6832
6833  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6834  int part_start = 0;
6835  for (int i = 0; i < part_count; i++) {
6836    HandleScope local_loop_handle(isolate);
6837    int part_end = indices.at(i);
6838    Handle<String> substring =
6839        isolate->factory()->NewProperSubString(subject, part_start, part_end);
6840    elements->set(i, *substring);
6841    part_start = part_end + pattern_length;
6842  }
6843
6844  if (limit == 0xffffffffu) {
6845    if (result->HasFastObjectElements()) {
6846      RegExpResultsCache::Enter(isolate,
6847                                subject,
6848                                pattern,
6849                                elements,
6850                                RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6851    }
6852  }
6853
6854  return *result;
6855}
6856
6857
6858// Copies Latin1 characters to the given fixed array looking up
6859// one-char strings in the cache. Gives up on the first char that is
6860// not in the cache and fills the remainder with smi zeros. Returns
6861// the length of the successfully copied prefix.
6862static int CopyCachedOneByteCharsToArray(Heap* heap, const uint8_t* chars,
6863                                         FixedArray* elements, int length) {
6864  DisallowHeapAllocation no_gc;
6865  FixedArray* one_byte_cache = heap->single_character_string_cache();
6866  Object* undefined = heap->undefined_value();
6867  int i;
6868  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6869  for (i = 0; i < length; ++i) {
6870    Object* value = one_byte_cache->get(chars[i]);
6871    if (value == undefined) break;
6872    elements->set(i, value, mode);
6873  }
6874  if (i < length) {
6875    DCHECK(Smi::FromInt(0) == 0);
6876    memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6877  }
6878#ifdef DEBUG
6879  for (int j = 0; j < length; ++j) {
6880    Object* element = elements->get(j);
6881    DCHECK(element == Smi::FromInt(0) ||
6882           (element->IsString() && String::cast(element)->LooksValid()));
6883  }
6884#endif
6885  return i;
6886}
6887
6888
6889// Converts a String to JSArray.
6890// For example, "foo" => ["f", "o", "o"].
6891RUNTIME_FUNCTION(Runtime_StringToArray) {
6892  HandleScope scope(isolate);
6893  DCHECK(args.length() == 2);
6894  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6895  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6896
6897  s = String::Flatten(s);
6898  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6899
6900  Handle<FixedArray> elements;
6901  int position = 0;
6902  if (s->IsFlat() && s->IsOneByteRepresentation()) {
6903    // Try using cached chars where possible.
6904    elements = isolate->factory()->NewUninitializedFixedArray(length);
6905
6906    DisallowHeapAllocation no_gc;
6907    String::FlatContent content = s->GetFlatContent();
6908    if (content.IsOneByte()) {
6909      Vector<const uint8_t> chars = content.ToOneByteVector();
6910      // Note, this will initialize all elements (not only the prefix)
6911      // to prevent GC from seeing partially initialized array.
6912      position = CopyCachedOneByteCharsToArray(isolate->heap(), chars.start(),
6913                                               *elements, length);
6914    } else {
6915      MemsetPointer(elements->data_start(),
6916                    isolate->heap()->undefined_value(),
6917                    length);
6918    }
6919  } else {
6920    elements = isolate->factory()->NewFixedArray(length);
6921  }
6922  for (int i = position; i < length; ++i) {
6923    Handle<Object> str =
6924        isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i));
6925    elements->set(i, *str);
6926  }
6927
6928#ifdef DEBUG
6929  for (int i = 0; i < length; ++i) {
6930    DCHECK(String::cast(elements->get(i))->length() == 1);
6931  }
6932#endif
6933
6934  return *isolate->factory()->NewJSArrayWithElements(elements);
6935}
6936
6937
6938RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
6939  HandleScope scope(isolate);
6940  DCHECK(args.length() == 1);
6941  CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
6942  return *Object::ToObject(isolate, value).ToHandleChecked();
6943}
6944
6945
6946bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6947  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6948  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6949  return char_length == 0;
6950}
6951
6952
6953RUNTIME_FUNCTION(Runtime_NumberToStringRT) {
6954  HandleScope scope(isolate);
6955  DCHECK(args.length() == 1);
6956  CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
6957
6958  return *isolate->factory()->NumberToString(number);
6959}
6960
6961
6962RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
6963  HandleScope scope(isolate);
6964  DCHECK(args.length() == 1);
6965  CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
6966
6967  return *isolate->factory()->NumberToString(number, false);
6968}
6969
6970
6971RUNTIME_FUNCTION(Runtime_NumberToInteger) {
6972  HandleScope scope(isolate);
6973  DCHECK(args.length() == 1);
6974
6975  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6976  return *isolate->factory()->NewNumber(DoubleToInteger(number));
6977}
6978
6979
6980RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
6981  HandleScope scope(isolate);
6982  DCHECK(args.length() == 1);
6983
6984  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6985  double double_value = DoubleToInteger(number);
6986  // Map both -0 and +0 to +0.
6987  if (double_value == 0) double_value = 0;
6988
6989  return *isolate->factory()->NewNumber(double_value);
6990}
6991
6992
6993RUNTIME_FUNCTION(Runtime_NumberToJSUint32) {
6994  HandleScope scope(isolate);
6995  DCHECK(args.length() == 1);
6996
6997  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6998  return *isolate->factory()->NewNumberFromUint(number);
6999}
7000
7001
7002RUNTIME_FUNCTION(Runtime_NumberToJSInt32) {
7003  HandleScope scope(isolate);
7004  DCHECK(args.length() == 1);
7005
7006  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
7007  return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number));
7008}
7009
7010
7011// Converts a Number to a Smi, if possible. Returns NaN if the number is not
7012// a small integer.
7013RUNTIME_FUNCTION(Runtime_NumberToSmi) {
7014  SealHandleScope shs(isolate);
7015  DCHECK(args.length() == 1);
7016  CONVERT_ARG_CHECKED(Object, obj, 0);
7017  if (obj->IsSmi()) {
7018    return obj;
7019  }
7020  if (obj->IsHeapNumber()) {
7021    double value = HeapNumber::cast(obj)->value();
7022    int int_value = FastD2I(value);
7023    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
7024      return Smi::FromInt(int_value);
7025    }
7026  }
7027  return isolate->heap()->nan_value();
7028}
7029
7030
7031RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
7032  HandleScope scope(isolate);
7033  DCHECK(args.length() == 0);
7034  return *isolate->factory()->NewHeapNumber(0);
7035}
7036
7037
7038RUNTIME_FUNCTION(Runtime_NumberAdd) {
7039  HandleScope scope(isolate);
7040  DCHECK(args.length() == 2);
7041
7042  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7043  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7044  return *isolate->factory()->NewNumber(x + y);
7045}
7046
7047
7048RUNTIME_FUNCTION(Runtime_NumberSub) {
7049  HandleScope scope(isolate);
7050  DCHECK(args.length() == 2);
7051
7052  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7053  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7054  return *isolate->factory()->NewNumber(x - y);
7055}
7056
7057
7058RUNTIME_FUNCTION(Runtime_NumberMul) {
7059  HandleScope scope(isolate);
7060  DCHECK(args.length() == 2);
7061
7062  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7063  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7064  return *isolate->factory()->NewNumber(x * y);
7065}
7066
7067
7068RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
7069  HandleScope scope(isolate);
7070  DCHECK(args.length() == 1);
7071
7072  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7073  return *isolate->factory()->NewNumber(-x);
7074}
7075
7076
7077RUNTIME_FUNCTION(Runtime_NumberDiv) {
7078  HandleScope scope(isolate);
7079  DCHECK(args.length() == 2);
7080
7081  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7082  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7083  return *isolate->factory()->NewNumber(x / y);
7084}
7085
7086
7087RUNTIME_FUNCTION(Runtime_NumberMod) {
7088  HandleScope scope(isolate);
7089  DCHECK(args.length() == 2);
7090
7091  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7092  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7093  return *isolate->factory()->NewNumber(modulo(x, y));
7094}
7095
7096
7097RUNTIME_FUNCTION(Runtime_NumberImul) {
7098  HandleScope scope(isolate);
7099  DCHECK(args.length() == 2);
7100
7101  // We rely on implementation-defined behavior below, but at least not on
7102  // undefined behavior.
7103  CONVERT_NUMBER_CHECKED(uint32_t, x, Int32, args[0]);
7104  CONVERT_NUMBER_CHECKED(uint32_t, y, Int32, args[1]);
7105  int32_t product = static_cast<int32_t>(x * y);
7106  return *isolate->factory()->NewNumberFromInt(product);
7107}
7108
7109
7110RUNTIME_FUNCTION(Runtime_StringAdd) {
7111  HandleScope scope(isolate);
7112  DCHECK(args.length() == 2);
7113  CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
7114  CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
7115  isolate->counters()->string_add_runtime()->Increment();
7116  Handle<String> result;
7117  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7118      isolate, result, isolate->factory()->NewConsString(str1, str2));
7119  return *result;
7120}
7121
7122
7123template <typename sinkchar>
7124static inline void StringBuilderConcatHelper(String* special,
7125                                             sinkchar* sink,
7126                                             FixedArray* fixed_array,
7127                                             int array_length) {
7128  DisallowHeapAllocation no_gc;
7129  int position = 0;
7130  for (int i = 0; i < array_length; i++) {
7131    Object* element = fixed_array->get(i);
7132    if (element->IsSmi()) {
7133      // Smi encoding of position and length.
7134      int encoded_slice = Smi::cast(element)->value();
7135      int pos;
7136      int len;
7137      if (encoded_slice > 0) {
7138        // Position and length encoded in one smi.
7139        pos = StringBuilderSubstringPosition::decode(encoded_slice);
7140        len = StringBuilderSubstringLength::decode(encoded_slice);
7141      } else {
7142        // Position and length encoded in two smis.
7143        Object* obj = fixed_array->get(++i);
7144        DCHECK(obj->IsSmi());
7145        pos = Smi::cast(obj)->value();
7146        len = -encoded_slice;
7147      }
7148      String::WriteToFlat(special,
7149                          sink + position,
7150                          pos,
7151                          pos + len);
7152      position += len;
7153    } else {
7154      String* string = String::cast(element);
7155      int element_length = string->length();
7156      String::WriteToFlat(string, sink + position, 0, element_length);
7157      position += element_length;
7158    }
7159  }
7160}
7161
7162
7163// Returns the result length of the concatenation.
7164// On illegal argument, -1 is returned.
7165static inline int StringBuilderConcatLength(int special_length,
7166                                            FixedArray* fixed_array,
7167                                            int array_length,
7168                                            bool* one_byte) {
7169  DisallowHeapAllocation no_gc;
7170  int position = 0;
7171  for (int i = 0; i < array_length; i++) {
7172    int increment = 0;
7173    Object* elt = fixed_array->get(i);
7174    if (elt->IsSmi()) {
7175      // Smi encoding of position and length.
7176      int smi_value = Smi::cast(elt)->value();
7177      int pos;
7178      int len;
7179      if (smi_value > 0) {
7180        // Position and length encoded in one smi.
7181        pos = StringBuilderSubstringPosition::decode(smi_value);
7182        len = StringBuilderSubstringLength::decode(smi_value);
7183      } else {
7184        // Position and length encoded in two smis.
7185        len = -smi_value;
7186        // Get the position and check that it is a positive smi.
7187        i++;
7188        if (i >= array_length) return -1;
7189        Object* next_smi = fixed_array->get(i);
7190        if (!next_smi->IsSmi()) return -1;
7191        pos = Smi::cast(next_smi)->value();
7192        if (pos < 0) return -1;
7193      }
7194      DCHECK(pos >= 0);
7195      DCHECK(len >= 0);
7196      if (pos > special_length || len > special_length - pos) return -1;
7197      increment = len;
7198    } else if (elt->IsString()) {
7199      String* element = String::cast(elt);
7200      int element_length = element->length();
7201      increment = element_length;
7202      if (*one_byte && !element->HasOnlyOneByteChars()) {
7203        *one_byte = false;
7204      }
7205    } else {
7206      return -1;
7207    }
7208    if (increment > String::kMaxLength - position) {
7209      return kMaxInt;  // Provoke throw on allocation.
7210    }
7211    position += increment;
7212  }
7213  return position;
7214}
7215
7216
7217RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
7218  HandleScope scope(isolate);
7219  DCHECK(args.length() == 3);
7220  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7221  int32_t array_length;
7222  if (!args[1]->ToInt32(&array_length)) {
7223    THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
7224  }
7225  CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7226
7227  size_t actual_array_length = 0;
7228  RUNTIME_ASSERT(
7229      TryNumberToSize(isolate, array->length(), &actual_array_length));
7230  RUNTIME_ASSERT(array_length >= 0);
7231  RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length);
7232
7233  // This assumption is used by the slice encoding in one or two smis.
7234  DCHECK(Smi::kMaxValue >= String::kMaxLength);
7235
7236  RUNTIME_ASSERT(array->HasFastElements());
7237  JSObject::EnsureCanContainHeapObjectElements(array);
7238
7239  int special_length = special->length();
7240  if (!array->HasFastObjectElements()) {
7241    return isolate->Throw(isolate->heap()->illegal_argument_string());
7242  }
7243
7244  int length;
7245  bool one_byte = special->HasOnlyOneByteChars();
7246
7247  { DisallowHeapAllocation no_gc;
7248    FixedArray* fixed_array = FixedArray::cast(array->elements());
7249    if (fixed_array->length() < array_length) {
7250      array_length = fixed_array->length();
7251    }
7252
7253    if (array_length == 0) {
7254      return isolate->heap()->empty_string();
7255    } else if (array_length == 1) {
7256      Object* first = fixed_array->get(0);
7257      if (first->IsString()) return first;
7258    }
7259    length = StringBuilderConcatLength(
7260        special_length, fixed_array, array_length, &one_byte);
7261  }
7262
7263  if (length == -1) {
7264    return isolate->Throw(isolate->heap()->illegal_argument_string());
7265  }
7266
7267  if (one_byte) {
7268    Handle<SeqOneByteString> answer;
7269    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7270        isolate, answer,
7271        isolate->factory()->NewRawOneByteString(length));
7272    StringBuilderConcatHelper(*special,
7273                              answer->GetChars(),
7274                              FixedArray::cast(array->elements()),
7275                              array_length);
7276    return *answer;
7277  } else {
7278    Handle<SeqTwoByteString> answer;
7279    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7280        isolate, answer,
7281        isolate->factory()->NewRawTwoByteString(length));
7282    StringBuilderConcatHelper(*special,
7283                              answer->GetChars(),
7284                              FixedArray::cast(array->elements()),
7285                              array_length);
7286    return *answer;
7287  }
7288}
7289
7290
7291RUNTIME_FUNCTION(Runtime_StringBuilderJoin) {
7292  HandleScope scope(isolate);
7293  DCHECK(args.length() == 3);
7294  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7295  int32_t array_length;
7296  if (!args[1]->ToInt32(&array_length)) {
7297    THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
7298  }
7299  CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7300  RUNTIME_ASSERT(array->HasFastObjectElements());
7301  RUNTIME_ASSERT(array_length >= 0);
7302
7303  Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
7304  if (fixed_array->length() < array_length) {
7305    array_length = fixed_array->length();
7306  }
7307
7308  if (array_length == 0) {
7309    return isolate->heap()->empty_string();
7310  } else if (array_length == 1) {
7311    Object* first = fixed_array->get(0);
7312    RUNTIME_ASSERT(first->IsString());
7313    return first;
7314  }
7315
7316  int separator_length = separator->length();
7317  RUNTIME_ASSERT(separator_length > 0);
7318  int max_nof_separators =
7319      (String::kMaxLength + separator_length - 1) / separator_length;
7320  if (max_nof_separators < (array_length - 1)) {
7321    THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
7322  }
7323  int length = (array_length - 1) * separator_length;
7324  for (int i = 0; i < array_length; i++) {
7325    Object* element_obj = fixed_array->get(i);
7326    RUNTIME_ASSERT(element_obj->IsString());
7327    String* element = String::cast(element_obj);
7328    int increment = element->length();
7329    if (increment > String::kMaxLength - length) {
7330      STATIC_ASSERT(String::kMaxLength < kMaxInt);
7331      length = kMaxInt;  // Provoke exception;
7332      break;
7333    }
7334    length += increment;
7335  }
7336
7337  Handle<SeqTwoByteString> answer;
7338  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7339      isolate, answer,
7340      isolate->factory()->NewRawTwoByteString(length));
7341
7342  DisallowHeapAllocation no_gc;
7343
7344  uc16* sink = answer->GetChars();
7345#ifdef DEBUG
7346  uc16* end = sink + length;
7347#endif
7348
7349  RUNTIME_ASSERT(fixed_array->get(0)->IsString());
7350  String* first = String::cast(fixed_array->get(0));
7351  String* separator_raw = *separator;
7352  int first_length = first->length();
7353  String::WriteToFlat(first, sink, 0, first_length);
7354  sink += first_length;
7355
7356  for (int i = 1; i < array_length; i++) {
7357    DCHECK(sink + separator_length <= end);
7358    String::WriteToFlat(separator_raw, sink, 0, separator_length);
7359    sink += separator_length;
7360
7361    RUNTIME_ASSERT(fixed_array->get(i)->IsString());
7362    String* element = String::cast(fixed_array->get(i));
7363    int element_length = element->length();
7364    DCHECK(sink + element_length <= end);
7365    String::WriteToFlat(element, sink, 0, element_length);
7366    sink += element_length;
7367  }
7368  DCHECK(sink == end);
7369
7370  // Use %_FastOneByteArrayJoin instead.
7371  DCHECK(!answer->IsOneByteRepresentation());
7372  return *answer;
7373}
7374
7375template <typename Char>
7376static void JoinSparseArrayWithSeparator(FixedArray* elements,
7377                                         int elements_length,
7378                                         uint32_t array_length,
7379                                         String* separator,
7380                                         Vector<Char> buffer) {
7381  DisallowHeapAllocation no_gc;
7382  int previous_separator_position = 0;
7383  int separator_length = separator->length();
7384  int cursor = 0;
7385  for (int i = 0; i < elements_length; i += 2) {
7386    int position = NumberToInt32(elements->get(i));
7387    String* string = String::cast(elements->get(i + 1));
7388    int string_length = string->length();
7389    if (string->length() > 0) {
7390      while (previous_separator_position < position) {
7391        String::WriteToFlat<Char>(separator, &buffer[cursor],
7392                                  0, separator_length);
7393        cursor += separator_length;
7394        previous_separator_position++;
7395      }
7396      String::WriteToFlat<Char>(string, &buffer[cursor],
7397                                0, string_length);
7398      cursor += string->length();
7399    }
7400  }
7401  if (separator_length > 0) {
7402    // Array length must be representable as a signed 32-bit number,
7403    // otherwise the total string length would have been too large.
7404    DCHECK(array_length <= 0x7fffffff);  // Is int32_t.
7405    int last_array_index = static_cast<int>(array_length - 1);
7406    while (previous_separator_position < last_array_index) {
7407      String::WriteToFlat<Char>(separator, &buffer[cursor],
7408                                0, separator_length);
7409      cursor += separator_length;
7410      previous_separator_position++;
7411    }
7412  }
7413  DCHECK(cursor <= buffer.length());
7414}
7415
7416
7417RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
7418  HandleScope scope(isolate);
7419  DCHECK(args.length() == 3);
7420  CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0);
7421  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7422  CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7423  // elements_array is fast-mode JSarray of alternating positions
7424  // (increasing order) and strings.
7425  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7426  // array_length is length of original array (used to add separators);
7427  // separator is string to put between elements. Assumed to be non-empty.
7428  RUNTIME_ASSERT(array_length > 0);
7429
7430  // Find total length of join result.
7431  int string_length = 0;
7432  bool is_one_byte = separator->IsOneByteRepresentation();
7433  bool overflow = false;
7434  CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
7435  RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
7436  RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7437  FixedArray* elements = FixedArray::cast(elements_array->elements());
7438  for (int i = 0; i < elements_length; i += 2) {
7439    RUNTIME_ASSERT(elements->get(i)->IsNumber());
7440    CONVERT_NUMBER_CHECKED(uint32_t, position, Uint32, elements->get(i));
7441    RUNTIME_ASSERT(position < array_length);
7442    RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7443  }
7444
7445  { DisallowHeapAllocation no_gc;
7446    for (int i = 0; i < elements_length; i += 2) {
7447      String* string = String::cast(elements->get(i + 1));
7448      int length = string->length();
7449      if (is_one_byte && !string->IsOneByteRepresentation()) {
7450        is_one_byte = false;
7451      }
7452      if (length > String::kMaxLength ||
7453          String::kMaxLength - length < string_length) {
7454        overflow = true;
7455        break;
7456      }
7457      string_length += length;
7458    }
7459  }
7460
7461  int separator_length = separator->length();
7462  if (!overflow && separator_length > 0) {
7463    if (array_length <= 0x7fffffffu) {
7464      int separator_count = static_cast<int>(array_length) - 1;
7465      int remaining_length = String::kMaxLength - string_length;
7466      if ((remaining_length / separator_length) >= separator_count) {
7467        string_length += separator_length * (array_length - 1);
7468      } else {
7469        // Not room for the separators within the maximal string length.
7470        overflow = true;
7471      }
7472    } else {
7473      // Nonempty separator and at least 2^31-1 separators necessary
7474      // means that the string is too large to create.
7475      STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7476      overflow = true;
7477    }
7478  }
7479  if (overflow) {
7480    // Throw an exception if the resulting string is too large. See
7481    // https://code.google.com/p/chromium/issues/detail?id=336820
7482    // for details.
7483    THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
7484  }
7485
7486  if (is_one_byte) {
7487    Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString(
7488        string_length).ToHandleChecked();
7489    JoinSparseArrayWithSeparator<uint8_t>(
7490        FixedArray::cast(elements_array->elements()),
7491        elements_length,
7492        array_length,
7493        *separator,
7494        Vector<uint8_t>(result->GetChars(), string_length));
7495    return *result;
7496  } else {
7497    Handle<SeqTwoByteString> result = isolate->factory()->NewRawTwoByteString(
7498        string_length).ToHandleChecked();
7499    JoinSparseArrayWithSeparator<uc16>(
7500        FixedArray::cast(elements_array->elements()),
7501        elements_length,
7502        array_length,
7503        *separator,
7504        Vector<uc16>(result->GetChars(), string_length));
7505    return *result;
7506  }
7507}
7508
7509
7510RUNTIME_FUNCTION(Runtime_NumberOr) {
7511  HandleScope scope(isolate);
7512  DCHECK(args.length() == 2);
7513
7514  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7515  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7516  return *isolate->factory()->NewNumberFromInt(x | y);
7517}
7518
7519
7520RUNTIME_FUNCTION(Runtime_NumberAnd) {
7521  HandleScope scope(isolate);
7522  DCHECK(args.length() == 2);
7523
7524  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7525  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7526  return *isolate->factory()->NewNumberFromInt(x & y);
7527}
7528
7529
7530RUNTIME_FUNCTION(Runtime_NumberXor) {
7531  HandleScope scope(isolate);
7532  DCHECK(args.length() == 2);
7533
7534  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7535  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7536  return *isolate->factory()->NewNumberFromInt(x ^ y);
7537}
7538
7539
7540RUNTIME_FUNCTION(Runtime_NumberShl) {
7541  HandleScope scope(isolate);
7542  DCHECK(args.length() == 2);
7543
7544  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7545  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7546  return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
7547}
7548
7549
7550RUNTIME_FUNCTION(Runtime_NumberShr) {
7551  HandleScope scope(isolate);
7552  DCHECK(args.length() == 2);
7553
7554  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7555  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7556  return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
7557}
7558
7559
7560RUNTIME_FUNCTION(Runtime_NumberSar) {
7561  HandleScope scope(isolate);
7562  DCHECK(args.length() == 2);
7563
7564  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7565  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7566  return *isolate->factory()->NewNumberFromInt(
7567      ArithmeticShiftRight(x, y & 0x1f));
7568}
7569
7570
7571RUNTIME_FUNCTION(Runtime_NumberEquals) {
7572  SealHandleScope shs(isolate);
7573  DCHECK(args.length() == 2);
7574
7575  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7576  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7577  if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7578  if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7579  if (x == y) return Smi::FromInt(EQUAL);
7580  Object* result;
7581  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7582    result = Smi::FromInt(EQUAL);
7583  } else {
7584    result = Smi::FromInt(NOT_EQUAL);
7585  }
7586  return result;
7587}
7588
7589
7590RUNTIME_FUNCTION(Runtime_StringEquals) {
7591  HandleScope handle_scope(isolate);
7592  DCHECK(args.length() == 2);
7593
7594  CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
7595  CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
7596
7597  bool not_equal = !String::Equals(x, y);
7598  // This is slightly convoluted because the value that signifies
7599  // equality is 0 and inequality is 1 so we have to negate the result
7600  // from String::Equals.
7601  DCHECK(not_equal == 0 || not_equal == 1);
7602  STATIC_ASSERT(EQUAL == 0);
7603  STATIC_ASSERT(NOT_EQUAL == 1);
7604  return Smi::FromInt(not_equal);
7605}
7606
7607
7608RUNTIME_FUNCTION(Runtime_NumberCompare) {
7609  SealHandleScope shs(isolate);
7610  DCHECK(args.length() == 3);
7611
7612  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7613  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7614  CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
7615  if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
7616  if (x == y) return Smi::FromInt(EQUAL);
7617  if (isless(x, y)) return Smi::FromInt(LESS);
7618  return Smi::FromInt(GREATER);
7619}
7620
7621
7622// Compare two Smis as if they were converted to strings and then
7623// compared lexicographically.
7624RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
7625  SealHandleScope shs(isolate);
7626  DCHECK(args.length() == 2);
7627  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7628  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7629
7630  // If the integers are equal so are the string representations.
7631  if (x_value == y_value) return Smi::FromInt(EQUAL);
7632
7633  // If one of the integers is zero the normal integer order is the
7634  // same as the lexicographic order of the string representations.
7635  if (x_value == 0 || y_value == 0)
7636    return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7637
7638  // If only one of the integers is negative the negative number is
7639  // smallest because the char code of '-' is less than the char code
7640  // of any digit.  Otherwise, we make both values positive.
7641
7642  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7643  // architectures using 32-bit Smis.
7644  uint32_t x_scaled = x_value;
7645  uint32_t y_scaled = y_value;
7646  if (x_value < 0 || y_value < 0) {
7647    if (y_value >= 0) return Smi::FromInt(LESS);
7648    if (x_value >= 0) return Smi::FromInt(GREATER);
7649    x_scaled = -x_value;
7650    y_scaled = -y_value;
7651  }
7652
7653  static const uint32_t kPowersOf10[] = {
7654    1, 10, 100, 1000, 10*1000, 100*1000,
7655    1000*1000, 10*1000*1000, 100*1000*1000,
7656    1000*1000*1000
7657  };
7658
7659  // If the integers have the same number of decimal digits they can be
7660  // compared directly as the numeric order is the same as the
7661  // lexicographic order.  If one integer has fewer digits, it is scaled
7662  // by some power of 10 to have the same number of digits as the longer
7663  // integer.  If the scaled integers are equal it means the shorter
7664  // integer comes first in the lexicographic order.
7665
7666  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7667  int x_log2 = IntegerLog2(x_scaled);
7668  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7669  x_log10 -= x_scaled < kPowersOf10[x_log10];
7670
7671  int y_log2 = IntegerLog2(y_scaled);
7672  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7673  y_log10 -= y_scaled < kPowersOf10[y_log10];
7674
7675  int tie = EQUAL;
7676
7677  if (x_log10 < y_log10) {
7678    // X has fewer digits.  We would like to simply scale up X but that
7679    // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7680    // be scaled up to 9_000_000_000. So we scale up by the next
7681    // smallest power and scale down Y to drop one digit. It is OK to
7682    // drop one digit from the longer integer since the final digit is
7683    // past the length of the shorter integer.
7684    x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7685    y_scaled /= 10;
7686    tie = LESS;
7687  } else if (y_log10 < x_log10) {
7688    y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7689    x_scaled /= 10;
7690    tie = GREATER;
7691  }
7692
7693  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7694  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7695  return Smi::FromInt(tie);
7696}
7697
7698
7699RUNTIME_FUNCTION(Runtime_StringCompare) {
7700  HandleScope handle_scope(isolate);
7701  DCHECK(args.length() == 2);
7702
7703  CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
7704  CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
7705
7706  isolate->counters()->string_compare_runtime()->Increment();
7707
7708  // A few fast case tests before we flatten.
7709  if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
7710  if (y->length() == 0) {
7711    if (x->length() == 0) return Smi::FromInt(EQUAL);
7712    return Smi::FromInt(GREATER);
7713  } else if (x->length() == 0) {
7714    return Smi::FromInt(LESS);
7715  }
7716
7717  int d = x->Get(0) - y->Get(0);
7718  if (d < 0) return Smi::FromInt(LESS);
7719  else if (d > 0) return Smi::FromInt(GREATER);
7720
7721  // Slow case.
7722  x = String::Flatten(x);
7723  y = String::Flatten(y);
7724
7725  DisallowHeapAllocation no_gc;
7726  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7727  int prefix_length = x->length();
7728  if (y->length() < prefix_length) {
7729    prefix_length = y->length();
7730    equal_prefix_result = Smi::FromInt(GREATER);
7731  } else if (y->length() > prefix_length) {
7732    equal_prefix_result = Smi::FromInt(LESS);
7733  }
7734  int r;
7735  String::FlatContent x_content = x->GetFlatContent();
7736  String::FlatContent y_content = y->GetFlatContent();
7737  if (x_content.IsOneByte()) {
7738    Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7739    if (y_content.IsOneByte()) {
7740      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7741      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7742    } else {
7743      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7744      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7745    }
7746  } else {
7747    Vector<const uc16> x_chars = x_content.ToUC16Vector();
7748    if (y_content.IsOneByte()) {
7749      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7750      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7751    } else {
7752      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7753      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7754    }
7755  }
7756  Object* result;
7757  if (r == 0) {
7758    result = equal_prefix_result;
7759  } else {
7760    result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7761  }
7762  return result;
7763}
7764
7765
7766#define RUNTIME_UNARY_MATH(Name, name)                                         \
7767RUNTIME_FUNCTION(Runtime_Math##Name) {                           \
7768  HandleScope scope(isolate);                                                  \
7769  DCHECK(args.length() == 1);                                                  \
7770  isolate->counters()->math_##name()->Increment();                             \
7771  CONVERT_DOUBLE_ARG_CHECKED(x, 0);                                            \
7772  return *isolate->factory()->NewHeapNumber(std::name(x));                     \
7773}
7774
7775RUNTIME_UNARY_MATH(Acos, acos)
7776RUNTIME_UNARY_MATH(Asin, asin)
7777RUNTIME_UNARY_MATH(Atan, atan)
7778RUNTIME_UNARY_MATH(LogRT, log)
7779#undef RUNTIME_UNARY_MATH
7780
7781
7782RUNTIME_FUNCTION(Runtime_DoubleHi) {
7783  HandleScope scope(isolate);
7784  DCHECK(args.length() == 1);
7785  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7786  uint64_t integer = double_to_uint64(x);
7787  integer = (integer >> 32) & 0xFFFFFFFFu;
7788  return *isolate->factory()->NewNumber(static_cast<int32_t>(integer));
7789}
7790
7791
7792RUNTIME_FUNCTION(Runtime_DoubleLo) {
7793  HandleScope scope(isolate);
7794  DCHECK(args.length() == 1);
7795  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7796  return *isolate->factory()->NewNumber(
7797      static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
7798}
7799
7800
7801RUNTIME_FUNCTION(Runtime_ConstructDouble) {
7802  HandleScope scope(isolate);
7803  DCHECK(args.length() == 2);
7804  CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
7805  CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
7806  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
7807  return *isolate->factory()->NewNumber(uint64_to_double(result));
7808}
7809
7810
7811RUNTIME_FUNCTION(Runtime_RemPiO2) {
7812  HandleScope handle_scope(isolate);
7813  DCHECK(args.length() == 1);
7814  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7815  Factory* factory = isolate->factory();
7816  double y[2] = {0.0, 0.0};
7817  int n = fdlibm::rempio2(x, y);
7818  Handle<FixedArray> array = factory->NewFixedArray(3);
7819  Handle<HeapNumber> y0 = factory->NewHeapNumber(y[0]);
7820  Handle<HeapNumber> y1 = factory->NewHeapNumber(y[1]);
7821  array->set(0, Smi::FromInt(n));
7822  array->set(1, *y0);
7823  array->set(2, *y1);
7824  return *factory->NewJSArrayWithElements(array);
7825}
7826
7827
7828static const double kPiDividedBy4 = 0.78539816339744830962;
7829
7830
7831RUNTIME_FUNCTION(Runtime_MathAtan2) {
7832  HandleScope scope(isolate);
7833  DCHECK(args.length() == 2);
7834  isolate->counters()->math_atan2()->Increment();
7835
7836  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7837  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7838  double result;
7839  if (std::isinf(x) && std::isinf(y)) {
7840    // Make sure that the result in case of two infinite arguments
7841    // is a multiple of Pi / 4. The sign of the result is determined
7842    // by the first argument (x) and the sign of the second argument
7843    // determines the multiplier: one or three.
7844    int multiplier = (x < 0) ? -1 : 1;
7845    if (y < 0) multiplier *= 3;
7846    result = multiplier * kPiDividedBy4;
7847  } else {
7848    result = std::atan2(x, y);
7849  }
7850  return *isolate->factory()->NewNumber(result);
7851}
7852
7853
7854RUNTIME_FUNCTION(Runtime_MathExpRT) {
7855  HandleScope scope(isolate);
7856  DCHECK(args.length() == 1);
7857  isolate->counters()->math_exp()->Increment();
7858
7859  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7860  lazily_initialize_fast_exp();
7861  return *isolate->factory()->NewNumber(fast_exp(x));
7862}
7863
7864
7865RUNTIME_FUNCTION(Runtime_MathFloorRT) {
7866  HandleScope scope(isolate);
7867  DCHECK(args.length() == 1);
7868  isolate->counters()->math_floor()->Increment();
7869
7870  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7871  return *isolate->factory()->NewNumber(Floor(x));
7872}
7873
7874
7875// Slow version of Math.pow.  We check for fast paths for special cases.
7876// Used if VFP3 is not available.
7877RUNTIME_FUNCTION(Runtime_MathPowSlow) {
7878  HandleScope scope(isolate);
7879  DCHECK(args.length() == 2);
7880  isolate->counters()->math_pow()->Increment();
7881
7882  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7883
7884  // If the second argument is a smi, it is much faster to call the
7885  // custom powi() function than the generic pow().
7886  if (args[1]->IsSmi()) {
7887    int y = args.smi_at(1);
7888    return *isolate->factory()->NewNumber(power_double_int(x, y));
7889  }
7890
7891  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7892  double result = power_helper(x, y);
7893  if (std::isnan(result)) return isolate->heap()->nan_value();
7894  return *isolate->factory()->NewNumber(result);
7895}
7896
7897
7898// Fast version of Math.pow if we know that y is not an integer and y is not
7899// -0.5 or 0.5.  Used as slow case from full codegen.
7900RUNTIME_FUNCTION(Runtime_MathPowRT) {
7901  HandleScope scope(isolate);
7902  DCHECK(args.length() == 2);
7903  isolate->counters()->math_pow()->Increment();
7904
7905  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7906  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7907  if (y == 0) {
7908    return Smi::FromInt(1);
7909  } else {
7910    double result = power_double_double(x, y);
7911    if (std::isnan(result)) return isolate->heap()->nan_value();
7912    return *isolate->factory()->NewNumber(result);
7913  }
7914}
7915
7916
7917RUNTIME_FUNCTION(Runtime_RoundNumber) {
7918  HandleScope scope(isolate);
7919  DCHECK(args.length() == 1);
7920  CONVERT_NUMBER_ARG_HANDLE_CHECKED(input, 0);
7921  isolate->counters()->math_round()->Increment();
7922
7923  if (!input->IsHeapNumber()) {
7924    DCHECK(input->IsSmi());
7925    return *input;
7926  }
7927
7928  Handle<HeapNumber> number = Handle<HeapNumber>::cast(input);
7929
7930  double value = number->value();
7931  int exponent = number->get_exponent();
7932  int sign = number->get_sign();
7933
7934  if (exponent < -1) {
7935    // Number in range ]-0.5..0.5[. These always round to +/-zero.
7936    if (sign) return isolate->heap()->minus_zero_value();
7937    return Smi::FromInt(0);
7938  }
7939
7940  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7941  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7942  // argument holds for 32-bit smis).
7943  if (!sign && exponent < kSmiValueSize - 2) {
7944    return Smi::FromInt(static_cast<int>(value + 0.5));
7945  }
7946
7947  // If the magnitude is big enough, there's no place for fraction part. If we
7948  // try to add 0.5 to this number, 1.0 will be added instead.
7949  if (exponent >= 52) {
7950    return *number;
7951  }
7952
7953  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7954
7955  // Do not call NumberFromDouble() to avoid extra checks.
7956  return *isolate->factory()->NewNumber(Floor(value + 0.5));
7957}
7958
7959
7960RUNTIME_FUNCTION(Runtime_MathSqrtRT) {
7961  HandleScope scope(isolate);
7962  DCHECK(args.length() == 1);
7963  isolate->counters()->math_sqrt()->Increment();
7964
7965  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7966  return *isolate->factory()->NewNumber(fast_sqrt(x));
7967}
7968
7969
7970RUNTIME_FUNCTION(Runtime_MathFround) {
7971  HandleScope scope(isolate);
7972  DCHECK(args.length() == 1);
7973
7974  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7975  float xf = DoubleToFloat32(x);
7976  return *isolate->factory()->NewNumber(xf);
7977}
7978
7979
7980RUNTIME_FUNCTION(Runtime_DateMakeDay) {
7981  SealHandleScope shs(isolate);
7982  DCHECK(args.length() == 2);
7983
7984  CONVERT_SMI_ARG_CHECKED(year, 0);
7985  CONVERT_SMI_ARG_CHECKED(month, 1);
7986
7987  int days = isolate->date_cache()->DaysFromYearMonth(year, month);
7988  RUNTIME_ASSERT(Smi::IsValid(days));
7989  return Smi::FromInt(days);
7990}
7991
7992
7993RUNTIME_FUNCTION(Runtime_DateSetValue) {
7994  HandleScope scope(isolate);
7995  DCHECK(args.length() == 3);
7996
7997  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7998  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7999  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
8000
8001  DateCache* date_cache = isolate->date_cache();
8002
8003  Handle<Object> value;;
8004  bool is_value_nan = false;
8005  if (std::isnan(time)) {
8006    value = isolate->factory()->nan_value();
8007    is_value_nan = true;
8008  } else if (!is_utc &&
8009             (time < -DateCache::kMaxTimeBeforeUTCInMs ||
8010              time > DateCache::kMaxTimeBeforeUTCInMs)) {
8011    value = isolate->factory()->nan_value();
8012    is_value_nan = true;
8013  } else {
8014    time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
8015    if (time < -DateCache::kMaxTimeInMs ||
8016        time > DateCache::kMaxTimeInMs) {
8017      value = isolate->factory()->nan_value();
8018      is_value_nan = true;
8019    } else  {
8020      value = isolate->factory()->NewNumber(DoubleToInteger(time));
8021    }
8022  }
8023  date->SetValue(*value, is_value_nan);
8024  return *value;
8025}
8026
8027
8028static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
8029                                           Handle<JSFunction> callee,
8030                                           Object** parameters,
8031                                           int argument_count) {
8032  Handle<JSObject> result =
8033      isolate->factory()->NewArgumentsObject(callee, argument_count);
8034
8035  // Allocate the elements if needed.
8036  int parameter_count = callee->shared()->formal_parameter_count();
8037  if (argument_count > 0) {
8038    if (parameter_count > 0) {
8039      int mapped_count = Min(argument_count, parameter_count);
8040      Handle<FixedArray> parameter_map =
8041          isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
8042      parameter_map->set_map(
8043          isolate->heap()->sloppy_arguments_elements_map());
8044
8045      Handle<Map> map = Map::Copy(handle(result->map()));
8046      map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
8047
8048      result->set_map(*map);
8049      result->set_elements(*parameter_map);
8050
8051      // Store the context and the arguments array at the beginning of the
8052      // parameter map.
8053      Handle<Context> context(isolate->context());
8054      Handle<FixedArray> arguments =
8055          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8056      parameter_map->set(0, *context);
8057      parameter_map->set(1, *arguments);
8058
8059      // Loop over the actual parameters backwards.
8060      int index = argument_count - 1;
8061      while (index >= mapped_count) {
8062        // These go directly in the arguments array and have no
8063        // corresponding slot in the parameter map.
8064        arguments->set(index, *(parameters - index - 1));
8065        --index;
8066      }
8067
8068      Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
8069      while (index >= 0) {
8070        // Detect duplicate names to the right in the parameter list.
8071        Handle<String> name(scope_info->ParameterName(index));
8072        int context_local_count = scope_info->ContextLocalCount();
8073        bool duplicate = false;
8074        for (int j = index + 1; j < parameter_count; ++j) {
8075          if (scope_info->ParameterName(j) == *name) {
8076            duplicate = true;
8077            break;
8078          }
8079        }
8080
8081        if (duplicate) {
8082          // This goes directly in the arguments array with a hole in the
8083          // parameter map.
8084          arguments->set(index, *(parameters - index - 1));
8085          parameter_map->set_the_hole(index + 2);
8086        } else {
8087          // The context index goes in the parameter map with a hole in the
8088          // arguments array.
8089          int context_index = -1;
8090          for (int j = 0; j < context_local_count; ++j) {
8091            if (scope_info->ContextLocalName(j) == *name) {
8092              context_index = j;
8093              break;
8094            }
8095          }
8096          DCHECK(context_index >= 0);
8097          arguments->set_the_hole(index);
8098          parameter_map->set(index + 2, Smi::FromInt(
8099              Context::MIN_CONTEXT_SLOTS + context_index));
8100        }
8101
8102        --index;
8103      }
8104    } else {
8105      // If there is no aliasing, the arguments object elements are not
8106      // special in any way.
8107      Handle<FixedArray> elements =
8108          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8109      result->set_elements(*elements);
8110      for (int i = 0; i < argument_count; ++i) {
8111        elements->set(i, *(parameters - i - 1));
8112      }
8113    }
8114  }
8115  return result;
8116}
8117
8118
8119static Handle<JSObject> NewStrictArguments(Isolate* isolate,
8120                                           Handle<JSFunction> callee,
8121                                           Object** parameters,
8122                                           int argument_count) {
8123  Handle<JSObject> result =
8124      isolate->factory()->NewArgumentsObject(callee, argument_count);
8125
8126  if (argument_count > 0) {
8127    Handle<FixedArray> array =
8128        isolate->factory()->NewUninitializedFixedArray(argument_count);
8129    DisallowHeapAllocation no_gc;
8130    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8131    for (int i = 0; i < argument_count; i++) {
8132      array->set(i, *--parameters, mode);
8133    }
8134    result->set_elements(*array);
8135  }
8136  return result;
8137}
8138
8139
8140RUNTIME_FUNCTION(Runtime_NewArguments) {
8141  HandleScope scope(isolate);
8142  DCHECK(args.length() == 1);
8143  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
8144  JavaScriptFrameIterator it(isolate);
8145
8146  // Find the frame that holds the actual arguments passed to the function.
8147  it.AdvanceToArgumentsFrame();
8148  JavaScriptFrame* frame = it.frame();
8149
8150  // Determine parameter location on the stack and dispatch on language mode.
8151  int argument_count = frame->GetArgumentsLength();
8152  Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
8153  return callee->shared()->strict_mode() == STRICT
8154             ? *NewStrictArguments(isolate, callee, parameters, argument_count)
8155             : *NewSloppyArguments(isolate, callee, parameters, argument_count);
8156}
8157
8158
8159RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
8160  HandleScope scope(isolate);
8161  DCHECK(args.length() == 3);
8162  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
8163  Object** parameters = reinterpret_cast<Object**>(args[1]);
8164  CONVERT_SMI_ARG_CHECKED(argument_count, 2);
8165  return *NewSloppyArguments(isolate, callee, parameters, argument_count);
8166}
8167
8168
8169RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
8170  HandleScope scope(isolate);
8171  DCHECK(args.length() == 3);
8172  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
8173  Object** parameters = reinterpret_cast<Object**>(args[1]);
8174  CONVERT_SMI_ARG_CHECKED(argument_count, 2);
8175  return *NewStrictArguments(isolate, callee, parameters, argument_count);
8176}
8177
8178
8179RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
8180  HandleScope scope(isolate);
8181  DCHECK(args.length() == 1);
8182  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
8183  Handle<Context> context(isolate->context());
8184  PretenureFlag pretenure_flag = NOT_TENURED;
8185  return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
8186                                                                pretenure_flag);
8187}
8188
8189
8190RUNTIME_FUNCTION(Runtime_NewClosure) {
8191  HandleScope scope(isolate);
8192  DCHECK(args.length() == 3);
8193  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8194  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
8195  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8196
8197  // The caller ensures that we pretenure closures that are assigned
8198  // directly to properties.
8199  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8200  return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
8201      shared, context, pretenure_flag);
8202}
8203
8204
8205// Find the arguments of the JavaScript function invocation that called
8206// into C++ code. Collect these in a newly allocated array of handles (possibly
8207// prefixed by a number of empty handles).
8208static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8209    Isolate* isolate,
8210    int prefix_argc,
8211    int* total_argc) {
8212  // Find frame containing arguments passed to the caller.
8213  JavaScriptFrameIterator it(isolate);
8214  JavaScriptFrame* frame = it.frame();
8215  List<JSFunction*> functions(2);
8216  frame->GetFunctions(&functions);
8217  if (functions.length() > 1) {
8218    int inlined_jsframe_index = functions.length() - 1;
8219    JSFunction* inlined_function = functions[inlined_jsframe_index];
8220    SlotRefValueBuilder slot_refs(
8221        frame,
8222        inlined_jsframe_index,
8223        inlined_function->shared()->formal_parameter_count());
8224
8225    int args_count = slot_refs.args_length();
8226
8227    *total_argc = prefix_argc + args_count;
8228    SmartArrayPointer<Handle<Object> > param_data(
8229        NewArray<Handle<Object> >(*total_argc));
8230    slot_refs.Prepare(isolate);
8231    for (int i = 0; i < args_count; i++) {
8232      Handle<Object> val = slot_refs.GetNext(isolate, 0);
8233      param_data[prefix_argc + i] = val;
8234    }
8235    slot_refs.Finish(isolate);
8236
8237    return param_data;
8238  } else {
8239    it.AdvanceToArgumentsFrame();
8240    frame = it.frame();
8241    int args_count = frame->ComputeParametersCount();
8242
8243    *total_argc = prefix_argc + args_count;
8244    SmartArrayPointer<Handle<Object> > param_data(
8245        NewArray<Handle<Object> >(*total_argc));
8246    for (int i = 0; i < args_count; i++) {
8247      Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8248      param_data[prefix_argc + i] = val;
8249    }
8250    return param_data;
8251  }
8252}
8253
8254
8255RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
8256  HandleScope scope(isolate);
8257  DCHECK(args.length() == 4);
8258  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8259  CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1);
8260  CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
8261  CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
8262
8263  // TODO(lrn): Create bound function in C++ code from premade shared info.
8264  bound_function->shared()->set_bound(true);
8265  // Get all arguments of calling function (Function.prototype.bind).
8266  int argc = 0;
8267  SmartArrayPointer<Handle<Object> > arguments =
8268      GetCallerArguments(isolate, 0, &argc);
8269  // Don't count the this-arg.
8270  if (argc > 0) {
8271    RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
8272    argc--;
8273  } else {
8274    RUNTIME_ASSERT(this_object->IsUndefined());
8275  }
8276  // Initialize array of bindings (function, this, and any existing arguments
8277  // if the function was already bound).
8278  Handle<FixedArray> new_bindings;
8279  int i;
8280  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8281    Handle<FixedArray> old_bindings(
8282        JSFunction::cast(*bindee)->function_bindings());
8283    RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex);
8284    new_bindings =
8285        isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8286    bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8287                            isolate);
8288    i = 0;
8289    for (int n = old_bindings->length(); i < n; i++) {
8290      new_bindings->set(i, old_bindings->get(i));
8291    }
8292  } else {
8293    int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8294    new_bindings = isolate->factory()->NewFixedArray(array_size);
8295    new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8296    new_bindings->set(JSFunction::kBoundThisIndex, *this_object);
8297    i = 2;
8298  }
8299  // Copy arguments, skipping the first which is "this_arg".
8300  for (int j = 0; j < argc; j++, i++) {
8301    new_bindings->set(i, *arguments[j + 1]);
8302  }
8303  new_bindings->set_map_no_write_barrier(
8304      isolate->heap()->fixed_cow_array_map());
8305  bound_function->set_function_bindings(*new_bindings);
8306
8307  // Update length. Have to remove the prototype first so that map migration
8308  // is happy about the number of fields.
8309  RUNTIME_ASSERT(bound_function->RemovePrototype());
8310  Handle<Map> bound_function_map(
8311      isolate->native_context()->bound_function_map());
8312  JSObject::MigrateToMap(bound_function, bound_function_map);
8313  Handle<String> length_string = isolate->factory()->length_string();
8314  PropertyAttributes attr =
8315      static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8316  RETURN_FAILURE_ON_EXCEPTION(
8317      isolate,
8318      JSObject::SetOwnPropertyIgnoreAttributes(
8319          bound_function, length_string, new_length, attr));
8320  return *bound_function;
8321}
8322
8323
8324RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
8325  HandleScope handles(isolate);
8326  DCHECK(args.length() == 1);
8327  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8328  if (callable->IsJSFunction()) {
8329    Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8330    if (function->shared()->bound()) {
8331      Handle<FixedArray> bindings(function->function_bindings());
8332      RUNTIME_ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8333      return *isolate->factory()->NewJSArrayWithElements(bindings);
8334    }
8335  }
8336  return isolate->heap()->undefined_value();
8337}
8338
8339
8340RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
8341  HandleScope scope(isolate);
8342  DCHECK(args.length() == 1);
8343  // First argument is a function to use as a constructor.
8344  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8345  RUNTIME_ASSERT(function->shared()->bound());
8346
8347  // The argument is a bound function. Extract its bound arguments
8348  // and callable.
8349  Handle<FixedArray> bound_args =
8350      Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8351  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8352  Handle<Object> bound_function(
8353      JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8354      isolate);
8355  DCHECK(!bound_function->IsJSFunction() ||
8356         !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8357
8358  int total_argc = 0;
8359  SmartArrayPointer<Handle<Object> > param_data =
8360      GetCallerArguments(isolate, bound_argc, &total_argc);
8361  for (int i = 0; i < bound_argc; i++) {
8362    param_data[i] = Handle<Object>(bound_args->get(
8363        JSFunction::kBoundArgumentsStartIndex + i), isolate);
8364  }
8365
8366  if (!bound_function->IsJSFunction()) {
8367    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8368        isolate, bound_function,
8369        Execution::TryGetConstructorDelegate(isolate, bound_function));
8370  }
8371  DCHECK(bound_function->IsJSFunction());
8372
8373  Handle<Object> result;
8374  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8375      isolate, result,
8376      Execution::New(Handle<JSFunction>::cast(bound_function),
8377                     total_argc, param_data.get()));
8378  return *result;
8379}
8380
8381
8382static Object* Runtime_NewObjectHelper(Isolate* isolate,
8383                                            Handle<Object> constructor,
8384                                            Handle<AllocationSite> site) {
8385  // If the constructor isn't a proper function we throw a type error.
8386  if (!constructor->IsJSFunction()) {
8387    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8388    THROW_NEW_ERROR_RETURN_FAILURE(isolate,
8389                                   NewTypeError("not_constructor", arguments));
8390  }
8391
8392  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8393
8394  // If function should not have prototype, construction is not allowed. In this
8395  // case generated code bailouts here, since function has no initial_map.
8396  if (!function->should_have_prototype() && !function->shared()->bound()) {
8397    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8398    THROW_NEW_ERROR_RETURN_FAILURE(isolate,
8399                                   NewTypeError("not_constructor", arguments));
8400  }
8401
8402  Debug* debug = isolate->debug();
8403  // Handle stepping into constructors if step into is active.
8404  if (debug->StepInActive()) {
8405    debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8406  }
8407
8408  if (function->has_initial_map()) {
8409    if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8410      // The 'Function' function ignores the receiver object when
8411      // called using 'new' and creates a new JSFunction object that
8412      // is returned.  The receiver object is only used for error
8413      // reporting if an error occurs when constructing the new
8414      // JSFunction. Factory::NewJSObject() should not be used to
8415      // allocate JSFunctions since it does not properly initialize
8416      // the shared part of the function. Since the receiver is
8417      // ignored anyway, we use the global object as the receiver
8418      // instead of a new JSFunction object. This way, errors are
8419      // reported the same way whether or not 'Function' is called
8420      // using 'new'.
8421      return isolate->global_proxy();
8422    }
8423  }
8424
8425  // The function should be compiled for the optimization hints to be
8426  // available.
8427  Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
8428
8429  Handle<JSObject> result;
8430  if (site.is_null()) {
8431    result = isolate->factory()->NewJSObject(function);
8432  } else {
8433    result = isolate->factory()->NewJSObjectWithMemento(function, site);
8434  }
8435
8436  isolate->counters()->constructed_objects()->Increment();
8437  isolate->counters()->constructed_objects_runtime()->Increment();
8438
8439  return *result;
8440}
8441
8442
8443RUNTIME_FUNCTION(Runtime_NewObject) {
8444  HandleScope scope(isolate);
8445  DCHECK(args.length() == 1);
8446  CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
8447  return Runtime_NewObjectHelper(isolate,
8448                                 constructor,
8449                                 Handle<AllocationSite>::null());
8450}
8451
8452
8453RUNTIME_FUNCTION(Runtime_NewObjectWithAllocationSite) {
8454  HandleScope scope(isolate);
8455  DCHECK(args.length() == 2);
8456  CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
8457  CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
8458  Handle<AllocationSite> site;
8459  if (feedback->IsAllocationSite()) {
8460    // The feedback can be an AllocationSite or undefined.
8461    site = Handle<AllocationSite>::cast(feedback);
8462  }
8463  return Runtime_NewObjectHelper(isolate, constructor, site);
8464}
8465
8466
8467RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
8468  HandleScope scope(isolate);
8469  DCHECK(args.length() == 1);
8470
8471  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8472  function->CompleteInobjectSlackTracking();
8473
8474  return isolate->heap()->undefined_value();
8475}
8476
8477
8478RUNTIME_FUNCTION(Runtime_CompileLazy) {
8479  HandleScope scope(isolate);
8480  DCHECK(args.length() == 1);
8481  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8482#ifdef DEBUG
8483  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8484    PrintF("[unoptimized: ");
8485    function->PrintName();
8486    PrintF("]\n");
8487  }
8488#endif
8489
8490  // Compile the target function.
8491  DCHECK(function->shared()->allows_lazy_compilation());
8492
8493  Handle<Code> code;
8494  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
8495                                     Compiler::GetLazyCode(function));
8496  DCHECK(code->kind() == Code::FUNCTION ||
8497         code->kind() == Code::OPTIMIZED_FUNCTION);
8498  function->ReplaceCode(*code);
8499  return *code;
8500}
8501
8502
8503RUNTIME_FUNCTION(Runtime_CompileOptimized) {
8504  HandleScope scope(isolate);
8505  DCHECK(args.length() == 2);
8506  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8507  CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
8508
8509  Handle<Code> unoptimized(function->shared()->code());
8510  if (!isolate->use_crankshaft() ||
8511      function->shared()->optimization_disabled() ||
8512      isolate->DebuggerHasBreakPoints()) {
8513    // If the function is not optimizable or debugger is active continue
8514    // using the code from the full compiler.
8515    if (FLAG_trace_opt) {
8516      PrintF("[failed to optimize ");
8517      function->PrintName();
8518      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8519          function->shared()->optimization_disabled() ? "F" : "T",
8520          isolate->DebuggerHasBreakPoints() ? "T" : "F");
8521    }
8522    function->ReplaceCode(*unoptimized);
8523    return function->code();
8524  }
8525
8526  Compiler::ConcurrencyMode mode =
8527      concurrent ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
8528  Handle<Code> code;
8529  if (Compiler::GetOptimizedCode(function, unoptimized, mode).ToHandle(&code)) {
8530    function->ReplaceCode(*code);
8531  } else {
8532    function->ReplaceCode(function->shared()->code());
8533  }
8534
8535  DCHECK(function->code()->kind() == Code::FUNCTION ||
8536         function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
8537         function->IsInOptimizationQueue());
8538  return function->code();
8539}
8540
8541
8542class ActivationsFinder : public ThreadVisitor {
8543 public:
8544  Code* code_;
8545  bool has_code_activations_;
8546
8547  explicit ActivationsFinder(Code* code)
8548    : code_(code),
8549      has_code_activations_(false) { }
8550
8551  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8552    JavaScriptFrameIterator it(isolate, top);
8553    VisitFrames(&it);
8554  }
8555
8556  void VisitFrames(JavaScriptFrameIterator* it) {
8557    for (; !it->done(); it->Advance()) {
8558      JavaScriptFrame* frame = it->frame();
8559      if (code_->contains(frame->pc())) has_code_activations_ = true;
8560    }
8561  }
8562};
8563
8564
8565RUNTIME_FUNCTION(Runtime_NotifyStubFailure) {
8566  HandleScope scope(isolate);
8567  DCHECK(args.length() == 0);
8568  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8569  DCHECK(AllowHeapAllocation::IsAllowed());
8570  delete deoptimizer;
8571  return isolate->heap()->undefined_value();
8572}
8573
8574
8575RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
8576  HandleScope scope(isolate);
8577  DCHECK(args.length() == 1);
8578  CONVERT_SMI_ARG_CHECKED(type_arg, 0);
8579  Deoptimizer::BailoutType type =
8580      static_cast<Deoptimizer::BailoutType>(type_arg);
8581  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8582  DCHECK(AllowHeapAllocation::IsAllowed());
8583
8584  Handle<JSFunction> function = deoptimizer->function();
8585  Handle<Code> optimized_code = deoptimizer->compiled_code();
8586
8587  DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8588  DCHECK(type == deoptimizer->bailout_type());
8589
8590  // Make sure to materialize objects before causing any allocation.
8591  JavaScriptFrameIterator it(isolate);
8592  deoptimizer->MaterializeHeapObjects(&it);
8593  delete deoptimizer;
8594
8595  JavaScriptFrame* frame = it.frame();
8596  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8597  DCHECK(frame->function() == *function);
8598
8599  // Avoid doing too much work when running with --always-opt and keep
8600  // the optimized code around.
8601  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8602    return isolate->heap()->undefined_value();
8603  }
8604
8605  // Search for other activations of the same function and code.
8606  ActivationsFinder activations_finder(*optimized_code);
8607  activations_finder.VisitFrames(&it);
8608  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8609
8610  if (!activations_finder.has_code_activations_) {
8611    if (function->code() == *optimized_code) {
8612      if (FLAG_trace_deopt) {
8613        PrintF("[removing optimized code for: ");
8614        function->PrintName();
8615        PrintF("]\n");
8616      }
8617      function->ReplaceCode(function->shared()->code());
8618      // Evict optimized code for this function from the cache so that it
8619      // doesn't get used for new closures.
8620      function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8621                                                    "notify deoptimized");
8622    }
8623  } else {
8624    // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8625    // unconditionally if the code is not already marked for deoptimization.
8626    // If there is an index by shared function info, all the better.
8627    Deoptimizer::DeoptimizeFunction(*function);
8628  }
8629
8630  return isolate->heap()->undefined_value();
8631}
8632
8633
8634RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
8635  HandleScope scope(isolate);
8636  DCHECK(args.length() == 1);
8637  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8638  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8639
8640  // TODO(turbofan): Deoptimization is not supported yet.
8641  if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
8642    return isolate->heap()->undefined_value();
8643  }
8644
8645  Deoptimizer::DeoptimizeFunction(*function);
8646
8647  return isolate->heap()->undefined_value();
8648}
8649
8650
8651RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
8652  HandleScope scope(isolate);
8653  DCHECK(args.length() == 1);
8654  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8655  function->shared()->ClearTypeFeedbackInfo();
8656  Code* unoptimized = function->shared()->code();
8657  if (unoptimized->kind() == Code::FUNCTION) {
8658    unoptimized->ClearInlineCaches();
8659  }
8660  return isolate->heap()->undefined_value();
8661}
8662
8663
8664RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
8665  SealHandleScope shs(isolate);
8666  DCHECK(args.length() == 0);
8667#if defined(USE_SIMULATOR)
8668  return isolate->heap()->true_value();
8669#else
8670  return isolate->heap()->false_value();
8671#endif
8672}
8673
8674
8675RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
8676  SealHandleScope shs(isolate);
8677  DCHECK(args.length() == 0);
8678  return isolate->heap()->ToBoolean(
8679      isolate->concurrent_recompilation_enabled());
8680}
8681
8682
8683RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
8684  HandleScope scope(isolate);
8685  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8686  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8687  // The following two assertions are lifted from the DCHECKs inside
8688  // JSFunction::MarkForOptimization().
8689  RUNTIME_ASSERT(!function->shared()->is_generator());
8690  RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
8691                 (function->code()->kind() == Code::FUNCTION &&
8692                  function->code()->optimizable()));
8693
8694  // If the function is optimized, just return.
8695  if (function->IsOptimized()) return isolate->heap()->undefined_value();
8696
8697  function->MarkForOptimization();
8698
8699  Code* unoptimized = function->shared()->code();
8700  if (args.length() == 2 &&
8701      unoptimized->kind() == Code::FUNCTION) {
8702    CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8703    if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("osr")) && FLAG_use_osr) {
8704      // Start patching from the currently patched loop nesting level.
8705      DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
8706      isolate->runtime_profiler()->AttemptOnStackReplacement(
8707          *function, Code::kMaxLoopNestingMarker);
8708    } else if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
8709               isolate->concurrent_recompilation_enabled()) {
8710      function->MarkForConcurrentOptimization();
8711    }
8712  }
8713
8714  return isolate->heap()->undefined_value();
8715}
8716
8717
8718RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
8719  HandleScope scope(isolate);
8720  DCHECK(args.length() == 1);
8721  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8722  function->shared()->set_optimization_disabled(true);
8723  return isolate->heap()->undefined_value();
8724}
8725
8726
8727RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
8728  HandleScope scope(isolate);
8729  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8730  if (!isolate->use_crankshaft()) {
8731    return Smi::FromInt(4);  // 4 == "never".
8732  }
8733  bool sync_with_compiler_thread = true;
8734  if (args.length() == 2) {
8735    CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8736    if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
8737      sync_with_compiler_thread = false;
8738    }
8739  }
8740  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8741  if (isolate->concurrent_recompilation_enabled() &&
8742      sync_with_compiler_thread) {
8743    while (function->IsInOptimizationQueue()) {
8744      isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8745      base::OS::Sleep(50);
8746    }
8747  }
8748  if (FLAG_always_opt) {
8749    // We may have always opt, but that is more best-effort than a real
8750    // promise, so we still say "no" if it is not optimized.
8751    return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8752                                   : Smi::FromInt(2);  // 2 == "no".
8753  }
8754  if (FLAG_deopt_every_n_times) {
8755    return Smi::FromInt(6);  // 6 == "maybe deopted".
8756  }
8757  if (function->IsOptimized() && function->code()->is_turbofanned()) {
8758    return Smi::FromInt(7);  // 7 == "TurboFan compiler".
8759  }
8760  return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8761                                 : Smi::FromInt(2);  // 2 == "no".
8762}
8763
8764
8765RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
8766  DCHECK(args.length() == 0);
8767  RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8768  RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
8769  isolate->optimizing_compiler_thread()->Unblock();
8770  return isolate->heap()->undefined_value();
8771}
8772
8773
8774RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
8775  HandleScope scope(isolate);
8776  DCHECK(args.length() == 1);
8777  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8778  return Smi::FromInt(function->shared()->opt_count());
8779}
8780
8781
8782static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8783                                            Handle<JSFunction> function,
8784                                            Handle<Code> current_code) {
8785  // Keep track of whether we've succeeded in optimizing.
8786  if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
8787  // If we are trying to do OSR when there are already optimized
8788  // activations of the function, it means (a) the function is directly or
8789  // indirectly recursive and (b) an optimized invocation has been
8790  // deoptimized so that we are currently in an unoptimized activation.
8791  // Check for optimized activations of this function.
8792  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8793    JavaScriptFrame* frame = it.frame();
8794    if (frame->is_optimized() && frame->function() == *function) return false;
8795  }
8796
8797  return true;
8798}
8799
8800
8801RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
8802  HandleScope scope(isolate);
8803  DCHECK(args.length() == 1);
8804  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8805  Handle<Code> caller_code(function->shared()->code());
8806
8807  // We're not prepared to handle a function with arguments object.
8808  DCHECK(!function->shared()->uses_arguments());
8809
8810  RUNTIME_ASSERT(FLAG_use_osr);
8811
8812  // Passing the PC in the javascript frame from the caller directly is
8813  // not GC safe, so we walk the stack to get it.
8814  JavaScriptFrameIterator it(isolate);
8815  JavaScriptFrame* frame = it.frame();
8816  if (!caller_code->contains(frame->pc())) {
8817    // Code on the stack may not be the code object referenced by the shared
8818    // function info.  It may have been replaced to include deoptimization data.
8819    caller_code = Handle<Code>(frame->LookupCode());
8820  }
8821
8822  uint32_t pc_offset = static_cast<uint32_t>(
8823      frame->pc() - caller_code->instruction_start());
8824
8825#ifdef DEBUG
8826  DCHECK_EQ(frame->function(), *function);
8827  DCHECK_EQ(frame->LookupCode(), *caller_code);
8828  DCHECK(caller_code->contains(frame->pc()));
8829#endif  // DEBUG
8830
8831
8832  BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
8833  DCHECK(!ast_id.IsNone());
8834
8835  Compiler::ConcurrencyMode mode =
8836      isolate->concurrent_osr_enabled() &&
8837      (function->shared()->ast_node_count() > 512) ? Compiler::CONCURRENT
8838                                                   : Compiler::NOT_CONCURRENT;
8839  Handle<Code> result = Handle<Code>::null();
8840
8841  OptimizedCompileJob* job = NULL;
8842  if (mode == Compiler::CONCURRENT) {
8843    // Gate the OSR entry with a stack check.
8844    BackEdgeTable::AddStackCheck(caller_code, pc_offset);
8845    // Poll already queued compilation jobs.
8846    OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
8847    if (thread->IsQueuedForOSR(function, ast_id)) {
8848      if (FLAG_trace_osr) {
8849        PrintF("[OSR - Still waiting for queued: ");
8850        function->PrintName();
8851        PrintF(" at AST id %d]\n", ast_id.ToInt());
8852      }
8853      return NULL;
8854    }
8855
8856    job = thread->FindReadyOSRCandidate(function, ast_id);
8857  }
8858
8859  if (job != NULL) {
8860    if (FLAG_trace_osr) {
8861      PrintF("[OSR - Found ready: ");
8862      function->PrintName();
8863      PrintF(" at AST id %d]\n", ast_id.ToInt());
8864    }
8865    result = Compiler::GetConcurrentlyOptimizedCode(job);
8866  } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
8867    if (FLAG_trace_osr) {
8868      PrintF("[OSR - Compiling: ");
8869      function->PrintName();
8870      PrintF(" at AST id %d]\n", ast_id.ToInt());
8871    }
8872    MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
8873        function, caller_code, mode, ast_id);
8874    if (maybe_result.ToHandle(&result) &&
8875        result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
8876      // Optimization is queued.  Return to check later.
8877      return NULL;
8878    }
8879  }
8880
8881  // Revert the patched back edge table, regardless of whether OSR succeeds.
8882  BackEdgeTable::Revert(isolate, *caller_code);
8883
8884  // Check whether we ended up with usable optimized code.
8885  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8886    DeoptimizationInputData* data =
8887        DeoptimizationInputData::cast(result->deoptimization_data());
8888
8889    if (data->OsrPcOffset()->value() >= 0) {
8890      DCHECK(BailoutId(data->OsrAstId()->value()) == ast_id);
8891      if (FLAG_trace_osr) {
8892        PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
8893               ast_id.ToInt(), data->OsrPcOffset()->value());
8894      }
8895      // TODO(titzer): this is a massive hack to make the deopt counts
8896      // match. Fix heuristics for reenabling optimizations!
8897      function->shared()->increment_deopt_count();
8898
8899      // TODO(titzer): Do not install code into the function.
8900      function->ReplaceCode(*result);
8901      return *result;
8902    }
8903  }
8904
8905  // Failed.
8906  if (FLAG_trace_osr) {
8907    PrintF("[OSR - Failed: ");
8908    function->PrintName();
8909    PrintF(" at AST id %d]\n", ast_id.ToInt());
8910  }
8911
8912  if (!function->IsOptimized()) {
8913    function->ReplaceCode(function->shared()->code());
8914  }
8915  return NULL;
8916}
8917
8918
8919RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
8920  SealHandleScope shs(isolate);
8921  DCHECK(args.length() == 2 || args.length() == 3);
8922#ifdef DEBUG
8923  CONVERT_SMI_ARG_CHECKED(interval, 0);
8924  CONVERT_SMI_ARG_CHECKED(timeout, 1);
8925  isolate->heap()->set_allocation_timeout(timeout);
8926  FLAG_gc_interval = interval;
8927  if (args.length() == 3) {
8928    // Enable/disable inline allocation if requested.
8929    CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
8930    if (inline_allocation) {
8931      isolate->heap()->EnableInlineAllocation();
8932    } else {
8933      isolate->heap()->DisableInlineAllocation();
8934    }
8935  }
8936#endif
8937  return isolate->heap()->undefined_value();
8938}
8939
8940
8941RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
8942  SealHandleScope shs(isolate);
8943  DCHECK(args.length() == 0);
8944  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8945  return isolate->heap()->undefined_value();
8946}
8947
8948
8949RUNTIME_FUNCTION(Runtime_GetRootNaN) {
8950  SealHandleScope shs(isolate);
8951  DCHECK(args.length() == 0);
8952  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8953  return isolate->heap()->nan_value();
8954}
8955
8956
8957RUNTIME_FUNCTION(Runtime_Call) {
8958  HandleScope scope(isolate);
8959  DCHECK(args.length() >= 2);
8960  int argc = args.length() - 2;
8961  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8962  Object* receiver = args[0];
8963
8964  // If there are too many arguments, allocate argv via malloc.
8965  const int argv_small_size = 10;
8966  Handle<Object> argv_small_buffer[argv_small_size];
8967  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8968  Handle<Object>* argv = argv_small_buffer;
8969  if (argc > argv_small_size) {
8970    argv = new Handle<Object>[argc];
8971    if (argv == NULL) return isolate->StackOverflow();
8972    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8973  }
8974
8975  for (int i = 0; i < argc; ++i) {
8976     argv[i] = Handle<Object>(args[1 + i], isolate);
8977  }
8978
8979  Handle<JSReceiver> hfun(fun);
8980  Handle<Object> hreceiver(receiver, isolate);
8981  Handle<Object> result;
8982  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8983      isolate, result,
8984      Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
8985  return *result;
8986}
8987
8988
8989RUNTIME_FUNCTION(Runtime_Apply) {
8990  HandleScope scope(isolate);
8991  DCHECK(args.length() == 5);
8992  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8993  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
8994  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8995  CONVERT_INT32_ARG_CHECKED(offset, 3);
8996  CONVERT_INT32_ARG_CHECKED(argc, 4);
8997  RUNTIME_ASSERT(offset >= 0);
8998  // Loose upper bound to allow fuzzing. We'll most likely run out of
8999  // stack space before hitting this limit.
9000  static int kMaxArgc = 1000000;
9001  RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
9002
9003  // If there are too many arguments, allocate argv via malloc.
9004  const int argv_small_size = 10;
9005  Handle<Object> argv_small_buffer[argv_small_size];
9006  SmartArrayPointer<Handle<Object> > argv_large_buffer;
9007  Handle<Object>* argv = argv_small_buffer;
9008  if (argc > argv_small_size) {
9009    argv = new Handle<Object>[argc];
9010    if (argv == NULL) return isolate->StackOverflow();
9011    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
9012  }
9013
9014  for (int i = 0; i < argc; ++i) {
9015    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9016        isolate, argv[i],
9017        Object::GetElement(isolate, arguments, offset + i));
9018  }
9019
9020  Handle<Object> result;
9021  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9022      isolate, result,
9023      Execution::Call(isolate, fun, receiver, argc, argv, true));
9024  return *result;
9025}
9026
9027
9028RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) {
9029  HandleScope scope(isolate);
9030  DCHECK(args.length() == 1);
9031  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
9032  RUNTIME_ASSERT(!object->IsJSFunction());
9033  return *Execution::GetFunctionDelegate(isolate, object);
9034}
9035
9036
9037RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
9038  HandleScope scope(isolate);
9039  DCHECK(args.length() == 1);
9040  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
9041  RUNTIME_ASSERT(!object->IsJSFunction());
9042  return *Execution::GetConstructorDelegate(isolate, object);
9043}
9044
9045
9046RUNTIME_FUNCTION(Runtime_NewGlobalContext) {
9047  HandleScope scope(isolate);
9048  DCHECK(args.length() == 2);
9049
9050  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9051  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9052  Handle<Context> result =
9053      isolate->factory()->NewGlobalContext(function, scope_info);
9054
9055  DCHECK(function->context() == isolate->context());
9056  DCHECK(function->context()->global_object() == result->global_object());
9057  result->global_object()->set_global_context(*result);
9058  return *result;
9059}
9060
9061
9062RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
9063  HandleScope scope(isolate);
9064  DCHECK(args.length() == 1);
9065
9066  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9067
9068  DCHECK(function->context() == isolate->context());
9069  int length = function->shared()->scope_info()->ContextLength();
9070  return *isolate->factory()->NewFunctionContext(length, function);
9071}
9072
9073
9074RUNTIME_FUNCTION(Runtime_PushWithContext) {
9075  HandleScope scope(isolate);
9076  DCHECK(args.length() == 2);
9077  Handle<JSReceiver> extension_object;
9078  if (args[0]->IsJSReceiver()) {
9079    extension_object = args.at<JSReceiver>(0);
9080  } else {
9081    // Try to convert the object to a proper JavaScript object.
9082    MaybeHandle<JSReceiver> maybe_object =
9083        Object::ToObject(isolate, args.at<Object>(0));
9084    if (!maybe_object.ToHandle(&extension_object)) {
9085      Handle<Object> handle = args.at<Object>(0);
9086      THROW_NEW_ERROR_RETURN_FAILURE(
9087          isolate, NewTypeError("with_expression", HandleVector(&handle, 1)));
9088    }
9089  }
9090
9091  Handle<JSFunction> function;
9092  if (args[1]->IsSmi()) {
9093    // A smi sentinel indicates a context nested inside global code rather
9094    // than some function.  There is a canonical empty function that can be
9095    // gotten from the native context.
9096    function = handle(isolate->native_context()->closure());
9097  } else {
9098    function = args.at<JSFunction>(1);
9099  }
9100
9101  Handle<Context> current(isolate->context());
9102  Handle<Context> context = isolate->factory()->NewWithContext(
9103      function, current, extension_object);
9104  isolate->set_context(*context);
9105  return *context;
9106}
9107
9108
9109RUNTIME_FUNCTION(Runtime_PushCatchContext) {
9110  HandleScope scope(isolate);
9111  DCHECK(args.length() == 3);
9112  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
9113  CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
9114  Handle<JSFunction> function;
9115  if (args[2]->IsSmi()) {
9116    // A smi sentinel indicates a context nested inside global code rather
9117    // than some function.  There is a canonical empty function that can be
9118    // gotten from the native context.
9119    function = handle(isolate->native_context()->closure());
9120  } else {
9121    function = args.at<JSFunction>(2);
9122  }
9123  Handle<Context> current(isolate->context());
9124  Handle<Context> context = isolate->factory()->NewCatchContext(
9125      function, current, name, thrown_object);
9126  isolate->set_context(*context);
9127  return *context;
9128}
9129
9130
9131RUNTIME_FUNCTION(Runtime_PushBlockContext) {
9132  HandleScope scope(isolate);
9133  DCHECK(args.length() == 2);
9134  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
9135  Handle<JSFunction> function;
9136  if (args[1]->IsSmi()) {
9137    // A smi sentinel indicates a context nested inside global code rather
9138    // than some function.  There is a canonical empty function that can be
9139    // gotten from the native context.
9140    function = handle(isolate->native_context()->closure());
9141  } else {
9142    function = args.at<JSFunction>(1);
9143  }
9144  Handle<Context> current(isolate->context());
9145  Handle<Context> context = isolate->factory()->NewBlockContext(
9146      function, current, scope_info);
9147  isolate->set_context(*context);
9148  return *context;
9149}
9150
9151
9152RUNTIME_FUNCTION(Runtime_IsJSModule) {
9153  SealHandleScope shs(isolate);
9154  DCHECK(args.length() == 1);
9155  CONVERT_ARG_CHECKED(Object, obj, 0);
9156  return isolate->heap()->ToBoolean(obj->IsJSModule());
9157}
9158
9159
9160RUNTIME_FUNCTION(Runtime_PushModuleContext) {
9161  SealHandleScope shs(isolate);
9162  DCHECK(args.length() == 2);
9163  CONVERT_SMI_ARG_CHECKED(index, 0);
9164
9165  if (!args[1]->IsScopeInfo()) {
9166    // Module already initialized. Find hosting context and retrieve context.
9167    Context* host = Context::cast(isolate->context())->global_context();
9168    Context* context = Context::cast(host->get(index));
9169    DCHECK(context->previous() == isolate->context());
9170    isolate->set_context(context);
9171    return context;
9172  }
9173
9174  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9175
9176  // Allocate module context.
9177  HandleScope scope(isolate);
9178  Factory* factory = isolate->factory();
9179  Handle<Context> context = factory->NewModuleContext(scope_info);
9180  Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9181  context->set_module(*module);
9182  Context* previous = isolate->context();
9183  context->set_previous(previous);
9184  context->set_closure(previous->closure());
9185  context->set_global_object(previous->global_object());
9186  isolate->set_context(*context);
9187
9188  // Find hosting scope and initialize internal variable holding module there.
9189  previous->global_context()->set(index, *context);
9190
9191  return *context;
9192}
9193
9194
9195RUNTIME_FUNCTION(Runtime_DeclareModules) {
9196  HandleScope scope(isolate);
9197  DCHECK(args.length() == 1);
9198  CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9199  Context* host_context = isolate->context();
9200
9201  for (int i = 0; i < descriptions->length(); ++i) {
9202    Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9203    int host_index = description->host_index();
9204    Handle<Context> context(Context::cast(host_context->get(host_index)));
9205    Handle<JSModule> module(context->module());
9206
9207    for (int j = 0; j < description->length(); ++j) {
9208      Handle<String> name(description->name(j));
9209      VariableMode mode = description->mode(j);
9210      int index = description->index(j);
9211      switch (mode) {
9212        case VAR:
9213        case LET:
9214        case CONST:
9215        case CONST_LEGACY: {
9216          PropertyAttributes attr =
9217              IsImmutableVariableMode(mode) ? FROZEN : SEALED;
9218          Handle<AccessorInfo> info =
9219              Accessors::MakeModuleExport(name, index, attr);
9220          Handle<Object> result =
9221              JSObject::SetAccessor(module, info).ToHandleChecked();
9222          DCHECK(!result->IsUndefined());
9223          USE(result);
9224          break;
9225        }
9226        case MODULE: {
9227          Object* referenced_context = Context::cast(host_context)->get(index);
9228          Handle<JSModule> value(Context::cast(referenced_context)->module());
9229          JSObject::SetOwnPropertyIgnoreAttributes(module, name, value, FROZEN)
9230              .Assert();
9231          break;
9232        }
9233        case INTERNAL:
9234        case TEMPORARY:
9235        case DYNAMIC:
9236        case DYNAMIC_GLOBAL:
9237        case DYNAMIC_LOCAL:
9238          UNREACHABLE();
9239      }
9240    }
9241
9242    JSObject::PreventExtensions(module).Assert();
9243  }
9244
9245  DCHECK(!isolate->has_pending_exception());
9246  return isolate->heap()->undefined_value();
9247}
9248
9249
9250RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
9251  HandleScope scope(isolate);
9252  DCHECK(args.length() == 2);
9253
9254  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9255  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
9256
9257  int index;
9258  PropertyAttributes attributes;
9259  ContextLookupFlags flags = FOLLOW_CHAINS;
9260  BindingFlags binding_flags;
9261  Handle<Object> holder = context->Lookup(name,
9262                                          flags,
9263                                          &index,
9264                                          &attributes,
9265                                          &binding_flags);
9266
9267  // If the slot was not found the result is true.
9268  if (holder.is_null()) {
9269    return isolate->heap()->true_value();
9270  }
9271
9272  // If the slot was found in a context, it should be DONT_DELETE.
9273  if (holder->IsContext()) {
9274    return isolate->heap()->false_value();
9275  }
9276
9277  // The slot was found in a JSObject, either a context extension object,
9278  // the global object, or the subject of a with.  Try to delete it
9279  // (respecting DONT_DELETE).
9280  Handle<JSObject> object = Handle<JSObject>::cast(holder);
9281  Handle<Object> result;
9282  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9283      isolate, result,
9284      JSReceiver::DeleteProperty(object, name));
9285  return *result;
9286}
9287
9288
9289// A mechanism to return a pair of Object pointers in registers (if possible).
9290// How this is achieved is calling convention-dependent.
9291// All currently supported x86 compiles uses calling conventions that are cdecl
9292// variants where a 64-bit value is returned in two 32-bit registers
9293// (edx:eax on ia32, r1:r0 on ARM).
9294// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9295// In Win64 calling convention, a struct of two pointers is returned in memory,
9296// allocated by the caller, and passed as a pointer in a hidden first parameter.
9297#ifdef V8_HOST_ARCH_64_BIT
9298struct ObjectPair {
9299  Object* x;
9300  Object* y;
9301};
9302
9303
9304static inline ObjectPair MakePair(Object* x, Object* y) {
9305  ObjectPair result = {x, y};
9306  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9307  // In Win64 they are assigned to a hidden first argument.
9308  return result;
9309}
9310#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
9311// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair
9312// are used in the full codegen and Crankshaft compiler. An alternative is
9313// using uint64_t and modifying full codegen and Crankshaft compiler.
9314struct ObjectPair {
9315  Object* x;
9316  uint32_t x_upper;
9317  Object* y;
9318  uint32_t y_upper;
9319};
9320
9321
9322static inline ObjectPair MakePair(Object* x, Object* y) {
9323  ObjectPair result = {x, 0, y, 0};
9324  // Pointers x and y returned in rax and rdx, in x32-abi.
9325  return result;
9326}
9327#else
9328typedef uint64_t ObjectPair;
9329static inline ObjectPair MakePair(Object* x, Object* y) {
9330#if defined(V8_TARGET_LITTLE_ENDIAN)
9331  return reinterpret_cast<uint32_t>(x) |
9332      (reinterpret_cast<ObjectPair>(y) << 32);
9333#elif defined(V8_TARGET_BIG_ENDIAN)
9334    return reinterpret_cast<uint32_t>(y) |
9335        (reinterpret_cast<ObjectPair>(x) << 32);
9336#else
9337#error Unknown endianness
9338#endif
9339}
9340#endif
9341
9342
9343static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9344                                           JSObject* holder) {
9345  DCHECK(!holder->IsGlobalObject());
9346  Context* top = isolate->context();
9347  // Get the context extension function.
9348  JSFunction* context_extension_function =
9349      top->native_context()->context_extension_function();
9350  // If the holder isn't a context extension object, we just return it
9351  // as the receiver. This allows arguments objects to be used as
9352  // receivers, but only if they are put in the context scope chain
9353  // explicitly via a with-statement.
9354  Object* constructor = holder->map()->constructor();
9355  if (constructor != context_extension_function) return holder;
9356  // Fall back to using the global object as the implicit receiver if
9357  // the property turns out to be a local variable allocated in a
9358  // context extension object - introduced via eval.
9359  return isolate->heap()->undefined_value();
9360}
9361
9362
9363static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
9364                                       bool throw_error) {
9365  HandleScope scope(isolate);
9366  DCHECK_EQ(2, args.length());
9367
9368  if (!args[0]->IsContext() || !args[1]->IsString()) {
9369    return MakePair(isolate->ThrowIllegalOperation(), NULL);
9370  }
9371  Handle<Context> context = args.at<Context>(0);
9372  Handle<String> name = args.at<String>(1);
9373
9374  int index;
9375  PropertyAttributes attributes;
9376  ContextLookupFlags flags = FOLLOW_CHAINS;
9377  BindingFlags binding_flags;
9378  Handle<Object> holder = context->Lookup(name,
9379                                          flags,
9380                                          &index,
9381                                          &attributes,
9382                                          &binding_flags);
9383  if (isolate->has_pending_exception()) {
9384    return MakePair(isolate->heap()->exception(), NULL);
9385  }
9386
9387  // If the index is non-negative, the slot has been found in a context.
9388  if (index >= 0) {
9389    DCHECK(holder->IsContext());
9390    // If the "property" we were looking for is a local variable, the
9391    // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9392    Handle<Object> receiver = isolate->factory()->undefined_value();
9393    Object* value = Context::cast(*holder)->get(index);
9394    // Check for uninitialized bindings.
9395    switch (binding_flags) {
9396      case MUTABLE_CHECK_INITIALIZED:
9397      case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9398        if (value->IsTheHole()) {
9399          Handle<Object> error;
9400          MaybeHandle<Object> maybe_error =
9401              isolate->factory()->NewReferenceError("not_defined",
9402                                                    HandleVector(&name, 1));
9403          if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
9404          return MakePair(isolate->heap()->exception(), NULL);
9405        }
9406        // FALLTHROUGH
9407      case MUTABLE_IS_INITIALIZED:
9408      case IMMUTABLE_IS_INITIALIZED:
9409      case IMMUTABLE_IS_INITIALIZED_HARMONY:
9410        DCHECK(!value->IsTheHole());
9411        return MakePair(value, *receiver);
9412      case IMMUTABLE_CHECK_INITIALIZED:
9413        if (value->IsTheHole()) {
9414          DCHECK((attributes & READ_ONLY) != 0);
9415          value = isolate->heap()->undefined_value();
9416        }
9417        return MakePair(value, *receiver);
9418      case MISSING_BINDING:
9419        UNREACHABLE();
9420        return MakePair(NULL, NULL);
9421    }
9422  }
9423
9424  // Otherwise, if the slot was found the holder is a context extension
9425  // object, subject of a with, or a global object.  We read the named
9426  // property from it.
9427  if (!holder.is_null()) {
9428    Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9429#ifdef DEBUG
9430    if (!object->IsJSProxy()) {
9431      Maybe<bool> maybe = JSReceiver::HasProperty(object, name);
9432      DCHECK(maybe.has_value);
9433      DCHECK(maybe.value);
9434    }
9435#endif
9436    // GetProperty below can cause GC.
9437    Handle<Object> receiver_handle(
9438        object->IsGlobalObject()
9439            ? Object::cast(isolate->heap()->undefined_value())
9440            : object->IsJSProxy() ? static_cast<Object*>(*object)
9441                : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9442        isolate);
9443
9444    // No need to unhole the value here.  This is taken care of by the
9445    // GetProperty function.
9446    Handle<Object> value;
9447    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9448        isolate, value,
9449        Object::GetProperty(object, name),
9450        MakePair(isolate->heap()->exception(), NULL));
9451    return MakePair(*value, *receiver_handle);
9452  }
9453
9454  if (throw_error) {
9455    // The property doesn't exist - throw exception.
9456    Handle<Object> error;
9457    MaybeHandle<Object> maybe_error = isolate->factory()->NewReferenceError(
9458        "not_defined", HandleVector(&name, 1));
9459    if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
9460    return MakePair(isolate->heap()->exception(), NULL);
9461  } else {
9462    // The property doesn't exist - return undefined.
9463    return MakePair(isolate->heap()->undefined_value(),
9464                    isolate->heap()->undefined_value());
9465  }
9466}
9467
9468
9469RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) {
9470  return LoadLookupSlotHelper(args, isolate, true);
9471}
9472
9473
9474RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) {
9475  return LoadLookupSlotHelper(args, isolate, false);
9476}
9477
9478
9479RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
9480  HandleScope scope(isolate);
9481  DCHECK(args.length() == 4);
9482
9483  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
9484  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9485  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9486  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
9487
9488  int index;
9489  PropertyAttributes attributes;
9490  ContextLookupFlags flags = FOLLOW_CHAINS;
9491  BindingFlags binding_flags;
9492  Handle<Object> holder = context->Lookup(name,
9493                                          flags,
9494                                          &index,
9495                                          &attributes,
9496                                          &binding_flags);
9497  // In case of JSProxy, an exception might have been thrown.
9498  if (isolate->has_pending_exception()) return isolate->heap()->exception();
9499
9500  // The property was found in a context slot.
9501  if (index >= 0) {
9502    if ((attributes & READ_ONLY) == 0) {
9503      Handle<Context>::cast(holder)->set(index, *value);
9504    } else if (strict_mode == STRICT) {
9505      // Setting read only property in strict mode.
9506      THROW_NEW_ERROR_RETURN_FAILURE(
9507          isolate,
9508          NewTypeError("strict_cannot_assign", HandleVector(&name, 1)));
9509    }
9510    return *value;
9511  }
9512
9513  // Slow case: The property is not in a context slot.  It is either in a
9514  // context extension object, a property of the subject of a with, or a
9515  // property of the global object.
9516  Handle<JSReceiver> object;
9517  if (attributes != ABSENT) {
9518    // The property exists on the holder.
9519    object = Handle<JSReceiver>::cast(holder);
9520  } else if (strict_mode == STRICT) {
9521    // If absent in strict mode: throw.
9522    THROW_NEW_ERROR_RETURN_FAILURE(
9523        isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
9524  } else {
9525    // If absent in sloppy mode: add the property to the global object.
9526    object = Handle<JSReceiver>(context->global_object());
9527  }
9528
9529  RETURN_FAILURE_ON_EXCEPTION(
9530      isolate, Object::SetProperty(object, name, value, strict_mode));
9531
9532  return *value;
9533}
9534
9535
9536RUNTIME_FUNCTION(Runtime_Throw) {
9537  HandleScope scope(isolate);
9538  DCHECK(args.length() == 1);
9539
9540  return isolate->Throw(args[0]);
9541}
9542
9543
9544RUNTIME_FUNCTION(Runtime_ReThrow) {
9545  HandleScope scope(isolate);
9546  DCHECK(args.length() == 1);
9547
9548  return isolate->ReThrow(args[0]);
9549}
9550
9551
9552RUNTIME_FUNCTION(Runtime_PromoteScheduledException) {
9553  SealHandleScope shs(isolate);
9554  DCHECK(args.length() == 0);
9555  return isolate->PromoteScheduledException();
9556}
9557
9558
9559RUNTIME_FUNCTION(Runtime_ThrowReferenceError) {
9560  HandleScope scope(isolate);
9561  DCHECK(args.length() == 1);
9562  CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
9563  THROW_NEW_ERROR_RETURN_FAILURE(
9564      isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
9565}
9566
9567
9568RUNTIME_FUNCTION(Runtime_ThrowNonMethodError) {
9569  HandleScope scope(isolate);
9570  DCHECK(args.length() == 0);
9571  THROW_NEW_ERROR_RETURN_FAILURE(
9572      isolate, NewReferenceError("non_method", HandleVector<Object>(NULL, 0)));
9573}
9574
9575
9576RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
9577  HandleScope scope(isolate);
9578  DCHECK(args.length() == 0);
9579  THROW_NEW_ERROR_RETURN_FAILURE(
9580      isolate,
9581      NewReferenceError("unsupported_super", HandleVector<Object>(NULL, 0)));
9582}
9583
9584
9585RUNTIME_FUNCTION(Runtime_ThrowNotDateError) {
9586  HandleScope scope(isolate);
9587  DCHECK(args.length() == 0);
9588  THROW_NEW_ERROR_RETURN_FAILURE(
9589      isolate, NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
9590}
9591
9592
9593RUNTIME_FUNCTION(Runtime_StackGuard) {
9594  SealHandleScope shs(isolate);
9595  DCHECK(args.length() == 0);
9596
9597  // First check if this is a real stack overflow.
9598  StackLimitCheck check(isolate);
9599  if (check.JsHasOverflowed()) {
9600    return isolate->StackOverflow();
9601  }
9602
9603  return isolate->stack_guard()->HandleInterrupts();
9604}
9605
9606
9607RUNTIME_FUNCTION(Runtime_TryInstallOptimizedCode) {
9608  HandleScope scope(isolate);
9609  DCHECK(args.length() == 1);
9610  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9611
9612  // First check if this is a real stack overflow.
9613  StackLimitCheck check(isolate);
9614  if (check.JsHasOverflowed()) {
9615    SealHandleScope shs(isolate);
9616    return isolate->StackOverflow();
9617  }
9618
9619  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9620  return (function->IsOptimized()) ? function->code()
9621                                   : function->shared()->code();
9622}
9623
9624
9625RUNTIME_FUNCTION(Runtime_Interrupt) {
9626  SealHandleScope shs(isolate);
9627  DCHECK(args.length() == 0);
9628  return isolate->stack_guard()->HandleInterrupts();
9629}
9630
9631
9632static int StackSize(Isolate* isolate) {
9633  int n = 0;
9634  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9635  return n;
9636}
9637
9638
9639static void PrintTransition(Isolate* isolate, Object* result) {
9640  // indentation
9641  { const int nmax = 80;
9642    int n = StackSize(isolate);
9643    if (n <= nmax)
9644      PrintF("%4d:%*s", n, n, "");
9645    else
9646      PrintF("%4d:%*s", n, nmax, "...");
9647  }
9648
9649  if (result == NULL) {
9650    JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9651    PrintF(" {\n");
9652  } else {
9653    // function result
9654    PrintF("} -> ");
9655    result->ShortPrint();
9656    PrintF("\n");
9657  }
9658}
9659
9660
9661RUNTIME_FUNCTION(Runtime_TraceEnter) {
9662  SealHandleScope shs(isolate);
9663  DCHECK(args.length() == 0);
9664  PrintTransition(isolate, NULL);
9665  return isolate->heap()->undefined_value();
9666}
9667
9668
9669RUNTIME_FUNCTION(Runtime_TraceExit) {
9670  SealHandleScope shs(isolate);
9671  DCHECK(args.length() == 1);
9672  CONVERT_ARG_CHECKED(Object, obj, 0);
9673  PrintTransition(isolate, obj);
9674  return obj;  // return TOS
9675}
9676
9677
9678RUNTIME_FUNCTION(Runtime_DebugPrint) {
9679  SealHandleScope shs(isolate);
9680  DCHECK(args.length() == 1);
9681
9682  OFStream os(stdout);
9683#ifdef DEBUG
9684  if (args[0]->IsString()) {
9685    // If we have a string, assume it's a code "marker"
9686    // and print some interesting cpu debugging info.
9687    JavaScriptFrameIterator it(isolate);
9688    JavaScriptFrame* frame = it.frame();
9689    os << "fp = " << frame->fp() << ", sp = " << frame->sp()
9690       << ", caller_sp = " << frame->caller_sp() << ": ";
9691  } else {
9692    os << "DebugPrint: ";
9693  }
9694  args[0]->Print(os);
9695  if (args[0]->IsHeapObject()) {
9696    os << "\n";
9697    HeapObject::cast(args[0])->map()->Print(os);
9698  }
9699#else
9700  // ShortPrint is available in release mode. Print is not.
9701  os << Brief(args[0]);
9702#endif
9703  os << endl;
9704
9705  return args[0];  // return TOS
9706}
9707
9708
9709RUNTIME_FUNCTION(Runtime_DebugTrace) {
9710  SealHandleScope shs(isolate);
9711  DCHECK(args.length() == 0);
9712  isolate->PrintStack(stdout);
9713  return isolate->heap()->undefined_value();
9714}
9715
9716
9717RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
9718  HandleScope scope(isolate);
9719  DCHECK(args.length() == 0);
9720  if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent());
9721
9722  // According to ECMA-262, section 15.9.1, page 117, the precision of
9723  // the number in a Date object representing a particular instant in
9724  // time is milliseconds. Therefore, we floor the result of getting
9725  // the OS time.
9726  double millis;
9727  if (FLAG_verify_predictable) {
9728    millis = 1388534400000.0;  // Jan 1 2014 00:00:00 GMT+0000
9729    millis += Floor(isolate->heap()->synthetic_time());
9730  } else {
9731    millis = Floor(base::OS::TimeCurrentMillis());
9732  }
9733  return *isolate->factory()->NewNumber(millis);
9734}
9735
9736
9737RUNTIME_FUNCTION(Runtime_DateParseString) {
9738  HandleScope scope(isolate);
9739  DCHECK(args.length() == 2);
9740  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9741  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9742
9743  RUNTIME_ASSERT(output->HasFastElements());
9744  JSObject::EnsureCanContainHeapObjectElements(output);
9745  RUNTIME_ASSERT(output->HasFastObjectElements());
9746  Handle<FixedArray> output_array(FixedArray::cast(output->elements()));
9747  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9748
9749  str = String::Flatten(str);
9750  DisallowHeapAllocation no_gc;
9751
9752  bool result;
9753  String::FlatContent str_content = str->GetFlatContent();
9754  if (str_content.IsOneByte()) {
9755    result = DateParser::Parse(str_content.ToOneByteVector(),
9756                               *output_array,
9757                               isolate->unicode_cache());
9758  } else {
9759    DCHECK(str_content.IsTwoByte());
9760    result = DateParser::Parse(str_content.ToUC16Vector(),
9761                               *output_array,
9762                               isolate->unicode_cache());
9763  }
9764
9765  if (result) {
9766    return *output;
9767  } else {
9768    return isolate->heap()->null_value();
9769  }
9770}
9771
9772
9773RUNTIME_FUNCTION(Runtime_DateLocalTimezone) {
9774  HandleScope scope(isolate);
9775  DCHECK(args.length() == 1);
9776
9777  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9778  RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
9779                 x <= DateCache::kMaxTimeBeforeUTCInMs);
9780  const char* zone =
9781      isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
9782  Handle<String> result = isolate->factory()->NewStringFromUtf8(
9783      CStrVector(zone)).ToHandleChecked();
9784  return *result;
9785}
9786
9787
9788RUNTIME_FUNCTION(Runtime_DateToUTC) {
9789  HandleScope scope(isolate);
9790  DCHECK(args.length() == 1);
9791
9792  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9793  RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
9794                 x <= DateCache::kMaxTimeBeforeUTCInMs);
9795  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9796
9797  return *isolate->factory()->NewNumber(static_cast<double>(time));
9798}
9799
9800
9801RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
9802  HandleScope hs(isolate);
9803  DCHECK(args.length() == 0);
9804  if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
9805    Handle<FixedArray> date_cache_version =
9806        isolate->factory()->NewFixedArray(1, TENURED);
9807    date_cache_version->set(0, Smi::FromInt(0));
9808    isolate->eternal_handles()->CreateSingleton(
9809        isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
9810  }
9811  Handle<FixedArray> date_cache_version =
9812      Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
9813          EternalHandles::DATE_CACHE_VERSION));
9814  // Return result as a JS array.
9815  Handle<JSObject> result =
9816      isolate->factory()->NewJSObject(isolate->array_function());
9817  JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
9818  return *result;
9819}
9820
9821
9822RUNTIME_FUNCTION(Runtime_GlobalProxy) {
9823  SealHandleScope shs(isolate);
9824  DCHECK(args.length() == 1);
9825  CONVERT_ARG_CHECKED(Object, global, 0);
9826  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9827  return JSGlobalObject::cast(global)->global_proxy();
9828}
9829
9830
9831RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) {
9832  SealHandleScope shs(isolate);
9833  DCHECK(args.length() == 1);
9834  CONVERT_ARG_CHECKED(Object, global, 0);
9835  if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
9836  return isolate->heap()->ToBoolean(
9837      !JSGlobalObject::cast(global)->IsDetached());
9838}
9839
9840
9841RUNTIME_FUNCTION(Runtime_ParseJson) {
9842  HandleScope scope(isolate);
9843  DCHECK(args.length() == 1);
9844  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9845
9846  source = String::Flatten(source);
9847  // Optimized fast case where we only have Latin1 characters.
9848  Handle<Object> result;
9849  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9850      isolate, result,
9851      source->IsSeqOneByteString() ? JsonParser<true>::Parse(source)
9852                                   : JsonParser<false>::Parse(source));
9853  return *result;
9854}
9855
9856
9857bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9858                                      Handle<Context> context) {
9859  DCHECK(context->allow_code_gen_from_strings()->IsFalse());
9860  // Check with callback if set.
9861  AllowCodeGenerationFromStringsCallback callback =
9862      isolate->allow_code_gen_callback();
9863  if (callback == NULL) {
9864    // No callback set and code generation disallowed.
9865    return false;
9866  } else {
9867    // Callback set. Let it decide if code generation is allowed.
9868    VMState<EXTERNAL> state(isolate);
9869    return callback(v8::Utils::ToLocal(context));
9870  }
9871}
9872
9873
9874RUNTIME_FUNCTION(Runtime_CompileString) {
9875  HandleScope scope(isolate);
9876  DCHECK(args.length() == 2);
9877  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9878  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9879
9880  // Extract native context.
9881  Handle<Context> context(isolate->native_context());
9882
9883  // Check if native context allows code generation from
9884  // strings. Throw an exception if it doesn't.
9885  if (context->allow_code_gen_from_strings()->IsFalse() &&
9886      !CodeGenerationFromStringsAllowed(isolate, context)) {
9887    Handle<Object> error_message =
9888        context->ErrorMessageForCodeGenerationFromStrings();
9889    THROW_NEW_ERROR_RETURN_FAILURE(
9890        isolate, NewEvalError("code_gen_from_strings",
9891                              HandleVector<Object>(&error_message, 1)));
9892  }
9893
9894  // Compile source string in the native context.
9895  ParseRestriction restriction = function_literal_only
9896      ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9897  Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
9898  Handle<JSFunction> fun;
9899  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9900      isolate, fun,
9901      Compiler::GetFunctionFromEval(
9902          source, outer_info,
9903          context, SLOPPY, restriction, RelocInfo::kNoPosition));
9904  return *fun;
9905}
9906
9907
9908static ObjectPair CompileGlobalEval(Isolate* isolate,
9909                                    Handle<String> source,
9910                                    Handle<SharedFunctionInfo> outer_info,
9911                                    Handle<Object> receiver,
9912                                    StrictMode strict_mode,
9913                                    int scope_position) {
9914  Handle<Context> context = Handle<Context>(isolate->context());
9915  Handle<Context> native_context = Handle<Context>(context->native_context());
9916
9917  // Check if native context allows code generation from
9918  // strings. Throw an exception if it doesn't.
9919  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9920      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9921    Handle<Object> error_message =
9922        native_context->ErrorMessageForCodeGenerationFromStrings();
9923    Handle<Object> error;
9924    MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
9925        "code_gen_from_strings", HandleVector<Object>(&error_message, 1));
9926    if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
9927    return MakePair(isolate->heap()->exception(), NULL);
9928  }
9929
9930  // Deal with a normal eval call with a string argument. Compile it
9931  // and return the compiled function bound in the local context.
9932  static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
9933  Handle<JSFunction> compiled;
9934  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9935      isolate, compiled,
9936      Compiler::GetFunctionFromEval(
9937          source, outer_info,
9938          context, strict_mode, restriction, scope_position),
9939      MakePair(isolate->heap()->exception(), NULL));
9940  return MakePair(*compiled, *receiver);
9941}
9942
9943
9944RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) {
9945  HandleScope scope(isolate);
9946  DCHECK(args.length() == 6);
9947
9948  Handle<Object> callee = args.at<Object>(0);
9949
9950  // If "eval" didn't refer to the original GlobalEval, it's not a
9951  // direct call to eval.
9952  // (And even if it is, but the first argument isn't a string, just let
9953  // execution default to an indirect call to eval, which will also return
9954  // the first argument without doing anything).
9955  if (*callee != isolate->native_context()->global_eval_fun() ||
9956      !args[1]->IsString()) {
9957    return MakePair(*callee, isolate->heap()->undefined_value());
9958  }
9959
9960  DCHECK(args[4]->IsSmi());
9961  DCHECK(args.smi_at(4) == SLOPPY || args.smi_at(4) == STRICT);
9962  StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(4));
9963  DCHECK(args[5]->IsSmi());
9964  Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
9965                                        isolate);
9966  return CompileGlobalEval(isolate,
9967                           args.at<String>(1),
9968                           outer_info,
9969                           args.at<Object>(3),
9970                           strict_mode,
9971                           args.smi_at(5));
9972}
9973
9974
9975RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) {
9976  HandleScope scope(isolate);
9977  DCHECK(args.length() == 1);
9978  CONVERT_SMI_ARG_CHECKED(size, 0);
9979  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9980  RUNTIME_ASSERT(size > 0);
9981  RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
9982  return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
9983}
9984
9985
9986RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) {
9987  HandleScope scope(isolate);
9988  DCHECK(args.length() == 2);
9989  CONVERT_SMI_ARG_CHECKED(size, 0);
9990  CONVERT_SMI_ARG_CHECKED(flags, 1);
9991  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9992  RUNTIME_ASSERT(size > 0);
9993  RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
9994  bool double_align = AllocateDoubleAlignFlag::decode(flags);
9995  AllocationSpace space = AllocateTargetSpace::decode(flags);
9996  return *isolate->factory()->NewFillerObject(size, double_align, space);
9997}
9998
9999
10000// Push an object unto an array of objects if it is not already in the
10001// array.  Returns true if the element was pushed on the stack and
10002// false otherwise.
10003RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
10004  HandleScope scope(isolate);
10005  DCHECK(args.length() == 2);
10006  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
10007  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1);
10008  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
10009  int length = Smi::cast(array->length())->value();
10010  FixedArray* elements = FixedArray::cast(array->elements());
10011  for (int i = 0; i < length; i++) {
10012    if (elements->get(i) == *element) return isolate->heap()->false_value();
10013  }
10014
10015  // Strict not needed. Used for cycle detection in Array join implementation.
10016  RETURN_FAILURE_ON_EXCEPTION(
10017      isolate,
10018      JSObject::SetFastElement(array, length, element, SLOPPY, true));
10019  return isolate->heap()->true_value();
10020}
10021
10022
10023/**
10024 * A simple visitor visits every element of Array's.
10025 * The backend storage can be a fixed array for fast elements case,
10026 * or a dictionary for sparse array. Since Dictionary is a subtype
10027 * of FixedArray, the class can be used by both fast and slow cases.
10028 * The second parameter of the constructor, fast_elements, specifies
10029 * whether the storage is a FixedArray or Dictionary.
10030 *
10031 * An index limit is used to deal with the situation that a result array
10032 * length overflows 32-bit non-negative integer.
10033 */
10034class ArrayConcatVisitor {
10035 public:
10036  ArrayConcatVisitor(Isolate* isolate,
10037                     Handle<FixedArray> storage,
10038                     bool fast_elements) :
10039      isolate_(isolate),
10040      storage_(Handle<FixedArray>::cast(
10041          isolate->global_handles()->Create(*storage))),
10042      index_offset_(0u),
10043      fast_elements_(fast_elements),
10044      exceeds_array_limit_(false) { }
10045
10046  ~ArrayConcatVisitor() {
10047    clear_storage();
10048  }
10049
10050  void visit(uint32_t i, Handle<Object> elm) {
10051    if (i > JSObject::kMaxElementCount - index_offset_) {
10052      exceeds_array_limit_ = true;
10053      return;
10054    }
10055    uint32_t index = index_offset_ + i;
10056
10057    if (fast_elements_) {
10058      if (index < static_cast<uint32_t>(storage_->length())) {
10059        storage_->set(index, *elm);
10060        return;
10061      }
10062      // Our initial estimate of length was foiled, possibly by
10063      // getters on the arrays increasing the length of later arrays
10064      // during iteration.
10065      // This shouldn't happen in anything but pathological cases.
10066      SetDictionaryMode();
10067      // Fall-through to dictionary mode.
10068    }
10069    DCHECK(!fast_elements_);
10070    Handle<SeededNumberDictionary> dict(
10071        SeededNumberDictionary::cast(*storage_));
10072    Handle<SeededNumberDictionary> result =
10073        SeededNumberDictionary::AtNumberPut(dict, index, elm);
10074    if (!result.is_identical_to(dict)) {
10075      // Dictionary needed to grow.
10076      clear_storage();
10077      set_storage(*result);
10078    }
10079  }
10080
10081  void increase_index_offset(uint32_t delta) {
10082    if (JSObject::kMaxElementCount - index_offset_ < delta) {
10083      index_offset_ = JSObject::kMaxElementCount;
10084    } else {
10085      index_offset_ += delta;
10086    }
10087    // If the initial length estimate was off (see special case in visit()),
10088    // but the array blowing the limit didn't contain elements beyond the
10089    // provided-for index range, go to dictionary mode now.
10090    if (fast_elements_ &&
10091        index_offset_ >
10092            static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
10093      SetDictionaryMode();
10094    }
10095  }
10096
10097  bool exceeds_array_limit() {
10098    return exceeds_array_limit_;
10099  }
10100
10101  Handle<JSArray> ToArray() {
10102    Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
10103    Handle<Object> length =
10104        isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
10105    Handle<Map> map = JSObject::GetElementsTransitionMap(
10106        array,
10107        fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
10108    array->set_map(*map);
10109    array->set_length(*length);
10110    array->set_elements(*storage_);
10111    return array;
10112  }
10113
10114 private:
10115  // Convert storage to dictionary mode.
10116  void SetDictionaryMode() {
10117    DCHECK(fast_elements_);
10118    Handle<FixedArray> current_storage(*storage_);
10119    Handle<SeededNumberDictionary> slow_storage(
10120        SeededNumberDictionary::New(isolate_, current_storage->length()));
10121    uint32_t current_length = static_cast<uint32_t>(current_storage->length());
10122    for (uint32_t i = 0; i < current_length; i++) {
10123      HandleScope loop_scope(isolate_);
10124      Handle<Object> element(current_storage->get(i), isolate_);
10125      if (!element->IsTheHole()) {
10126        Handle<SeededNumberDictionary> new_storage =
10127            SeededNumberDictionary::AtNumberPut(slow_storage, i, element);
10128        if (!new_storage.is_identical_to(slow_storage)) {
10129          slow_storage = loop_scope.CloseAndEscape(new_storage);
10130        }
10131      }
10132    }
10133    clear_storage();
10134    set_storage(*slow_storage);
10135    fast_elements_ = false;
10136  }
10137
10138  inline void clear_storage() {
10139    GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
10140  }
10141
10142  inline void set_storage(FixedArray* storage) {
10143    storage_ = Handle<FixedArray>::cast(
10144        isolate_->global_handles()->Create(storage));
10145  }
10146
10147  Isolate* isolate_;
10148  Handle<FixedArray> storage_;  // Always a global handle.
10149  // Index after last seen index. Always less than or equal to
10150  // JSObject::kMaxElementCount.
10151  uint32_t index_offset_;
10152  bool fast_elements_ : 1;
10153  bool exceeds_array_limit_ : 1;
10154};
10155
10156
10157static uint32_t EstimateElementCount(Handle<JSArray> array) {
10158  uint32_t length = static_cast<uint32_t>(array->length()->Number());
10159  int element_count = 0;
10160  switch (array->GetElementsKind()) {
10161    case FAST_SMI_ELEMENTS:
10162    case FAST_HOLEY_SMI_ELEMENTS:
10163    case FAST_ELEMENTS:
10164    case FAST_HOLEY_ELEMENTS: {
10165      // Fast elements can't have lengths that are not representable by
10166      // a 32-bit signed integer.
10167      DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
10168      int fast_length = static_cast<int>(length);
10169      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
10170      for (int i = 0; i < fast_length; i++) {
10171        if (!elements->get(i)->IsTheHole()) element_count++;
10172      }
10173      break;
10174    }
10175    case FAST_DOUBLE_ELEMENTS:
10176    case FAST_HOLEY_DOUBLE_ELEMENTS: {
10177      // Fast elements can't have lengths that are not representable by
10178      // a 32-bit signed integer.
10179      DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
10180      int fast_length = static_cast<int>(length);
10181      if (array->elements()->IsFixedArray()) {
10182        DCHECK(FixedArray::cast(array->elements())->length() == 0);
10183        break;
10184      }
10185      Handle<FixedDoubleArray> elements(
10186          FixedDoubleArray::cast(array->elements()));
10187      for (int i = 0; i < fast_length; i++) {
10188        if (!elements->is_the_hole(i)) element_count++;
10189      }
10190      break;
10191    }
10192    case DICTIONARY_ELEMENTS: {
10193      Handle<SeededNumberDictionary> dictionary(
10194          SeededNumberDictionary::cast(array->elements()));
10195      int capacity = dictionary->Capacity();
10196      for (int i = 0; i < capacity; i++) {
10197        Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10198        if (dictionary->IsKey(*key)) {
10199          element_count++;
10200        }
10201      }
10202      break;
10203    }
10204    case SLOPPY_ARGUMENTS_ELEMENTS:
10205#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
10206    case EXTERNAL_##TYPE##_ELEMENTS:                                         \
10207    case TYPE##_ELEMENTS:                                                    \
10208
10209    TYPED_ARRAYS(TYPED_ARRAY_CASE)
10210#undef TYPED_ARRAY_CASE
10211      // External arrays are always dense.
10212      return length;
10213  }
10214  // As an estimate, we assume that the prototype doesn't contain any
10215  // inherited elements.
10216  return element_count;
10217}
10218
10219
10220
10221template<class ExternalArrayClass, class ElementType>
10222static void IterateExternalArrayElements(Isolate* isolate,
10223                                         Handle<JSObject> receiver,
10224                                         bool elements_are_ints,
10225                                         bool elements_are_guaranteed_smis,
10226                                         ArrayConcatVisitor* visitor) {
10227  Handle<ExternalArrayClass> array(
10228      ExternalArrayClass::cast(receiver->elements()));
10229  uint32_t len = static_cast<uint32_t>(array->length());
10230
10231  DCHECK(visitor != NULL);
10232  if (elements_are_ints) {
10233    if (elements_are_guaranteed_smis) {
10234      for (uint32_t j = 0; j < len; j++) {
10235        HandleScope loop_scope(isolate);
10236        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10237                      isolate);
10238        visitor->visit(j, e);
10239      }
10240    } else {
10241      for (uint32_t j = 0; j < len; j++) {
10242        HandleScope loop_scope(isolate);
10243        int64_t val = static_cast<int64_t>(array->get_scalar(j));
10244        if (Smi::IsValid(static_cast<intptr_t>(val))) {
10245          Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10246          visitor->visit(j, e);
10247        } else {
10248          Handle<Object> e =
10249              isolate->factory()->NewNumber(static_cast<ElementType>(val));
10250          visitor->visit(j, e);
10251        }
10252      }
10253    }
10254  } else {
10255    for (uint32_t j = 0; j < len; j++) {
10256      HandleScope loop_scope(isolate);
10257      Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10258      visitor->visit(j, e);
10259    }
10260  }
10261}
10262
10263
10264// Used for sorting indices in a List<uint32_t>.
10265static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10266  uint32_t a = *ap;
10267  uint32_t b = *bp;
10268  return (a == b) ? 0 : (a < b) ? -1 : 1;
10269}
10270
10271
10272static void CollectElementIndices(Handle<JSObject> object,
10273                                  uint32_t range,
10274                                  List<uint32_t>* indices) {
10275  Isolate* isolate = object->GetIsolate();
10276  ElementsKind kind = object->GetElementsKind();
10277  switch (kind) {
10278    case FAST_SMI_ELEMENTS:
10279    case FAST_ELEMENTS:
10280    case FAST_HOLEY_SMI_ELEMENTS:
10281    case FAST_HOLEY_ELEMENTS: {
10282      Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10283      uint32_t length = static_cast<uint32_t>(elements->length());
10284      if (range < length) length = range;
10285      for (uint32_t i = 0; i < length; i++) {
10286        if (!elements->get(i)->IsTheHole()) {
10287          indices->Add(i);
10288        }
10289      }
10290      break;
10291    }
10292    case FAST_HOLEY_DOUBLE_ELEMENTS:
10293    case FAST_DOUBLE_ELEMENTS: {
10294      if (object->elements()->IsFixedArray()) {
10295        DCHECK(object->elements()->length() == 0);
10296        break;
10297      }
10298      Handle<FixedDoubleArray> elements(
10299          FixedDoubleArray::cast(object->elements()));
10300      uint32_t length = static_cast<uint32_t>(elements->length());
10301      if (range < length) length = range;
10302      for (uint32_t i = 0; i < length; i++) {
10303        if (!elements->is_the_hole(i)) {
10304          indices->Add(i);
10305        }
10306      }
10307      break;
10308    }
10309    case DICTIONARY_ELEMENTS: {
10310      Handle<SeededNumberDictionary> dict(
10311          SeededNumberDictionary::cast(object->elements()));
10312      uint32_t capacity = dict->Capacity();
10313      for (uint32_t j = 0; j < capacity; j++) {
10314        HandleScope loop_scope(isolate);
10315        Handle<Object> k(dict->KeyAt(j), isolate);
10316        if (dict->IsKey(*k)) {
10317          DCHECK(k->IsNumber());
10318          uint32_t index = static_cast<uint32_t>(k->Number());
10319          if (index < range) {
10320            indices->Add(index);
10321          }
10322        }
10323      }
10324      break;
10325    }
10326#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
10327    case TYPE##_ELEMENTS:                               \
10328    case EXTERNAL_##TYPE##_ELEMENTS:
10329
10330      TYPED_ARRAYS(TYPED_ARRAY_CASE)
10331#undef TYPED_ARRAY_CASE
10332    {
10333      uint32_t length = static_cast<uint32_t>(
10334          FixedArrayBase::cast(object->elements())->length());
10335      if (range <= length) {
10336        length = range;
10337        // We will add all indices, so we might as well clear it first
10338        // and avoid duplicates.
10339        indices->Clear();
10340      }
10341      for (uint32_t i = 0; i < length; i++) {
10342        indices->Add(i);
10343      }
10344      if (length == range) return;  // All indices accounted for already.
10345      break;
10346    }
10347    case SLOPPY_ARGUMENTS_ELEMENTS: {
10348      MaybeHandle<Object> length_obj =
10349          Object::GetProperty(object, isolate->factory()->length_string());
10350      double length_num = length_obj.ToHandleChecked()->Number();
10351      uint32_t length = static_cast<uint32_t>(DoubleToInt32(length_num));
10352      ElementsAccessor* accessor = object->GetElementsAccessor();
10353      for (uint32_t i = 0; i < length; i++) {
10354        if (accessor->HasElement(object, object, i)) {
10355          indices->Add(i);
10356        }
10357      }
10358      break;
10359    }
10360  }
10361
10362  PrototypeIterator iter(isolate, object);
10363  if (!iter.IsAtEnd()) {
10364    // The prototype will usually have no inherited element indices,
10365    // but we have to check.
10366    CollectElementIndices(
10367        Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), range,
10368        indices);
10369  }
10370}
10371
10372
10373/**
10374 * A helper function that visits elements of a JSArray in numerical
10375 * order.
10376 *
10377 * The visitor argument called for each existing element in the array
10378 * with the element index and the element's value.
10379 * Afterwards it increments the base-index of the visitor by the array
10380 * length.
10381 * Returns false if any access threw an exception, otherwise true.
10382 */
10383static bool IterateElements(Isolate* isolate,
10384                            Handle<JSArray> receiver,
10385                            ArrayConcatVisitor* visitor) {
10386  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10387  switch (receiver->GetElementsKind()) {
10388    case FAST_SMI_ELEMENTS:
10389    case FAST_ELEMENTS:
10390    case FAST_HOLEY_SMI_ELEMENTS:
10391    case FAST_HOLEY_ELEMENTS: {
10392      // Run through the elements FixedArray and use HasElement and GetElement
10393      // to check the prototype for missing elements.
10394      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10395      int fast_length = static_cast<int>(length);
10396      DCHECK(fast_length <= elements->length());
10397      for (int j = 0; j < fast_length; j++) {
10398        HandleScope loop_scope(isolate);
10399        Handle<Object> element_value(elements->get(j), isolate);
10400        if (!element_value->IsTheHole()) {
10401          visitor->visit(j, element_value);
10402        } else {
10403          Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
10404          if (!maybe.has_value) return false;
10405          if (maybe.value) {
10406            // Call GetElement on receiver, not its prototype, or getters won't
10407            // have the correct receiver.
10408            ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10409                isolate, element_value,
10410                Object::GetElement(isolate, receiver, j), false);
10411            visitor->visit(j, element_value);
10412          }
10413        }
10414      }
10415      break;
10416    }
10417    case FAST_HOLEY_DOUBLE_ELEMENTS:
10418    case FAST_DOUBLE_ELEMENTS: {
10419      // Empty array is FixedArray but not FixedDoubleArray.
10420      if (length == 0) break;
10421      // Run through the elements FixedArray and use HasElement and GetElement
10422      // to check the prototype for missing elements.
10423      if (receiver->elements()->IsFixedArray()) {
10424        DCHECK(receiver->elements()->length() == 0);
10425        break;
10426      }
10427      Handle<FixedDoubleArray> elements(
10428          FixedDoubleArray::cast(receiver->elements()));
10429      int fast_length = static_cast<int>(length);
10430      DCHECK(fast_length <= elements->length());
10431      for (int j = 0; j < fast_length; j++) {
10432        HandleScope loop_scope(isolate);
10433        if (!elements->is_the_hole(j)) {
10434          double double_value = elements->get_scalar(j);
10435          Handle<Object> element_value =
10436              isolate->factory()->NewNumber(double_value);
10437          visitor->visit(j, element_value);
10438        } else {
10439          Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
10440          if (!maybe.has_value) return false;
10441          if (maybe.value) {
10442            // Call GetElement on receiver, not its prototype, or getters won't
10443            // have the correct receiver.
10444            Handle<Object> element_value;
10445            ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10446                isolate, element_value,
10447                Object::GetElement(isolate, receiver, j), false);
10448            visitor->visit(j, element_value);
10449          }
10450        }
10451      }
10452      break;
10453    }
10454    case DICTIONARY_ELEMENTS: {
10455      Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10456      List<uint32_t> indices(dict->Capacity() / 2);
10457      // Collect all indices in the object and the prototypes less
10458      // than length. This might introduce duplicates in the indices list.
10459      CollectElementIndices(receiver, length, &indices);
10460      indices.Sort(&compareUInt32);
10461      int j = 0;
10462      int n = indices.length();
10463      while (j < n) {
10464        HandleScope loop_scope(isolate);
10465        uint32_t index = indices[j];
10466        Handle<Object> element;
10467        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10468            isolate, element,
10469            Object::GetElement(isolate, receiver, index),
10470            false);
10471        visitor->visit(index, element);
10472        // Skip to next different index (i.e., omit duplicates).
10473        do {
10474          j++;
10475        } while (j < n && indices[j] == index);
10476      }
10477      break;
10478    }
10479    case EXTERNAL_UINT8_CLAMPED_ELEMENTS: {
10480      Handle<ExternalUint8ClampedArray> pixels(ExternalUint8ClampedArray::cast(
10481          receiver->elements()));
10482      for (uint32_t j = 0; j < length; j++) {
10483        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10484        visitor->visit(j, e);
10485      }
10486      break;
10487    }
10488    case EXTERNAL_INT8_ELEMENTS: {
10489      IterateExternalArrayElements<ExternalInt8Array, int8_t>(
10490          isolate, receiver, true, true, visitor);
10491      break;
10492    }
10493    case EXTERNAL_UINT8_ELEMENTS: {
10494      IterateExternalArrayElements<ExternalUint8Array, uint8_t>(
10495          isolate, receiver, true, true, visitor);
10496      break;
10497    }
10498    case EXTERNAL_INT16_ELEMENTS: {
10499      IterateExternalArrayElements<ExternalInt16Array, int16_t>(
10500          isolate, receiver, true, true, visitor);
10501      break;
10502    }
10503    case EXTERNAL_UINT16_ELEMENTS: {
10504      IterateExternalArrayElements<ExternalUint16Array, uint16_t>(
10505          isolate, receiver, true, true, visitor);
10506      break;
10507    }
10508    case EXTERNAL_INT32_ELEMENTS: {
10509      IterateExternalArrayElements<ExternalInt32Array, int32_t>(
10510          isolate, receiver, true, false, visitor);
10511      break;
10512    }
10513    case EXTERNAL_UINT32_ELEMENTS: {
10514      IterateExternalArrayElements<ExternalUint32Array, uint32_t>(
10515          isolate, receiver, true, false, visitor);
10516      break;
10517    }
10518    case EXTERNAL_FLOAT32_ELEMENTS: {
10519      IterateExternalArrayElements<ExternalFloat32Array, float>(
10520          isolate, receiver, false, false, visitor);
10521      break;
10522    }
10523    case EXTERNAL_FLOAT64_ELEMENTS: {
10524      IterateExternalArrayElements<ExternalFloat64Array, double>(
10525          isolate, receiver, false, false, visitor);
10526      break;
10527    }
10528    default:
10529      UNREACHABLE();
10530      break;
10531  }
10532  visitor->increase_index_offset(length);
10533  return true;
10534}
10535
10536
10537/**
10538 * Array::concat implementation.
10539 * See ECMAScript 262, 15.4.4.4.
10540 * TODO(581): Fix non-compliance for very large concatenations and update to
10541 * following the ECMAScript 5 specification.
10542 */
10543RUNTIME_FUNCTION(Runtime_ArrayConcat) {
10544  HandleScope handle_scope(isolate);
10545  DCHECK(args.length() == 1);
10546
10547  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10548  int argument_count = static_cast<int>(arguments->length()->Number());
10549  RUNTIME_ASSERT(arguments->HasFastObjectElements());
10550  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10551
10552  // Pass 1: estimate the length and number of elements of the result.
10553  // The actual length can be larger if any of the arguments have getters
10554  // that mutate other arguments (but will otherwise be precise).
10555  // The number of elements is precise if there are no inherited elements.
10556
10557  ElementsKind kind = FAST_SMI_ELEMENTS;
10558
10559  uint32_t estimate_result_length = 0;
10560  uint32_t estimate_nof_elements = 0;
10561  for (int i = 0; i < argument_count; i++) {
10562    HandleScope loop_scope(isolate);
10563    Handle<Object> obj(elements->get(i), isolate);
10564    uint32_t length_estimate;
10565    uint32_t element_estimate;
10566    if (obj->IsJSArray()) {
10567      Handle<JSArray> array(Handle<JSArray>::cast(obj));
10568      length_estimate = static_cast<uint32_t>(array->length()->Number());
10569      if (length_estimate != 0) {
10570        ElementsKind array_kind =
10571            GetPackedElementsKind(array->map()->elements_kind());
10572        if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10573          kind = array_kind;
10574        }
10575      }
10576      element_estimate = EstimateElementCount(array);
10577    } else {
10578      if (obj->IsHeapObject()) {
10579        if (obj->IsNumber()) {
10580          if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10581            kind = FAST_DOUBLE_ELEMENTS;
10582          }
10583        } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10584          kind = FAST_ELEMENTS;
10585        }
10586      }
10587      length_estimate = 1;
10588      element_estimate = 1;
10589    }
10590    // Avoid overflows by capping at kMaxElementCount.
10591    if (JSObject::kMaxElementCount - estimate_result_length <
10592        length_estimate) {
10593      estimate_result_length = JSObject::kMaxElementCount;
10594    } else {
10595      estimate_result_length += length_estimate;
10596    }
10597    if (JSObject::kMaxElementCount - estimate_nof_elements <
10598        element_estimate) {
10599      estimate_nof_elements = JSObject::kMaxElementCount;
10600    } else {
10601      estimate_nof_elements += element_estimate;
10602    }
10603  }
10604
10605  // If estimated number of elements is more than half of length, a
10606  // fixed array (fast case) is more time and space-efficient than a
10607  // dictionary.
10608  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10609
10610  if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
10611    Handle<FixedArrayBase> storage =
10612        isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10613    int j = 0;
10614    bool failure = false;
10615    if (estimate_result_length > 0) {
10616      Handle<FixedDoubleArray> double_storage =
10617          Handle<FixedDoubleArray>::cast(storage);
10618      for (int i = 0; i < argument_count; i++) {
10619        Handle<Object> obj(elements->get(i), isolate);
10620        if (obj->IsSmi()) {
10621          double_storage->set(j, Smi::cast(*obj)->value());
10622          j++;
10623        } else if (obj->IsNumber()) {
10624          double_storage->set(j, obj->Number());
10625          j++;
10626        } else {
10627          JSArray* array = JSArray::cast(*obj);
10628          uint32_t length = static_cast<uint32_t>(array->length()->Number());
10629          switch (array->map()->elements_kind()) {
10630            case FAST_HOLEY_DOUBLE_ELEMENTS:
10631            case FAST_DOUBLE_ELEMENTS: {
10632              // Empty array is FixedArray but not FixedDoubleArray.
10633              if (length == 0) break;
10634              FixedDoubleArray* elements =
10635                  FixedDoubleArray::cast(array->elements());
10636              for (uint32_t i = 0; i < length; i++) {
10637                if (elements->is_the_hole(i)) {
10638                  // TODO(jkummerow/verwaest): We could be a bit more clever
10639                  // here: Check if there are no elements/getters on the
10640                  // prototype chain, and if so, allow creation of a holey
10641                  // result array.
10642                  // Same thing below (holey smi case).
10643                  failure = true;
10644                  break;
10645                }
10646                double double_value = elements->get_scalar(i);
10647                double_storage->set(j, double_value);
10648                j++;
10649              }
10650              break;
10651            }
10652            case FAST_HOLEY_SMI_ELEMENTS:
10653            case FAST_SMI_ELEMENTS: {
10654              FixedArray* elements(
10655                  FixedArray::cast(array->elements()));
10656              for (uint32_t i = 0; i < length; i++) {
10657                Object* element = elements->get(i);
10658                if (element->IsTheHole()) {
10659                  failure = true;
10660                  break;
10661                }
10662                int32_t int_value = Smi::cast(element)->value();
10663                double_storage->set(j, int_value);
10664                j++;
10665              }
10666              break;
10667            }
10668            case FAST_HOLEY_ELEMENTS:
10669            case FAST_ELEMENTS:
10670              DCHECK_EQ(0, length);
10671              break;
10672            default:
10673              UNREACHABLE();
10674          }
10675        }
10676        if (failure) break;
10677      }
10678    }
10679    if (!failure) {
10680      Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10681      Smi* length = Smi::FromInt(j);
10682      Handle<Map> map;
10683      map = JSObject::GetElementsTransitionMap(array, kind);
10684      array->set_map(*map);
10685      array->set_length(length);
10686      array->set_elements(*storage);
10687      return *array;
10688    }
10689    // In case of failure, fall through.
10690  }
10691
10692  Handle<FixedArray> storage;
10693  if (fast_case) {
10694    // The backing storage array must have non-existing elements to preserve
10695    // holes across concat operations.
10696    storage = isolate->factory()->NewFixedArrayWithHoles(
10697        estimate_result_length);
10698  } else {
10699    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10700    uint32_t at_least_space_for = estimate_nof_elements +
10701                                  (estimate_nof_elements >> 2);
10702    storage = Handle<FixedArray>::cast(
10703        SeededNumberDictionary::New(isolate, at_least_space_for));
10704  }
10705
10706  ArrayConcatVisitor visitor(isolate, storage, fast_case);
10707
10708  for (int i = 0; i < argument_count; i++) {
10709    Handle<Object> obj(elements->get(i), isolate);
10710    if (obj->IsJSArray()) {
10711      Handle<JSArray> array = Handle<JSArray>::cast(obj);
10712      if (!IterateElements(isolate, array, &visitor)) {
10713        return isolate->heap()->exception();
10714      }
10715    } else {
10716      visitor.visit(0, obj);
10717      visitor.increase_index_offset(1);
10718    }
10719  }
10720
10721  if (visitor.exceeds_array_limit()) {
10722    THROW_NEW_ERROR_RETURN_FAILURE(
10723        isolate,
10724        NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0)));
10725  }
10726  return *visitor.ToArray();
10727}
10728
10729
10730// This will not allocate (flatten the string), but it may run
10731// very slowly for very deeply nested ConsStrings.  For debugging use only.
10732RUNTIME_FUNCTION(Runtime_GlobalPrint) {
10733  SealHandleScope shs(isolate);
10734  DCHECK(args.length() == 1);
10735
10736  CONVERT_ARG_CHECKED(String, string, 0);
10737  ConsStringIteratorOp op;
10738  StringCharacterStream stream(string, &op);
10739  while (stream.HasMore()) {
10740    uint16_t character = stream.GetNext();
10741    PrintF("%c", character);
10742  }
10743  return string;
10744}
10745
10746
10747// Moves all own elements of an object, that are below a limit, to positions
10748// starting at zero. All undefined values are placed after non-undefined values,
10749// and are followed by non-existing element. Does not change the length
10750// property.
10751// Returns the number of non-undefined elements collected.
10752// Returns -1 if hole removal is not supported by this method.
10753RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
10754  HandleScope scope(isolate);
10755  DCHECK(args.length() == 2);
10756  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
10757  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10758  return *JSObject::PrepareElementsForSort(object, limit);
10759}
10760
10761
10762// Move contents of argument 0 (an array) to argument 1 (an array)
10763RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
10764  HandleScope scope(isolate);
10765  DCHECK(args.length() == 2);
10766  CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0);
10767  CONVERT_ARG_HANDLE_CHECKED(JSArray, to, 1);
10768  JSObject::ValidateElements(from);
10769  JSObject::ValidateElements(to);
10770
10771  Handle<FixedArrayBase> new_elements(from->elements());
10772  ElementsKind from_kind = from->GetElementsKind();
10773  Handle<Map> new_map = JSObject::GetElementsTransitionMap(to, from_kind);
10774  JSObject::SetMapAndElements(to, new_map, new_elements);
10775  to->set_length(from->length());
10776
10777  JSObject::ResetElements(from);
10778  from->set_length(Smi::FromInt(0));
10779
10780  JSObject::ValidateElements(to);
10781  return *to;
10782}
10783
10784
10785// How many elements does this object/array have?
10786RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
10787  HandleScope scope(isolate);
10788  DCHECK(args.length() == 1);
10789  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
10790  Handle<FixedArrayBase> elements(array->elements(), isolate);
10791  SealHandleScope shs(isolate);
10792  if (elements->IsDictionary()) {
10793    int result =
10794        Handle<SeededNumberDictionary>::cast(elements)->NumberOfElements();
10795    return Smi::FromInt(result);
10796  } else {
10797    DCHECK(array->length()->IsSmi());
10798    // For packed elements, we know the exact number of elements
10799    int length = elements->length();
10800    ElementsKind kind = array->GetElementsKind();
10801    if (IsFastPackedElementsKind(kind)) {
10802      return Smi::FromInt(length);
10803    }
10804    // For holey elements, take samples from the buffer checking for holes
10805    // to generate the estimate.
10806    const int kNumberOfHoleCheckSamples = 97;
10807    int increment = (length < kNumberOfHoleCheckSamples)
10808                        ? 1
10809                        : static_cast<int>(length / kNumberOfHoleCheckSamples);
10810    ElementsAccessor* accessor = array->GetElementsAccessor();
10811    int holes = 0;
10812    for (int i = 0; i < length; i += increment) {
10813      if (!accessor->HasElement(array, array, i, elements)) {
10814        ++holes;
10815      }
10816    }
10817    int estimate = static_cast<int>((kNumberOfHoleCheckSamples - holes) /
10818                                    kNumberOfHoleCheckSamples * length);
10819    return Smi::FromInt(estimate);
10820  }
10821}
10822
10823
10824// Returns an array that tells you where in the [0, length) interval an array
10825// might have elements.  Can either return an array of keys (positive integers
10826// or undefined) or a number representing the positive length of an interval
10827// starting at index 0.
10828// Intervals can span over some keys that are not in the object.
10829RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
10830  HandleScope scope(isolate);
10831  DCHECK(args.length() == 2);
10832  CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10833  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10834  if (array->elements()->IsDictionary()) {
10835    Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10836    for (PrototypeIterator iter(isolate, array,
10837                                PrototypeIterator::START_AT_RECEIVER);
10838         !iter.IsAtEnd(); iter.Advance()) {
10839      if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||
10840          JSObject::cast(*PrototypeIterator::GetCurrent(iter))
10841              ->HasIndexedInterceptor()) {
10842        // Bail out if we find a proxy or interceptor, likely not worth
10843        // collecting keys in that case.
10844        return *isolate->factory()->NewNumberFromUint(length);
10845      }
10846      Handle<JSObject> current =
10847          Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
10848      Handle<FixedArray> current_keys =
10849          isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
10850      current->GetOwnElementKeys(*current_keys, NONE);
10851      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
10852          isolate, keys, FixedArray::UnionOfKeys(keys, current_keys));
10853    }
10854    // Erase any keys >= length.
10855    // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10856    // is changed to let this happen on the JS side.
10857    for (int i = 0; i < keys->length(); i++) {
10858      if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10859    }
10860    return *isolate->factory()->NewJSArrayWithElements(keys);
10861  } else {
10862    RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
10863                   array->HasFastDoubleElements());
10864    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10865    return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10866  }
10867}
10868
10869
10870RUNTIME_FUNCTION(Runtime_LookupAccessor) {
10871  HandleScope scope(isolate);
10872  DCHECK(args.length() == 3);
10873  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10874  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10875  CONVERT_SMI_ARG_CHECKED(flag, 2);
10876  AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10877  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10878  Handle<Object> result;
10879  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
10880      isolate, result,
10881      JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
10882  return *result;
10883}
10884
10885
10886RUNTIME_FUNCTION(Runtime_DebugBreak) {
10887  SealHandleScope shs(isolate);
10888  DCHECK(args.length() == 0);
10889  isolate->debug()->HandleDebugBreak();
10890  return isolate->heap()->undefined_value();
10891}
10892
10893
10894// Helper functions for wrapping and unwrapping stack frame ids.
10895static Smi* WrapFrameId(StackFrame::Id id) {
10896  DCHECK(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10897  return Smi::FromInt(id >> 2);
10898}
10899
10900
10901static StackFrame::Id UnwrapFrameId(int wrapped) {
10902  return static_cast<StackFrame::Id>(wrapped << 2);
10903}
10904
10905
10906// Adds a JavaScript function as a debug event listener.
10907// args[0]: debug event listener function to set or null or undefined for
10908//          clearing the event listener function
10909// args[1]: object supplied during callback
10910RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
10911  SealHandleScope shs(isolate);
10912  DCHECK(args.length() == 2);
10913  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10914                 args[0]->IsUndefined() ||
10915                 args[0]->IsNull());
10916  CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
10917  CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
10918  isolate->debug()->SetEventListener(callback, data);
10919
10920  return isolate->heap()->undefined_value();
10921}
10922
10923
10924RUNTIME_FUNCTION(Runtime_Break) {
10925  SealHandleScope shs(isolate);
10926  DCHECK(args.length() == 0);
10927  isolate->stack_guard()->RequestDebugBreak();
10928  return isolate->heap()->undefined_value();
10929}
10930
10931
10932static Handle<Object> DebugGetProperty(LookupIterator* it,
10933                                       bool* has_caught = NULL) {
10934  for (; it->IsFound(); it->Next()) {
10935    switch (it->state()) {
10936      case LookupIterator::NOT_FOUND:
10937      case LookupIterator::TRANSITION:
10938        UNREACHABLE();
10939      case LookupIterator::ACCESS_CHECK:
10940        // Ignore access checks.
10941        break;
10942      case LookupIterator::INTERCEPTOR:
10943      case LookupIterator::JSPROXY:
10944        return it->isolate()->factory()->undefined_value();
10945      case LookupIterator::ACCESSOR: {
10946        Handle<Object> accessors = it->GetAccessors();
10947        if (!accessors->IsAccessorInfo()) {
10948          return it->isolate()->factory()->undefined_value();
10949        }
10950        MaybeHandle<Object> maybe_result = JSObject::GetPropertyWithAccessor(
10951            it->GetReceiver(), it->name(), it->GetHolder<JSObject>(),
10952            accessors);
10953        Handle<Object> result;
10954        if (!maybe_result.ToHandle(&result)) {
10955          result = handle(it->isolate()->pending_exception(), it->isolate());
10956          it->isolate()->clear_pending_exception();
10957          if (has_caught != NULL) *has_caught = true;
10958        }
10959        return result;
10960      }
10961
10962      case LookupIterator::DATA:
10963        return it->GetDataValue();
10964    }
10965  }
10966
10967  return it->isolate()->factory()->undefined_value();
10968}
10969
10970
10971// Get debugger related details for an object property, in the following format:
10972// 0: Property value
10973// 1: Property details
10974// 2: Property value is exception
10975// 3: Getter function if defined
10976// 4: Setter function if defined
10977// Items 2-4 are only filled if the property has either a getter or a setter.
10978RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
10979  HandleScope scope(isolate);
10980
10981  DCHECK(args.length() == 2);
10982
10983  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10984  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10985
10986  // Make sure to set the current context to the context before the debugger was
10987  // entered (if the debugger is entered). The reason for switching context here
10988  // is that for some property lookups (accessors and interceptors) callbacks
10989  // into the embedding application can occour, and the embedding application
10990  // could have the assumption that its own native context is the current
10991  // context and not some internal debugger context.
10992  SaveContext save(isolate);
10993  if (isolate->debug()->in_debug_scope()) {
10994    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10995  }
10996
10997  // Check if the name is trivially convertible to an index and get the element
10998  // if so.
10999  uint32_t index;
11000  if (name->AsArrayIndex(&index)) {
11001    Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
11002    Handle<Object> element_or_char;
11003    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
11004        isolate, element_or_char,
11005        Runtime::GetElementOrCharAt(isolate, obj, index));
11006    details->set(0, *element_or_char);
11007    details->set(
11008        1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
11009    return *isolate->factory()->NewJSArrayWithElements(details);
11010  }
11011
11012  LookupIterator it(obj, name, LookupIterator::HIDDEN);
11013  bool has_caught = false;
11014  Handle<Object> value = DebugGetProperty(&it, &has_caught);
11015  if (!it.IsFound()) return isolate->heap()->undefined_value();
11016
11017  Handle<Object> maybe_pair;
11018  if (it.state() == LookupIterator::ACCESSOR) {
11019    maybe_pair = it.GetAccessors();
11020  }
11021
11022  // If the callback object is a fixed array then it contains JavaScript
11023  // getter and/or setter.
11024  bool has_js_accessors = !maybe_pair.is_null() && maybe_pair->IsAccessorPair();
11025  Handle<FixedArray> details =
11026      isolate->factory()->NewFixedArray(has_js_accessors ? 6 : 3);
11027  details->set(0, *value);
11028  // TODO(verwaest): Get rid of this random way of handling interceptors.
11029  PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
11030                          ? PropertyDetails(NONE, NORMAL, 0)
11031                          : it.property_details();
11032  details->set(1, d.AsSmi());
11033  details->set(
11034      2, isolate->heap()->ToBoolean(it.state() == LookupIterator::INTERCEPTOR));
11035  if (has_js_accessors) {
11036    AccessorPair* accessors = AccessorPair::cast(*maybe_pair);
11037    details->set(3, isolate->heap()->ToBoolean(has_caught));
11038    details->set(4, accessors->GetComponent(ACCESSOR_GETTER));
11039    details->set(5, accessors->GetComponent(ACCESSOR_SETTER));
11040  }
11041
11042  return *isolate->factory()->NewJSArrayWithElements(details);
11043}
11044
11045
11046RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
11047  HandleScope scope(isolate);
11048
11049  DCHECK(args.length() == 2);
11050
11051  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11052  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11053
11054  LookupIterator it(obj, name);
11055  return *DebugGetProperty(&it);
11056}
11057
11058
11059// Return the property type calculated from the property details.
11060// args[0]: smi with property details.
11061RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
11062  SealHandleScope shs(isolate);
11063  DCHECK(args.length() == 1);
11064  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11065  return Smi::FromInt(static_cast<int>(details.type()));
11066}
11067
11068
11069// Return the property attribute calculated from the property details.
11070// args[0]: smi with property details.
11071RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
11072  SealHandleScope shs(isolate);
11073  DCHECK(args.length() == 1);
11074  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11075  return Smi::FromInt(static_cast<int>(details.attributes()));
11076}
11077
11078
11079// Return the property insertion index calculated from the property details.
11080// args[0]: smi with property details.
11081RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
11082  SealHandleScope shs(isolate);
11083  DCHECK(args.length() == 1);
11084  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11085  // TODO(verwaest): Depends on the type of details.
11086  return Smi::FromInt(details.dictionary_index());
11087}
11088
11089
11090// Return property value from named interceptor.
11091// args[0]: object
11092// args[1]: property name
11093RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
11094  HandleScope scope(isolate);
11095  DCHECK(args.length() == 2);
11096  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11097  RUNTIME_ASSERT(obj->HasNamedInterceptor());
11098  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11099
11100  Handle<Object> result;
11101  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
11102      isolate, result, JSObject::GetProperty(obj, name));
11103  return *result;
11104}
11105
11106
11107// Return element value from indexed interceptor.
11108// args[0]: object
11109// args[1]: index
11110RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
11111  HandleScope scope(isolate);
11112  DCHECK(args.length() == 2);
11113  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11114  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
11115  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
11116  Handle<Object> result;
11117  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
11118      isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index));
11119  return *result;
11120}
11121
11122
11123static bool CheckExecutionState(Isolate* isolate, int break_id) {
11124  return !isolate->debug()->debug_context().is_null() &&
11125         isolate->debug()->break_id() != 0 &&
11126         isolate->debug()->break_id() == break_id;
11127}
11128
11129
11130RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
11131  SealHandleScope shs(isolate);
11132  DCHECK(args.length() == 1);
11133  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11134  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11135  return isolate->heap()->true_value();
11136}
11137
11138
11139RUNTIME_FUNCTION(Runtime_GetFrameCount) {
11140  HandleScope scope(isolate);
11141  DCHECK(args.length() == 1);
11142  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11143  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11144
11145  // Count all frames which are relevant to debugging stack trace.
11146  int n = 0;
11147  StackFrame::Id id = isolate->debug()->break_frame_id();
11148  if (id == StackFrame::NO_ID) {
11149    // If there is no JavaScript stack frame count is 0.
11150    return Smi::FromInt(0);
11151  }
11152
11153  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
11154    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
11155    it.frame()->Summarize(&frames);
11156    for (int i = frames.length() - 1; i >= 0; i--) {
11157      // Omit functions from native scripts.
11158      if (!frames[i].function()->IsFromNativeScript()) n++;
11159    }
11160  }
11161  return Smi::FromInt(n);
11162}
11163
11164
11165class FrameInspector {
11166 public:
11167  FrameInspector(JavaScriptFrame* frame,
11168                 int inlined_jsframe_index,
11169                 Isolate* isolate)
11170      : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11171    // Calculate the deoptimized frame.
11172    if (frame->is_optimized()) {
11173      deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11174          frame, inlined_jsframe_index, isolate);
11175    }
11176    has_adapted_arguments_ = frame_->has_adapted_arguments();
11177    is_bottommost_ = inlined_jsframe_index == 0;
11178    is_optimized_ = frame_->is_optimized();
11179  }
11180
11181  ~FrameInspector() {
11182    // Get rid of the calculated deoptimized frame if any.
11183    if (deoptimized_frame_ != NULL) {
11184      Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11185                                                  isolate_);
11186    }
11187  }
11188
11189  int GetParametersCount() {
11190    return is_optimized_
11191        ? deoptimized_frame_->parameters_count()
11192        : frame_->ComputeParametersCount();
11193  }
11194  int expression_count() { return deoptimized_frame_->expression_count(); }
11195  Object* GetFunction() {
11196    return is_optimized_
11197        ? deoptimized_frame_->GetFunction()
11198        : frame_->function();
11199  }
11200  Object* GetParameter(int index) {
11201    return is_optimized_
11202        ? deoptimized_frame_->GetParameter(index)
11203        : frame_->GetParameter(index);
11204  }
11205  Object* GetExpression(int index) {
11206    return is_optimized_
11207        ? deoptimized_frame_->GetExpression(index)
11208        : frame_->GetExpression(index);
11209  }
11210  int GetSourcePosition() {
11211    return is_optimized_
11212        ? deoptimized_frame_->GetSourcePosition()
11213        : frame_->LookupCode()->SourcePosition(frame_->pc());
11214  }
11215  bool IsConstructor() {
11216    return is_optimized_ && !is_bottommost_
11217        ? deoptimized_frame_->HasConstructStub()
11218        : frame_->IsConstructor();
11219  }
11220  Object* GetContext() {
11221    return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context();
11222  }
11223
11224  // To inspect all the provided arguments the frame might need to be
11225  // replaced with the arguments frame.
11226  void SetArgumentsFrame(JavaScriptFrame* frame) {
11227    DCHECK(has_adapted_arguments_);
11228    frame_ = frame;
11229    is_optimized_ = frame_->is_optimized();
11230    DCHECK(!is_optimized_);
11231  }
11232
11233 private:
11234  JavaScriptFrame* frame_;
11235  DeoptimizedFrameInfo* deoptimized_frame_;
11236  Isolate* isolate_;
11237  bool is_optimized_;
11238  bool is_bottommost_;
11239  bool has_adapted_arguments_;
11240
11241  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11242};
11243
11244
11245static const int kFrameDetailsFrameIdIndex = 0;
11246static const int kFrameDetailsReceiverIndex = 1;
11247static const int kFrameDetailsFunctionIndex = 2;
11248static const int kFrameDetailsArgumentCountIndex = 3;
11249static const int kFrameDetailsLocalCountIndex = 4;
11250static const int kFrameDetailsSourcePositionIndex = 5;
11251static const int kFrameDetailsConstructCallIndex = 6;
11252static const int kFrameDetailsAtReturnIndex = 7;
11253static const int kFrameDetailsFlagsIndex = 8;
11254static const int kFrameDetailsFirstDynamicIndex = 9;
11255
11256
11257static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11258                                             JavaScriptFrame* frame) {
11259  SaveContext* save = isolate->save_context();
11260  while (save != NULL && !save->IsBelowFrame(frame)) {
11261    save = save->prev();
11262  }
11263  DCHECK(save != NULL);
11264  return save;
11265}
11266
11267
11268// Advances the iterator to the frame that matches the index and returns the
11269// inlined frame index, or -1 if not found.  Skips native JS functions.
11270static int FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, int index) {
11271  int count = -1;
11272  for (; !it->done(); it->Advance()) {
11273    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
11274    it->frame()->Summarize(&frames);
11275    for (int i = frames.length() - 1; i >= 0; i--) {
11276      // Omit functions from native scripts.
11277      if (frames[i].function()->IsFromNativeScript()) continue;
11278      if (++count == index) return i;
11279    }
11280  }
11281  return -1;
11282}
11283
11284
11285// Return an array with frame details
11286// args[0]: number: break id
11287// args[1]: number: frame index
11288//
11289// The array returned contains the following information:
11290// 0: Frame id
11291// 1: Receiver
11292// 2: Function
11293// 3: Argument count
11294// 4: Local count
11295// 5: Source position
11296// 6: Constructor call
11297// 7: Is at return
11298// 8: Flags
11299// Arguments name, value
11300// Locals name, value
11301// Return value if any
11302RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
11303  HandleScope scope(isolate);
11304  DCHECK(args.length() == 2);
11305  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11306  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11307
11308  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11309  Heap* heap = isolate->heap();
11310
11311  // Find the relevant frame with the requested index.
11312  StackFrame::Id id = isolate->debug()->break_frame_id();
11313  if (id == StackFrame::NO_ID) {
11314    // If there are no JavaScript stack frames return undefined.
11315    return heap->undefined_value();
11316  }
11317
11318  JavaScriptFrameIterator it(isolate, id);
11319  // Inlined frame index in optimized frame, starting from outer function.
11320  int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index);
11321  if (inlined_jsframe_index == -1) return heap->undefined_value();
11322
11323  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11324  bool is_optimized = it.frame()->is_optimized();
11325
11326  // Traverse the saved contexts chain to find the active context for the
11327  // selected frame.
11328  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11329
11330  // Get the frame id.
11331  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11332
11333  // Find source position in unoptimized code.
11334  int position = frame_inspector.GetSourcePosition();
11335
11336  // Check for constructor frame.
11337  bool constructor = frame_inspector.IsConstructor();
11338
11339  // Get scope info and read from it for local variable information.
11340  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11341  Handle<SharedFunctionInfo> shared(function->shared());
11342  Handle<ScopeInfo> scope_info(shared->scope_info());
11343  DCHECK(*scope_info != ScopeInfo::Empty(isolate));
11344
11345  // Get the locals names and values into a temporary array.
11346  int local_count = scope_info->LocalCount();
11347  for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
11348    // Hide compiler-introduced temporary variables, whether on the stack or on
11349    // the context.
11350    if (scope_info->LocalIsSynthetic(slot))
11351      local_count--;
11352  }
11353
11354  Handle<FixedArray> locals =
11355      isolate->factory()->NewFixedArray(local_count * 2);
11356
11357  // Fill in the values of the locals.
11358  int local = 0;
11359  int i = 0;
11360  for (; i < scope_info->StackLocalCount(); ++i) {
11361    // Use the value from the stack.
11362    if (scope_info->LocalIsSynthetic(i))
11363      continue;
11364    locals->set(local * 2, scope_info->LocalName(i));
11365    locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
11366    local++;
11367  }
11368  if (local < local_count) {
11369    // Get the context containing declarations.
11370    Handle<Context> context(
11371        Context::cast(frame_inspector.GetContext())->declaration_context());
11372    for (; i < scope_info->LocalCount(); ++i) {
11373      if (scope_info->LocalIsSynthetic(i))
11374        continue;
11375      Handle<String> name(scope_info->LocalName(i));
11376      VariableMode mode;
11377      InitializationFlag init_flag;
11378      MaybeAssignedFlag maybe_assigned_flag;
11379      locals->set(local * 2, *name);
11380      int context_slot_index = ScopeInfo::ContextSlotIndex(
11381          scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
11382      Object* value = context->get(context_slot_index);
11383      locals->set(local * 2 + 1, value);
11384      local++;
11385    }
11386  }
11387
11388  // Check whether this frame is positioned at return. If not top
11389  // frame or if the frame is optimized it cannot be at a return.
11390  bool at_return = false;
11391  if (!is_optimized && index == 0) {
11392    at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11393  }
11394
11395  // If positioned just before return find the value to be returned and add it
11396  // to the frame information.
11397  Handle<Object> return_value = isolate->factory()->undefined_value();
11398  if (at_return) {
11399    StackFrameIterator it2(isolate);
11400    Address internal_frame_sp = NULL;
11401    while (!it2.done()) {
11402      if (it2.frame()->is_internal()) {
11403        internal_frame_sp = it2.frame()->sp();
11404      } else {
11405        if (it2.frame()->is_java_script()) {
11406          if (it2.frame()->id() == it.frame()->id()) {
11407            // The internal frame just before the JavaScript frame contains the
11408            // value to return on top. A debug break at return will create an
11409            // internal frame to store the return value (eax/rax/r0) before
11410            // entering the debug break exit frame.
11411            if (internal_frame_sp != NULL) {
11412              return_value =
11413                  Handle<Object>(Memory::Object_at(internal_frame_sp),
11414                                 isolate);
11415              break;
11416            }
11417          }
11418        }
11419
11420        // Indicate that the previous frame was not an internal frame.
11421        internal_frame_sp = NULL;
11422      }
11423      it2.Advance();
11424    }
11425  }
11426
11427  // Now advance to the arguments adapter frame (if any). It contains all
11428  // the provided parameters whereas the function frame always have the number
11429  // of arguments matching the functions parameters. The rest of the
11430  // information (except for what is collected above) is the same.
11431  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11432    it.AdvanceToArgumentsFrame();
11433    frame_inspector.SetArgumentsFrame(it.frame());
11434  }
11435
11436  // Find the number of arguments to fill. At least fill the number of
11437  // parameters for the function and fill more if more parameters are provided.
11438  int argument_count = scope_info->ParameterCount();
11439  if (argument_count < frame_inspector.GetParametersCount()) {
11440    argument_count = frame_inspector.GetParametersCount();
11441  }
11442
11443  // Calculate the size of the result.
11444  int details_size = kFrameDetailsFirstDynamicIndex +
11445                     2 * (argument_count + local_count) +
11446                     (at_return ? 1 : 0);
11447  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11448
11449  // Add the frame id.
11450  details->set(kFrameDetailsFrameIdIndex, *frame_id);
11451
11452  // Add the function (same as in function frame).
11453  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11454
11455  // Add the arguments count.
11456  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11457
11458  // Add the locals count
11459  details->set(kFrameDetailsLocalCountIndex,
11460               Smi::FromInt(local_count));
11461
11462  // Add the source position.
11463  if (position != RelocInfo::kNoPosition) {
11464    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11465  } else {
11466    details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11467  }
11468
11469  // Add the constructor information.
11470  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11471
11472  // Add the at return information.
11473  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11474
11475  // Add flags to indicate information on whether this frame is
11476  //   bit 0: invoked in the debugger context.
11477  //   bit 1: optimized frame.
11478  //   bit 2: inlined in optimized frame
11479  int flags = 0;
11480  if (*save->context() == *isolate->debug()->debug_context()) {
11481    flags |= 1 << 0;
11482  }
11483  if (is_optimized) {
11484    flags |= 1 << 1;
11485    flags |= inlined_jsframe_index << 2;
11486  }
11487  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11488
11489  // Fill the dynamic part.
11490  int details_index = kFrameDetailsFirstDynamicIndex;
11491
11492  // Add arguments name and value.
11493  for (int i = 0; i < argument_count; i++) {
11494    // Name of the argument.
11495    if (i < scope_info->ParameterCount()) {
11496      details->set(details_index++, scope_info->ParameterName(i));
11497    } else {
11498      details->set(details_index++, heap->undefined_value());
11499    }
11500
11501    // Parameter value.
11502    if (i < frame_inspector.GetParametersCount()) {
11503      // Get the value from the stack.
11504      details->set(details_index++, frame_inspector.GetParameter(i));
11505    } else {
11506      details->set(details_index++, heap->undefined_value());
11507    }
11508  }
11509
11510  // Add locals name and value from the temporary copy from the function frame.
11511  for (int i = 0; i < local_count * 2; i++) {
11512    details->set(details_index++, locals->get(i));
11513  }
11514
11515  // Add the value being returned.
11516  if (at_return) {
11517    details->set(details_index++, *return_value);
11518  }
11519
11520  // Add the receiver (same as in function frame).
11521  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11522  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11523  Handle<Object> receiver(it.frame()->receiver(), isolate);
11524  if (!receiver->IsJSObject() &&
11525      shared->strict_mode() == SLOPPY &&
11526      !function->IsBuiltin()) {
11527    // If the receiver is not a JSObject and the function is not a
11528    // builtin or strict-mode we have hit an optimization where a
11529    // value object is not converted into a wrapped JS objects. To
11530    // hide this optimization from the debugger, we wrap the receiver
11531    // by creating correct wrapper object based on the calling frame's
11532    // native context.
11533    it.Advance();
11534    if (receiver->IsUndefined()) {
11535      receiver = handle(function->global_proxy());
11536    } else {
11537      Context* context = Context::cast(it.frame()->context());
11538      Handle<Context> native_context(Context::cast(context->native_context()));
11539      if (!Object::ToObject(isolate, receiver, native_context)
11540               .ToHandle(&receiver)) {
11541        // This only happens if the receiver is forcibly set in %_CallFunction.
11542        return heap->undefined_value();
11543      }
11544    }
11545  }
11546  details->set(kFrameDetailsReceiverIndex, *receiver);
11547
11548  DCHECK_EQ(details_size, details_index);
11549  return *isolate->factory()->NewJSArrayWithElements(details);
11550}
11551
11552
11553static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
11554                                              Handle<String> parameter_name) {
11555  VariableMode mode;
11556  InitializationFlag init_flag;
11557  MaybeAssignedFlag maybe_assigned_flag;
11558  return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag,
11559                                     &maybe_assigned_flag) != -1;
11560}
11561
11562
11563// Create a plain JSObject which materializes the local scope for the specified
11564// frame.
11565MUST_USE_RESULT
11566static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
11567    Isolate* isolate,
11568    Handle<JSObject> target,
11569    Handle<JSFunction> function,
11570    FrameInspector* frame_inspector) {
11571  Handle<SharedFunctionInfo> shared(function->shared());
11572  Handle<ScopeInfo> scope_info(shared->scope_info());
11573
11574  // First fill all parameters.
11575  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11576    // Do not materialize the parameter if it is shadowed by a context local.
11577    Handle<String> name(scope_info->ParameterName(i));
11578    if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
11579
11580    HandleScope scope(isolate);
11581    Handle<Object> value(i < frame_inspector->GetParametersCount()
11582                             ? frame_inspector->GetParameter(i)
11583                             : isolate->heap()->undefined_value(),
11584                         isolate);
11585    DCHECK(!value->IsTheHole());
11586
11587    RETURN_ON_EXCEPTION(
11588        isolate,
11589        Runtime::SetObjectProperty(isolate, target, name, value, SLOPPY),
11590        JSObject);
11591  }
11592
11593  // Second fill all stack locals.
11594  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11595    if (scope_info->LocalIsSynthetic(i)) continue;
11596    Handle<String> name(scope_info->StackLocalName(i));
11597    Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11598    if (value->IsTheHole()) continue;
11599
11600    RETURN_ON_EXCEPTION(
11601        isolate,
11602        Runtime::SetObjectProperty(isolate, target, name, value, SLOPPY),
11603        JSObject);
11604  }
11605
11606  return target;
11607}
11608
11609
11610static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11611                                                    Handle<JSObject> target,
11612                                                    Handle<JSFunction> function,
11613                                                    JavaScriptFrame* frame,
11614                                                    int inlined_jsframe_index) {
11615  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11616    // Optimized frames are not supported.
11617    // TODO(yangguo): make sure all code deoptimized when debugger is active
11618    //                and assert that this cannot happen.
11619    return;
11620  }
11621
11622  Handle<SharedFunctionInfo> shared(function->shared());
11623  Handle<ScopeInfo> scope_info(shared->scope_info());
11624
11625  // Parameters.
11626  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11627    // Shadowed parameters were not materialized.
11628    Handle<String> name(scope_info->ParameterName(i));
11629    if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
11630
11631    DCHECK(!frame->GetParameter(i)->IsTheHole());
11632    HandleScope scope(isolate);
11633    Handle<Object> value =
11634        Object::GetPropertyOrElement(target, name).ToHandleChecked();
11635    frame->SetParameterValue(i, *value);
11636  }
11637
11638  // Stack locals.
11639  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11640    if (scope_info->LocalIsSynthetic(i)) continue;
11641    if (frame->GetExpression(i)->IsTheHole()) continue;
11642    HandleScope scope(isolate);
11643    Handle<Object> value = Object::GetPropertyOrElement(
11644        target,
11645        handle(scope_info->StackLocalName(i), isolate)).ToHandleChecked();
11646    frame->SetExpression(i, *value);
11647  }
11648}
11649
11650
11651MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext(
11652    Isolate* isolate,
11653    Handle<JSObject> target,
11654    Handle<JSFunction> function,
11655    JavaScriptFrame* frame) {
11656  HandleScope scope(isolate);
11657  Handle<SharedFunctionInfo> shared(function->shared());
11658  Handle<ScopeInfo> scope_info(shared->scope_info());
11659
11660  if (!scope_info->HasContext()) return target;
11661
11662  // Third fill all context locals.
11663  Handle<Context> frame_context(Context::cast(frame->context()));
11664  Handle<Context> function_context(frame_context->declaration_context());
11665  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11666          scope_info, function_context, target)) {
11667    return MaybeHandle<JSObject>();
11668  }
11669
11670  // Finally copy any properties from the function context extension.
11671  // These will be variables introduced by eval.
11672  if (function_context->closure() == *function) {
11673    if (function_context->has_extension() &&
11674        !function_context->IsNativeContext()) {
11675      Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11676      Handle<FixedArray> keys;
11677      ASSIGN_RETURN_ON_EXCEPTION(
11678          isolate, keys,
11679          JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
11680          JSObject);
11681
11682      for (int i = 0; i < keys->length(); i++) {
11683        // Names of variables introduced by eval are strings.
11684        DCHECK(keys->get(i)->IsString());
11685        Handle<String> key(String::cast(keys->get(i)));
11686        Handle<Object> value;
11687        ASSIGN_RETURN_ON_EXCEPTION(
11688            isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
11689        RETURN_ON_EXCEPTION(
11690            isolate,
11691            Runtime::SetObjectProperty(isolate, target, key, value, SLOPPY),
11692            JSObject);
11693      }
11694    }
11695  }
11696
11697  return target;
11698}
11699
11700
11701MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope(
11702    Isolate* isolate,
11703    JavaScriptFrame* frame,
11704    int inlined_jsframe_index) {
11705  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11706  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11707
11708  Handle<JSObject> local_scope =
11709      isolate->factory()->NewJSObject(isolate->object_function());
11710  ASSIGN_RETURN_ON_EXCEPTION(
11711      isolate, local_scope,
11712      MaterializeStackLocalsWithFrameInspector(
11713          isolate, local_scope, function, &frame_inspector),
11714      JSObject);
11715
11716  return MaterializeLocalContext(isolate, local_scope, function, frame);
11717}
11718
11719
11720// Set the context local variable value.
11721static bool SetContextLocalValue(Isolate* isolate,
11722                                 Handle<ScopeInfo> scope_info,
11723                                 Handle<Context> context,
11724                                 Handle<String> variable_name,
11725                                 Handle<Object> new_value) {
11726  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11727    Handle<String> next_name(scope_info->ContextLocalName(i));
11728    if (String::Equals(variable_name, next_name)) {
11729      VariableMode mode;
11730      InitializationFlag init_flag;
11731      MaybeAssignedFlag maybe_assigned_flag;
11732      int context_index = ScopeInfo::ContextSlotIndex(
11733          scope_info, next_name, &mode, &init_flag, &maybe_assigned_flag);
11734      context->set(context_index, *new_value);
11735      return true;
11736    }
11737  }
11738
11739  return false;
11740}
11741
11742
11743static bool SetLocalVariableValue(Isolate* isolate,
11744                                  JavaScriptFrame* frame,
11745                                  int inlined_jsframe_index,
11746                                  Handle<String> variable_name,
11747                                  Handle<Object> new_value) {
11748  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11749    // Optimized frames are not supported.
11750    return false;
11751  }
11752
11753  Handle<JSFunction> function(frame->function());
11754  Handle<SharedFunctionInfo> shared(function->shared());
11755  Handle<ScopeInfo> scope_info(shared->scope_info());
11756
11757  bool default_result = false;
11758
11759  // Parameters.
11760  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11761    HandleScope scope(isolate);
11762    if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
11763      frame->SetParameterValue(i, *new_value);
11764      // Argument might be shadowed in heap context, don't stop here.
11765      default_result = true;
11766    }
11767  }
11768
11769  // Stack locals.
11770  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11771    HandleScope scope(isolate);
11772    if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
11773      frame->SetExpression(i, *new_value);
11774      return true;
11775    }
11776  }
11777
11778  if (scope_info->HasContext()) {
11779    // Context locals.
11780    Handle<Context> frame_context(Context::cast(frame->context()));
11781    Handle<Context> function_context(frame_context->declaration_context());
11782    if (SetContextLocalValue(
11783        isolate, scope_info, function_context, variable_name, new_value)) {
11784      return true;
11785    }
11786
11787    // Function context extension. These are variables introduced by eval.
11788    if (function_context->closure() == *function) {
11789      if (function_context->has_extension() &&
11790          !function_context->IsNativeContext()) {
11791        Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11792
11793        Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
11794        DCHECK(maybe.has_value);
11795        if (maybe.value) {
11796          // We don't expect this to do anything except replacing
11797          // property value.
11798          Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11799                                     SLOPPY).Assert();
11800          return true;
11801        }
11802      }
11803    }
11804  }
11805
11806  return default_result;
11807}
11808
11809
11810// Create a plain JSObject which materializes the closure content for the
11811// context.
11812MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure(
11813    Isolate* isolate,
11814    Handle<Context> context) {
11815  DCHECK(context->IsFunctionContext());
11816
11817  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11818  Handle<ScopeInfo> scope_info(shared->scope_info());
11819
11820  // Allocate and initialize a JSObject with all the content of this function
11821  // closure.
11822  Handle<JSObject> closure_scope =
11823      isolate->factory()->NewJSObject(isolate->object_function());
11824
11825  // Fill all context locals to the context extension.
11826  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11827          scope_info, context, closure_scope)) {
11828    return MaybeHandle<JSObject>();
11829  }
11830
11831  // Finally copy any properties from the function context extension. This will
11832  // be variables introduced by eval.
11833  if (context->has_extension()) {
11834    Handle<JSObject> ext(JSObject::cast(context->extension()));
11835    Handle<FixedArray> keys;
11836    ASSIGN_RETURN_ON_EXCEPTION(
11837        isolate, keys,
11838        JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), JSObject);
11839
11840    for (int i = 0; i < keys->length(); i++) {
11841      HandleScope scope(isolate);
11842      // Names of variables introduced by eval are strings.
11843      DCHECK(keys->get(i)->IsString());
11844      Handle<String> key(String::cast(keys->get(i)));
11845      Handle<Object> value;
11846      ASSIGN_RETURN_ON_EXCEPTION(
11847          isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
11848      RETURN_ON_EXCEPTION(
11849          isolate,
11850          Runtime::DefineObjectProperty(closure_scope, key, value, NONE),
11851          JSObject);
11852    }
11853  }
11854
11855  return closure_scope;
11856}
11857
11858
11859// This method copies structure of MaterializeClosure method above.
11860static bool SetClosureVariableValue(Isolate* isolate,
11861                                    Handle<Context> context,
11862                                    Handle<String> variable_name,
11863                                    Handle<Object> new_value) {
11864  DCHECK(context->IsFunctionContext());
11865
11866  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11867  Handle<ScopeInfo> scope_info(shared->scope_info());
11868
11869  // Context locals to the context extension.
11870  if (SetContextLocalValue(
11871          isolate, scope_info, context, variable_name, new_value)) {
11872    return true;
11873  }
11874
11875  // Properties from the function context extension. This will
11876  // be variables introduced by eval.
11877  if (context->has_extension()) {
11878    Handle<JSObject> ext(JSObject::cast(context->extension()));
11879    Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
11880    DCHECK(maybe.has_value);
11881    if (maybe.value) {
11882      // We don't expect this to do anything except replacing property value.
11883      Runtime::DefineObjectProperty(
11884          ext, variable_name, new_value, NONE).Assert();
11885      return true;
11886    }
11887  }
11888
11889  return false;
11890}
11891
11892
11893// Create a plain JSObject which materializes the scope for the specified
11894// catch context.
11895MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope(
11896    Isolate* isolate,
11897    Handle<Context> context) {
11898  DCHECK(context->IsCatchContext());
11899  Handle<String> name(String::cast(context->extension()));
11900  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11901                               isolate);
11902  Handle<JSObject> catch_scope =
11903      isolate->factory()->NewJSObject(isolate->object_function());
11904  RETURN_ON_EXCEPTION(
11905      isolate,
11906      Runtime::DefineObjectProperty(catch_scope, name, thrown_object, NONE),
11907      JSObject);
11908  return catch_scope;
11909}
11910
11911
11912static bool SetCatchVariableValue(Isolate* isolate,
11913                                  Handle<Context> context,
11914                                  Handle<String> variable_name,
11915                                  Handle<Object> new_value) {
11916  DCHECK(context->IsCatchContext());
11917  Handle<String> name(String::cast(context->extension()));
11918  if (!String::Equals(name, variable_name)) {
11919    return false;
11920  }
11921  context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11922  return true;
11923}
11924
11925
11926// Create a plain JSObject which materializes the block scope for the specified
11927// block context.
11928MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope(
11929    Isolate* isolate,
11930    Handle<Context> context) {
11931  DCHECK(context->IsBlockContext());
11932  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11933
11934  // Allocate and initialize a JSObject with all the arguments, stack locals
11935  // heap locals and extension properties of the debugged function.
11936  Handle<JSObject> block_scope =
11937      isolate->factory()->NewJSObject(isolate->object_function());
11938
11939  // Fill all context locals.
11940  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11941          scope_info, context, block_scope)) {
11942    return MaybeHandle<JSObject>();
11943  }
11944
11945  return block_scope;
11946}
11947
11948
11949// Create a plain JSObject which materializes the module scope for the specified
11950// module context.
11951MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope(
11952    Isolate* isolate,
11953    Handle<Context> context) {
11954  DCHECK(context->IsModuleContext());
11955  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11956
11957  // Allocate and initialize a JSObject with all the members of the debugged
11958  // module.
11959  Handle<JSObject> module_scope =
11960      isolate->factory()->NewJSObject(isolate->object_function());
11961
11962  // Fill all context locals.
11963  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11964          scope_info, context, module_scope)) {
11965    return MaybeHandle<JSObject>();
11966  }
11967
11968  return module_scope;
11969}
11970
11971
11972// Iterate over the actual scopes visible from a stack frame or from a closure.
11973// The iteration proceeds from the innermost visible nested scope outwards.
11974// All scopes are backed by an actual context except the local scope,
11975// which is inserted "artificially" in the context chain.
11976class ScopeIterator {
11977 public:
11978  enum ScopeType {
11979    ScopeTypeGlobal = 0,
11980    ScopeTypeLocal,
11981    ScopeTypeWith,
11982    ScopeTypeClosure,
11983    ScopeTypeCatch,
11984    ScopeTypeBlock,
11985    ScopeTypeModule
11986  };
11987
11988  ScopeIterator(Isolate* isolate,
11989                JavaScriptFrame* frame,
11990                int inlined_jsframe_index,
11991                bool ignore_nested_scopes = false)
11992    : isolate_(isolate),
11993      frame_(frame),
11994      inlined_jsframe_index_(inlined_jsframe_index),
11995      function_(frame->function()),
11996      context_(Context::cast(frame->context())),
11997      nested_scope_chain_(4),
11998      failed_(false) {
11999
12000    // Catch the case when the debugger stops in an internal function.
12001    Handle<SharedFunctionInfo> shared_info(function_->shared());
12002    Handle<ScopeInfo> scope_info(shared_info->scope_info());
12003    if (shared_info->script() == isolate->heap()->undefined_value()) {
12004      while (context_->closure() == *function_) {
12005        context_ = Handle<Context>(context_->previous(), isolate_);
12006      }
12007      return;
12008    }
12009
12010    // Get the debug info (create it if it does not exist).
12011    if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
12012      // Return if ensuring debug info failed.
12013      return;
12014    }
12015
12016    // Currently it takes too much time to find nested scopes due to script
12017    // parsing. Sometimes we want to run the ScopeIterator as fast as possible
12018    // (for example, while collecting async call stacks on every
12019    // addEventListener call), even if we drop some nested scopes.
12020    // Later we may optimize getting the nested scopes (cache the result?)
12021    // and include nested scopes into the "fast" iteration case as well.
12022    if (!ignore_nested_scopes) {
12023      Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
12024
12025      // Find the break point where execution has stopped.
12026      BreakLocationIterator break_location_iterator(debug_info,
12027                                                    ALL_BREAK_LOCATIONS);
12028      // pc points to the instruction after the current one, possibly a break
12029      // location as well. So the "- 1" to exclude it from the search.
12030      break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12031
12032      // Within the return sequence at the moment it is not possible to
12033      // get a source position which is consistent with the current scope chain.
12034      // Thus all nested with, catch and block contexts are skipped and we only
12035      // provide the function scope.
12036      ignore_nested_scopes = break_location_iterator.IsExit();
12037    }
12038
12039    if (ignore_nested_scopes) {
12040      if (scope_info->HasContext()) {
12041        context_ = Handle<Context>(context_->declaration_context(), isolate_);
12042      } else {
12043        while (context_->closure() == *function_) {
12044          context_ = Handle<Context>(context_->previous(), isolate_);
12045        }
12046      }
12047      if (scope_info->scope_type() == FUNCTION_SCOPE) {
12048        nested_scope_chain_.Add(scope_info);
12049      }
12050    } else {
12051      // Reparse the code and analyze the scopes.
12052      Handle<Script> script(Script::cast(shared_info->script()));
12053      Scope* scope = NULL;
12054
12055      // Check whether we are in global, eval or function code.
12056      Handle<ScopeInfo> scope_info(shared_info->scope_info());
12057      if (scope_info->scope_type() != FUNCTION_SCOPE) {
12058        // Global or eval code.
12059        CompilationInfoWithZone info(script);
12060        if (scope_info->scope_type() == GLOBAL_SCOPE) {
12061          info.MarkAsGlobal();
12062        } else {
12063          DCHECK(scope_info->scope_type() == EVAL_SCOPE);
12064          info.MarkAsEval();
12065          info.SetContext(Handle<Context>(function_->context()));
12066        }
12067        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
12068          scope = info.function()->scope();
12069        }
12070        RetrieveScopeChain(scope, shared_info);
12071      } else {
12072        // Function code
12073        CompilationInfoWithZone info(shared_info);
12074        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
12075          scope = info.function()->scope();
12076        }
12077        RetrieveScopeChain(scope, shared_info);
12078      }
12079    }
12080  }
12081
12082  ScopeIterator(Isolate* isolate,
12083                Handle<JSFunction> function)
12084    : isolate_(isolate),
12085      frame_(NULL),
12086      inlined_jsframe_index_(0),
12087      function_(function),
12088      context_(function->context()),
12089      failed_(false) {
12090    if (function->IsBuiltin()) {
12091      context_ = Handle<Context>();
12092    }
12093  }
12094
12095  // More scopes?
12096  bool Done() {
12097    DCHECK(!failed_);
12098    return context_.is_null();
12099  }
12100
12101  bool Failed() { return failed_; }
12102
12103  // Move to the next scope.
12104  void Next() {
12105    DCHECK(!failed_);
12106    ScopeType scope_type = Type();
12107    if (scope_type == ScopeTypeGlobal) {
12108      // The global scope is always the last in the chain.
12109      DCHECK(context_->IsNativeContext());
12110      context_ = Handle<Context>();
12111      return;
12112    }
12113    if (nested_scope_chain_.is_empty()) {
12114      context_ = Handle<Context>(context_->previous(), isolate_);
12115    } else {
12116      if (nested_scope_chain_.last()->HasContext()) {
12117        DCHECK(context_->previous() != NULL);
12118        context_ = Handle<Context>(context_->previous(), isolate_);
12119      }
12120      nested_scope_chain_.RemoveLast();
12121    }
12122  }
12123
12124  // Return the type of the current scope.
12125  ScopeType Type() {
12126    DCHECK(!failed_);
12127    if (!nested_scope_chain_.is_empty()) {
12128      Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
12129      switch (scope_info->scope_type()) {
12130        case FUNCTION_SCOPE:
12131          DCHECK(context_->IsFunctionContext() ||
12132                 !scope_info->HasContext());
12133          return ScopeTypeLocal;
12134        case MODULE_SCOPE:
12135          DCHECK(context_->IsModuleContext());
12136          return ScopeTypeModule;
12137        case GLOBAL_SCOPE:
12138          DCHECK(context_->IsNativeContext());
12139          return ScopeTypeGlobal;
12140        case WITH_SCOPE:
12141          DCHECK(context_->IsWithContext());
12142          return ScopeTypeWith;
12143        case CATCH_SCOPE:
12144          DCHECK(context_->IsCatchContext());
12145          return ScopeTypeCatch;
12146        case BLOCK_SCOPE:
12147          DCHECK(!scope_info->HasContext() ||
12148                 context_->IsBlockContext());
12149          return ScopeTypeBlock;
12150        case EVAL_SCOPE:
12151          UNREACHABLE();
12152      }
12153    }
12154    if (context_->IsNativeContext()) {
12155      DCHECK(context_->global_object()->IsGlobalObject());
12156      return ScopeTypeGlobal;
12157    }
12158    if (context_->IsFunctionContext()) {
12159      return ScopeTypeClosure;
12160    }
12161    if (context_->IsCatchContext()) {
12162      return ScopeTypeCatch;
12163    }
12164    if (context_->IsBlockContext()) {
12165      return ScopeTypeBlock;
12166    }
12167    if (context_->IsModuleContext()) {
12168      return ScopeTypeModule;
12169    }
12170    DCHECK(context_->IsWithContext());
12171    return ScopeTypeWith;
12172  }
12173
12174  // Return the JavaScript object with the content of the current scope.
12175  MaybeHandle<JSObject> ScopeObject() {
12176    DCHECK(!failed_);
12177    switch (Type()) {
12178      case ScopeIterator::ScopeTypeGlobal:
12179        return Handle<JSObject>(CurrentContext()->global_object());
12180      case ScopeIterator::ScopeTypeLocal:
12181        // Materialize the content of the local scope into a JSObject.
12182        DCHECK(nested_scope_chain_.length() == 1);
12183        return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
12184      case ScopeIterator::ScopeTypeWith:
12185        // Return the with object.
12186        return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
12187      case ScopeIterator::ScopeTypeCatch:
12188        return MaterializeCatchScope(isolate_, CurrentContext());
12189      case ScopeIterator::ScopeTypeClosure:
12190        // Materialize the content of the closure scope into a JSObject.
12191        return MaterializeClosure(isolate_, CurrentContext());
12192      case ScopeIterator::ScopeTypeBlock:
12193        return MaterializeBlockScope(isolate_, CurrentContext());
12194      case ScopeIterator::ScopeTypeModule:
12195        return MaterializeModuleScope(isolate_, CurrentContext());
12196    }
12197    UNREACHABLE();
12198    return Handle<JSObject>();
12199  }
12200
12201  bool SetVariableValue(Handle<String> variable_name,
12202                        Handle<Object> new_value) {
12203    DCHECK(!failed_);
12204    switch (Type()) {
12205      case ScopeIterator::ScopeTypeGlobal:
12206        break;
12207      case ScopeIterator::ScopeTypeLocal:
12208        return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
12209            variable_name, new_value);
12210      case ScopeIterator::ScopeTypeWith:
12211        break;
12212      case ScopeIterator::ScopeTypeCatch:
12213        return SetCatchVariableValue(isolate_, CurrentContext(),
12214            variable_name, new_value);
12215      case ScopeIterator::ScopeTypeClosure:
12216        return SetClosureVariableValue(isolate_, CurrentContext(),
12217            variable_name, new_value);
12218      case ScopeIterator::ScopeTypeBlock:
12219        // TODO(2399): should we implement it?
12220        break;
12221      case ScopeIterator::ScopeTypeModule:
12222        // TODO(2399): should we implement it?
12223        break;
12224    }
12225    return false;
12226  }
12227
12228  Handle<ScopeInfo> CurrentScopeInfo() {
12229    DCHECK(!failed_);
12230    if (!nested_scope_chain_.is_empty()) {
12231      return nested_scope_chain_.last();
12232    } else if (context_->IsBlockContext()) {
12233      return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12234    } else if (context_->IsFunctionContext()) {
12235      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12236    }
12237    return Handle<ScopeInfo>::null();
12238  }
12239
12240  // Return the context for this scope. For the local context there might not
12241  // be an actual context.
12242  Handle<Context> CurrentContext() {
12243    DCHECK(!failed_);
12244    if (Type() == ScopeTypeGlobal ||
12245        nested_scope_chain_.is_empty()) {
12246      return context_;
12247    } else if (nested_scope_chain_.last()->HasContext()) {
12248      return context_;
12249    } else {
12250      return Handle<Context>();
12251    }
12252  }
12253
12254#ifdef DEBUG
12255  // Debug print of the content of the current scope.
12256  void DebugPrint() {
12257    OFStream os(stdout);
12258    DCHECK(!failed_);
12259    switch (Type()) {
12260      case ScopeIterator::ScopeTypeGlobal:
12261        os << "Global:\n";
12262        CurrentContext()->Print(os);
12263        break;
12264
12265      case ScopeIterator::ScopeTypeLocal: {
12266        os << "Local:\n";
12267        function_->shared()->scope_info()->Print();
12268        if (!CurrentContext().is_null()) {
12269          CurrentContext()->Print(os);
12270          if (CurrentContext()->has_extension()) {
12271            Handle<Object> extension(CurrentContext()->extension(), isolate_);
12272            if (extension->IsJSContextExtensionObject()) {
12273              extension->Print(os);
12274            }
12275          }
12276        }
12277        break;
12278      }
12279
12280      case ScopeIterator::ScopeTypeWith:
12281        os << "With:\n";
12282        CurrentContext()->extension()->Print(os);
12283        break;
12284
12285      case ScopeIterator::ScopeTypeCatch:
12286        os << "Catch:\n";
12287        CurrentContext()->extension()->Print(os);
12288        CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(os);
12289        break;
12290
12291      case ScopeIterator::ScopeTypeClosure:
12292        os << "Closure:\n";
12293        CurrentContext()->Print(os);
12294        if (CurrentContext()->has_extension()) {
12295          Handle<Object> extension(CurrentContext()->extension(), isolate_);
12296          if (extension->IsJSContextExtensionObject()) {
12297            extension->Print(os);
12298          }
12299        }
12300        break;
12301
12302      default:
12303        UNREACHABLE();
12304    }
12305    PrintF("\n");
12306  }
12307#endif
12308
12309 private:
12310  Isolate* isolate_;
12311  JavaScriptFrame* frame_;
12312  int inlined_jsframe_index_;
12313  Handle<JSFunction> function_;
12314  Handle<Context> context_;
12315  List<Handle<ScopeInfo> > nested_scope_chain_;
12316  bool failed_;
12317
12318  void RetrieveScopeChain(Scope* scope,
12319                          Handle<SharedFunctionInfo> shared_info) {
12320    if (scope != NULL) {
12321      int source_position = shared_info->code()->SourcePosition(frame_->pc());
12322      scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12323    } else {
12324      // A failed reparse indicates that the preparser has diverged from the
12325      // parser or that the preparse data given to the initial parse has been
12326      // faulty. We fail in debug mode but in release mode we only provide the
12327      // information we get from the context chain but nothing about
12328      // completely stack allocated scopes or stack allocated locals.
12329      // Or it could be due to stack overflow.
12330      DCHECK(isolate_->has_pending_exception());
12331      failed_ = true;
12332    }
12333  }
12334
12335  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12336};
12337
12338
12339RUNTIME_FUNCTION(Runtime_GetScopeCount) {
12340  HandleScope scope(isolate);
12341  DCHECK(args.length() == 2);
12342  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12343  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12344
12345  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12346
12347  // Get the frame where the debugging is performed.
12348  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12349  JavaScriptFrameIterator it(isolate, id);
12350  JavaScriptFrame* frame = it.frame();
12351
12352  // Count the visible scopes.
12353  int n = 0;
12354  for (ScopeIterator it(isolate, frame, 0);
12355       !it.Done();
12356       it.Next()) {
12357    n++;
12358  }
12359
12360  return Smi::FromInt(n);
12361}
12362
12363
12364// Returns the list of step-in positions (text offset) in a function of the
12365// stack frame in a range from the current debug break position to the end
12366// of the corresponding statement.
12367RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
12368  HandleScope scope(isolate);
12369  DCHECK(args.length() == 2);
12370  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12371  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12372
12373  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12374
12375  // Get the frame where the debugging is performed.
12376  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12377  JavaScriptFrameIterator frame_it(isolate, id);
12378  RUNTIME_ASSERT(!frame_it.done());
12379
12380  JavaScriptFrame* frame = frame_it.frame();
12381
12382  Handle<JSFunction> fun =
12383      Handle<JSFunction>(frame->function());
12384  Handle<SharedFunctionInfo> shared =
12385      Handle<SharedFunctionInfo>(fun->shared());
12386
12387  if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12388    return isolate->heap()->undefined_value();
12389  }
12390
12391  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12392
12393  int len = 0;
12394  Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12395  // Find the break point where execution has stopped.
12396  BreakLocationIterator break_location_iterator(debug_info,
12397                                                ALL_BREAK_LOCATIONS);
12398
12399  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12400  int current_statement_pos = break_location_iterator.statement_position();
12401
12402  while (!break_location_iterator.Done()) {
12403    bool accept;
12404    if (break_location_iterator.pc() > frame->pc()) {
12405      accept = true;
12406    } else {
12407      StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12408      // The break point is near our pc. Could be a step-in possibility,
12409      // that is currently taken by active debugger call.
12410      if (break_frame_id == StackFrame::NO_ID) {
12411        // We are not stepping.
12412        accept = false;
12413      } else {
12414        JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12415        // If our frame is a top frame and we are stepping, we can do step-in
12416        // at this place.
12417        accept = additional_frame_it.frame()->id() == id;
12418      }
12419    }
12420    if (accept) {
12421      if (break_location_iterator.IsStepInLocation(isolate)) {
12422        Smi* position_value = Smi::FromInt(break_location_iterator.position());
12423        RETURN_FAILURE_ON_EXCEPTION(
12424            isolate,
12425            JSObject::SetElement(array, len,
12426                                 Handle<Object>(position_value, isolate),
12427                                 NONE, SLOPPY));
12428        len++;
12429      }
12430    }
12431    // Advance iterator.
12432    break_location_iterator.Next();
12433    if (current_statement_pos !=
12434        break_location_iterator.statement_position()) {
12435      break;
12436    }
12437  }
12438  return *array;
12439}
12440
12441
12442static const int kScopeDetailsTypeIndex = 0;
12443static const int kScopeDetailsObjectIndex = 1;
12444static const int kScopeDetailsSize = 2;
12445
12446
12447MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails(
12448    Isolate* isolate,
12449    ScopeIterator* it) {
12450  // Calculate the size of the result.
12451  int details_size = kScopeDetailsSize;
12452  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12453
12454  // Fill in scope details.
12455  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12456  Handle<JSObject> scope_object;
12457  ASSIGN_RETURN_ON_EXCEPTION(
12458      isolate, scope_object, it->ScopeObject(), JSObject);
12459  details->set(kScopeDetailsObjectIndex, *scope_object);
12460
12461  return isolate->factory()->NewJSArrayWithElements(details);
12462}
12463
12464
12465// Return an array with scope details
12466// args[0]: number: break id
12467// args[1]: number: frame index
12468// args[2]: number: inlined frame index
12469// args[3]: number: scope index
12470//
12471// The array returned contains the following information:
12472// 0: Scope type
12473// 1: Scope object
12474RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
12475  HandleScope scope(isolate);
12476  DCHECK(args.length() == 4);
12477  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12478  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12479
12480  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12481  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12482  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12483
12484  // Get the frame where the debugging is performed.
12485  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12486  JavaScriptFrameIterator frame_it(isolate, id);
12487  JavaScriptFrame* frame = frame_it.frame();
12488
12489  // Find the requested scope.
12490  int n = 0;
12491  ScopeIterator it(isolate, frame, inlined_jsframe_index);
12492  for (; !it.Done() && n < index; it.Next()) {
12493    n++;
12494  }
12495  if (it.Done()) {
12496    return isolate->heap()->undefined_value();
12497  }
12498  Handle<JSObject> details;
12499  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12500      isolate, details, MaterializeScopeDetails(isolate, &it));
12501  return *details;
12502}
12503
12504
12505// Return an array of scope details
12506// args[0]: number: break id
12507// args[1]: number: frame index
12508// args[2]: number: inlined frame index
12509// args[3]: boolean: ignore nested scopes
12510//
12511// The array returned contains arrays with the following information:
12512// 0: Scope type
12513// 1: Scope object
12514RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
12515  HandleScope scope(isolate);
12516  DCHECK(args.length() == 3 || args.length() == 4);
12517  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12518  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12519
12520  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12521  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12522
12523  bool ignore_nested_scopes = false;
12524  if (args.length() == 4) {
12525    CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
12526    ignore_nested_scopes = flag;
12527  }
12528
12529  // Get the frame where the debugging is performed.
12530  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12531  JavaScriptFrameIterator frame_it(isolate, id);
12532  JavaScriptFrame* frame = frame_it.frame();
12533
12534  List<Handle<JSObject> > result(4);
12535  ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
12536  for (; !it.Done(); it.Next()) {
12537    Handle<JSObject> details;
12538    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12539        isolate, details, MaterializeScopeDetails(isolate, &it));
12540    result.Add(details);
12541  }
12542
12543  Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
12544  for (int i = 0; i < result.length(); ++i) {
12545    array->set(i, *result[i]);
12546  }
12547  return *isolate->factory()->NewJSArrayWithElements(array);
12548}
12549
12550
12551RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
12552  HandleScope scope(isolate);
12553  DCHECK(args.length() == 1);
12554
12555  // Check arguments.
12556  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12557
12558  // Count the visible scopes.
12559  int n = 0;
12560  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12561    n++;
12562  }
12563
12564  return Smi::FromInt(n);
12565}
12566
12567
12568RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
12569  HandleScope scope(isolate);
12570  DCHECK(args.length() == 2);
12571
12572  // Check arguments.
12573  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12574  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12575
12576  // Find the requested scope.
12577  int n = 0;
12578  ScopeIterator it(isolate, fun);
12579  for (; !it.Done() && n < index; it.Next()) {
12580    n++;
12581  }
12582  if (it.Done()) {
12583    return isolate->heap()->undefined_value();
12584  }
12585
12586  Handle<JSObject> details;
12587  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12588      isolate, details, MaterializeScopeDetails(isolate, &it));
12589  return *details;
12590}
12591
12592
12593static bool SetScopeVariableValue(ScopeIterator* it, int index,
12594                                  Handle<String> variable_name,
12595                                  Handle<Object> new_value) {
12596  for (int n = 0; !it->Done() && n < index; it->Next()) {
12597    n++;
12598  }
12599  if (it->Done()) {
12600    return false;
12601  }
12602  return it->SetVariableValue(variable_name, new_value);
12603}
12604
12605
12606// Change variable value in closure or local scope
12607// args[0]: number or JsFunction: break id or function
12608// args[1]: number: frame index (when arg[0] is break id)
12609// args[2]: number: inlined frame index (when arg[0] is break id)
12610// args[3]: number: scope index
12611// args[4]: string: variable name
12612// args[5]: object: new value
12613//
12614// Return true if success and false otherwise
12615RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
12616  HandleScope scope(isolate);
12617  DCHECK(args.length() == 6);
12618
12619  // Check arguments.
12620  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12621  CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12622  CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
12623
12624  bool res;
12625  if (args[0]->IsNumber()) {
12626    CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12627    RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12628
12629    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12630    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12631
12632    // Get the frame where the debugging is performed.
12633    StackFrame::Id id = UnwrapFrameId(wrapped_id);
12634    JavaScriptFrameIterator frame_it(isolate, id);
12635    JavaScriptFrame* frame = frame_it.frame();
12636
12637    ScopeIterator it(isolate, frame, inlined_jsframe_index);
12638    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12639  } else {
12640    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12641    ScopeIterator it(isolate, fun);
12642    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12643  }
12644
12645  return isolate->heap()->ToBoolean(res);
12646}
12647
12648
12649RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
12650  HandleScope scope(isolate);
12651  DCHECK(args.length() == 0);
12652
12653#ifdef DEBUG
12654  // Print the scopes for the top frame.
12655  StackFrameLocator locator(isolate);
12656  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12657  for (ScopeIterator it(isolate, frame, 0);
12658       !it.Done();
12659       it.Next()) {
12660    it.DebugPrint();
12661  }
12662#endif
12663  return isolate->heap()->undefined_value();
12664}
12665
12666
12667RUNTIME_FUNCTION(Runtime_GetThreadCount) {
12668  HandleScope scope(isolate);
12669  DCHECK(args.length() == 1);
12670  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12671  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12672
12673  // Count all archived V8 threads.
12674  int n = 0;
12675  for (ThreadState* thread =
12676          isolate->thread_manager()->FirstThreadStateInUse();
12677       thread != NULL;
12678       thread = thread->Next()) {
12679    n++;
12680  }
12681
12682  // Total number of threads is current thread and archived threads.
12683  return Smi::FromInt(n + 1);
12684}
12685
12686
12687static const int kThreadDetailsCurrentThreadIndex = 0;
12688static const int kThreadDetailsThreadIdIndex = 1;
12689static const int kThreadDetailsSize = 2;
12690
12691// Return an array with thread details
12692// args[0]: number: break id
12693// args[1]: number: thread index
12694//
12695// The array returned contains the following information:
12696// 0: Is current thread?
12697// 1: Thread id
12698RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
12699  HandleScope scope(isolate);
12700  DCHECK(args.length() == 2);
12701  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12702  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12703
12704  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12705
12706  // Allocate array for result.
12707  Handle<FixedArray> details =
12708      isolate->factory()->NewFixedArray(kThreadDetailsSize);
12709
12710  // Thread index 0 is current thread.
12711  if (index == 0) {
12712    // Fill the details.
12713    details->set(kThreadDetailsCurrentThreadIndex,
12714                 isolate->heap()->true_value());
12715    details->set(kThreadDetailsThreadIdIndex,
12716                 Smi::FromInt(ThreadId::Current().ToInteger()));
12717  } else {
12718    // Find the thread with the requested index.
12719    int n = 1;
12720    ThreadState* thread =
12721        isolate->thread_manager()->FirstThreadStateInUse();
12722    while (index != n && thread != NULL) {
12723      thread = thread->Next();
12724      n++;
12725    }
12726    if (thread == NULL) {
12727      return isolate->heap()->undefined_value();
12728    }
12729
12730    // Fill the details.
12731    details->set(kThreadDetailsCurrentThreadIndex,
12732                 isolate->heap()->false_value());
12733    details->set(kThreadDetailsThreadIdIndex,
12734                 Smi::FromInt(thread->id().ToInteger()));
12735  }
12736
12737  // Convert to JS array and return.
12738  return *isolate->factory()->NewJSArrayWithElements(details);
12739}
12740
12741
12742// Sets the disable break state
12743// args[0]: disable break state
12744RUNTIME_FUNCTION(Runtime_SetDisableBreak) {
12745  HandleScope scope(isolate);
12746  DCHECK(args.length() == 1);
12747  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12748  isolate->debug()->set_disable_break(disable_break);
12749  return  isolate->heap()->undefined_value();
12750}
12751
12752
12753static bool IsPositionAlignmentCodeCorrect(int alignment) {
12754  return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12755}
12756
12757
12758RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
12759  HandleScope scope(isolate);
12760  DCHECK(args.length() == 2);
12761
12762  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12763  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12764
12765  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12766    return isolate->ThrowIllegalOperation();
12767  }
12768  BreakPositionAlignment alignment =
12769      static_cast<BreakPositionAlignment>(statement_aligned_code);
12770
12771  Handle<SharedFunctionInfo> shared(fun->shared());
12772  // Find the number of break points
12773  Handle<Object> break_locations =
12774      Debug::GetSourceBreakLocations(shared, alignment);
12775  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12776  // Return array as JS array
12777  return *isolate->factory()->NewJSArrayWithElements(
12778      Handle<FixedArray>::cast(break_locations));
12779}
12780
12781
12782// Set a break point in a function.
12783// args[0]: function
12784// args[1]: number: break source position (within the function source)
12785// args[2]: number: break point object
12786RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
12787  HandleScope scope(isolate);
12788  DCHECK(args.length() == 3);
12789  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12790  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12791  RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
12792                 source_position <= function->shared()->end_position());
12793  CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
12794
12795  // Set break point.
12796  RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
12797      function, break_point_object_arg, &source_position));
12798
12799  return Smi::FromInt(source_position);
12800}
12801
12802
12803// Changes the state of a break point in a script and returns source position
12804// where break point was set. NOTE: Regarding performance see the NOTE for
12805// GetScriptFromScriptData.
12806// args[0]: script to set break point in
12807// args[1]: number: break source position (within the script source)
12808// args[2]: number, breakpoint position alignment
12809// args[3]: number: break point object
12810RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
12811  HandleScope scope(isolate);
12812  DCHECK(args.length() == 4);
12813  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12814  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12815  RUNTIME_ASSERT(source_position >= 0);
12816  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12817  CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
12818
12819  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12820    return isolate->ThrowIllegalOperation();
12821  }
12822  BreakPositionAlignment alignment =
12823      static_cast<BreakPositionAlignment>(statement_aligned_code);
12824
12825  // Get the script from the script wrapper.
12826  RUNTIME_ASSERT(wrapper->value()->IsScript());
12827  Handle<Script> script(Script::cast(wrapper->value()));
12828
12829  // Set break point.
12830  if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12831                                                &source_position,
12832                                                alignment)) {
12833    return isolate->heap()->undefined_value();
12834  }
12835
12836  return Smi::FromInt(source_position);
12837}
12838
12839
12840// Clear a break point
12841// args[0]: number: break point object
12842RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
12843  HandleScope scope(isolate);
12844  DCHECK(args.length() == 1);
12845  CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
12846
12847  // Clear break point.
12848  isolate->debug()->ClearBreakPoint(break_point_object_arg);
12849
12850  return isolate->heap()->undefined_value();
12851}
12852
12853
12854// Change the state of break on exceptions.
12855// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12856// args[1]: Boolean indicating on/off.
12857RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
12858  HandleScope scope(isolate);
12859  DCHECK(args.length() == 2);
12860  CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
12861  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12862
12863  // If the number doesn't match an enum value, the ChangeBreakOnException
12864  // function will default to affecting caught exceptions.
12865  ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
12866  // Update break point state.
12867  isolate->debug()->ChangeBreakOnException(type, enable);
12868  return isolate->heap()->undefined_value();
12869}
12870
12871
12872// Returns the state of break on exceptions
12873// args[0]: boolean indicating uncaught exceptions
12874RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
12875  HandleScope scope(isolate);
12876  DCHECK(args.length() == 1);
12877  CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
12878
12879  ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
12880  bool result = isolate->debug()->IsBreakOnException(type);
12881  return Smi::FromInt(result);
12882}
12883
12884
12885// Prepare for stepping
12886// args[0]: break id for checking execution state
12887// args[1]: step action from the enumeration StepAction
12888// args[2]: number of times to perform the step, for step out it is the number
12889//          of frames to step down.
12890RUNTIME_FUNCTION(Runtime_PrepareStep) {
12891  HandleScope scope(isolate);
12892  DCHECK(args.length() == 4);
12893  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12894  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12895
12896  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12897    return isolate->Throw(isolate->heap()->illegal_argument_string());
12898  }
12899
12900  CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12901
12902  StackFrame::Id frame_id;
12903  if (wrapped_frame_id == 0) {
12904    frame_id = StackFrame::NO_ID;
12905  } else {
12906    frame_id = UnwrapFrameId(wrapped_frame_id);
12907  }
12908
12909  // Get the step action and check validity.
12910  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12911  if (step_action != StepIn &&
12912      step_action != StepNext &&
12913      step_action != StepOut &&
12914      step_action != StepInMin &&
12915      step_action != StepMin) {
12916    return isolate->Throw(isolate->heap()->illegal_argument_string());
12917  }
12918
12919  if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12920      step_action != StepMin && step_action != StepOut) {
12921    return isolate->ThrowIllegalOperation();
12922  }
12923
12924  // Get the number of steps.
12925  int step_count = NumberToInt32(args[2]);
12926  if (step_count < 1) {
12927    return isolate->Throw(isolate->heap()->illegal_argument_string());
12928  }
12929
12930  // Clear all current stepping setup.
12931  isolate->debug()->ClearStepping();
12932
12933  // Prepare step.
12934  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12935                                step_count,
12936                                frame_id);
12937  return isolate->heap()->undefined_value();
12938}
12939
12940
12941// Clear all stepping set by PrepareStep.
12942RUNTIME_FUNCTION(Runtime_ClearStepping) {
12943  HandleScope scope(isolate);
12944  DCHECK(args.length() == 0);
12945  isolate->debug()->ClearStepping();
12946  return isolate->heap()->undefined_value();
12947}
12948
12949
12950// Helper function to find or create the arguments object for
12951// Runtime_DebugEvaluate.
12952MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
12953    Isolate* isolate,
12954    Handle<JSObject> target,
12955    Handle<JSFunction> function) {
12956  // Do not materialize the arguments object for eval or top-level code.
12957  // Skip if "arguments" is already taken.
12958  if (!function->shared()->is_function()) return target;
12959  Maybe<bool> maybe = JSReceiver::HasOwnProperty(
12960      target, isolate->factory()->arguments_string());
12961  if (!maybe.has_value) return MaybeHandle<JSObject>();
12962  if (maybe.value) return target;
12963
12964  // FunctionGetArguments can't throw an exception.
12965  Handle<JSObject> arguments = Handle<JSObject>::cast(
12966      Accessors::FunctionGetArguments(function));
12967  Handle<String> arguments_str = isolate->factory()->arguments_string();
12968  RETURN_ON_EXCEPTION(
12969      isolate,
12970      Runtime::DefineObjectProperty(target, arguments_str, arguments, NONE),
12971      JSObject);
12972  return target;
12973}
12974
12975
12976// Compile and evaluate source for the given context.
12977static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
12978                                         Handle<SharedFunctionInfo> outer_info,
12979                                         Handle<Context> context,
12980                                         Handle<Object> context_extension,
12981                                         Handle<Object> receiver,
12982                                         Handle<String> source) {
12983  if (context_extension->IsJSObject()) {
12984    Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12985    Handle<JSFunction> closure(context->closure(), isolate);
12986    context = isolate->factory()->NewWithContext(closure, context, extension);
12987  }
12988
12989  Handle<JSFunction> eval_fun;
12990  ASSIGN_RETURN_ON_EXCEPTION(
12991      isolate, eval_fun,
12992      Compiler::GetFunctionFromEval(source,
12993                                    outer_info,
12994                                    context,
12995                                    SLOPPY,
12996                                    NO_PARSE_RESTRICTION,
12997                                    RelocInfo::kNoPosition),
12998      Object);
12999
13000  Handle<Object> result;
13001  ASSIGN_RETURN_ON_EXCEPTION(
13002      isolate, result,
13003      Execution::Call(isolate, eval_fun, receiver, 0, NULL),
13004      Object);
13005
13006  // Skip the global proxy as it has no properties and always delegates to the
13007  // real global object.
13008  if (result->IsJSGlobalProxy()) {
13009    PrototypeIterator iter(isolate, result);
13010    // TODO(verwaest): This will crash when the global proxy is detached.
13011    result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
13012  }
13013
13014  // Clear the oneshot breakpoints so that the debugger does not step further.
13015  isolate->debug()->ClearStepping();
13016  return result;
13017}
13018
13019
13020static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) {
13021  Handle<JSObject> result =
13022      isolate->factory()->NewJSObject(isolate->object_function());
13023  Handle<Map> new_map = Map::Copy(Handle<Map>(result->map()));
13024  new_map->set_prototype(*isolate->factory()->null_value());
13025  JSObject::MigrateToMap(result, new_map);
13026  return result;
13027}
13028
13029
13030// Evaluate a piece of JavaScript in the context of a stack frame for
13031// debugging.  Things that need special attention are:
13032// - Parameters and stack-allocated locals need to be materialized.  Altered
13033//   values need to be written back to the stack afterwards.
13034// - The arguments object needs to materialized.
13035RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
13036  HandleScope scope(isolate);
13037
13038  // Check the execution state and decode arguments frame and source to be
13039  // evaluated.
13040  DCHECK(args.length() == 6);
13041  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
13042  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
13043
13044  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
13045  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
13046  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
13047  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
13048  CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5);
13049
13050  // Handle the processing of break.
13051  DisableBreak disable_break_scope(isolate->debug(), disable_break);
13052
13053  // Get the frame where the debugging is performed.
13054  StackFrame::Id id = UnwrapFrameId(wrapped_id);
13055  JavaScriptFrameIterator it(isolate, id);
13056  JavaScriptFrame* frame = it.frame();
13057  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
13058  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
13059  Handle<SharedFunctionInfo> outer_info(function->shared());
13060
13061  // Traverse the saved contexts chain to find the active context for the
13062  // selected frame.
13063  SaveContext* save = FindSavedContextForFrame(isolate, frame);
13064
13065  SaveContext savex(isolate);
13066  isolate->set_context(*(save->context()));
13067
13068  // Evaluate on the context of the frame.
13069  Handle<Context> context(Context::cast(frame_inspector.GetContext()));
13070  DCHECK(!context.is_null());
13071
13072  // Materialize stack locals and the arguments object.
13073  Handle<JSObject> materialized = NewJSObjectWithNullProto(isolate);
13074
13075  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13076      isolate, materialized,
13077      MaterializeStackLocalsWithFrameInspector(
13078          isolate, materialized, function, &frame_inspector));
13079
13080  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13081      isolate, materialized,
13082      MaterializeArgumentsObject(isolate, materialized, function));
13083
13084  // Add the materialized object in a with-scope to shadow the stack locals.
13085  context = isolate->factory()->NewWithContext(function, context, materialized);
13086
13087  Handle<Object> receiver(frame->receiver(), isolate);
13088  Handle<Object> result;
13089  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13090      isolate, result,
13091      DebugEvaluate(isolate, outer_info,
13092                    context, context_extension, receiver, source));
13093
13094  // Write back potential changes to materialized stack locals to the stack.
13095  UpdateStackLocalsFromMaterializedObject(
13096      isolate, materialized, function, frame, inlined_jsframe_index);
13097
13098  return *result;
13099}
13100
13101
13102RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
13103  HandleScope scope(isolate);
13104
13105  // Check the execution state and decode arguments frame and source to be
13106  // evaluated.
13107  DCHECK(args.length() == 4);
13108  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
13109  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
13110
13111  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13112  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
13113  CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3);
13114
13115  // Handle the processing of break.
13116  DisableBreak disable_break_scope(isolate->debug(), disable_break);
13117
13118  // Enter the top context from before the debugger was invoked.
13119  SaveContext save(isolate);
13120  SaveContext* top = &save;
13121  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
13122    top = top->prev();
13123  }
13124  if (top != NULL) {
13125    isolate->set_context(*top->context());
13126  }
13127
13128  // Get the native context now set to the top context from before the
13129  // debugger was invoked.
13130  Handle<Context> context = isolate->native_context();
13131  Handle<JSObject> receiver(context->global_proxy());
13132  Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
13133  Handle<Object> result;
13134  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13135      isolate, result,
13136      DebugEvaluate(isolate, outer_info,
13137                    context, context_extension, receiver, source));
13138  return *result;
13139}
13140
13141
13142RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
13143  HandleScope scope(isolate);
13144  DCHECK(args.length() == 0);
13145
13146  // Fill the script objects.
13147  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
13148
13149  // Convert the script objects to proper JS objects.
13150  for (int i = 0; i < instances->length(); i++) {
13151    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
13152    // Get the script wrapper in a local handle before calling GetScriptWrapper,
13153    // because using
13154    //   instances->set(i, *GetScriptWrapper(script))
13155    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
13156    // already have dereferenced the instances handle.
13157    Handle<JSObject> wrapper = Script::GetWrapper(script);
13158    instances->set(i, *wrapper);
13159  }
13160
13161  // Return result as a JS array.
13162  Handle<JSObject> result =
13163      isolate->factory()->NewJSObject(isolate->array_function());
13164  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13165  return *result;
13166}
13167
13168
13169// Helper function used by Runtime_DebugReferencedBy below.
13170static int DebugReferencedBy(HeapIterator* iterator,
13171                             JSObject* target,
13172                             Object* instance_filter, int max_references,
13173                             FixedArray* instances, int instances_size,
13174                             JSFunction* arguments_function) {
13175  Isolate* isolate = target->GetIsolate();
13176  SealHandleScope shs(isolate);
13177  DisallowHeapAllocation no_allocation;
13178
13179  // Iterate the heap.
13180  int count = 0;
13181  JSObject* last = NULL;
13182  HeapObject* heap_obj = NULL;
13183  while (((heap_obj = iterator->next()) != NULL) &&
13184         (max_references == 0 || count < max_references)) {
13185    // Only look at all JSObjects.
13186    if (heap_obj->IsJSObject()) {
13187      // Skip context extension objects and argument arrays as these are
13188      // checked in the context of functions using them.
13189      JSObject* obj = JSObject::cast(heap_obj);
13190      if (obj->IsJSContextExtensionObject() ||
13191          obj->map()->constructor() == arguments_function) {
13192        continue;
13193      }
13194
13195      // Check if the JS object has a reference to the object looked for.
13196      if (obj->ReferencesObject(target)) {
13197        // Check instance filter if supplied. This is normally used to avoid
13198        // references from mirror objects (see Runtime_IsInPrototypeChain).
13199        if (!instance_filter->IsUndefined()) {
13200          for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd();
13201               iter.Advance()) {
13202            if (iter.GetCurrent() == instance_filter) {
13203              obj = NULL;  // Don't add this object.
13204              break;
13205            }
13206          }
13207        }
13208
13209        if (obj != NULL) {
13210          // Valid reference found add to instance array if supplied an update
13211          // count.
13212          if (instances != NULL && count < instances_size) {
13213            instances->set(count, obj);
13214          }
13215          last = obj;
13216          count++;
13217        }
13218      }
13219    }
13220  }
13221
13222  // Check for circular reference only. This can happen when the object is only
13223  // referenced from mirrors and has a circular reference in which case the
13224  // object is not really alive and would have been garbage collected if not
13225  // referenced from the mirror.
13226  if (count == 1 && last == target) {
13227    count = 0;
13228  }
13229
13230  // Return the number of referencing objects found.
13231  return count;
13232}
13233
13234
13235// Scan the heap for objects with direct references to an object
13236// args[0]: the object to find references to
13237// args[1]: constructor function for instances to exclude (Mirror)
13238// args[2]: the the maximum number of objects to return
13239RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
13240  HandleScope scope(isolate);
13241  DCHECK(args.length() == 3);
13242
13243  // Check parameters.
13244  CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
13245  CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
13246  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13247                 instance_filter->IsJSObject());
13248  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13249  RUNTIME_ASSERT(max_references >= 0);
13250
13251
13252  // Get the constructor function for context extension and arguments array.
13253  Handle<JSFunction> arguments_function(
13254      JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
13255
13256  // Get the number of referencing objects.
13257  int count;
13258  // First perform a full GC in order to avoid dead objects and to make the heap
13259  // iterable.
13260  Heap* heap = isolate->heap();
13261  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13262  {
13263    HeapIterator heap_iterator(heap);
13264    count = DebugReferencedBy(&heap_iterator,
13265                              *target, *instance_filter, max_references,
13266                              NULL, 0, *arguments_function);
13267  }
13268
13269  // Allocate an array to hold the result.
13270  Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13271
13272  // Fill the referencing objects.
13273  {
13274    HeapIterator heap_iterator(heap);
13275    count = DebugReferencedBy(&heap_iterator,
13276                              *target, *instance_filter, max_references,
13277                              *instances, count, *arguments_function);
13278  }
13279
13280  // Return result as JS array.
13281  Handle<JSFunction> constructor = isolate->array_function();
13282
13283  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
13284  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13285  return *result;
13286}
13287
13288
13289// Helper function used by Runtime_DebugConstructedBy below.
13290static int DebugConstructedBy(HeapIterator* iterator,
13291                              JSFunction* constructor,
13292                              int max_references,
13293                              FixedArray* instances,
13294                              int instances_size) {
13295  DisallowHeapAllocation no_allocation;
13296
13297  // Iterate the heap.
13298  int count = 0;
13299  HeapObject* heap_obj = NULL;
13300  while (((heap_obj = iterator->next()) != NULL) &&
13301         (max_references == 0 || count < max_references)) {
13302    // Only look at all JSObjects.
13303    if (heap_obj->IsJSObject()) {
13304      JSObject* obj = JSObject::cast(heap_obj);
13305      if (obj->map()->constructor() == constructor) {
13306        // Valid reference found add to instance array if supplied an update
13307        // count.
13308        if (instances != NULL && count < instances_size) {
13309          instances->set(count, obj);
13310        }
13311        count++;
13312      }
13313    }
13314  }
13315
13316  // Return the number of referencing objects found.
13317  return count;
13318}
13319
13320
13321// Scan the heap for objects constructed by a specific function.
13322// args[0]: the constructor to find instances of
13323// args[1]: the the maximum number of objects to return
13324RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
13325  HandleScope scope(isolate);
13326  DCHECK(args.length() == 2);
13327
13328
13329  // Check parameters.
13330  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
13331  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13332  RUNTIME_ASSERT(max_references >= 0);
13333
13334  // Get the number of referencing objects.
13335  int count;
13336  // First perform a full GC in order to avoid dead objects and to make the heap
13337  // iterable.
13338  Heap* heap = isolate->heap();
13339  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13340  {
13341    HeapIterator heap_iterator(heap);
13342    count = DebugConstructedBy(&heap_iterator,
13343                               *constructor,
13344                               max_references,
13345                               NULL,
13346                               0);
13347  }
13348
13349  // Allocate an array to hold the result.
13350  Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13351
13352  // Fill the referencing objects.
13353  {
13354    HeapIterator heap_iterator2(heap);
13355    count = DebugConstructedBy(&heap_iterator2,
13356                               *constructor,
13357                               max_references,
13358                               *instances,
13359                               count);
13360  }
13361
13362  // Return result as JS array.
13363  Handle<JSFunction> array_function = isolate->array_function();
13364  Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
13365  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13366  return *result;
13367}
13368
13369
13370// Find the effective prototype object as returned by __proto__.
13371// args[0]: the object to find the prototype for.
13372RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
13373  HandleScope shs(isolate);
13374  DCHECK(args.length() == 1);
13375  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
13376  return *GetPrototypeSkipHiddenPrototypes(isolate, obj);
13377}
13378
13379
13380// Patches script source (should be called upon BeforeCompile event).
13381RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
13382  HandleScope scope(isolate);
13383  DCHECK(args.length() == 2);
13384
13385  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13386  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13387
13388  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13389  Handle<Script> script(Script::cast(script_wrapper->value()));
13390
13391  int compilation_state = script->compilation_state();
13392  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13393  script->set_source(*source);
13394
13395  return isolate->heap()->undefined_value();
13396}
13397
13398
13399RUNTIME_FUNCTION(Runtime_SystemBreak) {
13400  SealHandleScope shs(isolate);
13401  DCHECK(args.length() == 0);
13402  base::OS::DebugBreak();
13403  return isolate->heap()->undefined_value();
13404}
13405
13406
13407RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) {
13408  HandleScope scope(isolate);
13409#ifdef DEBUG
13410  DCHECK(args.length() == 1);
13411  // Get the function and make sure it is compiled.
13412  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13413  if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13414    return isolate->heap()->exception();
13415  }
13416  OFStream os(stdout);
13417  func->code()->Print(os);
13418  os << endl;
13419#endif  // DEBUG
13420  return isolate->heap()->undefined_value();
13421}
13422
13423
13424RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) {
13425  HandleScope scope(isolate);
13426#ifdef DEBUG
13427  DCHECK(args.length() == 1);
13428  // Get the function and make sure it is compiled.
13429  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13430  if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13431    return isolate->heap()->exception();
13432  }
13433  OFStream os(stdout);
13434  func->shared()->construct_stub()->Print(os);
13435  os << endl;
13436#endif  // DEBUG
13437  return isolate->heap()->undefined_value();
13438}
13439
13440
13441RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
13442  SealHandleScope shs(isolate);
13443  DCHECK(args.length() == 1);
13444
13445  CONVERT_ARG_CHECKED(JSFunction, f, 0);
13446  return f->shared()->inferred_name();
13447}
13448
13449
13450static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13451                                            Script* script,
13452                                            FixedArray* buffer) {
13453  DisallowHeapAllocation no_allocation;
13454  int counter = 0;
13455  int buffer_size = buffer->length();
13456  for (HeapObject* obj = iterator->next();
13457       obj != NULL;
13458       obj = iterator->next()) {
13459    DCHECK(obj != NULL);
13460    if (!obj->IsSharedFunctionInfo()) {
13461      continue;
13462    }
13463    SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13464    if (shared->script() != script) {
13465      continue;
13466    }
13467    if (counter < buffer_size) {
13468      buffer->set(counter, shared);
13469    }
13470    counter++;
13471  }
13472  return counter;
13473}
13474
13475
13476// For a script finds all SharedFunctionInfo's in the heap that points
13477// to this script. Returns JSArray of SharedFunctionInfo wrapped
13478// in OpaqueReferences.
13479RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
13480  HandleScope scope(isolate);
13481  CHECK(isolate->debug()->live_edit_enabled());
13482  DCHECK(args.length() == 1);
13483  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13484
13485  RUNTIME_ASSERT(script_value->value()->IsScript());
13486  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13487
13488  const int kBufferSize = 32;
13489
13490  Handle<FixedArray> array;
13491  array = isolate->factory()->NewFixedArray(kBufferSize);
13492  int number;
13493  Heap* heap = isolate->heap();
13494  {
13495    HeapIterator heap_iterator(heap);
13496    Script* scr = *script;
13497    FixedArray* arr = *array;
13498    number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13499  }
13500  if (number > kBufferSize) {
13501    array = isolate->factory()->NewFixedArray(number);
13502    HeapIterator heap_iterator(heap);
13503    Script* scr = *script;
13504    FixedArray* arr = *array;
13505    FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13506  }
13507
13508  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13509  result->set_length(Smi::FromInt(number));
13510
13511  LiveEdit::WrapSharedFunctionInfos(result);
13512
13513  return *result;
13514}
13515
13516
13517// For a script calculates compilation information about all its functions.
13518// The script source is explicitly specified by the second argument.
13519// The source of the actual script is not used, however it is important that
13520// all generated code keeps references to this particular instance of script.
13521// Returns a JSArray of compilation infos. The array is ordered so that
13522// each function with all its descendant is always stored in a continues range
13523// with the function itself going first. The root function is a script function.
13524RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
13525  HandleScope scope(isolate);
13526  CHECK(isolate->debug()->live_edit_enabled());
13527  DCHECK(args.length() == 2);
13528  CONVERT_ARG_CHECKED(JSValue, script, 0);
13529  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13530
13531  RUNTIME_ASSERT(script->value()->IsScript());
13532  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13533
13534  Handle<JSArray> result;
13535  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13536      isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
13537  return *result;
13538}
13539
13540
13541// Changes the source of the script to a new_source.
13542// If old_script_name is provided (i.e. is a String), also creates a copy of
13543// the script with its original source and sends notification to debugger.
13544RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
13545  HandleScope scope(isolate);
13546  CHECK(isolate->debug()->live_edit_enabled());
13547  DCHECK(args.length() == 3);
13548  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13549  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13550  CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
13551
13552  RUNTIME_ASSERT(original_script_value->value()->IsScript());
13553  Handle<Script> original_script(Script::cast(original_script_value->value()));
13554
13555  Handle<Object> old_script = LiveEdit::ChangeScriptSource(
13556      original_script,  new_source,  old_script_name);
13557
13558  if (old_script->IsScript()) {
13559    Handle<Script> script_handle = Handle<Script>::cast(old_script);
13560    return *Script::GetWrapper(script_handle);
13561  } else {
13562    return isolate->heap()->null_value();
13563  }
13564}
13565
13566
13567RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
13568  HandleScope scope(isolate);
13569  CHECK(isolate->debug()->live_edit_enabled());
13570  DCHECK(args.length() == 1);
13571  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13572  RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
13573
13574  LiveEdit::FunctionSourceUpdated(shared_info);
13575  return isolate->heap()->undefined_value();
13576}
13577
13578
13579// Replaces code of SharedFunctionInfo with a new one.
13580RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
13581  HandleScope scope(isolate);
13582  CHECK(isolate->debug()->live_edit_enabled());
13583  DCHECK(args.length() == 2);
13584  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13585  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13586  RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
13587
13588  LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13589  return isolate->heap()->undefined_value();
13590}
13591
13592
13593// Connects SharedFunctionInfo to another script.
13594RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
13595  HandleScope scope(isolate);
13596  CHECK(isolate->debug()->live_edit_enabled());
13597  DCHECK(args.length() == 2);
13598  CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
13599  CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
13600
13601  if (function_object->IsJSValue()) {
13602    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13603    if (script_object->IsJSValue()) {
13604      RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13605      Script* script = Script::cast(JSValue::cast(*script_object)->value());
13606      script_object = Handle<Object>(script, isolate);
13607    }
13608    RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo());
13609    LiveEdit::SetFunctionScript(function_wrapper, script_object);
13610  } else {
13611    // Just ignore this. We may not have a SharedFunctionInfo for some functions
13612    // and we check it in this function.
13613  }
13614
13615  return isolate->heap()->undefined_value();
13616}
13617
13618
13619// In a code of a parent function replaces original function as embedded object
13620// with a substitution one.
13621RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
13622  HandleScope scope(isolate);
13623  CHECK(isolate->debug()->live_edit_enabled());
13624  DCHECK(args.length() == 3);
13625
13626  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13627  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13628  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13629  RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo());
13630  RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo());
13631  RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo());
13632
13633  LiveEdit::ReplaceRefToNestedFunction(
13634      parent_wrapper, orig_wrapper, subst_wrapper);
13635  return isolate->heap()->undefined_value();
13636}
13637
13638
13639// Updates positions of a shared function info (first parameter) according
13640// to script source change. Text change is described in second parameter as
13641// array of groups of 3 numbers:
13642// (change_begin, change_end, change_end_new_position).
13643// Each group describes a change in text; groups are sorted by change_begin.
13644RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
13645  HandleScope scope(isolate);
13646  CHECK(isolate->debug()->live_edit_enabled());
13647  DCHECK(args.length() == 2);
13648  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13649  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13650  RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array))
13651
13652  LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13653  return isolate->heap()->undefined_value();
13654}
13655
13656
13657// For array of SharedFunctionInfo's (each wrapped in JSValue)
13658// checks that none of them have activations on stacks (of any thread).
13659// Returns array of the same length with corresponding results of
13660// LiveEdit::FunctionPatchabilityStatus type.
13661RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
13662  HandleScope scope(isolate);
13663  CHECK(isolate->debug()->live_edit_enabled());
13664  DCHECK(args.length() == 2);
13665  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13666  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13667  RUNTIME_ASSERT(shared_array->length()->IsSmi());
13668  RUNTIME_ASSERT(shared_array->HasFastElements())
13669  int array_length = Smi::cast(shared_array->length())->value();
13670  for (int i = 0; i < array_length; i++) {
13671    Handle<Object> element =
13672        Object::GetElement(isolate, shared_array, i).ToHandleChecked();
13673    RUNTIME_ASSERT(
13674        element->IsJSValue() &&
13675        Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo());
13676  }
13677
13678  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13679}
13680
13681
13682// Compares 2 strings line-by-line, then token-wise and returns diff in form
13683// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13684// of diff chunks.
13685RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
13686  HandleScope scope(isolate);
13687  CHECK(isolate->debug()->live_edit_enabled());
13688  DCHECK(args.length() == 2);
13689  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13690  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13691
13692  return *LiveEdit::CompareStrings(s1, s2);
13693}
13694
13695
13696// Restarts a call frame and completely drops all frames above.
13697// Returns true if successful. Otherwise returns undefined or an error message.
13698RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
13699  HandleScope scope(isolate);
13700  CHECK(isolate->debug()->live_edit_enabled());
13701  DCHECK(args.length() == 2);
13702  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
13703  RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
13704
13705  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13706  Heap* heap = isolate->heap();
13707
13708  // Find the relevant frame with the requested index.
13709  StackFrame::Id id = isolate->debug()->break_frame_id();
13710  if (id == StackFrame::NO_ID) {
13711    // If there are no JavaScript stack frames return undefined.
13712    return heap->undefined_value();
13713  }
13714
13715  JavaScriptFrameIterator it(isolate, id);
13716  int inlined_jsframe_index = FindIndexedNonNativeFrame(&it, index);
13717  if (inlined_jsframe_index == -1) return heap->undefined_value();
13718  // We don't really care what the inlined frame index is, since we are
13719  // throwing away the entire frame anyways.
13720  const char* error_message = LiveEdit::RestartFrame(it.frame());
13721  if (error_message) {
13722    return *(isolate->factory()->InternalizeUtf8String(error_message));
13723  }
13724  return heap->true_value();
13725}
13726
13727
13728// A testing entry. Returns statement position which is the closest to
13729// source_position.
13730RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
13731  HandleScope scope(isolate);
13732  CHECK(isolate->debug()->live_edit_enabled());
13733  DCHECK(args.length() == 2);
13734  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13735  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13736
13737  Handle<Code> code(function->code(), isolate);
13738
13739  if (code->kind() != Code::FUNCTION &&
13740      code->kind() != Code::OPTIMIZED_FUNCTION) {
13741    return isolate->heap()->undefined_value();
13742  }
13743
13744  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13745  int closest_pc = 0;
13746  int distance = kMaxInt;
13747  while (!it.done()) {
13748    int statement_position = static_cast<int>(it.rinfo()->data());
13749    // Check if this break point is closer that what was previously found.
13750    if (source_position <= statement_position &&
13751        statement_position - source_position < distance) {
13752      closest_pc =
13753          static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13754      distance = statement_position - source_position;
13755      // Check whether we can't get any closer.
13756      if (distance == 0) break;
13757    }
13758    it.next();
13759  }
13760
13761  return Smi::FromInt(closest_pc);
13762}
13763
13764
13765// Calls specified function with or without entering the debugger.
13766// This is used in unit tests to run code as if debugger is entered or simply
13767// to have a stack with C++ frame in the middle.
13768RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
13769  HandleScope scope(isolate);
13770  DCHECK(args.length() == 2);
13771  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13772  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13773
13774  MaybeHandle<Object> maybe_result;
13775  if (without_debugger) {
13776    maybe_result = Execution::Call(isolate,
13777                                   function,
13778                                   handle(function->global_proxy()),
13779                                   0,
13780                                   NULL);
13781  } else {
13782    DebugScope debug_scope(isolate->debug());
13783    maybe_result = Execution::Call(isolate,
13784                                   function,
13785                                   handle(function->global_proxy()),
13786                                   0,
13787                                   NULL);
13788  }
13789  Handle<Object> result;
13790  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
13791  return *result;
13792}
13793
13794
13795// Sets a v8 flag.
13796RUNTIME_FUNCTION(Runtime_SetFlags) {
13797  SealHandleScope shs(isolate);
13798  DCHECK(args.length() == 1);
13799  CONVERT_ARG_CHECKED(String, arg, 0);
13800  SmartArrayPointer<char> flags =
13801      arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13802  FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
13803  return isolate->heap()->undefined_value();
13804}
13805
13806
13807// Performs a GC.
13808// Presently, it only does a full GC.
13809RUNTIME_FUNCTION(Runtime_CollectGarbage) {
13810  SealHandleScope shs(isolate);
13811  DCHECK(args.length() == 1);
13812  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13813  return isolate->heap()->undefined_value();
13814}
13815
13816
13817// Gets the current heap usage.
13818RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
13819  SealHandleScope shs(isolate);
13820  DCHECK(args.length() == 0);
13821  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13822  if (!Smi::IsValid(usage)) {
13823    return *isolate->factory()->NewNumberFromInt(usage);
13824  }
13825  return Smi::FromInt(usage);
13826}
13827
13828
13829#ifdef V8_I18N_SUPPORT
13830RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
13831  HandleScope scope(isolate);
13832  Factory* factory = isolate->factory();
13833
13834  DCHECK(args.length() == 1);
13835  CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13836
13837  v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13838
13839  // Return value which denotes invalid language tag.
13840  const char* const kInvalidTag = "invalid-tag";
13841
13842  UErrorCode error = U_ZERO_ERROR;
13843  char icu_result[ULOC_FULLNAME_CAPACITY];
13844  int icu_length = 0;
13845
13846  uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13847                      &icu_length, &error);
13848  if (U_FAILURE(error) || icu_length == 0) {
13849    return *factory->NewStringFromAsciiChecked(kInvalidTag);
13850  }
13851
13852  char result[ULOC_FULLNAME_CAPACITY];
13853
13854  // Force strict BCP47 rules.
13855  uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13856
13857  if (U_FAILURE(error)) {
13858    return *factory->NewStringFromAsciiChecked(kInvalidTag);
13859  }
13860
13861  return *factory->NewStringFromAsciiChecked(result);
13862}
13863
13864
13865RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
13866  HandleScope scope(isolate);
13867  Factory* factory = isolate->factory();
13868
13869  DCHECK(args.length() == 1);
13870  CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13871
13872  const icu::Locale* available_locales = NULL;
13873  int32_t count = 0;
13874
13875  if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13876    available_locales = icu::Collator::getAvailableLocales(count);
13877  } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13878    available_locales = icu::NumberFormat::getAvailableLocales(count);
13879  } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13880    available_locales = icu::DateFormat::getAvailableLocales(count);
13881  } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13882    available_locales = icu::BreakIterator::getAvailableLocales(count);
13883  }
13884
13885  UErrorCode error = U_ZERO_ERROR;
13886  char result[ULOC_FULLNAME_CAPACITY];
13887  Handle<JSObject> locales =
13888      factory->NewJSObject(isolate->object_function());
13889
13890  for (int32_t i = 0; i < count; ++i) {
13891    const char* icu_name = available_locales[i].getName();
13892
13893    error = U_ZERO_ERROR;
13894    // No need to force strict BCP47 rules.
13895    uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13896    if (U_FAILURE(error)) {
13897      // This shouldn't happen, but lets not break the user.
13898      continue;
13899    }
13900
13901    RETURN_FAILURE_ON_EXCEPTION(isolate,
13902        JSObject::SetOwnPropertyIgnoreAttributes(
13903            locales,
13904            factory->NewStringFromAsciiChecked(result),
13905            factory->NewNumber(i),
13906            NONE));
13907  }
13908
13909  return *locales;
13910}
13911
13912
13913RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
13914  HandleScope scope(isolate);
13915  Factory* factory = isolate->factory();
13916
13917  DCHECK(args.length() == 0);
13918
13919  icu::Locale default_locale;
13920
13921  // Set the locale
13922  char result[ULOC_FULLNAME_CAPACITY];
13923  UErrorCode status = U_ZERO_ERROR;
13924  uloc_toLanguageTag(
13925      default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13926  if (U_SUCCESS(status)) {
13927    return *factory->NewStringFromAsciiChecked(result);
13928  }
13929
13930  return *factory->NewStringFromStaticChars("und");
13931}
13932
13933
13934RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
13935  HandleScope scope(isolate);
13936  Factory* factory = isolate->factory();
13937
13938  DCHECK(args.length() == 1);
13939
13940  CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13941
13942  uint32_t length = static_cast<uint32_t>(input->length()->Number());
13943  // Set some limit to prevent fuzz tests from going OOM.
13944  // Can be bumped when callers' requirements change.
13945  RUNTIME_ASSERT(length < 100);
13946  Handle<FixedArray> output = factory->NewFixedArray(length);
13947  Handle<Name> maximized = factory->NewStringFromStaticChars("maximized");
13948  Handle<Name> base = factory->NewStringFromStaticChars("base");
13949  for (unsigned int i = 0; i < length; ++i) {
13950    Handle<Object> locale_id;
13951    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13952        isolate, locale_id, Object::GetElement(isolate, input, i));
13953    if (!locale_id->IsString()) {
13954      return isolate->Throw(*factory->illegal_argument_string());
13955    }
13956
13957    v8::String::Utf8Value utf8_locale_id(
13958        v8::Utils::ToLocal(Handle<String>::cast(locale_id)));
13959
13960    UErrorCode error = U_ZERO_ERROR;
13961
13962    // Convert from BCP47 to ICU format.
13963    // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13964    char icu_locale[ULOC_FULLNAME_CAPACITY];
13965    int icu_locale_length = 0;
13966    uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13967                        &icu_locale_length, &error);
13968    if (U_FAILURE(error) || icu_locale_length == 0) {
13969      return isolate->Throw(*factory->illegal_argument_string());
13970    }
13971
13972    // Maximize the locale.
13973    // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13974    char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13975    uloc_addLikelySubtags(
13976        icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13977
13978    // Remove extensions from maximized locale.
13979    // de_Latn_DE@collation=phonebook -> de_Latn_DE
13980    char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13981    uloc_getBaseName(
13982        icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13983
13984    // Get original name without extensions.
13985    // de_DE@collation=phonebook -> de_DE
13986    char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13987    uloc_getBaseName(
13988        icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13989
13990    // Convert from ICU locale format to BCP47 format.
13991    // de_Latn_DE -> de-Latn-DE
13992    char base_max_locale[ULOC_FULLNAME_CAPACITY];
13993    uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13994                       ULOC_FULLNAME_CAPACITY, FALSE, &error);
13995
13996    // de_DE -> de-DE
13997    char base_locale[ULOC_FULLNAME_CAPACITY];
13998    uloc_toLanguageTag(
13999        icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
14000
14001    if (U_FAILURE(error)) {
14002      return isolate->Throw(*factory->illegal_argument_string());
14003    }
14004
14005    Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
14006    Handle<String> value = factory->NewStringFromAsciiChecked(base_max_locale);
14007    JSObject::AddProperty(result, maximized, value, NONE);
14008    value = factory->NewStringFromAsciiChecked(base_locale);
14009    JSObject::AddProperty(result, base, value, NONE);
14010    output->set(i, *result);
14011  }
14012
14013  Handle<JSArray> result = factory->NewJSArrayWithElements(output);
14014  result->set_length(Smi::FromInt(length));
14015  return *result;
14016}
14017
14018
14019RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
14020  HandleScope scope(isolate);
14021
14022  DCHECK(args.length() == 1);
14023
14024  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
14025
14026  if (!input->IsJSObject()) return isolate->heap()->false_value();
14027  Handle<JSObject> obj = Handle<JSObject>::cast(input);
14028
14029  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
14030  Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
14031  return isolate->heap()->ToBoolean(!tag->IsTheHole());
14032}
14033
14034
14035RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
14036  HandleScope scope(isolate);
14037
14038  DCHECK(args.length() == 2);
14039
14040  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
14041  CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
14042
14043  if (!input->IsJSObject()) return isolate->heap()->false_value();
14044  Handle<JSObject> obj = Handle<JSObject>::cast(input);
14045
14046  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
14047  Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
14048  return isolate->heap()->ToBoolean(
14049      tag->IsString() && String::cast(*tag)->Equals(*expected_type));
14050}
14051
14052
14053RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
14054  HandleScope scope(isolate);
14055
14056  DCHECK(args.length() == 3);
14057
14058  CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
14059  CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
14060  CONVERT_ARG_HANDLE_CHECKED(JSObject, impl, 2);
14061
14062  Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
14063  JSObject::SetHiddenProperty(input, marker, type);
14064
14065  marker = isolate->factory()->intl_impl_object_string();
14066  JSObject::SetHiddenProperty(input, marker, impl);
14067
14068  return isolate->heap()->undefined_value();
14069}
14070
14071
14072RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
14073  HandleScope scope(isolate);
14074
14075  DCHECK(args.length() == 1);
14076
14077  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
14078
14079  if (!input->IsJSObject()) {
14080    Vector< Handle<Object> > arguments = HandleVector(&input, 1);
14081    THROW_NEW_ERROR_RETURN_FAILURE(isolate,
14082                                   NewTypeError("not_intl_object", arguments));
14083  }
14084
14085  Handle<JSObject> obj = Handle<JSObject>::cast(input);
14086
14087  Handle<String> marker = isolate->factory()->intl_impl_object_string();
14088  Handle<Object> impl(obj->GetHiddenProperty(marker), isolate);
14089  if (impl->IsTheHole()) {
14090    Vector< Handle<Object> > arguments = HandleVector(&obj, 1);
14091    THROW_NEW_ERROR_RETURN_FAILURE(isolate,
14092                                   NewTypeError("not_intl_object", arguments));
14093  }
14094  return *impl;
14095}
14096
14097
14098RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
14099  HandleScope scope(isolate);
14100
14101  DCHECK(args.length() == 3);
14102
14103  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14104  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14105  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14106
14107  Handle<ObjectTemplateInfo> date_format_template =
14108      I18N::GetTemplate(isolate);
14109
14110  // Create an empty object wrapper.
14111  Handle<JSObject> local_object;
14112  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14113      isolate, local_object,
14114      Execution::InstantiateObject(date_format_template));
14115
14116  // Set date time formatter as internal field of the resulting JS object.
14117  icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
14118      isolate, locale, options, resolved);
14119
14120  if (!date_format) return isolate->ThrowIllegalOperation();
14121
14122  local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
14123
14124  Factory* factory = isolate->factory();
14125  Handle<String> key = factory->NewStringFromStaticChars("dateFormat");
14126  Handle<String> value = factory->NewStringFromStaticChars("valid");
14127  JSObject::AddProperty(local_object, key, value, NONE);
14128
14129  // Make object handle weak so we can delete the data format once GC kicks in.
14130  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14131  GlobalHandles::MakeWeak(wrapper.location(),
14132                          reinterpret_cast<void*>(wrapper.location()),
14133                          DateFormat::DeleteDateFormat);
14134  return *local_object;
14135}
14136
14137
14138RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
14139  HandleScope scope(isolate);
14140
14141  DCHECK(args.length() == 2);
14142
14143  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14144  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
14145
14146  Handle<Object> value;
14147  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14148      isolate, value, Execution::ToNumber(isolate, date));
14149
14150  icu::SimpleDateFormat* date_format =
14151      DateFormat::UnpackDateFormat(isolate, date_format_holder);
14152  if (!date_format) return isolate->ThrowIllegalOperation();
14153
14154  icu::UnicodeString result;
14155  date_format->format(value->Number(), result);
14156
14157  Handle<String> result_str;
14158  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14159      isolate, result_str,
14160      isolate->factory()->NewStringFromTwoByte(
14161          Vector<const uint16_t>(
14162              reinterpret_cast<const uint16_t*>(result.getBuffer()),
14163              result.length())));
14164  return *result_str;
14165}
14166
14167
14168RUNTIME_FUNCTION(Runtime_InternalDateParse) {
14169  HandleScope scope(isolate);
14170
14171  DCHECK(args.length() == 2);
14172
14173  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14174  CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
14175
14176  v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
14177  icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
14178  icu::SimpleDateFormat* date_format =
14179      DateFormat::UnpackDateFormat(isolate, date_format_holder);
14180  if (!date_format) return isolate->ThrowIllegalOperation();
14181
14182  UErrorCode status = U_ZERO_ERROR;
14183  UDate date = date_format->parse(u_date, status);
14184  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14185
14186  Handle<Object> result;
14187  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14188      isolate, result,
14189      Execution::NewDate(isolate, static_cast<double>(date)));
14190  DCHECK(result->IsJSDate());
14191  return *result;
14192}
14193
14194
14195RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
14196  HandleScope scope(isolate);
14197
14198  DCHECK(args.length() == 3);
14199
14200  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14201  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14202  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14203
14204  Handle<ObjectTemplateInfo> number_format_template =
14205      I18N::GetTemplate(isolate);
14206
14207  // Create an empty object wrapper.
14208  Handle<JSObject> local_object;
14209  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14210      isolate, local_object,
14211      Execution::InstantiateObject(number_format_template));
14212
14213  // Set number formatter as internal field of the resulting JS object.
14214  icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
14215      isolate, locale, options, resolved);
14216
14217  if (!number_format) return isolate->ThrowIllegalOperation();
14218
14219  local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
14220
14221  Factory* factory = isolate->factory();
14222  Handle<String> key = factory->NewStringFromStaticChars("numberFormat");
14223  Handle<String> value = factory->NewStringFromStaticChars("valid");
14224  JSObject::AddProperty(local_object, key, value, NONE);
14225
14226  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14227  GlobalHandles::MakeWeak(wrapper.location(),
14228                          reinterpret_cast<void*>(wrapper.location()),
14229                          NumberFormat::DeleteNumberFormat);
14230  return *local_object;
14231}
14232
14233
14234RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
14235  HandleScope scope(isolate);
14236
14237  DCHECK(args.length() == 2);
14238
14239  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14240  CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
14241
14242  Handle<Object> value;
14243  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14244      isolate, value, Execution::ToNumber(isolate, number));
14245
14246  icu::DecimalFormat* number_format =
14247      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14248  if (!number_format) return isolate->ThrowIllegalOperation();
14249
14250  icu::UnicodeString result;
14251  number_format->format(value->Number(), result);
14252
14253  Handle<String> result_str;
14254  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14255      isolate, result_str,
14256      isolate->factory()->NewStringFromTwoByte(
14257          Vector<const uint16_t>(
14258              reinterpret_cast<const uint16_t*>(result.getBuffer()),
14259              result.length())));
14260  return *result_str;
14261}
14262
14263
14264RUNTIME_FUNCTION(Runtime_InternalNumberParse) {
14265  HandleScope scope(isolate);
14266
14267  DCHECK(args.length() == 2);
14268
14269  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14270  CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
14271
14272  v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
14273  icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
14274  icu::DecimalFormat* number_format =
14275      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14276  if (!number_format) return isolate->ThrowIllegalOperation();
14277
14278  UErrorCode status = U_ZERO_ERROR;
14279  icu::Formattable result;
14280  // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
14281  // to be part of Chrome.
14282  // TODO(cira): Include currency parsing code using parseCurrency call.
14283  // We need to check if the formatter parses all currencies or only the
14284  // one it was constructed with (it will impact the API - how to return ISO
14285  // code and the value).
14286  number_format->parse(u_number, result, status);
14287  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14288
14289  switch (result.getType()) {
14290  case icu::Formattable::kDouble:
14291    return *isolate->factory()->NewNumber(result.getDouble());
14292  case icu::Formattable::kLong:
14293    return *isolate->factory()->NewNumberFromInt(result.getLong());
14294  case icu::Formattable::kInt64:
14295    return *isolate->factory()->NewNumber(
14296        static_cast<double>(result.getInt64()));
14297  default:
14298    return isolate->heap()->undefined_value();
14299  }
14300}
14301
14302
14303RUNTIME_FUNCTION(Runtime_CreateCollator) {
14304  HandleScope scope(isolate);
14305
14306  DCHECK(args.length() == 3);
14307
14308  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14309  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14310  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14311
14312  Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14313
14314  // Create an empty object wrapper.
14315  Handle<JSObject> local_object;
14316  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14317      isolate, local_object, Execution::InstantiateObject(collator_template));
14318
14319  // Set collator as internal field of the resulting JS object.
14320  icu::Collator* collator = Collator::InitializeCollator(
14321      isolate, locale, options, resolved);
14322
14323  if (!collator) return isolate->ThrowIllegalOperation();
14324
14325  local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14326
14327  Factory* factory = isolate->factory();
14328  Handle<String> key = factory->NewStringFromStaticChars("collator");
14329  Handle<String> value = factory->NewStringFromStaticChars("valid");
14330  JSObject::AddProperty(local_object, key, value, NONE);
14331
14332  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14333  GlobalHandles::MakeWeak(wrapper.location(),
14334                          reinterpret_cast<void*>(wrapper.location()),
14335                          Collator::DeleteCollator);
14336  return *local_object;
14337}
14338
14339
14340RUNTIME_FUNCTION(Runtime_InternalCompare) {
14341  HandleScope scope(isolate);
14342
14343  DCHECK(args.length() == 3);
14344
14345  CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14346  CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14347  CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14348
14349  icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14350  if (!collator) return isolate->ThrowIllegalOperation();
14351
14352  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14353  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14354  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14355  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14356  UErrorCode status = U_ZERO_ERROR;
14357  UCollationResult result = collator->compare(u_string1,
14358                                              string_value1.length(),
14359                                              u_string2,
14360                                              string_value2.length(),
14361                                              status);
14362  if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14363
14364  return *isolate->factory()->NewNumberFromInt(result);
14365}
14366
14367
14368RUNTIME_FUNCTION(Runtime_StringNormalize) {
14369  HandleScope scope(isolate);
14370  static const UNormalizationMode normalizationForms[] =
14371      { UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
14372
14373  DCHECK(args.length() == 2);
14374
14375  CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
14376  CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
14377  RUNTIME_ASSERT(form_id >= 0 &&
14378                 static_cast<size_t>(form_id) < arraysize(normalizationForms));
14379
14380  v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
14381  const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
14382
14383  // TODO(mnita): check Normalizer2 (not available in ICU 46)
14384  UErrorCode status = U_ZERO_ERROR;
14385  icu::UnicodeString result;
14386  icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0,
14387      result, status);
14388  if (U_FAILURE(status)) {
14389    return isolate->heap()->undefined_value();
14390  }
14391
14392  Handle<String> result_str;
14393  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14394      isolate, result_str,
14395      isolate->factory()->NewStringFromTwoByte(
14396          Vector<const uint16_t>(
14397              reinterpret_cast<const uint16_t*>(result.getBuffer()),
14398              result.length())));
14399  return *result_str;
14400}
14401
14402
14403RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
14404  HandleScope scope(isolate);
14405
14406  DCHECK(args.length() == 3);
14407
14408  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14409  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14410  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14411
14412  Handle<ObjectTemplateInfo> break_iterator_template =
14413      I18N::GetTemplate2(isolate);
14414
14415  // Create an empty object wrapper.
14416  Handle<JSObject> local_object;
14417  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14418      isolate, local_object,
14419      Execution::InstantiateObject(break_iterator_template));
14420
14421  // Set break iterator as internal field of the resulting JS object.
14422  icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14423      isolate, locale, options, resolved);
14424
14425  if (!break_iterator) return isolate->ThrowIllegalOperation();
14426
14427  local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14428  // Make sure that the pointer to adopted text is NULL.
14429  local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14430
14431  Factory* factory = isolate->factory();
14432  Handle<String> key = factory->NewStringFromStaticChars("breakIterator");
14433  Handle<String> value = factory->NewStringFromStaticChars("valid");
14434  JSObject::AddProperty(local_object, key, value, NONE);
14435
14436  // Make object handle weak so we can delete the break iterator once GC kicks
14437  // in.
14438  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14439  GlobalHandles::MakeWeak(wrapper.location(),
14440                          reinterpret_cast<void*>(wrapper.location()),
14441                          BreakIterator::DeleteBreakIterator);
14442  return *local_object;
14443}
14444
14445
14446RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
14447  HandleScope scope(isolate);
14448
14449  DCHECK(args.length() == 2);
14450
14451  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14452  CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14453
14454  icu::BreakIterator* break_iterator =
14455      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14456  if (!break_iterator) return isolate->ThrowIllegalOperation();
14457
14458  icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14459      break_iterator_holder->GetInternalField(1));
14460  delete u_text;
14461
14462  v8::String::Value text_value(v8::Utils::ToLocal(text));
14463  u_text = new icu::UnicodeString(
14464      reinterpret_cast<const UChar*>(*text_value), text_value.length());
14465  break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14466
14467  break_iterator->setText(*u_text);
14468
14469  return isolate->heap()->undefined_value();
14470}
14471
14472
14473RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
14474  HandleScope scope(isolate);
14475
14476  DCHECK(args.length() == 1);
14477
14478  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14479
14480  icu::BreakIterator* break_iterator =
14481      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14482  if (!break_iterator) return isolate->ThrowIllegalOperation();
14483
14484  return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14485}
14486
14487
14488RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
14489  HandleScope scope(isolate);
14490
14491  DCHECK(args.length() == 1);
14492
14493  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14494
14495  icu::BreakIterator* break_iterator =
14496      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14497  if (!break_iterator) return isolate->ThrowIllegalOperation();
14498
14499  return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14500}
14501
14502
14503RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
14504  HandleScope scope(isolate);
14505
14506  DCHECK(args.length() == 1);
14507
14508  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14509
14510  icu::BreakIterator* break_iterator =
14511      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14512  if (!break_iterator) return isolate->ThrowIllegalOperation();
14513
14514  return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14515}
14516
14517
14518RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
14519  HandleScope scope(isolate);
14520
14521  DCHECK(args.length() == 1);
14522
14523  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14524
14525  icu::BreakIterator* break_iterator =
14526      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14527  if (!break_iterator) return isolate->ThrowIllegalOperation();
14528
14529  // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14530  icu::RuleBasedBreakIterator* rule_based_iterator =
14531      static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14532  int32_t status = rule_based_iterator->getRuleStatus();
14533  // Keep return values in sync with JavaScript BreakType enum.
14534  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14535    return *isolate->factory()->NewStringFromStaticChars("none");
14536  } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14537    return *isolate->factory()->number_string();
14538  } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14539    return *isolate->factory()->NewStringFromStaticChars("letter");
14540  } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14541    return *isolate->factory()->NewStringFromStaticChars("kana");
14542  } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14543    return *isolate->factory()->NewStringFromStaticChars("ideo");
14544  } else {
14545    return *isolate->factory()->NewStringFromStaticChars("unknown");
14546  }
14547}
14548#endif  // V8_I18N_SUPPORT
14549
14550
14551// Finds the script object from the script data. NOTE: This operation uses
14552// heap traversal to find the function generated for the source position
14553// for the requested break point. For lazily compiled functions several heap
14554// traversals might be required rendering this operation as a rather slow
14555// operation. However for setting break points which is normally done through
14556// some kind of user interaction the performance is not crucial.
14557static Handle<Object> Runtime_GetScriptFromScriptName(
14558    Handle<String> script_name) {
14559  // Scan the heap for Script objects to find the script with the requested
14560  // script data.
14561  Handle<Script> script;
14562  Factory* factory = script_name->GetIsolate()->factory();
14563  Heap* heap = script_name->GetHeap();
14564  HeapIterator iterator(heap);
14565  HeapObject* obj = NULL;
14566  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14567    // If a script is found check if it has the script data requested.
14568    if (obj->IsScript()) {
14569      if (Script::cast(obj)->name()->IsString()) {
14570        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14571          script = Handle<Script>(Script::cast(obj));
14572        }
14573      }
14574    }
14575  }
14576
14577  // If no script with the requested script data is found return undefined.
14578  if (script.is_null()) return factory->undefined_value();
14579
14580  // Return the script found.
14581  return Script::GetWrapper(script);
14582}
14583
14584
14585// Get the script object from script data. NOTE: Regarding performance
14586// see the NOTE for GetScriptFromScriptData.
14587// args[0]: script data for the script to find the source for
14588RUNTIME_FUNCTION(Runtime_GetScript) {
14589  HandleScope scope(isolate);
14590
14591  DCHECK(args.length() == 1);
14592
14593  CONVERT_ARG_CHECKED(String, script_name, 0);
14594
14595  // Find the requested script.
14596  Handle<Object> result =
14597      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14598  return *result;
14599}
14600
14601
14602// Collect the raw data for a stack trace.  Returns an array of 4
14603// element segments each containing a receiver, function, code and
14604// native code offset.
14605RUNTIME_FUNCTION(Runtime_CollectStackTrace) {
14606  HandleScope scope(isolate);
14607  DCHECK(args.length() == 2);
14608  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14609  CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1);
14610
14611  if (!isolate->bootstrapper()->IsActive()) {
14612    // Optionally capture a more detailed stack trace for the message.
14613    isolate->CaptureAndSetDetailedStackTrace(error_object);
14614    // Capture a simple stack trace for the stack property.
14615    isolate->CaptureAndSetSimpleStackTrace(error_object, caller);
14616  }
14617  return isolate->heap()->undefined_value();
14618}
14619
14620
14621// Returns V8 version as a string.
14622RUNTIME_FUNCTION(Runtime_GetV8Version) {
14623  HandleScope scope(isolate);
14624  DCHECK(args.length() == 0);
14625
14626  const char* version_string = v8::V8::GetVersion();
14627
14628  return *isolate->factory()->NewStringFromAsciiChecked(version_string);
14629}
14630
14631
14632// Returns function of generator activation.
14633RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
14634  HandleScope scope(isolate);
14635  DCHECK(args.length() == 1);
14636  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
14637
14638  return generator->function();
14639}
14640
14641
14642// Returns context of generator activation.
14643RUNTIME_FUNCTION(Runtime_GeneratorGetContext) {
14644  HandleScope scope(isolate);
14645  DCHECK(args.length() == 1);
14646  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
14647
14648  return generator->context();
14649}
14650
14651
14652// Returns receiver of generator activation.
14653RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
14654  HandleScope scope(isolate);
14655  DCHECK(args.length() == 1);
14656  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
14657
14658  return generator->receiver();
14659}
14660
14661
14662// Returns generator continuation as a PC offset, or the magic -1 or 0 values.
14663RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
14664  HandleScope scope(isolate);
14665  DCHECK(args.length() == 1);
14666  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
14667
14668  return Smi::FromInt(generator->continuation());
14669}
14670
14671
14672RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
14673  HandleScope scope(isolate);
14674  DCHECK(args.length() == 1);
14675  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
14676
14677  if (generator->is_suspended()) {
14678    Handle<Code> code(generator->function()->code(), isolate);
14679    int offset = generator->continuation();
14680
14681    RUNTIME_ASSERT(0 <= offset && offset < code->Size());
14682    Address pc = code->address() + offset;
14683
14684    return Smi::FromInt(code->SourcePosition(pc));
14685  }
14686
14687  return isolate->heap()->undefined_value();
14688}
14689
14690
14691RUNTIME_FUNCTION(Runtime_Abort) {
14692  SealHandleScope shs(isolate);
14693  DCHECK(args.length() == 1);
14694  CONVERT_SMI_ARG_CHECKED(message_id, 0);
14695  const char* message = GetBailoutReason(
14696      static_cast<BailoutReason>(message_id));
14697  base::OS::PrintError("abort: %s\n", message);
14698  isolate->PrintStack(stderr);
14699  base::OS::Abort();
14700  UNREACHABLE();
14701  return NULL;
14702}
14703
14704
14705RUNTIME_FUNCTION(Runtime_AbortJS) {
14706  HandleScope scope(isolate);
14707  DCHECK(args.length() == 1);
14708  CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
14709  base::OS::PrintError("abort: %s\n", message->ToCString().get());
14710  isolate->PrintStack(stderr);
14711  base::OS::Abort();
14712  UNREACHABLE();
14713  return NULL;
14714}
14715
14716
14717RUNTIME_FUNCTION(Runtime_FlattenString) {
14718  HandleScope scope(isolate);
14719  DCHECK(args.length() == 1);
14720  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
14721  return *String::Flatten(str);
14722}
14723
14724
14725RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
14726  HandleScope scope(isolate);
14727  DCHECK(args.length() == 0);
14728  isolate->heap()->NotifyContextDisposed();
14729  return isolate->heap()->undefined_value();
14730}
14731
14732
14733RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
14734  HandleScope scope(isolate);
14735  DCHECK(args.length() == 2);
14736  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
14737  CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
14738  RUNTIME_ASSERT((index->value() & 1) == 1);
14739  FieldIndex field_index =
14740      FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
14741  if (field_index.is_inobject()) {
14742    RUNTIME_ASSERT(field_index.property_index() <
14743                   object->map()->inobject_properties());
14744  } else {
14745    RUNTIME_ASSERT(field_index.outobject_array_index() <
14746                   object->properties()->length());
14747  }
14748  Handle<Object> raw_value(object->RawFastPropertyAt(field_index), isolate);
14749  RUNTIME_ASSERT(raw_value->IsMutableHeapNumber());
14750  return *Object::WrapForRead(isolate, raw_value, Representation::Double());
14751}
14752
14753
14754RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
14755  HandleScope scope(isolate);
14756  DCHECK(args.length() == 1);
14757  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14758  if (!object->IsJSObject()) return Smi::FromInt(0);
14759  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14760  if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14761  // This call must not cause lazy deopts, because it's called from deferred
14762  // code where we can't handle lazy deopts for lack of a suitable bailout
14763  // ID. So we just try migration and signal failure if necessary,
14764  // which will also trigger a deopt.
14765  if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
14766  return *object;
14767}
14768
14769
14770RUNTIME_FUNCTION(Runtime_GetFromCache) {
14771  SealHandleScope shs(isolate);
14772  // This is only called from codegen, so checks might be more lax.
14773  CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14774  CONVERT_ARG_CHECKED(Object, key, 1);
14775
14776  {
14777    DisallowHeapAllocation no_alloc;
14778
14779    int finger_index = cache->finger_index();
14780    Object* o = cache->get(finger_index);
14781    if (o == key) {
14782      // The fastest case: hit the same place again.
14783      return cache->get(finger_index + 1);
14784    }
14785
14786    for (int i = finger_index - 2;
14787         i >= JSFunctionResultCache::kEntriesIndex;
14788         i -= 2) {
14789      o = cache->get(i);
14790      if (o == key) {
14791        cache->set_finger_index(i);
14792        return cache->get(i + 1);
14793      }
14794    }
14795
14796    int size = cache->size();
14797    DCHECK(size <= cache->length());
14798
14799    for (int i = size - 2; i > finger_index; i -= 2) {
14800      o = cache->get(i);
14801      if (o == key) {
14802        cache->set_finger_index(i);
14803        return cache->get(i + 1);
14804      }
14805    }
14806  }
14807
14808  // There is no value in the cache.  Invoke the function and cache result.
14809  HandleScope scope(isolate);
14810
14811  Handle<JSFunctionResultCache> cache_handle(cache);
14812  Handle<Object> key_handle(key, isolate);
14813  Handle<Object> value;
14814  {
14815    Handle<JSFunction> factory(JSFunction::cast(
14816          cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14817    // TODO(antonm): consider passing a receiver when constructing a cache.
14818    Handle<JSObject> receiver(isolate->global_proxy());
14819    // This handle is nor shared, nor used later, so it's safe.
14820    Handle<Object> argv[] = { key_handle };
14821    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14822        isolate, value,
14823        Execution::Call(isolate, factory, receiver, arraysize(argv), argv));
14824  }
14825
14826#ifdef VERIFY_HEAP
14827  if (FLAG_verify_heap) {
14828    cache_handle->JSFunctionResultCacheVerify();
14829  }
14830#endif
14831
14832  // Function invocation may have cleared the cache.  Reread all the data.
14833  int finger_index = cache_handle->finger_index();
14834  int size = cache_handle->size();
14835
14836  // If we have spare room, put new data into it, otherwise evict post finger
14837  // entry which is likely to be the least recently used.
14838  int index = -1;
14839  if (size < cache_handle->length()) {
14840    cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14841    index = size;
14842  } else {
14843    index = finger_index + JSFunctionResultCache::kEntrySize;
14844    if (index == cache_handle->length()) {
14845      index = JSFunctionResultCache::kEntriesIndex;
14846    }
14847  }
14848
14849  DCHECK(index % 2 == 0);
14850  DCHECK(index >= JSFunctionResultCache::kEntriesIndex);
14851  DCHECK(index < cache_handle->length());
14852
14853  cache_handle->set(index, *key_handle);
14854  cache_handle->set(index + 1, *value);
14855  cache_handle->set_finger_index(index);
14856
14857#ifdef VERIFY_HEAP
14858  if (FLAG_verify_heap) {
14859    cache_handle->JSFunctionResultCacheVerify();
14860  }
14861#endif
14862
14863  return *value;
14864}
14865
14866
14867RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) {
14868  SealHandleScope shs(isolate);
14869  DCHECK(args.length() == 1);
14870  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14871  return Smi::FromInt(message->start_position());
14872}
14873
14874
14875RUNTIME_FUNCTION(Runtime_MessageGetScript) {
14876  SealHandleScope shs(isolate);
14877  DCHECK(args.length() == 1);
14878  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14879  return message->script();
14880}
14881
14882
14883#ifdef DEBUG
14884// ListNatives is ONLY used by the fuzz-natives.js in debug mode
14885// Exclude the code in release mode.
14886RUNTIME_FUNCTION(Runtime_ListNatives) {
14887  HandleScope scope(isolate);
14888  DCHECK(args.length() == 0);
14889#define COUNT_ENTRY(Name, argc, ressize) + 1
14890  int entry_count = 0
14891      RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14892      INLINE_FUNCTION_LIST(COUNT_ENTRY)
14893      INLINE_OPTIMIZED_FUNCTION_LIST(COUNT_ENTRY);
14894#undef COUNT_ENTRY
14895  Factory* factory = isolate->factory();
14896  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14897  int index = 0;
14898  bool inline_runtime_functions = false;
14899#define ADD_ENTRY(Name, argc, ressize)                                      \
14900  {                                                                         \
14901    HandleScope inner(isolate);                                             \
14902    Handle<String> name;                                                    \
14903    /* Inline runtime functions have an underscore in front of the name. */ \
14904    if (inline_runtime_functions) {                                         \
14905      name = factory->NewStringFromStaticChars("_" #Name);                  \
14906    } else {                                                                \
14907      name = factory->NewStringFromStaticChars(#Name);                      \
14908    }                                                                       \
14909    Handle<FixedArray> pair_elements = factory->NewFixedArray(2);           \
14910    pair_elements->set(0, *name);                                           \
14911    pair_elements->set(1, Smi::FromInt(argc));                              \
14912    Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);  \
14913    elements->set(index++, *pair);                                          \
14914  }
14915  inline_runtime_functions = false;
14916  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14917  INLINE_OPTIMIZED_FUNCTION_LIST(ADD_ENTRY)
14918  inline_runtime_functions = true;
14919  INLINE_FUNCTION_LIST(ADD_ENTRY)
14920#undef ADD_ENTRY
14921  DCHECK_EQ(index, entry_count);
14922  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14923  return *result;
14924}
14925#endif
14926
14927
14928RUNTIME_FUNCTION(Runtime_IS_VAR) {
14929  UNREACHABLE();  // implemented as macro in the parser
14930  return NULL;
14931}
14932
14933
14934#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14935  RUNTIME_FUNCTION(Runtime_Has##Name) {          \
14936    CONVERT_ARG_CHECKED(JSObject, obj, 0);                \
14937    return isolate->heap()->ToBoolean(obj->Has##Name());  \
14938  }
14939
14940ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14941ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14942ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14943ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14944ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14945ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14946ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
14947ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14948// Properties test sitting with elements tests - not fooling anyone.
14949ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14950
14951#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14952
14953
14954#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size)     \
14955  RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) {             \
14956    CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14957    return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements());     \
14958  }
14959
14960TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14961
14962#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14963
14964
14965#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s)  \
14966  RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                \
14967    CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14968    return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements());        \
14969  }
14970
14971TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14972
14973#undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14974
14975
14976RUNTIME_FUNCTION(Runtime_HaveSameMap) {
14977  SealHandleScope shs(isolate);
14978  DCHECK(args.length() == 2);
14979  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14980  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14981  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14982}
14983
14984
14985RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
14986  SealHandleScope shs(isolate);
14987  DCHECK(args.length() == 1);
14988  CONVERT_ARG_CHECKED(Object, obj, 0);
14989  return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
14990}
14991
14992
14993RUNTIME_FUNCTION(Runtime_IsObserved) {
14994  SealHandleScope shs(isolate);
14995  DCHECK(args.length() == 1);
14996
14997  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14998  CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
14999  DCHECK(!obj->IsJSGlobalProxy() || !obj->map()->is_observed());
15000  return isolate->heap()->ToBoolean(obj->map()->is_observed());
15001}
15002
15003
15004RUNTIME_FUNCTION(Runtime_SetIsObserved) {
15005  HandleScope scope(isolate);
15006  DCHECK(args.length() == 1);
15007  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
15008  RUNTIME_ASSERT(!obj->IsJSGlobalProxy());
15009  if (obj->IsJSProxy()) return isolate->heap()->undefined_value();
15010  RUNTIME_ASSERT(!obj->map()->is_observed());
15011
15012  DCHECK(obj->IsJSObject());
15013  JSObject::SetObserved(Handle<JSObject>::cast(obj));
15014  return isolate->heap()->undefined_value();
15015}
15016
15017
15018RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
15019  HandleScope scope(isolate);
15020  DCHECK(args.length() == 1);
15021  CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0);
15022  isolate->EnqueueMicrotask(microtask);
15023  return isolate->heap()->undefined_value();
15024}
15025
15026
15027RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
15028  HandleScope scope(isolate);
15029  DCHECK(args.length() == 0);
15030  isolate->RunMicrotasks();
15031  return isolate->heap()->undefined_value();
15032}
15033
15034
15035RUNTIME_FUNCTION(Runtime_GetObservationState) {
15036  SealHandleScope shs(isolate);
15037  DCHECK(args.length() == 0);
15038  return isolate->heap()->observation_state();
15039}
15040
15041
15042RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
15043  HandleScope scope(isolate);
15044  DCHECK(args.length() == 0);
15045  // TODO(adamk): Currently this runtime function is only called three times per
15046  // isolate. If it's called more often, the map should be moved into the
15047  // strong root list.
15048  Handle<Map> map =
15049      isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
15050  Handle<JSWeakMap> weakmap =
15051      Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
15052  return *WeakCollectionInitialize(isolate, weakmap);
15053}
15054
15055
15056static bool ContextsHaveSameOrigin(Handle<Context> context1,
15057                                   Handle<Context> context2) {
15058  return context1->security_token() == context2->security_token();
15059}
15060
15061
15062RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) {
15063  HandleScope scope(isolate);
15064  DCHECK(args.length() == 3);
15065  CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
15066  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
15067  CONVERT_ARG_HANDLE_CHECKED(JSObject, record, 2);
15068
15069  Handle<Context> observer_context(observer->context()->native_context());
15070  Handle<Context> object_context(object->GetCreationContext());
15071  Handle<Context> record_context(record->GetCreationContext());
15072
15073  return isolate->heap()->ToBoolean(
15074      ContextsHaveSameOrigin(object_context, observer_context) &&
15075      ContextsHaveSameOrigin(object_context, record_context));
15076}
15077
15078
15079RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin) {
15080  HandleScope scope(isolate);
15081  DCHECK(args.length() == 1);
15082  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
15083
15084  Handle<Context> creation_context(object->GetCreationContext(), isolate);
15085  return isolate->heap()->ToBoolean(
15086      ContextsHaveSameOrigin(creation_context, isolate->native_context()));
15087}
15088
15089
15090RUNTIME_FUNCTION(Runtime_GetObjectContextObjectObserve) {
15091  HandleScope scope(isolate);
15092  DCHECK(args.length() == 1);
15093  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
15094
15095  Handle<Context> context(object->GetCreationContext(), isolate);
15096  return context->native_object_observe();
15097}
15098
15099
15100RUNTIME_FUNCTION(Runtime_GetObjectContextObjectGetNotifier) {
15101  HandleScope scope(isolate);
15102  DCHECK(args.length() == 1);
15103  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
15104
15105  Handle<Context> context(object->GetCreationContext(), isolate);
15106  return context->native_object_get_notifier();
15107}
15108
15109
15110RUNTIME_FUNCTION(Runtime_GetObjectContextNotifierPerformChange) {
15111  HandleScope scope(isolate);
15112  DCHECK(args.length() == 1);
15113  CONVERT_ARG_HANDLE_CHECKED(JSObject, object_info, 0);
15114
15115  Handle<Context> context(object_info->GetCreationContext(), isolate);
15116  return context->native_object_notifier_perform_change();
15117}
15118
15119
15120static Object* ArrayConstructorCommon(Isolate* isolate,
15121                                           Handle<JSFunction> constructor,
15122                                           Handle<AllocationSite> site,
15123                                           Arguments* caller_args) {
15124  Factory* factory = isolate->factory();
15125
15126  bool holey = false;
15127  bool can_use_type_feedback = true;
15128  if (caller_args->length() == 1) {
15129    Handle<Object> argument_one = caller_args->at<Object>(0);
15130    if (argument_one->IsSmi()) {
15131      int value = Handle<Smi>::cast(argument_one)->value();
15132      if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
15133        // the array is a dictionary in this case.
15134        can_use_type_feedback = false;
15135      } else if (value != 0) {
15136        holey = true;
15137      }
15138    } else {
15139      // Non-smi length argument produces a dictionary
15140      can_use_type_feedback = false;
15141    }
15142  }
15143
15144  Handle<JSArray> array;
15145  if (!site.is_null() && can_use_type_feedback) {
15146    ElementsKind to_kind = site->GetElementsKind();
15147    if (holey && !IsFastHoleyElementsKind(to_kind)) {
15148      to_kind = GetHoleyElementsKind(to_kind);
15149      // Update the allocation site info to reflect the advice alteration.
15150      site->SetElementsKind(to_kind);
15151    }
15152
15153    // We should allocate with an initial map that reflects the allocation site
15154    // advice. Therefore we use AllocateJSObjectFromMap instead of passing
15155    // the constructor.
15156    Handle<Map> initial_map(constructor->initial_map(), isolate);
15157    if (to_kind != initial_map->elements_kind()) {
15158      initial_map = Map::AsElementsKind(initial_map, to_kind);
15159    }
15160
15161    // If we don't care to track arrays of to_kind ElementsKind, then
15162    // don't emit a memento for them.
15163    Handle<AllocationSite> allocation_site;
15164    if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) {
15165      allocation_site = site;
15166    }
15167
15168    array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
15169        initial_map, NOT_TENURED, true, allocation_site));
15170  } else {
15171    array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
15172
15173    // We might need to transition to holey
15174    ElementsKind kind = constructor->initial_map()->elements_kind();
15175    if (holey && !IsFastHoleyElementsKind(kind)) {
15176      kind = GetHoleyElementsKind(kind);
15177      JSObject::TransitionElementsKind(array, kind);
15178    }
15179  }
15180
15181  factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
15182
15183  ElementsKind old_kind = array->GetElementsKind();
15184  RETURN_FAILURE_ON_EXCEPTION(
15185      isolate, ArrayConstructInitializeElements(array, caller_args));
15186  if (!site.is_null() &&
15187      (old_kind != array->GetElementsKind() ||
15188       !can_use_type_feedback)) {
15189    // The arguments passed in caused a transition. This kind of complexity
15190    // can't be dealt with in the inlined hydrogen array constructor case.
15191    // We must mark the allocationsite as un-inlinable.
15192    site->SetDoNotInlineCall();
15193  }
15194  return *array;
15195}
15196
15197
15198RUNTIME_FUNCTION(Runtime_ArrayConstructor) {
15199  HandleScope scope(isolate);
15200  // If we get 2 arguments then they are the stub parameters (constructor, type
15201  // info).  If we get 4, then the first one is a pointer to the arguments
15202  // passed by the caller, and the last one is the length of the arguments
15203  // passed to the caller (redundant, but useful to check on the deoptimizer
15204  // with an assert).
15205  Arguments empty_args(0, NULL);
15206  bool no_caller_args = args.length() == 2;
15207  DCHECK(no_caller_args || args.length() == 4);
15208  int parameters_start = no_caller_args ? 0 : 1;
15209  Arguments* caller_args = no_caller_args
15210      ? &empty_args
15211      : reinterpret_cast<Arguments*>(args[0]);
15212  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15213  CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
15214#ifdef DEBUG
15215  if (!no_caller_args) {
15216    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
15217    DCHECK(arg_count == caller_args->length());
15218  }
15219#endif
15220
15221  Handle<AllocationSite> site;
15222  if (!type_info.is_null() &&
15223      *type_info != isolate->heap()->undefined_value()) {
15224    site = Handle<AllocationSite>::cast(type_info);
15225    DCHECK(!site->SitePointsToLiteral());
15226  }
15227
15228  return ArrayConstructorCommon(isolate,
15229                                constructor,
15230                                site,
15231                                caller_args);
15232}
15233
15234
15235RUNTIME_FUNCTION(Runtime_InternalArrayConstructor) {
15236  HandleScope scope(isolate);
15237  Arguments empty_args(0, NULL);
15238  bool no_caller_args = args.length() == 1;
15239  DCHECK(no_caller_args || args.length() == 3);
15240  int parameters_start = no_caller_args ? 0 : 1;
15241  Arguments* caller_args = no_caller_args
15242      ? &empty_args
15243      : reinterpret_cast<Arguments*>(args[0]);
15244  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15245#ifdef DEBUG
15246  if (!no_caller_args) {
15247    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
15248    DCHECK(arg_count == caller_args->length());
15249  }
15250#endif
15251  return ArrayConstructorCommon(isolate,
15252                                constructor,
15253                                Handle<AllocationSite>::null(),
15254                                caller_args);
15255}
15256
15257
15258RUNTIME_FUNCTION(Runtime_NormalizeElements) {
15259  HandleScope scope(isolate);
15260  DCHECK(args.length() == 1);
15261  CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
15262  RUNTIME_ASSERT(!array->HasExternalArrayElements() &&
15263                 !array->HasFixedTypedArrayElements());
15264  JSObject::NormalizeElements(array);
15265  return *array;
15266}
15267
15268
15269RUNTIME_FUNCTION(Runtime_MaxSmi) {
15270  SealHandleScope shs(isolate);
15271  DCHECK(args.length() == 0);
15272  return Smi::FromInt(Smi::kMaxValue);
15273}
15274
15275
15276// TODO(dcarney): remove this function when TurboFan supports it.
15277// Takes the object to be iterated over and the result of GetPropertyNamesFast
15278// Returns pair (cache_array, cache_type).
15279RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ForInInit) {
15280  SealHandleScope scope(isolate);
15281  DCHECK(args.length() == 2);
15282  // This simulates CONVERT_ARG_HANDLE_CHECKED for calls returning pairs.
15283  // Not worth creating a macro atm as this function should be removed.
15284  if (!args[0]->IsJSReceiver() || !args[1]->IsObject()) {
15285    Object* error = isolate->ThrowIllegalOperation();
15286    return MakePair(error, isolate->heap()->undefined_value());
15287  }
15288  Handle<JSReceiver> object = args.at<JSReceiver>(0);
15289  Handle<Object> cache_type = args.at<Object>(1);
15290  if (cache_type->IsMap()) {
15291    // Enum cache case.
15292    if (Map::EnumLengthBits::decode(Map::cast(*cache_type)->bit_field3()) ==
15293        0) {
15294      // 0 length enum.
15295      // Can't handle this case in the graph builder,
15296      // so transform it into the empty fixed array case.
15297      return MakePair(isolate->heap()->empty_fixed_array(), Smi::FromInt(1));
15298    }
15299    return MakePair(object->map()->instance_descriptors()->GetEnumCache(),
15300                    *cache_type);
15301  } else {
15302    // FixedArray case.
15303    Smi* new_cache_type = Smi::FromInt(object->IsJSProxy() ? 0 : 1);
15304    return MakePair(*Handle<FixedArray>::cast(cache_type), new_cache_type);
15305  }
15306}
15307
15308
15309// TODO(dcarney): remove this function when TurboFan supports it.
15310RUNTIME_FUNCTION(Runtime_ForInCacheArrayLength) {
15311  SealHandleScope shs(isolate);
15312  DCHECK(args.length() == 2);
15313  CONVERT_ARG_HANDLE_CHECKED(Object, cache_type, 0);
15314  CONVERT_ARG_HANDLE_CHECKED(FixedArray, array, 1);
15315  int length = 0;
15316  if (cache_type->IsMap()) {
15317    length = Map::cast(*cache_type)->EnumLength();
15318  } else {
15319    DCHECK(cache_type->IsSmi());
15320    length = array->length();
15321  }
15322  return Smi::FromInt(length);
15323}
15324
15325
15326// TODO(dcarney): remove this function when TurboFan supports it.
15327// Takes (the object to be iterated over,
15328//        cache_array from ForInInit,
15329//        cache_type from ForInInit,
15330//        the current index)
15331// Returns pair (array[index], needs_filtering).
15332RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ForInNext) {
15333  SealHandleScope scope(isolate);
15334  DCHECK(args.length() == 4);
15335  int32_t index;
15336  // This simulates CONVERT_ARG_HANDLE_CHECKED for calls returning pairs.
15337  // Not worth creating a macro atm as this function should be removed.
15338  if (!args[0]->IsJSReceiver() || !args[1]->IsFixedArray() ||
15339      !args[2]->IsObject() || !args[3]->ToInt32(&index)) {
15340    Object* error = isolate->ThrowIllegalOperation();
15341    return MakePair(error, isolate->heap()->undefined_value());
15342  }
15343  Handle<JSReceiver> object = args.at<JSReceiver>(0);
15344  Handle<FixedArray> array = args.at<FixedArray>(1);
15345  Handle<Object> cache_type = args.at<Object>(2);
15346  // Figure out first if a slow check is needed for this object.
15347  bool slow_check_needed = false;
15348  if (cache_type->IsMap()) {
15349    if (object->map() != Map::cast(*cache_type)) {
15350      // Object transitioned.  Need slow check.
15351      slow_check_needed = true;
15352    }
15353  } else {
15354    // No slow check needed for proxies.
15355    slow_check_needed = Smi::cast(*cache_type)->value() == 1;
15356  }
15357  return MakePair(array->get(index),
15358                  isolate->heap()->ToBoolean(slow_check_needed));
15359}
15360
15361
15362// ----------------------------------------------------------------------------
15363// Reference implementation for inlined runtime functions.  Only used when the
15364// compiler does not support a certain intrinsic.  Don't optimize these, but
15365// implement the intrinsic in the respective compiler instead.
15366
15367// TODO(mstarzinger): These are place-holder stubs for TurboFan and will
15368// eventually all have a C++ implementation and this macro will be gone.
15369#define U(name)                               \
15370  RUNTIME_FUNCTION(RuntimeReference_##name) { \
15371    UNIMPLEMENTED();                          \
15372    return NULL;                              \
15373  }
15374
15375U(IsStringWrapperSafeForDefaultValueOf)
15376U(DebugBreakInOptimizedCode)
15377
15378#undef U
15379
15380
15381RUNTIME_FUNCTION(RuntimeReference_IsSmi) {
15382  SealHandleScope shs(isolate);
15383  DCHECK(args.length() == 1);
15384  CONVERT_ARG_CHECKED(Object, obj, 0);
15385  return isolate->heap()->ToBoolean(obj->IsSmi());
15386}
15387
15388
15389RUNTIME_FUNCTION(RuntimeReference_IsNonNegativeSmi) {
15390  SealHandleScope shs(isolate);
15391  DCHECK(args.length() == 1);
15392  CONVERT_ARG_CHECKED(Object, obj, 0);
15393  return isolate->heap()->ToBoolean(obj->IsSmi() &&
15394                                    Smi::cast(obj)->value() >= 0);
15395}
15396
15397
15398RUNTIME_FUNCTION(RuntimeReference_IsArray) {
15399  SealHandleScope shs(isolate);
15400  DCHECK(args.length() == 1);
15401  CONVERT_ARG_CHECKED(Object, obj, 0);
15402  return isolate->heap()->ToBoolean(obj->IsJSArray());
15403}
15404
15405
15406RUNTIME_FUNCTION(RuntimeReference_IsRegExp) {
15407  SealHandleScope shs(isolate);
15408  DCHECK(args.length() == 1);
15409  CONVERT_ARG_CHECKED(Object, obj, 0);
15410  return isolate->heap()->ToBoolean(obj->IsJSRegExp());
15411}
15412
15413
15414RUNTIME_FUNCTION(RuntimeReference_IsConstructCall) {
15415  SealHandleScope shs(isolate);
15416  DCHECK(args.length() == 0);
15417  JavaScriptFrameIterator it(isolate);
15418  JavaScriptFrame* frame = it.frame();
15419  return isolate->heap()->ToBoolean(frame->IsConstructor());
15420}
15421
15422
15423RUNTIME_FUNCTION(RuntimeReference_CallFunction) {
15424  SealHandleScope shs(isolate);
15425  return __RT_impl_Runtime_Call(args, isolate);
15426}
15427
15428
15429RUNTIME_FUNCTION(RuntimeReference_ArgumentsLength) {
15430  SealHandleScope shs(isolate);
15431  DCHECK(args.length() == 0);
15432  JavaScriptFrameIterator it(isolate);
15433  JavaScriptFrame* frame = it.frame();
15434  return Smi::FromInt(frame->GetArgumentsLength());
15435}
15436
15437
15438RUNTIME_FUNCTION(RuntimeReference_Arguments) {
15439  SealHandleScope shs(isolate);
15440  return __RT_impl_Runtime_GetArgumentsProperty(args, isolate);
15441}
15442
15443
15444RUNTIME_FUNCTION(RuntimeReference_ValueOf) {
15445  SealHandleScope shs(isolate);
15446  DCHECK(args.length() == 1);
15447  CONVERT_ARG_CHECKED(Object, obj, 0);
15448  if (!obj->IsJSValue()) return obj;
15449  return JSValue::cast(obj)->value();
15450}
15451
15452
15453RUNTIME_FUNCTION(RuntimeReference_SetValueOf) {
15454  SealHandleScope shs(isolate);
15455  DCHECK(args.length() == 2);
15456  CONVERT_ARG_CHECKED(Object, obj, 0);
15457  CONVERT_ARG_CHECKED(Object, value, 1);
15458  if (!obj->IsJSValue()) return value;
15459  JSValue::cast(obj)->set_value(value);
15460  return value;
15461}
15462
15463
15464RUNTIME_FUNCTION(RuntimeReference_DateField) {
15465  SealHandleScope shs(isolate);
15466  DCHECK(args.length() == 2);
15467  CONVERT_ARG_CHECKED(Object, obj, 0);
15468  CONVERT_SMI_ARG_CHECKED(index, 1);
15469  if (!obj->IsJSDate()) {
15470    HandleScope scope(isolate);
15471    THROW_NEW_ERROR_RETURN_FAILURE(
15472        isolate,
15473        NewTypeError("not_date_object", HandleVector<Object>(NULL, 0)));
15474  }
15475  JSDate* date = JSDate::cast(obj);
15476  if (index == 0) return date->value();
15477  return JSDate::GetField(date, Smi::FromInt(index));
15478}
15479
15480
15481RUNTIME_FUNCTION(RuntimeReference_StringCharFromCode) {
15482  SealHandleScope shs(isolate);
15483  return __RT_impl_Runtime_CharFromCode(args, isolate);
15484}
15485
15486
15487RUNTIME_FUNCTION(RuntimeReference_StringCharAt) {
15488  SealHandleScope shs(isolate);
15489  DCHECK(args.length() == 2);
15490  if (!args[0]->IsString()) return Smi::FromInt(0);
15491  if (!args[1]->IsNumber()) return Smi::FromInt(0);
15492  if (std::isinf(args.number_at(1))) return isolate->heap()->empty_string();
15493  Object* code = __RT_impl_Runtime_StringCharCodeAtRT(args, isolate);
15494  if (code->IsNaN()) return isolate->heap()->empty_string();
15495  return __RT_impl_Runtime_CharFromCode(Arguments(1, &code), isolate);
15496}
15497
15498
15499RUNTIME_FUNCTION(RuntimeReference_OneByteSeqStringSetChar) {
15500  SealHandleScope shs(isolate);
15501  DCHECK(args.length() == 3);
15502  CONVERT_INT32_ARG_CHECKED(index, 0);
15503  CONVERT_INT32_ARG_CHECKED(value, 1);
15504  CONVERT_ARG_CHECKED(SeqOneByteString, string, 2);
15505  string->SeqOneByteStringSet(index, value);
15506  return string;
15507}
15508
15509
15510RUNTIME_FUNCTION(RuntimeReference_TwoByteSeqStringSetChar) {
15511  SealHandleScope shs(isolate);
15512  DCHECK(args.length() == 3);
15513  CONVERT_INT32_ARG_CHECKED(index, 0);
15514  CONVERT_INT32_ARG_CHECKED(value, 1);
15515  CONVERT_ARG_CHECKED(SeqTwoByteString, string, 2);
15516  string->SeqTwoByteStringSet(index, value);
15517  return string;
15518}
15519
15520
15521RUNTIME_FUNCTION(RuntimeReference_ObjectEquals) {
15522  SealHandleScope shs(isolate);
15523  DCHECK(args.length() == 2);
15524  CONVERT_ARG_CHECKED(Object, obj1, 0);
15525  CONVERT_ARG_CHECKED(Object, obj2, 1);
15526  return isolate->heap()->ToBoolean(obj1 == obj2);
15527}
15528
15529
15530RUNTIME_FUNCTION(RuntimeReference_IsObject) {
15531  SealHandleScope shs(isolate);
15532  DCHECK(args.length() == 1);
15533  CONVERT_ARG_CHECKED(Object, obj, 0);
15534  if (!obj->IsHeapObject()) return isolate->heap()->false_value();
15535  if (obj->IsNull()) return isolate->heap()->true_value();
15536  if (obj->IsUndetectableObject()) return isolate->heap()->false_value();
15537  Map* map = HeapObject::cast(obj)->map();
15538  bool is_non_callable_spec_object =
15539      map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE &&
15540      map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE;
15541  return isolate->heap()->ToBoolean(is_non_callable_spec_object);
15542}
15543
15544
15545RUNTIME_FUNCTION(RuntimeReference_IsFunction) {
15546  SealHandleScope shs(isolate);
15547  DCHECK(args.length() == 1);
15548  CONVERT_ARG_CHECKED(Object, obj, 0);
15549  return isolate->heap()->ToBoolean(obj->IsJSFunction());
15550}
15551
15552
15553RUNTIME_FUNCTION(RuntimeReference_IsUndetectableObject) {
15554  SealHandleScope shs(isolate);
15555  DCHECK(args.length() == 1);
15556  CONVERT_ARG_CHECKED(Object, obj, 0);
15557  return isolate->heap()->ToBoolean(obj->IsUndetectableObject());
15558}
15559
15560
15561RUNTIME_FUNCTION(RuntimeReference_IsSpecObject) {
15562  SealHandleScope shs(isolate);
15563  DCHECK(args.length() == 1);
15564  CONVERT_ARG_CHECKED(Object, obj, 0);
15565  return isolate->heap()->ToBoolean(obj->IsSpecObject());
15566}
15567
15568
15569RUNTIME_FUNCTION(RuntimeReference_MathPow) {
15570  SealHandleScope shs(isolate);
15571  return __RT_impl_Runtime_MathPowSlow(args, isolate);
15572}
15573
15574
15575RUNTIME_FUNCTION(RuntimeReference_IsMinusZero) {
15576  SealHandleScope shs(isolate);
15577  DCHECK(args.length() == 1);
15578  CONVERT_ARG_CHECKED(Object, obj, 0);
15579  if (!obj->IsHeapNumber()) return isolate->heap()->false_value();
15580  HeapNumber* number = HeapNumber::cast(obj);
15581  return isolate->heap()->ToBoolean(IsMinusZero(number->value()));
15582}
15583
15584
15585RUNTIME_FUNCTION(RuntimeReference_HasCachedArrayIndex) {
15586  SealHandleScope shs(isolate);
15587  DCHECK(args.length() == 1);
15588  return isolate->heap()->false_value();
15589}
15590
15591
15592RUNTIME_FUNCTION(RuntimeReference_GetCachedArrayIndex) {
15593  SealHandleScope shs(isolate);
15594  DCHECK(args.length() == 1);
15595  return isolate->heap()->undefined_value();
15596}
15597
15598
15599RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) {
15600  SealHandleScope shs(isolate);
15601  DCHECK(args.length() == 2);
15602  return isolate->heap()->undefined_value();
15603}
15604
15605
15606RUNTIME_FUNCTION(RuntimeReference_GeneratorNext) {
15607  UNREACHABLE();  // Optimization disabled in SetUpGenerators().
15608  return NULL;
15609}
15610
15611
15612RUNTIME_FUNCTION(RuntimeReference_GeneratorThrow) {
15613  UNREACHABLE();  // Optimization disabled in SetUpGenerators().
15614  return NULL;
15615}
15616
15617
15618RUNTIME_FUNCTION(RuntimeReference_ClassOf) {
15619  SealHandleScope shs(isolate);
15620  DCHECK(args.length() == 1);
15621  CONVERT_ARG_CHECKED(Object, obj, 0);
15622  if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
15623  return JSReceiver::cast(obj)->class_name();
15624}
15625
15626
15627RUNTIME_FUNCTION(RuntimeReference_StringCharCodeAt) {
15628  SealHandleScope shs(isolate);
15629  DCHECK(args.length() == 2);
15630  if (!args[0]->IsString()) return isolate->heap()->undefined_value();
15631  if (!args[1]->IsNumber()) return isolate->heap()->undefined_value();
15632  if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value();
15633  return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate);
15634}
15635
15636
15637RUNTIME_FUNCTION(RuntimeReference_StringAdd) {
15638  SealHandleScope shs(isolate);
15639  return __RT_impl_Runtime_StringAdd(args, isolate);
15640}
15641
15642
15643RUNTIME_FUNCTION(RuntimeReference_SubString) {
15644  SealHandleScope shs(isolate);
15645  return __RT_impl_Runtime_SubString(args, isolate);
15646}
15647
15648
15649RUNTIME_FUNCTION(RuntimeReference_StringCompare) {
15650  SealHandleScope shs(isolate);
15651  return __RT_impl_Runtime_StringCompare(args, isolate);
15652}
15653
15654
15655RUNTIME_FUNCTION(RuntimeReference_RegExpExec) {
15656  SealHandleScope shs(isolate);
15657  return __RT_impl_Runtime_RegExpExecRT(args, isolate);
15658}
15659
15660
15661RUNTIME_FUNCTION(RuntimeReference_RegExpConstructResult) {
15662  SealHandleScope shs(isolate);
15663  return __RT_impl_Runtime_RegExpConstructResult(args, isolate);
15664}
15665
15666
15667RUNTIME_FUNCTION(RuntimeReference_GetFromCache) {
15668  HandleScope scope(isolate);
15669  DCHECK(args.length() == 2);
15670  CONVERT_SMI_ARG_CHECKED(id, 0);
15671  args[0] = isolate->native_context()->jsfunction_result_caches()->get(id);
15672  return __RT_impl_Runtime_GetFromCache(args, isolate);
15673}
15674
15675
15676RUNTIME_FUNCTION(RuntimeReference_NumberToString) {
15677  SealHandleScope shs(isolate);
15678  return __RT_impl_Runtime_NumberToStringRT(args, isolate);
15679}
15680
15681
15682RUNTIME_FUNCTION(RuntimeReference_DebugIsActive) {
15683  SealHandleScope shs(isolate);
15684  return Smi::FromInt(isolate->debug()->is_active());
15685}
15686
15687
15688// ----------------------------------------------------------------------------
15689// Implementation of Runtime
15690
15691#define F(name, number_of_args, result_size)                                  \
15692  {                                                                           \
15693    Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
15694        number_of_args, result_size                                           \
15695  }                                                                           \
15696  ,
15697
15698
15699#define I(name, number_of_args, result_size)                                \
15700  {                                                                         \
15701    Runtime::kInline##name, Runtime::INLINE, "_" #name,                     \
15702        FUNCTION_ADDR(RuntimeReference_##name), number_of_args, result_size \
15703  }                                                                         \
15704  ,
15705
15706
15707#define IO(name, number_of_args, result_size)                              \
15708  {                                                                        \
15709    Runtime::kInlineOptimized##name, Runtime::INLINE_OPTIMIZED, "_" #name, \
15710        FUNCTION_ADDR(Runtime_##name), number_of_args, result_size         \
15711  }                                                                        \
15712  ,
15713
15714
15715static const Runtime::Function kIntrinsicFunctions[] = {
15716  RUNTIME_FUNCTION_LIST(F)
15717  INLINE_OPTIMIZED_FUNCTION_LIST(F)
15718  INLINE_FUNCTION_LIST(I)
15719  INLINE_OPTIMIZED_FUNCTION_LIST(IO)
15720};
15721
15722#undef IO
15723#undef I
15724#undef F
15725
15726
15727void Runtime::InitializeIntrinsicFunctionNames(Isolate* isolate,
15728                                               Handle<NameDictionary> dict) {
15729  DCHECK(dict->NumberOfElements() == 0);
15730  HandleScope scope(isolate);
15731  for (int i = 0; i < kNumFunctions; ++i) {
15732    const char* name = kIntrinsicFunctions[i].name;
15733    if (name == NULL) continue;
15734    Handle<NameDictionary> new_dict = NameDictionary::Add(
15735        dict,
15736        isolate->factory()->InternalizeUtf8String(name),
15737        Handle<Smi>(Smi::FromInt(i), isolate),
15738        PropertyDetails(NONE, NORMAL, Representation::None()));
15739    // The dictionary does not need to grow.
15740    CHECK(new_dict.is_identical_to(dict));
15741  }
15742}
15743
15744
15745const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
15746  Heap* heap = name->GetHeap();
15747  int entry = heap->intrinsic_function_names()->FindEntry(name);
15748  if (entry != kNotFound) {
15749    Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
15750    int function_index = Smi::cast(smi_index)->value();
15751    return &(kIntrinsicFunctions[function_index]);
15752  }
15753  return NULL;
15754}
15755
15756
15757const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
15758  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
15759    if (entry == kIntrinsicFunctions[i].entry) {
15760      return &(kIntrinsicFunctions[i]);
15761    }
15762  }
15763  return NULL;
15764}
15765
15766
15767const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
15768  return &(kIntrinsicFunctions[static_cast<int>(id)]);
15769}
15770
15771} }  // namespace v8::internal
15772