1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29#include <limits>
30
31#include "v8.h"
32
33#include "accessors.h"
34#include "api.h"
35#include "arguments.h"
36#include "bootstrapper.h"
37#include "codegen.h"
38#include "compilation-cache.h"
39#include "compiler.h"
40#include "cpu.h"
41#include "cpu-profiler.h"
42#include "dateparser-inl.h"
43#include "debug.h"
44#include "deoptimizer.h"
45#include "date.h"
46#include "execution.h"
47#include "full-codegen.h"
48#include "global-handles.h"
49#include "isolate-inl.h"
50#include "jsregexp.h"
51#include "jsregexp-inl.h"
52#include "json-parser.h"
53#include "json-stringifier.h"
54#include "liveedit.h"
55#include "misc-intrinsics.h"
56#include "parser.h"
57#include "platform.h"
58#include "runtime-profiler.h"
59#include "runtime.h"
60#include "scopeinfo.h"
61#include "smart-pointers.h"
62#include "string-search.h"
63#include "stub-cache.h"
64#include "uri.h"
65#include "v8conversions.h"
66#include "v8threads.h"
67#include "vm-state-inl.h"
68
69#ifdef V8_I18N_SUPPORT
70#include "i18n.h"
71#include "unicode/brkiter.h"
72#include "unicode/calendar.h"
73#include "unicode/coll.h"
74#include "unicode/curramt.h"
75#include "unicode/datefmt.h"
76#include "unicode/dcfmtsym.h"
77#include "unicode/decimfmt.h"
78#include "unicode/dtfmtsym.h"
79#include "unicode/dtptngen.h"
80#include "unicode/locid.h"
81#include "unicode/numfmt.h"
82#include "unicode/numsys.h"
83#include "unicode/smpdtfmt.h"
84#include "unicode/timezone.h"
85#include "unicode/uchar.h"
86#include "unicode/ucol.h"
87#include "unicode/ucurr.h"
88#include "unicode/uloc.h"
89#include "unicode/unum.h"
90#include "unicode/uversion.h"
91#endif
92
93#ifndef _STLP_VENDOR_CSTD
94// STLPort doesn't import fpclassify and isless into the std namespace.
95using std::fpclassify;
96using std::isless;
97#endif
98
99namespace v8 {
100namespace internal {
101
102
103#define RUNTIME_ASSERT(value) \
104  if (!(value)) return isolate->ThrowIllegalOperation();
105
106// Cast the given object to a value of the specified type and store
107// it in a variable with the given name.  If the object is not of the
108// expected type call IllegalOperation and return.
109#define CONVERT_ARG_CHECKED(Type, name, index)                       \
110  RUNTIME_ASSERT(args[index]->Is##Type());                           \
111  Type* name = Type::cast(args[index]);
112
113#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
114  RUNTIME_ASSERT(args[index]->Is##Type());                           \
115  Handle<Type> name = args.at<Type>(index);
116
117// Cast the given object to a boolean and store it in a variable with
118// the given name.  If the object is not a boolean call IllegalOperation
119// and return.
120#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
121  RUNTIME_ASSERT(args[index]->IsBoolean());                          \
122  bool name = args[index]->IsTrue();
123
124// Cast the given argument to a Smi and store its value in an int variable
125// with the given name.  If the argument is not a Smi call IllegalOperation
126// and return.
127#define CONVERT_SMI_ARG_CHECKED(name, index)                         \
128  RUNTIME_ASSERT(args[index]->IsSmi());                              \
129  int name = args.smi_at(index);
130
131// Cast the given argument to a double and store it in a variable with
132// the given name.  If the argument is not a number (as opposed to
133// the number not-a-number) call IllegalOperation and return.
134#define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
135  RUNTIME_ASSERT(args[index]->IsNumber());                           \
136  double name = args.number_at(index);
137
138// Call the specified converter on the object *comand store the result in
139// a variable of the specified type with the given name.  If the
140// object is not a Number call IllegalOperation and return.
141#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
142  RUNTIME_ASSERT(obj->IsNumber());                                   \
143  type name = NumberTo##Type(obj);
144
145
146// Cast the given argument to PropertyDetails and store its value in a
147// variable with the given name.  If the argument is not a Smi call
148// IllegalOperation and return.
149#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
150  RUNTIME_ASSERT(args[index]->IsSmi());                              \
151  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
152
153
154// Assert that the given argument has a valid value for a StrictModeFlag
155// and store it in a StrictModeFlag variable with the given name.
156#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
157  RUNTIME_ASSERT(args[index]->IsSmi());                              \
158  RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
159                 args.smi_at(index) == kNonStrictMode);              \
160  StrictModeFlag name =                                              \
161      static_cast<StrictModeFlag>(args.smi_at(index));
162
163
164// Assert that the given argument has a valid value for a LanguageMode
165// and store it in a LanguageMode variable with the given name.
166#define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
167  ASSERT(args[index]->IsSmi());                                      \
168  ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
169         args.smi_at(index) == STRICT_MODE ||                        \
170         args.smi_at(index) == EXTENDED_MODE);                       \
171  LanguageMode name =                                                \
172      static_cast<LanguageMode>(args.smi_at(index));
173
174
175static Handle<Map> ComputeObjectLiteralMap(
176    Handle<Context> context,
177    Handle<FixedArray> constant_properties,
178    bool* is_result_from_cache) {
179  Isolate* isolate = context->GetIsolate();
180  int properties_length = constant_properties->length();
181  int number_of_properties = properties_length / 2;
182  // Check that there are only internal strings and array indices among keys.
183  int number_of_string_keys = 0;
184  for (int p = 0; p != properties_length; p += 2) {
185    Object* key = constant_properties->get(p);
186    uint32_t element_index = 0;
187    if (key->IsInternalizedString()) {
188      number_of_string_keys++;
189    } else if (key->ToArrayIndex(&element_index)) {
190      // An index key does not require space in the property backing store.
191      number_of_properties--;
192    } else {
193      // Bail out as a non-internalized-string non-index key makes caching
194      // impossible.
195      // ASSERT to make sure that the if condition after the loop is false.
196      ASSERT(number_of_string_keys != number_of_properties);
197      break;
198    }
199  }
200  // If we only have internalized strings and array indices among keys then we
201  // can use the map cache in the native context.
202  const int kMaxKeys = 10;
203  if ((number_of_string_keys == number_of_properties) &&
204      (number_of_string_keys < kMaxKeys)) {
205    // Create the fixed array with the key.
206    Handle<FixedArray> keys =
207        isolate->factory()->NewFixedArray(number_of_string_keys);
208    if (number_of_string_keys > 0) {
209      int index = 0;
210      for (int p = 0; p < properties_length; p += 2) {
211        Object* key = constant_properties->get(p);
212        if (key->IsInternalizedString()) {
213          keys->set(index++, key);
214        }
215      }
216      ASSERT(index == number_of_string_keys);
217    }
218    *is_result_from_cache = true;
219    return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
220  }
221  *is_result_from_cache = false;
222  return isolate->factory()->CopyMap(
223      Handle<Map>(context->object_function()->initial_map()),
224      number_of_properties);
225}
226
227
228static Handle<Object> CreateLiteralBoilerplate(
229    Isolate* isolate,
230    Handle<FixedArray> literals,
231    Handle<FixedArray> constant_properties);
232
233
234static Handle<Object> CreateObjectLiteralBoilerplate(
235    Isolate* isolate,
236    Handle<FixedArray> literals,
237    Handle<FixedArray> constant_properties,
238    bool should_have_fast_elements,
239    bool has_function_literal) {
240  // Get the native context from the literals array.  This is the
241  // context in which the function was created and we use the object
242  // function from this context to create the object literal.  We do
243  // not use the object function from the current native context
244  // because this might be the object function from another context
245  // which we should not have access to.
246  Handle<Context> context =
247      Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
248
249  // In case we have function literals, we want the object to be in
250  // slow properties mode for now. We don't go in the map cache because
251  // maps with constant functions can't be shared if the functions are
252  // not the same (which is the common case).
253  bool is_result_from_cache = false;
254  Handle<Map> map = has_function_literal
255      ? Handle<Map>(context->object_function()->initial_map())
256      : ComputeObjectLiteralMap(context,
257                                constant_properties,
258                                &is_result_from_cache);
259
260  Handle<JSObject> boilerplate =
261      isolate->factory()->NewJSObjectFromMap(
262          map, isolate->heap()->GetPretenureMode());
263
264  // Normalize the elements of the boilerplate to save space if needed.
265  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
266
267  // Add the constant properties to the boilerplate.
268  int length = constant_properties->length();
269  bool should_transform =
270      !is_result_from_cache && boilerplate->HasFastProperties();
271  if (should_transform || has_function_literal) {
272    // Normalize the properties of object to avoid n^2 behavior
273    // when extending the object multiple properties. Indicate the number of
274    // properties to be added.
275    JSObject::NormalizeProperties(
276        boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
277  }
278
279  // TODO(verwaest): Support tracking representations in the boilerplate.
280  for (int index = 0; index < length; index +=2) {
281    Handle<Object> key(constant_properties->get(index+0), isolate);
282    Handle<Object> value(constant_properties->get(index+1), isolate);
283    if (value->IsFixedArray()) {
284      // The value contains the constant_properties of a
285      // simple object or array literal.
286      Handle<FixedArray> array = Handle<FixedArray>::cast(value);
287      value = CreateLiteralBoilerplate(isolate, literals, array);
288      if (value.is_null()) return value;
289    }
290    Handle<Object> result;
291    uint32_t element_index = 0;
292    JSReceiver::StoreMode mode = value->IsJSObject()
293        ? JSReceiver::FORCE_FIELD
294        : JSReceiver::ALLOW_AS_CONSTANT;
295    if (key->IsInternalizedString()) {
296      if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
297        // Array index as string (uint32).
298        result = JSObject::SetOwnElement(
299            boilerplate, element_index, value, kNonStrictMode);
300      } else {
301        Handle<String> name(String::cast(*key));
302        ASSERT(!name->AsArrayIndex(&element_index));
303        result = JSObject::SetLocalPropertyIgnoreAttributes(
304            boilerplate, name, value, NONE,
305            Object::OPTIMAL_REPRESENTATION, mode);
306      }
307    } else if (key->ToArrayIndex(&element_index)) {
308      // Array index (uint32).
309      result = JSObject::SetOwnElement(
310          boilerplate, element_index, value, kNonStrictMode);
311    } else {
312      // Non-uint32 number.
313      ASSERT(key->IsNumber());
314      double num = key->Number();
315      char arr[100];
316      Vector<char> buffer(arr, ARRAY_SIZE(arr));
317      const char* str = DoubleToCString(num, buffer);
318      Handle<String> name =
319          isolate->factory()->NewStringFromAscii(CStrVector(str));
320      result = JSObject::SetLocalPropertyIgnoreAttributes(
321          boilerplate, name, value, NONE,
322          Object::OPTIMAL_REPRESENTATION, mode);
323    }
324    // If setting the property on the boilerplate throws an
325    // exception, the exception is converted to an empty handle in
326    // the handle based operations.  In that case, we need to
327    // convert back to an exception.
328    if (result.is_null()) return result;
329  }
330
331  // Transform to fast properties if necessary. For object literals with
332  // containing function literals we defer this operation until after all
333  // computed properties have been assigned so that we can generate
334  // constant function properties.
335  if (should_transform && !has_function_literal) {
336    JSObject::TransformToFastProperties(
337        boilerplate, boilerplate->map()->unused_property_fields());
338  }
339
340  return boilerplate;
341}
342
343
344MaybeObject* TransitionElements(Handle<Object> object,
345                                ElementsKind to_kind,
346                                Isolate* isolate) {
347  HandleScope scope(isolate);
348  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
349  ElementsKind from_kind =
350      Handle<JSObject>::cast(object)->map()->elements_kind();
351  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
352    Handle<Object> result = JSObject::TransitionElementsKind(
353        Handle<JSObject>::cast(object), to_kind);
354    if (result.is_null()) return isolate->ThrowIllegalOperation();
355    return *result;
356  }
357  return isolate->ThrowIllegalOperation();
358}
359
360
361static const int kSmiLiteralMinimumLength = 1024;
362
363
364Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
365    Isolate* isolate,
366    Handle<FixedArray> literals,
367    Handle<FixedArray> elements) {
368  // Create the JSArray.
369  Handle<JSFunction> constructor(
370      JSFunction::NativeContextFromLiterals(*literals)->array_function());
371
372  Handle<JSArray> object = Handle<JSArray>::cast(
373      isolate->factory()->NewJSObject(
374          constructor, isolate->heap()->GetPretenureMode()));
375
376  ElementsKind constant_elements_kind =
377      static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
378  Handle<FixedArrayBase> constant_elements_values(
379      FixedArrayBase::cast(elements->get(1)));
380
381  ASSERT(IsFastElementsKind(constant_elements_kind));
382  Context* native_context = isolate->context()->native_context();
383  Object* maybe_maps_array = native_context->js_array_maps();
384  ASSERT(!maybe_maps_array->IsUndefined());
385  Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
386      constant_elements_kind);
387  ASSERT(maybe_map->IsMap());
388  object->set_map(Map::cast(maybe_map));
389
390  Handle<FixedArrayBase> copied_elements_values;
391  if (IsFastDoubleElementsKind(constant_elements_kind)) {
392    ASSERT(FLAG_smi_only_arrays);
393    copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
394        Handle<FixedDoubleArray>::cast(constant_elements_values));
395  } else {
396    ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
397    const bool is_cow =
398        (constant_elements_values->map() ==
399         isolate->heap()->fixed_cow_array_map());
400    if (is_cow) {
401      copied_elements_values = constant_elements_values;
402#if DEBUG
403      Handle<FixedArray> fixed_array_values =
404          Handle<FixedArray>::cast(copied_elements_values);
405      for (int i = 0; i < fixed_array_values->length(); i++) {
406        ASSERT(!fixed_array_values->get(i)->IsFixedArray());
407      }
408#endif
409    } else {
410      Handle<FixedArray> fixed_array_values =
411          Handle<FixedArray>::cast(constant_elements_values);
412      Handle<FixedArray> fixed_array_values_copy =
413          isolate->factory()->CopyFixedArray(fixed_array_values);
414      copied_elements_values = fixed_array_values_copy;
415      for (int i = 0; i < fixed_array_values->length(); i++) {
416        Object* current = fixed_array_values->get(i);
417        if (current->IsFixedArray()) {
418          // The value contains the constant_properties of a
419          // simple object or array literal.
420          Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
421          Handle<Object> result =
422              CreateLiteralBoilerplate(isolate, literals, fa);
423          if (result.is_null()) return result;
424          fixed_array_values_copy->set(i, *result);
425        }
426      }
427    }
428  }
429  object->set_elements(*copied_elements_values);
430  object->set_length(Smi::FromInt(copied_elements_values->length()));
431
432  //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
433  //  on or the object is larger than the threshold.
434  if (!FLAG_smi_only_arrays &&
435      constant_elements_values->length() < kSmiLiteralMinimumLength) {
436    ElementsKind elements_kind = object->GetElementsKind();
437    if (!IsFastObjectElementsKind(elements_kind)) {
438      if (IsFastHoleyElementsKind(elements_kind)) {
439        CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
440                                  isolate)->IsFailure());
441      } else {
442        CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
443      }
444    }
445  }
446
447  object->ValidateElements();
448  return object;
449}
450
451
452static Handle<Object> CreateLiteralBoilerplate(
453    Isolate* isolate,
454    Handle<FixedArray> literals,
455    Handle<FixedArray> array) {
456  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
457  const bool kHasNoFunctionLiteral = false;
458  switch (CompileTimeValue::GetLiteralType(array)) {
459    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
460      return CreateObjectLiteralBoilerplate(isolate,
461                                            literals,
462                                            elements,
463                                            true,
464                                            kHasNoFunctionLiteral);
465    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
466      return CreateObjectLiteralBoilerplate(isolate,
467                                            literals,
468                                            elements,
469                                            false,
470                                            kHasNoFunctionLiteral);
471    case CompileTimeValue::ARRAY_LITERAL:
472      return Runtime::CreateArrayLiteralBoilerplate(
473          isolate, literals, elements);
474    default:
475      UNREACHABLE();
476      return Handle<Object>::null();
477  }
478}
479
480
481RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
482  HandleScope scope(isolate);
483  ASSERT(args.length() == 4);
484  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
485  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
486  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
487  CONVERT_SMI_ARG_CHECKED(flags, 3);
488  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
489  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
490
491  // Check if boilerplate exists. If not, create it first.
492  Handle<Object> boilerplate(literals->get(literals_index), isolate);
493  if (*boilerplate == isolate->heap()->undefined_value()) {
494    boilerplate = CreateObjectLiteralBoilerplate(isolate,
495                                                 literals,
496                                                 constant_properties,
497                                                 should_have_fast_elements,
498                                                 has_function_literal);
499    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
500    // Update the functions literal and return the boilerplate.
501    literals->set(literals_index, *boilerplate);
502  }
503  return JSObject::cast(*boilerplate)->DeepCopy(isolate);
504}
505
506
507RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
508  HandleScope scope(isolate);
509  ASSERT(args.length() == 4);
510  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
511  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
512  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
513  CONVERT_SMI_ARG_CHECKED(flags, 3);
514  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
515  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
516
517  // Check if boilerplate exists. If not, create it first.
518  Handle<Object> boilerplate(literals->get(literals_index), isolate);
519  if (*boilerplate == isolate->heap()->undefined_value()) {
520    boilerplate = CreateObjectLiteralBoilerplate(isolate,
521                                                 literals,
522                                                 constant_properties,
523                                                 should_have_fast_elements,
524                                                 has_function_literal);
525    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
526    // Update the functions literal and return the boilerplate.
527    literals->set(literals_index, *boilerplate);
528  }
529  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
530}
531
532
533static Handle<AllocationSite> GetLiteralAllocationSite(
534    Isolate* isolate,
535    Handle<FixedArray> literals,
536    int literals_index,
537    Handle<FixedArray> elements) {
538  // Check if boilerplate exists. If not, create it first.
539  Handle<Object> literal_site(literals->get(literals_index), isolate);
540  Handle<AllocationSite> site;
541  if (*literal_site == isolate->heap()->undefined_value()) {
542    ASSERT(*elements != isolate->heap()->empty_fixed_array());
543    Handle<Object> boilerplate =
544        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
545    if (boilerplate.is_null()) return site;
546    site = isolate->factory()->NewAllocationSite();
547    site->set_transition_info(*boilerplate);
548    literals->set(literals_index, *site);
549  } else {
550    site = Handle<AllocationSite>::cast(literal_site);
551  }
552
553  return site;
554}
555
556
557RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
558  HandleScope scope(isolate);
559  ASSERT(args.length() == 3);
560  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
561  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
562  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
563
564  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
565      literals_index, elements);
566  RETURN_IF_EMPTY_HANDLE(isolate, site);
567
568  JSObject* boilerplate = JSObject::cast(site->transition_info());
569  return boilerplate->DeepCopy(isolate);
570}
571
572
573RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
574  HandleScope scope(isolate);
575  ASSERT(args.length() == 3);
576  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
577  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
578  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
579
580  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
581      literals_index, elements);
582  RETURN_IF_EMPTY_HANDLE(isolate, site);
583
584  JSObject* boilerplate = JSObject::cast(site->transition_info());
585  if (boilerplate->elements()->map() ==
586      isolate->heap()->fixed_cow_array_map()) {
587    isolate->counters()->cow_arrays_created_runtime()->Increment();
588  }
589
590  AllocationSiteMode mode = AllocationSite::GetMode(
591      boilerplate->GetElementsKind());
592  if (mode == TRACK_ALLOCATION_SITE) {
593    return isolate->heap()->CopyJSObjectWithAllocationSite(
594        boilerplate, *site);
595  }
596
597  return isolate->heap()->CopyJSObject(boilerplate);
598}
599
600
601RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
602  HandleScope scope(isolate);
603  ASSERT(args.length() == 1);
604  Handle<Object> name(args[0], isolate);
605  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
606  Symbol* symbol;
607  MaybeObject* maybe = isolate->heap()->AllocateSymbol();
608  if (!maybe->To(&symbol)) return maybe;
609  if (name->IsString()) symbol->set_name(*name);
610  return symbol;
611}
612
613
614RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
615  SealHandleScope shs(isolate);
616  ASSERT(args.length() == 1);
617  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
618  return symbol->name();
619}
620
621
622RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
623  SealHandleScope shs(isolate);
624  ASSERT(args.length() == 2);
625  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
626  Object* prototype = args[1];
627  Object* used_prototype =
628      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
629  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
630}
631
632
633RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
634  SealHandleScope shs(isolate);
635  ASSERT(args.length() == 4);
636  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
637  Object* call_trap = args[1];
638  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
639  CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
640  Object* prototype = args[3];
641  Object* used_prototype =
642      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
643  return isolate->heap()->AllocateJSFunctionProxy(
644      handler, call_trap, construct_trap, used_prototype);
645}
646
647
648RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
649  SealHandleScope shs(isolate);
650  ASSERT(args.length() == 1);
651  Object* obj = args[0];
652  return isolate->heap()->ToBoolean(obj->IsJSProxy());
653}
654
655
656RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
657  SealHandleScope shs(isolate);
658  ASSERT(args.length() == 1);
659  Object* obj = args[0];
660  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
661}
662
663
664RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
665  SealHandleScope shs(isolate);
666  ASSERT(args.length() == 1);
667  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
668  return proxy->handler();
669}
670
671
672RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
673  SealHandleScope shs(isolate);
674  ASSERT(args.length() == 1);
675  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
676  return proxy->call_trap();
677}
678
679
680RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
681  SealHandleScope shs(isolate);
682  ASSERT(args.length() == 1);
683  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
684  return proxy->construct_trap();
685}
686
687
688RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
689  SealHandleScope shs(isolate);
690  ASSERT(args.length() == 1);
691  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
692  proxy->Fix();
693  return isolate->heap()->undefined_value();
694}
695
696
697void Runtime::FreeArrayBuffer(Isolate* isolate,
698                              JSArrayBuffer* phantom_array_buffer) {
699  if (phantom_array_buffer->is_external()) return;
700
701  size_t allocated_length = NumberToSize(
702      isolate, phantom_array_buffer->byte_length());
703
704  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
705      -static_cast<intptr_t>(allocated_length));
706  CHECK(V8::ArrayBufferAllocator() != NULL);
707  V8::ArrayBufferAllocator()->Free(
708      phantom_array_buffer->backing_store(),
709      allocated_length);
710}
711
712
713void Runtime::SetupArrayBuffer(Isolate* isolate,
714                               Handle<JSArrayBuffer> array_buffer,
715                               bool is_external,
716                               void* data,
717                               size_t allocated_length) {
718  ASSERT(array_buffer->GetInternalFieldCount() ==
719      v8::ArrayBuffer::kInternalFieldCount);
720  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
721    array_buffer->SetInternalField(i, Smi::FromInt(0));
722  }
723  array_buffer->set_backing_store(data);
724  array_buffer->set_flag(Smi::FromInt(0));
725  array_buffer->set_is_external(is_external);
726
727  Handle<Object> byte_length =
728      isolate->factory()->NewNumberFromSize(allocated_length);
729  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
730  array_buffer->set_byte_length(*byte_length);
731
732  array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
733  isolate->heap()->set_array_buffers_list(*array_buffer);
734  array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
735}
736
737
738bool Runtime::SetupArrayBufferAllocatingData(
739    Isolate* isolate,
740    Handle<JSArrayBuffer> array_buffer,
741    size_t allocated_length,
742    bool initialize) {
743  void* data;
744  CHECK(V8::ArrayBufferAllocator() != NULL);
745  if (allocated_length != 0) {
746    if (initialize) {
747      data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
748    } else {
749      data =
750        V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
751    }
752    if (data == NULL) return false;
753  } else {
754    data = NULL;
755  }
756
757  SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
758
759  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
760
761  return true;
762}
763
764
765RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
766  HandleScope scope(isolate);
767  ASSERT(args.length() == 2);
768  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
769  CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
770  size_t allocated_length;
771  if (byteLength->IsSmi()) {
772    allocated_length = Smi::cast(*byteLength)->value();
773  } else {
774    ASSERT(byteLength->IsHeapNumber());
775    double value = HeapNumber::cast(*byteLength)->value();
776
777    ASSERT(value >= 0);
778
779    if (value > std::numeric_limits<size_t>::max()) {
780      return isolate->Throw(
781          *isolate->factory()->NewRangeError("invalid_array_buffer_length",
782            HandleVector<Object>(NULL, 0)));
783    }
784
785    allocated_length = static_cast<size_t>(value);
786  }
787
788  if (!Runtime::SetupArrayBufferAllocatingData(isolate,
789                                               holder, allocated_length)) {
790      return isolate->Throw(*isolate->factory()->
791          NewRangeError("invalid_array_buffer_length",
792            HandleVector<Object>(NULL, 0)));
793  }
794
795  return *holder;
796}
797
798
799RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
800  SealHandleScope shs(isolate);
801  ASSERT(args.length() == 1);
802  CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
803  return holder->byte_length();
804}
805
806
807RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
808  HandleScope scope(isolate);
809  ASSERT(args.length() == 3);
810  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
811  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
812  CONVERT_DOUBLE_ARG_CHECKED(first, 2);
813  size_t start = static_cast<size_t>(first);
814  size_t target_length = NumberToSize(isolate, target->byte_length());
815
816  if (target_length == 0) return isolate->heap()->undefined_value();
817
818  ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
819  uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
820  uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
821  CopyBytes(target_data, source_data + start, target_length);
822  return isolate->heap()->undefined_value();
823}
824
825
826enum TypedArrayId {
827  // arrayIds below should be synchromized with typedarray.js natives.
828  ARRAY_ID_UINT8 = 1,
829  ARRAY_ID_INT8 = 2,
830  ARRAY_ID_UINT16 = 3,
831  ARRAY_ID_INT16 = 4,
832  ARRAY_ID_UINT32 = 5,
833  ARRAY_ID_INT32 = 6,
834  ARRAY_ID_FLOAT32 = 7,
835  ARRAY_ID_FLOAT64 = 8,
836  ARRAY_ID_UINT8C = 9
837};
838
839static void ArrayIdToTypeAndSize(
840    int arrayId, ExternalArrayType* array_type, size_t* element_size) {
841  switch (arrayId) {
842    case ARRAY_ID_UINT8:
843      *array_type = kExternalUnsignedByteArray;
844      *element_size = 1;
845      break;
846    case ARRAY_ID_INT8:
847      *array_type = kExternalByteArray;
848      *element_size = 1;
849      break;
850    case ARRAY_ID_UINT16:
851      *array_type = kExternalUnsignedShortArray;
852      *element_size = 2;
853      break;
854    case ARRAY_ID_INT16:
855      *array_type = kExternalShortArray;
856      *element_size = 2;
857      break;
858    case ARRAY_ID_UINT32:
859      *array_type = kExternalUnsignedIntArray;
860      *element_size = 4;
861      break;
862    case ARRAY_ID_INT32:
863      *array_type = kExternalIntArray;
864      *element_size = 4;
865      break;
866    case ARRAY_ID_FLOAT32:
867      *array_type = kExternalFloatArray;
868      *element_size = 4;
869      break;
870    case ARRAY_ID_FLOAT64:
871      *array_type = kExternalDoubleArray;
872      *element_size = 8;
873      break;
874    case ARRAY_ID_UINT8C:
875      *array_type = kExternalPixelArray;
876      *element_size = 1;
877      break;
878    default:
879      UNREACHABLE();
880  }
881}
882
883
884RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
885  HandleScope scope(isolate);
886  ASSERT(args.length() == 5);
887  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
888  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
889  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
890  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
891  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
892
893  ASSERT(holder->GetInternalFieldCount() ==
894      v8::ArrayBufferView::kInternalFieldCount);
895  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
896    holder->SetInternalField(i, Smi::FromInt(0));
897  }
898
899  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
900  size_t element_size = 1;  // Bogus initialization.
901  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
902
903  holder->set_buffer(*buffer);
904  holder->set_byte_offset(*byte_offset_object);
905  holder->set_byte_length(*byte_length_object);
906
907  size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
908  size_t byte_length = NumberToSize(isolate, *byte_length_object);
909  ASSERT(byte_length % element_size == 0);
910  size_t length = byte_length / element_size;
911
912  Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
913  holder->set_length(*length_obj);
914  holder->set_weak_next(buffer->weak_first_view());
915  buffer->set_weak_first_view(*holder);
916
917  Handle<ExternalArray> elements =
918      isolate->factory()->NewExternalArray(
919          static_cast<int>(length), array_type,
920          static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
921  holder->set_elements(*elements);
922  return isolate->heap()->undefined_value();
923}
924
925
926// Initializes a typed array from an array-like object.
927// If an array-like object happens to be a typed array of the same type,
928// initializes backing store using memove.
929//
930// Returns true if backing store was initialized or false otherwise.
931RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
932  HandleScope scope(isolate);
933  ASSERT(args.length() == 4);
934  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
935  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
936  CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
937  CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
938
939  ASSERT(holder->GetInternalFieldCount() ==
940      v8::ArrayBufferView::kInternalFieldCount);
941  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
942    holder->SetInternalField(i, Smi::FromInt(0));
943  }
944
945  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
946  size_t element_size = 1;  // Bogus initialization.
947  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
948
949  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
950  size_t length = NumberToSize(isolate, *length_obj);
951  if (length > (kMaxInt / element_size)) {
952    return isolate->Throw(*isolate->factory()->
953          NewRangeError("invalid_array_buffer_length",
954            HandleVector<Object>(NULL, 0)));
955  }
956  size_t byte_length = length * element_size;
957
958  // We assume that the caller of this function will initialize holder
959  // with the loop
960  //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
961  // If source is a typed array, this loop will always run to completion,
962  // so we are sure that the backing store will be initialized.
963  // Otherwise, we do not know (the indexing operation might throw).
964  // Hence we require zero initialization unless our source is a typed array.
965  bool should_zero_initialize = !source->IsJSTypedArray();
966
967  if (!Runtime::SetupArrayBufferAllocatingData(
968        isolate, buffer, byte_length, should_zero_initialize)) {
969    return isolate->Throw(*isolate->factory()->
970          NewRangeError("invalid_array_buffer_length",
971            HandleVector<Object>(NULL, 0)));
972  }
973
974  holder->set_buffer(*buffer);
975  holder->set_byte_offset(Smi::FromInt(0));
976  Handle<Object> byte_length_obj(
977      isolate->factory()->NewNumberFromSize(byte_length));
978  holder->set_byte_length(*byte_length_obj);
979  holder->set_length(*length_obj);
980  holder->set_weak_next(buffer->weak_first_view());
981  buffer->set_weak_first_view(*holder);
982
983  Handle<ExternalArray> elements =
984      isolate->factory()->NewExternalArray(
985          static_cast<int>(length), array_type,
986          static_cast<uint8_t*>(buffer->backing_store()));
987  holder->set_elements(*elements);
988
989  if (source->IsJSTypedArray()) {
990    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
991
992    if (typed_array->type() == holder->type()) {
993      uint8_t* backing_store =
994        static_cast<uint8_t*>(
995          JSArrayBuffer::cast(typed_array->buffer())->backing_store());
996      size_t source_byte_offset =
997          NumberToSize(isolate, typed_array->byte_offset());
998      OS::MemCopy(
999          buffer->backing_store(),
1000          backing_store + source_byte_offset,
1001          byte_length);
1002      return *isolate->factory()->true_value();
1003    } else {
1004      return *isolate->factory()->false_value();
1005    }
1006  }
1007
1008  return *isolate->factory()->false_value();
1009}
1010
1011
1012#define TYPED_ARRAY_GETTER(getter, accessor) \
1013  RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
1014    HandleScope scope(isolate);                                               \
1015    ASSERT(args.length() == 1);                                               \
1016    CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);                            \
1017    if (!holder->IsJSTypedArray())                                            \
1018      return isolate->Throw(*isolate->factory()->NewTypeError(                \
1019          "not_typed_array", HandleVector<Object>(NULL, 0)));                 \
1020    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));            \
1021    return typed_array->accessor();                                           \
1022  }
1023
1024TYPED_ARRAY_GETTER(Buffer, buffer)
1025TYPED_ARRAY_GETTER(ByteLength, byte_length)
1026TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1027TYPED_ARRAY_GETTER(Length, length)
1028
1029#undef TYPED_ARRAY_GETTER
1030
1031// Return codes for Runtime_TypedArraySetFastCases.
1032// Should be synchronized with typedarray.js natives.
1033enum TypedArraySetResultCodes {
1034  // Set from typed array of the same type.
1035  // This is processed by TypedArraySetFastCases
1036  TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1037  // Set from typed array of the different type, overlapping in memory.
1038  TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1039  // Set from typed array of the different type, non-overlapping.
1040  TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1041  // Set from non-typed array.
1042  TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1043};
1044
1045
1046RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1047  HandleScope scope(isolate);
1048  CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1049  CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1050  CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1051
1052  if (!target_obj->IsJSTypedArray())
1053    return isolate->Throw(*isolate->factory()->NewTypeError(
1054        "not_typed_array", HandleVector<Object>(NULL, 0)));
1055
1056  if (!source_obj->IsJSTypedArray())
1057    return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1058
1059  Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1060  Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1061  size_t offset = NumberToSize(isolate, *offset_obj);
1062  size_t target_length = NumberToSize(isolate, target->length());
1063  size_t source_length = NumberToSize(isolate, source->length());
1064  size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1065  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1066  if (offset > target_length ||
1067      offset + source_length > target_length ||
1068      offset + source_length < offset)  // overflow
1069    return isolate->Throw(*isolate->factory()->NewRangeError(
1070          "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1071
1072  size_t target_offset = NumberToSize(isolate, target->byte_offset());
1073  size_t source_offset = NumberToSize(isolate, source->byte_offset());
1074  uint8_t* target_base =
1075      static_cast<uint8_t*>(
1076        JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
1077  uint8_t* source_base =
1078      static_cast<uint8_t*>(
1079        JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
1080
1081  // Typed arrays of the same type: use memmove.
1082  if (target->type() == source->type()) {
1083    memmove(target_base + offset * target->element_size(),
1084        source_base, source_byte_length);
1085    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1086  }
1087
1088  // Typed arrays of different types over the same backing store
1089  if ((source_base <= target_base &&
1090        source_base + source_byte_length > target_base) ||
1091      (target_base <= source_base &&
1092        target_base + target_byte_length > source_base)) {
1093    // We do not support overlapping ArrayBuffers
1094    ASSERT(
1095      JSArrayBuffer::cast(target->buffer())->backing_store() ==
1096      JSArrayBuffer::cast(source->buffer())->backing_store());
1097    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1098  } else {  // Non-overlapping typed arrays
1099    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1100  }
1101}
1102
1103
1104RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1105  HandleScope scope(isolate);
1106  ASSERT(args.length() == 4);
1107  CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1108  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1109  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1110  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1111
1112  ASSERT(holder->GetInternalFieldCount() ==
1113      v8::ArrayBufferView::kInternalFieldCount);
1114  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1115    holder->SetInternalField(i, Smi::FromInt(0));
1116  }
1117
1118  holder->set_buffer(*buffer);
1119  ASSERT(byte_offset->IsNumber());
1120  ASSERT(
1121      NumberToSize(isolate, buffer->byte_length()) >=
1122        NumberToSize(isolate, *byte_offset)
1123        + NumberToSize(isolate, *byte_length));
1124  holder->set_byte_offset(*byte_offset);
1125  ASSERT(byte_length->IsNumber());
1126  holder->set_byte_length(*byte_length);
1127
1128  holder->set_weak_next(buffer->weak_first_view());
1129  buffer->set_weak_first_view(*holder);
1130
1131  return isolate->heap()->undefined_value();
1132}
1133
1134
1135RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1136  HandleScope scope(isolate);
1137  ASSERT(args.length() == 1);
1138  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1139  return data_view->buffer();
1140}
1141
1142
1143RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1144  HandleScope scope(isolate);
1145  ASSERT(args.length() == 1);
1146  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1147  return data_view->byte_offset();
1148}
1149
1150
1151RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1152  HandleScope scope(isolate);
1153  ASSERT(args.length() == 1);
1154  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1155  return data_view->byte_length();
1156}
1157
1158
1159inline static bool NeedToFlipBytes(bool is_little_endian) {
1160#ifdef V8_TARGET_LITTLE_ENDIAN
1161  return !is_little_endian;
1162#else
1163  return is_little_endian;
1164#endif
1165}
1166
1167
1168template<int n>
1169inline void CopyBytes(uint8_t* target, uint8_t* source) {
1170  for (int i = 0; i < n; i++) {
1171    *(target++) = *(source++);
1172  }
1173}
1174
1175
1176template<int n>
1177inline void FlipBytes(uint8_t* target, uint8_t* source) {
1178  source = source + (n-1);
1179  for (int i = 0; i < n; i++) {
1180    *(target++) = *(source--);
1181  }
1182}
1183
1184
1185template<typename T>
1186inline static bool DataViewGetValue(
1187    Isolate* isolate,
1188    Handle<JSDataView> data_view,
1189    Handle<Object> byte_offset_obj,
1190    bool is_little_endian,
1191    T* result) {
1192  size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1193  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1194
1195  size_t data_view_byte_offset =
1196      NumberToSize(isolate, data_view->byte_offset());
1197  size_t data_view_byte_length =
1198      NumberToSize(isolate, data_view->byte_length());
1199  if (byte_offset + sizeof(T) > data_view_byte_length ||
1200      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1201    return false;
1202  }
1203
1204  union Value {
1205    T data;
1206    uint8_t bytes[sizeof(T)];
1207  };
1208
1209  Value value;
1210  size_t buffer_offset = data_view_byte_offset + byte_offset;
1211  ASSERT(
1212      NumberToSize(isolate, buffer->byte_length())
1213      >= buffer_offset + sizeof(T));
1214  uint8_t* source =
1215        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1216  if (NeedToFlipBytes(is_little_endian)) {
1217    FlipBytes<sizeof(T)>(value.bytes, source);
1218  } else {
1219    CopyBytes<sizeof(T)>(value.bytes, source);
1220  }
1221  *result = value.data;
1222  return true;
1223}
1224
1225
1226template<typename T>
1227static bool DataViewSetValue(
1228    Isolate* isolate,
1229    Handle<JSDataView> data_view,
1230    Handle<Object> byte_offset_obj,
1231    bool is_little_endian,
1232    T data) {
1233  size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1234  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1235
1236  size_t data_view_byte_offset =
1237      NumberToSize(isolate, data_view->byte_offset());
1238  size_t data_view_byte_length =
1239      NumberToSize(isolate, data_view->byte_length());
1240  if (byte_offset + sizeof(T) > data_view_byte_length ||
1241      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1242    return false;
1243  }
1244
1245  union Value {
1246    T data;
1247    uint8_t bytes[sizeof(T)];
1248  };
1249
1250  Value value;
1251  value.data = data;
1252  size_t buffer_offset = data_view_byte_offset + byte_offset;
1253  ASSERT(
1254      NumberToSize(isolate, buffer->byte_length())
1255      >= buffer_offset + sizeof(T));
1256  uint8_t* target =
1257        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1258  if (NeedToFlipBytes(is_little_endian)) {
1259    FlipBytes<sizeof(T)>(target, value.bytes);
1260  } else {
1261    CopyBytes<sizeof(T)>(target, value.bytes);
1262  }
1263  return true;
1264}
1265
1266
1267#define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1268  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) {             \
1269    HandleScope scope(isolate);                                               \
1270    ASSERT(args.length() == 3);                                               \
1271    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1272    CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1273    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1274    Type result;                                                              \
1275    if (DataViewGetValue(                                                     \
1276          isolate, holder, offset, is_little_endian, &result)) {              \
1277      return isolate->heap()->Converter(result);                              \
1278    } else {                                                                  \
1279      return isolate->Throw(*isolate->factory()->NewRangeError(               \
1280          "invalid_data_view_accessor_offset",                                \
1281          HandleVector<Object>(NULL, 0)));                                    \
1282    }                                                                         \
1283  }
1284
1285DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1286DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1287DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1288DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1289DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1290DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1291DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1292DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1293
1294#undef DATA_VIEW_GETTER
1295
1296
1297template <typename T>
1298static T DataViewConvertValue(double value);
1299
1300
1301template <>
1302int8_t DataViewConvertValue<int8_t>(double value) {
1303  return static_cast<int8_t>(DoubleToInt32(value));
1304}
1305
1306
1307template <>
1308int16_t DataViewConvertValue<int16_t>(double value) {
1309  return static_cast<int16_t>(DoubleToInt32(value));
1310}
1311
1312
1313template <>
1314int32_t DataViewConvertValue<int32_t>(double value) {
1315  return DoubleToInt32(value);
1316}
1317
1318
1319template <>
1320uint8_t DataViewConvertValue<uint8_t>(double value) {
1321  return static_cast<uint8_t>(DoubleToUint32(value));
1322}
1323
1324
1325template <>
1326uint16_t DataViewConvertValue<uint16_t>(double value) {
1327  return static_cast<uint16_t>(DoubleToUint32(value));
1328}
1329
1330
1331template <>
1332uint32_t DataViewConvertValue<uint32_t>(double value) {
1333  return DoubleToUint32(value);
1334}
1335
1336
1337template <>
1338float DataViewConvertValue<float>(double value) {
1339  return static_cast<float>(value);
1340}
1341
1342
1343template <>
1344double DataViewConvertValue<double>(double value) {
1345  return value;
1346}
1347
1348
1349#define DATA_VIEW_SETTER(TypeName, Type)                                      \
1350  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) {             \
1351    HandleScope scope(isolate);                                               \
1352    ASSERT(args.length() == 4);                                               \
1353    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1354    CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1355    CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);                             \
1356    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1357    Type v = DataViewConvertValue<Type>(value->Number());                     \
1358    if (DataViewSetValue(                                                     \
1359          isolate, holder, offset, is_little_endian, v)) {                    \
1360      return isolate->heap()->undefined_value();                              \
1361    } else {                                                                  \
1362      return isolate->Throw(*isolate->factory()->NewRangeError(               \
1363          "invalid_data_view_accessor_offset",                                \
1364          HandleVector<Object>(NULL, 0)));                                    \
1365    }                                                                         \
1366  }
1367
1368DATA_VIEW_SETTER(Uint8, uint8_t)
1369DATA_VIEW_SETTER(Int8, int8_t)
1370DATA_VIEW_SETTER(Uint16, uint16_t)
1371DATA_VIEW_SETTER(Int16, int16_t)
1372DATA_VIEW_SETTER(Uint32, uint32_t)
1373DATA_VIEW_SETTER(Int32, int32_t)
1374DATA_VIEW_SETTER(Float32, float)
1375DATA_VIEW_SETTER(Float64, double)
1376
1377#undef DATA_VIEW_SETTER
1378
1379
1380RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1381  HandleScope scope(isolate);
1382  ASSERT(args.length() == 1);
1383  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1384  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1385  holder->set_table(*table);
1386  return *holder;
1387}
1388
1389
1390RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1391  HandleScope scope(isolate);
1392  ASSERT(args.length() == 2);
1393  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1394  Handle<Object> key(args[1], isolate);
1395  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1396  table = ObjectHashSetAdd(table, key);
1397  holder->set_table(*table);
1398  return isolate->heap()->undefined_value();
1399}
1400
1401
1402RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1403  HandleScope scope(isolate);
1404  ASSERT(args.length() == 2);
1405  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1406  Handle<Object> key(args[1], isolate);
1407  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1408  return isolate->heap()->ToBoolean(table->Contains(*key));
1409}
1410
1411
1412RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1413  HandleScope scope(isolate);
1414  ASSERT(args.length() == 2);
1415  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1416  Handle<Object> key(args[1], isolate);
1417  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1418  table = ObjectHashSetRemove(table, key);
1419  holder->set_table(*table);
1420  return isolate->heap()->undefined_value();
1421}
1422
1423
1424RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1425  HandleScope scope(isolate);
1426  ASSERT(args.length() == 1);
1427  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1428  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1429  return Smi::FromInt(table->NumberOfElements());
1430}
1431
1432
1433RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1434  HandleScope scope(isolate);
1435  ASSERT(args.length() == 1);
1436  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1437  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1438  holder->set_table(*table);
1439  return *holder;
1440}
1441
1442
1443RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1444  HandleScope scope(isolate);
1445  ASSERT(args.length() == 2);
1446  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1447  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1448  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1449  Handle<Object> lookup(table->Lookup(*key), isolate);
1450  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1451}
1452
1453
1454RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1455  HandleScope scope(isolate);
1456  ASSERT(args.length() == 2);
1457  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1458  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1459  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1460  Handle<Object> lookup(table->Lookup(*key), isolate);
1461  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1462}
1463
1464
1465RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1466  HandleScope scope(isolate);
1467  ASSERT(args.length() == 2);
1468  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1469  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1470  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1471  Handle<Object> lookup(table->Lookup(*key), isolate);
1472  Handle<ObjectHashTable> new_table =
1473      PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1474  holder->set_table(*new_table);
1475  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1476}
1477
1478
1479RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1480  HandleScope scope(isolate);
1481  ASSERT(args.length() == 3);
1482  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1483  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1484  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1485  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1486  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1487  holder->set_table(*new_table);
1488  return isolate->heap()->undefined_value();
1489}
1490
1491
1492RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1493  HandleScope scope(isolate);
1494  ASSERT(args.length() == 1);
1495  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1496  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1497  return Smi::FromInt(table->NumberOfElements());
1498}
1499
1500
1501static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1502    Handle<JSWeakCollection> weak_collection) {
1503  ASSERT(weak_collection->map()->inobject_properties() == 0);
1504  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1505  weak_collection->set_table(*table);
1506  weak_collection->set_next(Smi::FromInt(0));
1507  return *weak_collection;
1508}
1509
1510
1511RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1512  HandleScope scope(isolate);
1513  ASSERT(args.length() == 1);
1514  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1515  return WeakCollectionInitialize(isolate, weak_collection);
1516}
1517
1518
1519RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1520  HandleScope scope(isolate);
1521  ASSERT(args.length() == 2);
1522  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1523  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1524  Handle<ObjectHashTable> table(
1525      ObjectHashTable::cast(weak_collection->table()));
1526  Handle<Object> lookup(table->Lookup(*key), isolate);
1527  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1528}
1529
1530
1531RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1532  HandleScope scope(isolate);
1533  ASSERT(args.length() == 2);
1534  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1535  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1536  Handle<ObjectHashTable> table(
1537      ObjectHashTable::cast(weak_collection->table()));
1538  Handle<Object> lookup(table->Lookup(*key), isolate);
1539  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1540}
1541
1542
1543RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1544  HandleScope scope(isolate);
1545  ASSERT(args.length() == 2);
1546  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1547  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1548  Handle<ObjectHashTable> table(ObjectHashTable::cast(
1549      weak_collection->table()));
1550  Handle<Object> lookup(table->Lookup(*key), isolate);
1551  Handle<ObjectHashTable> new_table =
1552      PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1553  weak_collection->set_table(*new_table);
1554  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1555}
1556
1557
1558RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1559  HandleScope scope(isolate);
1560  ASSERT(args.length() == 3);
1561  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1562  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1563  Handle<Object> value(args[2], isolate);
1564  Handle<ObjectHashTable> table(
1565      ObjectHashTable::cast(weak_collection->table()));
1566  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1567  weak_collection->set_table(*new_table);
1568  return isolate->heap()->undefined_value();
1569}
1570
1571
1572RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1573  SealHandleScope shs(isolate);
1574  ASSERT(args.length() == 1);
1575  Object* obj = args[0];
1576  if (!obj->IsJSObject()) return isolate->heap()->null_value();
1577  return JSObject::cast(obj)->class_name();
1578}
1579
1580
1581RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1582  SealHandleScope shs(isolate);
1583  ASSERT(args.length() == 1);
1584  CONVERT_ARG_CHECKED(Object, obj, 0);
1585  // We don't expect access checks to be needed on JSProxy objects.
1586  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1587  do {
1588    if (obj->IsAccessCheckNeeded() &&
1589        !isolate->MayNamedAccess(JSObject::cast(obj),
1590                                 isolate->heap()->proto_string(),
1591                                 v8::ACCESS_GET)) {
1592      isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
1593      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1594      return isolate->heap()->undefined_value();
1595    }
1596    obj = obj->GetPrototype(isolate);
1597  } while (obj->IsJSObject() &&
1598           JSObject::cast(obj)->map()->is_hidden_prototype());
1599  return obj;
1600}
1601
1602
1603static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1604                                                       Object* receiver) {
1605  Object* current = receiver->GetPrototype(isolate);
1606  while (current->IsJSObject() &&
1607         JSObject::cast(current)->map()->is_hidden_prototype()) {
1608    current = current->GetPrototype(isolate);
1609  }
1610  return current;
1611}
1612
1613
1614RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1615  HandleScope scope(isolate);
1616  ASSERT(args.length() == 2);
1617  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1618  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1619  if (FLAG_harmony_observation && obj->map()->is_observed()) {
1620    Handle<Object> old_value(
1621        GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1622
1623    Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1624    RETURN_IF_EMPTY_HANDLE(isolate, result);
1625
1626    Handle<Object> new_value(
1627        GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1628    if (!new_value->SameValue(*old_value)) {
1629      JSObject::EnqueueChangeRecord(obj, "prototype",
1630                                    isolate->factory()->proto_string(),
1631                                    old_value);
1632    }
1633    return *result;
1634  }
1635  Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1636  RETURN_IF_EMPTY_HANDLE(isolate, result);
1637  return *result;
1638}
1639
1640
1641RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1642  SealHandleScope shs(isolate);
1643  ASSERT(args.length() == 2);
1644  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1645  Object* O = args[0];
1646  Object* V = args[1];
1647  while (true) {
1648    Object* prototype = V->GetPrototype(isolate);
1649    if (prototype->IsNull()) return isolate->heap()->false_value();
1650    if (O == prototype) return isolate->heap()->true_value();
1651    V = prototype;
1652  }
1653}
1654
1655
1656static bool CheckAccessException(Object* callback,
1657                                 v8::AccessType access_type) {
1658  if (callback->IsAccessorInfo()) {
1659    AccessorInfo* info = AccessorInfo::cast(callback);
1660    return
1661        (access_type == v8::ACCESS_HAS &&
1662           (info->all_can_read() || info->all_can_write())) ||
1663        (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1664        (access_type == v8::ACCESS_SET && info->all_can_write());
1665  }
1666  return false;
1667}
1668
1669
1670template<class Key>
1671static bool CheckGenericAccess(
1672    JSObject* receiver,
1673    JSObject* holder,
1674    Key key,
1675    v8::AccessType access_type,
1676    bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) {
1677  Isolate* isolate = receiver->GetIsolate();
1678  for (JSObject* current = receiver;
1679       true;
1680       current = JSObject::cast(current->GetPrototype())) {
1681    if (current->IsAccessCheckNeeded() &&
1682        !(isolate->*mayAccess)(current, key, access_type)) {
1683      return false;
1684    }
1685    if (current == holder) break;
1686  }
1687  return true;
1688}
1689
1690
1691enum AccessCheckResult {
1692  ACCESS_FORBIDDEN,
1693  ACCESS_ALLOWED,
1694  ACCESS_ABSENT
1695};
1696
1697
1698static AccessCheckResult CheckPropertyAccess(
1699    JSObject* obj,
1700    Name* name,
1701    v8::AccessType access_type) {
1702  uint32_t index;
1703  if (name->AsArrayIndex(&index)) {
1704    // TODO(1095): we should traverse hidden prototype hierachy as well.
1705    if (CheckGenericAccess(
1706            obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
1707      return ACCESS_ALLOWED;
1708    }
1709
1710    obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1711    return ACCESS_FORBIDDEN;
1712  }
1713
1714  LookupResult lookup(obj->GetIsolate());
1715  obj->LocalLookup(name, &lookup, true);
1716
1717  if (!lookup.IsProperty()) return ACCESS_ABSENT;
1718  if (CheckGenericAccess<Object*>(
1719          obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) {
1720    return ACCESS_ALLOWED;
1721  }
1722
1723  // Access check callback denied the access, but some properties
1724  // can have a special permissions which override callbacks descision
1725  // (currently see v8::AccessControl).
1726  // API callbacks can have per callback access exceptions.
1727  switch (lookup.type()) {
1728    case CALLBACKS:
1729      if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1730        return ACCESS_ALLOWED;
1731      }
1732      break;
1733    case INTERCEPTOR:
1734      // If the object has an interceptor, try real named properties.
1735      // Overwrite the result to fetch the correct property later.
1736      lookup.holder()->LookupRealNamedProperty(name, &lookup);
1737      if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1738        if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1739          return ACCESS_ALLOWED;
1740        }
1741      }
1742      break;
1743    default:
1744      break;
1745  }
1746
1747  obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1748  return ACCESS_FORBIDDEN;
1749}
1750
1751
1752// Enumerator used as indices into the array returned from GetOwnProperty
1753enum PropertyDescriptorIndices {
1754  IS_ACCESSOR_INDEX,
1755  VALUE_INDEX,
1756  GETTER_INDEX,
1757  SETTER_INDEX,
1758  WRITABLE_INDEX,
1759  ENUMERABLE_INDEX,
1760  CONFIGURABLE_INDEX,
1761  DESCRIPTOR_SIZE
1762};
1763
1764
1765static MaybeObject* GetOwnProperty(Isolate* isolate,
1766                                   Handle<JSObject> obj,
1767                                   Handle<Name> name) {
1768  Heap* heap = isolate->heap();
1769  // Due to some WebKit tests, we want to make sure that we do not log
1770  // more than one access failure here.
1771  AccessCheckResult access_check_result =
1772      CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS);
1773  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1774  switch (access_check_result) {
1775    case ACCESS_FORBIDDEN: return heap->false_value();
1776    case ACCESS_ALLOWED: break;
1777    case ACCESS_ABSENT: return heap->undefined_value();
1778  }
1779
1780  PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
1781  if (attrs == ABSENT) {
1782    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1783    return heap->undefined_value();
1784  }
1785  ASSERT(!isolate->has_scheduled_exception());
1786  AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1787  Handle<AccessorPair> accessors(raw_accessors, isolate);
1788
1789  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1790  elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1791  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1792  elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1793
1794  if (raw_accessors == NULL) {
1795    elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1796    // GetProperty does access check.
1797    Handle<Object> value = GetProperty(isolate, obj, name);
1798    RETURN_IF_EMPTY_HANDLE(isolate, value);
1799    elms->set(VALUE_INDEX, *value);
1800  } else {
1801    // Access checks are performed for both accessors separately.
1802    // When they fail, the respective field is not set in the descriptor.
1803    Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
1804    Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
1805    if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) {
1806      ASSERT(!isolate->has_scheduled_exception());
1807      elms->set(GETTER_INDEX, getter);
1808    } else {
1809      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1810    }
1811    if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) {
1812      ASSERT(!isolate->has_scheduled_exception());
1813      elms->set(SETTER_INDEX, setter);
1814    } else {
1815      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1816    }
1817  }
1818
1819  return *isolate->factory()->NewJSArrayWithElements(elms);
1820}
1821
1822
1823// Returns an array with the property description:
1824//  if args[1] is not a property on args[0]
1825//          returns undefined
1826//  if args[1] is a data property on args[0]
1827//         [false, value, Writeable, Enumerable, Configurable]
1828//  if args[1] is an accessor on args[0]
1829//         [true, GetFunction, SetFunction, Enumerable, Configurable]
1830RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1831  HandleScope scope(isolate);
1832  ASSERT(args.length() == 2);
1833  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1834  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1835  return GetOwnProperty(isolate, obj, name);
1836}
1837
1838
1839RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1840  SealHandleScope shs(isolate);
1841  ASSERT(args.length() == 1);
1842  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1843  return obj->PreventExtensions();
1844}
1845
1846
1847RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1848  SealHandleScope shs(isolate);
1849  ASSERT(args.length() == 1);
1850  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1851  if (obj->IsJSGlobalProxy()) {
1852    Object* proto = obj->GetPrototype();
1853    if (proto->IsNull()) return isolate->heap()->false_value();
1854    ASSERT(proto->IsJSGlobalObject());
1855    obj = JSObject::cast(proto);
1856  }
1857  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1858}
1859
1860
1861RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1862  HandleScope scope(isolate);
1863  ASSERT(args.length() == 3);
1864  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1865  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1866  CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1867  Handle<Object> result =
1868      RegExpImpl::Compile(re, pattern, flags);
1869  RETURN_IF_EMPTY_HANDLE(isolate, result);
1870  return *result;
1871}
1872
1873
1874RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1875  HandleScope scope(isolate);
1876  ASSERT(args.length() == 1);
1877  CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1878  return *isolate->factory()->CreateApiFunction(data);
1879}
1880
1881
1882RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1883  SealHandleScope shs(isolate);
1884  ASSERT(args.length() == 1);
1885  Object* arg = args[0];
1886  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1887  return isolate->heap()->ToBoolean(result);
1888}
1889
1890
1891RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1892  SealHandleScope shs(isolate);
1893  ASSERT(args.length() == 2);
1894  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1895  CONVERT_SMI_ARG_CHECKED(index, 1)
1896  int offset = index * kPointerSize + HeapObject::kHeaderSize;
1897  InstanceType type = templ->map()->instance_type();
1898  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1899                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
1900  RUNTIME_ASSERT(offset > 0);
1901  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1902    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1903  } else {
1904    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1905  }
1906  return *HeapObject::RawField(templ, offset);
1907}
1908
1909
1910RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1911  SealHandleScope shs(isolate);
1912  ASSERT(args.length() == 1);
1913  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1914  Map* old_map = object->map();
1915  bool needs_access_checks = old_map->is_access_check_needed();
1916  if (needs_access_checks) {
1917    // Copy map so it won't interfere constructor's initial map.
1918    Map* new_map;
1919    MaybeObject* maybe_new_map = old_map->Copy();
1920    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1921
1922    new_map->set_is_access_check_needed(false);
1923    object->set_map(new_map);
1924  }
1925  return isolate->heap()->ToBoolean(needs_access_checks);
1926}
1927
1928
1929RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1930  SealHandleScope shs(isolate);
1931  ASSERT(args.length() == 1);
1932  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1933  Map* old_map = object->map();
1934  if (!old_map->is_access_check_needed()) {
1935    // Copy map so it won't interfere constructor's initial map.
1936    Map* new_map;
1937    MaybeObject* maybe_new_map = old_map->Copy();
1938    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1939
1940    new_map->set_is_access_check_needed(true);
1941    object->set_map(new_map);
1942  }
1943  return isolate->heap()->undefined_value();
1944}
1945
1946
1947static Failure* ThrowRedeclarationError(Isolate* isolate,
1948                                        const char* type,
1949                                        Handle<String> name) {
1950  HandleScope scope(isolate);
1951  Handle<Object> type_handle =
1952      isolate->factory()->NewStringFromAscii(CStrVector(type));
1953  Handle<Object> args[2] = { type_handle, name };
1954  Handle<Object> error =
1955      isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1956  return isolate->Throw(*error);
1957}
1958
1959
1960RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1961  HandleScope scope(isolate);
1962  ASSERT(args.length() == 3);
1963  Handle<GlobalObject> global = Handle<GlobalObject>(
1964      isolate->context()->global_object());
1965
1966  Handle<Context> context = args.at<Context>(0);
1967  CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1968  CONVERT_SMI_ARG_CHECKED(flags, 2);
1969
1970  // Traverse the name/value pairs and set the properties.
1971  int length = pairs->length();
1972  for (int i = 0; i < length; i += 2) {
1973    HandleScope scope(isolate);
1974    Handle<String> name(String::cast(pairs->get(i)));
1975    Handle<Object> value(pairs->get(i + 1), isolate);
1976
1977    // We have to declare a global const property. To capture we only
1978    // assign to it when evaluating the assignment for "const x =
1979    // <expr>" the initial value is the hole.
1980    bool is_var = value->IsUndefined();
1981    bool is_const = value->IsTheHole();
1982    bool is_function = value->IsSharedFunctionInfo();
1983    ASSERT(is_var + is_const + is_function == 1);
1984
1985    if (is_var || is_const) {
1986      // Lookup the property in the global object, and don't set the
1987      // value of the variable if the property is already there.
1988      // Do the lookup locally only, see ES5 erratum.
1989      LookupResult lookup(isolate);
1990      if (FLAG_es52_globals) {
1991        global->LocalLookup(*name, &lookup, true);
1992      } else {
1993        global->Lookup(*name, &lookup);
1994      }
1995      if (lookup.IsFound()) {
1996        // We found an existing property. Unless it was an interceptor
1997        // that claims the property is absent, skip this declaration.
1998        if (!lookup.IsInterceptor()) continue;
1999        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
2000        if (attributes != ABSENT) continue;
2001        // Fall-through and introduce the absent property by using
2002        // SetProperty.
2003      }
2004    } else if (is_function) {
2005      // Copy the function and update its context. Use it as value.
2006      Handle<SharedFunctionInfo> shared =
2007          Handle<SharedFunctionInfo>::cast(value);
2008      Handle<JSFunction> function =
2009          isolate->factory()->NewFunctionFromSharedFunctionInfo(
2010              shared, context, TENURED);
2011      value = function;
2012    }
2013
2014    LookupResult lookup(isolate);
2015    global->LocalLookup(*name, &lookup, true);
2016
2017    // Compute the property attributes. According to ECMA-262,
2018    // the property must be non-configurable except in eval.
2019    int attr = NONE;
2020    bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2021    if (!is_eval) {
2022      attr |= DONT_DELETE;
2023    }
2024    bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2025    if (is_const || (is_native && is_function)) {
2026      attr |= READ_ONLY;
2027    }
2028
2029    LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
2030
2031    if (!lookup.IsFound() || is_function) {
2032      // If the local property exists, check that we can reconfigure it
2033      // as required for function declarations.
2034      if (lookup.IsFound() && lookup.IsDontDelete()) {
2035        if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2036            lookup.IsPropertyCallbacks()) {
2037          return ThrowRedeclarationError(isolate, "function", name);
2038        }
2039        // If the existing property is not configurable, keep its attributes.
2040        attr = lookup.GetAttributes();
2041      }
2042      // Define or redefine own property.
2043      RETURN_IF_EMPTY_HANDLE(isolate,
2044          JSObject::SetLocalPropertyIgnoreAttributes(
2045              global, name, value, static_cast<PropertyAttributes>(attr)));
2046    } else {
2047      // Do a [[Put]] on the existing (own) property.
2048      RETURN_IF_EMPTY_HANDLE(isolate,
2049          JSObject::SetProperty(
2050              global, name, value, static_cast<PropertyAttributes>(attr),
2051              language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
2052    }
2053  }
2054
2055  ASSERT(!isolate->has_pending_exception());
2056  return isolate->heap()->undefined_value();
2057}
2058
2059
2060RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
2061  HandleScope scope(isolate);
2062  ASSERT(args.length() == 4);
2063
2064  // Declarations are always made in a function or native context.  In the
2065  // case of eval code, the context passed is the context of the caller,
2066  // which may be some nested context and not the declaration context.
2067  RUNTIME_ASSERT(args[0]->IsContext());
2068  Handle<Context> context(Context::cast(args[0])->declaration_context());
2069
2070  Handle<String> name(String::cast(args[1]));
2071  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2072  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2073  Handle<Object> initial_value(args[3], isolate);
2074
2075  int index;
2076  PropertyAttributes attributes;
2077  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2078  BindingFlags binding_flags;
2079  Handle<Object> holder =
2080      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2081
2082  if (attributes != ABSENT) {
2083    // The name was declared before; check for conflicting re-declarations.
2084    // Note: this is actually inconsistent with what happens for globals (where
2085    // we silently ignore such declarations).
2086    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2087      // Functions are not read-only.
2088      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2089      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2090      return ThrowRedeclarationError(isolate, type, name);
2091    }
2092
2093    // Initialize it if necessary.
2094    if (*initial_value != NULL) {
2095      if (index >= 0) {
2096        ASSERT(holder.is_identical_to(context));
2097        if (((attributes & READ_ONLY) == 0) ||
2098            context->get(index)->IsTheHole()) {
2099          context->set(index, *initial_value);
2100        }
2101      } else {
2102        // Slow case: The property is in the context extension object of a
2103        // function context or the global object of a native context.
2104        Handle<JSObject> object = Handle<JSObject>::cast(holder);
2105        RETURN_IF_EMPTY_HANDLE(
2106            isolate,
2107            JSReceiver::SetProperty(object, name, initial_value, mode,
2108                                    kNonStrictMode));
2109      }
2110    }
2111
2112  } else {
2113    // The property is not in the function context. It needs to be
2114    // "declared" in the function context's extension context or as a
2115    // property of the the global object.
2116    Handle<JSObject> object;
2117    if (context->has_extension()) {
2118      object = Handle<JSObject>(JSObject::cast(context->extension()));
2119    } else {
2120      // Context extension objects are allocated lazily.
2121      ASSERT(context->IsFunctionContext());
2122      object = isolate->factory()->NewJSObject(
2123          isolate->context_extension_function());
2124      context->set_extension(*object);
2125    }
2126    ASSERT(*object != NULL);
2127
2128    // Declare the property by setting it to the initial value if provided,
2129    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2130    // constant declarations).
2131    ASSERT(!object->HasLocalProperty(*name));
2132    Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2133    if (*initial_value != NULL) value = initial_value;
2134    // Declaring a const context slot is a conflicting declaration if
2135    // there is a callback with that name in a prototype. It is
2136    // allowed to introduce const variables in
2137    // JSContextExtensionObjects. They are treated specially in
2138    // SetProperty and no setters are invoked for those since they are
2139    // not real JSObjects.
2140    if (initial_value->IsTheHole() &&
2141        !object->IsJSContextExtensionObject()) {
2142      LookupResult lookup(isolate);
2143      object->Lookup(*name, &lookup);
2144      if (lookup.IsPropertyCallbacks()) {
2145        return ThrowRedeclarationError(isolate, "const", name);
2146      }
2147    }
2148    if (object->IsJSGlobalObject()) {
2149      // Define own property on the global object.
2150      RETURN_IF_EMPTY_HANDLE(isolate,
2151         JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2152    } else {
2153      RETURN_IF_EMPTY_HANDLE(isolate,
2154         JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
2155    }
2156  }
2157
2158  return isolate->heap()->undefined_value();
2159}
2160
2161
2162RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2163  SealHandleScope shs(isolate);
2164  // args[0] == name
2165  // args[1] == language_mode
2166  // args[2] == value (optional)
2167
2168  // Determine if we need to assign to the variable if it already
2169  // exists (based on the number of arguments).
2170  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2171  bool assign = args.length() == 3;
2172
2173  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2174  GlobalObject* global = isolate->context()->global_object();
2175  RUNTIME_ASSERT(args[1]->IsSmi());
2176  CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
2177  StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
2178      ? kNonStrictMode : kStrictMode;
2179
2180  // According to ECMA-262, section 12.2, page 62, the property must
2181  // not be deletable.
2182  PropertyAttributes attributes = DONT_DELETE;
2183
2184  // Lookup the property locally in the global object. If it isn't
2185  // there, there is a property with this name in the prototype chain.
2186  // We follow Safari and Firefox behavior and only set the property
2187  // locally if there is an explicit initialization value that we have
2188  // to assign to the property.
2189  // Note that objects can have hidden prototypes, so we need to traverse
2190  // the whole chain of hidden prototypes to do a 'local' lookup.
2191  Object* object = global;
2192  LookupResult lookup(isolate);
2193  JSObject::cast(object)->LocalLookup(*name, &lookup, true);
2194  if (lookup.IsInterceptor()) {
2195    HandleScope handle_scope(isolate);
2196    PropertyAttributes intercepted =
2197        lookup.holder()->GetPropertyAttribute(*name);
2198    if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2199      // Found an interceptor that's not read only.
2200      if (assign) {
2201        return lookup.holder()->SetProperty(
2202            &lookup, *name, args[2], attributes, strict_mode_flag);
2203      } else {
2204        return isolate->heap()->undefined_value();
2205      }
2206    }
2207  }
2208
2209  // Reload global in case the loop above performed a GC.
2210  global = isolate->context()->global_object();
2211  if (assign) {
2212    return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
2213  }
2214  return isolate->heap()->undefined_value();
2215}
2216
2217
2218RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
2219  SealHandleScope shs(isolate);
2220  // All constants are declared with an initial value. The name
2221  // of the constant is the first argument and the initial value
2222  // is the second.
2223  RUNTIME_ASSERT(args.length() == 2);
2224  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2225  Handle<Object> value = args.at<Object>(1);
2226
2227  // Get the current global object from top.
2228  GlobalObject* global = isolate->context()->global_object();
2229
2230  // According to ECMA-262, section 12.2, page 62, the property must
2231  // not be deletable. Since it's a const, it must be READ_ONLY too.
2232  PropertyAttributes attributes =
2233      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2234
2235  // Lookup the property locally in the global object. If it isn't
2236  // there, we add the property and take special precautions to always
2237  // add it as a local property even in case of callbacks in the
2238  // prototype chain (this rules out using SetProperty).
2239  // We use SetLocalPropertyIgnoreAttributes instead
2240  LookupResult lookup(isolate);
2241  global->LocalLookup(*name, &lookup);
2242  if (!lookup.IsFound()) {
2243    return global->SetLocalPropertyIgnoreAttributes(*name,
2244                                                    *value,
2245                                                    attributes);
2246  }
2247
2248  if (!lookup.IsReadOnly()) {
2249    // Restore global object from context (in case of GC) and continue
2250    // with setting the value.
2251    HandleScope handle_scope(isolate);
2252    Handle<GlobalObject> global(isolate->context()->global_object());
2253
2254    // BUG 1213575: Handle the case where we have to set a read-only
2255    // property through an interceptor and only do it if it's
2256    // uninitialized, e.g. the hole. Nirk...
2257    // Passing non-strict mode because the property is writable.
2258    RETURN_IF_EMPTY_HANDLE(
2259        isolate,
2260        JSReceiver::SetProperty(global, name, value, attributes,
2261                                kNonStrictMode));
2262    return *value;
2263  }
2264
2265  // Set the value, but only if we're assigning the initial value to a
2266  // constant. For now, we determine this by checking if the
2267  // current value is the hole.
2268  // Strict mode handling not needed (const is disallowed in strict mode).
2269  if (lookup.IsField()) {
2270    FixedArray* properties = global->properties();
2271    int index = lookup.GetFieldIndex().field_index();
2272    if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2273      properties->set(index, *value);
2274    }
2275  } else if (lookup.IsNormal()) {
2276    if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2277        !lookup.IsReadOnly()) {
2278      HandleScope scope(isolate);
2279      JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2280    }
2281  } else {
2282    // Ignore re-initialization of constants that have already been
2283    // assigned a constant value.
2284    ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2285  }
2286
2287  // Use the set value as the result of the operation.
2288  return *value;
2289}
2290
2291
2292RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
2293  HandleScope scope(isolate);
2294  ASSERT(args.length() == 3);
2295
2296  Handle<Object> value(args[0], isolate);
2297  ASSERT(!value->IsTheHole());
2298
2299  // Initializations are always done in a function or native context.
2300  RUNTIME_ASSERT(args[1]->IsContext());
2301  Handle<Context> context(Context::cast(args[1])->declaration_context());
2302
2303  Handle<String> name(String::cast(args[2]));
2304
2305  int index;
2306  PropertyAttributes attributes;
2307  ContextLookupFlags flags = FOLLOW_CHAINS;
2308  BindingFlags binding_flags;
2309  Handle<Object> holder =
2310      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2311
2312  if (index >= 0) {
2313    ASSERT(holder->IsContext());
2314    // Property was found in a context.  Perform the assignment if we
2315    // found some non-constant or an uninitialized constant.
2316    Handle<Context> context = Handle<Context>::cast(holder);
2317    if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2318      context->set(index, *value);
2319    }
2320    return *value;
2321  }
2322
2323  // The property could not be found, we introduce it as a property of the
2324  // global object.
2325  if (attributes == ABSENT) {
2326    Handle<JSObject> global = Handle<JSObject>(
2327        isolate->context()->global_object());
2328    // Strict mode not needed (const disallowed in strict mode).
2329    RETURN_IF_EMPTY_HANDLE(
2330        isolate,
2331        JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
2332    return *value;
2333  }
2334
2335  // The property was present in some function's context extension object,
2336  // as a property on the subject of a with, or as a property of the global
2337  // object.
2338  //
2339  // In most situations, eval-introduced consts should still be present in
2340  // the context extension object.  However, because declaration and
2341  // initialization are separate, the property might have been deleted
2342  // before we reach the initialization point.
2343  //
2344  // Example:
2345  //
2346  //    function f() { eval("delete x; const x;"); }
2347  //
2348  // In that case, the initialization behaves like a normal assignment.
2349  Handle<JSObject> object = Handle<JSObject>::cast(holder);
2350
2351  if (*object == context->extension()) {
2352    // This is the property that was introduced by the const declaration.
2353    // Set it if it hasn't been set before.  NOTE: We cannot use
2354    // GetProperty() to get the current value as it 'unholes' the value.
2355    LookupResult lookup(isolate);
2356    object->LocalLookupRealNamedProperty(*name, &lookup);
2357    ASSERT(lookup.IsFound());  // the property was declared
2358    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2359
2360    if (lookup.IsField()) {
2361      FixedArray* properties = object->properties();
2362      int index = lookup.GetFieldIndex().field_index();
2363      if (properties->get(index)->IsTheHole()) {
2364        properties->set(index, *value);
2365      }
2366    } else if (lookup.IsNormal()) {
2367      if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2368        JSObject::SetNormalizedProperty(object, &lookup, value);
2369      }
2370    } else {
2371      // We should not reach here. Any real, named property should be
2372      // either a field or a dictionary slot.
2373      UNREACHABLE();
2374    }
2375  } else {
2376    // The property was found on some other object.  Set it if it is not a
2377    // read-only property.
2378    if ((attributes & READ_ONLY) == 0) {
2379      // Strict mode not needed (const disallowed in strict mode).
2380      RETURN_IF_EMPTY_HANDLE(
2381          isolate,
2382          JSReceiver::SetProperty(object, name, value, attributes,
2383                                  kNonStrictMode));
2384    }
2385  }
2386
2387  return *value;
2388}
2389
2390
2391RUNTIME_FUNCTION(MaybeObject*,
2392                 Runtime_OptimizeObjectForAddingMultipleProperties) {
2393  HandleScope scope(isolate);
2394  ASSERT(args.length() == 2);
2395  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2396  CONVERT_SMI_ARG_CHECKED(properties, 1);
2397  if (object->HasFastProperties()) {
2398    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2399  }
2400  return *object;
2401}
2402
2403
2404RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
2405  HandleScope scope(isolate);
2406  ASSERT(args.length() == 4);
2407  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2408  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2409  // Due to the way the JS calls are constructed this must be less than the
2410  // length of a string, i.e. it is always a Smi.  We check anyway for security.
2411  CONVERT_SMI_ARG_CHECKED(index, 2);
2412  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2413  RUNTIME_ASSERT(index >= 0);
2414  RUNTIME_ASSERT(index <= subject->length());
2415  isolate->counters()->regexp_entry_runtime()->Increment();
2416  Handle<Object> result = RegExpImpl::Exec(regexp,
2417                                           subject,
2418                                           index,
2419                                           last_match_info);
2420  RETURN_IF_EMPTY_HANDLE(isolate, result);
2421  return *result;
2422}
2423
2424
2425RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
2426  SealHandleScope shs(isolate);
2427  ASSERT(args.length() == 3);
2428  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2429  if (elements_count < 0 ||
2430      elements_count > FixedArray::kMaxLength ||
2431      !Smi::IsValid(elements_count)) {
2432    return isolate->ThrowIllegalOperation();
2433  }
2434  Object* new_object;
2435  { MaybeObject* maybe_new_object =
2436        isolate->heap()->AllocateFixedArray(elements_count);
2437    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2438  }
2439  FixedArray* elements = FixedArray::cast(new_object);
2440  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2441      JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
2442    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2443  }
2444  {
2445    DisallowHeapAllocation no_gc;
2446    HandleScope scope(isolate);
2447    reinterpret_cast<HeapObject*>(new_object)->
2448        set_map(isolate->native_context()->regexp_result_map());
2449  }
2450  JSArray* array = JSArray::cast(new_object);
2451  array->set_properties(isolate->heap()->empty_fixed_array());
2452  array->set_elements(elements);
2453  array->set_length(Smi::FromInt(elements_count));
2454  // Write in-object properties after the length of the array.
2455  array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
2456  array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
2457  return array;
2458}
2459
2460
2461RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2462  SealHandleScope shs(isolate);
2463  DisallowHeapAllocation no_allocation;
2464  ASSERT(args.length() == 5);
2465  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
2466  CONVERT_ARG_CHECKED(String, source, 1);
2467  // If source is the empty string we set it to "(?:)" instead as
2468  // suggested by ECMA-262, 5th, section 15.10.4.1.
2469  if (source->length() == 0) source = isolate->heap()->query_colon_string();
2470
2471  Object* global = args[2];
2472  if (!global->IsTrue()) global = isolate->heap()->false_value();
2473
2474  Object* ignoreCase = args[3];
2475  if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
2476
2477  Object* multiline = args[4];
2478  if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
2479
2480  Map* map = regexp->map();
2481  Object* constructor = map->constructor();
2482  if (constructor->IsJSFunction() &&
2483      JSFunction::cast(constructor)->initial_map() == map) {
2484    // If we still have the original map, set in-object properties directly.
2485    regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
2486    // Both true and false are immovable immortal objects so no need for write
2487    // barrier.
2488    regexp->InObjectPropertyAtPut(
2489        JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
2490    regexp->InObjectPropertyAtPut(
2491        JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
2492    regexp->InObjectPropertyAtPut(
2493        JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
2494    regexp->InObjectPropertyAtPut(
2495        JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2496    return regexp;
2497  }
2498
2499  // Map has changed, so use generic, but slower, method.
2500  PropertyAttributes final =
2501      static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2502  PropertyAttributes writable =
2503      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2504  Heap* heap = isolate->heap();
2505  MaybeObject* result;
2506  result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_string(),
2507                                                    source,
2508                                                    final);
2509  // TODO(jkummerow): Turn these back into ASSERTs when we can be certain
2510  // that it never fires in Release mode in the wild.
2511  CHECK(!result->IsFailure());
2512  result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_string(),
2513                                                    global,
2514                                                    final);
2515  CHECK(!result->IsFailure());
2516  result =
2517      regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_string(),
2518                                               ignoreCase,
2519                                               final);
2520  CHECK(!result->IsFailure());
2521  result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_string(),
2522                                                    multiline,
2523                                                    final);
2524  CHECK(!result->IsFailure());
2525  result =
2526      regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_string(),
2527                                               Smi::FromInt(0),
2528                                               writable);
2529  CHECK(!result->IsFailure());
2530  USE(result);
2531  return regexp;
2532}
2533
2534
2535RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2536  HandleScope scope(isolate);
2537  ASSERT(args.length() == 1);
2538  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2539  // This is necessary to enable fast checks for absence of elements
2540  // on Array.prototype and below.
2541  prototype->set_elements(isolate->heap()->empty_fixed_array());
2542  return Smi::FromInt(0);
2543}
2544
2545
2546static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2547                                         Handle<JSObject> holder,
2548                                         const char* name,
2549                                         Builtins::Name builtin_name) {
2550  Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2551  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2552  Handle<JSFunction> optimized =
2553      isolate->factory()->NewFunction(key,
2554                                      JS_OBJECT_TYPE,
2555                                      JSObject::kHeaderSize,
2556                                      code,
2557                                      false);
2558  optimized->shared()->DontAdaptArguments();
2559  JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
2560  return optimized;
2561}
2562
2563
2564RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2565  HandleScope scope(isolate);
2566  ASSERT(args.length() == 1);
2567  CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
2568
2569  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2570  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2571  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2572  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2573  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2574  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2575  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2576
2577  return *holder;
2578}
2579
2580
2581RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
2582  SealHandleScope shs(isolate);
2583  ASSERT(args.length() == 1);
2584  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2585  if (!callable->IsJSFunction()) {
2586    HandleScope scope(isolate);
2587    bool threw = false;
2588    Handle<Object> delegate =
2589        Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
2590    if (threw) return Failure::Exception();
2591    callable = JSFunction::cast(*delegate);
2592  }
2593  JSFunction* function = JSFunction::cast(callable);
2594  SharedFunctionInfo* shared = function->shared();
2595  return isolate->heap()->ToBoolean(shared->is_classic_mode());
2596}
2597
2598
2599RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2600  SealHandleScope shs(isolate);
2601  ASSERT(args.length() == 1);
2602  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2603
2604  if (!callable->IsJSFunction()) {
2605    HandleScope scope(isolate);
2606    bool threw = false;
2607    Handle<Object> delegate =
2608        Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
2609    if (threw) return Failure::Exception();
2610    callable = JSFunction::cast(*delegate);
2611  }
2612  JSFunction* function = JSFunction::cast(callable);
2613
2614  SharedFunctionInfo* shared = function->shared();
2615  if (shared->native() || !shared->is_classic_mode()) {
2616    return isolate->heap()->undefined_value();
2617  }
2618  // Returns undefined for strict or native functions, or
2619  // the associated global receiver for "normal" functions.
2620
2621  Context* native_context =
2622      function->context()->global_object()->native_context();
2623  return native_context->global_object()->global_receiver();
2624}
2625
2626
2627RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
2628  HandleScope scope(isolate);
2629  ASSERT(args.length() == 4);
2630  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2631  int index = args.smi_at(1);
2632  Handle<String> pattern = args.at<String>(2);
2633  Handle<String> flags = args.at<String>(3);
2634
2635  // Get the RegExp function from the context in the literals array.
2636  // This is the RegExp function from the context in which the
2637  // function was created.  We do not use the RegExp function from the
2638  // current native context because this might be the RegExp function
2639  // from another context which we should not have access to.
2640  Handle<JSFunction> constructor =
2641      Handle<JSFunction>(
2642          JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2643  // Compute the regular expression literal.
2644  bool has_pending_exception;
2645  Handle<Object> regexp =
2646      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2647                                      &has_pending_exception);
2648  if (has_pending_exception) {
2649    ASSERT(isolate->has_pending_exception());
2650    return Failure::Exception();
2651  }
2652  literals->set(index, *regexp);
2653  return *regexp;
2654}
2655
2656
2657RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2658  SealHandleScope shs(isolate);
2659  ASSERT(args.length() == 1);
2660
2661  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2662  return f->shared()->name();
2663}
2664
2665
2666RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2667  SealHandleScope shs(isolate);
2668  ASSERT(args.length() == 2);
2669
2670  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2671  CONVERT_ARG_CHECKED(String, name, 1);
2672  f->shared()->set_name(name);
2673  return isolate->heap()->undefined_value();
2674}
2675
2676
2677RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2678  SealHandleScope shs(isolate);
2679  ASSERT(args.length() == 1);
2680  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2681  return isolate->heap()->ToBoolean(
2682      f->shared()->name_should_print_as_anonymous());
2683}
2684
2685
2686RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2687  SealHandleScope shs(isolate);
2688  ASSERT(args.length() == 1);
2689  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2690  f->shared()->set_name_should_print_as_anonymous(true);
2691  return isolate->heap()->undefined_value();
2692}
2693
2694
2695RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2696  SealHandleScope shs(isolate);
2697  ASSERT(args.length() == 1);
2698  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2699  return isolate->heap()->ToBoolean(f->shared()->is_generator());
2700}
2701
2702
2703RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2704  SealHandleScope shs(isolate);
2705  ASSERT(args.length() == 1);
2706
2707  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2708  f->RemovePrototype();
2709
2710  return isolate->heap()->undefined_value();
2711}
2712
2713
2714RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2715  HandleScope scope(isolate);
2716  ASSERT(args.length() == 1);
2717
2718  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2719  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2720  if (!script->IsScript()) return isolate->heap()->undefined_value();
2721
2722  return *GetScriptWrapper(Handle<Script>::cast(script));
2723}
2724
2725
2726RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2727  HandleScope scope(isolate);
2728  ASSERT(args.length() == 1);
2729
2730  CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2731  Handle<SharedFunctionInfo> shared(f->shared());
2732  return *shared->GetSourceCode();
2733}
2734
2735
2736RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2737  SealHandleScope shs(isolate);
2738  ASSERT(args.length() == 1);
2739
2740  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2741  int pos = fun->shared()->start_position();
2742  return Smi::FromInt(pos);
2743}
2744
2745
2746RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2747  SealHandleScope shs(isolate);
2748  ASSERT(args.length() == 2);
2749
2750  CONVERT_ARG_CHECKED(Code, code, 0);
2751  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2752
2753  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2754
2755  Address pc = code->address() + offset;
2756  return Smi::FromInt(code->SourcePosition(pc));
2757}
2758
2759
2760RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2761  SealHandleScope shs(isolate);
2762  ASSERT(args.length() == 2);
2763
2764  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2765  CONVERT_ARG_CHECKED(String, name, 1);
2766  fun->SetInstanceClassName(name);
2767  return isolate->heap()->undefined_value();
2768}
2769
2770
2771RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2772  SealHandleScope shs(isolate);
2773  ASSERT(args.length() == 2);
2774
2775  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2776  CONVERT_SMI_ARG_CHECKED(length, 1);
2777  fun->shared()->set_length(length);
2778  return isolate->heap()->undefined_value();
2779}
2780
2781
2782RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2783  SealHandleScope shs(isolate);
2784  ASSERT(args.length() == 2);
2785
2786  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2787  ASSERT(fun->should_have_prototype());
2788  Object* obj;
2789  { MaybeObject* maybe_obj =
2790        Accessors::FunctionSetPrototype(fun, args[1], NULL);
2791    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2792  }
2793  return args[0];  // return TOS
2794}
2795
2796
2797RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2798  SealHandleScope shs(isolate);
2799  RUNTIME_ASSERT(args.length() == 1);
2800  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2801
2802  String* name = isolate->heap()->prototype_string();
2803
2804  if (function->HasFastProperties()) {
2805    // Construct a new field descriptor with updated attributes.
2806    DescriptorArray* instance_desc = function->map()->instance_descriptors();
2807
2808    int index = instance_desc->SearchWithCache(name, function->map());
2809    ASSERT(index != DescriptorArray::kNotFound);
2810    PropertyDetails details = instance_desc->GetDetails(index);
2811
2812    CallbacksDescriptor new_desc(name,
2813        instance_desc->GetValue(index),
2814        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2815
2816    // Create a new map featuring the new field descriptors array.
2817    Map* new_map;
2818    MaybeObject* maybe_map =
2819        function->map()->CopyReplaceDescriptor(
2820            instance_desc, &new_desc, index, OMIT_TRANSITION);
2821    if (!maybe_map->To(&new_map)) return maybe_map;
2822
2823    function->set_map(new_map);
2824  } else {  // Dictionary properties.
2825    // Directly manipulate the property details.
2826    int entry = function->property_dictionary()->FindEntry(name);
2827    ASSERT(entry != NameDictionary::kNotFound);
2828    PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2829    PropertyDetails new_details(
2830        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2831        details.type(),
2832        details.dictionary_index());
2833    function->property_dictionary()->DetailsAtPut(entry, new_details);
2834  }
2835  return function;
2836}
2837
2838
2839RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2840  SealHandleScope shs(isolate);
2841  ASSERT(args.length() == 1);
2842
2843  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2844  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2845}
2846
2847
2848RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2849  SealHandleScope shs(isolate);
2850  ASSERT(args.length() == 1);
2851
2852  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2853  return isolate->heap()->ToBoolean(f->IsBuiltin());
2854}
2855
2856
2857RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2858  HandleScope scope(isolate);
2859  ASSERT(args.length() == 2);
2860
2861  CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2862  Handle<Object> code = args.at<Object>(1);
2863
2864  if (code->IsNull()) return *target;
2865  RUNTIME_ASSERT(code->IsJSFunction());
2866  Handle<JSFunction> source = Handle<JSFunction>::cast(code);
2867  Handle<SharedFunctionInfo> target_shared(target->shared());
2868  Handle<SharedFunctionInfo> source_shared(source->shared());
2869
2870  if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
2871    return Failure::Exception();
2872  }
2873
2874  // Mark both, the source and the target, as un-flushable because the
2875  // shared unoptimized code makes them impossible to enqueue in a list.
2876  ASSERT(target_shared->code()->gc_metadata() == NULL);
2877  ASSERT(source_shared->code()->gc_metadata() == NULL);
2878  target_shared->set_dont_flush(true);
2879  source_shared->set_dont_flush(true);
2880
2881  // Set the code, scope info, formal parameter count, and the length
2882  // of the target shared function info.  Set the source code of the
2883  // target function to undefined.  SetCode is only used for built-in
2884  // constructors like String, Array, and Object, and some web code
2885  // doesn't like seeing source code for constructors.
2886  target_shared->ReplaceCode(source_shared->code());
2887  target_shared->set_scope_info(source_shared->scope_info());
2888  target_shared->set_length(source_shared->length());
2889  target_shared->set_formal_parameter_count(
2890      source_shared->formal_parameter_count());
2891  target_shared->set_script(isolate->heap()->undefined_value());
2892
2893  // Since we don't store the source we should never optimize this.
2894  target_shared->code()->set_optimizable(false);
2895
2896  // Set the code of the target function.
2897  target->ReplaceCode(source_shared->code());
2898  ASSERT(target->next_function_link()->IsUndefined());
2899
2900  // Make sure we get a fresh copy of the literal vector to avoid cross
2901  // context contamination.
2902  Handle<Context> context(source->context());
2903  int number_of_literals = source->NumberOfLiterals();
2904  Handle<FixedArray> literals =
2905      isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2906  if (number_of_literals > 0) {
2907    literals->set(JSFunction::kLiteralNativeContextIndex,
2908                  context->native_context());
2909  }
2910  target->set_context(*context);
2911  target->set_literals(*literals);
2912
2913  if (isolate->logger()->is_logging_code_events() ||
2914      isolate->cpu_profiler()->is_profiling()) {
2915    isolate->logger()->LogExistingFunction(
2916        source_shared, Handle<Code>(source_shared->code()));
2917  }
2918
2919  return *target;
2920}
2921
2922
2923RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2924  HandleScope scope(isolate);
2925  ASSERT(args.length() == 2);
2926  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2927  CONVERT_SMI_ARG_CHECKED(num, 1);
2928  RUNTIME_ASSERT(num >= 0);
2929  SetExpectedNofProperties(function, num);
2930  return isolate->heap()->undefined_value();
2931}
2932
2933
2934RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
2935  SealHandleScope shs(isolate);
2936  ASSERT(args.length() == 0);
2937
2938  JavaScriptFrameIterator it(isolate);
2939  JavaScriptFrame* frame = it.frame();
2940  JSFunction* function = frame->function();
2941  RUNTIME_ASSERT(function->shared()->is_generator());
2942
2943  JSGeneratorObject* generator;
2944  if (frame->IsConstructor()) {
2945    generator = JSGeneratorObject::cast(frame->receiver());
2946  } else {
2947    MaybeObject* maybe_generator =
2948        isolate->heap()->AllocateJSGeneratorObject(function);
2949    if (!maybe_generator->To(&generator)) return maybe_generator;
2950  }
2951  generator->set_function(function);
2952  generator->set_context(Context::cast(frame->context()));
2953  generator->set_receiver(frame->receiver());
2954  generator->set_continuation(0);
2955  generator->set_operand_stack(isolate->heap()->empty_fixed_array());
2956  generator->set_stack_handler_index(-1);
2957
2958  return generator;
2959}
2960
2961
2962RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
2963  SealHandleScope shs(isolate);
2964  ASSERT(args.length() == 1);
2965  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
2966
2967  JavaScriptFrameIterator stack_iterator(isolate);
2968  JavaScriptFrame* frame = stack_iterator.frame();
2969  RUNTIME_ASSERT(frame->function()->shared()->is_generator());
2970  ASSERT_EQ(frame->function(), generator_object->function());
2971
2972  // The caller should have saved the context and continuation already.
2973  ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
2974  ASSERT_LT(0, generator_object->continuation());
2975
2976  // We expect there to be at least two values on the operand stack: the return
2977  // value of the yield expression, and the argument to this runtime call.
2978  // Neither of those should be saved.
2979  int operands_count = frame->ComputeOperandsCount();
2980  ASSERT_GE(operands_count, 2);
2981  operands_count -= 2;
2982
2983  if (operands_count == 0) {
2984    // Although it's semantically harmless to call this function with an
2985    // operands_count of zero, it is also unnecessary.
2986    ASSERT_EQ(generator_object->operand_stack(),
2987              isolate->heap()->empty_fixed_array());
2988    ASSERT_EQ(generator_object->stack_handler_index(), -1);
2989    // If there are no operands on the stack, there shouldn't be a handler
2990    // active either.
2991    ASSERT(!frame->HasHandler());
2992  } else {
2993    int stack_handler_index = -1;
2994    MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
2995    FixedArray* operand_stack;
2996    if (!alloc->To(&operand_stack)) return alloc;
2997    frame->SaveOperandStack(operand_stack, &stack_handler_index);
2998    generator_object->set_operand_stack(operand_stack);
2999    generator_object->set_stack_handler_index(stack_handler_index);
3000  }
3001
3002  return isolate->heap()->undefined_value();
3003}
3004
3005
3006// Note that this function is the slow path for resuming generators.  It is only
3007// called if the suspended activation had operands on the stack, stack handlers
3008// needing rewinding, or if the resume should throw an exception.  The fast path
3009// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3010// inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3011// called in any case, as it needs to reconstruct the stack frame and make space
3012// for arguments and operands.
3013RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
3014  SealHandleScope shs(isolate);
3015  ASSERT(args.length() == 3);
3016  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3017  CONVERT_ARG_CHECKED(Object, value, 1);
3018  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3019  JavaScriptFrameIterator stack_iterator(isolate);
3020  JavaScriptFrame* frame = stack_iterator.frame();
3021
3022  ASSERT_EQ(frame->function(), generator_object->function());
3023  ASSERT(frame->function()->is_compiled());
3024
3025  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
3026  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
3027
3028  Address pc = generator_object->function()->code()->instruction_start();
3029  int offset = generator_object->continuation();
3030  ASSERT(offset > 0);
3031  frame->set_pc(pc + offset);
3032  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3033
3034  FixedArray* operand_stack = generator_object->operand_stack();
3035  int operands_count = operand_stack->length();
3036  if (operands_count != 0) {
3037    frame->RestoreOperandStack(operand_stack,
3038                               generator_object->stack_handler_index());
3039    generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3040    generator_object->set_stack_handler_index(-1);
3041  }
3042
3043  JSGeneratorObject::ResumeMode resume_mode =
3044      static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3045  switch (resume_mode) {
3046    case JSGeneratorObject::NEXT:
3047      return value;
3048    case JSGeneratorObject::THROW:
3049      return isolate->Throw(value);
3050  }
3051
3052  UNREACHABLE();
3053  return isolate->ThrowIllegalOperation();
3054}
3055
3056
3057RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
3058  HandleScope scope(isolate);
3059  ASSERT(args.length() == 1);
3060  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3061  int continuation = generator->continuation();
3062  const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3063      "generator_finished" : "generator_running";
3064  Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3065  Handle<Object> error = isolate->factory()->NewError(message, argv);
3066  return isolate->Throw(*error);
3067}
3068
3069
3070RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3071  SealHandleScope shs(isolate);
3072  ASSERT(args.length() == 1);
3073  CONVERT_ARG_CHECKED(JSObject, object, 0);
3074  return object->Freeze(isolate);
3075}
3076
3077
3078MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3079                                                 Object* char_code) {
3080  if (char_code->IsNumber()) {
3081    return isolate->heap()->LookupSingleCharacterStringFromCode(
3082        NumberToUint32(char_code) & 0xffff);
3083  }
3084  return isolate->heap()->empty_string();
3085}
3086
3087
3088RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
3089  SealHandleScope shs(isolate);
3090  ASSERT(args.length() == 2);
3091
3092  CONVERT_ARG_CHECKED(String, subject, 0);
3093  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3094
3095  // Flatten the string.  If someone wants to get a char at an index
3096  // in a cons string, it is likely that more indices will be
3097  // accessed.
3098  Object* flat;
3099  { MaybeObject* maybe_flat = subject->TryFlatten();
3100    if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3101  }
3102  subject = String::cast(flat);
3103
3104  if (i >= static_cast<uint32_t>(subject->length())) {
3105    return isolate->heap()->nan_value();
3106  }
3107
3108  return Smi::FromInt(subject->Get(i));
3109}
3110
3111
3112RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3113  SealHandleScope shs(isolate);
3114  ASSERT(args.length() == 1);
3115  return CharFromCode(isolate, args[0]);
3116}
3117
3118
3119class FixedArrayBuilder {
3120 public:
3121  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3122      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3123        length_(0),
3124        has_non_smi_elements_(false) {
3125    // Require a non-zero initial size. Ensures that doubling the size to
3126    // extend the array will work.
3127    ASSERT(initial_capacity > 0);
3128  }
3129
3130  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3131      : array_(backing_store),
3132        length_(0),
3133        has_non_smi_elements_(false) {
3134    // Require a non-zero initial size. Ensures that doubling the size to
3135    // extend the array will work.
3136    ASSERT(backing_store->length() > 0);
3137  }
3138
3139  bool HasCapacity(int elements) {
3140    int length = array_->length();
3141    int required_length = length_ + elements;
3142    return (length >= required_length);
3143  }
3144
3145  void EnsureCapacity(int elements) {
3146    int length = array_->length();
3147    int required_length = length_ + elements;
3148    if (length < required_length) {
3149      int new_length = length;
3150      do {
3151        new_length *= 2;
3152      } while (new_length < required_length);
3153      Handle<FixedArray> extended_array =
3154          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3155      array_->CopyTo(0, *extended_array, 0, length_);
3156      array_ = extended_array;
3157    }
3158  }
3159
3160  void Add(Object* value) {
3161    ASSERT(!value->IsSmi());
3162    ASSERT(length_ < capacity());
3163    array_->set(length_, value);
3164    length_++;
3165    has_non_smi_elements_ = true;
3166  }
3167
3168  void Add(Smi* value) {
3169    ASSERT(value->IsSmi());
3170    ASSERT(length_ < capacity());
3171    array_->set(length_, value);
3172    length_++;
3173  }
3174
3175  Handle<FixedArray> array() {
3176    return array_;
3177  }
3178
3179  int length() {
3180    return length_;
3181  }
3182
3183  int capacity() {
3184    return array_->length();
3185  }
3186
3187  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3188    Factory* factory = target_array->GetIsolate()->factory();
3189    factory->SetContent(target_array, array_);
3190    target_array->set_length(Smi::FromInt(length_));
3191    return target_array;
3192  }
3193
3194
3195 private:
3196  Handle<FixedArray> array_;
3197  int length_;
3198  bool has_non_smi_elements_;
3199};
3200
3201
3202// Forward declarations.
3203const int kStringBuilderConcatHelperLengthBits = 11;
3204const int kStringBuilderConcatHelperPositionBits = 19;
3205
3206template <typename schar>
3207static inline void StringBuilderConcatHelper(String*,
3208                                             schar*,
3209                                             FixedArray*,
3210                                             int);
3211
3212typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3213    StringBuilderSubstringLength;
3214typedef BitField<int,
3215                 kStringBuilderConcatHelperLengthBits,
3216                 kStringBuilderConcatHelperPositionBits>
3217    StringBuilderSubstringPosition;
3218
3219
3220class ReplacementStringBuilder {
3221 public:
3222  ReplacementStringBuilder(Heap* heap,
3223                           Handle<String> subject,
3224                           int estimated_part_count)
3225      : heap_(heap),
3226        array_builder_(heap->isolate(), estimated_part_count),
3227        subject_(subject),
3228        character_count_(0),
3229        is_ascii_(subject->IsOneByteRepresentation()) {
3230    // Require a non-zero initial size. Ensures that doubling the size to
3231    // extend the array will work.
3232    ASSERT(estimated_part_count > 0);
3233  }
3234
3235  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3236                                     int from,
3237                                     int to) {
3238    ASSERT(from >= 0);
3239    int length = to - from;
3240    ASSERT(length > 0);
3241    if (StringBuilderSubstringLength::is_valid(length) &&
3242        StringBuilderSubstringPosition::is_valid(from)) {
3243      int encoded_slice = StringBuilderSubstringLength::encode(length) |
3244          StringBuilderSubstringPosition::encode(from);
3245      builder->Add(Smi::FromInt(encoded_slice));
3246    } else {
3247      // Otherwise encode as two smis.
3248      builder->Add(Smi::FromInt(-length));
3249      builder->Add(Smi::FromInt(from));
3250    }
3251  }
3252
3253
3254  void EnsureCapacity(int elements) {
3255    array_builder_.EnsureCapacity(elements);
3256  }
3257
3258
3259  void AddSubjectSlice(int from, int to) {
3260    AddSubjectSlice(&array_builder_, from, to);
3261    IncrementCharacterCount(to - from);
3262  }
3263
3264
3265  void AddString(Handle<String> string) {
3266    int length = string->length();
3267    ASSERT(length > 0);
3268    AddElement(*string);
3269    if (!string->IsOneByteRepresentation()) {
3270      is_ascii_ = false;
3271    }
3272    IncrementCharacterCount(length);
3273  }
3274
3275
3276  Handle<String> ToString() {
3277    if (array_builder_.length() == 0) {
3278      return heap_->isolate()->factory()->empty_string();
3279    }
3280
3281    Handle<String> joined_string;
3282    if (is_ascii_) {
3283      Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3284      DisallowHeapAllocation no_gc;
3285      uint8_t* char_buffer = seq->GetChars();
3286      StringBuilderConcatHelper(*subject_,
3287                                char_buffer,
3288                                *array_builder_.array(),
3289                                array_builder_.length());
3290      joined_string = Handle<String>::cast(seq);
3291    } else {
3292      // Non-ASCII.
3293      Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3294      DisallowHeapAllocation no_gc;
3295      uc16* char_buffer = seq->GetChars();
3296      StringBuilderConcatHelper(*subject_,
3297                                char_buffer,
3298                                *array_builder_.array(),
3299                                array_builder_.length());
3300      joined_string = Handle<String>::cast(seq);
3301    }
3302    return joined_string;
3303  }
3304
3305
3306  void IncrementCharacterCount(int by) {
3307    if (character_count_ > String::kMaxLength - by) {
3308      V8::FatalProcessOutOfMemory("String.replace result too large.");
3309    }
3310    character_count_ += by;
3311  }
3312
3313 private:
3314  Handle<SeqOneByteString> NewRawOneByteString(int length) {
3315    return heap_->isolate()->factory()->NewRawOneByteString(length);
3316  }
3317
3318
3319  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3320    return heap_->isolate()->factory()->NewRawTwoByteString(length);
3321  }
3322
3323
3324  void AddElement(Object* element) {
3325    ASSERT(element->IsSmi() || element->IsString());
3326    ASSERT(array_builder_.capacity() > array_builder_.length());
3327    array_builder_.Add(element);
3328  }
3329
3330  Heap* heap_;
3331  FixedArrayBuilder array_builder_;
3332  Handle<String> subject_;
3333  int character_count_;
3334  bool is_ascii_;
3335};
3336
3337
3338class CompiledReplacement {
3339 public:
3340  explicit CompiledReplacement(Zone* zone)
3341      : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3342
3343  // Return whether the replacement is simple.
3344  bool Compile(Handle<String> replacement,
3345               int capture_count,
3346               int subject_length);
3347
3348  // Use Apply only if Compile returned false.
3349  void Apply(ReplacementStringBuilder* builder,
3350             int match_from,
3351             int match_to,
3352             int32_t* match);
3353
3354  // Number of distinct parts of the replacement pattern.
3355  int parts() {
3356    return parts_.length();
3357  }
3358
3359  Zone* zone() const { return zone_; }
3360
3361 private:
3362  enum PartType {
3363    SUBJECT_PREFIX = 1,
3364    SUBJECT_SUFFIX,
3365    SUBJECT_CAPTURE,
3366    REPLACEMENT_SUBSTRING,
3367    REPLACEMENT_STRING,
3368
3369    NUMBER_OF_PART_TYPES
3370  };
3371
3372  struct ReplacementPart {
3373    static inline ReplacementPart SubjectMatch() {
3374      return ReplacementPart(SUBJECT_CAPTURE, 0);
3375    }
3376    static inline ReplacementPart SubjectCapture(int capture_index) {
3377      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3378    }
3379    static inline ReplacementPart SubjectPrefix() {
3380      return ReplacementPart(SUBJECT_PREFIX, 0);
3381    }
3382    static inline ReplacementPart SubjectSuffix(int subject_length) {
3383      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3384    }
3385    static inline ReplacementPart ReplacementString() {
3386      return ReplacementPart(REPLACEMENT_STRING, 0);
3387    }
3388    static inline ReplacementPart ReplacementSubString(int from, int to) {
3389      ASSERT(from >= 0);
3390      ASSERT(to > from);
3391      return ReplacementPart(-from, to);
3392    }
3393
3394    // If tag <= 0 then it is the negation of a start index of a substring of
3395    // the replacement pattern, otherwise it's a value from PartType.
3396    ReplacementPart(int tag, int data)
3397        : tag(tag), data(data) {
3398      // Must be non-positive or a PartType value.
3399      ASSERT(tag < NUMBER_OF_PART_TYPES);
3400    }
3401    // Either a value of PartType or a non-positive number that is
3402    // the negation of an index into the replacement string.
3403    int tag;
3404    // The data value's interpretation depends on the value of tag:
3405    // tag == SUBJECT_PREFIX ||
3406    // tag == SUBJECT_SUFFIX:  data is unused.
3407    // tag == SUBJECT_CAPTURE: data is the number of the capture.
3408    // tag == REPLACEMENT_SUBSTRING ||
3409    // tag == REPLACEMENT_STRING:    data is index into array of substrings
3410    //                               of the replacement string.
3411    // tag <= 0: Temporary representation of the substring of the replacement
3412    //           string ranging over -tag .. data.
3413    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3414    //           substring objects.
3415    int data;
3416  };
3417
3418  template<typename Char>
3419  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3420                               Vector<Char> characters,
3421                               int capture_count,
3422                               int subject_length,
3423                               Zone* zone) {
3424    int length = characters.length();
3425    int last = 0;
3426    for (int i = 0; i < length; i++) {
3427      Char c = characters[i];
3428      if (c == '$') {
3429        int next_index = i + 1;
3430        if (next_index == length) {  // No next character!
3431          break;
3432        }
3433        Char c2 = characters[next_index];
3434        switch (c2) {
3435        case '$':
3436          if (i > last) {
3437            // There is a substring before. Include the first "$".
3438            parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3439                       zone);
3440            last = next_index + 1;  // Continue after the second "$".
3441          } else {
3442            // Let the next substring start with the second "$".
3443            last = next_index;
3444          }
3445          i = next_index;
3446          break;
3447        case '`':
3448          if (i > last) {
3449            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3450          }
3451          parts->Add(ReplacementPart::SubjectPrefix(), zone);
3452          i = next_index;
3453          last = i + 1;
3454          break;
3455        case '\'':
3456          if (i > last) {
3457            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3458          }
3459          parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3460          i = next_index;
3461          last = i + 1;
3462          break;
3463        case '&':
3464          if (i > last) {
3465            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3466          }
3467          parts->Add(ReplacementPart::SubjectMatch(), zone);
3468          i = next_index;
3469          last = i + 1;
3470          break;
3471        case '0':
3472        case '1':
3473        case '2':
3474        case '3':
3475        case '4':
3476        case '5':
3477        case '6':
3478        case '7':
3479        case '8':
3480        case '9': {
3481          int capture_ref = c2 - '0';
3482          if (capture_ref > capture_count) {
3483            i = next_index;
3484            continue;
3485          }
3486          int second_digit_index = next_index + 1;
3487          if (second_digit_index < length) {
3488            // Peek ahead to see if we have two digits.
3489            Char c3 = characters[second_digit_index];
3490            if ('0' <= c3 && c3 <= '9') {  // Double digits.
3491              int double_digit_ref = capture_ref * 10 + c3 - '0';
3492              if (double_digit_ref <= capture_count) {
3493                next_index = second_digit_index;
3494                capture_ref = double_digit_ref;
3495              }
3496            }
3497          }
3498          if (capture_ref > 0) {
3499            if (i > last) {
3500              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3501            }
3502            ASSERT(capture_ref <= capture_count);
3503            parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3504            last = next_index + 1;
3505          }
3506          i = next_index;
3507          break;
3508        }
3509        default:
3510          i = next_index;
3511          break;
3512        }
3513      }
3514    }
3515    if (length > last) {
3516      if (last == 0) {
3517        // Replacement is simple.  Do not use Apply to do the replacement.
3518        return true;
3519      } else {
3520        parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3521      }
3522    }
3523    return false;
3524  }
3525
3526  ZoneList<ReplacementPart> parts_;
3527  ZoneList<Handle<String> > replacement_substrings_;
3528  Zone* zone_;
3529};
3530
3531
3532bool CompiledReplacement::Compile(Handle<String> replacement,
3533                                  int capture_count,
3534                                  int subject_length) {
3535  {
3536    DisallowHeapAllocation no_gc;
3537    String::FlatContent content = replacement->GetFlatContent();
3538    ASSERT(content.IsFlat());
3539    bool simple = false;
3540    if (content.IsAscii()) {
3541      simple = ParseReplacementPattern(&parts_,
3542                                       content.ToOneByteVector(),
3543                                       capture_count,
3544                                       subject_length,
3545                                       zone());
3546    } else {
3547      ASSERT(content.IsTwoByte());
3548      simple = ParseReplacementPattern(&parts_,
3549                                       content.ToUC16Vector(),
3550                                       capture_count,
3551                                       subject_length,
3552                                       zone());
3553    }
3554    if (simple) return true;
3555  }
3556
3557  Isolate* isolate = replacement->GetIsolate();
3558  // Find substrings of replacement string and create them as String objects.
3559  int substring_index = 0;
3560  for (int i = 0, n = parts_.length(); i < n; i++) {
3561    int tag = parts_[i].tag;
3562    if (tag <= 0) {  // A replacement string slice.
3563      int from = -tag;
3564      int to = parts_[i].data;
3565      replacement_substrings_.Add(
3566          isolate->factory()->NewSubString(replacement, from, to), zone());
3567      parts_[i].tag = REPLACEMENT_SUBSTRING;
3568      parts_[i].data = substring_index;
3569      substring_index++;
3570    } else if (tag == REPLACEMENT_STRING) {
3571      replacement_substrings_.Add(replacement, zone());
3572      parts_[i].data = substring_index;
3573      substring_index++;
3574    }
3575  }
3576  return false;
3577}
3578
3579
3580void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3581                                int match_from,
3582                                int match_to,
3583                                int32_t* match) {
3584  ASSERT_LT(0, parts_.length());
3585  for (int i = 0, n = parts_.length(); i < n; i++) {
3586    ReplacementPart part = parts_[i];
3587    switch (part.tag) {
3588      case SUBJECT_PREFIX:
3589        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3590        break;
3591      case SUBJECT_SUFFIX: {
3592        int subject_length = part.data;
3593        if (match_to < subject_length) {
3594          builder->AddSubjectSlice(match_to, subject_length);
3595        }
3596        break;
3597      }
3598      case SUBJECT_CAPTURE: {
3599        int capture = part.data;
3600        int from = match[capture * 2];
3601        int to = match[capture * 2 + 1];
3602        if (from >= 0 && to > from) {
3603          builder->AddSubjectSlice(from, to);
3604        }
3605        break;
3606      }
3607      case REPLACEMENT_SUBSTRING:
3608      case REPLACEMENT_STRING:
3609        builder->AddString(replacement_substrings_[part.data]);
3610        break;
3611      default:
3612        UNREACHABLE();
3613    }
3614  }
3615}
3616
3617
3618void FindAsciiStringIndices(Vector<const uint8_t> subject,
3619                            char pattern,
3620                            ZoneList<int>* indices,
3621                            unsigned int limit,
3622                            Zone* zone) {
3623  ASSERT(limit > 0);
3624  // Collect indices of pattern in subject using memchr.
3625  // Stop after finding at most limit values.
3626  const uint8_t* subject_start = subject.start();
3627  const uint8_t* subject_end = subject_start + subject.length();
3628  const uint8_t* pos = subject_start;
3629  while (limit > 0) {
3630    pos = reinterpret_cast<const uint8_t*>(
3631        memchr(pos, pattern, subject_end - pos));
3632    if (pos == NULL) return;
3633    indices->Add(static_cast<int>(pos - subject_start), zone);
3634    pos++;
3635    limit--;
3636  }
3637}
3638
3639
3640void FindTwoByteStringIndices(const Vector<const uc16> subject,
3641                              uc16 pattern,
3642                              ZoneList<int>* indices,
3643                              unsigned int limit,
3644                              Zone* zone) {
3645  ASSERT(limit > 0);
3646  const uc16* subject_start = subject.start();
3647  const uc16* subject_end = subject_start + subject.length();
3648  for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3649    if (*pos == pattern) {
3650      indices->Add(static_cast<int>(pos - subject_start), zone);
3651      limit--;
3652    }
3653  }
3654}
3655
3656
3657template <typename SubjectChar, typename PatternChar>
3658void FindStringIndices(Isolate* isolate,
3659                       Vector<const SubjectChar> subject,
3660                       Vector<const PatternChar> pattern,
3661                       ZoneList<int>* indices,
3662                       unsigned int limit,
3663                       Zone* zone) {
3664  ASSERT(limit > 0);
3665  // Collect indices of pattern in subject.
3666  // Stop after finding at most limit values.
3667  int pattern_length = pattern.length();
3668  int index = 0;
3669  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3670  while (limit > 0) {
3671    index = search.Search(subject, index);
3672    if (index < 0) return;
3673    indices->Add(index, zone);
3674    index += pattern_length;
3675    limit--;
3676  }
3677}
3678
3679
3680void FindStringIndicesDispatch(Isolate* isolate,
3681                               String* subject,
3682                               String* pattern,
3683                               ZoneList<int>* indices,
3684                               unsigned int limit,
3685                               Zone* zone) {
3686  {
3687    DisallowHeapAllocation no_gc;
3688    String::FlatContent subject_content = subject->GetFlatContent();
3689    String::FlatContent pattern_content = pattern->GetFlatContent();
3690    ASSERT(subject_content.IsFlat());
3691    ASSERT(pattern_content.IsFlat());
3692    if (subject_content.IsAscii()) {
3693      Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3694      if (pattern_content.IsAscii()) {
3695        Vector<const uint8_t> pattern_vector =
3696            pattern_content.ToOneByteVector();
3697        if (pattern_vector.length() == 1) {
3698          FindAsciiStringIndices(subject_vector,
3699                                 pattern_vector[0],
3700                                 indices,
3701                                 limit,
3702                                 zone);
3703        } else {
3704          FindStringIndices(isolate,
3705                            subject_vector,
3706                            pattern_vector,
3707                            indices,
3708                            limit,
3709                            zone);
3710        }
3711      } else {
3712        FindStringIndices(isolate,
3713                          subject_vector,
3714                          pattern_content.ToUC16Vector(),
3715                          indices,
3716                          limit,
3717                          zone);
3718      }
3719    } else {
3720      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3721      if (pattern_content.IsAscii()) {
3722        Vector<const uint8_t> pattern_vector =
3723            pattern_content.ToOneByteVector();
3724        if (pattern_vector.length() == 1) {
3725          FindTwoByteStringIndices(subject_vector,
3726                                   pattern_vector[0],
3727                                   indices,
3728                                   limit,
3729                                   zone);
3730        } else {
3731          FindStringIndices(isolate,
3732                            subject_vector,
3733                            pattern_vector,
3734                            indices,
3735                            limit,
3736                            zone);
3737        }
3738      } else {
3739        Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3740        if (pattern_vector.length() == 1) {
3741          FindTwoByteStringIndices(subject_vector,
3742                                   pattern_vector[0],
3743                                   indices,
3744                                   limit,
3745                                   zone);
3746        } else {
3747          FindStringIndices(isolate,
3748                            subject_vector,
3749                            pattern_vector,
3750                            indices,
3751                            limit,
3752                            zone);
3753        }
3754      }
3755    }
3756  }
3757}
3758
3759
3760template<typename ResultSeqString>
3761MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3762    Isolate* isolate,
3763    Handle<String> subject,
3764    Handle<JSRegExp> pattern_regexp,
3765    Handle<String> replacement,
3766    Handle<JSArray> last_match_info) {
3767  ASSERT(subject->IsFlat());
3768  ASSERT(replacement->IsFlat());
3769
3770  ZoneScope zone_scope(isolate->runtime_zone());
3771  ZoneList<int> indices(8, zone_scope.zone());
3772  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3773  String* pattern =
3774      String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3775  int subject_len = subject->length();
3776  int pattern_len = pattern->length();
3777  int replacement_len = replacement->length();
3778
3779  FindStringIndicesDispatch(
3780      isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3781
3782  int matches = indices.length();
3783  if (matches == 0) return *subject;
3784
3785  // Detect integer overflow.
3786  int64_t result_len_64 =
3787      (static_cast<int64_t>(replacement_len) -
3788       static_cast<int64_t>(pattern_len)) *
3789      static_cast<int64_t>(matches) +
3790      static_cast<int64_t>(subject_len);
3791  if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
3792  int result_len = static_cast<int>(result_len_64);
3793
3794  int subject_pos = 0;
3795  int result_pos = 0;
3796
3797  Handle<ResultSeqString> result;
3798  if (ResultSeqString::kHasAsciiEncoding) {
3799    result = Handle<ResultSeqString>::cast(
3800        isolate->factory()->NewRawOneByteString(result_len));
3801  } else {
3802    result = Handle<ResultSeqString>::cast(
3803        isolate->factory()->NewRawTwoByteString(result_len));
3804  }
3805
3806  for (int i = 0; i < matches; i++) {
3807    // Copy non-matched subject content.
3808    if (subject_pos < indices.at(i)) {
3809      String::WriteToFlat(*subject,
3810                          result->GetChars() + result_pos,
3811                          subject_pos,
3812                          indices.at(i));
3813      result_pos += indices.at(i) - subject_pos;
3814    }
3815
3816    // Replace match.
3817    if (replacement_len > 0) {
3818      String::WriteToFlat(*replacement,
3819                          result->GetChars() + result_pos,
3820                          0,
3821                          replacement_len);
3822      result_pos += replacement_len;
3823    }
3824
3825    subject_pos = indices.at(i) + pattern_len;
3826  }
3827  // Add remaining subject content at the end.
3828  if (subject_pos < subject_len) {
3829    String::WriteToFlat(*subject,
3830                        result->GetChars() + result_pos,
3831                        subject_pos,
3832                        subject_len);
3833  }
3834
3835  int32_t match_indices[] = { indices.at(matches - 1),
3836                              indices.at(matches - 1) + pattern_len };
3837  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3838
3839  return *result;
3840}
3841
3842
3843MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
3844    Isolate* isolate,
3845    Handle<String> subject,
3846    Handle<JSRegExp> regexp,
3847    Handle<String> replacement,
3848    Handle<JSArray> last_match_info) {
3849  ASSERT(subject->IsFlat());
3850  ASSERT(replacement->IsFlat());
3851
3852  int capture_count = regexp->CaptureCount();
3853  int subject_length = subject->length();
3854
3855  // CompiledReplacement uses zone allocation.
3856  ZoneScope zone_scope(isolate->runtime_zone());
3857  CompiledReplacement compiled_replacement(zone_scope.zone());
3858  bool simple_replace = compiled_replacement.Compile(replacement,
3859                                                     capture_count,
3860                                                     subject_length);
3861
3862  // Shortcut for simple non-regexp global replacements
3863  if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
3864    if (subject->HasOnlyOneByteChars() &&
3865        replacement->HasOnlyOneByteChars()) {
3866      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3867          isolate, subject, regexp, replacement, last_match_info);
3868    } else {
3869      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3870          isolate, subject, regexp, replacement, last_match_info);
3871    }
3872  }
3873
3874  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3875  if (global_cache.HasException()) return Failure::Exception();
3876
3877  int32_t* current_match = global_cache.FetchNext();
3878  if (current_match == NULL) {
3879    if (global_cache.HasException()) return Failure::Exception();
3880    return *subject;
3881  }
3882
3883  // Guessing the number of parts that the final result string is built
3884  // from. Global regexps can match any number of times, so we guess
3885  // conservatively.
3886  int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
3887  ReplacementStringBuilder builder(isolate->heap(),
3888                                   subject,
3889                                   expected_parts);
3890
3891  // Number of parts added by compiled replacement plus preceeding
3892  // string and possibly suffix after last match.  It is possible for
3893  // all components to use two elements when encoded as two smis.
3894  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3895
3896  int prev = 0;
3897
3898  do {
3899    builder.EnsureCapacity(parts_added_per_loop);
3900
3901    int start = current_match[0];
3902    int end = current_match[1];
3903
3904    if (prev < start) {
3905      builder.AddSubjectSlice(prev, start);
3906    }
3907
3908    if (simple_replace) {
3909      builder.AddString(replacement);
3910    } else {
3911      compiled_replacement.Apply(&builder,
3912                                 start,
3913                                 end,
3914                                 current_match);
3915    }
3916    prev = end;
3917
3918    current_match = global_cache.FetchNext();
3919  } while (current_match != NULL);
3920
3921  if (global_cache.HasException()) return Failure::Exception();
3922
3923  if (prev < subject_length) {
3924    builder.EnsureCapacity(2);
3925    builder.AddSubjectSlice(prev, subject_length);
3926  }
3927
3928  RegExpImpl::SetLastMatchInfo(last_match_info,
3929                               subject,
3930                               capture_count,
3931                               global_cache.LastSuccessfulMatch());
3932
3933  return *(builder.ToString());
3934}
3935
3936
3937template <typename ResultSeqString>
3938MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
3939    Isolate* isolate,
3940    Handle<String> subject,
3941    Handle<JSRegExp> regexp,
3942    Handle<JSArray> last_match_info) {
3943  ASSERT(subject->IsFlat());
3944
3945  // Shortcut for simple non-regexp global replacements
3946  if (regexp->TypeTag() == JSRegExp::ATOM) {
3947    Handle<String> empty_string = isolate->factory()->empty_string();
3948    if (subject->IsOneByteRepresentation()) {
3949      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3950          isolate, subject, regexp, empty_string, last_match_info);
3951    } else {
3952      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3953          isolate, subject, regexp, empty_string, last_match_info);
3954    }
3955  }
3956
3957  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3958  if (global_cache.HasException()) return Failure::Exception();
3959
3960  int32_t* current_match = global_cache.FetchNext();
3961  if (current_match == NULL) {
3962    if (global_cache.HasException()) return Failure::Exception();
3963    return *subject;
3964  }
3965
3966  int start = current_match[0];
3967  int end = current_match[1];
3968  int capture_count = regexp->CaptureCount();
3969  int subject_length = subject->length();
3970
3971  int new_length = subject_length - (end - start);
3972  if (new_length == 0) return isolate->heap()->empty_string();
3973
3974  Handle<ResultSeqString> answer;
3975  if (ResultSeqString::kHasAsciiEncoding) {
3976    answer = Handle<ResultSeqString>::cast(
3977        isolate->factory()->NewRawOneByteString(new_length));
3978  } else {
3979    answer = Handle<ResultSeqString>::cast(
3980        isolate->factory()->NewRawTwoByteString(new_length));
3981  }
3982
3983  int prev = 0;
3984  int position = 0;
3985
3986  do {
3987    start = current_match[0];
3988    end = current_match[1];
3989    if (prev < start) {
3990      // Add substring subject[prev;start] to answer string.
3991      String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
3992      position += start - prev;
3993    }
3994    prev = end;
3995
3996    current_match = global_cache.FetchNext();
3997  } while (current_match != NULL);
3998
3999  if (global_cache.HasException()) return Failure::Exception();
4000
4001  RegExpImpl::SetLastMatchInfo(last_match_info,
4002                               subject,
4003                               capture_count,
4004                               global_cache.LastSuccessfulMatch());
4005
4006  if (prev < subject_length) {
4007    // Add substring subject[prev;length] to answer string.
4008    String::WriteToFlat(
4009        *subject, answer->GetChars() + position, prev, subject_length);
4010    position += subject_length - prev;
4011  }
4012
4013  if (position == 0) return isolate->heap()->empty_string();
4014
4015  // Shorten string and fill
4016  int string_size = ResultSeqString::SizeFor(position);
4017  int allocated_string_size = ResultSeqString::SizeFor(new_length);
4018  int delta = allocated_string_size - string_size;
4019
4020  answer->set_length(position);
4021  if (delta == 0) return *answer;
4022
4023  Address end_of_string = answer->address() + string_size;
4024  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
4025  if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
4026    MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
4027  }
4028
4029  return *answer;
4030}
4031
4032
4033RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4034  HandleScope scope(isolate);
4035  ASSERT(args.length() == 4);
4036
4037  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4038  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4039  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4040  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4041
4042  ASSERT(regexp->GetFlags().is_global());
4043
4044  if (!subject->IsFlat()) subject = FlattenGetString(subject);
4045
4046  if (replacement->length() == 0) {
4047    if (subject->HasOnlyOneByteChars()) {
4048      return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4049          isolate, subject, regexp, last_match_info);
4050    } else {
4051      return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4052          isolate, subject, regexp, last_match_info);
4053    }
4054  }
4055
4056  if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4057
4058  return StringReplaceGlobalRegExpWithString(
4059      isolate, subject, regexp, replacement, last_match_info);
4060}
4061
4062
4063Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
4064                                              Handle<String> subject,
4065                                              Handle<String> search,
4066                                              Handle<String> replace,
4067                                              bool* found,
4068                                              int recursion_limit) {
4069  if (recursion_limit == 0) return Handle<String>::null();
4070  if (subject->IsConsString()) {
4071    ConsString* cons = ConsString::cast(*subject);
4072    Handle<String> first = Handle<String>(cons->first());
4073    Handle<String> second = Handle<String>(cons->second());
4074    Handle<String> new_first =
4075        StringReplaceOneCharWithString(isolate,
4076                                       first,
4077                                       search,
4078                                       replace,
4079                                       found,
4080                                       recursion_limit - 1);
4081    if (*found) return isolate->factory()->NewConsString(new_first, second);
4082    if (new_first.is_null()) return new_first;
4083
4084    Handle<String> new_second =
4085        StringReplaceOneCharWithString(isolate,
4086                                       second,
4087                                       search,
4088                                       replace,
4089                                       found,
4090                                       recursion_limit - 1);
4091    if (*found) return isolate->factory()->NewConsString(first, new_second);
4092    if (new_second.is_null()) return new_second;
4093
4094    return subject;
4095  } else {
4096    int index = Runtime::StringMatch(isolate, subject, search, 0);
4097    if (index == -1) return subject;
4098    *found = true;
4099    Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4100    Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4101    Handle<String> second =
4102        isolate->factory()->NewSubString(subject, index + 1, subject->length());
4103    return isolate->factory()->NewConsString(cons1, second);
4104  }
4105}
4106
4107
4108RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4109  HandleScope scope(isolate);
4110  ASSERT(args.length() == 3);
4111  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4112  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4113  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4114
4115  // If the cons string tree is too deep, we simply abort the recursion and
4116  // retry with a flattened subject string.
4117  const int kRecursionLimit = 0x1000;
4118  bool found = false;
4119  Handle<String> result = StringReplaceOneCharWithString(isolate,
4120                                                         subject,
4121                                                         search,
4122                                                         replace,
4123                                                         &found,
4124                                                         kRecursionLimit);
4125  if (!result.is_null()) return *result;
4126  return *StringReplaceOneCharWithString(isolate,
4127                                         FlattenGetString(subject),
4128                                         search,
4129                                         replace,
4130                                         &found,
4131                                         kRecursionLimit);
4132}
4133
4134
4135// Perform string match of pattern on subject, starting at start index.
4136// Caller must ensure that 0 <= start_index <= sub->length(),
4137// and should check that pat->length() + start_index <= sub->length().
4138int Runtime::StringMatch(Isolate* isolate,
4139                         Handle<String> sub,
4140                         Handle<String> pat,
4141                         int start_index) {
4142  ASSERT(0 <= start_index);
4143  ASSERT(start_index <= sub->length());
4144
4145  int pattern_length = pat->length();
4146  if (pattern_length == 0) return start_index;
4147
4148  int subject_length = sub->length();
4149  if (start_index + pattern_length > subject_length) return -1;
4150
4151  if (!sub->IsFlat()) FlattenString(sub);
4152  if (!pat->IsFlat()) FlattenString(pat);
4153
4154  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4155  // Extract flattened substrings of cons strings before determining asciiness.
4156  String::FlatContent seq_sub = sub->GetFlatContent();
4157  String::FlatContent seq_pat = pat->GetFlatContent();
4158
4159  // dispatch on type of strings
4160  if (seq_pat.IsAscii()) {
4161    Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4162    if (seq_sub.IsAscii()) {
4163      return SearchString(isolate,
4164                          seq_sub.ToOneByteVector(),
4165                          pat_vector,
4166                          start_index);
4167    }
4168    return SearchString(isolate,
4169                        seq_sub.ToUC16Vector(),
4170                        pat_vector,
4171                        start_index);
4172  }
4173  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4174  if (seq_sub.IsAscii()) {
4175    return SearchString(isolate,
4176                        seq_sub.ToOneByteVector(),
4177                        pat_vector,
4178                        start_index);
4179  }
4180  return SearchString(isolate,
4181                      seq_sub.ToUC16Vector(),
4182                      pat_vector,
4183                      start_index);
4184}
4185
4186
4187RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4188  HandleScope scope(isolate);
4189  ASSERT(args.length() == 3);
4190
4191  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4192  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4193
4194  Object* index = args[2];
4195  uint32_t start_index;
4196  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4197
4198  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4199  int position =
4200      Runtime::StringMatch(isolate, sub, pat, start_index);
4201  return Smi::FromInt(position);
4202}
4203
4204
4205template <typename schar, typename pchar>
4206static int StringMatchBackwards(Vector<const schar> subject,
4207                                Vector<const pchar> pattern,
4208                                int idx) {
4209  int pattern_length = pattern.length();
4210  ASSERT(pattern_length >= 1);
4211  ASSERT(idx + pattern_length <= subject.length());
4212
4213  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4214    for (int i = 0; i < pattern_length; i++) {
4215      uc16 c = pattern[i];
4216      if (c > String::kMaxOneByteCharCode) {
4217        return -1;
4218      }
4219    }
4220  }
4221
4222  pchar pattern_first_char = pattern[0];
4223  for (int i = idx; i >= 0; i--) {
4224    if (subject[i] != pattern_first_char) continue;
4225    int j = 1;
4226    while (j < pattern_length) {
4227      if (pattern[j] != subject[i+j]) {
4228        break;
4229      }
4230      j++;
4231    }
4232    if (j == pattern_length) {
4233      return i;
4234    }
4235  }
4236  return -1;
4237}
4238
4239
4240RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4241  HandleScope scope(isolate);
4242  ASSERT(args.length() == 3);
4243
4244  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4245  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4246
4247  Object* index = args[2];
4248  uint32_t start_index;
4249  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4250
4251  uint32_t pat_length = pat->length();
4252  uint32_t sub_length = sub->length();
4253
4254  if (start_index + pat_length > sub_length) {
4255    start_index = sub_length - pat_length;
4256  }
4257
4258  if (pat_length == 0) {
4259    return Smi::FromInt(start_index);
4260  }
4261
4262  if (!sub->IsFlat()) FlattenString(sub);
4263  if (!pat->IsFlat()) FlattenString(pat);
4264
4265  int position = -1;
4266  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4267
4268  String::FlatContent sub_content = sub->GetFlatContent();
4269  String::FlatContent pat_content = pat->GetFlatContent();
4270
4271  if (pat_content.IsAscii()) {
4272    Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4273    if (sub_content.IsAscii()) {
4274      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4275                                      pat_vector,
4276                                      start_index);
4277    } else {
4278      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4279                                      pat_vector,
4280                                      start_index);
4281    }
4282  } else {
4283    Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4284    if (sub_content.IsAscii()) {
4285      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4286                                      pat_vector,
4287                                      start_index);
4288    } else {
4289      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4290                                      pat_vector,
4291                                      start_index);
4292    }
4293  }
4294
4295  return Smi::FromInt(position);
4296}
4297
4298
4299RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4300  SealHandleScope shs(isolate);
4301  ASSERT(args.length() == 2);
4302
4303  CONVERT_ARG_CHECKED(String, str1, 0);
4304  CONVERT_ARG_CHECKED(String, str2, 1);
4305
4306  if (str1 == str2) return Smi::FromInt(0);  // Equal.
4307  int str1_length = str1->length();
4308  int str2_length = str2->length();
4309
4310  // Decide trivial cases without flattening.
4311  if (str1_length == 0) {
4312    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4313    return Smi::FromInt(-str2_length);
4314  } else {
4315    if (str2_length == 0) return Smi::FromInt(str1_length);
4316  }
4317
4318  int end = str1_length < str2_length ? str1_length : str2_length;
4319
4320  // No need to flatten if we are going to find the answer on the first
4321  // character.  At this point we know there is at least one character
4322  // in each string, due to the trivial case handling above.
4323  int d = str1->Get(0) - str2->Get(0);
4324  if (d != 0) return Smi::FromInt(d);
4325
4326  str1->TryFlatten();
4327  str2->TryFlatten();
4328
4329  ConsStringIteratorOp* op1 =
4330      isolate->runtime_state()->string_locale_compare_it1();
4331  ConsStringIteratorOp* op2 =
4332      isolate->runtime_state()->string_locale_compare_it2();
4333  // TODO(dcarney) Can do array compares here more efficiently.
4334  StringCharacterStream stream1(str1, op1);
4335  StringCharacterStream stream2(str2, op2);
4336
4337  for (int i = 0; i < end; i++) {
4338    uint16_t char1 = stream1.GetNext();
4339    uint16_t char2 = stream2.GetNext();
4340    if (char1 != char2) return Smi::FromInt(char1 - char2);
4341  }
4342
4343  return Smi::FromInt(str1_length - str2_length);
4344}
4345
4346
4347RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
4348  SealHandleScope shs(isolate);
4349  ASSERT(args.length() == 3);
4350
4351  CONVERT_ARG_CHECKED(String, value, 0);
4352  int start, end;
4353  // We have a fast integer-only case here to avoid a conversion to double in
4354  // the common case where from and to are Smis.
4355  if (args[1]->IsSmi() && args[2]->IsSmi()) {
4356    CONVERT_SMI_ARG_CHECKED(from_number, 1);
4357    CONVERT_SMI_ARG_CHECKED(to_number, 2);
4358    start = from_number;
4359    end = to_number;
4360  } else {
4361    CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4362    CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4363    start = FastD2IChecked(from_number);
4364    end = FastD2IChecked(to_number);
4365  }
4366  RUNTIME_ASSERT(end >= start);
4367  RUNTIME_ASSERT(start >= 0);
4368  RUNTIME_ASSERT(end <= value->length());
4369  isolate->counters()->sub_string_runtime()->Increment();
4370  if (end - start == 1) {
4371     return isolate->heap()->LookupSingleCharacterStringFromCode(
4372         value->Get(start));
4373  }
4374  return value->SubString(start, end);
4375}
4376
4377
4378RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4379  HandleScope handles(isolate);
4380  ASSERT_EQ(3, args.length());
4381
4382  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4383  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4384  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4385
4386  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4387  if (global_cache.HasException()) return Failure::Exception();
4388
4389  int capture_count = regexp->CaptureCount();
4390
4391  ZoneScope zone_scope(isolate->runtime_zone());
4392  ZoneList<int> offsets(8, zone_scope.zone());
4393
4394  while (true) {
4395    int32_t* match = global_cache.FetchNext();
4396    if (match == NULL) break;
4397    offsets.Add(match[0], zone_scope.zone());  // start
4398    offsets.Add(match[1], zone_scope.zone());  // end
4399  }
4400
4401  if (global_cache.HasException()) return Failure::Exception();
4402
4403  if (offsets.length() == 0) {
4404    // Not a single match.
4405    return isolate->heap()->null_value();
4406  }
4407
4408  RegExpImpl::SetLastMatchInfo(regexp_info,
4409                               subject,
4410                               capture_count,
4411                               global_cache.LastSuccessfulMatch());
4412
4413  int matches = offsets.length() / 2;
4414  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4415  Handle<String> substring =
4416      isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4417  elements->set(0, *substring);
4418  for (int i = 1; i < matches; i++) {
4419    HandleScope temp_scope(isolate);
4420    int from = offsets.at(i * 2);
4421    int to = offsets.at(i * 2 + 1);
4422    Handle<String> substring =
4423        isolate->factory()->NewProperSubString(subject, from, to);
4424    elements->set(i, *substring);
4425  }
4426  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4427  result->set_length(Smi::FromInt(matches));
4428  return *result;
4429}
4430
4431
4432// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4433// separate last match info.  See comment on that function.
4434template<bool has_capture>
4435static MaybeObject* SearchRegExpMultiple(
4436    Isolate* isolate,
4437    Handle<String> subject,
4438    Handle<JSRegExp> regexp,
4439    Handle<JSArray> last_match_array,
4440    Handle<JSArray> result_array) {
4441  ASSERT(subject->IsFlat());
4442  ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4443
4444  int capture_count = regexp->CaptureCount();
4445  int subject_length = subject->length();
4446
4447  static const int kMinLengthToCache = 0x1000;
4448
4449  if (subject_length > kMinLengthToCache) {
4450    Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4451        isolate->heap(),
4452        *subject,
4453        regexp->data(),
4454        RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4455    if (*cached_answer != Smi::FromInt(0)) {
4456      Handle<FixedArray> cached_fixed_array =
4457          Handle<FixedArray>(FixedArray::cast(*cached_answer));
4458      // The cache FixedArray is a COW-array and can therefore be reused.
4459      isolate->factory()->SetContent(result_array, cached_fixed_array);
4460      // The actual length of the result array is stored in the last element of
4461      // the backing store (the backing FixedArray may have a larger capacity).
4462      Object* cached_fixed_array_last_element =
4463          cached_fixed_array->get(cached_fixed_array->length() - 1);
4464      Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4465      result_array->set_length(js_array_length);
4466      RegExpImpl::SetLastMatchInfo(
4467          last_match_array, subject, capture_count, NULL);
4468      return *result_array;
4469    }
4470  }
4471
4472  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4473  if (global_cache.HasException()) return Failure::Exception();
4474
4475  Handle<FixedArray> result_elements;
4476  if (result_array->HasFastObjectElements()) {
4477    result_elements =
4478        Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4479  }
4480  if (result_elements.is_null() || result_elements->length() < 16) {
4481    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4482  }
4483
4484  FixedArrayBuilder builder(result_elements);
4485
4486  // Position to search from.
4487  int match_start = -1;
4488  int match_end = 0;
4489  bool first = true;
4490
4491  // Two smis before and after the match, for very long strings.
4492  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4493
4494  while (true) {
4495    int32_t* current_match = global_cache.FetchNext();
4496    if (current_match == NULL) break;
4497    match_start = current_match[0];
4498    builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4499    if (match_end < match_start) {
4500      ReplacementStringBuilder::AddSubjectSlice(&builder,
4501                                                match_end,
4502                                                match_start);
4503    }
4504    match_end = current_match[1];
4505    {
4506      // Avoid accumulating new handles inside loop.
4507      HandleScope temp_scope(isolate);
4508      Handle<String> match;
4509      if (!first) {
4510        match = isolate->factory()->NewProperSubString(subject,
4511                                                       match_start,
4512                                                       match_end);
4513      } else {
4514        match = isolate->factory()->NewSubString(subject,
4515                                                 match_start,
4516                                                 match_end);
4517        first = false;
4518      }
4519
4520      if (has_capture) {
4521        // Arguments array to replace function is match, captures, index and
4522        // subject, i.e., 3 + capture count in total.
4523        Handle<FixedArray> elements =
4524            isolate->factory()->NewFixedArray(3 + capture_count);
4525
4526        elements->set(0, *match);
4527        for (int i = 1; i <= capture_count; i++) {
4528          int start = current_match[i * 2];
4529          if (start >= 0) {
4530            int end = current_match[i * 2 + 1];
4531            ASSERT(start <= end);
4532            Handle<String> substring =
4533                isolate->factory()->NewSubString(subject, start, end);
4534            elements->set(i, *substring);
4535          } else {
4536            ASSERT(current_match[i * 2 + 1] < 0);
4537            elements->set(i, isolate->heap()->undefined_value());
4538          }
4539        }
4540        elements->set(capture_count + 1, Smi::FromInt(match_start));
4541        elements->set(capture_count + 2, *subject);
4542        builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4543      } else {
4544        builder.Add(*match);
4545      }
4546    }
4547  }
4548
4549  if (global_cache.HasException()) return Failure::Exception();
4550
4551  if (match_start >= 0) {
4552    // Finished matching, with at least one match.
4553    if (match_end < subject_length) {
4554      ReplacementStringBuilder::AddSubjectSlice(&builder,
4555                                                match_end,
4556                                                subject_length);
4557    }
4558
4559    RegExpImpl::SetLastMatchInfo(
4560        last_match_array, subject, capture_count, NULL);
4561
4562    if (subject_length > kMinLengthToCache) {
4563      // Store the length of the result array into the last element of the
4564      // backing FixedArray.
4565      builder.EnsureCapacity(1);
4566      Handle<FixedArray> fixed_array = builder.array();
4567      fixed_array->set(fixed_array->length() - 1,
4568                       Smi::FromInt(builder.length()));
4569      // Cache the result and turn the FixedArray into a COW array.
4570      RegExpResultsCache::Enter(isolate->heap(),
4571                                *subject,
4572                                regexp->data(),
4573                                *fixed_array,
4574                                RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4575    }
4576    return *builder.ToJSArray(result_array);
4577  } else {
4578    return isolate->heap()->null_value();  // No matches at all.
4579  }
4580}
4581
4582
4583// This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4584// lastMatchInfoOverride to maintain the last match info, so we don't need to
4585// set any other last match array info.
4586RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4587  HandleScope handles(isolate);
4588  ASSERT(args.length() == 4);
4589
4590  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4591  if (!subject->IsFlat()) FlattenString(subject);
4592  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4593  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4594  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4595
4596  ASSERT(regexp->GetFlags().is_global());
4597
4598  if (regexp->CaptureCount() == 0) {
4599    return SearchRegExpMultiple<false>(
4600        isolate, subject, regexp, last_match_info, result_array);
4601  } else {
4602    return SearchRegExpMultiple<true>(
4603        isolate, subject, regexp, last_match_info, result_array);
4604  }
4605}
4606
4607
4608RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4609  SealHandleScope shs(isolate);
4610  ASSERT(args.length() == 2);
4611  CONVERT_SMI_ARG_CHECKED(radix, 1);
4612  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4613
4614  // Fast case where the result is a one character string.
4615  if (args[0]->IsSmi()) {
4616    int value = args.smi_at(0);
4617    if (value >= 0 && value < radix) {
4618      // Character array used for conversion.
4619      static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4620      return isolate->heap()->
4621          LookupSingleCharacterStringFromCode(kCharTable[value]);
4622    }
4623  }
4624
4625  // Slow case.
4626  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4627  if (std::isnan(value)) {
4628    return *isolate->factory()->nan_string();
4629  }
4630  if (std::isinf(value)) {
4631    if (value < 0) {
4632      return *isolate->factory()->minus_infinity_string();
4633    }
4634    return *isolate->factory()->infinity_string();
4635  }
4636  char* str = DoubleToRadixCString(value, radix);
4637  MaybeObject* result =
4638      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4639  DeleteArray(str);
4640  return result;
4641}
4642
4643
4644RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4645  SealHandleScope shs(isolate);
4646  ASSERT(args.length() == 2);
4647
4648  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4649  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4650  int f = FastD2IChecked(f_number);
4651  RUNTIME_ASSERT(f >= 0);
4652  char* str = DoubleToFixedCString(value, f);
4653  MaybeObject* res =
4654      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4655  DeleteArray(str);
4656  return res;
4657}
4658
4659
4660RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4661  SealHandleScope shs(isolate);
4662  ASSERT(args.length() == 2);
4663
4664  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4665  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4666  int f = FastD2IChecked(f_number);
4667  RUNTIME_ASSERT(f >= -1 && f <= 20);
4668  char* str = DoubleToExponentialCString(value, f);
4669  MaybeObject* res =
4670      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4671  DeleteArray(str);
4672  return res;
4673}
4674
4675
4676RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4677  SealHandleScope shs(isolate);
4678  ASSERT(args.length() == 2);
4679
4680  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4681  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4682  int f = FastD2IChecked(f_number);
4683  RUNTIME_ASSERT(f >= 1 && f <= 21);
4684  char* str = DoubleToPrecisionCString(value, f);
4685  MaybeObject* res =
4686      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4687  DeleteArray(str);
4688  return res;
4689}
4690
4691
4692// Returns a single character string where first character equals
4693// string->Get(index).
4694static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4695  if (index < static_cast<uint32_t>(string->length())) {
4696    string->TryFlatten();
4697    return LookupSingleCharacterStringFromCode(
4698        string->GetIsolate(),
4699        string->Get(index));
4700  }
4701  return Execution::CharAt(string, index);
4702}
4703
4704
4705MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
4706                                               Handle<Object> object,
4707                                               uint32_t index) {
4708  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4709      GetElementOrCharAt(isolate, object, index));
4710}
4711
4712
4713MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4714                                         Handle<Object> object,
4715                                         uint32_t index) {
4716  // Handle [] indexing on Strings
4717  if (object->IsString()) {
4718    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4719    if (!result->IsUndefined()) return *result;
4720  }
4721
4722  // Handle [] indexing on String objects
4723  if (object->IsStringObjectWithCharacterAt(index)) {
4724    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4725    Handle<Object> result =
4726        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4727    if (!result->IsUndefined()) return *result;
4728  }
4729
4730  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4731    return object->GetPrototype(isolate)->GetElement(index);
4732  }
4733
4734  return object->GetElement(index);
4735}
4736
4737
4738MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4739                                        Handle<JSReceiver> object,
4740                                        Handle<Object> key) {
4741  HandleScope scope(isolate);
4742
4743  // Check if the given key is an array index.
4744  uint32_t index;
4745  if (key->ToArrayIndex(&index)) {
4746    return isolate->heap()->ToBoolean(object->HasElement(index));
4747  }
4748
4749  // Convert the key to a name - possibly by calling back into JavaScript.
4750  Handle<Name> name;
4751  if (key->IsName()) {
4752    name = Handle<Name>::cast(key);
4753  } else {
4754    bool has_pending_exception = false;
4755    Handle<Object> converted =
4756        Execution::ToString(key, &has_pending_exception);
4757    if (has_pending_exception) return Failure::Exception();
4758    name = Handle<Name>::cast(converted);
4759  }
4760
4761  return isolate->heap()->ToBoolean(object->HasProperty(*name));
4762}
4763
4764MaybeObject* Runtime::GetObjectPropertyOrFail(
4765    Isolate* isolate,
4766    Handle<Object> object,
4767    Handle<Object> key) {
4768  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4769      GetObjectProperty(isolate, object, key));
4770}
4771
4772MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4773                                        Handle<Object> object,
4774                                        Handle<Object> key) {
4775  HandleScope scope(isolate);
4776
4777  if (object->IsUndefined() || object->IsNull()) {
4778    Handle<Object> args[2] = { key, object };
4779    Handle<Object> error =
4780        isolate->factory()->NewTypeError("non_object_property_load",
4781                                         HandleVector(args, 2));
4782    return isolate->Throw(*error);
4783  }
4784
4785  // Check if the given key is an array index.
4786  uint32_t index;
4787  if (key->ToArrayIndex(&index)) {
4788    return GetElementOrCharAt(isolate, object, index);
4789  }
4790
4791  // Convert the key to a name - possibly by calling back into JavaScript.
4792  Handle<Name> name;
4793  if (key->IsName()) {
4794    name = Handle<Name>::cast(key);
4795  } else {
4796    bool has_pending_exception = false;
4797    Handle<Object> converted =
4798        Execution::ToString(key, &has_pending_exception);
4799    if (has_pending_exception) return Failure::Exception();
4800    name = Handle<Name>::cast(converted);
4801  }
4802
4803  // Check if the name is trivially convertible to an index and get
4804  // the element if so.
4805  if (name->AsArrayIndex(&index)) {
4806    return GetElementOrCharAt(isolate, object, index);
4807  } else {
4808    return object->GetProperty(*name);
4809  }
4810}
4811
4812
4813RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4814  SealHandleScope shs(isolate);
4815  ASSERT(args.length() == 2);
4816
4817  Handle<Object> object = args.at<Object>(0);
4818  Handle<Object> key = args.at<Object>(1);
4819
4820  return Runtime::GetObjectProperty(isolate, object, key);
4821}
4822
4823
4824// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
4825RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4826  SealHandleScope shs(isolate);
4827  ASSERT(args.length() == 2);
4828
4829  // Fast cases for getting named properties of the receiver JSObject
4830  // itself.
4831  //
4832  // The global proxy objects has to be excluded since LocalLookup on
4833  // the global proxy object can return a valid result even though the
4834  // global proxy object never has properties.  This is the case
4835  // because the global proxy object forwards everything to its hidden
4836  // prototype including local lookups.
4837  //
4838  // Additionally, we need to make sure that we do not cache results
4839  // for objects that require access checks.
4840  if (args[0]->IsJSObject()) {
4841    if (!args[0]->IsJSGlobalProxy() &&
4842        !args[0]->IsAccessCheckNeeded() &&
4843        args[1]->IsName()) {
4844      JSObject* receiver = JSObject::cast(args[0]);
4845      Name* key = Name::cast(args[1]);
4846      if (receiver->HasFastProperties()) {
4847        // Attempt to use lookup cache.
4848        Map* receiver_map = receiver->map();
4849        KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4850        int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4851        if (offset != -1) {
4852          // Doubles are not cached, so raw read the value.
4853          Object* value = receiver->RawFastPropertyAt(offset);
4854          return value->IsTheHole()
4855              ? isolate->heap()->undefined_value()
4856              : value;
4857        }
4858        // Lookup cache miss.  Perform lookup and update the cache if
4859        // appropriate.
4860        LookupResult result(isolate);
4861        receiver->LocalLookup(key, &result);
4862        if (result.IsField()) {
4863          int offset = result.GetFieldIndex().field_index();
4864          // Do not track double fields in the keyed lookup cache. Reading
4865          // double values requires boxing.
4866          if (!FLAG_track_double_fields ||
4867              !result.representation().IsDouble()) {
4868            keyed_lookup_cache->Update(receiver_map, key, offset);
4869          }
4870          return receiver->FastPropertyAt(result.representation(), offset);
4871        }
4872      } else {
4873        // Attempt dictionary lookup.
4874        NameDictionary* dictionary = receiver->property_dictionary();
4875        int entry = dictionary->FindEntry(key);
4876        if ((entry != NameDictionary::kNotFound) &&
4877            (dictionary->DetailsAt(entry).type() == NORMAL)) {
4878          Object* value = dictionary->ValueAt(entry);
4879          if (!receiver->IsGlobalObject()) return value;
4880          value = PropertyCell::cast(value)->value();
4881          if (!value->IsTheHole()) return value;
4882          // If value is the hole do the general lookup.
4883        }
4884      }
4885    } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4886      // JSObject without a name key. If the key is a Smi, check for a
4887      // definite out-of-bounds access to elements, which is a strong indicator
4888      // that subsequent accesses will also call the runtime. Proactively
4889      // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4890      // doubles for those future calls in the case that the elements would
4891      // become FAST_DOUBLE_ELEMENTS.
4892      Handle<JSObject> js_object(args.at<JSObject>(0));
4893      ElementsKind elements_kind = js_object->GetElementsKind();
4894      if (IsFastDoubleElementsKind(elements_kind)) {
4895        FixedArrayBase* elements = js_object->elements();
4896        if (args.at<Smi>(1)->value() >= elements->length()) {
4897          if (IsFastHoleyElementsKind(elements_kind)) {
4898            elements_kind = FAST_HOLEY_ELEMENTS;
4899          } else {
4900            elements_kind = FAST_ELEMENTS;
4901          }
4902          MaybeObject* maybe_object = TransitionElements(js_object,
4903                                                         elements_kind,
4904                                                         isolate);
4905          if (maybe_object->IsFailure()) return maybe_object;
4906        }
4907      } else {
4908        ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
4909               !IsFastElementsKind(elements_kind));
4910      }
4911    }
4912  } else if (args[0]->IsString() && args[1]->IsSmi()) {
4913    // Fast case for string indexing using [] with a smi index.
4914    HandleScope scope(isolate);
4915    Handle<String> str = args.at<String>(0);
4916    int index = args.smi_at(1);
4917    if (index >= 0 && index < str->length()) {
4918      Handle<Object> result = GetCharAt(str, index);
4919      return *result;
4920    }
4921  }
4922
4923  // Fall back to GetObjectProperty.
4924  return Runtime::GetObjectProperty(isolate,
4925                                    args.at<Object>(0),
4926                                    args.at<Object>(1));
4927}
4928
4929
4930static bool IsValidAccessor(Handle<Object> obj) {
4931  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4932}
4933
4934
4935// Implements part of 8.12.9 DefineOwnProperty.
4936// There are 3 cases that lead here:
4937// Step 4b - define a new accessor property.
4938// Steps 9c & 12 - replace an existing data property with an accessor property.
4939// Step 12 - update an existing accessor property with an accessor or generic
4940//           descriptor.
4941RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4942  HandleScope scope(isolate);
4943  ASSERT(args.length() == 5);
4944  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4945  RUNTIME_ASSERT(!obj->IsNull());
4946  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
4947  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4948  RUNTIME_ASSERT(IsValidAccessor(getter));
4949  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4950  RUNTIME_ASSERT(IsValidAccessor(setter));
4951  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4952  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4953  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4954
4955  bool fast = obj->HasFastProperties();
4956  JSObject::DefineAccessor(obj, name, getter, setter, attr);
4957  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
4958  if (fast) JSObject::TransformToFastProperties(obj, 0);
4959  return isolate->heap()->undefined_value();
4960}
4961
4962
4963// Implements part of 8.12.9 DefineOwnProperty.
4964// There are 3 cases that lead here:
4965// Step 4a - define a new data property.
4966// Steps 9b & 12 - replace an existing accessor property with a data property.
4967// Step 12 - update an existing data property with a data or generic
4968//           descriptor.
4969RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4970  HandleScope scope(isolate);
4971  ASSERT(args.length() == 4);
4972  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4973  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
4974  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4975  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4976  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4977  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4978
4979  LookupResult result(isolate);
4980  js_object->LocalLookupRealNamedProperty(*name, &result);
4981
4982  // Special case for callback properties.
4983  if (result.IsPropertyCallbacks()) {
4984    Object* callback = result.GetCallbackObject();
4985    // To be compatible with Safari we do not change the value on API objects
4986    // in Object.defineProperty(). Firefox disagrees here, and actually changes
4987    // the value.
4988    if (callback->IsAccessorInfo()) {
4989      return isolate->heap()->undefined_value();
4990    }
4991    // Avoid redefining foreign callback as data property, just use the stored
4992    // setter to update the value instead.
4993    // TODO(mstarzinger): So far this only works if property attributes don't
4994    // change, this should be fixed once we cleanup the underlying code.
4995    if (callback->IsForeign() && result.GetAttributes() == attr) {
4996      return js_object->SetPropertyWithCallback(callback,
4997                                                *name,
4998                                                *obj_value,
4999                                                result.holder(),
5000                                                kStrictMode);
5001    }
5002  }
5003
5004  // Take special care when attributes are different and there is already
5005  // a property. For simplicity we normalize the property which enables us
5006  // to not worry about changing the instance_descriptor and creating a new
5007  // map. The current version of SetObjectProperty does not handle attributes
5008  // correctly in the case where a property is a field and is reset with
5009  // new attributes.
5010  if (result.IsFound() &&
5011      (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
5012    // New attributes - normalize to avoid writing to instance descriptor
5013    if (js_object->IsJSGlobalProxy()) {
5014      // Since the result is a property, the prototype will exist so
5015      // we don't have to check for null.
5016      js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5017    }
5018    JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5019    // Use IgnoreAttributes version since a readonly property may be
5020    // overridden and SetProperty does not allow this.
5021    return js_object->SetLocalPropertyIgnoreAttributes(*name,
5022                                                       *obj_value,
5023                                                       attr);
5024  }
5025
5026  return Runtime::ForceSetObjectProperty(isolate,
5027                                         js_object,
5028                                         name,
5029                                         obj_value,
5030                                         attr);
5031}
5032
5033
5034// Return property without being observable by accessors or interceptors.
5035RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5036  SealHandleScope shs(isolate);
5037  ASSERT(args.length() == 2);
5038  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5039  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5040  LookupResult lookup(isolate);
5041  object->LookupRealNamedProperty(*key, &lookup);
5042  if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5043  switch (lookup.type()) {
5044    case NORMAL:
5045      return lookup.holder()->GetNormalizedProperty(&lookup);
5046    case FIELD:
5047      return lookup.holder()->FastPropertyAt(
5048          lookup.representation(),
5049          lookup.GetFieldIndex().field_index());
5050    case CONSTANT:
5051      return lookup.GetConstant();
5052    case CALLBACKS:
5053    case HANDLER:
5054    case INTERCEPTOR:
5055    case TRANSITION:
5056      return isolate->heap()->undefined_value();
5057    case NONEXISTENT:
5058      UNREACHABLE();
5059  }
5060  return isolate->heap()->undefined_value();
5061}
5062
5063
5064MaybeObject* Runtime::SetObjectPropertyOrFail(
5065    Isolate* isolate,
5066    Handle<Object> object,
5067    Handle<Object> key,
5068    Handle<Object> value,
5069    PropertyAttributes attr,
5070    StrictModeFlag strict_mode) {
5071  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
5072      SetObjectProperty(isolate, object, key, value, attr, strict_mode));
5073}
5074
5075
5076MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
5077                                        Handle<Object> object,
5078                                        Handle<Object> key,
5079                                        Handle<Object> value,
5080                                        PropertyAttributes attr,
5081                                        StrictModeFlag strict_mode) {
5082  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5083  HandleScope scope(isolate);
5084
5085  if (object->IsUndefined() || object->IsNull()) {
5086    Handle<Object> args[2] = { key, object };
5087    Handle<Object> error =
5088        isolate->factory()->NewTypeError("non_object_property_store",
5089                                         HandleVector(args, 2));
5090    return isolate->Throw(*error);
5091  }
5092
5093  if (object->IsJSProxy()) {
5094    bool has_pending_exception = false;
5095    Handle<Object> name = key->IsSymbol()
5096        ? key : Execution::ToString(key, &has_pending_exception);
5097    if (has_pending_exception) return Failure::Exception();
5098    return JSProxy::cast(*object)->SetProperty(
5099        Name::cast(*name), *value, attr, strict_mode);
5100  }
5101
5102  // If the object isn't a JavaScript object, we ignore the store.
5103  if (!object->IsJSObject()) return *value;
5104
5105  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5106
5107  // Check if the given key is an array index.
5108  uint32_t index;
5109  if (key->ToArrayIndex(&index)) {
5110    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5111    // of a string using [] notation.  We need to support this too in
5112    // JavaScript.
5113    // In the case of a String object we just need to redirect the assignment to
5114    // the underlying string if the index is in range.  Since the underlying
5115    // string does nothing with the assignment then we can ignore such
5116    // assignments.
5117    if (js_object->IsStringObjectWithCharacterAt(index)) {
5118      return *value;
5119    }
5120
5121    js_object->ValidateElements();
5122    if (js_object->HasExternalArrayElements()) {
5123      if (!value->IsNumber() && !value->IsUndefined()) {
5124        bool has_exception;
5125        Handle<Object> number = Execution::ToNumber(value, &has_exception);
5126        if (has_exception) return Failure::Exception();
5127        value = number;
5128      }
5129    }
5130    MaybeObject* result = js_object->SetElement(
5131        index, *value, attr, strict_mode, true, set_mode);
5132    js_object->ValidateElements();
5133    if (result->IsFailure()) return result;
5134    return *value;
5135  }
5136
5137  if (key->IsName()) {
5138    MaybeObject* result;
5139    Handle<Name> name = Handle<Name>::cast(key);
5140    if (name->AsArrayIndex(&index)) {
5141      if (js_object->HasExternalArrayElements()) {
5142        if (!value->IsNumber() && !value->IsUndefined()) {
5143          bool has_exception;
5144          Handle<Object> number = Execution::ToNumber(value, &has_exception);
5145          if (has_exception) return Failure::Exception();
5146          value = number;
5147        }
5148      }
5149      result = js_object->SetElement(
5150          index, *value, attr, strict_mode, true, set_mode);
5151    } else {
5152      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5153      result = js_object->SetProperty(*name, *value, attr, strict_mode);
5154    }
5155    if (result->IsFailure()) return result;
5156    return *value;
5157  }
5158
5159  // Call-back into JavaScript to convert the key to a string.
5160  bool has_pending_exception = false;
5161  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5162  if (has_pending_exception) return Failure::Exception();
5163  Handle<String> name = Handle<String>::cast(converted);
5164
5165  if (name->AsArrayIndex(&index)) {
5166    return js_object->SetElement(
5167        index, *value, attr, strict_mode, true, set_mode);
5168  } else {
5169    return js_object->SetProperty(*name, *value, attr, strict_mode);
5170  }
5171}
5172
5173
5174MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
5175                                             Handle<JSObject> js_object,
5176                                             Handle<Object> key,
5177                                             Handle<Object> value,
5178                                             PropertyAttributes attr) {
5179  HandleScope scope(isolate);
5180
5181  // Check if the given key is an array index.
5182  uint32_t index;
5183  if (key->ToArrayIndex(&index)) {
5184    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5185    // of a string using [] notation.  We need to support this too in
5186    // JavaScript.
5187    // In the case of a String object we just need to redirect the assignment to
5188    // the underlying string if the index is in range.  Since the underlying
5189    // string does nothing with the assignment then we can ignore such
5190    // assignments.
5191    if (js_object->IsStringObjectWithCharacterAt(index)) {
5192      return *value;
5193    }
5194
5195    return js_object->SetElement(
5196        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5197  }
5198
5199  if (key->IsName()) {
5200    Handle<Name> name = Handle<Name>::cast(key);
5201    if (name->AsArrayIndex(&index)) {
5202      return js_object->SetElement(
5203          index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5204    } else {
5205      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5206      return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
5207    }
5208  }
5209
5210  // Call-back into JavaScript to convert the key to a string.
5211  bool has_pending_exception = false;
5212  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5213  if (has_pending_exception) return Failure::Exception();
5214  Handle<String> name = Handle<String>::cast(converted);
5215
5216  if (name->AsArrayIndex(&index)) {
5217    return js_object->SetElement(
5218        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5219  } else {
5220    return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
5221  }
5222}
5223
5224
5225MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5226                                           Handle<JSReceiver> receiver,
5227                                           Handle<Object> key,
5228                                           JSReceiver::DeleteMode mode) {
5229  HandleScope scope(isolate);
5230
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
5235    // characters of a string using [] notation.  In the case of a
5236    // String object we just need to redirect the deletion to the
5237    // underlying string if the index is in range.  Since the
5238    // underlying string does nothing with the deletion, we can ignore
5239    // such deletions.
5240    if (receiver->IsStringObjectWithCharacterAt(index)) {
5241      return isolate->heap()->true_value();
5242    }
5243
5244    Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5245    RETURN_IF_EMPTY_HANDLE(isolate, result);
5246    return *result;
5247  }
5248
5249  Handle<Name> name;
5250  if (key->IsName()) {
5251    name = Handle<Name>::cast(key);
5252  } else {
5253    // Call-back into JavaScript to convert the key to a string.
5254    bool has_pending_exception = false;
5255    Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5256    if (has_pending_exception) return Failure::Exception();
5257    name = Handle<String>::cast(converted);
5258  }
5259
5260  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5261  Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5262  RETURN_IF_EMPTY_HANDLE(isolate, result);
5263  return *result;
5264}
5265
5266
5267RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5268  SealHandleScope shs(isolate);
5269  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5270
5271  Handle<Object> object = args.at<Object>(0);
5272  Handle<Object> key = args.at<Object>(1);
5273  Handle<Object> value = args.at<Object>(2);
5274  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5275  RUNTIME_ASSERT(
5276      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5277  // Compute attributes.
5278  PropertyAttributes attributes =
5279      static_cast<PropertyAttributes>(unchecked_attributes);
5280
5281  StrictModeFlag strict_mode = kNonStrictMode;
5282  if (args.length() == 5) {
5283    CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
5284    strict_mode = strict_mode_flag;
5285  }
5286
5287  return Runtime::SetObjectProperty(isolate,
5288                                    object,
5289                                    key,
5290                                    value,
5291                                    attributes,
5292                                    strict_mode);
5293}
5294
5295
5296RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5297  HandleScope scope(isolate);
5298  RUNTIME_ASSERT(args.length() == 2);
5299  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5300  CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5301  JSObject::TransitionElementsKind(array, map->elements_kind());
5302  return *array;
5303}
5304
5305
5306// Set the native flag on the function.
5307// This is used to decide if we should transform null and undefined
5308// into the global object when doing call and apply.
5309RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5310  SealHandleScope shs(isolate);
5311  RUNTIME_ASSERT(args.length() == 1);
5312
5313  Handle<Object> object = args.at<Object>(0);
5314
5315  if (object->IsJSFunction()) {
5316    JSFunction* func = JSFunction::cast(*object);
5317    func->shared()->set_native(true);
5318  }
5319  return isolate->heap()->undefined_value();
5320}
5321
5322
5323RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5324  HandleScope scope(isolate);
5325  RUNTIME_ASSERT(args.length() == 5);
5326  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5327  CONVERT_SMI_ARG_CHECKED(store_index, 1);
5328  Handle<Object> value = args.at<Object>(2);
5329  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5330  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5331
5332  Object* raw_literal_cell = literals->get(literal_index);
5333  JSArray* boilerplate = NULL;
5334  if (raw_literal_cell->IsAllocationSite()) {
5335    AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5336    boilerplate = JSArray::cast(site->transition_info());
5337  } else {
5338    boilerplate = JSArray::cast(raw_literal_cell);
5339  }
5340  Handle<JSArray> boilerplate_object(boilerplate);
5341  ElementsKind elements_kind = object->GetElementsKind();
5342  ASSERT(IsFastElementsKind(elements_kind));
5343  // Smis should never trigger transitions.
5344  ASSERT(!value->IsSmi());
5345
5346  if (value->IsNumber()) {
5347    ASSERT(IsFastSmiElementsKind(elements_kind));
5348    ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5349        ? FAST_HOLEY_DOUBLE_ELEMENTS
5350        : FAST_DOUBLE_ELEMENTS;
5351    if (IsMoreGeneralElementsKindTransition(
5352            boilerplate_object->GetElementsKind(),
5353            transitioned_kind)) {
5354      JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5355    }
5356    JSObject::TransitionElementsKind(object, transitioned_kind);
5357    ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5358    FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5359    HeapNumber* number = HeapNumber::cast(*value);
5360    double_array->set(store_index, number->Number());
5361  } else {
5362    ASSERT(IsFastSmiElementsKind(elements_kind) ||
5363           IsFastDoubleElementsKind(elements_kind));
5364    ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5365        ? FAST_HOLEY_ELEMENTS
5366        : FAST_ELEMENTS;
5367    JSObject::TransitionElementsKind(object, transitioned_kind);
5368    if (IsMoreGeneralElementsKindTransition(
5369            boilerplate_object->GetElementsKind(),
5370            transitioned_kind)) {
5371      JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5372    }
5373    FixedArray* object_array = FixedArray::cast(object->elements());
5374    object_array->set(store_index, *value);
5375  }
5376  return *object;
5377}
5378
5379
5380// Check whether debugger and is about to step into the callback that is passed
5381// to a built-in function such as Array.forEach.
5382RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5383  SealHandleScope shs(isolate);
5384#ifdef ENABLE_DEBUGGER_SUPPORT
5385  if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5386    return isolate->heap()->false_value();
5387  }
5388  CONVERT_ARG_CHECKED(Object, callback, 0);
5389  // We do not step into the callback if it's a builtin or not even a function.
5390  if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5391    return isolate->heap()->false_value();
5392  }
5393  return isolate->heap()->true_value();
5394#else
5395  return isolate->heap()->false_value();
5396#endif  // ENABLE_DEBUGGER_SUPPORT
5397}
5398
5399
5400// Set one shot breakpoints for the callback function that is passed to a
5401// built-in function such as Array.forEach to enable stepping into the callback.
5402RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5403  SealHandleScope shs(isolate);
5404#ifdef ENABLE_DEBUGGER_SUPPORT
5405  Debug* debug = isolate->debug();
5406  if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5407  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5408  HandleScope scope(isolate);
5409  // When leaving the callback, step out has been activated, but not performed
5410  // if we do not leave the builtin.  To be able to step into the callback
5411  // again, we need to clear the step out at this point.
5412  debug->ClearStepOut();
5413  debug->FloodWithOneShot(callback);
5414#endif  // ENABLE_DEBUGGER_SUPPORT
5415  return isolate->heap()->undefined_value();
5416}
5417
5418
5419// Set a local property, even if it is READ_ONLY.  If the property does not
5420// exist, it will be added with attributes NONE.
5421RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5422  SealHandleScope shs(isolate);
5423  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5424  CONVERT_ARG_CHECKED(JSObject, object, 0);
5425  CONVERT_ARG_CHECKED(Name, name, 1);
5426  // Compute attributes.
5427  PropertyAttributes attributes = NONE;
5428  if (args.length() == 4) {
5429    CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5430    // Only attribute bits should be set.
5431    RUNTIME_ASSERT(
5432        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5433    attributes = static_cast<PropertyAttributes>(unchecked_value);
5434  }
5435
5436  return object->
5437      SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
5438}
5439
5440
5441RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5442  HandleScope scope(isolate);
5443  ASSERT(args.length() == 3);
5444  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5445  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5446  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5447  JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
5448      ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5449  Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5450  RETURN_IF_EMPTY_HANDLE(isolate, result);
5451  return *result;
5452}
5453
5454
5455static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5456                                                   Handle<JSObject> object,
5457                                                   Handle<Name> key) {
5458  if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
5459  // Handle hidden prototypes.  If there's a hidden prototype above this thing
5460  // then we have to check it for properties, because they are supposed to
5461  // look like they are on this object.
5462  Handle<Object> proto(object->GetPrototype(), isolate);
5463  if (proto->IsJSObject() &&
5464      Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5465    return HasLocalPropertyImplementation(isolate,
5466                                          Handle<JSObject>::cast(proto),
5467                                          key);
5468  }
5469  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5470  return isolate->heap()->false_value();
5471}
5472
5473
5474RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5475  SealHandleScope shs(isolate);
5476  ASSERT(args.length() == 2);
5477  CONVERT_ARG_CHECKED(Name, key, 1);
5478
5479  uint32_t index;
5480  const bool key_is_array_index = key->AsArrayIndex(&index);
5481
5482  Object* obj = args[0];
5483  // Only JS objects can have properties.
5484  if (obj->IsJSObject()) {
5485    JSObject* object = JSObject::cast(obj);
5486    // Fast case: either the key is a real named property or it is not
5487    // an array index and there are no interceptors or hidden
5488    // prototypes.
5489    if (object->HasRealNamedProperty(isolate, key)) {
5490      ASSERT(!isolate->has_scheduled_exception());
5491      return isolate->heap()->true_value();
5492    } else {
5493      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5494    }
5495    Map* map = object->map();
5496    if (!key_is_array_index &&
5497        !map->has_named_interceptor() &&
5498        !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5499      return isolate->heap()->false_value();
5500    }
5501    // Slow case.
5502    HandleScope scope(isolate);
5503    return HasLocalPropertyImplementation(isolate,
5504                                          Handle<JSObject>(object),
5505                                          Handle<Name>(key));
5506  } else if (obj->IsString() && key_is_array_index) {
5507    // Well, there is one exception:  Handle [] on strings.
5508    String* string = String::cast(obj);
5509    if (index < static_cast<uint32_t>(string->length())) {
5510      return isolate->heap()->true_value();
5511    }
5512  }
5513  return isolate->heap()->false_value();
5514}
5515
5516
5517RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5518  SealHandleScope shs(isolate);
5519  ASSERT(args.length() == 2);
5520  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
5521  CONVERT_ARG_CHECKED(Name, key, 1);
5522
5523  bool result = receiver->HasProperty(key);
5524  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5525  if (isolate->has_pending_exception()) return Failure::Exception();
5526  return isolate->heap()->ToBoolean(result);
5527}
5528
5529
5530RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5531  SealHandleScope shs(isolate);
5532  ASSERT(args.length() == 2);
5533  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
5534  CONVERT_SMI_ARG_CHECKED(index, 1);
5535
5536  bool result = receiver->HasElement(index);
5537  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5538  if (isolate->has_pending_exception()) return Failure::Exception();
5539  return isolate->heap()->ToBoolean(result);
5540}
5541
5542
5543RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5544  SealHandleScope shs(isolate);
5545  ASSERT(args.length() == 2);
5546
5547  CONVERT_ARG_CHECKED(JSObject, object, 0);
5548  CONVERT_ARG_CHECKED(Name, key, 1);
5549
5550  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
5551  if (att == ABSENT || (att & DONT_ENUM) != 0) {
5552    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5553    return isolate->heap()->false_value();
5554  }
5555  ASSERT(!isolate->has_scheduled_exception());
5556  return isolate->heap()->true_value();
5557}
5558
5559
5560RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5561  HandleScope scope(isolate);
5562  ASSERT(args.length() == 1);
5563  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5564  bool threw = false;
5565  Handle<JSArray> result = GetKeysFor(object, &threw);
5566  if (threw) return Failure::Exception();
5567  return *result;
5568}
5569
5570
5571// Returns either a FixedArray as Runtime_GetPropertyNames,
5572// or, if the given object has an enum cache that contains
5573// all enumerable properties of the object and its prototypes
5574// have none, the map of the object. This is used to speed up
5575// the check for deletions during a for-in.
5576RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5577  SealHandleScope shs(isolate);
5578  ASSERT(args.length() == 1);
5579
5580  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5581
5582  if (raw_object->IsSimpleEnum()) return raw_object->map();
5583
5584  HandleScope scope(isolate);
5585  Handle<JSReceiver> object(raw_object);
5586  bool threw = false;
5587  Handle<FixedArray> content =
5588      GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5589  if (threw) return Failure::Exception();
5590
5591  // Test again, since cache may have been built by preceding call.
5592  if (object->IsSimpleEnum()) return object->map();
5593
5594  return *content;
5595}
5596
5597
5598// Find the length of the prototype chain that is to to handled as one. If a
5599// prototype object is hidden it is to be viewed as part of the the object it
5600// is prototype for.
5601static int LocalPrototypeChainLength(JSObject* obj) {
5602  int count = 1;
5603  Object* proto = obj->GetPrototype();
5604  while (proto->IsJSObject() &&
5605         JSObject::cast(proto)->map()->is_hidden_prototype()) {
5606    count++;
5607    proto = JSObject::cast(proto)->GetPrototype();
5608  }
5609  return count;
5610}
5611
5612
5613// Return the names of the local named properties.
5614// args[0]: object
5615RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5616  HandleScope scope(isolate);
5617  ASSERT(args.length() == 2);
5618  if (!args[0]->IsJSObject()) {
5619    return isolate->heap()->undefined_value();
5620  }
5621  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5622  CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
5623  PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
5624
5625  // Skip the global proxy as it has no properties and always delegates to the
5626  // real global object.
5627  if (obj->IsJSGlobalProxy()) {
5628    // Only collect names if access is permitted.
5629    if (obj->IsAccessCheckNeeded() &&
5630        !isolate->MayNamedAccess(*obj,
5631                                 isolate->heap()->undefined_value(),
5632                                 v8::ACCESS_KEYS)) {
5633      isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5634      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5635      return *isolate->factory()->NewJSArray(0);
5636    }
5637    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5638  }
5639
5640  // Find the number of objects making up this.
5641  int length = LocalPrototypeChainLength(*obj);
5642
5643  // Find the number of local properties for each of the objects.
5644  ScopedVector<int> local_property_count(length);
5645  int total_property_count = 0;
5646  Handle<JSObject> jsproto = obj;
5647  for (int i = 0; i < length; i++) {
5648    // Only collect names if access is permitted.
5649    if (jsproto->IsAccessCheckNeeded() &&
5650        !isolate->MayNamedAccess(*jsproto,
5651                                 isolate->heap()->undefined_value(),
5652                                 v8::ACCESS_KEYS)) {
5653      isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5654      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5655      return *isolate->factory()->NewJSArray(0);
5656    }
5657    int n;
5658    n = jsproto->NumberOfLocalProperties(filter);
5659    local_property_count[i] = n;
5660    total_property_count += n;
5661    if (i < length - 1) {
5662      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5663    }
5664  }
5665
5666  // Allocate an array with storage for all the property names.
5667  Handle<FixedArray> names =
5668      isolate->factory()->NewFixedArray(total_property_count);
5669
5670  // Get the property names.
5671  jsproto = obj;
5672  int proto_with_hidden_properties = 0;
5673  int next_copy_index = 0;
5674  for (int i = 0; i < length; i++) {
5675    jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5676    next_copy_index += local_property_count[i];
5677    if (jsproto->HasHiddenProperties()) {
5678      proto_with_hidden_properties++;
5679    }
5680    if (i < length - 1) {
5681      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5682    }
5683  }
5684
5685  // Filter out name of hidden properties object.
5686  if (proto_with_hidden_properties > 0) {
5687    Handle<FixedArray> old_names = names;
5688    names = isolate->factory()->NewFixedArray(
5689        names->length() - proto_with_hidden_properties);
5690    int dest_pos = 0;
5691    for (int i = 0; i < total_property_count; i++) {
5692      Object* name = old_names->get(i);
5693      if (name == isolate->heap()->hidden_string()) {
5694        continue;
5695      }
5696      names->set(dest_pos++, name);
5697    }
5698  }
5699
5700  return *isolate->factory()->NewJSArrayWithElements(names);
5701}
5702
5703
5704// Return the names of the local indexed properties.
5705// args[0]: object
5706RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5707  HandleScope scope(isolate);
5708  ASSERT(args.length() == 1);
5709  if (!args[0]->IsJSObject()) {
5710    return isolate->heap()->undefined_value();
5711  }
5712  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5713
5714  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5715  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5716  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5717  return *isolate->factory()->NewJSArrayWithElements(names);
5718}
5719
5720
5721// Return information on whether an object has a named or indexed interceptor.
5722// args[0]: object
5723RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5724  HandleScope scope(isolate);
5725  ASSERT(args.length() == 1);
5726  if (!args[0]->IsJSObject()) {
5727    return Smi::FromInt(0);
5728  }
5729  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5730
5731  int result = 0;
5732  if (obj->HasNamedInterceptor()) result |= 2;
5733  if (obj->HasIndexedInterceptor()) result |= 1;
5734
5735  return Smi::FromInt(result);
5736}
5737
5738
5739// Return property names from named interceptor.
5740// args[0]: object
5741RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5742  HandleScope scope(isolate);
5743  ASSERT(args.length() == 1);
5744  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5745
5746  if (obj->HasNamedInterceptor()) {
5747    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5748    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5749  }
5750  return isolate->heap()->undefined_value();
5751}
5752
5753
5754// Return element names from indexed interceptor.
5755// args[0]: object
5756RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5757  HandleScope scope(isolate);
5758  ASSERT(args.length() == 1);
5759  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5760
5761  if (obj->HasIndexedInterceptor()) {
5762    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5763    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5764  }
5765  return isolate->heap()->undefined_value();
5766}
5767
5768
5769RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5770  HandleScope scope(isolate);
5771  ASSERT_EQ(args.length(), 1);
5772  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5773  Handle<JSObject> object(raw_object);
5774
5775  if (object->IsJSGlobalProxy()) {
5776    // Do access checks before going to the global object.
5777    if (object->IsAccessCheckNeeded() &&
5778        !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5779                             v8::ACCESS_KEYS)) {
5780      isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5781      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5782      return *isolate->factory()->NewJSArray(0);
5783    }
5784
5785    Handle<Object> proto(object->GetPrototype(), isolate);
5786    // If proxy is detached we simply return an empty array.
5787    if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5788    object = Handle<JSObject>::cast(proto);
5789  }
5790
5791  bool threw = false;
5792  Handle<FixedArray> contents =
5793      GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5794  if (threw) return Failure::Exception();
5795
5796  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5797  // property array and since the result is mutable we have to create
5798  // a fresh clone on each invocation.
5799  int length = contents->length();
5800  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5801  for (int i = 0; i < length; i++) {
5802    Object* entry = contents->get(i);
5803    if (entry->IsString()) {
5804      copy->set(i, entry);
5805    } else {
5806      ASSERT(entry->IsNumber());
5807      HandleScope scope(isolate);
5808      Handle<Object> entry_handle(entry, isolate);
5809      Handle<Object> entry_str =
5810          isolate->factory()->NumberToString(entry_handle);
5811      copy->set(i, *entry_str);
5812    }
5813  }
5814  return *isolate->factory()->NewJSArrayWithElements(copy);
5815}
5816
5817
5818RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5819  SealHandleScope shs(isolate);
5820  ASSERT(args.length() == 1);
5821
5822  // Compute the frame holding the arguments.
5823  JavaScriptFrameIterator it(isolate);
5824  it.AdvanceToArgumentsFrame();
5825  JavaScriptFrame* frame = it.frame();
5826
5827  // Get the actual number of provided arguments.
5828  const uint32_t n = frame->ComputeParametersCount();
5829
5830  // Try to convert the key to an index. If successful and within
5831  // index return the the argument from the frame.
5832  uint32_t index;
5833  if (args[0]->ToArrayIndex(&index) && index < n) {
5834    return frame->GetParameter(index);
5835  }
5836
5837  if (args[0]->IsSymbol()) {
5838    // Lookup in the initial Object.prototype object.
5839    return isolate->initial_object_prototype()->GetProperty(
5840        Symbol::cast(args[0]));
5841  }
5842
5843  // Convert the key to a string.
5844  HandleScope scope(isolate);
5845  bool exception = false;
5846  Handle<Object> converted =
5847      Execution::ToString(args.at<Object>(0), &exception);
5848  if (exception) return Failure::Exception();
5849  Handle<String> key = Handle<String>::cast(converted);
5850
5851  // Try to convert the string key into an array index.
5852  if (key->AsArrayIndex(&index)) {
5853    if (index < n) {
5854      return frame->GetParameter(index);
5855    } else {
5856      return isolate->initial_object_prototype()->GetElement(index);
5857    }
5858  }
5859
5860  // Handle special arguments properties.
5861  if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
5862  if (key->Equals(isolate->heap()->callee_string())) {
5863    JSFunction* function = frame->function();
5864    if (!function->shared()->is_classic_mode()) {
5865      return isolate->Throw(*isolate->factory()->NewTypeError(
5866          "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5867    }
5868    return function;
5869  }
5870
5871  // Lookup in the initial Object.prototype object.
5872  return isolate->initial_object_prototype()->GetProperty(*key);
5873}
5874
5875
5876RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5877  SealHandleScope shs(isolate);
5878  ASSERT(args.length() == 1);
5879  Object* object = args[0];
5880  return (object->IsJSObject() && !object->IsGlobalObject())
5881      ? JSObject::cast(object)->TransformToFastProperties(0)
5882      : object;
5883}
5884
5885
5886RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5887  SealHandleScope shs(isolate);
5888  ASSERT(args.length() == 1);
5889
5890  return isolate->heap()->ToBoolean(args[0]->BooleanValue());
5891}
5892
5893
5894// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5895// Possible optimizations: put the type string into the oddballs.
5896RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5897  SealHandleScope shs(isolate);
5898
5899  Object* obj = args[0];
5900  if (obj->IsNumber()) return isolate->heap()->number_string();
5901  HeapObject* heap_obj = HeapObject::cast(obj);
5902
5903  // typeof an undetectable object is 'undefined'
5904  if (heap_obj->map()->is_undetectable()) {
5905    return isolate->heap()->undefined_string();
5906  }
5907
5908  InstanceType instance_type = heap_obj->map()->instance_type();
5909  if (instance_type < FIRST_NONSTRING_TYPE) {
5910    return isolate->heap()->string_string();
5911  }
5912
5913  switch (instance_type) {
5914    case ODDBALL_TYPE:
5915      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5916        return isolate->heap()->boolean_string();
5917      }
5918      if (heap_obj->IsNull()) {
5919        return FLAG_harmony_typeof
5920            ? isolate->heap()->null_string()
5921            : isolate->heap()->object_string();
5922      }
5923      ASSERT(heap_obj->IsUndefined());
5924      return isolate->heap()->undefined_string();
5925    case SYMBOL_TYPE:
5926      return isolate->heap()->symbol_string();
5927    case JS_FUNCTION_TYPE:
5928    case JS_FUNCTION_PROXY_TYPE:
5929      return isolate->heap()->function_string();
5930    default:
5931      // For any kind of object not handled above, the spec rule for
5932      // host objects gives that it is okay to return "object"
5933      return isolate->heap()->object_string();
5934  }
5935}
5936
5937
5938static bool AreDigits(const uint8_t*s, int from, int to) {
5939  for (int i = from; i < to; i++) {
5940    if (s[i] < '0' || s[i] > '9') return false;
5941  }
5942
5943  return true;
5944}
5945
5946
5947static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
5948  ASSERT(to - from < 10);  // Overflow is not possible.
5949  ASSERT(from < to);
5950  int d = s[from] - '0';
5951
5952  for (int i = from + 1; i < to; i++) {
5953    d = 10 * d + (s[i] - '0');
5954  }
5955
5956  return d;
5957}
5958
5959
5960RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5961  SealHandleScope shs(isolate);
5962  ASSERT(args.length() == 1);
5963  CONVERT_ARG_CHECKED(String, subject, 0);
5964  subject->TryFlatten();
5965
5966  // Fast case: short integer or some sorts of junk values.
5967  int len = subject->length();
5968  if (subject->IsSeqOneByteString()) {
5969    if (len == 0) return Smi::FromInt(0);
5970
5971    uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
5972    bool minus = (data[0] == '-');
5973    int start_pos = (minus ? 1 : 0);
5974
5975    if (start_pos == len) {
5976      return isolate->heap()->nan_value();
5977    } else if (data[start_pos] > '9') {
5978      // Fast check for a junk value. A valid string may start from a
5979      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5980      // the 'I' character ('Infinity'). All of that have codes not greater than
5981      // '9' except 'I' and &nbsp;.
5982      if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
5983        return isolate->heap()->nan_value();
5984      }
5985    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5986      // The maximal/minimal smi has 10 digits. If the string has less digits we
5987      // know it will fit into the smi-data type.
5988      int d = ParseDecimalInteger(data, start_pos, len);
5989      if (minus) {
5990        if (d == 0) return isolate->heap()->minus_zero_value();
5991        d = -d;
5992      } else if (!subject->HasHashCode() &&
5993                 len <= String::kMaxArrayIndexSize &&
5994                 (len == 1 || data[0] != '0')) {
5995        // String hash is not calculated yet but all the data are present.
5996        // Update the hash field to speed up sequential convertions.
5997        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5998#ifdef DEBUG
5999        subject->Hash();  // Force hash calculation.
6000        ASSERT_EQ(static_cast<int>(subject->hash_field()),
6001                  static_cast<int>(hash));
6002#endif
6003        subject->set_hash_field(hash);
6004      }
6005      return Smi::FromInt(d);
6006    }
6007  }
6008
6009  // Slower case.
6010  int flags = ALLOW_HEX;
6011  if (FLAG_harmony_numeric_literals) {
6012    // The current spec draft has not updated "ToNumber Applied to the String
6013    // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6014    flags |= ALLOW_OCTAL | ALLOW_BINARY;
6015  }
6016  return isolate->heap()->NumberFromDouble(
6017      StringToDouble(isolate->unicode_cache(), subject, flags));
6018}
6019
6020
6021RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6022  SealHandleScope shs(isolate);
6023  CONVERT_SMI_ARG_CHECKED(length, 0);
6024  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6025  if (length == 0) return isolate->heap()->empty_string();
6026  if (is_one_byte) {
6027    return isolate->heap()->AllocateRawOneByteString(length);
6028  } else {
6029    return isolate->heap()->AllocateRawTwoByteString(length);
6030  }
6031}
6032
6033
6034RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6035  HandleScope scope(isolate);
6036  CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6037  CONVERT_SMI_ARG_CHECKED(new_length, 1);
6038  return *SeqString::Truncate(string, new_length);
6039}
6040
6041
6042RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6043  HandleScope scope(isolate);
6044  ASSERT(args.length() == 1);
6045  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6046  Handle<String> string = FlattenGetString(source);
6047  ASSERT(string->IsFlat());
6048  Handle<String> result = string->IsOneByteRepresentationUnderneath()
6049      ? URIEscape::Escape<uint8_t>(isolate, source)
6050      : URIEscape::Escape<uc16>(isolate, source);
6051  if (result.is_null()) return Failure::OutOfMemoryException(0x12);
6052  return *result;
6053}
6054
6055
6056RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6057  HandleScope scope(isolate);
6058  ASSERT(args.length() == 1);
6059  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6060  Handle<String> string = FlattenGetString(source);
6061  ASSERT(string->IsFlat());
6062  return string->IsOneByteRepresentationUnderneath()
6063      ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6064      : *URIUnescape::Unescape<uc16>(isolate, source);
6065}
6066
6067
6068RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6069  HandleScope scope(isolate);
6070  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6071  ASSERT(args.length() == 1);
6072  return BasicJsonStringifier::StringifyString(isolate, string);
6073}
6074
6075
6076RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6077  HandleScope scope(isolate);
6078  ASSERT(args.length() == 1);
6079  BasicJsonStringifier stringifier(isolate);
6080  return stringifier.Stringify(Handle<Object>(args[0], isolate));
6081}
6082
6083
6084RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6085  SealHandleScope shs(isolate);
6086
6087  CONVERT_ARG_CHECKED(String, s, 0);
6088  CONVERT_SMI_ARG_CHECKED(radix, 1);
6089
6090  s->TryFlatten();
6091
6092  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6093  double value = StringToInt(isolate->unicode_cache(), s, radix);
6094  return isolate->heap()->NumberFromDouble(value);
6095}
6096
6097
6098RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6099  SealHandleScope shs(isolate);
6100  CONVERT_ARG_CHECKED(String, str, 0);
6101
6102  // ECMA-262 section 15.1.2.3, empty string is NaN
6103  double value = StringToDouble(isolate->unicode_cache(),
6104                                str, ALLOW_TRAILING_JUNK, OS::nan_value());
6105
6106  // Create a number object from the value.
6107  return isolate->heap()->NumberFromDouble(value);
6108}
6109
6110
6111template <class Converter>
6112MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6113    Isolate* isolate,
6114    String* s,
6115    int length,
6116    int input_string_length,
6117    unibrow::Mapping<Converter, 128>* mapping) {
6118  // We try this twice, once with the assumption that the result is no longer
6119  // than the input and, if that assumption breaks, again with the exact
6120  // length.  This may not be pretty, but it is nicer than what was here before
6121  // and I hereby claim my vaffel-is.
6122  //
6123  // Allocate the resulting string.
6124  //
6125  // NOTE: This assumes that the upper/lower case of an ASCII
6126  // character is also ASCII.  This is currently the case, but it
6127  // might break in the future if we implement more context and locale
6128  // dependent upper/lower conversions.
6129  Object* o;
6130  { MaybeObject* maybe_o = s->IsOneByteRepresentation()
6131        ? isolate->heap()->AllocateRawOneByteString(length)
6132        : isolate->heap()->AllocateRawTwoByteString(length);
6133    if (!maybe_o->ToObject(&o)) return maybe_o;
6134  }
6135  String* result = String::cast(o);
6136  bool has_changed_character = false;
6137
6138  // Convert all characters to upper case, assuming that they will fit
6139  // in the buffer
6140  Access<ConsStringIteratorOp> op(
6141      isolate->runtime_state()->string_iterator());
6142  StringCharacterStream stream(s, op.value());
6143  unibrow::uchar chars[Converter::kMaxWidth];
6144  // We can assume that the string is not empty
6145  uc32 current = stream.GetNext();
6146  for (int i = 0; i < length;) {
6147    bool has_next = stream.HasMore();
6148    uc32 next = has_next ? stream.GetNext() : 0;
6149    int char_length = mapping->get(current, next, chars);
6150    if (char_length == 0) {
6151      // The case conversion of this character is the character itself.
6152      result->Set(i, current);
6153      i++;
6154    } else if (char_length == 1) {
6155      // Common case: converting the letter resulted in one character.
6156      ASSERT(static_cast<uc32>(chars[0]) != current);
6157      result->Set(i, chars[0]);
6158      has_changed_character = true;
6159      i++;
6160    } else if (length == input_string_length) {
6161      // We've assumed that the result would be as long as the
6162      // input but here is a character that converts to several
6163      // characters.  No matter, we calculate the exact length
6164      // of the result and try the whole thing again.
6165      //
6166      // Note that this leaves room for optimization.  We could just
6167      // memcpy what we already have to the result string.  Also,
6168      // the result string is the last object allocated we could
6169      // "realloc" it and probably, in the vast majority of cases,
6170      // extend the existing string to be able to hold the full
6171      // result.
6172      int next_length = 0;
6173      if (has_next) {
6174        next_length = mapping->get(next, 0, chars);
6175        if (next_length == 0) next_length = 1;
6176      }
6177      int current_length = i + char_length + next_length;
6178      while (stream.HasMore()) {
6179        current = stream.GetNext();
6180        // NOTE: we use 0 as the next character here because, while
6181        // the next character may affect what a character converts to,
6182        // it does not in any case affect the length of what it convert
6183        // to.
6184        int char_length = mapping->get(current, 0, chars);
6185        if (char_length == 0) char_length = 1;
6186        current_length += char_length;
6187        if (current_length > Smi::kMaxValue) {
6188          isolate->context()->mark_out_of_memory();
6189          return Failure::OutOfMemoryException(0x13);
6190        }
6191      }
6192      // Try again with the real length.
6193      return Smi::FromInt(current_length);
6194    } else {
6195      for (int j = 0; j < char_length; j++) {
6196        result->Set(i, chars[j]);
6197        i++;
6198      }
6199      has_changed_character = true;
6200    }
6201    current = next;
6202  }
6203  if (has_changed_character) {
6204    return result;
6205  } else {
6206    // If we didn't actually change anything in doing the conversion
6207    // we simple return the result and let the converted string
6208    // become garbage; there is no reason to keep two identical strings
6209    // alive.
6210    return s;
6211  }
6212}
6213
6214
6215namespace {
6216
6217static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6218static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6219
6220// Given a word and two range boundaries returns a word with high bit
6221// set in every byte iff the corresponding input byte was strictly in
6222// the range (m, n). All the other bits in the result are cleared.
6223// This function is only useful when it can be inlined and the
6224// boundaries are statically known.
6225// Requires: all bytes in the input word and the boundaries must be
6226// ASCII (less than 0x7F).
6227static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6228  // Use strict inequalities since in edge cases the function could be
6229  // further simplified.
6230  ASSERT(0 < m && m < n);
6231  // Has high bit set in every w byte less than n.
6232  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6233  // Has high bit set in every w byte greater than m.
6234  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6235  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6236}
6237
6238
6239enum AsciiCaseConversion {
6240  ASCII_TO_LOWER,
6241  ASCII_TO_UPPER
6242};
6243
6244
6245template <AsciiCaseConversion dir>
6246struct FastAsciiConverter {
6247  static bool Convert(char* dst, char* src, int length, bool* changed_out) {
6248#ifdef DEBUG
6249    char* saved_dst = dst;
6250    char* saved_src = src;
6251#endif
6252    // We rely on the distance between upper and lower case letters
6253    // being a known power of 2.
6254    ASSERT('a' - 'A' == (1 << 5));
6255    // Boundaries for the range of input characters than require conversion.
6256    const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6257    const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6258    bool changed = false;
6259    uintptr_t or_acc = 0;
6260    char* const limit = src + length;
6261#ifdef V8_HOST_CAN_READ_UNALIGNED
6262    // Process the prefix of the input that requires no conversion one
6263    // (machine) word at a time.
6264    while (src <= limit - sizeof(uintptr_t)) {
6265      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6266      or_acc |= w;
6267      if (AsciiRangeMask(w, lo, hi) != 0) {
6268        changed = true;
6269        break;
6270      }
6271      *reinterpret_cast<uintptr_t*>(dst) = w;
6272      src += sizeof(uintptr_t);
6273      dst += sizeof(uintptr_t);
6274    }
6275    // Process the remainder of the input performing conversion when
6276    // required one word at a time.
6277    while (src <= limit - sizeof(uintptr_t)) {
6278      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6279      or_acc |= w;
6280      uintptr_t m = AsciiRangeMask(w, lo, hi);
6281      // The mask has high (7th) bit set in every byte that needs
6282      // conversion and we know that the distance between cases is
6283      // 1 << 5.
6284      *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6285      src += sizeof(uintptr_t);
6286      dst += sizeof(uintptr_t);
6287    }
6288#endif
6289    // Process the last few bytes of the input (or the whole input if
6290    // unaligned access is not supported).
6291    while (src < limit) {
6292      char c = *src;
6293      or_acc |= c;
6294      if (lo < c && c < hi) {
6295        c ^= (1 << 5);
6296        changed = true;
6297      }
6298      *dst = c;
6299      ++src;
6300      ++dst;
6301    }
6302    if ((or_acc & kAsciiMask) != 0) {
6303      return false;
6304    }
6305#ifdef DEBUG
6306    CheckConvert(saved_dst, saved_src, length, changed);
6307#endif
6308    *changed_out = changed;
6309    return true;
6310  }
6311
6312#ifdef DEBUG
6313  static void CheckConvert(char* dst, char* src, int length, bool changed) {
6314    bool expected_changed = false;
6315    for (int i = 0; i < length; i++) {
6316      if (dst[i] == src[i]) continue;
6317      expected_changed = true;
6318      if (dir == ASCII_TO_LOWER) {
6319        ASSERT('A' <= src[i] && src[i] <= 'Z');
6320        ASSERT(dst[i] == src[i] + ('a' - 'A'));
6321      } else {
6322        ASSERT(dir == ASCII_TO_UPPER);
6323        ASSERT('a' <= src[i] && src[i] <= 'z');
6324        ASSERT(dst[i] == src[i] - ('a' - 'A'));
6325      }
6326    }
6327    ASSERT(expected_changed == changed);
6328  }
6329#endif
6330};
6331
6332
6333struct ToLowerTraits {
6334  typedef unibrow::ToLowercase UnibrowConverter;
6335
6336  typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6337};
6338
6339
6340struct ToUpperTraits {
6341  typedef unibrow::ToUppercase UnibrowConverter;
6342
6343  typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6344};
6345
6346}  // namespace
6347
6348
6349template <typename ConvertTraits>
6350MUST_USE_RESULT static MaybeObject* ConvertCase(
6351    Arguments args,
6352    Isolate* isolate,
6353    unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6354  SealHandleScope shs(isolate);
6355  CONVERT_ARG_CHECKED(String, s, 0);
6356  s = s->TryFlattenGetString();
6357
6358  const int length = s->length();
6359  // Assume that the string is not empty; we need this assumption later
6360  if (length == 0) return s;
6361
6362  // Simpler handling of ASCII strings.
6363  //
6364  // NOTE: This assumes that the upper/lower case of an ASCII
6365  // character is also ASCII.  This is currently the case, but it
6366  // might break in the future if we implement more context and locale
6367  // dependent upper/lower conversions.
6368  if (s->IsSeqOneByteString()) {
6369    Object* o;
6370    { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
6371      if (!maybe_o->ToObject(&o)) return maybe_o;
6372    }
6373    SeqOneByteString* result = SeqOneByteString::cast(o);
6374    bool has_changed_character;
6375    bool is_ascii = ConvertTraits::AsciiConverter::Convert(
6376        reinterpret_cast<char*>(result->GetChars()),
6377        reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
6378        length,
6379        &has_changed_character);
6380    // If not ASCII, we discard the result and take the 2 byte path.
6381    if (is_ascii) {
6382      return has_changed_character ? result : s;
6383    }
6384  }
6385
6386  Object* answer;
6387  { MaybeObject* maybe_answer =
6388        ConvertCaseHelper(isolate, s, length, length, mapping);
6389    if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6390  }
6391  if (answer->IsSmi()) {
6392    // Retry with correct length.
6393    { MaybeObject* maybe_answer =
6394          ConvertCaseHelper(isolate,
6395                            s, Smi::cast(answer)->value(), length, mapping);
6396      if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6397    }
6398  }
6399  return answer;
6400}
6401
6402
6403RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6404  return ConvertCase<ToLowerTraits>(
6405      args, isolate, isolate->runtime_state()->to_lower_mapping());
6406}
6407
6408
6409RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6410  return ConvertCase<ToUpperTraits>(
6411      args, isolate, isolate->runtime_state()->to_upper_mapping());
6412}
6413
6414
6415static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6416  return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6417}
6418
6419
6420RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6421  SealHandleScope shs(isolate);
6422  ASSERT(args.length() == 3);
6423
6424  CONVERT_ARG_CHECKED(String, s, 0);
6425  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6426  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6427
6428  s->TryFlatten();
6429  int length = s->length();
6430
6431  int left = 0;
6432  if (trimLeft) {
6433    while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6434      left++;
6435    }
6436  }
6437
6438  int right = length;
6439  if (trimRight) {
6440    while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6441      right--;
6442    }
6443  }
6444  return s->SubString(left, right);
6445}
6446
6447
6448RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6449  HandleScope handle_scope(isolate);
6450  ASSERT(args.length() == 3);
6451  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6452  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6453  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6454
6455  int subject_length = subject->length();
6456  int pattern_length = pattern->length();
6457  RUNTIME_ASSERT(pattern_length > 0);
6458
6459  if (limit == 0xffffffffu) {
6460    Handle<Object> cached_answer(
6461        RegExpResultsCache::Lookup(isolate->heap(),
6462                                   *subject,
6463                                   *pattern,
6464                                   RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6465        isolate);
6466    if (*cached_answer != Smi::FromInt(0)) {
6467      // The cache FixedArray is a COW-array and can therefore be reused.
6468      Handle<JSArray> result =
6469          isolate->factory()->NewJSArrayWithElements(
6470              Handle<FixedArray>::cast(cached_answer));
6471      return *result;
6472    }
6473  }
6474
6475  // The limit can be very large (0xffffffffu), but since the pattern
6476  // isn't empty, we can never create more parts than ~half the length
6477  // of the subject.
6478
6479  if (!subject->IsFlat()) FlattenString(subject);
6480
6481  static const int kMaxInitialListCapacity = 16;
6482
6483  ZoneScope zone_scope(isolate->runtime_zone());
6484
6485  // Find (up to limit) indices of separator and end-of-string in subject
6486  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6487  ZoneList<int> indices(initial_capacity, zone_scope.zone());
6488  if (!pattern->IsFlat()) FlattenString(pattern);
6489
6490  FindStringIndicesDispatch(isolate, *subject, *pattern,
6491                            &indices, limit, zone_scope.zone());
6492
6493  if (static_cast<uint32_t>(indices.length()) < limit) {
6494    indices.Add(subject_length, zone_scope.zone());
6495  }
6496
6497  // The list indices now contains the end of each part to create.
6498
6499  // Create JSArray of substrings separated by separator.
6500  int part_count = indices.length();
6501
6502  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6503  MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6504  if (maybe_result->IsFailure()) return maybe_result;
6505  result->set_length(Smi::FromInt(part_count));
6506
6507  ASSERT(result->HasFastObjectElements());
6508
6509  if (part_count == 1 && indices.at(0) == subject_length) {
6510    FixedArray::cast(result->elements())->set(0, *subject);
6511    return *result;
6512  }
6513
6514  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6515  int part_start = 0;
6516  for (int i = 0; i < part_count; i++) {
6517    HandleScope local_loop_handle(isolate);
6518    int part_end = indices.at(i);
6519    Handle<String> substring =
6520        isolate->factory()->NewProperSubString(subject, part_start, part_end);
6521    elements->set(i, *substring);
6522    part_start = part_end + pattern_length;
6523  }
6524
6525  if (limit == 0xffffffffu) {
6526    if (result->HasFastObjectElements()) {
6527      RegExpResultsCache::Enter(isolate->heap(),
6528                                *subject,
6529                                *pattern,
6530                                *elements,
6531                                RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6532    }
6533  }
6534
6535  return *result;
6536}
6537
6538
6539// Copies ASCII characters to the given fixed array looking up
6540// one-char strings in the cache. Gives up on the first char that is
6541// not in the cache and fills the remainder with smi zeros. Returns
6542// the length of the successfully copied prefix.
6543static int CopyCachedAsciiCharsToArray(Heap* heap,
6544                                       const uint8_t* chars,
6545                                       FixedArray* elements,
6546                                       int length) {
6547  DisallowHeapAllocation no_gc;
6548  FixedArray* ascii_cache = heap->single_character_string_cache();
6549  Object* undefined = heap->undefined_value();
6550  int i;
6551  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6552  for (i = 0; i < length; ++i) {
6553    Object* value = ascii_cache->get(chars[i]);
6554    if (value == undefined) break;
6555    elements->set(i, value, mode);
6556  }
6557  if (i < length) {
6558    ASSERT(Smi::FromInt(0) == 0);
6559    memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6560  }
6561#ifdef DEBUG
6562  for (int j = 0; j < length; ++j) {
6563    Object* element = elements->get(j);
6564    ASSERT(element == Smi::FromInt(0) ||
6565           (element->IsString() && String::cast(element)->LooksValid()));
6566  }
6567#endif
6568  return i;
6569}
6570
6571
6572// Converts a String to JSArray.
6573// For example, "foo" => ["f", "o", "o"].
6574RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6575  HandleScope scope(isolate);
6576  ASSERT(args.length() == 2);
6577  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6578  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6579
6580  s = FlattenGetString(s);
6581  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6582
6583  Handle<FixedArray> elements;
6584  int position = 0;
6585  if (s->IsFlat() && s->IsOneByteRepresentation()) {
6586    // Try using cached chars where possible.
6587    Object* obj;
6588    { MaybeObject* maybe_obj =
6589          isolate->heap()->AllocateUninitializedFixedArray(length);
6590      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6591    }
6592    elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6593    DisallowHeapAllocation no_gc;
6594    String::FlatContent content = s->GetFlatContent();
6595    if (content.IsAscii()) {
6596      Vector<const uint8_t> chars = content.ToOneByteVector();
6597      // Note, this will initialize all elements (not only the prefix)
6598      // to prevent GC from seeing partially initialized array.
6599      position = CopyCachedAsciiCharsToArray(isolate->heap(),
6600                                             chars.start(),
6601                                             *elements,
6602                                             length);
6603    } else {
6604      MemsetPointer(elements->data_start(),
6605                    isolate->heap()->undefined_value(),
6606                    length);
6607    }
6608  } else {
6609    elements = isolate->factory()->NewFixedArray(length);
6610  }
6611  for (int i = position; i < length; ++i) {
6612    Handle<Object> str =
6613        LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6614    elements->set(i, *str);
6615  }
6616
6617#ifdef DEBUG
6618  for (int i = 0; i < length; ++i) {
6619    ASSERT(String::cast(elements->get(i))->length() == 1);
6620  }
6621#endif
6622
6623  return *isolate->factory()->NewJSArrayWithElements(elements);
6624}
6625
6626
6627RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6628  SealHandleScope shs(isolate);
6629  ASSERT(args.length() == 1);
6630  CONVERT_ARG_CHECKED(String, value, 0);
6631  return value->ToObject();
6632}
6633
6634
6635bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6636  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6637  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6638  return char_length == 0;
6639}
6640
6641
6642RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6643  SealHandleScope shs(isolate);
6644  ASSERT(args.length() == 1);
6645
6646  Object* number = args[0];
6647  RUNTIME_ASSERT(number->IsNumber());
6648
6649  return isolate->heap()->NumberToString(number);
6650}
6651
6652
6653RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6654  SealHandleScope shs(isolate);
6655  ASSERT(args.length() == 1);
6656
6657  Object* number = args[0];
6658  RUNTIME_ASSERT(number->IsNumber());
6659
6660  return isolate->heap()->NumberToString(
6661      number, false, isolate->heap()->GetPretenureMode());
6662}
6663
6664
6665RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6666  SealHandleScope shs(isolate);
6667  ASSERT(args.length() == 1);
6668
6669  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6670
6671  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6672  if (number > 0 && number <= Smi::kMaxValue) {
6673    return Smi::FromInt(static_cast<int>(number));
6674  }
6675  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6676}
6677
6678
6679// ES6 draft 9.1.11
6680RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
6681  SealHandleScope shs(isolate);
6682  ASSERT(args.length() == 1);
6683
6684  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6685
6686  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6687  if (number > 0 && number <= Smi::kMaxValue) {
6688    return Smi::FromInt(static_cast<int>(number));
6689  }
6690  if (number <= 0) {
6691    return Smi::FromInt(0);
6692  }
6693  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6694}
6695
6696
6697RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6698  SealHandleScope shs(isolate);
6699  ASSERT(args.length() == 1);
6700
6701  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6702
6703  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6704  if (number > 0 && number <= Smi::kMaxValue) {
6705    return Smi::FromInt(static_cast<int>(number));
6706  }
6707
6708  double double_value = DoubleToInteger(number);
6709  // Map both -0 and +0 to +0.
6710  if (double_value == 0) double_value = 0;
6711
6712  return isolate->heap()->NumberFromDouble(double_value);
6713}
6714
6715
6716RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6717  SealHandleScope shs(isolate);
6718  ASSERT(args.length() == 1);
6719
6720  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6721  return isolate->heap()->NumberFromUint32(number);
6722}
6723
6724
6725RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6726  SealHandleScope shs(isolate);
6727  ASSERT(args.length() == 1);
6728
6729  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6730
6731  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6732  if (number > 0 && number <= Smi::kMaxValue) {
6733    return Smi::FromInt(static_cast<int>(number));
6734  }
6735  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6736}
6737
6738
6739// Converts a Number to a Smi, if possible. Returns NaN if the number is not
6740// a small integer.
6741RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6742  SealHandleScope shs(isolate);
6743  ASSERT(args.length() == 1);
6744
6745  Object* obj = args[0];
6746  if (obj->IsSmi()) {
6747    return obj;
6748  }
6749  if (obj->IsHeapNumber()) {
6750    double value = HeapNumber::cast(obj)->value();
6751    int int_value = FastD2I(value);
6752    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6753      return Smi::FromInt(int_value);
6754    }
6755  }
6756  return isolate->heap()->nan_value();
6757}
6758
6759
6760RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6761  SealHandleScope shs(isolate);
6762  ASSERT(args.length() == 0);
6763  return isolate->heap()->AllocateHeapNumber(0);
6764}
6765
6766
6767RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6768  SealHandleScope shs(isolate);
6769  ASSERT(args.length() == 2);
6770
6771  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6772  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6773  return isolate->heap()->NumberFromDouble(x + y);
6774}
6775
6776
6777RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6778  SealHandleScope shs(isolate);
6779  ASSERT(args.length() == 2);
6780
6781  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6782  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6783  return isolate->heap()->NumberFromDouble(x - y);
6784}
6785
6786
6787RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6788  SealHandleScope shs(isolate);
6789  ASSERT(args.length() == 2);
6790
6791  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6792  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6793  return isolate->heap()->NumberFromDouble(x * y);
6794}
6795
6796
6797RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6798  SealHandleScope shs(isolate);
6799  ASSERT(args.length() == 1);
6800
6801  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6802  return isolate->heap()->NumberFromDouble(-x);
6803}
6804
6805
6806RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6807  SealHandleScope shs(isolate);
6808  ASSERT(args.length() == 0);
6809
6810  return isolate->heap()->NumberFromDouble(9876543210.0);
6811}
6812
6813
6814RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6815  SealHandleScope shs(isolate);
6816  ASSERT(args.length() == 2);
6817
6818  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6819  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6820  return isolate->heap()->NumberFromDouble(x / y);
6821}
6822
6823
6824RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6825  SealHandleScope shs(isolate);
6826  ASSERT(args.length() == 2);
6827
6828  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6829  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6830
6831  x = modulo(x, y);
6832  // NumberFromDouble may return a Smi instead of a Number object
6833  return isolate->heap()->NumberFromDouble(x);
6834}
6835
6836
6837RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
6838  SealHandleScope shs(isolate);
6839  ASSERT(args.length() == 2);
6840
6841  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6842  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6843  return isolate->heap()->NumberFromInt32(x * y);
6844}
6845
6846
6847RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6848  SealHandleScope shs(isolate);
6849  ASSERT(args.length() == 2);
6850  CONVERT_ARG_CHECKED(String, str1, 0);
6851  CONVERT_ARG_CHECKED(String, str2, 1);
6852  isolate->counters()->string_add_runtime()->Increment();
6853  return isolate->heap()->AllocateConsString(str1, str2);
6854}
6855
6856
6857template <typename sinkchar>
6858static inline void StringBuilderConcatHelper(String* special,
6859                                             sinkchar* sink,
6860                                             FixedArray* fixed_array,
6861                                             int array_length) {
6862  int position = 0;
6863  for (int i = 0; i < array_length; i++) {
6864    Object* element = fixed_array->get(i);
6865    if (element->IsSmi()) {
6866      // Smi encoding of position and length.
6867      int encoded_slice = Smi::cast(element)->value();
6868      int pos;
6869      int len;
6870      if (encoded_slice > 0) {
6871        // Position and length encoded in one smi.
6872        pos = StringBuilderSubstringPosition::decode(encoded_slice);
6873        len = StringBuilderSubstringLength::decode(encoded_slice);
6874      } else {
6875        // Position and length encoded in two smis.
6876        Object* obj = fixed_array->get(++i);
6877        ASSERT(obj->IsSmi());
6878        pos = Smi::cast(obj)->value();
6879        len = -encoded_slice;
6880      }
6881      String::WriteToFlat(special,
6882                          sink + position,
6883                          pos,
6884                          pos + len);
6885      position += len;
6886    } else {
6887      String* string = String::cast(element);
6888      int element_length = string->length();
6889      String::WriteToFlat(string, sink + position, 0, element_length);
6890      position += element_length;
6891    }
6892  }
6893}
6894
6895
6896RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6897  SealHandleScope shs(isolate);
6898  ASSERT(args.length() == 3);
6899  CONVERT_ARG_CHECKED(JSArray, array, 0);
6900  if (!args[1]->IsSmi()) {
6901    isolate->context()->mark_out_of_memory();
6902    return Failure::OutOfMemoryException(0x14);
6903  }
6904  int array_length = args.smi_at(1);
6905  CONVERT_ARG_CHECKED(String, special, 2);
6906
6907  // This assumption is used by the slice encoding in one or two smis.
6908  ASSERT(Smi::kMaxValue >= String::kMaxLength);
6909
6910  MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6911  if (maybe_result->IsFailure()) return maybe_result;
6912
6913  int special_length = special->length();
6914  if (!array->HasFastObjectElements()) {
6915    return isolate->Throw(isolate->heap()->illegal_argument_string());
6916  }
6917  FixedArray* fixed_array = FixedArray::cast(array->elements());
6918  if (fixed_array->length() < array_length) {
6919    array_length = fixed_array->length();
6920  }
6921
6922  if (array_length == 0) {
6923    return isolate->heap()->empty_string();
6924  } else if (array_length == 1) {
6925    Object* first = fixed_array->get(0);
6926    if (first->IsString()) return first;
6927  }
6928
6929  bool one_byte = special->HasOnlyOneByteChars();
6930  int position = 0;
6931  for (int i = 0; i < array_length; i++) {
6932    int increment = 0;
6933    Object* elt = fixed_array->get(i);
6934    if (elt->IsSmi()) {
6935      // Smi encoding of position and length.
6936      int smi_value = Smi::cast(elt)->value();
6937      int pos;
6938      int len;
6939      if (smi_value > 0) {
6940        // Position and length encoded in one smi.
6941        pos = StringBuilderSubstringPosition::decode(smi_value);
6942        len = StringBuilderSubstringLength::decode(smi_value);
6943      } else {
6944        // Position and length encoded in two smis.
6945        len = -smi_value;
6946        // Get the position and check that it is a positive smi.
6947        i++;
6948        if (i >= array_length) {
6949          return isolate->Throw(isolate->heap()->illegal_argument_string());
6950        }
6951        Object* next_smi = fixed_array->get(i);
6952        if (!next_smi->IsSmi()) {
6953          return isolate->Throw(isolate->heap()->illegal_argument_string());
6954        }
6955        pos = Smi::cast(next_smi)->value();
6956        if (pos < 0) {
6957          return isolate->Throw(isolate->heap()->illegal_argument_string());
6958        }
6959      }
6960      ASSERT(pos >= 0);
6961      ASSERT(len >= 0);
6962      if (pos > special_length || len > special_length - pos) {
6963        return isolate->Throw(isolate->heap()->illegal_argument_string());
6964      }
6965      increment = len;
6966    } else if (elt->IsString()) {
6967      String* element = String::cast(elt);
6968      int element_length = element->length();
6969      increment = element_length;
6970      if (one_byte && !element->HasOnlyOneByteChars()) {
6971        one_byte = false;
6972      }
6973    } else {
6974      ASSERT(!elt->IsTheHole());
6975      return isolate->Throw(isolate->heap()->illegal_argument_string());
6976    }
6977    if (increment > String::kMaxLength - position) {
6978      isolate->context()->mark_out_of_memory();
6979      return Failure::OutOfMemoryException(0x15);
6980    }
6981    position += increment;
6982  }
6983
6984  int length = position;
6985  Object* object;
6986
6987  if (one_byte) {
6988    { MaybeObject* maybe_object =
6989          isolate->heap()->AllocateRawOneByteString(length);
6990      if (!maybe_object->ToObject(&object)) return maybe_object;
6991    }
6992    SeqOneByteString* answer = SeqOneByteString::cast(object);
6993    StringBuilderConcatHelper(special,
6994                              answer->GetChars(),
6995                              fixed_array,
6996                              array_length);
6997    return answer;
6998  } else {
6999    { MaybeObject* maybe_object =
7000          isolate->heap()->AllocateRawTwoByteString(length);
7001      if (!maybe_object->ToObject(&object)) return maybe_object;
7002    }
7003    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7004    StringBuilderConcatHelper(special,
7005                              answer->GetChars(),
7006                              fixed_array,
7007                              array_length);
7008    return answer;
7009  }
7010}
7011
7012
7013RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7014  SealHandleScope shs(isolate);
7015  ASSERT(args.length() == 3);
7016  CONVERT_ARG_CHECKED(JSArray, array, 0);
7017  if (!args[1]->IsSmi()) {
7018    isolate->context()->mark_out_of_memory();
7019    return Failure::OutOfMemoryException(0x16);
7020  }
7021  int array_length = args.smi_at(1);
7022  CONVERT_ARG_CHECKED(String, separator, 2);
7023
7024  if (!array->HasFastObjectElements()) {
7025    return isolate->Throw(isolate->heap()->illegal_argument_string());
7026  }
7027  FixedArray* fixed_array = FixedArray::cast(array->elements());
7028  if (fixed_array->length() < array_length) {
7029    array_length = fixed_array->length();
7030  }
7031
7032  if (array_length == 0) {
7033    return isolate->heap()->empty_string();
7034  } else if (array_length == 1) {
7035    Object* first = fixed_array->get(0);
7036    if (first->IsString()) return first;
7037  }
7038
7039  int separator_length = separator->length();
7040  int max_nof_separators =
7041      (String::kMaxLength + separator_length - 1) / separator_length;
7042  if (max_nof_separators < (array_length - 1)) {
7043      isolate->context()->mark_out_of_memory();
7044      return Failure::OutOfMemoryException(0x17);
7045  }
7046  int length = (array_length - 1) * separator_length;
7047  for (int i = 0; i < array_length; i++) {
7048    Object* element_obj = fixed_array->get(i);
7049    if (!element_obj->IsString()) {
7050      // TODO(1161): handle this case.
7051      return isolate->Throw(isolate->heap()->illegal_argument_string());
7052    }
7053    String* element = String::cast(element_obj);
7054    int increment = element->length();
7055    if (increment > String::kMaxLength - length) {
7056      isolate->context()->mark_out_of_memory();
7057      return Failure::OutOfMemoryException(0x18);
7058    }
7059    length += increment;
7060  }
7061
7062  Object* object;
7063  { MaybeObject* maybe_object =
7064        isolate->heap()->AllocateRawTwoByteString(length);
7065    if (!maybe_object->ToObject(&object)) return maybe_object;
7066  }
7067  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7068
7069  uc16* sink = answer->GetChars();
7070#ifdef DEBUG
7071  uc16* end = sink + length;
7072#endif
7073
7074  String* first = String::cast(fixed_array->get(0));
7075  int first_length = first->length();
7076  String::WriteToFlat(first, sink, 0, first_length);
7077  sink += first_length;
7078
7079  for (int i = 1; i < array_length; i++) {
7080    ASSERT(sink + separator_length <= end);
7081    String::WriteToFlat(separator, sink, 0, separator_length);
7082    sink += separator_length;
7083
7084    String* element = String::cast(fixed_array->get(i));
7085    int element_length = element->length();
7086    ASSERT(sink + element_length <= end);
7087    String::WriteToFlat(element, sink, 0, element_length);
7088    sink += element_length;
7089  }
7090  ASSERT(sink == end);
7091
7092  // Use %_FastAsciiArrayJoin instead.
7093  ASSERT(!answer->IsOneByteRepresentation());
7094  return answer;
7095}
7096
7097template <typename Char>
7098static void JoinSparseArrayWithSeparator(FixedArray* elements,
7099                                         int elements_length,
7100                                         uint32_t array_length,
7101                                         String* separator,
7102                                         Vector<Char> buffer) {
7103  int previous_separator_position = 0;
7104  int separator_length = separator->length();
7105  int cursor = 0;
7106  for (int i = 0; i < elements_length; i += 2) {
7107    int position = NumberToInt32(elements->get(i));
7108    String* string = String::cast(elements->get(i + 1));
7109    int string_length = string->length();
7110    if (string->length() > 0) {
7111      while (previous_separator_position < position) {
7112        String::WriteToFlat<Char>(separator, &buffer[cursor],
7113                                  0, separator_length);
7114        cursor += separator_length;
7115        previous_separator_position++;
7116      }
7117      String::WriteToFlat<Char>(string, &buffer[cursor],
7118                                0, string_length);
7119      cursor += string->length();
7120    }
7121  }
7122  if (separator_length > 0) {
7123    // Array length must be representable as a signed 32-bit number,
7124    // otherwise the total string length would have been too large.
7125    ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7126    int last_array_index = static_cast<int>(array_length - 1);
7127    while (previous_separator_position < last_array_index) {
7128      String::WriteToFlat<Char>(separator, &buffer[cursor],
7129                                0, separator_length);
7130      cursor += separator_length;
7131      previous_separator_position++;
7132    }
7133  }
7134  ASSERT(cursor <= buffer.length());
7135}
7136
7137
7138RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7139  SealHandleScope shs(isolate);
7140  ASSERT(args.length() == 3);
7141  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7142  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7143  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7144  CONVERT_ARG_CHECKED(String, separator, 2);
7145  // elements_array is fast-mode JSarray of alternating positions
7146  // (increasing order) and strings.
7147  // array_length is length of original array (used to add separators);
7148  // separator is string to put between elements. Assumed to be non-empty.
7149
7150  // Find total length of join result.
7151  int string_length = 0;
7152  bool is_ascii = separator->IsOneByteRepresentation();
7153  int max_string_length;
7154  if (is_ascii) {
7155    max_string_length = SeqOneByteString::kMaxLength;
7156  } else {
7157    max_string_length = SeqTwoByteString::kMaxLength;
7158  }
7159  bool overflow = false;
7160  CONVERT_NUMBER_CHECKED(int, elements_length,
7161                         Int32, elements_array->length());
7162  RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7163  FixedArray* elements = FixedArray::cast(elements_array->elements());
7164  for (int i = 0; i < elements_length; i += 2) {
7165    RUNTIME_ASSERT(elements->get(i)->IsNumber());
7166    RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7167    String* string = String::cast(elements->get(i + 1));
7168    int length = string->length();
7169    if (is_ascii && !string->IsOneByteRepresentation()) {
7170      is_ascii = false;
7171      max_string_length = SeqTwoByteString::kMaxLength;
7172    }
7173    if (length > max_string_length ||
7174        max_string_length - length < string_length) {
7175      overflow = true;
7176      break;
7177    }
7178    string_length += length;
7179  }
7180  int separator_length = separator->length();
7181  if (!overflow && separator_length > 0) {
7182    if (array_length <= 0x7fffffffu) {
7183      int separator_count = static_cast<int>(array_length) - 1;
7184      int remaining_length = max_string_length - string_length;
7185      if ((remaining_length / separator_length) >= separator_count) {
7186        string_length += separator_length * (array_length - 1);
7187      } else {
7188        // Not room for the separators within the maximal string length.
7189        overflow = true;
7190      }
7191    } else {
7192      // Nonempty separator and at least 2^31-1 separators necessary
7193      // means that the string is too large to create.
7194      STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7195      overflow = true;
7196    }
7197  }
7198  if (overflow) {
7199    // Throw OutOfMemory exception for creating too large a string.
7200    V8::FatalProcessOutOfMemory("Array join result too large.");
7201  }
7202
7203  if (is_ascii) {
7204    MaybeObject* result_allocation =
7205        isolate->heap()->AllocateRawOneByteString(string_length);
7206    if (result_allocation->IsFailure()) return result_allocation;
7207    SeqOneByteString* result_string =
7208        SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7209    JoinSparseArrayWithSeparator<uint8_t>(elements,
7210                                          elements_length,
7211                                          array_length,
7212                                          separator,
7213                                          Vector<uint8_t>(
7214                                              result_string->GetChars(),
7215                                              string_length));
7216    return result_string;
7217  } else {
7218    MaybeObject* result_allocation =
7219        isolate->heap()->AllocateRawTwoByteString(string_length);
7220    if (result_allocation->IsFailure()) return result_allocation;
7221    SeqTwoByteString* result_string =
7222        SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7223    JoinSparseArrayWithSeparator<uc16>(elements,
7224                                       elements_length,
7225                                       array_length,
7226                                       separator,
7227                                       Vector<uc16>(result_string->GetChars(),
7228                                                    string_length));
7229    return result_string;
7230  }
7231}
7232
7233
7234RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7235  SealHandleScope shs(isolate);
7236  ASSERT(args.length() == 2);
7237
7238  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7239  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7240  return isolate->heap()->NumberFromInt32(x | y);
7241}
7242
7243
7244RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7245  SealHandleScope shs(isolate);
7246  ASSERT(args.length() == 2);
7247
7248  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7249  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7250  return isolate->heap()->NumberFromInt32(x & y);
7251}
7252
7253
7254RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7255  SealHandleScope shs(isolate);
7256  ASSERT(args.length() == 2);
7257
7258  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7259  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7260  return isolate->heap()->NumberFromInt32(x ^ y);
7261}
7262
7263
7264RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7265  SealHandleScope shs(isolate);
7266  ASSERT(args.length() == 2);
7267
7268  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7269  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7270  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7271}
7272
7273
7274RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7275  SealHandleScope shs(isolate);
7276  ASSERT(args.length() == 2);
7277
7278  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7279  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7280  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7281}
7282
7283
7284RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7285  SealHandleScope shs(isolate);
7286  ASSERT(args.length() == 2);
7287
7288  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7289  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7290  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7291}
7292
7293
7294RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7295  SealHandleScope shs(isolate);
7296  ASSERT(args.length() == 2);
7297
7298  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7299  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7300  if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7301  if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7302  if (x == y) return Smi::FromInt(EQUAL);
7303  Object* result;
7304  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7305    result = Smi::FromInt(EQUAL);
7306  } else {
7307    result = Smi::FromInt(NOT_EQUAL);
7308  }
7309  return result;
7310}
7311
7312
7313RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7314  SealHandleScope shs(isolate);
7315  ASSERT(args.length() == 2);
7316
7317  CONVERT_ARG_CHECKED(String, x, 0);
7318  CONVERT_ARG_CHECKED(String, y, 1);
7319
7320  bool not_equal = !x->Equals(y);
7321  // This is slightly convoluted because the value that signifies
7322  // equality is 0 and inequality is 1 so we have to negate the result
7323  // from String::Equals.
7324  ASSERT(not_equal == 0 || not_equal == 1);
7325  STATIC_CHECK(EQUAL == 0);
7326  STATIC_CHECK(NOT_EQUAL == 1);
7327  return Smi::FromInt(not_equal);
7328}
7329
7330
7331RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7332  SealHandleScope shs(isolate);
7333  ASSERT(args.length() == 3);
7334
7335  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7336  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7337  if (std::isnan(x) || std::isnan(y)) return args[2];
7338  if (x == y) return Smi::FromInt(EQUAL);
7339  if (isless(x, y)) return Smi::FromInt(LESS);
7340  return Smi::FromInt(GREATER);
7341}
7342
7343
7344// Compare two Smis as if they were converted to strings and then
7345// compared lexicographically.
7346RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7347  SealHandleScope shs(isolate);
7348  ASSERT(args.length() == 2);
7349  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7350  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7351
7352  // If the integers are equal so are the string representations.
7353  if (x_value == y_value) return Smi::FromInt(EQUAL);
7354
7355  // If one of the integers is zero the normal integer order is the
7356  // same as the lexicographic order of the string representations.
7357  if (x_value == 0 || y_value == 0)
7358    return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7359
7360  // If only one of the integers is negative the negative number is
7361  // smallest because the char code of '-' is less than the char code
7362  // of any digit.  Otherwise, we make both values positive.
7363
7364  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7365  // architectures using 32-bit Smis.
7366  uint32_t x_scaled = x_value;
7367  uint32_t y_scaled = y_value;
7368  if (x_value < 0 || y_value < 0) {
7369    if (y_value >= 0) return Smi::FromInt(LESS);
7370    if (x_value >= 0) return Smi::FromInt(GREATER);
7371    x_scaled = -x_value;
7372    y_scaled = -y_value;
7373  }
7374
7375  static const uint32_t kPowersOf10[] = {
7376    1, 10, 100, 1000, 10*1000, 100*1000,
7377    1000*1000, 10*1000*1000, 100*1000*1000,
7378    1000*1000*1000
7379  };
7380
7381  // If the integers have the same number of decimal digits they can be
7382  // compared directly as the numeric order is the same as the
7383  // lexicographic order.  If one integer has fewer digits, it is scaled
7384  // by some power of 10 to have the same number of digits as the longer
7385  // integer.  If the scaled integers are equal it means the shorter
7386  // integer comes first in the lexicographic order.
7387
7388  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7389  int x_log2 = IntegerLog2(x_scaled);
7390  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7391  x_log10 -= x_scaled < kPowersOf10[x_log10];
7392
7393  int y_log2 = IntegerLog2(y_scaled);
7394  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7395  y_log10 -= y_scaled < kPowersOf10[y_log10];
7396
7397  int tie = EQUAL;
7398
7399  if (x_log10 < y_log10) {
7400    // X has fewer digits.  We would like to simply scale up X but that
7401    // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7402    // be scaled up to 9_000_000_000. So we scale up by the next
7403    // smallest power and scale down Y to drop one digit. It is OK to
7404    // drop one digit from the longer integer since the final digit is
7405    // past the length of the shorter integer.
7406    x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7407    y_scaled /= 10;
7408    tie = LESS;
7409  } else if (y_log10 < x_log10) {
7410    y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7411    x_scaled /= 10;
7412    tie = GREATER;
7413  }
7414
7415  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7416  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7417  return Smi::FromInt(tie);
7418}
7419
7420
7421static Object* StringCharacterStreamCompare(RuntimeState* state,
7422                                        String* x,
7423                                        String* y) {
7424  StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7425  StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7426  while (stream_x.HasMore() && stream_y.HasMore()) {
7427    int d = stream_x.GetNext() - stream_y.GetNext();
7428    if (d < 0) return Smi::FromInt(LESS);
7429    else if (d > 0) return Smi::FromInt(GREATER);
7430  }
7431
7432  // x is (non-trivial) prefix of y:
7433  if (stream_y.HasMore()) return Smi::FromInt(LESS);
7434  // y is prefix of x:
7435  return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7436}
7437
7438
7439static Object* FlatStringCompare(String* x, String* y) {
7440  ASSERT(x->IsFlat());
7441  ASSERT(y->IsFlat());
7442  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7443  int prefix_length = x->length();
7444  if (y->length() < prefix_length) {
7445    prefix_length = y->length();
7446    equal_prefix_result = Smi::FromInt(GREATER);
7447  } else if (y->length() > prefix_length) {
7448    equal_prefix_result = Smi::FromInt(LESS);
7449  }
7450  int r;
7451  DisallowHeapAllocation no_gc;
7452  String::FlatContent x_content = x->GetFlatContent();
7453  String::FlatContent y_content = y->GetFlatContent();
7454  if (x_content.IsAscii()) {
7455    Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7456    if (y_content.IsAscii()) {
7457      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7458      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7459    } else {
7460      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7461      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7462    }
7463  } else {
7464    Vector<const uc16> x_chars = x_content.ToUC16Vector();
7465    if (y_content.IsAscii()) {
7466      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7467      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7468    } else {
7469      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7470      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7471    }
7472  }
7473  Object* result;
7474  if (r == 0) {
7475    result = equal_prefix_result;
7476  } else {
7477    result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7478  }
7479  ASSERT(result ==
7480      StringCharacterStreamCompare(Isolate::Current()->runtime_state(), x, y));
7481  return result;
7482}
7483
7484
7485RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7486  SealHandleScope shs(isolate);
7487  ASSERT(args.length() == 2);
7488
7489  CONVERT_ARG_CHECKED(String, x, 0);
7490  CONVERT_ARG_CHECKED(String, y, 1);
7491
7492  isolate->counters()->string_compare_runtime()->Increment();
7493
7494  // A few fast case tests before we flatten.
7495  if (x == y) return Smi::FromInt(EQUAL);
7496  if (y->length() == 0) {
7497    if (x->length() == 0) return Smi::FromInt(EQUAL);
7498    return Smi::FromInt(GREATER);
7499  } else if (x->length() == 0) {
7500    return Smi::FromInt(LESS);
7501  }
7502
7503  int d = x->Get(0) - y->Get(0);
7504  if (d < 0) return Smi::FromInt(LESS);
7505  else if (d > 0) return Smi::FromInt(GREATER);
7506
7507  Object* obj;
7508  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7509    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7510  }
7511  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7512    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7513  }
7514
7515  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7516      : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7517}
7518
7519
7520RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7521  SealHandleScope shs(isolate);
7522  ASSERT(args.length() == 1);
7523  isolate->counters()->math_acos()->Increment();
7524
7525  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7526  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7527}
7528
7529
7530RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7531  SealHandleScope shs(isolate);
7532  ASSERT(args.length() == 1);
7533  isolate->counters()->math_asin()->Increment();
7534
7535  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7536  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7537}
7538
7539
7540RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7541  SealHandleScope shs(isolate);
7542  ASSERT(args.length() == 1);
7543  isolate->counters()->math_atan()->Increment();
7544
7545  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7546  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7547}
7548
7549
7550static const double kPiDividedBy4 = 0.78539816339744830962;
7551
7552
7553RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7554  SealHandleScope shs(isolate);
7555  ASSERT(args.length() == 2);
7556  isolate->counters()->math_atan2()->Increment();
7557
7558  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7559  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7560  double result;
7561  if (std::isinf(x) && std::isinf(y)) {
7562    // Make sure that the result in case of two infinite arguments
7563    // is a multiple of Pi / 4. The sign of the result is determined
7564    // by the first argument (x) and the sign of the second argument
7565    // determines the multiplier: one or three.
7566    int multiplier = (x < 0) ? -1 : 1;
7567    if (y < 0) multiplier *= 3;
7568    result = multiplier * kPiDividedBy4;
7569  } else {
7570    result = atan2(x, y);
7571  }
7572  return isolate->heap()->AllocateHeapNumber(result);
7573}
7574
7575
7576RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7577  SealHandleScope shs(isolate);
7578  ASSERT(args.length() == 1);
7579  isolate->counters()->math_ceil()->Increment();
7580
7581  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7582  return isolate->heap()->NumberFromDouble(ceiling(x));
7583}
7584
7585
7586RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7587  SealHandleScope shs(isolate);
7588  ASSERT(args.length() == 1);
7589  isolate->counters()->math_cos()->Increment();
7590
7591  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7592  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7593}
7594
7595
7596RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7597  SealHandleScope shs(isolate);
7598  ASSERT(args.length() == 1);
7599  isolate->counters()->math_exp()->Increment();
7600
7601  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7602  lazily_initialize_fast_exp();
7603  return isolate->heap()->NumberFromDouble(fast_exp(x));
7604}
7605
7606
7607RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7608  SealHandleScope shs(isolate);
7609  ASSERT(args.length() == 1);
7610  isolate->counters()->math_floor()->Increment();
7611
7612  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7613  return isolate->heap()->NumberFromDouble(floor(x));
7614}
7615
7616
7617RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7618  SealHandleScope shs(isolate);
7619  ASSERT(args.length() == 1);
7620  isolate->counters()->math_log()->Increment();
7621
7622  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7623  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7624}
7625
7626
7627// Slow version of Math.pow.  We check for fast paths for special cases.
7628// Used if SSE2/VFP3 is not available.
7629RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7630  SealHandleScope shs(isolate);
7631  ASSERT(args.length() == 2);
7632  isolate->counters()->math_pow()->Increment();
7633
7634  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7635
7636  // If the second argument is a smi, it is much faster to call the
7637  // custom powi() function than the generic pow().
7638  if (args[1]->IsSmi()) {
7639    int y = args.smi_at(1);
7640    return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7641  }
7642
7643  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7644  double result = power_helper(x, y);
7645  if (std::isnan(result)) return isolate->heap()->nan_value();
7646  return isolate->heap()->AllocateHeapNumber(result);
7647}
7648
7649
7650// Fast version of Math.pow if we know that y is not an integer and y is not
7651// -0.5 or 0.5.  Used as slow case from full codegen.
7652RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7653  SealHandleScope shs(isolate);
7654  ASSERT(args.length() == 2);
7655  isolate->counters()->math_pow()->Increment();
7656
7657  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7658  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7659  if (y == 0) {
7660    return Smi::FromInt(1);
7661  } else {
7662    double result = power_double_double(x, y);
7663    if (std::isnan(result)) return isolate->heap()->nan_value();
7664    return isolate->heap()->AllocateHeapNumber(result);
7665  }
7666}
7667
7668
7669RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7670  SealHandleScope shs(isolate);
7671  ASSERT(args.length() == 1);
7672  isolate->counters()->math_round()->Increment();
7673
7674  if (!args[0]->IsHeapNumber()) {
7675    // Must be smi. Return the argument unchanged for all the other types
7676    // to make fuzz-natives test happy.
7677    return args[0];
7678  }
7679
7680  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7681
7682  double value = number->value();
7683  int exponent = number->get_exponent();
7684  int sign = number->get_sign();
7685
7686  if (exponent < -1) {
7687    // Number in range ]-0.5..0.5[. These always round to +/-zero.
7688    if (sign) return isolate->heap()->minus_zero_value();
7689    return Smi::FromInt(0);
7690  }
7691
7692  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7693  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7694  // argument holds for 32-bit smis).
7695  if (!sign && exponent < kSmiValueSize - 2) {
7696    return Smi::FromInt(static_cast<int>(value + 0.5));
7697  }
7698
7699  // If the magnitude is big enough, there's no place for fraction part. If we
7700  // try to add 0.5 to this number, 1.0 will be added instead.
7701  if (exponent >= 52) {
7702    return number;
7703  }
7704
7705  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7706
7707  // Do not call NumberFromDouble() to avoid extra checks.
7708  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7709}
7710
7711
7712RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7713  SealHandleScope shs(isolate);
7714  ASSERT(args.length() == 1);
7715  isolate->counters()->math_sin()->Increment();
7716
7717  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7718  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7719}
7720
7721
7722RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7723  SealHandleScope shs(isolate);
7724  ASSERT(args.length() == 1);
7725  isolate->counters()->math_sqrt()->Increment();
7726
7727  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7728  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7729}
7730
7731
7732RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7733  SealHandleScope shs(isolate);
7734  ASSERT(args.length() == 1);
7735  isolate->counters()->math_tan()->Increment();
7736
7737  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7738  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7739}
7740
7741
7742RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7743  SealHandleScope shs(isolate);
7744  ASSERT(args.length() == 2);
7745
7746  CONVERT_SMI_ARG_CHECKED(year, 0);
7747  CONVERT_SMI_ARG_CHECKED(month, 1);
7748
7749  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7750}
7751
7752
7753RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7754  HandleScope scope(isolate);
7755  ASSERT(args.length() == 3);
7756
7757  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7758  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7759  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7760
7761  DateCache* date_cache = isolate->date_cache();
7762
7763  Object* value = NULL;
7764  bool is_value_nan = false;
7765  if (std::isnan(time)) {
7766    value = isolate->heap()->nan_value();
7767    is_value_nan = true;
7768  } else if (!is_utc &&
7769             (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7770              time > DateCache::kMaxTimeBeforeUTCInMs)) {
7771    value = isolate->heap()->nan_value();
7772    is_value_nan = true;
7773  } else {
7774    time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7775    if (time < -DateCache::kMaxTimeInMs ||
7776        time > DateCache::kMaxTimeInMs) {
7777      value = isolate->heap()->nan_value();
7778      is_value_nan = true;
7779    } else  {
7780      MaybeObject* maybe_result =
7781          isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7782      if (!maybe_result->ToObject(&value)) return maybe_result;
7783    }
7784  }
7785  date->SetValue(value, is_value_nan);
7786  return value;
7787}
7788
7789
7790RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7791  HandleScope scope(isolate);
7792  ASSERT(args.length() == 3);
7793
7794  Handle<JSFunction> callee = args.at<JSFunction>(0);
7795  Object** parameters = reinterpret_cast<Object**>(args[1]);
7796  const int argument_count = Smi::cast(args[2])->value();
7797
7798  Handle<JSObject> result =
7799      isolate->factory()->NewArgumentsObject(callee, argument_count);
7800  // Allocate the elements if needed.
7801  int parameter_count = callee->shared()->formal_parameter_count();
7802  if (argument_count > 0) {
7803    if (parameter_count > 0) {
7804      int mapped_count = Min(argument_count, parameter_count);
7805      Handle<FixedArray> parameter_map =
7806          isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7807      parameter_map->set_map(
7808          isolate->heap()->non_strict_arguments_elements_map());
7809
7810      Handle<Map> old_map(result->map());
7811      Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
7812      new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7813
7814      result->set_map(*new_map);
7815      result->set_elements(*parameter_map);
7816
7817      // Store the context and the arguments array at the beginning of the
7818      // parameter map.
7819      Handle<Context> context(isolate->context());
7820      Handle<FixedArray> arguments =
7821          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7822      parameter_map->set(0, *context);
7823      parameter_map->set(1, *arguments);
7824
7825      // Loop over the actual parameters backwards.
7826      int index = argument_count - 1;
7827      while (index >= mapped_count) {
7828        // These go directly in the arguments array and have no
7829        // corresponding slot in the parameter map.
7830        arguments->set(index, *(parameters - index - 1));
7831        --index;
7832      }
7833
7834      Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7835      while (index >= 0) {
7836        // Detect duplicate names to the right in the parameter list.
7837        Handle<String> name(scope_info->ParameterName(index));
7838        int context_local_count = scope_info->ContextLocalCount();
7839        bool duplicate = false;
7840        for (int j = index + 1; j < parameter_count; ++j) {
7841          if (scope_info->ParameterName(j) == *name) {
7842            duplicate = true;
7843            break;
7844          }
7845        }
7846
7847        if (duplicate) {
7848          // This goes directly in the arguments array with a hole in the
7849          // parameter map.
7850          arguments->set(index, *(parameters - index - 1));
7851          parameter_map->set_the_hole(index + 2);
7852        } else {
7853          // The context index goes in the parameter map with a hole in the
7854          // arguments array.
7855          int context_index = -1;
7856          for (int j = 0; j < context_local_count; ++j) {
7857            if (scope_info->ContextLocalName(j) == *name) {
7858              context_index = j;
7859              break;
7860            }
7861          }
7862          ASSERT(context_index >= 0);
7863          arguments->set_the_hole(index);
7864          parameter_map->set(index + 2, Smi::FromInt(
7865              Context::MIN_CONTEXT_SLOTS + context_index));
7866        }
7867
7868        --index;
7869      }
7870    } else {
7871      // If there is no aliasing, the arguments object elements are not
7872      // special in any way.
7873      Handle<FixedArray> elements =
7874          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7875      result->set_elements(*elements);
7876      for (int i = 0; i < argument_count; ++i) {
7877        elements->set(i, *(parameters - i - 1));
7878      }
7879    }
7880  }
7881  return *result;
7882}
7883
7884
7885RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7886  SealHandleScope shs(isolate);
7887  ASSERT(args.length() == 3);
7888
7889  JSFunction* callee = JSFunction::cast(args[0]);
7890  Object** parameters = reinterpret_cast<Object**>(args[1]);
7891  const int length = args.smi_at(2);
7892
7893  Object* result;
7894  { MaybeObject* maybe_result =
7895        isolate->heap()->AllocateArgumentsObject(callee, length);
7896    if (!maybe_result->ToObject(&result)) return maybe_result;
7897  }
7898  // Allocate the elements if needed.
7899  if (length > 0) {
7900    // Allocate the fixed array.
7901    Object* obj;
7902    { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7903      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7904    }
7905
7906    DisallowHeapAllocation no_gc;
7907    FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7908    array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7909    array->set_length(length);
7910
7911    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7912    for (int i = 0; i < length; i++) {
7913      array->set(i, *--parameters, mode);
7914    }
7915    JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7916  }
7917  return result;
7918}
7919
7920
7921RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7922  HandleScope scope(isolate);
7923  ASSERT(args.length() == 3);
7924  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7925  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
7926  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7927
7928  // The caller ensures that we pretenure closures that are assigned
7929  // directly to properties.
7930  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7931  Handle<JSFunction> result =
7932      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7933                                                            context,
7934                                                            pretenure_flag);
7935  return *result;
7936}
7937
7938
7939// Find the arguments of the JavaScript function invocation that called
7940// into C++ code. Collect these in a newly allocated array of handles (possibly
7941// prefixed by a number of empty handles).
7942static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7943    Isolate* isolate,
7944    int prefix_argc,
7945    int* total_argc) {
7946  // Find frame containing arguments passed to the caller.
7947  JavaScriptFrameIterator it(isolate);
7948  JavaScriptFrame* frame = it.frame();
7949  List<JSFunction*> functions(2);
7950  frame->GetFunctions(&functions);
7951  if (functions.length() > 1) {
7952    int inlined_jsframe_index = functions.length() - 1;
7953    JSFunction* inlined_function = functions[inlined_jsframe_index];
7954    Vector<SlotRef> args_slots =
7955        SlotRef::ComputeSlotMappingForArguments(
7956            frame,
7957            inlined_jsframe_index,
7958            inlined_function->shared()->formal_parameter_count());
7959
7960    int args_count = args_slots.length();
7961
7962    *total_argc = prefix_argc + args_count;
7963    SmartArrayPointer<Handle<Object> > param_data(
7964        NewArray<Handle<Object> >(*total_argc));
7965    for (int i = 0; i < args_count; i++) {
7966      Handle<Object> val = args_slots[i].GetValue(isolate);
7967      param_data[prefix_argc + i] = val;
7968    }
7969
7970    args_slots.Dispose();
7971
7972    return param_data;
7973  } else {
7974    it.AdvanceToArgumentsFrame();
7975    frame = it.frame();
7976    int args_count = frame->ComputeParametersCount();
7977
7978    *total_argc = prefix_argc + args_count;
7979    SmartArrayPointer<Handle<Object> > param_data(
7980        NewArray<Handle<Object> >(*total_argc));
7981    for (int i = 0; i < args_count; i++) {
7982      Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
7983      param_data[prefix_argc + i] = val;
7984    }
7985    return param_data;
7986  }
7987}
7988
7989
7990RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7991  HandleScope scope(isolate);
7992  ASSERT(args.length() == 4);
7993  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7994  RUNTIME_ASSERT(args[3]->IsNumber());
7995  Handle<Object> bindee = args.at<Object>(1);
7996
7997  // TODO(lrn): Create bound function in C++ code from premade shared info.
7998  bound_function->shared()->set_bound(true);
7999  // Get all arguments of calling function (Function.prototype.bind).
8000  int argc = 0;
8001  SmartArrayPointer<Handle<Object> > arguments =
8002      GetCallerArguments(isolate, 0, &argc);
8003  // Don't count the this-arg.
8004  if (argc > 0) {
8005    ASSERT(*arguments[0] == args[2]);
8006    argc--;
8007  } else {
8008    ASSERT(args[2]->IsUndefined());
8009  }
8010  // Initialize array of bindings (function, this, and any existing arguments
8011  // if the function was already bound).
8012  Handle<FixedArray> new_bindings;
8013  int i;
8014  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8015    Handle<FixedArray> old_bindings(
8016        JSFunction::cast(*bindee)->function_bindings());
8017    new_bindings =
8018        isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8019    bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8020                            isolate);
8021    i = 0;
8022    for (int n = old_bindings->length(); i < n; i++) {
8023      new_bindings->set(i, old_bindings->get(i));
8024    }
8025  } else {
8026    int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8027    new_bindings = isolate->factory()->NewFixedArray(array_size);
8028    new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8029    new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8030    i = 2;
8031  }
8032  // Copy arguments, skipping the first which is "this_arg".
8033  for (int j = 0; j < argc; j++, i++) {
8034    new_bindings->set(i, *arguments[j + 1]);
8035  }
8036  new_bindings->set_map_no_write_barrier(
8037      isolate->heap()->fixed_cow_array_map());
8038  bound_function->set_function_bindings(*new_bindings);
8039
8040  // Update length.
8041  Handle<String> length_string = isolate->factory()->length_string();
8042  Handle<Object> new_length(args.at<Object>(3));
8043  PropertyAttributes attr =
8044      static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8045  ForceSetProperty(bound_function, length_string, new_length, attr);
8046  return *bound_function;
8047}
8048
8049
8050RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8051  HandleScope handles(isolate);
8052  ASSERT(args.length() == 1);
8053  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8054  if (callable->IsJSFunction()) {
8055    Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8056    if (function->shared()->bound()) {
8057      Handle<FixedArray> bindings(function->function_bindings());
8058      ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8059      return *isolate->factory()->NewJSArrayWithElements(bindings);
8060    }
8061  }
8062  return isolate->heap()->undefined_value();
8063}
8064
8065
8066RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8067  HandleScope scope(isolate);
8068  ASSERT(args.length() == 1);
8069  // First argument is a function to use as a constructor.
8070  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8071  RUNTIME_ASSERT(function->shared()->bound());
8072
8073  // The argument is a bound function. Extract its bound arguments
8074  // and callable.
8075  Handle<FixedArray> bound_args =
8076      Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8077  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8078  Handle<Object> bound_function(
8079      JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8080      isolate);
8081  ASSERT(!bound_function->IsJSFunction() ||
8082         !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8083
8084  int total_argc = 0;
8085  SmartArrayPointer<Handle<Object> > param_data =
8086      GetCallerArguments(isolate, bound_argc, &total_argc);
8087  for (int i = 0; i < bound_argc; i++) {
8088    param_data[i] = Handle<Object>(bound_args->get(
8089        JSFunction::kBoundArgumentsStartIndex + i), isolate);
8090  }
8091
8092  if (!bound_function->IsJSFunction()) {
8093    bool exception_thrown;
8094    bound_function = Execution::TryGetConstructorDelegate(bound_function,
8095                                                          &exception_thrown);
8096    if (exception_thrown) return Failure::Exception();
8097  }
8098  ASSERT(bound_function->IsJSFunction());
8099
8100  bool exception = false;
8101  Handle<Object> result =
8102      Execution::New(Handle<JSFunction>::cast(bound_function),
8103                     total_argc, *param_data, &exception);
8104  if (exception) {
8105    return Failure::Exception();
8106  }
8107  ASSERT(!result.is_null());
8108  return *result;
8109}
8110
8111
8112RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8113  HandleScope scope(isolate);
8114  ASSERT(args.length() == 1);
8115
8116  Handle<Object> constructor = args.at<Object>(0);
8117
8118  // If the constructor isn't a proper function we throw a type error.
8119  if (!constructor->IsJSFunction()) {
8120    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8121    Handle<Object> type_error =
8122        isolate->factory()->NewTypeError("not_constructor", arguments);
8123    return isolate->Throw(*type_error);
8124  }
8125
8126  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8127
8128  // If function should not have prototype, construction is not allowed. In this
8129  // case generated code bailouts here, since function has no initial_map.
8130  if (!function->should_have_prototype() && !function->shared()->bound()) {
8131    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8132    Handle<Object> type_error =
8133        isolate->factory()->NewTypeError("not_constructor", arguments);
8134    return isolate->Throw(*type_error);
8135  }
8136
8137#ifdef ENABLE_DEBUGGER_SUPPORT
8138  Debug* debug = isolate->debug();
8139  // Handle stepping into constructors if step into is active.
8140  if (debug->StepInActive()) {
8141    debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8142  }
8143#endif
8144
8145  if (function->has_initial_map()) {
8146    if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8147      // The 'Function' function ignores the receiver object when
8148      // called using 'new' and creates a new JSFunction object that
8149      // is returned.  The receiver object is only used for error
8150      // reporting if an error occurs when constructing the new
8151      // JSFunction. Factory::NewJSObject() should not be used to
8152      // allocate JSFunctions since it does not properly initialize
8153      // the shared part of the function. Since the receiver is
8154      // ignored anyway, we use the global object as the receiver
8155      // instead of a new JSFunction object. This way, errors are
8156      // reported the same way whether or not 'Function' is called
8157      // using 'new'.
8158      return isolate->context()->global_object();
8159    }
8160  }
8161
8162  // The function should be compiled for the optimization hints to be
8163  // available.
8164  JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
8165
8166  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8167  if (!function->has_initial_map() &&
8168      shared->IsInobjectSlackTrackingInProgress()) {
8169    // The tracking is already in progress for another function. We can only
8170    // track one initial_map at a time, so we force the completion before the
8171    // function is called as a constructor for the first time.
8172    shared->CompleteInobjectSlackTracking();
8173  }
8174
8175  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8176  RETURN_IF_EMPTY_HANDLE(isolate, result);
8177
8178  isolate->counters()->constructed_objects()->Increment();
8179  isolate->counters()->constructed_objects_runtime()->Increment();
8180
8181  return *result;
8182}
8183
8184
8185RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8186  HandleScope scope(isolate);
8187  ASSERT(args.length() == 1);
8188
8189  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8190  function->shared()->CompleteInobjectSlackTracking();
8191
8192  return isolate->heap()->undefined_value();
8193}
8194
8195
8196RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8197  HandleScope scope(isolate);
8198  ASSERT(args.length() == 1);
8199
8200  Handle<JSFunction> function = args.at<JSFunction>(0);
8201#ifdef DEBUG
8202  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8203    PrintF("[lazy: ");
8204    function->PrintName();
8205    PrintF("]\n");
8206  }
8207#endif
8208
8209  // Compile the target function.
8210  ASSERT(!function->is_compiled());
8211  if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8212    return Failure::Exception();
8213  }
8214
8215  // All done. Return the compiled code.
8216  ASSERT(function->is_compiled());
8217  return function->code();
8218}
8219
8220
8221bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
8222  // If the function is not compiled ignore the lazy
8223  // recompilation. This can happen if the debugger is activated and
8224  // the function is returned to the not compiled state.
8225  if (!function->shared()->is_compiled()) return false;
8226
8227  // If the function is not optimizable or debugger is active continue using the
8228  // code from the full compiler.
8229  if (!FLAG_crankshaft ||
8230      function->shared()->optimization_disabled() ||
8231      isolate->DebuggerHasBreakPoints()) {
8232    if (FLAG_trace_opt) {
8233      PrintF("[failed to optimize ");
8234      function->PrintName();
8235      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8236          function->shared()->optimization_disabled() ? "F" : "T",
8237          isolate->DebuggerHasBreakPoints() ? "T" : "F");
8238    }
8239    return false;
8240  }
8241  return true;
8242}
8243
8244
8245RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8246  HandleScope scope(isolate);
8247  ASSERT(args.length() == 1);
8248  Handle<JSFunction> function = args.at<JSFunction>(0);
8249
8250  if (!AllowOptimization(isolate, function)) {
8251    function->ReplaceCode(function->shared()->code());
8252    return function->code();
8253  }
8254  function->shared()->code()->set_profiler_ticks(0);
8255  if (JSFunction::CompileOptimized(function,
8256                                   BailoutId::None(),
8257                                   CLEAR_EXCEPTION)) {
8258    return function->code();
8259  }
8260  if (FLAG_trace_opt) {
8261    PrintF("[failed to optimize ");
8262    function->PrintName();
8263    PrintF(": optimized compilation failed]\n");
8264  }
8265  function->ReplaceCode(function->shared()->code());
8266  return function->code();
8267}
8268
8269
8270RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) {
8271  HandleScope handle_scope(isolate);
8272  ASSERT(args.length() == 1);
8273  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8274  if (!AllowOptimization(isolate, function)) {
8275    function->ReplaceCode(function->shared()->code());
8276    return isolate->heap()->undefined_value();
8277  }
8278  function->shared()->code()->set_profiler_ticks(0);
8279  ASSERT(FLAG_parallel_recompilation);
8280  Compiler::RecompileParallel(function);
8281  return isolate->heap()->undefined_value();
8282}
8283
8284
8285RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) {
8286  HandleScope handle_scope(isolate);
8287  ASSERT(args.length() == 1);
8288  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8289  ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation);
8290  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8291  return function->code();
8292}
8293
8294
8295class ActivationsFinder : public ThreadVisitor {
8296 public:
8297  Code* code_;
8298  bool has_code_activations_;
8299
8300  explicit ActivationsFinder(Code* code)
8301    : code_(code),
8302      has_code_activations_(false) { }
8303
8304  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8305    JavaScriptFrameIterator it(isolate, top);
8306    VisitFrames(&it);
8307  }
8308
8309  void VisitFrames(JavaScriptFrameIterator* it) {
8310    for (; !it->done(); it->Advance()) {
8311      JavaScriptFrame* frame = it->frame();
8312      if (code_->contains(frame->pc())) has_code_activations_ = true;
8313    }
8314  }
8315};
8316
8317
8318RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
8319  HandleScope scope(isolate);
8320  ASSERT(args.length() == 0);
8321  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8322  ASSERT(AllowHeapAllocation::IsAllowed());
8323  delete deoptimizer;
8324  return isolate->heap()->undefined_value();
8325}
8326
8327
8328RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8329  HandleScope scope(isolate);
8330  ASSERT(args.length() == 1);
8331  RUNTIME_ASSERT(args[0]->IsSmi());
8332  Deoptimizer::BailoutType type =
8333      static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8334  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8335  ASSERT(AllowHeapAllocation::IsAllowed());
8336
8337  Handle<JSFunction> function = deoptimizer->function();
8338  Handle<Code> optimized_code = deoptimizer->compiled_code();
8339
8340  ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8341  ASSERT(type == deoptimizer->bailout_type());
8342
8343  // Make sure to materialize objects before causing any allocation.
8344  JavaScriptFrameIterator it(isolate);
8345  deoptimizer->MaterializeHeapObjects(&it);
8346  delete deoptimizer;
8347
8348  JavaScriptFrame* frame = it.frame();
8349  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8350
8351  // Avoid doing too much work when running with --always-opt and keep
8352  // the optimized code around.
8353  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8354    return isolate->heap()->undefined_value();
8355  }
8356
8357  // Search for other activations of the same function and code.
8358  ActivationsFinder activations_finder(*optimized_code);
8359  activations_finder.VisitFrames(&it);
8360  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8361
8362  if (!activations_finder.has_code_activations_) {
8363    if (function->code() == *optimized_code) {
8364      if (FLAG_trace_deopt) {
8365        PrintF("[removing optimized code for: ");
8366        function->PrintName();
8367        PrintF("]\n");
8368      }
8369      function->ReplaceCode(function->shared()->code());
8370    }
8371  } else {
8372    // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8373    // unconditionally if the code is not already marked for deoptimization.
8374    // If there is an index by shared function info, all the better.
8375    Deoptimizer::DeoptimizeFunction(*function);
8376  }
8377  // Evict optimized code for this function from the cache so that it doesn't
8378  // get used for new closures.
8379  function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8380                                                "notify deoptimized");
8381
8382  return isolate->heap()->undefined_value();
8383}
8384
8385
8386RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8387  SealHandleScope shs(isolate);
8388  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8389  delete deoptimizer;
8390  return isolate->heap()->undefined_value();
8391}
8392
8393
8394RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8395  HandleScope scope(isolate);
8396  ASSERT(args.length() == 1);
8397  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8398  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8399
8400  Deoptimizer::DeoptimizeFunction(*function);
8401
8402  return isolate->heap()->undefined_value();
8403}
8404
8405
8406RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8407  HandleScope scope(isolate);
8408  ASSERT(args.length() == 1);
8409  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8410  Code* unoptimized = function->shared()->code();
8411  if (unoptimized->kind() == Code::FUNCTION) {
8412    unoptimized->ClearInlineCaches();
8413    unoptimized->ClearTypeFeedbackCells(isolate->heap());
8414  }
8415  return isolate->heap()->undefined_value();
8416}
8417
8418
8419RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8420  SealHandleScope shs(isolate);
8421#if defined(USE_SIMULATOR)
8422  return isolate->heap()->true_value();
8423#else
8424  return isolate->heap()->false_value();
8425#endif
8426}
8427
8428
8429RUNTIME_FUNCTION(MaybeObject*, Runtime_IsParallelRecompilationSupported) {
8430  HandleScope scope(isolate);
8431  return FLAG_parallel_recompilation
8432      ? isolate->heap()->true_value() : isolate->heap()->false_value();
8433}
8434
8435
8436RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8437  HandleScope scope(isolate);
8438  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8439  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8440
8441  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8442  function->MarkForLazyRecompilation();
8443
8444  Code* unoptimized = function->shared()->code();
8445  if (args.length() == 2 &&
8446      unoptimized->kind() == Code::FUNCTION) {
8447    CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8448    if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8449      for (int i = 0; i <= Code::kMaxLoopNestingMarker; i++) {
8450        unoptimized->set_allow_osr_at_loop_nesting_level(i);
8451        isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8452      }
8453    } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("parallel"))) {
8454      function->MarkForParallelRecompilation();
8455    }
8456  }
8457
8458  return isolate->heap()->undefined_value();
8459}
8460
8461
8462RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8463  HandleScope scope(isolate);
8464  ASSERT(args.length() == 1);
8465  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8466  ASSERT(!function->IsOptimized());
8467  function->shared()->set_optimization_disabled(true);
8468  return isolate->heap()->undefined_value();
8469}
8470
8471
8472RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8473  HandleScope scope(isolate);
8474  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8475  if (!V8::UseCrankshaft()) {
8476    return Smi::FromInt(4);  // 4 == "never".
8477  }
8478  bool sync_with_compiler_thread = true;
8479  if (args.length() == 2) {
8480    CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8481    if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8482      sync_with_compiler_thread = false;
8483    }
8484  }
8485  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8486  if (FLAG_parallel_recompilation && sync_with_compiler_thread) {
8487    while (function->IsInRecompileQueue() ||
8488           function->IsMarkedForInstallingRecompiledCode()) {
8489      isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8490      OS::Sleep(50);
8491    }
8492  }
8493  if (FLAG_always_opt) {
8494    // We may have always opt, but that is more best-effort than a real
8495    // promise, so we still say "no" if it is not optimized.
8496    return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8497                                   : Smi::FromInt(2);  // 2 == "no".
8498  }
8499  if (FLAG_deopt_every_n_times) {
8500    return Smi::FromInt(6);  // 6 == "maybe deopted".
8501  }
8502  return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8503                                 : Smi::FromInt(2);  // 2 == "no".
8504}
8505
8506
8507RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8508  HandleScope scope(isolate);
8509  ASSERT(args.length() == 1);
8510  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8511  return Smi::FromInt(function->shared()->opt_count());
8512}
8513
8514
8515RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8516  HandleScope scope(isolate);
8517  ASSERT(args.length() == 1);
8518  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8519
8520  // We're not prepared to handle a function with arguments object.
8521  ASSERT(!function->shared()->uses_arguments());
8522
8523  // We have hit a back edge in an unoptimized frame for a function that was
8524  // selected for on-stack replacement.  Find the unoptimized code object.
8525  Handle<Code> unoptimized(function->shared()->code(), isolate);
8526  // Keep track of whether we've succeeded in optimizing.
8527  bool succeeded = unoptimized->optimizable();
8528  if (succeeded) {
8529    // If we are trying to do OSR when there are already optimized
8530    // activations of the function, it means (a) the function is directly or
8531    // indirectly recursive and (b) an optimized invocation has been
8532    // deoptimized so that we are currently in an unoptimized activation.
8533    // Check for optimized activations of this function.
8534    JavaScriptFrameIterator it(isolate);
8535    while (succeeded && !it.done()) {
8536      JavaScriptFrame* frame = it.frame();
8537      succeeded = !frame->is_optimized() || frame->function() != *function;
8538      it.Advance();
8539    }
8540  }
8541
8542  BailoutId ast_id = BailoutId::None();
8543  if (succeeded) {
8544    // The top JS function is this one, the PC is somewhere in the
8545    // unoptimized code.
8546    JavaScriptFrameIterator it(isolate);
8547    JavaScriptFrame* frame = it.frame();
8548    ASSERT(frame->function() == *function);
8549    ASSERT(frame->LookupCode() == *unoptimized);
8550    ASSERT(unoptimized->contains(frame->pc()));
8551
8552    // Use linear search of the unoptimized code's back edge table to find
8553    // the AST id matching the PC.
8554    uint32_t target_pc_offset =
8555      static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
8556    uint32_t loop_depth = 0;
8557
8558    for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized);
8559         !back_edges.Done();
8560         back_edges.Next()) {
8561      if (back_edges.pc_offset() == target_pc_offset) {
8562        ast_id = back_edges.ast_id();
8563        loop_depth = back_edges.loop_depth();
8564        break;
8565      }
8566    }
8567    ASSERT(!ast_id.IsNone());
8568
8569    if (FLAG_trace_osr) {
8570      PrintF("[replacing on-stack at AST id %d, loop depth %d in ",
8571              ast_id.ToInt(), loop_depth);
8572      function->PrintName();
8573      PrintF("]\n");
8574    }
8575
8576    // Try to compile the optimized code.  A true return value from
8577    // CompileOptimized means that compilation succeeded, not necessarily
8578    // that optimization succeeded.
8579    if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8580        function->IsOptimized()) {
8581      DeoptimizationInputData* data = DeoptimizationInputData::cast(
8582          function->code()->deoptimization_data());
8583      if (data->OsrPcOffset()->value() >= 0) {
8584        if (FLAG_trace_osr) {
8585          PrintF("[on-stack replacement offset %d in optimized code]\n",
8586               data->OsrPcOffset()->value());
8587        }
8588        ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8589      } else {
8590        // We may never generate the desired OSR entry if we emit an
8591        // early deoptimize.
8592        succeeded = false;
8593      }
8594    } else {
8595      succeeded = false;
8596    }
8597  }
8598
8599  // Revert to the original interrupt calls in the original unoptimized code.
8600  if (FLAG_trace_osr) {
8601    PrintF("[restoring original interrupt calls in ");
8602    function->PrintName();
8603    PrintF("]\n");
8604  }
8605  InterruptStub interrupt_stub;
8606  Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate);
8607  Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8608  Deoptimizer::RevertInterruptCode(*unoptimized,
8609                                   *interrupt_code,
8610                                   *replacement_code);
8611
8612  // If the optimization attempt succeeded, return the AST id tagged as a
8613  // smi. This tells the builtin that we need to translate the unoptimized
8614  // frame to an optimized one.
8615  if (succeeded) {
8616    ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8617    return Smi::FromInt(ast_id.ToInt());
8618  } else {
8619    if (function->IsMarkedForLazyRecompilation()) {
8620      function->ReplaceCode(function->shared()->code());
8621    }
8622    return Smi::FromInt(-1);
8623  }
8624}
8625
8626
8627RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
8628  SealHandleScope shs(isolate);
8629  ASSERT(args.length() == 2);
8630#ifdef DEBUG
8631  CONVERT_SMI_ARG_CHECKED(interval, 0);
8632  CONVERT_SMI_ARG_CHECKED(timeout, 1);
8633  isolate->heap()->set_allocation_timeout(timeout);
8634  FLAG_gc_interval = interval;
8635#endif
8636  return isolate->heap()->undefined_value();
8637}
8638
8639
8640RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8641  SealHandleScope shs(isolate);
8642  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8643  return isolate->heap()->undefined_value();
8644}
8645
8646
8647RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8648  SealHandleScope shs(isolate);
8649  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8650  return isolate->heap()->nan_value();
8651}
8652
8653
8654RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8655  HandleScope scope(isolate);
8656  ASSERT(args.length() >= 2);
8657  int argc = args.length() - 2;
8658  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8659  Object* receiver = args[0];
8660
8661  // If there are too many arguments, allocate argv via malloc.
8662  const int argv_small_size = 10;
8663  Handle<Object> argv_small_buffer[argv_small_size];
8664  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8665  Handle<Object>* argv = argv_small_buffer;
8666  if (argc > argv_small_size) {
8667    argv = new Handle<Object>[argc];
8668    if (argv == NULL) return isolate->StackOverflow();
8669    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8670  }
8671
8672  for (int i = 0; i < argc; ++i) {
8673     MaybeObject* maybe = args[1 + i];
8674     Object* object;
8675     if (!maybe->To<Object>(&object)) return maybe;
8676     argv[i] = Handle<Object>(object, isolate);
8677  }
8678
8679  bool threw;
8680  Handle<JSReceiver> hfun(fun);
8681  Handle<Object> hreceiver(receiver, isolate);
8682  Handle<Object> result =
8683      Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8684
8685  if (threw) return Failure::Exception();
8686  return *result;
8687}
8688
8689
8690RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8691  HandleScope scope(isolate);
8692  ASSERT(args.length() == 5);
8693  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8694  Handle<Object> receiver = args.at<Object>(1);
8695  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8696  CONVERT_SMI_ARG_CHECKED(offset, 3);
8697  CONVERT_SMI_ARG_CHECKED(argc, 4);
8698  RUNTIME_ASSERT(offset >= 0);
8699  RUNTIME_ASSERT(argc >= 0);
8700
8701  // If there are too many arguments, allocate argv via malloc.
8702  const int argv_small_size = 10;
8703  Handle<Object> argv_small_buffer[argv_small_size];
8704  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8705  Handle<Object>* argv = argv_small_buffer;
8706  if (argc > argv_small_size) {
8707    argv = new Handle<Object>[argc];
8708    if (argv == NULL) return isolate->StackOverflow();
8709    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8710  }
8711
8712  for (int i = 0; i < argc; ++i) {
8713    argv[i] = Object::GetElement(arguments, offset + i);
8714  }
8715
8716  bool threw;
8717  Handle<Object> result =
8718      Execution::Call(fun, receiver, argc, argv, &threw, true);
8719
8720  if (threw) return Failure::Exception();
8721  return *result;
8722}
8723
8724
8725RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8726  HandleScope scope(isolate);
8727  ASSERT(args.length() == 1);
8728  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8729  return *Execution::GetFunctionDelegate(args.at<Object>(0));
8730}
8731
8732
8733RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8734  HandleScope scope(isolate);
8735  ASSERT(args.length() == 1);
8736  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8737  return *Execution::GetConstructorDelegate(args.at<Object>(0));
8738}
8739
8740
8741RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
8742  SealHandleScope shs(isolate);
8743  ASSERT(args.length() == 2);
8744
8745  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8746  CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
8747  Context* result;
8748  MaybeObject* maybe_result =
8749      isolate->heap()->AllocateGlobalContext(function, scope_info);
8750  if (!maybe_result->To(&result)) return maybe_result;
8751
8752  ASSERT(function->context() == isolate->context());
8753  ASSERT(function->context()->global_object() == result->global_object());
8754  isolate->set_context(result);
8755  result->global_object()->set_global_context(result);
8756
8757  return result;  // non-failure
8758}
8759
8760
8761RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8762  SealHandleScope shs(isolate);
8763  ASSERT(args.length() == 1);
8764
8765  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8766  int length = function->shared()->scope_info()->ContextLength();
8767  Context* result;
8768  MaybeObject* maybe_result =
8769      isolate->heap()->AllocateFunctionContext(length, function);
8770  if (!maybe_result->To(&result)) return maybe_result;
8771
8772  isolate->set_context(result);
8773
8774  return result;  // non-failure
8775}
8776
8777
8778RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8779  SealHandleScope shs(isolate);
8780  ASSERT(args.length() == 2);
8781  JSReceiver* extension_object;
8782  if (args[0]->IsJSReceiver()) {
8783    extension_object = JSReceiver::cast(args[0]);
8784  } else {
8785    // Convert the object to a proper JavaScript object.
8786    MaybeObject* maybe_js_object = args[0]->ToObject();
8787    if (!maybe_js_object->To(&extension_object)) {
8788      if (Failure::cast(maybe_js_object)->IsInternalError()) {
8789        HandleScope scope(isolate);
8790        Handle<Object> handle = args.at<Object>(0);
8791        Handle<Object> result =
8792            isolate->factory()->NewTypeError("with_expression",
8793                                             HandleVector(&handle, 1));
8794        return isolate->Throw(*result);
8795      } else {
8796        return maybe_js_object;
8797      }
8798    }
8799  }
8800
8801  JSFunction* function;
8802  if (args[1]->IsSmi()) {
8803    // A smi sentinel indicates a context nested inside global code rather
8804    // than some function.  There is a canonical empty function that can be
8805    // gotten from the native context.
8806    function = isolate->context()->native_context()->closure();
8807  } else {
8808    function = JSFunction::cast(args[1]);
8809  }
8810
8811  Context* context;
8812  MaybeObject* maybe_context =
8813      isolate->heap()->AllocateWithContext(function,
8814                                           isolate->context(),
8815                                           extension_object);
8816  if (!maybe_context->To(&context)) return maybe_context;
8817  isolate->set_context(context);
8818  return context;
8819}
8820
8821
8822RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8823  SealHandleScope shs(isolate);
8824  ASSERT(args.length() == 3);
8825  String* name = String::cast(args[0]);
8826  Object* thrown_object = args[1];
8827  JSFunction* function;
8828  if (args[2]->IsSmi()) {
8829    // A smi sentinel indicates a context nested inside global code rather
8830    // than some function.  There is a canonical empty function that can be
8831    // gotten from the native context.
8832    function = isolate->context()->native_context()->closure();
8833  } else {
8834    function = JSFunction::cast(args[2]);
8835  }
8836  Context* context;
8837  MaybeObject* maybe_context =
8838      isolate->heap()->AllocateCatchContext(function,
8839                                            isolate->context(),
8840                                            name,
8841                                            thrown_object);
8842  if (!maybe_context->To(&context)) return maybe_context;
8843  isolate->set_context(context);
8844  return context;
8845}
8846
8847
8848RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8849  SealHandleScope shs(isolate);
8850  ASSERT(args.length() == 2);
8851  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8852  JSFunction* function;
8853  if (args[1]->IsSmi()) {
8854    // A smi sentinel indicates a context nested inside global code rather
8855    // than some function.  There is a canonical empty function that can be
8856    // gotten from the native context.
8857    function = isolate->context()->native_context()->closure();
8858  } else {
8859    function = JSFunction::cast(args[1]);
8860  }
8861  Context* context;
8862  MaybeObject* maybe_context =
8863      isolate->heap()->AllocateBlockContext(function,
8864                                            isolate->context(),
8865                                            scope_info);
8866  if (!maybe_context->To(&context)) return maybe_context;
8867  isolate->set_context(context);
8868  return context;
8869}
8870
8871
8872RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
8873  SealHandleScope shs(isolate);
8874  ASSERT(args.length() == 1);
8875  Object* obj = args[0];
8876  return isolate->heap()->ToBoolean(obj->IsJSModule());
8877}
8878
8879
8880RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
8881  SealHandleScope shs(isolate);
8882  ASSERT(args.length() == 2);
8883  CONVERT_SMI_ARG_CHECKED(index, 0);
8884
8885  if (!args[1]->IsScopeInfo()) {
8886    // Module already initialized. Find hosting context and retrieve context.
8887    Context* host = Context::cast(isolate->context())->global_context();
8888    Context* context = Context::cast(host->get(index));
8889    ASSERT(context->previous() == isolate->context());
8890    isolate->set_context(context);
8891    return context;
8892  }
8893
8894  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
8895
8896  // Allocate module context.
8897  HandleScope scope(isolate);
8898  Factory* factory = isolate->factory();
8899  Handle<Context> context = factory->NewModuleContext(scope_info);
8900  Handle<JSModule> module = factory->NewJSModule(context, scope_info);
8901  context->set_module(*module);
8902  Context* previous = isolate->context();
8903  context->set_previous(previous);
8904  context->set_closure(previous->closure());
8905  context->set_global_object(previous->global_object());
8906  isolate->set_context(*context);
8907
8908  // Find hosting scope and initialize internal variable holding module there.
8909  previous->global_context()->set(index, *context);
8910
8911  return *context;
8912}
8913
8914
8915RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
8916  HandleScope scope(isolate);
8917  ASSERT(args.length() == 1);
8918  CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
8919  Context* host_context = isolate->context();
8920
8921  for (int i = 0; i < descriptions->length(); ++i) {
8922    Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
8923    int host_index = description->host_index();
8924    Handle<Context> context(Context::cast(host_context->get(host_index)));
8925    Handle<JSModule> module(context->module());
8926
8927    for (int j = 0; j < description->length(); ++j) {
8928      Handle<String> name(description->name(j));
8929      VariableMode mode = description->mode(j);
8930      int index = description->index(j);
8931      switch (mode) {
8932        case VAR:
8933        case LET:
8934        case CONST:
8935        case CONST_HARMONY: {
8936          PropertyAttributes attr =
8937              IsImmutableVariableMode(mode) ? FROZEN : SEALED;
8938          Handle<AccessorInfo> info =
8939              Accessors::MakeModuleExport(name, index, attr);
8940          Handle<Object> result = SetAccessor(module, info);
8941          ASSERT(!(result.is_null() || result->IsUndefined()));
8942          USE(result);
8943          break;
8944        }
8945        case MODULE: {
8946          Object* referenced_context = Context::cast(host_context)->get(index);
8947          Handle<JSModule> value(Context::cast(referenced_context)->module());
8948          JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
8949          break;
8950        }
8951        case INTERNAL:
8952        case TEMPORARY:
8953        case DYNAMIC:
8954        case DYNAMIC_GLOBAL:
8955        case DYNAMIC_LOCAL:
8956          UNREACHABLE();
8957      }
8958    }
8959
8960    JSObject::PreventExtensions(module);
8961  }
8962
8963  ASSERT(!isolate->has_pending_exception());
8964  return isolate->heap()->undefined_value();
8965}
8966
8967
8968RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8969  HandleScope scope(isolate);
8970  ASSERT(args.length() == 2);
8971
8972  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8973  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
8974
8975  int index;
8976  PropertyAttributes attributes;
8977  ContextLookupFlags flags = FOLLOW_CHAINS;
8978  BindingFlags binding_flags;
8979  Handle<Object> holder = context->Lookup(name,
8980                                          flags,
8981                                          &index,
8982                                          &attributes,
8983                                          &binding_flags);
8984
8985  // If the slot was not found the result is true.
8986  if (holder.is_null()) {
8987    return isolate->heap()->true_value();
8988  }
8989
8990  // If the slot was found in a context, it should be DONT_DELETE.
8991  if (holder->IsContext()) {
8992    return isolate->heap()->false_value();
8993  }
8994
8995  // The slot was found in a JSObject, either a context extension object,
8996  // the global object, or the subject of a with.  Try to delete it
8997  // (respecting DONT_DELETE).
8998  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8999  Handle<Object> result = JSReceiver::DeleteProperty(object, name);
9000  RETURN_IF_EMPTY_HANDLE(isolate, result);
9001  return *result;
9002}
9003
9004
9005// A mechanism to return a pair of Object pointers in registers (if possible).
9006// How this is achieved is calling convention-dependent.
9007// All currently supported x86 compiles uses calling conventions that are cdecl
9008// variants where a 64-bit value is returned in two 32-bit registers
9009// (edx:eax on ia32, r1:r0 on ARM).
9010// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9011// In Win64 calling convention, a struct of two pointers is returned in memory,
9012// allocated by the caller, and passed as a pointer in a hidden first parameter.
9013#ifdef V8_HOST_ARCH_64_BIT
9014struct ObjectPair {
9015  MaybeObject* x;
9016  MaybeObject* y;
9017};
9018
9019
9020static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9021  ObjectPair result = {x, y};
9022  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9023  // In Win64 they are assigned to a hidden first argument.
9024  return result;
9025}
9026#else
9027typedef uint64_t ObjectPair;
9028static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9029  return reinterpret_cast<uint32_t>(x) |
9030      (reinterpret_cast<ObjectPair>(y) << 32);
9031}
9032#endif
9033
9034
9035static inline MaybeObject* Unhole(Heap* heap,
9036                                  MaybeObject* x,
9037                                  PropertyAttributes attributes) {
9038  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9039  USE(attributes);
9040  return x->IsTheHole() ? heap->undefined_value() : x;
9041}
9042
9043
9044static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9045                                           JSObject* holder) {
9046  ASSERT(!holder->IsGlobalObject());
9047  Context* top = isolate->context();
9048  // Get the context extension function.
9049  JSFunction* context_extension_function =
9050      top->native_context()->context_extension_function();
9051  // If the holder isn't a context extension object, we just return it
9052  // as the receiver. This allows arguments objects to be used as
9053  // receivers, but only if they are put in the context scope chain
9054  // explicitly via a with-statement.
9055  Object* constructor = holder->map()->constructor();
9056  if (constructor != context_extension_function) return holder;
9057  // Fall back to using the global object as the implicit receiver if
9058  // the property turns out to be a local variable allocated in a
9059  // context extension object - introduced via eval. Implicit global
9060  // receivers are indicated with the hole value.
9061  return isolate->heap()->the_hole_value();
9062}
9063
9064
9065static ObjectPair LoadContextSlotHelper(Arguments args,
9066                                        Isolate* isolate,
9067                                        bool throw_error) {
9068  HandleScope scope(isolate);
9069  ASSERT_EQ(2, args.length());
9070
9071  if (!args[0]->IsContext() || !args[1]->IsString()) {
9072    return MakePair(isolate->ThrowIllegalOperation(), NULL);
9073  }
9074  Handle<Context> context = args.at<Context>(0);
9075  Handle<String> name = args.at<String>(1);
9076
9077  int index;
9078  PropertyAttributes attributes;
9079  ContextLookupFlags flags = FOLLOW_CHAINS;
9080  BindingFlags binding_flags;
9081  Handle<Object> holder = context->Lookup(name,
9082                                          flags,
9083                                          &index,
9084                                          &attributes,
9085                                          &binding_flags);
9086  if (isolate->has_pending_exception()) {
9087    return MakePair(Failure::Exception(), NULL);
9088  }
9089
9090  // If the index is non-negative, the slot has been found in a context.
9091  if (index >= 0) {
9092    ASSERT(holder->IsContext());
9093    // If the "property" we were looking for is a local variable, the
9094    // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9095    //
9096    // Use the hole as the receiver to signal that the receiver is implicit
9097    // and that the global receiver should be used (as distinguished from an
9098    // explicit receiver that happens to be a global object).
9099    Handle<Object> receiver = isolate->factory()->the_hole_value();
9100    Object* value = Context::cast(*holder)->get(index);
9101    // Check for uninitialized bindings.
9102    switch (binding_flags) {
9103      case MUTABLE_CHECK_INITIALIZED:
9104      case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9105        if (value->IsTheHole()) {
9106          Handle<Object> reference_error =
9107              isolate->factory()->NewReferenceError("not_defined",
9108                                                    HandleVector(&name, 1));
9109          return MakePair(isolate->Throw(*reference_error), NULL);
9110        }
9111        // FALLTHROUGH
9112      case MUTABLE_IS_INITIALIZED:
9113      case IMMUTABLE_IS_INITIALIZED:
9114      case IMMUTABLE_IS_INITIALIZED_HARMONY:
9115        ASSERT(!value->IsTheHole());
9116        return MakePair(value, *receiver);
9117      case IMMUTABLE_CHECK_INITIALIZED:
9118        return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9119      case MISSING_BINDING:
9120        UNREACHABLE();
9121        return MakePair(NULL, NULL);
9122    }
9123  }
9124
9125  // Otherwise, if the slot was found the holder is a context extension
9126  // object, subject of a with, or a global object.  We read the named
9127  // property from it.
9128  if (!holder.is_null()) {
9129    Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9130    ASSERT(object->IsJSProxy() || object->HasProperty(*name));
9131    // GetProperty below can cause GC.
9132    Handle<Object> receiver_handle(
9133        object->IsGlobalObject()
9134            ? GlobalObject::cast(*object)->global_receiver()
9135            : object->IsJSProxy() ? static_cast<Object*>(*object)
9136                : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9137        isolate);
9138
9139    // No need to unhole the value here.  This is taken care of by the
9140    // GetProperty function.
9141    MaybeObject* value = object->GetProperty(*name);
9142    return MakePair(value, *receiver_handle);
9143  }
9144
9145  if (throw_error) {
9146    // The property doesn't exist - throw exception.
9147    Handle<Object> reference_error =
9148        isolate->factory()->NewReferenceError("not_defined",
9149                                              HandleVector(&name, 1));
9150    return MakePair(isolate->Throw(*reference_error), NULL);
9151  } else {
9152    // The property doesn't exist - return undefined.
9153    return MakePair(isolate->heap()->undefined_value(),
9154                    isolate->heap()->undefined_value());
9155  }
9156}
9157
9158
9159RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
9160  return LoadContextSlotHelper(args, isolate, true);
9161}
9162
9163
9164RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
9165  return LoadContextSlotHelper(args, isolate, false);
9166}
9167
9168
9169RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
9170  HandleScope scope(isolate);
9171  ASSERT(args.length() == 4);
9172
9173  Handle<Object> value(args[0], isolate);
9174  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9175  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9176  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9177  StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
9178      ? kNonStrictMode : kStrictMode;
9179
9180  int index;
9181  PropertyAttributes attributes;
9182  ContextLookupFlags flags = FOLLOW_CHAINS;
9183  BindingFlags binding_flags;
9184  Handle<Object> holder = context->Lookup(name,
9185                                          flags,
9186                                          &index,
9187                                          &attributes,
9188                                          &binding_flags);
9189  if (isolate->has_pending_exception()) return Failure::Exception();
9190
9191  if (index >= 0) {
9192    // The property was found in a context slot.
9193    Handle<Context> context = Handle<Context>::cast(holder);
9194    if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9195        context->get(index)->IsTheHole()) {
9196      Handle<Object> error =
9197          isolate->factory()->NewReferenceError("not_defined",
9198                                                HandleVector(&name, 1));
9199      return isolate->Throw(*error);
9200    }
9201    // Ignore if read_only variable.
9202    if ((attributes & READ_ONLY) == 0) {
9203      // Context is a fixed array and set cannot fail.
9204      context->set(index, *value);
9205    } else if (strict_mode == kStrictMode) {
9206      // Setting read only property in strict mode.
9207      Handle<Object> error =
9208          isolate->factory()->NewTypeError("strict_cannot_assign",
9209                                           HandleVector(&name, 1));
9210      return isolate->Throw(*error);
9211    }
9212    return *value;
9213  }
9214
9215  // Slow case: The property is not in a context slot.  It is either in a
9216  // context extension object, a property of the subject of a with, or a
9217  // property of the global object.
9218  Handle<JSReceiver> object;
9219
9220  if (!holder.is_null()) {
9221    // The property exists on the holder.
9222    object = Handle<JSReceiver>::cast(holder);
9223  } else {
9224    // The property was not found.
9225    ASSERT(attributes == ABSENT);
9226
9227    if (strict_mode == kStrictMode) {
9228      // Throw in strict mode (assignment to undefined variable).
9229      Handle<Object> error =
9230          isolate->factory()->NewReferenceError(
9231              "not_defined", HandleVector(&name, 1));
9232      return isolate->Throw(*error);
9233    }
9234    // In non-strict mode, the property is added to the global object.
9235    attributes = NONE;
9236    object = Handle<JSReceiver>(isolate->context()->global_object());
9237  }
9238
9239  // Set the property if it's not read only or doesn't yet exist.
9240  if ((attributes & READ_ONLY) == 0 ||
9241      (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9242    RETURN_IF_EMPTY_HANDLE(
9243        isolate,
9244        JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9245  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9246    // Setting read only property in strict mode.
9247    Handle<Object> error =
9248      isolate->factory()->NewTypeError(
9249          "strict_cannot_assign", HandleVector(&name, 1));
9250    return isolate->Throw(*error);
9251  }
9252  return *value;
9253}
9254
9255
9256RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9257  HandleScope scope(isolate);
9258  ASSERT(args.length() == 1);
9259
9260  return isolate->Throw(args[0]);
9261}
9262
9263
9264RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9265  HandleScope scope(isolate);
9266  ASSERT(args.length() == 1);
9267
9268  return isolate->ReThrow(args[0]);
9269}
9270
9271
9272RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9273  SealHandleScope shs(isolate);
9274  ASSERT_EQ(0, args.length());
9275  return isolate->PromoteScheduledException();
9276}
9277
9278
9279RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9280  HandleScope scope(isolate);
9281  ASSERT(args.length() == 1);
9282
9283  Handle<Object> name(args[0], isolate);
9284  Handle<Object> reference_error =
9285    isolate->factory()->NewReferenceError("not_defined",
9286                                          HandleVector(&name, 1));
9287  return isolate->Throw(*reference_error);
9288}
9289
9290
9291RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
9292  HandleScope scope(isolate);
9293  ASSERT(args.length() == 0);
9294  return isolate->Throw(*isolate->factory()->NewTypeError(
9295      "not_date_object", HandleVector<Object>(NULL, 0)));
9296}
9297
9298
9299
9300RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9301  SealHandleScope shs(isolate);
9302  ASSERT(args.length() == 0);
9303
9304  // First check if this is a real stack overflow.
9305  if (isolate->stack_guard()->IsStackOverflow()) {
9306    SealHandleScope shs(isolate);
9307    return isolate->StackOverflow();
9308  }
9309
9310  return Execution::HandleStackGuardInterrupt(isolate);
9311}
9312
9313
9314RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9315  SealHandleScope shs(isolate);
9316  ASSERT(args.length() == 0);
9317  return Execution::HandleStackGuardInterrupt(isolate);
9318}
9319
9320
9321static int StackSize(Isolate* isolate) {
9322  int n = 0;
9323  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9324  return n;
9325}
9326
9327
9328static void PrintTransition(Isolate* isolate, Object* result) {
9329  // indentation
9330  { const int nmax = 80;
9331    int n = StackSize(isolate);
9332    if (n <= nmax)
9333      PrintF("%4d:%*s", n, n, "");
9334    else
9335      PrintF("%4d:%*s", n, nmax, "...");
9336  }
9337
9338  if (result == NULL) {
9339    JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9340    PrintF(" {\n");
9341  } else {
9342    // function result
9343    PrintF("} -> ");
9344    result->ShortPrint();
9345    PrintF("\n");
9346  }
9347}
9348
9349
9350RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9351  SealHandleScope shs(isolate);
9352  ASSERT(args.length() == 0);
9353  PrintTransition(isolate, NULL);
9354  return isolate->heap()->undefined_value();
9355}
9356
9357
9358RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9359  SealHandleScope shs(isolate);
9360  PrintTransition(isolate, args[0]);
9361  return args[0];  // return TOS
9362}
9363
9364
9365RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9366  SealHandleScope shs(isolate);
9367  ASSERT(args.length() == 1);
9368
9369#ifdef DEBUG
9370  if (args[0]->IsString()) {
9371    // If we have a string, assume it's a code "marker"
9372    // and print some interesting cpu debugging info.
9373    JavaScriptFrameIterator it(isolate);
9374    JavaScriptFrame* frame = it.frame();
9375    PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9376           frame->fp(), frame->sp(), frame->caller_sp());
9377  } else {
9378    PrintF("DebugPrint: ");
9379  }
9380  args[0]->Print();
9381  if (args[0]->IsHeapObject()) {
9382    PrintF("\n");
9383    HeapObject::cast(args[0])->map()->Print();
9384  }
9385#else
9386  // ShortPrint is available in release mode. Print is not.
9387  args[0]->ShortPrint();
9388#endif
9389  PrintF("\n");
9390  Flush();
9391
9392  return args[0];  // return TOS
9393}
9394
9395
9396RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9397  SealHandleScope shs(isolate);
9398  ASSERT(args.length() == 0);
9399  isolate->PrintStack(stdout);
9400  return isolate->heap()->undefined_value();
9401}
9402
9403
9404RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9405  SealHandleScope shs(isolate);
9406  ASSERT(args.length() == 0);
9407
9408  // According to ECMA-262, section 15.9.1, page 117, the precision of
9409  // the number in a Date object representing a particular instant in
9410  // time is milliseconds. Therefore, we floor the result of getting
9411  // the OS time.
9412  double millis = floor(OS::TimeCurrentMillis());
9413  return isolate->heap()->NumberFromDouble(millis);
9414}
9415
9416
9417RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9418  HandleScope scope(isolate);
9419  ASSERT(args.length() == 2);
9420
9421  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9422  FlattenString(str);
9423
9424  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9425
9426  MaybeObject* maybe_result_array =
9427      output->EnsureCanContainHeapObjectElements();
9428  if (maybe_result_array->IsFailure()) return maybe_result_array;
9429  RUNTIME_ASSERT(output->HasFastObjectElements());
9430
9431  DisallowHeapAllocation no_gc;
9432
9433  FixedArray* output_array = FixedArray::cast(output->elements());
9434  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9435  bool result;
9436  String::FlatContent str_content = str->GetFlatContent();
9437  if (str_content.IsAscii()) {
9438    result = DateParser::Parse(str_content.ToOneByteVector(),
9439                               output_array,
9440                               isolate->unicode_cache());
9441  } else {
9442    ASSERT(str_content.IsTwoByte());
9443    result = DateParser::Parse(str_content.ToUC16Vector(),
9444                               output_array,
9445                               isolate->unicode_cache());
9446  }
9447
9448  if (result) {
9449    return *output;
9450  } else {
9451    return isolate->heap()->null_value();
9452  }
9453}
9454
9455
9456RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9457  SealHandleScope shs(isolate);
9458  ASSERT(args.length() == 1);
9459
9460  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9461  int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9462  const char* zone = OS::LocalTimezone(static_cast<double>(time));
9463  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9464}
9465
9466
9467RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9468  SealHandleScope shs(isolate);
9469  ASSERT(args.length() == 1);
9470
9471  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9472  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9473
9474  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9475}
9476
9477
9478RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9479  SealHandleScope shs(isolate);
9480  ASSERT(args.length() == 1);
9481  Object* global = args[0];
9482  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9483  return JSGlobalObject::cast(global)->global_receiver();
9484}
9485
9486
9487RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9488  HandleScope scope(isolate);
9489  ASSERT_EQ(1, args.length());
9490  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9491
9492  source = Handle<String>(FlattenGetString(source));
9493  // Optimized fast case where we only have ASCII characters.
9494  Handle<Object> result;
9495  if (source->IsSeqOneByteString()) {
9496    result = JsonParser<true>::Parse(source);
9497  } else {
9498    result = JsonParser<false>::Parse(source);
9499  }
9500  if (result.is_null()) {
9501    // Syntax error or stack overflow in scanner.
9502    ASSERT(isolate->has_pending_exception());
9503    return Failure::Exception();
9504  }
9505  return *result;
9506}
9507
9508
9509bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9510                                      Handle<Context> context) {
9511  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9512  // Check with callback if set.
9513  AllowCodeGenerationFromStringsCallback callback =
9514      isolate->allow_code_gen_callback();
9515  if (callback == NULL) {
9516    // No callback set and code generation disallowed.
9517    return false;
9518  } else {
9519    // Callback set. Let it decide if code generation is allowed.
9520    VMState<EXTERNAL> state(isolate);
9521    return callback(v8::Utils::ToLocal(context));
9522  }
9523}
9524
9525
9526RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9527  HandleScope scope(isolate);
9528  ASSERT_EQ(2, args.length());
9529  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9530  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9531
9532  // Extract native context.
9533  Handle<Context> context(isolate->context()->native_context());
9534
9535  // Check if native context allows code generation from
9536  // strings. Throw an exception if it doesn't.
9537  if (context->allow_code_gen_from_strings()->IsFalse() &&
9538      !CodeGenerationFromStringsAllowed(isolate, context)) {
9539    Handle<Object> error_message =
9540        context->ErrorMessageForCodeGenerationFromStrings();
9541    return isolate->Throw(*isolate->factory()->NewEvalError(
9542        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9543  }
9544
9545  // Compile source string in the native context.
9546  ParseRestriction restriction = function_literal_only
9547      ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9548  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9549      source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
9550  RETURN_IF_EMPTY_HANDLE(isolate, shared);
9551  Handle<JSFunction> fun =
9552      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9553                                                            context,
9554                                                            NOT_TENURED);
9555  return *fun;
9556}
9557
9558
9559static ObjectPair CompileGlobalEval(Isolate* isolate,
9560                                    Handle<String> source,
9561                                    Handle<Object> receiver,
9562                                    LanguageMode language_mode,
9563                                    int scope_position) {
9564  Handle<Context> context = Handle<Context>(isolate->context());
9565  Handle<Context> native_context = Handle<Context>(context->native_context());
9566
9567  // Check if native context allows code generation from
9568  // strings. Throw an exception if it doesn't.
9569  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9570      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9571    Handle<Object> error_message =
9572        native_context->ErrorMessageForCodeGenerationFromStrings();
9573    isolate->Throw(*isolate->factory()->NewEvalError(
9574        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9575    return MakePair(Failure::Exception(), NULL);
9576  }
9577
9578  // Deal with a normal eval call with a string argument. Compile it
9579  // and return the compiled function bound in the local context.
9580  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9581      source,
9582      context,
9583      context->IsNativeContext(),
9584      language_mode,
9585      NO_PARSE_RESTRICTION,
9586      scope_position);
9587  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
9588                               MakePair(Failure::Exception(), NULL));
9589  Handle<JSFunction> compiled =
9590      isolate->factory()->NewFunctionFromSharedFunctionInfo(
9591          shared, context, NOT_TENURED);
9592  return MakePair(*compiled, *receiver);
9593}
9594
9595
9596RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9597  HandleScope scope(isolate);
9598  ASSERT(args.length() == 5);
9599
9600  Handle<Object> callee = args.at<Object>(0);
9601
9602  // If "eval" didn't refer to the original GlobalEval, it's not a
9603  // direct call to eval.
9604  // (And even if it is, but the first argument isn't a string, just let
9605  // execution default to an indirect call to eval, which will also return
9606  // the first argument without doing anything).
9607  if (*callee != isolate->native_context()->global_eval_fun() ||
9608      !args[1]->IsString()) {
9609    return MakePair(*callee, isolate->heap()->the_hole_value());
9610  }
9611
9612  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9613  ASSERT(args[4]->IsSmi());
9614  return CompileGlobalEval(isolate,
9615                           args.at<String>(1),
9616                           args.at<Object>(2),
9617                           language_mode,
9618                           args.smi_at(4));
9619}
9620
9621
9622static MaybeObject* Allocate(Isolate* isolate,
9623                             int size,
9624                             AllocationSpace space) {
9625  // Allocate a block of memory in the given space (filled with a filler).
9626  // Use as fallback for allocation in generated code when the space
9627  // is full.
9628  SealHandleScope shs(isolate);
9629  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9630  RUNTIME_ASSERT(size > 0);
9631  Heap* heap = isolate->heap();
9632  RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
9633  Object* allocation;
9634  { MaybeObject* maybe_allocation;
9635    if (space == NEW_SPACE) {
9636      maybe_allocation = heap->new_space()->AllocateRaw(size);
9637    } else {
9638      ASSERT(space == OLD_POINTER_SPACE || space == OLD_DATA_SPACE);
9639      maybe_allocation = heap->paged_space(space)->AllocateRaw(size);
9640    }
9641    if (maybe_allocation->ToObject(&allocation)) {
9642      heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9643    }
9644    return maybe_allocation;
9645  }
9646}
9647
9648
9649RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9650  SealHandleScope shs(isolate);
9651  ASSERT(args.length() == 1);
9652  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9653  return Allocate(isolate, size_smi->value(), NEW_SPACE);
9654}
9655
9656
9657RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldPointerSpace) {
9658  SealHandleScope shs(isolate);
9659  ASSERT(args.length() == 1);
9660  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9661  return Allocate(isolate, size_smi->value(), OLD_POINTER_SPACE);
9662}
9663
9664
9665RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldDataSpace) {
9666  SealHandleScope shs(isolate);
9667  ASSERT(args.length() == 1);
9668  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9669  return Allocate(isolate, size_smi->value(), OLD_DATA_SPACE);
9670}
9671
9672
9673// Push an object unto an array of objects if it is not already in the
9674// array.  Returns true if the element was pushed on the stack and
9675// false otherwise.
9676RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9677  SealHandleScope shs(isolate);
9678  ASSERT(args.length() == 2);
9679  CONVERT_ARG_CHECKED(JSArray, array, 0);
9680  CONVERT_ARG_CHECKED(JSReceiver, element, 1);
9681  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9682  int length = Smi::cast(array->length())->value();
9683  FixedArray* elements = FixedArray::cast(array->elements());
9684  for (int i = 0; i < length; i++) {
9685    if (elements->get(i) == element) return isolate->heap()->false_value();
9686  }
9687  Object* obj;
9688  // Strict not needed. Used for cycle detection in Array join implementation.
9689  { MaybeObject* maybe_obj =
9690        array->SetFastElement(length, element, kNonStrictMode, true);
9691    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9692  }
9693  return isolate->heap()->true_value();
9694}
9695
9696
9697/**
9698 * A simple visitor visits every element of Array's.
9699 * The backend storage can be a fixed array for fast elements case,
9700 * or a dictionary for sparse array. Since Dictionary is a subtype
9701 * of FixedArray, the class can be used by both fast and slow cases.
9702 * The second parameter of the constructor, fast_elements, specifies
9703 * whether the storage is a FixedArray or Dictionary.
9704 *
9705 * An index limit is used to deal with the situation that a result array
9706 * length overflows 32-bit non-negative integer.
9707 */
9708class ArrayConcatVisitor {
9709 public:
9710  ArrayConcatVisitor(Isolate* isolate,
9711                     Handle<FixedArray> storage,
9712                     bool fast_elements) :
9713      isolate_(isolate),
9714      storage_(Handle<FixedArray>::cast(
9715          isolate->global_handles()->Create(*storage))),
9716      index_offset_(0u),
9717      fast_elements_(fast_elements),
9718      exceeds_array_limit_(false) { }
9719
9720  ~ArrayConcatVisitor() {
9721    clear_storage();
9722  }
9723
9724  void visit(uint32_t i, Handle<Object> elm) {
9725    if (i > JSObject::kMaxElementCount - index_offset_) {
9726      exceeds_array_limit_ = true;
9727      return;
9728    }
9729    uint32_t index = index_offset_ + i;
9730
9731    if (fast_elements_) {
9732      if (index < static_cast<uint32_t>(storage_->length())) {
9733        storage_->set(index, *elm);
9734        return;
9735      }
9736      // Our initial estimate of length was foiled, possibly by
9737      // getters on the arrays increasing the length of later arrays
9738      // during iteration.
9739      // This shouldn't happen in anything but pathological cases.
9740      SetDictionaryMode(index);
9741      // Fall-through to dictionary mode.
9742    }
9743    ASSERT(!fast_elements_);
9744    Handle<SeededNumberDictionary> dict(
9745        SeededNumberDictionary::cast(*storage_));
9746    Handle<SeededNumberDictionary> result =
9747        isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9748    if (!result.is_identical_to(dict)) {
9749      // Dictionary needed to grow.
9750      clear_storage();
9751      set_storage(*result);
9752    }
9753  }
9754
9755  void increase_index_offset(uint32_t delta) {
9756    if (JSObject::kMaxElementCount - index_offset_ < delta) {
9757      index_offset_ = JSObject::kMaxElementCount;
9758    } else {
9759      index_offset_ += delta;
9760    }
9761  }
9762
9763  bool exceeds_array_limit() {
9764    return exceeds_array_limit_;
9765  }
9766
9767  Handle<JSArray> ToArray() {
9768    Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9769    Handle<Object> length =
9770        isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9771    Handle<Map> map;
9772    if (fast_elements_) {
9773      map = isolate_->factory()->GetElementsTransitionMap(array,
9774                                                          FAST_HOLEY_ELEMENTS);
9775    } else {
9776      map = isolate_->factory()->GetElementsTransitionMap(array,
9777                                                          DICTIONARY_ELEMENTS);
9778    }
9779    array->set_map(*map);
9780    array->set_length(*length);
9781    array->set_elements(*storage_);
9782    return array;
9783  }
9784
9785 private:
9786  // Convert storage to dictionary mode.
9787  void SetDictionaryMode(uint32_t index) {
9788    ASSERT(fast_elements_);
9789    Handle<FixedArray> current_storage(*storage_);
9790    Handle<SeededNumberDictionary> slow_storage(
9791        isolate_->factory()->NewSeededNumberDictionary(
9792            current_storage->length()));
9793    uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9794    for (uint32_t i = 0; i < current_length; i++) {
9795      HandleScope loop_scope(isolate_);
9796      Handle<Object> element(current_storage->get(i), isolate_);
9797      if (!element->IsTheHole()) {
9798        Handle<SeededNumberDictionary> new_storage =
9799          isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9800        if (!new_storage.is_identical_to(slow_storage)) {
9801          slow_storage = loop_scope.CloseAndEscape(new_storage);
9802        }
9803      }
9804    }
9805    clear_storage();
9806    set_storage(*slow_storage);
9807    fast_elements_ = false;
9808  }
9809
9810  inline void clear_storage() {
9811    isolate_->global_handles()->Destroy(
9812        Handle<Object>::cast(storage_).location());
9813  }
9814
9815  inline void set_storage(FixedArray* storage) {
9816    storage_ = Handle<FixedArray>::cast(
9817        isolate_->global_handles()->Create(storage));
9818  }
9819
9820  Isolate* isolate_;
9821  Handle<FixedArray> storage_;  // Always a global handle.
9822  // Index after last seen index. Always less than or equal to
9823  // JSObject::kMaxElementCount.
9824  uint32_t index_offset_;
9825  bool fast_elements_ : 1;
9826  bool exceeds_array_limit_ : 1;
9827};
9828
9829
9830static uint32_t EstimateElementCount(Handle<JSArray> array) {
9831  uint32_t length = static_cast<uint32_t>(array->length()->Number());
9832  int element_count = 0;
9833  switch (array->GetElementsKind()) {
9834    case FAST_SMI_ELEMENTS:
9835    case FAST_HOLEY_SMI_ELEMENTS:
9836    case FAST_ELEMENTS:
9837    case FAST_HOLEY_ELEMENTS: {
9838      // Fast elements can't have lengths that are not representable by
9839      // a 32-bit signed integer.
9840      ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9841      int fast_length = static_cast<int>(length);
9842      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9843      for (int i = 0; i < fast_length; i++) {
9844        if (!elements->get(i)->IsTheHole()) element_count++;
9845      }
9846      break;
9847    }
9848    case FAST_DOUBLE_ELEMENTS:
9849    case FAST_HOLEY_DOUBLE_ELEMENTS: {
9850      // Fast elements can't have lengths that are not representable by
9851      // a 32-bit signed integer.
9852      ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
9853      int fast_length = static_cast<int>(length);
9854      if (array->elements()->IsFixedArray()) {
9855        ASSERT(FixedArray::cast(array->elements())->length() == 0);
9856        break;
9857      }
9858      Handle<FixedDoubleArray> elements(
9859          FixedDoubleArray::cast(array->elements()));
9860      for (int i = 0; i < fast_length; i++) {
9861        if (!elements->is_the_hole(i)) element_count++;
9862      }
9863      break;
9864    }
9865    case DICTIONARY_ELEMENTS: {
9866      Handle<SeededNumberDictionary> dictionary(
9867          SeededNumberDictionary::cast(array->elements()));
9868      int capacity = dictionary->Capacity();
9869      for (int i = 0; i < capacity; i++) {
9870        Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
9871        if (dictionary->IsKey(*key)) {
9872          element_count++;
9873        }
9874      }
9875      break;
9876    }
9877    case NON_STRICT_ARGUMENTS_ELEMENTS:
9878    case EXTERNAL_BYTE_ELEMENTS:
9879    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9880    case EXTERNAL_SHORT_ELEMENTS:
9881    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9882    case EXTERNAL_INT_ELEMENTS:
9883    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9884    case EXTERNAL_FLOAT_ELEMENTS:
9885    case EXTERNAL_DOUBLE_ELEMENTS:
9886    case EXTERNAL_PIXEL_ELEMENTS:
9887      // External arrays are always dense.
9888      return length;
9889  }
9890  // As an estimate, we assume that the prototype doesn't contain any
9891  // inherited elements.
9892  return element_count;
9893}
9894
9895
9896
9897template<class ExternalArrayClass, class ElementType>
9898static void IterateExternalArrayElements(Isolate* isolate,
9899                                         Handle<JSObject> receiver,
9900                                         bool elements_are_ints,
9901                                         bool elements_are_guaranteed_smis,
9902                                         ArrayConcatVisitor* visitor) {
9903  Handle<ExternalArrayClass> array(
9904      ExternalArrayClass::cast(receiver->elements()));
9905  uint32_t len = static_cast<uint32_t>(array->length());
9906
9907  ASSERT(visitor != NULL);
9908  if (elements_are_ints) {
9909    if (elements_are_guaranteed_smis) {
9910      for (uint32_t j = 0; j < len; j++) {
9911        HandleScope loop_scope(isolate);
9912        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
9913                      isolate);
9914        visitor->visit(j, e);
9915      }
9916    } else {
9917      for (uint32_t j = 0; j < len; j++) {
9918        HandleScope loop_scope(isolate);
9919        int64_t val = static_cast<int64_t>(array->get_scalar(j));
9920        if (Smi::IsValid(static_cast<intptr_t>(val))) {
9921          Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
9922          visitor->visit(j, e);
9923        } else {
9924          Handle<Object> e =
9925              isolate->factory()->NewNumber(static_cast<ElementType>(val));
9926          visitor->visit(j, e);
9927        }
9928      }
9929    }
9930  } else {
9931    for (uint32_t j = 0; j < len; j++) {
9932      HandleScope loop_scope(isolate);
9933      Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9934      visitor->visit(j, e);
9935    }
9936  }
9937}
9938
9939
9940// Used for sorting indices in a List<uint32_t>.
9941static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9942  uint32_t a = *ap;
9943  uint32_t b = *bp;
9944  return (a == b) ? 0 : (a < b) ? -1 : 1;
9945}
9946
9947
9948static void CollectElementIndices(Handle<JSObject> object,
9949                                  uint32_t range,
9950                                  List<uint32_t>* indices) {
9951  Isolate* isolate = object->GetIsolate();
9952  ElementsKind kind = object->GetElementsKind();
9953  switch (kind) {
9954    case FAST_SMI_ELEMENTS:
9955    case FAST_ELEMENTS:
9956    case FAST_HOLEY_SMI_ELEMENTS:
9957    case FAST_HOLEY_ELEMENTS: {
9958      Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9959      uint32_t length = static_cast<uint32_t>(elements->length());
9960      if (range < length) length = range;
9961      for (uint32_t i = 0; i < length; i++) {
9962        if (!elements->get(i)->IsTheHole()) {
9963          indices->Add(i);
9964        }
9965      }
9966      break;
9967    }
9968    case FAST_HOLEY_DOUBLE_ELEMENTS:
9969    case FAST_DOUBLE_ELEMENTS: {
9970      // TODO(1810): Decide if it's worthwhile to implement this.
9971      UNREACHABLE();
9972      break;
9973    }
9974    case DICTIONARY_ELEMENTS: {
9975      Handle<SeededNumberDictionary> dict(
9976          SeededNumberDictionary::cast(object->elements()));
9977      uint32_t capacity = dict->Capacity();
9978      for (uint32_t j = 0; j < capacity; j++) {
9979        HandleScope loop_scope(isolate);
9980        Handle<Object> k(dict->KeyAt(j), isolate);
9981        if (dict->IsKey(*k)) {
9982          ASSERT(k->IsNumber());
9983          uint32_t index = static_cast<uint32_t>(k->Number());
9984          if (index < range) {
9985            indices->Add(index);
9986          }
9987        }
9988      }
9989      break;
9990    }
9991    default: {
9992      int dense_elements_length;
9993      switch (kind) {
9994        case EXTERNAL_PIXEL_ELEMENTS: {
9995          dense_elements_length =
9996              ExternalPixelArray::cast(object->elements())->length();
9997          break;
9998        }
9999        case EXTERNAL_BYTE_ELEMENTS: {
10000          dense_elements_length =
10001              ExternalByteArray::cast(object->elements())->length();
10002          break;
10003        }
10004        case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10005          dense_elements_length =
10006              ExternalUnsignedByteArray::cast(object->elements())->length();
10007          break;
10008        }
10009        case EXTERNAL_SHORT_ELEMENTS: {
10010          dense_elements_length =
10011              ExternalShortArray::cast(object->elements())->length();
10012          break;
10013        }
10014        case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10015          dense_elements_length =
10016              ExternalUnsignedShortArray::cast(object->elements())->length();
10017          break;
10018        }
10019        case EXTERNAL_INT_ELEMENTS: {
10020          dense_elements_length =
10021              ExternalIntArray::cast(object->elements())->length();
10022          break;
10023        }
10024        case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10025          dense_elements_length =
10026              ExternalUnsignedIntArray::cast(object->elements())->length();
10027          break;
10028        }
10029        case EXTERNAL_FLOAT_ELEMENTS: {
10030          dense_elements_length =
10031              ExternalFloatArray::cast(object->elements())->length();
10032          break;
10033        }
10034        case EXTERNAL_DOUBLE_ELEMENTS: {
10035          dense_elements_length =
10036              ExternalDoubleArray::cast(object->elements())->length();
10037          break;
10038        }
10039        default:
10040          UNREACHABLE();
10041          dense_elements_length = 0;
10042          break;
10043      }
10044      uint32_t length = static_cast<uint32_t>(dense_elements_length);
10045      if (range <= length) {
10046        length = range;
10047        // We will add all indices, so we might as well clear it first
10048        // and avoid duplicates.
10049        indices->Clear();
10050      }
10051      for (uint32_t i = 0; i < length; i++) {
10052        indices->Add(i);
10053      }
10054      if (length == range) return;  // All indices accounted for already.
10055      break;
10056    }
10057  }
10058
10059  Handle<Object> prototype(object->GetPrototype(), isolate);
10060  if (prototype->IsJSObject()) {
10061    // The prototype will usually have no inherited element indices,
10062    // but we have to check.
10063    CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10064  }
10065}
10066
10067
10068/**
10069 * A helper function that visits elements of a JSArray in numerical
10070 * order.
10071 *
10072 * The visitor argument called for each existing element in the array
10073 * with the element index and the element's value.
10074 * Afterwards it increments the base-index of the visitor by the array
10075 * length.
10076 * Returns false if any access threw an exception, otherwise true.
10077 */
10078static bool IterateElements(Isolate* isolate,
10079                            Handle<JSArray> receiver,
10080                            ArrayConcatVisitor* visitor) {
10081  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10082  switch (receiver->GetElementsKind()) {
10083    case FAST_SMI_ELEMENTS:
10084    case FAST_ELEMENTS:
10085    case FAST_HOLEY_SMI_ELEMENTS:
10086    case FAST_HOLEY_ELEMENTS: {
10087      // Run through the elements FixedArray and use HasElement and GetElement
10088      // to check the prototype for missing elements.
10089      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10090      int fast_length = static_cast<int>(length);
10091      ASSERT(fast_length <= elements->length());
10092      for (int j = 0; j < fast_length; j++) {
10093        HandleScope loop_scope(isolate);
10094        Handle<Object> element_value(elements->get(j), isolate);
10095        if (!element_value->IsTheHole()) {
10096          visitor->visit(j, element_value);
10097        } else if (receiver->HasElement(j)) {
10098          // Call GetElement on receiver, not its prototype, or getters won't
10099          // have the correct receiver.
10100          element_value = Object::GetElement(receiver, j);
10101          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10102          visitor->visit(j, element_value);
10103        }
10104      }
10105      break;
10106    }
10107    case FAST_HOLEY_DOUBLE_ELEMENTS:
10108    case FAST_DOUBLE_ELEMENTS: {
10109      // Run through the elements FixedArray and use HasElement and GetElement
10110      // to check the prototype for missing elements.
10111      Handle<FixedDoubleArray> elements(
10112          FixedDoubleArray::cast(receiver->elements()));
10113      int fast_length = static_cast<int>(length);
10114      ASSERT(fast_length <= elements->length());
10115      for (int j = 0; j < fast_length; j++) {
10116        HandleScope loop_scope(isolate);
10117        if (!elements->is_the_hole(j)) {
10118          double double_value = elements->get_scalar(j);
10119          Handle<Object> element_value =
10120              isolate->factory()->NewNumber(double_value);
10121          visitor->visit(j, element_value);
10122        } else if (receiver->HasElement(j)) {
10123          // Call GetElement on receiver, not its prototype, or getters won't
10124          // have the correct receiver.
10125          Handle<Object> element_value = Object::GetElement(receiver, j);
10126          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10127          visitor->visit(j, element_value);
10128        }
10129      }
10130      break;
10131    }
10132    case DICTIONARY_ELEMENTS: {
10133      Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10134      List<uint32_t> indices(dict->Capacity() / 2);
10135      // Collect all indices in the object and the prototypes less
10136      // than length. This might introduce duplicates in the indices list.
10137      CollectElementIndices(receiver, length, &indices);
10138      indices.Sort(&compareUInt32);
10139      int j = 0;
10140      int n = indices.length();
10141      while (j < n) {
10142        HandleScope loop_scope(isolate);
10143        uint32_t index = indices[j];
10144        Handle<Object> element = Object::GetElement(receiver, index);
10145        RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10146        visitor->visit(index, element);
10147        // Skip to next different index (i.e., omit duplicates).
10148        do {
10149          j++;
10150        } while (j < n && indices[j] == index);
10151      }
10152      break;
10153    }
10154    case EXTERNAL_PIXEL_ELEMENTS: {
10155      Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
10156          receiver->elements()));
10157      for (uint32_t j = 0; j < length; j++) {
10158        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10159        visitor->visit(j, e);
10160      }
10161      break;
10162    }
10163    case EXTERNAL_BYTE_ELEMENTS: {
10164      IterateExternalArrayElements<ExternalByteArray, int8_t>(
10165          isolate, receiver, true, true, visitor);
10166      break;
10167    }
10168    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10169      IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
10170          isolate, receiver, true, true, visitor);
10171      break;
10172    }
10173    case EXTERNAL_SHORT_ELEMENTS: {
10174      IterateExternalArrayElements<ExternalShortArray, int16_t>(
10175          isolate, receiver, true, true, visitor);
10176      break;
10177    }
10178    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10179      IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
10180          isolate, receiver, true, true, visitor);
10181      break;
10182    }
10183    case EXTERNAL_INT_ELEMENTS: {
10184      IterateExternalArrayElements<ExternalIntArray, int32_t>(
10185          isolate, receiver, true, false, visitor);
10186      break;
10187    }
10188    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10189      IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
10190          isolate, receiver, true, false, visitor);
10191      break;
10192    }
10193    case EXTERNAL_FLOAT_ELEMENTS: {
10194      IterateExternalArrayElements<ExternalFloatArray, float>(
10195          isolate, receiver, false, false, visitor);
10196      break;
10197    }
10198    case EXTERNAL_DOUBLE_ELEMENTS: {
10199      IterateExternalArrayElements<ExternalDoubleArray, double>(
10200          isolate, receiver, false, false, visitor);
10201      break;
10202    }
10203    default:
10204      UNREACHABLE();
10205      break;
10206  }
10207  visitor->increase_index_offset(length);
10208  return true;
10209}
10210
10211
10212/**
10213 * Array::concat implementation.
10214 * See ECMAScript 262, 15.4.4.4.
10215 * TODO(581): Fix non-compliance for very large concatenations and update to
10216 * following the ECMAScript 5 specification.
10217 */
10218RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10219  HandleScope handle_scope(isolate);
10220  ASSERT(args.length() == 1);
10221
10222  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10223  int argument_count = static_cast<int>(arguments->length()->Number());
10224  RUNTIME_ASSERT(arguments->HasFastObjectElements());
10225  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10226
10227  // Pass 1: estimate the length and number of elements of the result.
10228  // The actual length can be larger if any of the arguments have getters
10229  // that mutate other arguments (but will otherwise be precise).
10230  // The number of elements is precise if there are no inherited elements.
10231
10232  ElementsKind kind = FAST_SMI_ELEMENTS;
10233
10234  uint32_t estimate_result_length = 0;
10235  uint32_t estimate_nof_elements = 0;
10236  for (int i = 0; i < argument_count; i++) {
10237    HandleScope loop_scope(isolate);
10238    Handle<Object> obj(elements->get(i), isolate);
10239    uint32_t length_estimate;
10240    uint32_t element_estimate;
10241    if (obj->IsJSArray()) {
10242      Handle<JSArray> array(Handle<JSArray>::cast(obj));
10243      length_estimate = static_cast<uint32_t>(array->length()->Number());
10244      if (length_estimate != 0) {
10245        ElementsKind array_kind =
10246            GetPackedElementsKind(array->map()->elements_kind());
10247        if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10248          kind = array_kind;
10249        }
10250      }
10251      element_estimate = EstimateElementCount(array);
10252    } else {
10253      if (obj->IsHeapObject()) {
10254        if (obj->IsNumber()) {
10255          if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10256            kind = FAST_DOUBLE_ELEMENTS;
10257          }
10258        } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10259          kind = FAST_ELEMENTS;
10260        }
10261      }
10262      length_estimate = 1;
10263      element_estimate = 1;
10264    }
10265    // Avoid overflows by capping at kMaxElementCount.
10266    if (JSObject::kMaxElementCount - estimate_result_length <
10267        length_estimate) {
10268      estimate_result_length = JSObject::kMaxElementCount;
10269    } else {
10270      estimate_result_length += length_estimate;
10271    }
10272    if (JSObject::kMaxElementCount - estimate_nof_elements <
10273        element_estimate) {
10274      estimate_nof_elements = JSObject::kMaxElementCount;
10275    } else {
10276      estimate_nof_elements += element_estimate;
10277    }
10278  }
10279
10280  // If estimated number of elements is more than half of length, a
10281  // fixed array (fast case) is more time and space-efficient than a
10282  // dictionary.
10283  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10284
10285  Handle<FixedArray> storage;
10286  if (fast_case) {
10287    if (kind == FAST_DOUBLE_ELEMENTS) {
10288      Handle<FixedDoubleArray> double_storage =
10289          isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10290      int j = 0;
10291      bool failure = false;
10292      for (int i = 0; i < argument_count; i++) {
10293        Handle<Object> obj(elements->get(i), isolate);
10294        if (obj->IsSmi()) {
10295          double_storage->set(j, Smi::cast(*obj)->value());
10296          j++;
10297        } else if (obj->IsNumber()) {
10298          double_storage->set(j, obj->Number());
10299          j++;
10300        } else {
10301          JSArray* array = JSArray::cast(*obj);
10302          uint32_t length = static_cast<uint32_t>(array->length()->Number());
10303          switch (array->map()->elements_kind()) {
10304            case FAST_HOLEY_DOUBLE_ELEMENTS:
10305            case FAST_DOUBLE_ELEMENTS: {
10306              // Empty fixed array indicates that there are no elements.
10307              if (array->elements()->IsFixedArray()) break;
10308              FixedDoubleArray* elements =
10309                  FixedDoubleArray::cast(array->elements());
10310              for (uint32_t i = 0; i < length; i++) {
10311                if (elements->is_the_hole(i)) {
10312                  failure = true;
10313                  break;
10314                }
10315                double double_value = elements->get_scalar(i);
10316                double_storage->set(j, double_value);
10317                j++;
10318              }
10319              break;
10320            }
10321            case FAST_HOLEY_SMI_ELEMENTS:
10322            case FAST_SMI_ELEMENTS: {
10323              FixedArray* elements(
10324                  FixedArray::cast(array->elements()));
10325              for (uint32_t i = 0; i < length; i++) {
10326                Object* element = elements->get(i);
10327                if (element->IsTheHole()) {
10328                  failure = true;
10329                  break;
10330                }
10331                int32_t int_value = Smi::cast(element)->value();
10332                double_storage->set(j, int_value);
10333                j++;
10334              }
10335              break;
10336            }
10337            case FAST_HOLEY_ELEMENTS:
10338              ASSERT_EQ(0, length);
10339              break;
10340            default:
10341              UNREACHABLE();
10342          }
10343        }
10344        if (failure) break;
10345      }
10346      Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10347      Smi* length = Smi::FromInt(j);
10348      Handle<Map> map;
10349      map = isolate->factory()->GetElementsTransitionMap(array, kind);
10350      array->set_map(*map);
10351      array->set_length(length);
10352      array->set_elements(*double_storage);
10353      return *array;
10354    }
10355    // The backing storage array must have non-existing elements to preserve
10356    // holes across concat operations.
10357    storage = isolate->factory()->NewFixedArrayWithHoles(
10358        estimate_result_length);
10359  } else {
10360    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10361    uint32_t at_least_space_for = estimate_nof_elements +
10362                                  (estimate_nof_elements >> 2);
10363    storage = Handle<FixedArray>::cast(
10364        isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10365  }
10366
10367  ArrayConcatVisitor visitor(isolate, storage, fast_case);
10368
10369  for (int i = 0; i < argument_count; i++) {
10370    Handle<Object> obj(elements->get(i), isolate);
10371    if (obj->IsJSArray()) {
10372      Handle<JSArray> array = Handle<JSArray>::cast(obj);
10373      if (!IterateElements(isolate, array, &visitor)) {
10374        return Failure::Exception();
10375      }
10376    } else {
10377      visitor.visit(0, obj);
10378      visitor.increase_index_offset(1);
10379    }
10380  }
10381
10382  if (visitor.exceeds_array_limit()) {
10383    return isolate->Throw(
10384        *isolate->factory()->NewRangeError("invalid_array_length",
10385                                           HandleVector<Object>(NULL, 0)));
10386  }
10387  return *visitor.ToArray();
10388}
10389
10390
10391// This will not allocate (flatten the string), but it may run
10392// very slowly for very deeply nested ConsStrings.  For debugging use only.
10393RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10394  SealHandleScope shs(isolate);
10395  ASSERT(args.length() == 1);
10396
10397  CONVERT_ARG_CHECKED(String, string, 0);
10398  ConsStringIteratorOp op;
10399  StringCharacterStream stream(string, &op);
10400  while (stream.HasMore()) {
10401    uint16_t character = stream.GetNext();
10402    PrintF("%c", character);
10403  }
10404  return string;
10405}
10406
10407
10408// Moves all own elements of an object, that are below a limit, to positions
10409// starting at zero. All undefined values are placed after non-undefined values,
10410// and are followed by non-existing element. Does not change the length
10411// property.
10412// Returns the number of non-undefined elements collected.
10413RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10414  SealHandleScope shs(isolate);
10415  ASSERT(args.length() == 2);
10416  CONVERT_ARG_CHECKED(JSObject, object, 0);
10417  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10418  return object->PrepareElementsForSort(limit);
10419}
10420
10421
10422// Move contents of argument 0 (an array) to argument 1 (an array)
10423RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10424  SealHandleScope shs(isolate);
10425  ASSERT(args.length() == 2);
10426  CONVERT_ARG_CHECKED(JSArray, from, 0);
10427  CONVERT_ARG_CHECKED(JSArray, to, 1);
10428  from->ValidateElements();
10429  to->ValidateElements();
10430  FixedArrayBase* new_elements = from->elements();
10431  ElementsKind from_kind = from->GetElementsKind();
10432  MaybeObject* maybe_new_map;
10433  maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10434  Object* new_map;
10435  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10436  to->set_map_and_elements(Map::cast(new_map), new_elements);
10437  to->set_length(from->length());
10438  Object* obj;
10439  { MaybeObject* maybe_obj = from->ResetElements();
10440    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10441  }
10442  from->set_length(Smi::FromInt(0));
10443  to->ValidateElements();
10444  return to;
10445}
10446
10447
10448// How many elements does this object/array have?
10449RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10450  SealHandleScope shs(isolate);
10451  ASSERT(args.length() == 1);
10452  CONVERT_ARG_CHECKED(JSObject, object, 0);
10453  HeapObject* elements = object->elements();
10454  if (elements->IsDictionary()) {
10455    int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10456    return Smi::FromInt(result);
10457  } else if (object->IsJSArray()) {
10458    return JSArray::cast(object)->length();
10459  } else {
10460    return Smi::FromInt(FixedArray::cast(elements)->length());
10461  }
10462}
10463
10464
10465// Returns an array that tells you where in the [0, length) interval an array
10466// might have elements.  Can either return an array of keys (positive integers
10467// or undefined) or a number representing the positive length of an interval
10468// starting at index 0.
10469// Intervals can span over some keys that are not in the object.
10470RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10471  HandleScope scope(isolate);
10472  ASSERT(args.length() == 2);
10473  CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10474  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10475  if (array->elements()->IsDictionary()) {
10476    Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10477    for (Handle<Object> p = array;
10478         !p->IsNull();
10479         p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10480      if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10481        // Bail out if we find a proxy or interceptor, likely not worth
10482        // collecting keys in that case.
10483        return *isolate->factory()->NewNumberFromUint(length);
10484      }
10485      Handle<JSObject> current = Handle<JSObject>::cast(p);
10486      Handle<FixedArray> current_keys =
10487          isolate->factory()->NewFixedArray(
10488              current->NumberOfLocalElements(NONE));
10489      current->GetLocalElementKeys(*current_keys, NONE);
10490      keys = UnionOfKeys(keys, current_keys);
10491    }
10492    // Erase any keys >= length.
10493    // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10494    // is changed to let this happen on the JS side.
10495    for (int i = 0; i < keys->length(); i++) {
10496      if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10497    }
10498    return *isolate->factory()->NewJSArrayWithElements(keys);
10499  } else {
10500    ASSERT(array->HasFastSmiOrObjectElements() ||
10501           array->HasFastDoubleElements());
10502    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10503    return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10504  }
10505}
10506
10507
10508RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10509  SealHandleScope shs(isolate);
10510  ASSERT(args.length() == 3);
10511  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
10512  CONVERT_ARG_CHECKED(Name, name, 1);
10513  CONVERT_SMI_ARG_CHECKED(flag, 2);
10514  AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10515  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10516  return JSObject::cast(receiver)->LookupAccessor(name, component);
10517}
10518
10519
10520#ifdef ENABLE_DEBUGGER_SUPPORT
10521RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10522  SealHandleScope shs(isolate);
10523  ASSERT(args.length() == 0);
10524  return Execution::DebugBreakHelper();
10525}
10526
10527
10528// Helper functions for wrapping and unwrapping stack frame ids.
10529static Smi* WrapFrameId(StackFrame::Id id) {
10530  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10531  return Smi::FromInt(id >> 2);
10532}
10533
10534
10535static StackFrame::Id UnwrapFrameId(int wrapped) {
10536  return static_cast<StackFrame::Id>(wrapped << 2);
10537}
10538
10539
10540// Adds a JavaScript function as a debug event listener.
10541// args[0]: debug event listener function to set or null or undefined for
10542//          clearing the event listener function
10543// args[1]: object supplied during callback
10544RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10545  SealHandleScope shs(isolate);
10546  ASSERT(args.length() == 2);
10547  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10548                 args[0]->IsUndefined() ||
10549                 args[0]->IsNull());
10550  Handle<Object> callback = args.at<Object>(0);
10551  Handle<Object> data = args.at<Object>(1);
10552  isolate->debugger()->SetEventListener(callback, data);
10553
10554  return isolate->heap()->undefined_value();
10555}
10556
10557
10558RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10559  SealHandleScope shs(isolate);
10560  ASSERT(args.length() == 0);
10561  isolate->stack_guard()->DebugBreak();
10562  return isolate->heap()->undefined_value();
10563}
10564
10565
10566static MaybeObject* DebugLookupResultValue(Heap* heap,
10567                                           Object* receiver,
10568                                           Name* name,
10569                                           LookupResult* result,
10570                                           bool* caught_exception) {
10571  Object* value;
10572  switch (result->type()) {
10573    case NORMAL:
10574      value = result->holder()->GetNormalizedProperty(result);
10575      if (value->IsTheHole()) {
10576        return heap->undefined_value();
10577      }
10578      return value;
10579    case FIELD: {
10580      Object* value;
10581      MaybeObject* maybe_value =
10582          JSObject::cast(result->holder())->FastPropertyAt(
10583              result->representation(),
10584              result->GetFieldIndex().field_index());
10585      if (!maybe_value->To(&value)) return maybe_value;
10586      if (value->IsTheHole()) {
10587        return heap->undefined_value();
10588      }
10589      return value;
10590    }
10591    case CONSTANT:
10592      return result->GetConstant();
10593    case CALLBACKS: {
10594      Object* structure = result->GetCallbackObject();
10595      if (structure->IsForeign() || structure->IsAccessorInfo()) {
10596        MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10597            receiver, structure, name);
10598        if (!maybe_value->ToObject(&value)) {
10599          if (maybe_value->IsRetryAfterGC()) return maybe_value;
10600          ASSERT(maybe_value->IsException());
10601          maybe_value = heap->isolate()->pending_exception();
10602          heap->isolate()->clear_pending_exception();
10603          if (caught_exception != NULL) {
10604            *caught_exception = true;
10605          }
10606          return maybe_value;
10607        }
10608        return value;
10609      } else {
10610        return heap->undefined_value();
10611      }
10612    }
10613    case INTERCEPTOR:
10614    case TRANSITION:
10615      return heap->undefined_value();
10616    case HANDLER:
10617    case NONEXISTENT:
10618      UNREACHABLE();
10619      return heap->undefined_value();
10620  }
10621  UNREACHABLE();  // keep the compiler happy
10622  return heap->undefined_value();
10623}
10624
10625
10626// Get debugger related details for an object property.
10627// args[0]: object holding property
10628// args[1]: name of the property
10629//
10630// The array returned contains the following information:
10631// 0: Property value
10632// 1: Property details
10633// 2: Property value is exception
10634// 3: Getter function if defined
10635// 4: Setter function if defined
10636// Items 2-4 are only filled if the property has either a getter or a setter
10637// defined through __defineGetter__ and/or __defineSetter__.
10638RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10639  HandleScope scope(isolate);
10640
10641  ASSERT(args.length() == 2);
10642
10643  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10644  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10645
10646  // Make sure to set the current context to the context before the debugger was
10647  // entered (if the debugger is entered). The reason for switching context here
10648  // is that for some property lookups (accessors and interceptors) callbacks
10649  // into the embedding application can occour, and the embedding application
10650  // could have the assumption that its own native context is the current
10651  // context and not some internal debugger context.
10652  SaveContext save(isolate);
10653  if (isolate->debug()->InDebugger()) {
10654    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10655  }
10656
10657  // Skip the global proxy as it has no properties and always delegates to the
10658  // real global object.
10659  if (obj->IsJSGlobalProxy()) {
10660    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10661  }
10662
10663
10664  // Check if the name is trivially convertible to an index and get the element
10665  // if so.
10666  uint32_t index;
10667  if (name->AsArrayIndex(&index)) {
10668    Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10669    Object* element_or_char;
10670    { MaybeObject* maybe_element_or_char =
10671          Runtime::GetElementOrCharAt(isolate, obj, index);
10672      if (!maybe_element_or_char->ToObject(&element_or_char)) {
10673        return maybe_element_or_char;
10674      }
10675    }
10676    details->set(0, element_or_char);
10677    details->set(
10678        1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10679    return *isolate->factory()->NewJSArrayWithElements(details);
10680  }
10681
10682  // Find the number of objects making up this.
10683  int length = LocalPrototypeChainLength(*obj);
10684
10685  // Try local lookup on each of the objects.
10686  Handle<JSObject> jsproto = obj;
10687  for (int i = 0; i < length; i++) {
10688    LookupResult result(isolate);
10689    jsproto->LocalLookup(*name, &result);
10690    if (result.IsFound()) {
10691      // LookupResult is not GC safe as it holds raw object pointers.
10692      // GC can happen later in this code so put the required fields into
10693      // local variables using handles when required for later use.
10694      Handle<Object> result_callback_obj;
10695      if (result.IsPropertyCallbacks()) {
10696        result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10697                                             isolate);
10698      }
10699      Smi* property_details = result.GetPropertyDetails().AsSmi();
10700      // DebugLookupResultValue can cause GC so details from LookupResult needs
10701      // to be copied to handles before this.
10702      bool caught_exception = false;
10703      Object* raw_value;
10704      { MaybeObject* maybe_raw_value =
10705            DebugLookupResultValue(isolate->heap(), *obj, *name,
10706                                   &result, &caught_exception);
10707        if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10708      }
10709      Handle<Object> value(raw_value, isolate);
10710
10711      // If the callback object is a fixed array then it contains JavaScript
10712      // getter and/or setter.
10713      bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10714                                    result_callback_obj->IsAccessorPair();
10715      Handle<FixedArray> details =
10716          isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10717      details->set(0, *value);
10718      details->set(1, property_details);
10719      if (hasJavaScriptAccessors) {
10720        AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10721        details->set(2, isolate->heap()->ToBoolean(caught_exception));
10722        details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10723        details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10724      }
10725
10726      return *isolate->factory()->NewJSArrayWithElements(details);
10727    }
10728    if (i < length - 1) {
10729      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10730    }
10731  }
10732
10733  return isolate->heap()->undefined_value();
10734}
10735
10736
10737RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10738  HandleScope scope(isolate);
10739
10740  ASSERT(args.length() == 2);
10741
10742  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10743  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10744
10745  LookupResult result(isolate);
10746  obj->Lookup(*name, &result);
10747  if (result.IsFound()) {
10748    return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10749  }
10750  return isolate->heap()->undefined_value();
10751}
10752
10753
10754// Return the property type calculated from the property details.
10755// args[0]: smi with property details.
10756RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10757  SealHandleScope shs(isolate);
10758  ASSERT(args.length() == 1);
10759  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10760  return Smi::FromInt(static_cast<int>(details.type()));
10761}
10762
10763
10764// Return the property attribute calculated from the property details.
10765// args[0]: smi with property details.
10766RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10767  SealHandleScope shs(isolate);
10768  ASSERT(args.length() == 1);
10769  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10770  return Smi::FromInt(static_cast<int>(details.attributes()));
10771}
10772
10773
10774// Return the property insertion index calculated from the property details.
10775// args[0]: smi with property details.
10776RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10777  SealHandleScope shs(isolate);
10778  ASSERT(args.length() == 1);
10779  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10780  // TODO(verwaest): Depends on the type of details.
10781  return Smi::FromInt(details.dictionary_index());
10782}
10783
10784
10785// Return property value from named interceptor.
10786// args[0]: object
10787// args[1]: property name
10788RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10789  HandleScope scope(isolate);
10790  ASSERT(args.length() == 2);
10791  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10792  RUNTIME_ASSERT(obj->HasNamedInterceptor());
10793  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10794
10795  PropertyAttributes attributes;
10796  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10797}
10798
10799
10800// Return element value from indexed interceptor.
10801// args[0]: object
10802// args[1]: index
10803RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10804  HandleScope scope(isolate);
10805  ASSERT(args.length() == 2);
10806  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10807  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10808  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10809
10810  return obj->GetElementWithInterceptor(*obj, index);
10811}
10812
10813
10814RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10815  SealHandleScope shs(isolate);
10816  ASSERT(args.length() >= 1);
10817  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10818  // Check that the break id is valid.
10819  if (isolate->debug()->break_id() == 0 ||
10820      break_id != isolate->debug()->break_id()) {
10821    return isolate->Throw(
10822        isolate->heap()->illegal_execution_state_string());
10823  }
10824
10825  return isolate->heap()->true_value();
10826}
10827
10828
10829RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10830  HandleScope scope(isolate);
10831  ASSERT(args.length() == 1);
10832
10833  // Check arguments.
10834  Object* result;
10835  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10836      RUNTIME_ARGUMENTS(isolate, args));
10837    if (!maybe_result->ToObject(&result)) return maybe_result;
10838  }
10839
10840  // Count all frames which are relevant to debugging stack trace.
10841  int n = 0;
10842  StackFrame::Id id = isolate->debug()->break_frame_id();
10843  if (id == StackFrame::NO_ID) {
10844    // If there is no JavaScript stack frame count is 0.
10845    return Smi::FromInt(0);
10846  }
10847
10848  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10849    n += it.frame()->GetInlineCount();
10850  }
10851  return Smi::FromInt(n);
10852}
10853
10854
10855class FrameInspector {
10856 public:
10857  FrameInspector(JavaScriptFrame* frame,
10858                 int inlined_jsframe_index,
10859                 Isolate* isolate)
10860      : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10861    // Calculate the deoptimized frame.
10862    if (frame->is_optimized()) {
10863      deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10864          frame, inlined_jsframe_index, isolate);
10865    }
10866    has_adapted_arguments_ = frame_->has_adapted_arguments();
10867    is_bottommost_ = inlined_jsframe_index == 0;
10868    is_optimized_ = frame_->is_optimized();
10869  }
10870
10871  ~FrameInspector() {
10872    // Get rid of the calculated deoptimized frame if any.
10873    if (deoptimized_frame_ != NULL) {
10874      Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10875                                                  isolate_);
10876    }
10877  }
10878
10879  int GetParametersCount() {
10880    return is_optimized_
10881        ? deoptimized_frame_->parameters_count()
10882        : frame_->ComputeParametersCount();
10883  }
10884  int expression_count() { return deoptimized_frame_->expression_count(); }
10885  Object* GetFunction() {
10886    return is_optimized_
10887        ? deoptimized_frame_->GetFunction()
10888        : frame_->function();
10889  }
10890  Object* GetParameter(int index) {
10891    return is_optimized_
10892        ? deoptimized_frame_->GetParameter(index)
10893        : frame_->GetParameter(index);
10894  }
10895  Object* GetExpression(int index) {
10896    return is_optimized_
10897        ? deoptimized_frame_->GetExpression(index)
10898        : frame_->GetExpression(index);
10899  }
10900  int GetSourcePosition() {
10901    return is_optimized_
10902        ? deoptimized_frame_->GetSourcePosition()
10903        : frame_->LookupCode()->SourcePosition(frame_->pc());
10904  }
10905  bool IsConstructor() {
10906    return is_optimized_ && !is_bottommost_
10907        ? deoptimized_frame_->HasConstructStub()
10908        : frame_->IsConstructor();
10909  }
10910
10911  // To inspect all the provided arguments the frame might need to be
10912  // replaced with the arguments frame.
10913  void SetArgumentsFrame(JavaScriptFrame* frame) {
10914    ASSERT(has_adapted_arguments_);
10915    frame_ = frame;
10916    is_optimized_ = frame_->is_optimized();
10917    ASSERT(!is_optimized_);
10918  }
10919
10920 private:
10921  JavaScriptFrame* frame_;
10922  DeoptimizedFrameInfo* deoptimized_frame_;
10923  Isolate* isolate_;
10924  bool is_optimized_;
10925  bool is_bottommost_;
10926  bool has_adapted_arguments_;
10927
10928  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10929};
10930
10931
10932static const int kFrameDetailsFrameIdIndex = 0;
10933static const int kFrameDetailsReceiverIndex = 1;
10934static const int kFrameDetailsFunctionIndex = 2;
10935static const int kFrameDetailsArgumentCountIndex = 3;
10936static const int kFrameDetailsLocalCountIndex = 4;
10937static const int kFrameDetailsSourcePositionIndex = 5;
10938static const int kFrameDetailsConstructCallIndex = 6;
10939static const int kFrameDetailsAtReturnIndex = 7;
10940static const int kFrameDetailsFlagsIndex = 8;
10941static const int kFrameDetailsFirstDynamicIndex = 9;
10942
10943
10944static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10945                                             JavaScriptFrame* frame) {
10946  SaveContext* save = isolate->save_context();
10947  while (save != NULL && !save->IsBelowFrame(frame)) {
10948    save = save->prev();
10949  }
10950  ASSERT(save != NULL);
10951  return save;
10952}
10953
10954
10955// Return an array with frame details
10956// args[0]: number: break id
10957// args[1]: number: frame index
10958//
10959// The array returned contains the following information:
10960// 0: Frame id
10961// 1: Receiver
10962// 2: Function
10963// 3: Argument count
10964// 4: Local count
10965// 5: Source position
10966// 6: Constructor call
10967// 7: Is at return
10968// 8: Flags
10969// Arguments name, value
10970// Locals name, value
10971// Return value if any
10972RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10973  HandleScope scope(isolate);
10974  ASSERT(args.length() == 2);
10975
10976  // Check arguments.
10977  Object* check;
10978  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10979      RUNTIME_ARGUMENTS(isolate, args));
10980    if (!maybe_check->ToObject(&check)) return maybe_check;
10981  }
10982  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10983  Heap* heap = isolate->heap();
10984
10985  // Find the relevant frame with the requested index.
10986  StackFrame::Id id = isolate->debug()->break_frame_id();
10987  if (id == StackFrame::NO_ID) {
10988    // If there are no JavaScript stack frames return undefined.
10989    return heap->undefined_value();
10990  }
10991
10992  int count = 0;
10993  JavaScriptFrameIterator it(isolate, id);
10994  for (; !it.done(); it.Advance()) {
10995    if (index < count + it.frame()->GetInlineCount()) break;
10996    count += it.frame()->GetInlineCount();
10997  }
10998  if (it.done()) return heap->undefined_value();
10999
11000  bool is_optimized = it.frame()->is_optimized();
11001
11002  int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11003  if (is_optimized) {
11004    inlined_jsframe_index =
11005        it.frame()->GetInlineCount() - (index - count) - 1;
11006  }
11007  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11008
11009  // Traverse the saved contexts chain to find the active context for the
11010  // selected frame.
11011  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11012
11013  // Get the frame id.
11014  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11015
11016  // Find source position in unoptimized code.
11017  int position = frame_inspector.GetSourcePosition();
11018
11019  // Check for constructor frame.
11020  bool constructor = frame_inspector.IsConstructor();
11021
11022  // Get scope info and read from it for local variable information.
11023  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11024  Handle<SharedFunctionInfo> shared(function->shared());
11025  Handle<ScopeInfo> scope_info(shared->scope_info());
11026  ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11027
11028  // Get the locals names and values into a temporary array.
11029  //
11030  // TODO(1240907): Hide compiler-introduced stack variables
11031  // (e.g. .result)?  For users of the debugger, they will probably be
11032  // confusing.
11033  Handle<FixedArray> locals =
11034      isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11035
11036  // Fill in the values of the locals.
11037  int i = 0;
11038  for (; i < scope_info->StackLocalCount(); ++i) {
11039    // Use the value from the stack.
11040    locals->set(i * 2, scope_info->LocalName(i));
11041    locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11042  }
11043  if (i < scope_info->LocalCount()) {
11044    // Get the context containing declarations.
11045    Handle<Context> context(
11046        Context::cast(it.frame()->context())->declaration_context());
11047    for (; i < scope_info->LocalCount(); ++i) {
11048      Handle<String> name(scope_info->LocalName(i));
11049      VariableMode mode;
11050      InitializationFlag init_flag;
11051      locals->set(i * 2, *name);
11052      locals->set(i * 2 + 1, context->get(
11053          scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
11054    }
11055  }
11056
11057  // Check whether this frame is positioned at return. If not top
11058  // frame or if the frame is optimized it cannot be at a return.
11059  bool at_return = false;
11060  if (!is_optimized && index == 0) {
11061    at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11062  }
11063
11064  // If positioned just before return find the value to be returned and add it
11065  // to the frame information.
11066  Handle<Object> return_value = isolate->factory()->undefined_value();
11067  if (at_return) {
11068    StackFrameIterator it2(isolate);
11069    Address internal_frame_sp = NULL;
11070    while (!it2.done()) {
11071      if (it2.frame()->is_internal()) {
11072        internal_frame_sp = it2.frame()->sp();
11073      } else {
11074        if (it2.frame()->is_java_script()) {
11075          if (it2.frame()->id() == it.frame()->id()) {
11076            // The internal frame just before the JavaScript frame contains the
11077            // value to return on top. A debug break at return will create an
11078            // internal frame to store the return value (eax/rax/r0) before
11079            // entering the debug break exit frame.
11080            if (internal_frame_sp != NULL) {
11081              return_value =
11082                  Handle<Object>(Memory::Object_at(internal_frame_sp),
11083                                 isolate);
11084              break;
11085            }
11086          }
11087        }
11088
11089        // Indicate that the previous frame was not an internal frame.
11090        internal_frame_sp = NULL;
11091      }
11092      it2.Advance();
11093    }
11094  }
11095
11096  // Now advance to the arguments adapter frame (if any). It contains all
11097  // the provided parameters whereas the function frame always have the number
11098  // of arguments matching the functions parameters. The rest of the
11099  // information (except for what is collected above) is the same.
11100  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11101    it.AdvanceToArgumentsFrame();
11102    frame_inspector.SetArgumentsFrame(it.frame());
11103  }
11104
11105  // Find the number of arguments to fill. At least fill the number of
11106  // parameters for the function and fill more if more parameters are provided.
11107  int argument_count = scope_info->ParameterCount();
11108  if (argument_count < frame_inspector.GetParametersCount()) {
11109    argument_count = frame_inspector.GetParametersCount();
11110  }
11111
11112  // Calculate the size of the result.
11113  int details_size = kFrameDetailsFirstDynamicIndex +
11114                     2 * (argument_count + scope_info->LocalCount()) +
11115                     (at_return ? 1 : 0);
11116  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11117
11118  // Add the frame id.
11119  details->set(kFrameDetailsFrameIdIndex, *frame_id);
11120
11121  // Add the function (same as in function frame).
11122  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11123
11124  // Add the arguments count.
11125  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11126
11127  // Add the locals count
11128  details->set(kFrameDetailsLocalCountIndex,
11129               Smi::FromInt(scope_info->LocalCount()));
11130
11131  // Add the source position.
11132  if (position != RelocInfo::kNoPosition) {
11133    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11134  } else {
11135    details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11136  }
11137
11138  // Add the constructor information.
11139  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11140
11141  // Add the at return information.
11142  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11143
11144  // Add flags to indicate information on whether this frame is
11145  //   bit 0: invoked in the debugger context.
11146  //   bit 1: optimized frame.
11147  //   bit 2: inlined in optimized frame
11148  int flags = 0;
11149  if (*save->context() == *isolate->debug()->debug_context()) {
11150    flags |= 1 << 0;
11151  }
11152  if (is_optimized) {
11153    flags |= 1 << 1;
11154    flags |= inlined_jsframe_index << 2;
11155  }
11156  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11157
11158  // Fill the dynamic part.
11159  int details_index = kFrameDetailsFirstDynamicIndex;
11160
11161  // Add arguments name and value.
11162  for (int i = 0; i < argument_count; i++) {
11163    // Name of the argument.
11164    if (i < scope_info->ParameterCount()) {
11165      details->set(details_index++, scope_info->ParameterName(i));
11166    } else {
11167      details->set(details_index++, heap->undefined_value());
11168    }
11169
11170    // Parameter value.
11171    if (i < frame_inspector.GetParametersCount()) {
11172      // Get the value from the stack.
11173      details->set(details_index++, frame_inspector.GetParameter(i));
11174    } else {
11175      details->set(details_index++, heap->undefined_value());
11176    }
11177  }
11178
11179  // Add locals name and value from the temporary copy from the function frame.
11180  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11181    details->set(details_index++, locals->get(i));
11182  }
11183
11184  // Add the value being returned.
11185  if (at_return) {
11186    details->set(details_index++, *return_value);
11187  }
11188
11189  // Add the receiver (same as in function frame).
11190  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11191  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11192  Handle<Object> receiver(it.frame()->receiver(), isolate);
11193  if (!receiver->IsJSObject() &&
11194      shared->is_classic_mode() &&
11195      !function->IsBuiltin()) {
11196    // If the receiver is not a JSObject and the function is not a
11197    // builtin or strict-mode we have hit an optimization where a
11198    // value object is not converted into a wrapped JS objects. To
11199    // hide this optimization from the debugger, we wrap the receiver
11200    // by creating correct wrapper object based on the calling frame's
11201    // native context.
11202    it.Advance();
11203    Handle<Context> calling_frames_native_context(
11204        Context::cast(Context::cast(it.frame()->context())->native_context()));
11205    ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
11206    receiver =
11207        isolate->factory()->ToObject(receiver, calling_frames_native_context);
11208  }
11209  details->set(kFrameDetailsReceiverIndex, *receiver);
11210
11211  ASSERT_EQ(details_size, details_index);
11212  return *isolate->factory()->NewJSArrayWithElements(details);
11213}
11214
11215
11216// Create a plain JSObject which materializes the local scope for the specified
11217// frame.
11218static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11219    Isolate* isolate,
11220    Handle<JSObject> target,
11221    Handle<JSFunction> function,
11222    FrameInspector* frame_inspector) {
11223  Handle<SharedFunctionInfo> shared(function->shared());
11224  Handle<ScopeInfo> scope_info(shared->scope_info());
11225
11226  // First fill all parameters.
11227  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11228    Handle<Object> value(i < frame_inspector->GetParametersCount()
11229                             ? frame_inspector->GetParameter(i)
11230                             : isolate->heap()->undefined_value(),
11231                         isolate);
11232    ASSERT(!value->IsTheHole());
11233
11234    RETURN_IF_EMPTY_HANDLE_VALUE(
11235        isolate,
11236        SetProperty(isolate,
11237                    target,
11238                    Handle<String>(scope_info->ParameterName(i)),
11239                    value,
11240                    NONE,
11241                    kNonStrictMode),
11242        Handle<JSObject>());
11243  }
11244
11245  // Second fill all stack locals.
11246  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11247    Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11248    if (value->IsTheHole()) continue;
11249
11250    RETURN_IF_EMPTY_HANDLE_VALUE(
11251        isolate,
11252        SetProperty(isolate,
11253                    target,
11254                    Handle<String>(scope_info->StackLocalName(i)),
11255                    value,
11256                    NONE,
11257                    kNonStrictMode),
11258        Handle<JSObject>());
11259  }
11260
11261  return target;
11262}
11263
11264
11265static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11266                                                    Handle<JSObject> target,
11267                                                    Handle<JSFunction> function,
11268                                                    JavaScriptFrame* frame,
11269                                                    int inlined_jsframe_index) {
11270  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11271    // Optimized frames are not supported.
11272    // TODO(yangguo): make sure all code deoptimized when debugger is active
11273    //                and assert that this cannot happen.
11274    return;
11275  }
11276
11277  Handle<SharedFunctionInfo> shared(function->shared());
11278  Handle<ScopeInfo> scope_info(shared->scope_info());
11279
11280  // Parameters.
11281  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11282    ASSERT(!frame->GetParameter(i)->IsTheHole());
11283    HandleScope scope(isolate);
11284    Handle<Object> value = GetProperty(
11285        isolate, target, Handle<String>(scope_info->ParameterName(i)));
11286    frame->SetParameterValue(i, *value);
11287  }
11288
11289  // Stack locals.
11290  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11291    if (frame->GetExpression(i)->IsTheHole()) continue;
11292    HandleScope scope(isolate);
11293    Handle<Object> value = GetProperty(
11294        isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11295    frame->SetExpression(i, *value);
11296  }
11297}
11298
11299
11300static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11301                                                Handle<JSObject> target,
11302                                                Handle<JSFunction> function,
11303                                                JavaScriptFrame* frame) {
11304  HandleScope scope(isolate);
11305  Handle<SharedFunctionInfo> shared(function->shared());
11306  Handle<ScopeInfo> scope_info(shared->scope_info());
11307
11308  if (!scope_info->HasContext()) return target;
11309
11310  // Third fill all context locals.
11311  Handle<Context> frame_context(Context::cast(frame->context()));
11312  Handle<Context> function_context(frame_context->declaration_context());
11313  if (!scope_info->CopyContextLocalsToScopeObject(
11314          isolate, function_context, target)) {
11315    return Handle<JSObject>();
11316  }
11317
11318  // Finally copy any properties from the function context extension.
11319  // These will be variables introduced by eval.
11320  if (function_context->closure() == *function) {
11321    if (function_context->has_extension() &&
11322        !function_context->IsNativeContext()) {
11323      Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11324      bool threw = false;
11325      Handle<FixedArray> keys =
11326          GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11327      if (threw) return Handle<JSObject>();
11328
11329      for (int i = 0; i < keys->length(); i++) {
11330        // Names of variables introduced by eval are strings.
11331        ASSERT(keys->get(i)->IsString());
11332        Handle<String> key(String::cast(keys->get(i)));
11333        RETURN_IF_EMPTY_HANDLE_VALUE(
11334            isolate,
11335            SetProperty(isolate,
11336                        target,
11337                        key,
11338                        GetProperty(isolate, ext, key),
11339                        NONE,
11340                        kNonStrictMode),
11341            Handle<JSObject>());
11342      }
11343    }
11344  }
11345
11346  return target;
11347}
11348
11349
11350static Handle<JSObject> MaterializeLocalScope(
11351    Isolate* isolate,
11352    JavaScriptFrame* frame,
11353    int inlined_jsframe_index) {
11354  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11355  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11356
11357  Handle<JSObject> local_scope =
11358      isolate->factory()->NewJSObject(isolate->object_function());
11359  local_scope = MaterializeStackLocalsWithFrameInspector(
11360                    isolate, local_scope, function, &frame_inspector);
11361  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11362
11363  return MaterializeLocalContext(isolate, local_scope, function, frame);
11364}
11365
11366
11367// Set the context local variable value.
11368static bool SetContextLocalValue(Isolate* isolate,
11369                                 Handle<ScopeInfo> scope_info,
11370                                 Handle<Context> context,
11371                                 Handle<String> variable_name,
11372                                 Handle<Object> new_value) {
11373  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11374    Handle<String> next_name(scope_info->ContextLocalName(i));
11375    if (variable_name->Equals(*next_name)) {
11376      VariableMode mode;
11377      InitializationFlag init_flag;
11378      int context_index =
11379          scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11380      context->set(context_index, *new_value);
11381      return true;
11382    }
11383  }
11384
11385  return false;
11386}
11387
11388
11389static bool SetLocalVariableValue(Isolate* isolate,
11390                                  JavaScriptFrame* frame,
11391                                  int inlined_jsframe_index,
11392                                  Handle<String> variable_name,
11393                                  Handle<Object> new_value) {
11394  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11395    // Optimized frames are not supported.
11396    return false;
11397  }
11398
11399  Handle<JSFunction> function(frame->function());
11400  Handle<SharedFunctionInfo> shared(function->shared());
11401  Handle<ScopeInfo> scope_info(shared->scope_info());
11402
11403  bool default_result = false;
11404
11405  // Parameters.
11406  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11407    if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11408      frame->SetParameterValue(i, *new_value);
11409      // Argument might be shadowed in heap context, don't stop here.
11410      default_result = true;
11411    }
11412  }
11413
11414  // Stack locals.
11415  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11416    if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11417      frame->SetExpression(i, *new_value);
11418      return true;
11419    }
11420  }
11421
11422  if (scope_info->HasContext()) {
11423    // Context locals.
11424    Handle<Context> frame_context(Context::cast(frame->context()));
11425    Handle<Context> function_context(frame_context->declaration_context());
11426    if (SetContextLocalValue(
11427        isolate, scope_info, function_context, variable_name, new_value)) {
11428      return true;
11429    }
11430
11431    // Function context extension. These are variables introduced by eval.
11432    if (function_context->closure() == *function) {
11433      if (function_context->has_extension() &&
11434          !function_context->IsNativeContext()) {
11435        Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11436
11437        if (ext->HasProperty(*variable_name)) {
11438          // We don't expect this to do anything except replacing
11439          // property value.
11440          SetProperty(isolate,
11441                      ext,
11442                      variable_name,
11443                      new_value,
11444                      NONE,
11445                      kNonStrictMode);
11446          return true;
11447        }
11448      }
11449    }
11450  }
11451
11452  return default_result;
11453}
11454
11455
11456// Create a plain JSObject which materializes the closure content for the
11457// context.
11458static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11459                                           Handle<Context> context) {
11460  ASSERT(context->IsFunctionContext());
11461
11462  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11463  Handle<ScopeInfo> scope_info(shared->scope_info());
11464
11465  // Allocate and initialize a JSObject with all the content of this function
11466  // closure.
11467  Handle<JSObject> closure_scope =
11468      isolate->factory()->NewJSObject(isolate->object_function());
11469
11470  // Fill all context locals to the context extension.
11471  if (!scope_info->CopyContextLocalsToScopeObject(
11472          isolate, context, closure_scope)) {
11473    return Handle<JSObject>();
11474  }
11475
11476  // Finally copy any properties from the function context extension. This will
11477  // be variables introduced by eval.
11478  if (context->has_extension()) {
11479    Handle<JSObject> ext(JSObject::cast(context->extension()));
11480    bool threw = false;
11481    Handle<FixedArray> keys =
11482        GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11483    if (threw) return Handle<JSObject>();
11484
11485    for (int i = 0; i < keys->length(); i++) {
11486      // Names of variables introduced by eval are strings.
11487      ASSERT(keys->get(i)->IsString());
11488      Handle<String> key(String::cast(keys->get(i)));
11489       RETURN_IF_EMPTY_HANDLE_VALUE(
11490          isolate,
11491          SetProperty(isolate,
11492                      closure_scope,
11493                      key,
11494                      GetProperty(isolate, ext, key),
11495                      NONE,
11496                      kNonStrictMode),
11497          Handle<JSObject>());
11498    }
11499  }
11500
11501  return closure_scope;
11502}
11503
11504
11505// This method copies structure of MaterializeClosure method above.
11506static bool SetClosureVariableValue(Isolate* isolate,
11507                                    Handle<Context> context,
11508                                    Handle<String> variable_name,
11509                                    Handle<Object> new_value) {
11510  ASSERT(context->IsFunctionContext());
11511
11512  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11513  Handle<ScopeInfo> scope_info(shared->scope_info());
11514
11515  // Context locals to the context extension.
11516  if (SetContextLocalValue(
11517          isolate, scope_info, context, variable_name, new_value)) {
11518    return true;
11519  }
11520
11521  // Properties from the function context extension. This will
11522  // be variables introduced by eval.
11523  if (context->has_extension()) {
11524    Handle<JSObject> ext(JSObject::cast(context->extension()));
11525    if (ext->HasProperty(*variable_name)) {
11526      // We don't expect this to do anything except replacing property value.
11527      SetProperty(isolate,
11528                  ext,
11529                  variable_name,
11530                  new_value,
11531                  NONE,
11532                  kNonStrictMode);
11533      return true;
11534    }
11535  }
11536
11537  return false;
11538}
11539
11540
11541// Create a plain JSObject which materializes the scope for the specified
11542// catch context.
11543static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11544                                              Handle<Context> context) {
11545  ASSERT(context->IsCatchContext());
11546  Handle<String> name(String::cast(context->extension()));
11547  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11548                               isolate);
11549  Handle<JSObject> catch_scope =
11550      isolate->factory()->NewJSObject(isolate->object_function());
11551  RETURN_IF_EMPTY_HANDLE_VALUE(
11552      isolate,
11553      SetProperty(isolate,
11554                  catch_scope,
11555                  name,
11556                  thrown_object,
11557                  NONE,
11558                  kNonStrictMode),
11559      Handle<JSObject>());
11560  return catch_scope;
11561}
11562
11563
11564static bool SetCatchVariableValue(Isolate* isolate,
11565                                  Handle<Context> context,
11566                                  Handle<String> variable_name,
11567                                  Handle<Object> new_value) {
11568  ASSERT(context->IsCatchContext());
11569  Handle<String> name(String::cast(context->extension()));
11570  if (!name->Equals(*variable_name)) {
11571    return false;
11572  }
11573  context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11574  return true;
11575}
11576
11577
11578// Create a plain JSObject which materializes the block scope for the specified
11579// block context.
11580static Handle<JSObject> MaterializeBlockScope(
11581    Isolate* isolate,
11582    Handle<Context> context) {
11583  ASSERT(context->IsBlockContext());
11584  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11585
11586  // Allocate and initialize a JSObject with all the arguments, stack locals
11587  // heap locals and extension properties of the debugged function.
11588  Handle<JSObject> block_scope =
11589      isolate->factory()->NewJSObject(isolate->object_function());
11590
11591  // Fill all context locals.
11592  if (!scope_info->CopyContextLocalsToScopeObject(
11593          isolate, context, block_scope)) {
11594    return Handle<JSObject>();
11595  }
11596
11597  return block_scope;
11598}
11599
11600
11601// Create a plain JSObject which materializes the module scope for the specified
11602// module context.
11603static Handle<JSObject> MaterializeModuleScope(
11604    Isolate* isolate,
11605    Handle<Context> context) {
11606  ASSERT(context->IsModuleContext());
11607  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11608
11609  // Allocate and initialize a JSObject with all the members of the debugged
11610  // module.
11611  Handle<JSObject> module_scope =
11612      isolate->factory()->NewJSObject(isolate->object_function());
11613
11614  // Fill all context locals.
11615  if (!scope_info->CopyContextLocalsToScopeObject(
11616          isolate, context, module_scope)) {
11617    return Handle<JSObject>();
11618  }
11619
11620  return module_scope;
11621}
11622
11623
11624// Iterate over the actual scopes visible from a stack frame or from a closure.
11625// The iteration proceeds from the innermost visible nested scope outwards.
11626// All scopes are backed by an actual context except the local scope,
11627// which is inserted "artificially" in the context chain.
11628class ScopeIterator {
11629 public:
11630  enum ScopeType {
11631    ScopeTypeGlobal = 0,
11632    ScopeTypeLocal,
11633    ScopeTypeWith,
11634    ScopeTypeClosure,
11635    ScopeTypeCatch,
11636    ScopeTypeBlock,
11637    ScopeTypeModule
11638  };
11639
11640  ScopeIterator(Isolate* isolate,
11641                JavaScriptFrame* frame,
11642                int inlined_jsframe_index)
11643    : isolate_(isolate),
11644      frame_(frame),
11645      inlined_jsframe_index_(inlined_jsframe_index),
11646      function_(frame->function()),
11647      context_(Context::cast(frame->context())),
11648      nested_scope_chain_(4),
11649      failed_(false) {
11650
11651    // Catch the case when the debugger stops in an internal function.
11652    Handle<SharedFunctionInfo> shared_info(function_->shared());
11653    Handle<ScopeInfo> scope_info(shared_info->scope_info());
11654    if (shared_info->script() == isolate->heap()->undefined_value()) {
11655      while (context_->closure() == *function_) {
11656        context_ = Handle<Context>(context_->previous(), isolate_);
11657      }
11658      return;
11659    }
11660
11661    // Get the debug info (create it if it does not exist).
11662    if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11663      // Return if ensuring debug info failed.
11664      return;
11665    }
11666    Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11667
11668    // Find the break point where execution has stopped.
11669    BreakLocationIterator break_location_iterator(debug_info,
11670                                                  ALL_BREAK_LOCATIONS);
11671    // pc points to the instruction after the current one, possibly a break
11672    // location as well. So the "- 1" to exclude it from the search.
11673    break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11674    if (break_location_iterator.IsExit()) {
11675      // We are within the return sequence. At the momemt it is not possible to
11676      // get a source position which is consistent with the current scope chain.
11677      // Thus all nested with, catch and block contexts are skipped and we only
11678      // provide the function scope.
11679      if (scope_info->HasContext()) {
11680        context_ = Handle<Context>(context_->declaration_context(), isolate_);
11681      } else {
11682        while (context_->closure() == *function_) {
11683          context_ = Handle<Context>(context_->previous(), isolate_);
11684        }
11685      }
11686      if (scope_info->scope_type() != EVAL_SCOPE) {
11687        nested_scope_chain_.Add(scope_info);
11688      }
11689    } else {
11690      // Reparse the code and analyze the scopes.
11691      Handle<Script> script(Script::cast(shared_info->script()));
11692      Scope* scope = NULL;
11693
11694      // Check whether we are in global, eval or function code.
11695      Handle<ScopeInfo> scope_info(shared_info->scope_info());
11696      if (scope_info->scope_type() != FUNCTION_SCOPE) {
11697        // Global or eval code.
11698        CompilationInfoWithZone info(script);
11699        if (scope_info->scope_type() == GLOBAL_SCOPE) {
11700          info.MarkAsGlobal();
11701        } else {
11702          ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11703          info.MarkAsEval();
11704          info.SetContext(Handle<Context>(function_->context()));
11705        }
11706        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11707          scope = info.function()->scope();
11708        }
11709        RetrieveScopeChain(scope, shared_info);
11710      } else {
11711        // Function code
11712        CompilationInfoWithZone info(shared_info);
11713        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11714          scope = info.function()->scope();
11715        }
11716        RetrieveScopeChain(scope, shared_info);
11717      }
11718    }
11719  }
11720
11721  ScopeIterator(Isolate* isolate,
11722                Handle<JSFunction> function)
11723    : isolate_(isolate),
11724      frame_(NULL),
11725      inlined_jsframe_index_(0),
11726      function_(function),
11727      context_(function->context()),
11728      failed_(false) {
11729    if (function->IsBuiltin()) {
11730      context_ = Handle<Context>();
11731    }
11732  }
11733
11734  // More scopes?
11735  bool Done() {
11736    ASSERT(!failed_);
11737    return context_.is_null();
11738  }
11739
11740  bool Failed() { return failed_; }
11741
11742  // Move to the next scope.
11743  void Next() {
11744    ASSERT(!failed_);
11745    ScopeType scope_type = Type();
11746    if (scope_type == ScopeTypeGlobal) {
11747      // The global scope is always the last in the chain.
11748      ASSERT(context_->IsNativeContext());
11749      context_ = Handle<Context>();
11750      return;
11751    }
11752    if (nested_scope_chain_.is_empty()) {
11753      context_ = Handle<Context>(context_->previous(), isolate_);
11754    } else {
11755      if (nested_scope_chain_.last()->HasContext()) {
11756        ASSERT(context_->previous() != NULL);
11757        context_ = Handle<Context>(context_->previous(), isolate_);
11758      }
11759      nested_scope_chain_.RemoveLast();
11760    }
11761  }
11762
11763  // Return the type of the current scope.
11764  ScopeType Type() {
11765    ASSERT(!failed_);
11766    if (!nested_scope_chain_.is_empty()) {
11767      Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11768      switch (scope_info->scope_type()) {
11769        case FUNCTION_SCOPE:
11770          ASSERT(context_->IsFunctionContext() ||
11771                 !scope_info->HasContext());
11772          return ScopeTypeLocal;
11773        case MODULE_SCOPE:
11774          ASSERT(context_->IsModuleContext());
11775          return ScopeTypeModule;
11776        case GLOBAL_SCOPE:
11777          ASSERT(context_->IsNativeContext());
11778          return ScopeTypeGlobal;
11779        case WITH_SCOPE:
11780          ASSERT(context_->IsWithContext());
11781          return ScopeTypeWith;
11782        case CATCH_SCOPE:
11783          ASSERT(context_->IsCatchContext());
11784          return ScopeTypeCatch;
11785        case BLOCK_SCOPE:
11786          ASSERT(!scope_info->HasContext() ||
11787                 context_->IsBlockContext());
11788          return ScopeTypeBlock;
11789        case EVAL_SCOPE:
11790          UNREACHABLE();
11791      }
11792    }
11793    if (context_->IsNativeContext()) {
11794      ASSERT(context_->global_object()->IsGlobalObject());
11795      return ScopeTypeGlobal;
11796    }
11797    if (context_->IsFunctionContext()) {
11798      return ScopeTypeClosure;
11799    }
11800    if (context_->IsCatchContext()) {
11801      return ScopeTypeCatch;
11802    }
11803    if (context_->IsBlockContext()) {
11804      return ScopeTypeBlock;
11805    }
11806    if (context_->IsModuleContext()) {
11807      return ScopeTypeModule;
11808    }
11809    ASSERT(context_->IsWithContext());
11810    return ScopeTypeWith;
11811  }
11812
11813  // Return the JavaScript object with the content of the current scope.
11814  Handle<JSObject> ScopeObject() {
11815    ASSERT(!failed_);
11816    switch (Type()) {
11817      case ScopeIterator::ScopeTypeGlobal:
11818        return Handle<JSObject>(CurrentContext()->global_object());
11819      case ScopeIterator::ScopeTypeLocal:
11820        // Materialize the content of the local scope into a JSObject.
11821        ASSERT(nested_scope_chain_.length() == 1);
11822        return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11823      case ScopeIterator::ScopeTypeWith:
11824        // Return the with object.
11825        return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11826      case ScopeIterator::ScopeTypeCatch:
11827        return MaterializeCatchScope(isolate_, CurrentContext());
11828      case ScopeIterator::ScopeTypeClosure:
11829        // Materialize the content of the closure scope into a JSObject.
11830        return MaterializeClosure(isolate_, CurrentContext());
11831      case ScopeIterator::ScopeTypeBlock:
11832        return MaterializeBlockScope(isolate_, CurrentContext());
11833      case ScopeIterator::ScopeTypeModule:
11834        return MaterializeModuleScope(isolate_, CurrentContext());
11835    }
11836    UNREACHABLE();
11837    return Handle<JSObject>();
11838  }
11839
11840  bool SetVariableValue(Handle<String> variable_name,
11841                        Handle<Object> new_value) {
11842    ASSERT(!failed_);
11843    switch (Type()) {
11844      case ScopeIterator::ScopeTypeGlobal:
11845        break;
11846      case ScopeIterator::ScopeTypeLocal:
11847        return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
11848            variable_name, new_value);
11849      case ScopeIterator::ScopeTypeWith:
11850        break;
11851      case ScopeIterator::ScopeTypeCatch:
11852        return SetCatchVariableValue(isolate_, CurrentContext(),
11853            variable_name, new_value);
11854      case ScopeIterator::ScopeTypeClosure:
11855        return SetClosureVariableValue(isolate_, CurrentContext(),
11856            variable_name, new_value);
11857      case ScopeIterator::ScopeTypeBlock:
11858        // TODO(2399): should we implement it?
11859        break;
11860      case ScopeIterator::ScopeTypeModule:
11861        // TODO(2399): should we implement it?
11862        break;
11863    }
11864    return false;
11865  }
11866
11867  Handle<ScopeInfo> CurrentScopeInfo() {
11868    ASSERT(!failed_);
11869    if (!nested_scope_chain_.is_empty()) {
11870      return nested_scope_chain_.last();
11871    } else if (context_->IsBlockContext()) {
11872      return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11873    } else if (context_->IsFunctionContext()) {
11874      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11875    }
11876    return Handle<ScopeInfo>::null();
11877  }
11878
11879  // Return the context for this scope. For the local context there might not
11880  // be an actual context.
11881  Handle<Context> CurrentContext() {
11882    ASSERT(!failed_);
11883    if (Type() == ScopeTypeGlobal ||
11884        nested_scope_chain_.is_empty()) {
11885      return context_;
11886    } else if (nested_scope_chain_.last()->HasContext()) {
11887      return context_;
11888    } else {
11889      return Handle<Context>();
11890    }
11891  }
11892
11893#ifdef DEBUG
11894  // Debug print of the content of the current scope.
11895  void DebugPrint() {
11896    ASSERT(!failed_);
11897    switch (Type()) {
11898      case ScopeIterator::ScopeTypeGlobal:
11899        PrintF("Global:\n");
11900        CurrentContext()->Print();
11901        break;
11902
11903      case ScopeIterator::ScopeTypeLocal: {
11904        PrintF("Local:\n");
11905        function_->shared()->scope_info()->Print();
11906        if (!CurrentContext().is_null()) {
11907          CurrentContext()->Print();
11908          if (CurrentContext()->has_extension()) {
11909            Handle<Object> extension(CurrentContext()->extension(), isolate_);
11910            if (extension->IsJSContextExtensionObject()) {
11911              extension->Print();
11912            }
11913          }
11914        }
11915        break;
11916      }
11917
11918      case ScopeIterator::ScopeTypeWith:
11919        PrintF("With:\n");
11920        CurrentContext()->extension()->Print();
11921        break;
11922
11923      case ScopeIterator::ScopeTypeCatch:
11924        PrintF("Catch:\n");
11925        CurrentContext()->extension()->Print();
11926        CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11927        break;
11928
11929      case ScopeIterator::ScopeTypeClosure:
11930        PrintF("Closure:\n");
11931        CurrentContext()->Print();
11932        if (CurrentContext()->has_extension()) {
11933          Handle<Object> extension(CurrentContext()->extension(), isolate_);
11934          if (extension->IsJSContextExtensionObject()) {
11935            extension->Print();
11936          }
11937        }
11938        break;
11939
11940      default:
11941        UNREACHABLE();
11942    }
11943    PrintF("\n");
11944  }
11945#endif
11946
11947 private:
11948  Isolate* isolate_;
11949  JavaScriptFrame* frame_;
11950  int inlined_jsframe_index_;
11951  Handle<JSFunction> function_;
11952  Handle<Context> context_;
11953  List<Handle<ScopeInfo> > nested_scope_chain_;
11954  bool failed_;
11955
11956  void RetrieveScopeChain(Scope* scope,
11957                          Handle<SharedFunctionInfo> shared_info) {
11958    if (scope != NULL) {
11959      int source_position = shared_info->code()->SourcePosition(frame_->pc());
11960      scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11961    } else {
11962      // A failed reparse indicates that the preparser has diverged from the
11963      // parser or that the preparse data given to the initial parse has been
11964      // faulty. We fail in debug mode but in release mode we only provide the
11965      // information we get from the context chain but nothing about
11966      // completely stack allocated scopes or stack allocated locals.
11967      // Or it could be due to stack overflow.
11968      ASSERT(isolate_->has_pending_exception());
11969      failed_ = true;
11970    }
11971  }
11972
11973  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11974};
11975
11976
11977RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11978  HandleScope scope(isolate);
11979  ASSERT(args.length() == 2);
11980
11981  // Check arguments.
11982  Object* check;
11983  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11984      RUNTIME_ARGUMENTS(isolate, args));
11985    if (!maybe_check->ToObject(&check)) return maybe_check;
11986  }
11987  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11988
11989  // Get the frame where the debugging is performed.
11990  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11991  JavaScriptFrameIterator it(isolate, id);
11992  JavaScriptFrame* frame = it.frame();
11993
11994  // Count the visible scopes.
11995  int n = 0;
11996  for (ScopeIterator it(isolate, frame, 0);
11997       !it.Done();
11998       it.Next()) {
11999    n++;
12000  }
12001
12002  return Smi::FromInt(n);
12003}
12004
12005
12006// Returns the list of step-in positions (text offset) in a function of the
12007// stack frame in a range from the current debug break position to the end
12008// of the corresponding statement.
12009RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12010  HandleScope scope(isolate);
12011  ASSERT(args.length() == 2);
12012
12013  // Check arguments.
12014  Object* check;
12015  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12016      RUNTIME_ARGUMENTS(isolate, args));
12017    if (!maybe_check->ToObject(&check)) return maybe_check;
12018  }
12019  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12020
12021  // Get the frame where the debugging is performed.
12022  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12023  JavaScriptFrameIterator frame_it(isolate, id);
12024  JavaScriptFrame* frame = frame_it.frame();
12025
12026  Handle<JSFunction> fun =
12027      Handle<JSFunction>(frame->function());
12028  Handle<SharedFunctionInfo> shared =
12029      Handle<SharedFunctionInfo>(fun->shared());
12030
12031  if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12032    return isolate->heap()->undefined_value();
12033  }
12034
12035  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12036
12037  int len = 0;
12038  Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12039  // Find the break point where execution has stopped.
12040  BreakLocationIterator break_location_iterator(debug_info,
12041                                                ALL_BREAK_LOCATIONS);
12042
12043  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
12044  int current_statement_pos = break_location_iterator.statement_position();
12045
12046  while (!break_location_iterator.Done()) {
12047    if (break_location_iterator.pc() > frame->pc()) {
12048      if (break_location_iterator.IsStepInLocation(isolate)) {
12049        Smi* position_value = Smi::FromInt(break_location_iterator.position());
12050        JSObject::SetElement(array, len,
12051            Handle<Object>(position_value, isolate),
12052            NONE, kNonStrictMode);
12053        len++;
12054      }
12055    }
12056    // Advance iterator.
12057    break_location_iterator.Next();
12058    if (current_statement_pos !=
12059        break_location_iterator.statement_position()) {
12060      break;
12061    }
12062  }
12063  return *array;
12064}
12065
12066
12067static const int kScopeDetailsTypeIndex = 0;
12068static const int kScopeDetailsObjectIndex = 1;
12069static const int kScopeDetailsSize = 2;
12070
12071
12072static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
12073    ScopeIterator* it) {
12074  // Calculate the size of the result.
12075  int details_size = kScopeDetailsSize;
12076  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12077
12078  // Fill in scope details.
12079  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12080  Handle<JSObject> scope_object = it->ScopeObject();
12081  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
12082  details->set(kScopeDetailsObjectIndex, *scope_object);
12083
12084  return *isolate->factory()->NewJSArrayWithElements(details);
12085}
12086
12087
12088// Return an array with scope details
12089// args[0]: number: break id
12090// args[1]: number: frame index
12091// args[2]: number: inlined frame index
12092// args[3]: number: scope index
12093//
12094// The array returned contains the following information:
12095// 0: Scope type
12096// 1: Scope object
12097RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12098  HandleScope scope(isolate);
12099  ASSERT(args.length() == 4);
12100
12101  // Check arguments.
12102  Object* check;
12103  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12104      RUNTIME_ARGUMENTS(isolate, args));
12105    if (!maybe_check->ToObject(&check)) return maybe_check;
12106  }
12107  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12108  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12109  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12110
12111  // Get the frame where the debugging is performed.
12112  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12113  JavaScriptFrameIterator frame_it(isolate, id);
12114  JavaScriptFrame* frame = frame_it.frame();
12115
12116  // Find the requested scope.
12117  int n = 0;
12118  ScopeIterator it(isolate, frame, inlined_jsframe_index);
12119  for (; !it.Done() && n < index; it.Next()) {
12120    n++;
12121  }
12122  if (it.Done()) {
12123    return isolate->heap()->undefined_value();
12124  }
12125  return MaterializeScopeDetails(isolate, &it);
12126}
12127
12128
12129RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12130  HandleScope scope(isolate);
12131  ASSERT(args.length() == 1);
12132
12133  // Check arguments.
12134  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12135
12136  // Count the visible scopes.
12137  int n = 0;
12138  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12139    n++;
12140  }
12141
12142  return Smi::FromInt(n);
12143}
12144
12145
12146RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12147  HandleScope scope(isolate);
12148  ASSERT(args.length() == 2);
12149
12150  // Check arguments.
12151  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12152  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12153
12154  // Find the requested scope.
12155  int n = 0;
12156  ScopeIterator it(isolate, fun);
12157  for (; !it.Done() && n < index; it.Next()) {
12158    n++;
12159  }
12160  if (it.Done()) {
12161    return isolate->heap()->undefined_value();
12162  }
12163
12164  return MaterializeScopeDetails(isolate, &it);
12165}
12166
12167
12168static bool SetScopeVariableValue(ScopeIterator* it, int index,
12169                                  Handle<String> variable_name,
12170                                  Handle<Object> new_value) {
12171  for (int n = 0; !it->Done() && n < index; it->Next()) {
12172    n++;
12173  }
12174  if (it->Done()) {
12175    return false;
12176  }
12177  return it->SetVariableValue(variable_name, new_value);
12178}
12179
12180
12181// Change variable value in closure or local scope
12182// args[0]: number or JsFunction: break id or function
12183// args[1]: number: frame index (when arg[0] is break id)
12184// args[2]: number: inlined frame index (when arg[0] is break id)
12185// args[3]: number: scope index
12186// args[4]: string: variable name
12187// args[5]: object: new value
12188//
12189// Return true if success and false otherwise
12190RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12191  HandleScope scope(isolate);
12192  ASSERT(args.length() == 6);
12193
12194  // Check arguments.
12195  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12196  CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12197  Handle<Object> new_value = args.at<Object>(5);
12198
12199  bool res;
12200  if (args[0]->IsNumber()) {
12201    Object* check;
12202    { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12203        RUNTIME_ARGUMENTS(isolate, args));
12204      if (!maybe_check->ToObject(&check)) return maybe_check;
12205    }
12206    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12207    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12208
12209    // Get the frame where the debugging is performed.
12210    StackFrame::Id id = UnwrapFrameId(wrapped_id);
12211    JavaScriptFrameIterator frame_it(isolate, id);
12212    JavaScriptFrame* frame = frame_it.frame();
12213
12214    ScopeIterator it(isolate, frame, inlined_jsframe_index);
12215    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12216  } else {
12217    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12218    ScopeIterator it(isolate, fun);
12219    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12220  }
12221
12222  return isolate->heap()->ToBoolean(res);
12223}
12224
12225
12226RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12227  HandleScope scope(isolate);
12228  ASSERT(args.length() == 0);
12229
12230#ifdef DEBUG
12231  // Print the scopes for the top frame.
12232  StackFrameLocator locator(isolate);
12233  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12234  for (ScopeIterator it(isolate, frame, 0);
12235       !it.Done();
12236       it.Next()) {
12237    it.DebugPrint();
12238  }
12239#endif
12240  return isolate->heap()->undefined_value();
12241}
12242
12243
12244RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12245  HandleScope scope(isolate);
12246  ASSERT(args.length() == 1);
12247
12248  // Check arguments.
12249  Object* result;
12250  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12251      RUNTIME_ARGUMENTS(isolate, args));
12252    if (!maybe_result->ToObject(&result)) return maybe_result;
12253  }
12254
12255  // Count all archived V8 threads.
12256  int n = 0;
12257  for (ThreadState* thread =
12258          isolate->thread_manager()->FirstThreadStateInUse();
12259       thread != NULL;
12260       thread = thread->Next()) {
12261    n++;
12262  }
12263
12264  // Total number of threads is current thread and archived threads.
12265  return Smi::FromInt(n + 1);
12266}
12267
12268
12269static const int kThreadDetailsCurrentThreadIndex = 0;
12270static const int kThreadDetailsThreadIdIndex = 1;
12271static const int kThreadDetailsSize = 2;
12272
12273// Return an array with thread details
12274// args[0]: number: break id
12275// args[1]: number: thread index
12276//
12277// The array returned contains the following information:
12278// 0: Is current thread?
12279// 1: Thread id
12280RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12281  HandleScope scope(isolate);
12282  ASSERT(args.length() == 2);
12283
12284  // Check arguments.
12285  Object* check;
12286  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12287      RUNTIME_ARGUMENTS(isolate, args));
12288    if (!maybe_check->ToObject(&check)) return maybe_check;
12289  }
12290  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12291
12292  // Allocate array for result.
12293  Handle<FixedArray> details =
12294      isolate->factory()->NewFixedArray(kThreadDetailsSize);
12295
12296  // Thread index 0 is current thread.
12297  if (index == 0) {
12298    // Fill the details.
12299    details->set(kThreadDetailsCurrentThreadIndex,
12300                 isolate->heap()->true_value());
12301    details->set(kThreadDetailsThreadIdIndex,
12302                 Smi::FromInt(ThreadId::Current().ToInteger()));
12303  } else {
12304    // Find the thread with the requested index.
12305    int n = 1;
12306    ThreadState* thread =
12307        isolate->thread_manager()->FirstThreadStateInUse();
12308    while (index != n && thread != NULL) {
12309      thread = thread->Next();
12310      n++;
12311    }
12312    if (thread == NULL) {
12313      return isolate->heap()->undefined_value();
12314    }
12315
12316    // Fill the details.
12317    details->set(kThreadDetailsCurrentThreadIndex,
12318                 isolate->heap()->false_value());
12319    details->set(kThreadDetailsThreadIdIndex,
12320                 Smi::FromInt(thread->id().ToInteger()));
12321  }
12322
12323  // Convert to JS array and return.
12324  return *isolate->factory()->NewJSArrayWithElements(details);
12325}
12326
12327
12328// Sets the disable break state
12329// args[0]: disable break state
12330RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12331  HandleScope scope(isolate);
12332  ASSERT(args.length() == 1);
12333  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12334  isolate->debug()->set_disable_break(disable_break);
12335  return  isolate->heap()->undefined_value();
12336}
12337
12338
12339static bool IsPositionAlignmentCodeCorrect(int alignment) {
12340  return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12341}
12342
12343
12344RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12345  HandleScope scope(isolate);
12346  ASSERT(args.length() == 2);
12347
12348  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12349  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12350
12351  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12352    return isolate->ThrowIllegalOperation();
12353  }
12354  BreakPositionAlignment alignment =
12355      static_cast<BreakPositionAlignment>(statement_aligned_code);
12356
12357  Handle<SharedFunctionInfo> shared(fun->shared());
12358  // Find the number of break points
12359  Handle<Object> break_locations =
12360      Debug::GetSourceBreakLocations(shared, alignment);
12361  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12362  // Return array as JS array
12363  return *isolate->factory()->NewJSArrayWithElements(
12364      Handle<FixedArray>::cast(break_locations));
12365}
12366
12367
12368// Set a break point in a function.
12369// args[0]: function
12370// args[1]: number: break source position (within the function source)
12371// args[2]: number: break point object
12372RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12373  HandleScope scope(isolate);
12374  ASSERT(args.length() == 3);
12375  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12376  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12377  RUNTIME_ASSERT(source_position >= 0);
12378  Handle<Object> break_point_object_arg = args.at<Object>(2);
12379
12380  // Set break point.
12381  isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12382                                  &source_position);
12383
12384  return Smi::FromInt(source_position);
12385}
12386
12387
12388// Changes the state of a break point in a script and returns source position
12389// where break point was set. NOTE: Regarding performance see the NOTE for
12390// GetScriptFromScriptData.
12391// args[0]: script to set break point in
12392// args[1]: number: break source position (within the script source)
12393// args[2]: number, breakpoint position alignment
12394// args[3]: number: break point object
12395RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12396  HandleScope scope(isolate);
12397  ASSERT(args.length() == 4);
12398  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12399  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12400  RUNTIME_ASSERT(source_position >= 0);
12401  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12402  Handle<Object> break_point_object_arg = args.at<Object>(3);
12403
12404  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12405    return isolate->ThrowIllegalOperation();
12406  }
12407  BreakPositionAlignment alignment =
12408      static_cast<BreakPositionAlignment>(statement_aligned_code);
12409
12410  // Get the script from the script wrapper.
12411  RUNTIME_ASSERT(wrapper->value()->IsScript());
12412  Handle<Script> script(Script::cast(wrapper->value()));
12413
12414  // Set break point.
12415  if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12416                                                &source_position,
12417                                                alignment)) {
12418    return  isolate->heap()->undefined_value();
12419  }
12420
12421  return Smi::FromInt(source_position);
12422}
12423
12424
12425// Clear a break point
12426// args[0]: number: break point object
12427RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12428  HandleScope scope(isolate);
12429  ASSERT(args.length() == 1);
12430  Handle<Object> break_point_object_arg = args.at<Object>(0);
12431
12432  // Clear break point.
12433  isolate->debug()->ClearBreakPoint(break_point_object_arg);
12434
12435  return isolate->heap()->undefined_value();
12436}
12437
12438
12439// Change the state of break on exceptions.
12440// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12441// args[1]: Boolean indicating on/off.
12442RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12443  HandleScope scope(isolate);
12444  ASSERT(args.length() == 2);
12445  RUNTIME_ASSERT(args[0]->IsNumber());
12446  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12447
12448  // If the number doesn't match an enum value, the ChangeBreakOnException
12449  // function will default to affecting caught exceptions.
12450  ExceptionBreakType type =
12451      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12452  // Update break point state.
12453  isolate->debug()->ChangeBreakOnException(type, enable);
12454  return isolate->heap()->undefined_value();
12455}
12456
12457
12458// Returns the state of break on exceptions
12459// args[0]: boolean indicating uncaught exceptions
12460RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12461  HandleScope scope(isolate);
12462  ASSERT(args.length() == 1);
12463  RUNTIME_ASSERT(args[0]->IsNumber());
12464
12465  ExceptionBreakType type =
12466      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12467  bool result = isolate->debug()->IsBreakOnException(type);
12468  return Smi::FromInt(result);
12469}
12470
12471
12472// Prepare for stepping
12473// args[0]: break id for checking execution state
12474// args[1]: step action from the enumeration StepAction
12475// args[2]: number of times to perform the step, for step out it is the number
12476//          of frames to step down.
12477RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12478  HandleScope scope(isolate);
12479  ASSERT(args.length() == 3);
12480  // Check arguments.
12481  Object* check;
12482  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12483      RUNTIME_ARGUMENTS(isolate, args));
12484    if (!maybe_check->ToObject(&check)) return maybe_check;
12485  }
12486  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12487    return isolate->Throw(isolate->heap()->illegal_argument_string());
12488  }
12489
12490  // Get the step action and check validity.
12491  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12492  if (step_action != StepIn &&
12493      step_action != StepNext &&
12494      step_action != StepOut &&
12495      step_action != StepInMin &&
12496      step_action != StepMin) {
12497    return isolate->Throw(isolate->heap()->illegal_argument_string());
12498  }
12499
12500  // Get the number of steps.
12501  int step_count = NumberToInt32(args[2]);
12502  if (step_count < 1) {
12503    return isolate->Throw(isolate->heap()->illegal_argument_string());
12504  }
12505
12506  // Clear all current stepping setup.
12507  isolate->debug()->ClearStepping();
12508
12509  // Prepare step.
12510  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12511                                step_count);
12512  return isolate->heap()->undefined_value();
12513}
12514
12515
12516// Clear all stepping set by PrepareStep.
12517RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12518  HandleScope scope(isolate);
12519  ASSERT(args.length() == 0);
12520  isolate->debug()->ClearStepping();
12521  return isolate->heap()->undefined_value();
12522}
12523
12524
12525// Helper function to find or create the arguments object for
12526// Runtime_DebugEvaluate.
12527static Handle<JSObject> MaterializeArgumentsObject(
12528    Isolate* isolate,
12529    Handle<JSObject> target,
12530    Handle<JSFunction> function) {
12531  // Do not materialize the arguments object for eval or top-level code.
12532  // Skip if "arguments" is already taken.
12533  if (!function->shared()->is_function() ||
12534      target->HasLocalProperty(isolate->heap()->arguments_string())) {
12535    return target;
12536  }
12537
12538  // FunctionGetArguments can't throw an exception.
12539  Handle<JSObject> arguments = Handle<JSObject>::cast(
12540      Accessors::FunctionGetArguments(function));
12541  SetProperty(isolate,
12542              target,
12543              isolate->factory()->arguments_string(),
12544              arguments,
12545              ::NONE,
12546              kNonStrictMode);
12547  return target;
12548}
12549
12550
12551// Compile and evaluate source for the given context.
12552static MaybeObject* DebugEvaluate(Isolate* isolate,
12553                                  Handle<Context> context,
12554                                  Handle<Object> context_extension,
12555                                  Handle<Object> receiver,
12556                                  Handle<String> source) {
12557  if (context_extension->IsJSObject()) {
12558    Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12559    Handle<JSFunction> closure(context->closure(), isolate);
12560    context = isolate->factory()->NewWithContext(closure, context, extension);
12561  }
12562
12563  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
12564      source,
12565      context,
12566      context->IsNativeContext(),
12567      CLASSIC_MODE,
12568      NO_PARSE_RESTRICTION,
12569      RelocInfo::kNoPosition);
12570  RETURN_IF_EMPTY_HANDLE(isolate, shared);
12571
12572  Handle<JSFunction> eval_fun =
12573      isolate->factory()->NewFunctionFromSharedFunctionInfo(
12574          shared, context, NOT_TENURED);
12575  bool pending_exception;
12576  Handle<Object> result = Execution::Call(
12577      eval_fun, receiver, 0, NULL, &pending_exception);
12578
12579  if (pending_exception) return Failure::Exception();
12580
12581  // Skip the global proxy as it has no properties and always delegates to the
12582  // real global object.
12583  if (result->IsJSGlobalProxy()) {
12584    result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12585  }
12586
12587  // Clear the oneshot breakpoints so that the debugger does not step further.
12588  isolate->debug()->ClearStepping();
12589  return *result;
12590}
12591
12592
12593// Evaluate a piece of JavaScript in the context of a stack frame for
12594// debugging.  Things that need special attention are:
12595// - Parameters and stack-allocated locals need to be materialized.  Altered
12596//   values need to be written back to the stack afterwards.
12597// - The arguments object needs to materialized.
12598RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12599  HandleScope scope(isolate);
12600
12601  // Check the execution state and decode arguments frame and source to be
12602  // evaluated.
12603  ASSERT(args.length() == 6);
12604  Object* check_result;
12605  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12606      RUNTIME_ARGUMENTS(isolate, args));
12607    if (!maybe_result->ToObject(&check_result)) return maybe_result;
12608  }
12609  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12610  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12611  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12612  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12613  Handle<Object> context_extension(args[5], isolate);
12614
12615  // Handle the processing of break.
12616  DisableBreak disable_break_save(disable_break);
12617
12618  // Get the frame where the debugging is performed.
12619  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12620  JavaScriptFrameIterator it(isolate, id);
12621  JavaScriptFrame* frame = it.frame();
12622  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12623  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12624
12625  // Traverse the saved contexts chain to find the active context for the
12626  // selected frame.
12627  SaveContext* save = FindSavedContextForFrame(isolate, frame);
12628
12629  SaveContext savex(isolate);
12630  isolate->set_context(*(save->context()));
12631
12632  // Evaluate on the context of the frame.
12633  Handle<Context> context(Context::cast(frame->context()));
12634  ASSERT(!context.is_null());
12635
12636  // Materialize stack locals and the arguments object.
12637  Handle<JSObject> materialized =
12638      isolate->factory()->NewJSObject(isolate->object_function());
12639
12640  materialized = MaterializeStackLocalsWithFrameInspector(
12641      isolate, materialized, function, &frame_inspector);
12642  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12643
12644  materialized = MaterializeArgumentsObject(isolate, materialized, function);
12645  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12646
12647  // Add the materialized object in a with-scope to shadow the stack locals.
12648  context = isolate->factory()->NewWithContext(function, context, materialized);
12649
12650  Handle<Object> receiver(frame->receiver(), isolate);
12651  Object* evaluate_result_object;
12652  { MaybeObject* maybe_result =
12653    DebugEvaluate(isolate, context, context_extension, receiver, source);
12654    if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
12655  }
12656
12657  Handle<Object> result(evaluate_result_object, isolate);
12658
12659  // Write back potential changes to materialized stack locals to the stack.
12660  UpdateStackLocalsFromMaterializedObject(
12661      isolate, materialized, function, frame, inlined_jsframe_index);
12662
12663  return *result;
12664}
12665
12666
12667RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12668  HandleScope scope(isolate);
12669
12670  // Check the execution state and decode arguments frame and source to be
12671  // evaluated.
12672  ASSERT(args.length() == 4);
12673  Object* check_result;
12674  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12675      RUNTIME_ARGUMENTS(isolate, args));
12676    if (!maybe_result->ToObject(&check_result)) return maybe_result;
12677  }
12678  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12679  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12680  Handle<Object> context_extension(args[3], isolate);
12681
12682  // Handle the processing of break.
12683  DisableBreak disable_break_save(disable_break);
12684
12685  // Enter the top context from before the debugger was invoked.
12686  SaveContext save(isolate);
12687  SaveContext* top = &save;
12688  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12689    top = top->prev();
12690  }
12691  if (top != NULL) {
12692    isolate->set_context(*top->context());
12693  }
12694
12695  // Get the native context now set to the top context from before the
12696  // debugger was invoked.
12697  Handle<Context> context = isolate->native_context();
12698  Handle<Object> receiver = isolate->global_object();
12699  return DebugEvaluate(isolate, context, context_extension, receiver, source);
12700}
12701
12702
12703RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12704  HandleScope scope(isolate);
12705  ASSERT(args.length() == 0);
12706
12707  // Fill the script objects.
12708  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12709
12710  // Convert the script objects to proper JS objects.
12711  for (int i = 0; i < instances->length(); i++) {
12712    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12713    // Get the script wrapper in a local handle before calling GetScriptWrapper,
12714    // because using
12715    //   instances->set(i, *GetScriptWrapper(script))
12716    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12717    // already have dereferenced the instances handle.
12718    Handle<JSValue> wrapper = GetScriptWrapper(script);
12719    instances->set(i, *wrapper);
12720  }
12721
12722  // Return result as a JS array.
12723  Handle<JSObject> result =
12724      isolate->factory()->NewJSObject(isolate->array_function());
12725  isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12726  return *result;
12727}
12728
12729
12730// Helper function used by Runtime_DebugReferencedBy below.
12731static int DebugReferencedBy(HeapIterator* iterator,
12732                             JSObject* target,
12733                             Object* instance_filter, int max_references,
12734                             FixedArray* instances, int instances_size,
12735                             JSFunction* arguments_function) {
12736  Isolate* isolate = target->GetIsolate();
12737  SealHandleScope shs(isolate);
12738  DisallowHeapAllocation no_allocation;
12739
12740  // Iterate the heap.
12741  int count = 0;
12742  JSObject* last = NULL;
12743  HeapObject* heap_obj = NULL;
12744  while (((heap_obj = iterator->next()) != NULL) &&
12745         (max_references == 0 || count < max_references)) {
12746    // Only look at all JSObjects.
12747    if (heap_obj->IsJSObject()) {
12748      // Skip context extension objects and argument arrays as these are
12749      // checked in the context of functions using them.
12750      JSObject* obj = JSObject::cast(heap_obj);
12751      if (obj->IsJSContextExtensionObject() ||
12752          obj->map()->constructor() == arguments_function) {
12753        continue;
12754      }
12755
12756      // Check if the JS object has a reference to the object looked for.
12757      if (obj->ReferencesObject(target)) {
12758        // Check instance filter if supplied. This is normally used to avoid
12759        // references from mirror objects (see Runtime_IsInPrototypeChain).
12760        if (!instance_filter->IsUndefined()) {
12761          Object* V = obj;
12762          while (true) {
12763            Object* prototype = V->GetPrototype(isolate);
12764            if (prototype->IsNull()) {
12765              break;
12766            }
12767            if (instance_filter == prototype) {
12768              obj = NULL;  // Don't add this object.
12769              break;
12770            }
12771            V = prototype;
12772          }
12773        }
12774
12775        if (obj != NULL) {
12776          // Valid reference found add to instance array if supplied an update
12777          // count.
12778          if (instances != NULL && count < instances_size) {
12779            instances->set(count, obj);
12780          }
12781          last = obj;
12782          count++;
12783        }
12784      }
12785    }
12786  }
12787
12788  // Check for circular reference only. This can happen when the object is only
12789  // referenced from mirrors and has a circular reference in which case the
12790  // object is not really alive and would have been garbage collected if not
12791  // referenced from the mirror.
12792  if (count == 1 && last == target) {
12793    count = 0;
12794  }
12795
12796  // Return the number of referencing objects found.
12797  return count;
12798}
12799
12800
12801// Scan the heap for objects with direct references to an object
12802// args[0]: the object to find references to
12803// args[1]: constructor function for instances to exclude (Mirror)
12804// args[2]: the the maximum number of objects to return
12805RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12806  SealHandleScope shs(isolate);
12807  ASSERT(args.length() == 3);
12808
12809  // First perform a full GC in order to avoid references from dead objects.
12810  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12811                                     "%DebugReferencedBy");
12812  // The heap iterator reserves the right to do a GC to make the heap iterable.
12813  // Due to the GC above we know it won't need to do that, but it seems cleaner
12814  // to get the heap iterator constructed before we start having unprotected
12815  // Object* locals that are not protected by handles.
12816
12817  // Check parameters.
12818  CONVERT_ARG_CHECKED(JSObject, target, 0);
12819  Object* instance_filter = args[1];
12820  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12821                 instance_filter->IsJSObject());
12822  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12823  RUNTIME_ASSERT(max_references >= 0);
12824
12825
12826  // Get the constructor function for context extension and arguments array.
12827  JSObject* arguments_boilerplate =
12828      isolate->context()->native_context()->arguments_boilerplate();
12829  JSFunction* arguments_function =
12830      JSFunction::cast(arguments_boilerplate->map()->constructor());
12831
12832  // Get the number of referencing objects.
12833  int count;
12834  Heap* heap = isolate->heap();
12835  HeapIterator heap_iterator(heap);
12836  count = DebugReferencedBy(&heap_iterator,
12837                            target, instance_filter, max_references,
12838                            NULL, 0, arguments_function);
12839
12840  // Allocate an array to hold the result.
12841  Object* object;
12842  { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
12843    if (!maybe_object->ToObject(&object)) return maybe_object;
12844  }
12845  FixedArray* instances = FixedArray::cast(object);
12846
12847  // Fill the referencing objects.
12848  // AllocateFixedArray above does not make the heap non-iterable.
12849  ASSERT(heap->IsHeapIterable());
12850  HeapIterator heap_iterator2(heap);
12851  count = DebugReferencedBy(&heap_iterator2,
12852                            target, instance_filter, max_references,
12853                            instances, count, arguments_function);
12854
12855  // Return result as JS array.
12856  Object* result;
12857  MaybeObject* maybe_result = heap->AllocateJSObject(
12858      isolate->context()->native_context()->array_function());
12859  if (!maybe_result->ToObject(&result)) return maybe_result;
12860  return JSArray::cast(result)->SetContent(instances);
12861}
12862
12863
12864// Helper function used by Runtime_DebugConstructedBy below.
12865static int DebugConstructedBy(HeapIterator* iterator,
12866                              JSFunction* constructor,
12867                              int max_references,
12868                              FixedArray* instances,
12869                              int instances_size) {
12870  DisallowHeapAllocation no_allocation;
12871
12872  // Iterate the heap.
12873  int count = 0;
12874  HeapObject* heap_obj = NULL;
12875  while (((heap_obj = iterator->next()) != NULL) &&
12876         (max_references == 0 || count < max_references)) {
12877    // Only look at all JSObjects.
12878    if (heap_obj->IsJSObject()) {
12879      JSObject* obj = JSObject::cast(heap_obj);
12880      if (obj->map()->constructor() == constructor) {
12881        // Valid reference found add to instance array if supplied an update
12882        // count.
12883        if (instances != NULL && count < instances_size) {
12884          instances->set(count, obj);
12885        }
12886        count++;
12887      }
12888    }
12889  }
12890
12891  // Return the number of referencing objects found.
12892  return count;
12893}
12894
12895
12896// Scan the heap for objects constructed by a specific function.
12897// args[0]: the constructor to find instances of
12898// args[1]: the the maximum number of objects to return
12899RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12900  SealHandleScope shs(isolate);
12901  ASSERT(args.length() == 2);
12902
12903  // First perform a full GC in order to avoid dead objects.
12904  Heap* heap = isolate->heap();
12905  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
12906
12907  // Check parameters.
12908  CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12909  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12910  RUNTIME_ASSERT(max_references >= 0);
12911
12912  // Get the number of referencing objects.
12913  int count;
12914  HeapIterator heap_iterator(heap);
12915  count = DebugConstructedBy(&heap_iterator,
12916                             constructor,
12917                             max_references,
12918                             NULL,
12919                             0);
12920
12921  // Allocate an array to hold the result.
12922  Object* object;
12923  { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
12924    if (!maybe_object->ToObject(&object)) return maybe_object;
12925  }
12926  FixedArray* instances = FixedArray::cast(object);
12927
12928  ASSERT(HEAP->IsHeapIterable());
12929  // Fill the referencing objects.
12930  HeapIterator heap_iterator2(heap);
12931  count = DebugConstructedBy(&heap_iterator2,
12932                             constructor,
12933                             max_references,
12934                             instances,
12935                             count);
12936
12937  // Return result as JS array.
12938  Object* result;
12939  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12940      isolate->context()->native_context()->array_function());
12941    if (!maybe_result->ToObject(&result)) return maybe_result;
12942  }
12943  return JSArray::cast(result)->SetContent(instances);
12944}
12945
12946
12947// Find the effective prototype object as returned by __proto__.
12948// args[0]: the object to find the prototype for.
12949RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12950  SealHandleScope shs(isolate);
12951  ASSERT(args.length() == 1);
12952  CONVERT_ARG_CHECKED(JSObject, obj, 0);
12953  return GetPrototypeSkipHiddenPrototypes(isolate, obj);
12954}
12955
12956
12957// Patches script source (should be called upon BeforeCompile event).
12958RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12959  HandleScope scope(isolate);
12960  ASSERT(args.length() == 2);
12961
12962  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12963  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12964
12965  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12966  Handle<Script> script(Script::cast(script_wrapper->value()));
12967
12968  int compilation_state = script->compilation_state();
12969  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12970  script->set_source(*source);
12971
12972  return isolate->heap()->undefined_value();
12973}
12974
12975
12976RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12977  SealHandleScope shs(isolate);
12978  ASSERT(args.length() == 0);
12979  CPU::DebugBreak();
12980  return isolate->heap()->undefined_value();
12981}
12982
12983
12984RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12985  HandleScope scope(isolate);
12986#ifdef DEBUG
12987  ASSERT(args.length() == 1);
12988  // Get the function and make sure it is compiled.
12989  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12990  if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
12991    return Failure::Exception();
12992  }
12993  func->code()->PrintLn();
12994#endif  // DEBUG
12995  return isolate->heap()->undefined_value();
12996}
12997
12998
12999RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
13000  HandleScope scope(isolate);
13001#ifdef DEBUG
13002  ASSERT(args.length() == 1);
13003  // Get the function and make sure it is compiled.
13004  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13005  if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13006    return Failure::Exception();
13007  }
13008  func->shared()->construct_stub()->PrintLn();
13009#endif  // DEBUG
13010  return isolate->heap()->undefined_value();
13011}
13012
13013
13014RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13015  SealHandleScope shs(isolate);
13016  ASSERT(args.length() == 1);
13017
13018  CONVERT_ARG_CHECKED(JSFunction, f, 0);
13019  return f->shared()->inferred_name();
13020}
13021
13022
13023static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13024                                            Script* script,
13025                                            FixedArray* buffer) {
13026  DisallowHeapAllocation no_allocation;
13027  int counter = 0;
13028  int buffer_size = buffer->length();
13029  for (HeapObject* obj = iterator->next();
13030       obj != NULL;
13031       obj = iterator->next()) {
13032    ASSERT(obj != NULL);
13033    if (!obj->IsSharedFunctionInfo()) {
13034      continue;
13035    }
13036    SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13037    if (shared->script() != script) {
13038      continue;
13039    }
13040    if (counter < buffer_size) {
13041      buffer->set(counter, shared);
13042    }
13043    counter++;
13044  }
13045  return counter;
13046}
13047
13048
13049// For a script finds all SharedFunctionInfo's in the heap that points
13050// to this script. Returns JSArray of SharedFunctionInfo wrapped
13051// in OpaqueReferences.
13052RUNTIME_FUNCTION(MaybeObject*,
13053                 Runtime_LiveEditFindSharedFunctionInfosForScript) {
13054  HandleScope scope(isolate);
13055  CHECK(isolate->debugger()->live_edit_enabled());
13056  ASSERT(args.length() == 1);
13057  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13058
13059  RUNTIME_ASSERT(script_value->value()->IsScript());
13060  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13061
13062  const int kBufferSize = 32;
13063
13064  Handle<FixedArray> array;
13065  array = isolate->factory()->NewFixedArray(kBufferSize);
13066  int number;
13067  Heap* heap = isolate->heap();
13068  {
13069    heap->EnsureHeapIsIterable();
13070    DisallowHeapAllocation no_allocation;
13071    HeapIterator heap_iterator(heap);
13072    Script* scr = *script;
13073    FixedArray* arr = *array;
13074    number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13075  }
13076  if (number > kBufferSize) {
13077    array = isolate->factory()->NewFixedArray(number);
13078    heap->EnsureHeapIsIterable();
13079    DisallowHeapAllocation no_allocation;
13080    HeapIterator heap_iterator(heap);
13081    Script* scr = *script;
13082    FixedArray* arr = *array;
13083    FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13084  }
13085
13086  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13087  result->set_length(Smi::FromInt(number));
13088
13089  LiveEdit::WrapSharedFunctionInfos(result);
13090
13091  return *result;
13092}
13093
13094
13095// For a script calculates compilation information about all its functions.
13096// The script source is explicitly specified by the second argument.
13097// The source of the actual script is not used, however it is important that
13098// all generated code keeps references to this particular instance of script.
13099// Returns a JSArray of compilation infos. The array is ordered so that
13100// each function with all its descendant is always stored in a continues range
13101// with the function itself going first. The root function is a script function.
13102RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13103  HandleScope scope(isolate);
13104  CHECK(isolate->debugger()->live_edit_enabled());
13105  ASSERT(args.length() == 2);
13106  CONVERT_ARG_CHECKED(JSValue, script, 0);
13107  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13108
13109  RUNTIME_ASSERT(script->value()->IsScript());
13110  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13111
13112  JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
13113
13114  if (isolate->has_pending_exception()) {
13115    return Failure::Exception();
13116  }
13117
13118  return result;
13119}
13120
13121
13122// Changes the source of the script to a new_source.
13123// If old_script_name is provided (i.e. is a String), also creates a copy of
13124// the script with its original source and sends notification to debugger.
13125RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13126  HandleScope scope(isolate);
13127  CHECK(isolate->debugger()->live_edit_enabled());
13128  ASSERT(args.length() == 3);
13129  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13130  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13131  Handle<Object> old_script_name(args[2], isolate);
13132
13133  RUNTIME_ASSERT(original_script_value->value()->IsScript());
13134  Handle<Script> original_script(Script::cast(original_script_value->value()));
13135
13136  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13137                                                    new_source,
13138                                                    old_script_name);
13139
13140  if (old_script->IsScript()) {
13141    Handle<Script> script_handle(Script::cast(old_script));
13142    return *(GetScriptWrapper(script_handle));
13143  } else {
13144    return isolate->heap()->null_value();
13145  }
13146}
13147
13148
13149RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13150  HandleScope scope(isolate);
13151  CHECK(isolate->debugger()->live_edit_enabled());
13152  ASSERT(args.length() == 1);
13153  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13154  return LiveEdit::FunctionSourceUpdated(shared_info);
13155}
13156
13157
13158// Replaces code of SharedFunctionInfo with a new one.
13159RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13160  HandleScope scope(isolate);
13161  CHECK(isolate->debugger()->live_edit_enabled());
13162  ASSERT(args.length() == 2);
13163  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13164  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13165
13166  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13167}
13168
13169
13170// Connects SharedFunctionInfo to another script.
13171RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13172  HandleScope scope(isolate);
13173  CHECK(isolate->debugger()->live_edit_enabled());
13174  ASSERT(args.length() == 2);
13175  Handle<Object> function_object(args[0], isolate);
13176  Handle<Object> script_object(args[1], isolate);
13177
13178  if (function_object->IsJSValue()) {
13179    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13180    if (script_object->IsJSValue()) {
13181      RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13182      Script* script = Script::cast(JSValue::cast(*script_object)->value());
13183      script_object = Handle<Object>(script, isolate);
13184    }
13185
13186    LiveEdit::SetFunctionScript(function_wrapper, script_object);
13187  } else {
13188    // Just ignore this. We may not have a SharedFunctionInfo for some functions
13189    // and we check it in this function.
13190  }
13191
13192  return isolate->heap()->undefined_value();
13193}
13194
13195
13196// In a code of a parent function replaces original function as embedded object
13197// with a substitution one.
13198RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13199  HandleScope scope(isolate);
13200  CHECK(isolate->debugger()->live_edit_enabled());
13201  ASSERT(args.length() == 3);
13202
13203  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13204  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13205  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13206
13207  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13208                                       subst_wrapper);
13209
13210  return isolate->heap()->undefined_value();
13211}
13212
13213
13214// Updates positions of a shared function info (first parameter) according
13215// to script source change. Text change is described in second parameter as
13216// array of groups of 3 numbers:
13217// (change_begin, change_end, change_end_new_position).
13218// Each group describes a change in text; groups are sorted by change_begin.
13219RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13220  HandleScope scope(isolate);
13221  CHECK(isolate->debugger()->live_edit_enabled());
13222  ASSERT(args.length() == 2);
13223  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13224  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13225
13226  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13227}
13228
13229
13230// For array of SharedFunctionInfo's (each wrapped in JSValue)
13231// checks that none of them have activations on stacks (of any thread).
13232// Returns array of the same length with corresponding results of
13233// LiveEdit::FunctionPatchabilityStatus type.
13234RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13235  HandleScope scope(isolate);
13236  CHECK(isolate->debugger()->live_edit_enabled());
13237  ASSERT(args.length() == 2);
13238  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13239  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13240
13241  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13242}
13243
13244
13245// Compares 2 strings line-by-line, then token-wise and returns diff in form
13246// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13247// of diff chunks.
13248RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13249  HandleScope scope(isolate);
13250  CHECK(isolate->debugger()->live_edit_enabled());
13251  ASSERT(args.length() == 2);
13252  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13253  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13254
13255  return *LiveEdit::CompareStrings(s1, s2);
13256}
13257
13258
13259// Restarts a call frame and completely drops all frames above.
13260// Returns true if successful. Otherwise returns undefined or an error message.
13261RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13262  HandleScope scope(isolate);
13263  CHECK(isolate->debugger()->live_edit_enabled());
13264  ASSERT(args.length() == 2);
13265
13266  // Check arguments.
13267  Object* check;
13268  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13269      RUNTIME_ARGUMENTS(isolate, args));
13270    if (!maybe_check->ToObject(&check)) return maybe_check;
13271  }
13272  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13273  Heap* heap = isolate->heap();
13274
13275  // Find the relevant frame with the requested index.
13276  StackFrame::Id id = isolate->debug()->break_frame_id();
13277  if (id == StackFrame::NO_ID) {
13278    // If there are no JavaScript stack frames return undefined.
13279    return heap->undefined_value();
13280  }
13281
13282  int count = 0;
13283  JavaScriptFrameIterator it(isolate, id);
13284  for (; !it.done(); it.Advance()) {
13285    if (index < count + it.frame()->GetInlineCount()) break;
13286    count += it.frame()->GetInlineCount();
13287  }
13288  if (it.done()) return heap->undefined_value();
13289
13290  const char* error_message = LiveEdit::RestartFrame(it.frame());
13291  if (error_message) {
13292    return *(isolate->factory()->InternalizeUtf8String(error_message));
13293  }
13294  return heap->true_value();
13295}
13296
13297
13298// A testing entry. Returns statement position which is the closest to
13299// source_position.
13300RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13301  HandleScope scope(isolate);
13302  CHECK(isolate->debugger()->live_edit_enabled());
13303  ASSERT(args.length() == 2);
13304  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13305  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13306
13307  Handle<Code> code(function->code(), isolate);
13308
13309  if (code->kind() != Code::FUNCTION &&
13310      code->kind() != Code::OPTIMIZED_FUNCTION) {
13311    return isolate->heap()->undefined_value();
13312  }
13313
13314  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13315  int closest_pc = 0;
13316  int distance = kMaxInt;
13317  while (!it.done()) {
13318    int statement_position = static_cast<int>(it.rinfo()->data());
13319    // Check if this break point is closer that what was previously found.
13320    if (source_position <= statement_position &&
13321        statement_position - source_position < distance) {
13322      closest_pc =
13323          static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13324      distance = statement_position - source_position;
13325      // Check whether we can't get any closer.
13326      if (distance == 0) break;
13327    }
13328    it.next();
13329  }
13330
13331  return Smi::FromInt(closest_pc);
13332}
13333
13334
13335// Calls specified function with or without entering the debugger.
13336// This is used in unit tests to run code as if debugger is entered or simply
13337// to have a stack with C++ frame in the middle.
13338RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13339  HandleScope scope(isolate);
13340  ASSERT(args.length() == 2);
13341  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13342  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13343
13344  Handle<Object> result;
13345  bool pending_exception;
13346  {
13347    if (without_debugger) {
13348      result = Execution::Call(function, isolate->global_object(), 0, NULL,
13349                               &pending_exception);
13350    } else {
13351      EnterDebugger enter_debugger;
13352      result = Execution::Call(function, isolate->global_object(), 0, NULL,
13353                               &pending_exception);
13354    }
13355  }
13356  if (!pending_exception) {
13357    return *result;
13358  } else {
13359    return Failure::Exception();
13360  }
13361}
13362
13363
13364// Sets a v8 flag.
13365RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13366  SealHandleScope shs(isolate);
13367  CONVERT_ARG_CHECKED(String, arg, 0);
13368  SmartArrayPointer<char> flags =
13369      arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13370  FlagList::SetFlagsFromString(*flags, StrLength(*flags));
13371  return isolate->heap()->undefined_value();
13372}
13373
13374
13375// Performs a GC.
13376// Presently, it only does a full GC.
13377RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13378  SealHandleScope shs(isolate);
13379  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13380  return isolate->heap()->undefined_value();
13381}
13382
13383
13384// Gets the current heap usage.
13385RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13386  SealHandleScope shs(isolate);
13387  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13388  if (!Smi::IsValid(usage)) {
13389    return *isolate->factory()->NewNumberFromInt(usage);
13390  }
13391  return Smi::FromInt(usage);
13392}
13393
13394#endif  // ENABLE_DEBUGGER_SUPPORT
13395
13396
13397#ifdef V8_I18N_SUPPORT
13398RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13399  HandleScope scope(isolate);
13400
13401  ASSERT(args.length() == 1);
13402  CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13403
13404  v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13405
13406  // Return value which denotes invalid language tag.
13407  const char* const kInvalidTag = "invalid-tag";
13408
13409  UErrorCode error = U_ZERO_ERROR;
13410  char icu_result[ULOC_FULLNAME_CAPACITY];
13411  int icu_length = 0;
13412
13413  uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13414                      &icu_length, &error);
13415  if (U_FAILURE(error) || icu_length == 0) {
13416    return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13417  }
13418
13419  char result[ULOC_FULLNAME_CAPACITY];
13420
13421  // Force strict BCP47 rules.
13422  uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13423
13424  if (U_FAILURE(error)) {
13425    return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13426  }
13427
13428  return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13429}
13430
13431
13432RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13433  HandleScope scope(isolate);
13434
13435  ASSERT(args.length() == 1);
13436  CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13437
13438  const icu::Locale* available_locales = NULL;
13439  int32_t count = 0;
13440
13441  if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13442    available_locales = icu::Collator::getAvailableLocales(count);
13443  } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13444    available_locales = icu::NumberFormat::getAvailableLocales(count);
13445  } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13446    available_locales = icu::DateFormat::getAvailableLocales(count);
13447  } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13448    available_locales = icu::BreakIterator::getAvailableLocales(count);
13449  }
13450
13451  UErrorCode error = U_ZERO_ERROR;
13452  char result[ULOC_FULLNAME_CAPACITY];
13453  Handle<JSObject> locales =
13454      isolate->factory()->NewJSObject(isolate->object_function());
13455
13456  for (int32_t i = 0; i < count; ++i) {
13457    const char* icu_name = available_locales[i].getName();
13458
13459    error = U_ZERO_ERROR;
13460    // No need to force strict BCP47 rules.
13461    uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13462    if (U_FAILURE(error)) {
13463      // This shouldn't happen, but lets not break the user.
13464      continue;
13465    }
13466
13467    RETURN_IF_EMPTY_HANDLE(isolate,
13468        JSObject::SetLocalPropertyIgnoreAttributes(
13469            locales,
13470            isolate->factory()->NewStringFromAscii(CStrVector(result)),
13471            isolate->factory()->NewNumber(i),
13472            NONE));
13473  }
13474
13475  return *locales;
13476}
13477
13478
13479RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13480  SealHandleScope shs(isolate);
13481
13482  ASSERT(args.length() == 0);
13483
13484  icu::Locale default_locale;
13485
13486  // Set the locale
13487  char result[ULOC_FULLNAME_CAPACITY];
13488  UErrorCode status = U_ZERO_ERROR;
13489  uloc_toLanguageTag(
13490      default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13491  if (U_SUCCESS(status)) {
13492    return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13493  }
13494
13495  return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13496}
13497
13498
13499RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13500  HandleScope scope(isolate);
13501
13502  ASSERT(args.length() == 1);
13503
13504  CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13505
13506  uint32_t length = static_cast<uint32_t>(input->length()->Number());
13507  Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13508  Handle<Name> maximized =
13509      isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13510  Handle<Name> base =
13511      isolate->factory()->NewStringFromAscii(CStrVector("base"));
13512  for (unsigned int i = 0; i < length; ++i) {
13513    MaybeObject* maybe_string = input->GetElement(i);
13514    Object* locale_id;
13515    if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
13516      return isolate->Throw(isolate->heap()->illegal_argument_string());
13517    }
13518
13519    v8::String::Utf8Value utf8_locale_id(
13520        v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
13521
13522    UErrorCode error = U_ZERO_ERROR;
13523
13524    // Convert from BCP47 to ICU format.
13525    // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13526    char icu_locale[ULOC_FULLNAME_CAPACITY];
13527    int icu_locale_length = 0;
13528    uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13529                        &icu_locale_length, &error);
13530    if (U_FAILURE(error) || icu_locale_length == 0) {
13531      return isolate->Throw(isolate->heap()->illegal_argument_string());
13532    }
13533
13534    // Maximize the locale.
13535    // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13536    char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13537    uloc_addLikelySubtags(
13538        icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13539
13540    // Remove extensions from maximized locale.
13541    // de_Latn_DE@collation=phonebook -> de_Latn_DE
13542    char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13543    uloc_getBaseName(
13544        icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13545
13546    // Get original name without extensions.
13547    // de_DE@collation=phonebook -> de_DE
13548    char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13549    uloc_getBaseName(
13550        icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13551
13552    // Convert from ICU locale format to BCP47 format.
13553    // de_Latn_DE -> de-Latn-DE
13554    char base_max_locale[ULOC_FULLNAME_CAPACITY];
13555    uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13556                       ULOC_FULLNAME_CAPACITY, FALSE, &error);
13557
13558    // de_DE -> de-DE
13559    char base_locale[ULOC_FULLNAME_CAPACITY];
13560    uloc_toLanguageTag(
13561        icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13562
13563    if (U_FAILURE(error)) {
13564      return isolate->Throw(isolate->heap()->illegal_argument_string());
13565    }
13566
13567    Handle<JSObject> result =
13568        isolate->factory()->NewJSObject(isolate->object_function());
13569    RETURN_IF_EMPTY_HANDLE(isolate,
13570        JSObject::SetLocalPropertyIgnoreAttributes(
13571            result,
13572            maximized,
13573            isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13574            NONE));
13575    RETURN_IF_EMPTY_HANDLE(isolate,
13576        JSObject::SetLocalPropertyIgnoreAttributes(
13577            result,
13578            base,
13579            isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13580            NONE));
13581    output->set(i, *result);
13582  }
13583
13584  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
13585  result->set_length(Smi::FromInt(length));
13586  return *result;
13587}
13588
13589
13590RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
13591  HandleScope scope(isolate);
13592
13593  ASSERT(args.length() == 3);
13594
13595  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13596  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13597  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13598
13599  Handle<ObjectTemplateInfo> date_format_template =
13600      I18N::GetTemplate(isolate);
13601
13602  // Create an empty object wrapper.
13603  bool has_pending_exception = false;
13604  Handle<JSObject> local_object = Execution::InstantiateObject(
13605      date_format_template, &has_pending_exception);
13606  if (has_pending_exception) {
13607    ASSERT(isolate->has_pending_exception());
13608    return Failure::Exception();
13609  }
13610
13611  // Set date time formatter as internal field of the resulting JS object.
13612  icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
13613      isolate, locale, options, resolved);
13614
13615  if (!date_format) return isolate->ThrowIllegalOperation();
13616
13617  local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
13618
13619  RETURN_IF_EMPTY_HANDLE(isolate,
13620      JSObject::SetLocalPropertyIgnoreAttributes(
13621          local_object,
13622          isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
13623          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13624          NONE));
13625
13626  Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13627                                 v8::Utils::ToLocal(local_object));
13628  // Make object handle weak so we can delete the data format once GC kicks in.
13629  wrapper.MakeWeak<void>(NULL, &DateFormat::DeleteDateFormat);
13630  wrapper.ClearAndLeak();
13631  return *local_object;
13632}
13633
13634
13635RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
13636  HandleScope scope(isolate);
13637
13638  ASSERT(args.length() == 2);
13639
13640  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13641  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
13642
13643  bool has_pending_exception = false;
13644  Handle<Object> value = Execution::ToNumber(date, &has_pending_exception);
13645  if (has_pending_exception) {
13646    ASSERT(isolate->has_pending_exception());
13647    return Failure::Exception();
13648  }
13649
13650  icu::SimpleDateFormat* date_format =
13651      DateFormat::UnpackDateFormat(isolate, date_format_holder);
13652  if (!date_format) return isolate->ThrowIllegalOperation();
13653
13654  icu::UnicodeString result;
13655  date_format->format(value->Number(), result);
13656
13657  return *isolate->factory()->NewStringFromTwoByte(
13658      Vector<const uint16_t>(
13659          reinterpret_cast<const uint16_t*>(result.getBuffer()),
13660          result.length()));
13661}
13662
13663
13664RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
13665  HandleScope scope(isolate);
13666
13667  ASSERT(args.length() == 2);
13668
13669  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13670  CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
13671
13672  v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
13673  icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
13674  icu::SimpleDateFormat* date_format =
13675      DateFormat::UnpackDateFormat(isolate, date_format_holder);
13676  if (!date_format) return isolate->ThrowIllegalOperation();
13677
13678  UErrorCode status = U_ZERO_ERROR;
13679  UDate date = date_format->parse(u_date, status);
13680  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13681
13682  bool has_pending_exception = false;
13683  Handle<JSDate> result = Handle<JSDate>::cast(
13684      Execution::NewDate(static_cast<double>(date), &has_pending_exception));
13685  if (has_pending_exception) {
13686    ASSERT(isolate->has_pending_exception());
13687    return Failure::Exception();
13688  }
13689  return *result;
13690}
13691
13692
13693RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
13694  HandleScope scope(isolate);
13695
13696  ASSERT(args.length() == 3);
13697
13698  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13699  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13700  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13701
13702  Handle<ObjectTemplateInfo> number_format_template =
13703      I18N::GetTemplate(isolate);
13704
13705  // Create an empty object wrapper.
13706  bool has_pending_exception = false;
13707  Handle<JSObject> local_object = Execution::InstantiateObject(
13708      number_format_template, &has_pending_exception);
13709  if (has_pending_exception) {
13710    ASSERT(isolate->has_pending_exception());
13711    return Failure::Exception();
13712  }
13713
13714  // Set number formatter as internal field of the resulting JS object.
13715  icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
13716      isolate, locale, options, resolved);
13717
13718  if (!number_format) return isolate->ThrowIllegalOperation();
13719
13720  local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
13721
13722  RETURN_IF_EMPTY_HANDLE(isolate,
13723      JSObject::SetLocalPropertyIgnoreAttributes(
13724          local_object,
13725          isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
13726          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13727          NONE));
13728
13729  Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13730                                 v8::Utils::ToLocal(local_object));
13731  // Make object handle weak so we can delete the number format once GC kicks
13732  // in.
13733  wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat);
13734  wrapper.ClearAndLeak();
13735  return *local_object;
13736}
13737
13738
13739RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
13740  HandleScope scope(isolate);
13741
13742  ASSERT(args.length() == 2);
13743
13744  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13745  CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
13746
13747  bool has_pending_exception = false;
13748  Handle<Object> value = Execution::ToNumber(number, &has_pending_exception);
13749  if (has_pending_exception) {
13750    ASSERT(isolate->has_pending_exception());
13751    return Failure::Exception();
13752  }
13753
13754  icu::DecimalFormat* number_format =
13755      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13756  if (!number_format) return isolate->ThrowIllegalOperation();
13757
13758  icu::UnicodeString result;
13759  number_format->format(value->Number(), result);
13760
13761  return *isolate->factory()->NewStringFromTwoByte(
13762      Vector<const uint16_t>(
13763          reinterpret_cast<const uint16_t*>(result.getBuffer()),
13764          result.length()));
13765}
13766
13767
13768RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
13769  HandleScope scope(isolate);
13770
13771  ASSERT(args.length() == 2);
13772
13773  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13774  CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
13775
13776  v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
13777  icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
13778  icu::DecimalFormat* number_format =
13779      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13780  if (!number_format) return isolate->ThrowIllegalOperation();
13781
13782  UErrorCode status = U_ZERO_ERROR;
13783  icu::Formattable result;
13784  // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
13785  // to be part of Chrome.
13786  // TODO(cira): Include currency parsing code using parseCurrency call.
13787  // We need to check if the formatter parses all currencies or only the
13788  // one it was constructed with (it will impact the API - how to return ISO
13789  // code and the value).
13790  number_format->parse(u_number, result, status);
13791  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13792
13793  switch (result.getType()) {
13794  case icu::Formattable::kDouble:
13795    return *isolate->factory()->NewNumber(result.getDouble());
13796  case icu::Formattable::kLong:
13797    return *isolate->factory()->NewNumberFromInt(result.getLong());
13798  case icu::Formattable::kInt64:
13799    return *isolate->factory()->NewNumber(
13800        static_cast<double>(result.getInt64()));
13801  default:
13802    return isolate->heap()->undefined_value();
13803  }
13804}
13805
13806
13807RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
13808  HandleScope scope(isolate);
13809
13810  ASSERT(args.length() == 3);
13811
13812  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13813  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13814  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13815
13816  Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
13817
13818  // Create an empty object wrapper.
13819  bool has_pending_exception = false;
13820  Handle<JSObject> local_object = Execution::InstantiateObject(
13821      collator_template, &has_pending_exception);
13822  if (has_pending_exception) {
13823    ASSERT(isolate->has_pending_exception());
13824    return Failure::Exception();
13825  }
13826
13827  // Set collator as internal field of the resulting JS object.
13828  icu::Collator* collator = Collator::InitializeCollator(
13829      isolate, locale, options, resolved);
13830
13831  if (!collator) return isolate->ThrowIllegalOperation();
13832
13833  local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
13834
13835  RETURN_IF_EMPTY_HANDLE(isolate,
13836      JSObject::SetLocalPropertyIgnoreAttributes(
13837          local_object,
13838          isolate->factory()->NewStringFromAscii(CStrVector("collator")),
13839          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13840          NONE));
13841
13842  Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13843                                 v8::Utils::ToLocal(local_object));
13844  // Make object handle weak so we can delete the collator once GC kicks in.
13845  wrapper.MakeWeak<void>(NULL, &Collator::DeleteCollator);
13846  wrapper.ClearAndLeak();
13847  return *local_object;
13848}
13849
13850
13851RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
13852  HandleScope scope(isolate);
13853
13854  ASSERT(args.length() == 3);
13855
13856  CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
13857  CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
13858  CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
13859
13860  icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
13861  if (!collator) return isolate->ThrowIllegalOperation();
13862
13863  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
13864  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
13865  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
13866  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
13867  UErrorCode status = U_ZERO_ERROR;
13868  UCollationResult result = collator->compare(u_string1,
13869                                              string_value1.length(),
13870                                              u_string2,
13871                                              string_value2.length(),
13872                                              status);
13873  if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
13874
13875  return *isolate->factory()->NewNumberFromInt(result);
13876}
13877#endif  // V8_I18N_SUPPORT
13878
13879
13880// Finds the script object from the script data. NOTE: This operation uses
13881// heap traversal to find the function generated for the source position
13882// for the requested break point. For lazily compiled functions several heap
13883// traversals might be required rendering this operation as a rather slow
13884// operation. However for setting break points which is normally done through
13885// some kind of user interaction the performance is not crucial.
13886static Handle<Object> Runtime_GetScriptFromScriptName(
13887    Handle<String> script_name) {
13888  // Scan the heap for Script objects to find the script with the requested
13889  // script data.
13890  Handle<Script> script;
13891  Factory* factory = script_name->GetIsolate()->factory();
13892  Heap* heap = script_name->GetHeap();
13893  heap->EnsureHeapIsIterable();
13894  DisallowHeapAllocation no_allocation_during_heap_iteration;
13895  HeapIterator iterator(heap);
13896  HeapObject* obj = NULL;
13897  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
13898    // If a script is found check if it has the script data requested.
13899    if (obj->IsScript()) {
13900      if (Script::cast(obj)->name()->IsString()) {
13901        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
13902          script = Handle<Script>(Script::cast(obj));
13903        }
13904      }
13905    }
13906  }
13907
13908  // If no script with the requested script data is found return undefined.
13909  if (script.is_null()) return factory->undefined_value();
13910
13911  // Return the script found.
13912  return GetScriptWrapper(script);
13913}
13914
13915
13916// Get the script object from script data. NOTE: Regarding performance
13917// see the NOTE for GetScriptFromScriptData.
13918// args[0]: script data for the script to find the source for
13919RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
13920  HandleScope scope(isolate);
13921
13922  ASSERT(args.length() == 1);
13923
13924  CONVERT_ARG_CHECKED(String, script_name, 0);
13925
13926  // Find the requested script.
13927  Handle<Object> result =
13928      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
13929  return *result;
13930}
13931
13932
13933// Collect the raw data for a stack trace.  Returns an array of 4
13934// element segments each containing a receiver, function, code and
13935// native code offset.
13936RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
13937  HandleScope scope(isolate);
13938  ASSERT_EQ(args.length(), 3);
13939  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
13940  Handle<Object> caller = args.at<Object>(1);
13941  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
13942
13943  // Optionally capture a more detailed stack trace for the message.
13944  isolate->CaptureAndSetDetailedStackTrace(error_object);
13945  // Capture a simple stack trace for the stack property.
13946  return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
13947}
13948
13949
13950// Retrieve the stack trace.  This is the raw stack trace that yet has to
13951// be formatted.  Since we only need this once, clear it afterwards.
13952RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
13953  HandleScope scope(isolate);
13954  ASSERT_EQ(args.length(), 1);
13955  CONVERT_ARG_CHECKED(JSObject, error_object, 0);
13956  String* key = isolate->heap()->hidden_stack_trace_string();
13957  Object* result = error_object->GetHiddenProperty(key);
13958  if (result->IsTheHole()) return isolate->heap()->undefined_value();
13959  RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
13960  error_object->DeleteHiddenProperty(key);
13961  return result;
13962}
13963
13964
13965// Returns V8 version as a string.
13966RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
13967  SealHandleScope shs(isolate);
13968  ASSERT_EQ(args.length(), 0);
13969
13970  const char* version_string = v8::V8::GetVersion();
13971
13972  return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
13973                                                  NOT_TENURED);
13974}
13975
13976
13977RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13978  SealHandleScope shs(isolate);
13979  ASSERT(args.length() == 2);
13980  OS::PrintError("abort: %s\n",
13981                 reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13982  isolate->PrintStack(stderr);
13983  OS::Abort();
13984  UNREACHABLE();
13985  return NULL;
13986}
13987
13988
13989RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
13990  HandleScope scope(isolate);
13991  ASSERT(args.length() == 1);
13992  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
13993  FlattenString(str);
13994  return isolate->heap()->undefined_value();
13995}
13996
13997
13998RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
13999  HandleScope scope(isolate);
14000  ASSERT(args.length() == 0);
14001  isolate->heap()->NotifyContextDisposed();
14002  return isolate->heap()->undefined_value();
14003}
14004
14005
14006RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
14007  HandleScope scope(isolate);
14008  ASSERT(args.length() == 1);
14009  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14010  if (!object->IsJSObject()) return Smi::FromInt(0);
14011  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14012  if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14013  JSObject::MigrateInstance(js_object);
14014  return *object;
14015}
14016
14017
14018RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
14019  SealHandleScope shs(isolate);
14020  // This is only called from codegen, so checks might be more lax.
14021  CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14022  Object* key = args[1];
14023
14024  int finger_index = cache->finger_index();
14025  Object* o = cache->get(finger_index);
14026  if (o == key) {
14027    // The fastest case: hit the same place again.
14028    return cache->get(finger_index + 1);
14029  }
14030
14031  for (int i = finger_index - 2;
14032       i >= JSFunctionResultCache::kEntriesIndex;
14033       i -= 2) {
14034    o = cache->get(i);
14035    if (o == key) {
14036      cache->set_finger_index(i);
14037      return cache->get(i + 1);
14038    }
14039  }
14040
14041  int size = cache->size();
14042  ASSERT(size <= cache->length());
14043
14044  for (int i = size - 2; i > finger_index; i -= 2) {
14045    o = cache->get(i);
14046    if (o == key) {
14047      cache->set_finger_index(i);
14048      return cache->get(i + 1);
14049    }
14050  }
14051
14052  // There is no value in the cache.  Invoke the function and cache result.
14053  HandleScope scope(isolate);
14054
14055  Handle<JSFunctionResultCache> cache_handle(cache);
14056  Handle<Object> key_handle(key, isolate);
14057  Handle<Object> value;
14058  {
14059    Handle<JSFunction> factory(JSFunction::cast(
14060          cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14061    // TODO(antonm): consider passing a receiver when constructing a cache.
14062    Handle<Object> receiver(isolate->native_context()->global_object(),
14063                            isolate);
14064    // This handle is nor shared, nor used later, so it's safe.
14065    Handle<Object> argv[] = { key_handle };
14066    bool pending_exception;
14067    value = Execution::Call(factory,
14068                            receiver,
14069                            ARRAY_SIZE(argv),
14070                            argv,
14071                            &pending_exception);
14072    if (pending_exception) return Failure::Exception();
14073  }
14074
14075#ifdef VERIFY_HEAP
14076  if (FLAG_verify_heap) {
14077    cache_handle->JSFunctionResultCacheVerify();
14078  }
14079#endif
14080
14081  // Function invocation may have cleared the cache.  Reread all the data.
14082  finger_index = cache_handle->finger_index();
14083  size = cache_handle->size();
14084
14085  // If we have spare room, put new data into it, otherwise evict post finger
14086  // entry which is likely to be the least recently used.
14087  int index = -1;
14088  if (size < cache_handle->length()) {
14089    cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14090    index = size;
14091  } else {
14092    index = finger_index + JSFunctionResultCache::kEntrySize;
14093    if (index == cache_handle->length()) {
14094      index = JSFunctionResultCache::kEntriesIndex;
14095    }
14096  }
14097
14098  ASSERT(index % 2 == 0);
14099  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14100  ASSERT(index < cache_handle->length());
14101
14102  cache_handle->set(index, *key_handle);
14103  cache_handle->set(index + 1, *value);
14104  cache_handle->set_finger_index(index);
14105
14106#ifdef VERIFY_HEAP
14107  if (FLAG_verify_heap) {
14108    cache_handle->JSFunctionResultCacheVerify();
14109  }
14110#endif
14111
14112  return *value;
14113}
14114
14115
14116RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14117  SealHandleScope shs(isolate);
14118  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14119  return Smi::FromInt(message->start_position());
14120}
14121
14122
14123RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14124  SealHandleScope shs(isolate);
14125  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14126  return message->script();
14127}
14128
14129
14130#ifdef DEBUG
14131// ListNatives is ONLY used by the fuzz-natives.js in debug mode
14132// Exclude the code in release mode.
14133RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14134  HandleScope scope(isolate);
14135  ASSERT(args.length() == 0);
14136#define COUNT_ENTRY(Name, argc, ressize) + 1
14137  int entry_count = 0
14138      RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14139      INLINE_FUNCTION_LIST(COUNT_ENTRY)
14140      INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
14141#undef COUNT_ENTRY
14142  Factory* factory = isolate->factory();
14143  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14144  int index = 0;
14145  bool inline_runtime_functions = false;
14146#define ADD_ENTRY(Name, argc, ressize)                                       \
14147  {                                                                          \
14148    HandleScope inner(isolate);                                              \
14149    Handle<String> name;                                                     \
14150    /* Inline runtime functions have an underscore in front of the name. */  \
14151    if (inline_runtime_functions) {                                          \
14152      name = factory->NewStringFromAscii(                                    \
14153          Vector<const char>("_" #Name, StrLength("_" #Name)));              \
14154    } else {                                                                 \
14155      name = factory->NewStringFromAscii(                                    \
14156          Vector<const char>(#Name, StrLength(#Name)));                      \
14157    }                                                                        \
14158    Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14159    pair_elements->set(0, *name);                                            \
14160    pair_elements->set(1, Smi::FromInt(argc));                               \
14161    Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14162    elements->set(index++, *pair);                                           \
14163  }
14164  inline_runtime_functions = false;
14165  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14166  inline_runtime_functions = true;
14167  INLINE_FUNCTION_LIST(ADD_ENTRY)
14168  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14169#undef ADD_ENTRY
14170  ASSERT_EQ(index, entry_count);
14171  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14172  return *result;
14173}
14174#endif
14175
14176
14177RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
14178  SealHandleScope shs(isolate);
14179  ASSERT(args.length() == 2);
14180  CONVERT_ARG_CHECKED(String, format, 0);
14181  CONVERT_ARG_CHECKED(JSArray, elms, 1);
14182  DisallowHeapAllocation no_gc;
14183  String::FlatContent format_content = format->GetFlatContent();
14184  RUNTIME_ASSERT(format_content.IsAscii());
14185  Vector<const uint8_t> chars = format_content.ToOneByteVector();
14186  isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
14187  return isolate->heap()->undefined_value();
14188}
14189
14190
14191RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14192  UNREACHABLE();  // implemented as macro in the parser
14193  return NULL;
14194}
14195
14196
14197#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14198  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
14199    CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
14200    return isolate->heap()->ToBoolean(obj->Has##Name());  \
14201  }
14202
14203ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14204ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14205ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14206ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14207ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14208ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14209ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
14210ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
14211ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14212ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
14213ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
14214ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
14215ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
14216ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
14217ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
14218ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
14219ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
14220// Properties test sitting with elements tests - not fooling anyone.
14221ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14222
14223#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14224
14225
14226RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14227  SealHandleScope shs(isolate);
14228  ASSERT(args.length() == 2);
14229  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14230  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14231  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14232}
14233
14234
14235RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14236  SealHandleScope shs(isolate);
14237  ASSERT(args.length() == 1);
14238
14239  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14240  JSReceiver* obj = JSReceiver::cast(args[0]);
14241  if (obj->IsJSGlobalProxy()) {
14242    Object* proto = obj->GetPrototype();
14243    if (proto->IsNull()) return isolate->heap()->false_value();
14244    ASSERT(proto->IsJSGlobalObject());
14245    obj = JSReceiver::cast(proto);
14246  }
14247  return isolate->heap()->ToBoolean(obj->map()->is_observed());
14248}
14249
14250
14251RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14252  SealHandleScope shs(isolate);
14253  ASSERT(args.length() == 1);
14254  CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
14255  if (obj->IsJSGlobalProxy()) {
14256    Object* proto = obj->GetPrototype();
14257    if (proto->IsNull()) return isolate->heap()->undefined_value();
14258    ASSERT(proto->IsJSGlobalObject());
14259    obj = JSReceiver::cast(proto);
14260  }
14261  if (obj->IsJSProxy())
14262    return isolate->heap()->undefined_value();
14263
14264  ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14265           JSObject::cast(obj)->HasFastElements()));
14266  ASSERT(obj->IsJSObject());
14267  return JSObject::cast(obj)->SetObserved(isolate);
14268}
14269
14270
14271RUNTIME_FUNCTION(MaybeObject*, Runtime_SetObserverDeliveryPending) {
14272  SealHandleScope shs(isolate);
14273  ASSERT(args.length() == 0);
14274  isolate->set_observer_delivery_pending(true);
14275  return isolate->heap()->undefined_value();
14276}
14277
14278
14279RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14280  SealHandleScope shs(isolate);
14281  ASSERT(args.length() == 0);
14282  return isolate->heap()->observation_state();
14283}
14284
14285
14286RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14287  HandleScope scope(isolate);
14288  ASSERT(args.length() == 0);
14289  // TODO(adamk): Currently this runtime function is only called three times per
14290  // isolate. If it's called more often, the map should be moved into the
14291  // strong root list.
14292  Handle<Map> map =
14293      isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14294  Handle<JSWeakMap> weakmap =
14295      Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14296  return WeakCollectionInitialize(isolate, weakmap);
14297}
14298
14299
14300RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14301  SealHandleScope shs(isolate);
14302  ASSERT(args.length() == 1);
14303  Object* object = args[0];
14304  if (object->IsJSGlobalProxy()) {
14305    object = object->GetPrototype(isolate);
14306    if (object->IsNull()) return isolate->heap()->undefined_value();
14307  }
14308  return object;
14309}
14310
14311
14312static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14313                                           Handle<JSFunction> constructor,
14314                                           Handle<Object> type_info,
14315                                           Arguments* caller_args) {
14316  bool holey = false;
14317  bool can_use_type_feedback = true;
14318  if (caller_args->length() == 1) {
14319    Object* argument_one = (*caller_args)[0];
14320    if (argument_one->IsSmi()) {
14321      int value = Smi::cast(argument_one)->value();
14322      if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
14323        // the array is a dictionary in this case.
14324        can_use_type_feedback = false;
14325      } else if (value != 0) {
14326        holey = true;
14327      }
14328    } else {
14329      // Non-smi length argument produces a dictionary
14330      can_use_type_feedback = false;
14331    }
14332  }
14333
14334  JSArray* array;
14335  MaybeObject* maybe_array;
14336  if (!type_info.is_null() &&
14337      *type_info != isolate->heap()->undefined_value() &&
14338      Cell::cast(*type_info)->value()->IsAllocationSite() &&
14339      can_use_type_feedback) {
14340    Handle<Cell> cell = Handle<Cell>::cast(type_info);
14341    Handle<AllocationSite> site = Handle<AllocationSite>(
14342        AllocationSite::cast(cell->value()), isolate);
14343    ASSERT(!site->IsLiteralSite());
14344    ElementsKind to_kind = site->GetElementsKind();
14345    if (holey && !IsFastHoleyElementsKind(to_kind)) {
14346      to_kind = GetHoleyElementsKind(to_kind);
14347      // Update the allocation site info to reflect the advice alteration.
14348      site->SetElementsKind(to_kind);
14349    }
14350
14351    maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
14352        *constructor, site);
14353    if (!maybe_array->To(&array)) return maybe_array;
14354  } else {
14355    maybe_array = isolate->heap()->AllocateJSObject(*constructor);
14356    if (!maybe_array->To(&array)) return maybe_array;
14357    // We might need to transition to holey
14358    ElementsKind kind = constructor->initial_map()->elements_kind();
14359    if (holey && !IsFastHoleyElementsKind(kind)) {
14360      kind = GetHoleyElementsKind(kind);
14361      maybe_array = array->TransitionElementsKind(kind);
14362      if (maybe_array->IsFailure()) return maybe_array;
14363    }
14364  }
14365
14366  maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
14367      DONT_INITIALIZE_ARRAY_ELEMENTS);
14368  if (maybe_array->IsFailure()) return maybe_array;
14369  maybe_array = ArrayConstructInitializeElements(array, caller_args);
14370  if (maybe_array->IsFailure()) return maybe_array;
14371  return array;
14372}
14373
14374
14375RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
14376  HandleScope scope(isolate);
14377  // If we get 2 arguments then they are the stub parameters (constructor, type
14378  // info).  If we get 3, then the first one is a pointer to the arguments
14379  // passed by the caller.
14380  Arguments empty_args(0, NULL);
14381  bool no_caller_args = args.length() == 2;
14382  ASSERT(no_caller_args || args.length() == 3);
14383  int parameters_start = no_caller_args ? 0 : 1;
14384  Arguments* caller_args = no_caller_args
14385      ? &empty_args
14386      : reinterpret_cast<Arguments*>(args[0]);
14387  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14388  CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
14389
14390  return ArrayConstructorCommon(isolate,
14391                                constructor,
14392                                type_info,
14393                                caller_args);
14394}
14395
14396
14397RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
14398  HandleScope scope(isolate);
14399  Arguments empty_args(0, NULL);
14400  bool no_caller_args = args.length() == 1;
14401  ASSERT(no_caller_args || args.length() == 2);
14402  int parameters_start = no_caller_args ? 0 : 1;
14403  Arguments* caller_args = no_caller_args
14404      ? &empty_args
14405      : reinterpret_cast<Arguments*>(args[0]);
14406  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14407
14408  return ArrayConstructorCommon(isolate,
14409                                constructor,
14410                                Handle<Object>::null(),
14411                                caller_args);
14412}
14413
14414
14415// ----------------------------------------------------------------------------
14416// Implementation of Runtime
14417
14418#define F(name, number_of_args, result_size)                             \
14419  { Runtime::k##name, Runtime::RUNTIME, #name,   \
14420    FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
14421
14422
14423#define I(name, number_of_args, result_size)                             \
14424  { Runtime::kInline##name, Runtime::INLINE,     \
14425    "_" #name, NULL, number_of_args, result_size },
14426
14427static const Runtime::Function kIntrinsicFunctions[] = {
14428  RUNTIME_FUNCTION_LIST(F)
14429  INLINE_FUNCTION_LIST(I)
14430  INLINE_RUNTIME_FUNCTION_LIST(I)
14431};
14432
14433
14434MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
14435                                                       Object* dictionary) {
14436  ASSERT(Isolate::Current()->heap() == heap);
14437  ASSERT(dictionary != NULL);
14438  ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
14439  for (int i = 0; i < kNumFunctions; ++i) {
14440    Object* name_string;
14441    { MaybeObject* maybe_name_string =
14442          heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
14443      if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
14444    }
14445    NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
14446    { MaybeObject* maybe_dictionary = name_dictionary->Add(
14447          String::cast(name_string),
14448          Smi::FromInt(i),
14449          PropertyDetails(NONE, NORMAL, Representation::None()));
14450      if (!maybe_dictionary->ToObject(&dictionary)) {
14451        // Non-recoverable failure.  Calling code must restart heap
14452        // initialization.
14453        return maybe_dictionary;
14454      }
14455    }
14456  }
14457  return dictionary;
14458}
14459
14460
14461const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
14462  Heap* heap = name->GetHeap();
14463  int entry = heap->intrinsic_function_names()->FindEntry(*name);
14464  if (entry != kNotFound) {
14465    Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
14466    int function_index = Smi::cast(smi_index)->value();
14467    return &(kIntrinsicFunctions[function_index]);
14468  }
14469  return NULL;
14470}
14471
14472
14473const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
14474  return &(kIntrinsicFunctions[static_cast<int>(id)]);
14475}
14476
14477
14478void Runtime::PerformGC(Object* result) {
14479  Isolate* isolate = Isolate::Current();
14480  Failure* failure = Failure::cast(result);
14481  if (failure->IsRetryAfterGC()) {
14482    if (isolate->heap()->new_space()->AddFreshPage()) {
14483      return;
14484    }
14485
14486    // Try to do a garbage collection; ignore it if it fails. The C
14487    // entry stub will throw an out-of-memory exception in that case.
14488    isolate->heap()->CollectGarbage(failure->allocation_space(),
14489                                    "Runtime::PerformGC");
14490  } else {
14491    // Handle last resort GC and make sure to allow future allocations
14492    // to grow the heap without causing GCs (if possible).
14493    isolate->counters()->gc_last_resort_from_js()->Increment();
14494    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14495                                       "Runtime::PerformGC");
14496  }
14497}
14498
14499
14500} }  // namespace v8::internal
14501