Home | History | Annotate | Download | only in src
      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 
     30 #include "v8.h"
     31 
     32 #include "accessors.h"
     33 #include "api.h"
     34 #include "arguments.h"
     35 #include "bootstrapper.h"
     36 #include "codegen.h"
     37 #include "compilation-cache.h"
     38 #include "compiler.h"
     39 #include "cpu.h"
     40 #include "dateparser-inl.h"
     41 #include "debug.h"
     42 #include "deoptimizer.h"
     43 #include "date.h"
     44 #include "execution.h"
     45 #include "global-handles.h"
     46 #include "isolate-inl.h"
     47 #include "jsregexp.h"
     48 #include "json-parser.h"
     49 #include "liveedit.h"
     50 #include "liveobjectlist-inl.h"
     51 #include "misc-intrinsics.h"
     52 #include "parser.h"
     53 #include "platform.h"
     54 #include "runtime-profiler.h"
     55 #include "runtime.h"
     56 #include "scopeinfo.h"
     57 #include "smart-array-pointer.h"
     58 #include "string-search.h"
     59 #include "stub-cache.h"
     60 #include "v8threads.h"
     61 #include "vm-state-inl.h"
     62 
     63 namespace v8 {
     64 namespace internal {
     65 
     66 
     67 #define RUNTIME_ASSERT(value) \
     68   if (!(value)) return isolate->ThrowIllegalOperation();
     69 
     70 // Cast the given object to a value of the specified type and store
     71 // it in a variable with the given name.  If the object is not of the
     72 // expected type call IllegalOperation and return.
     73 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
     74   RUNTIME_ASSERT(args[index]->Is##Type());                           \
     75   Type* name = Type::cast(args[index]);
     76 
     77 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
     78   RUNTIME_ASSERT(args[index]->Is##Type());                           \
     79   Handle<Type> name = args.at<Type>(index);
     80 
     81 // Cast the given object to a boolean and store it in a variable with
     82 // the given name.  If the object is not a boolean call IllegalOperation
     83 // and return.
     84 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
     85   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
     86   bool name = args[index]->IsTrue();
     87 
     88 // Cast the given argument to a Smi and store its value in an int variable
     89 // with the given name.  If the argument is not a Smi call IllegalOperation
     90 // and return.
     91 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
     92   RUNTIME_ASSERT(args[index]->IsSmi());                              \
     93   int name = args.smi_at(index);
     94 
     95 // Cast the given argument to a double and store it in a variable with
     96 // the given name.  If the argument is not a number (as opposed to
     97 // the number not-a-number) call IllegalOperation and return.
     98 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
     99   RUNTIME_ASSERT(args[index]->IsNumber());                           \
    100   double name = args.number_at(index);
    101 
    102 // Call the specified converter on the object *comand store the result in
    103 // a variable of the specified type with the given name.  If the
    104 // object is not a Number call IllegalOperation and return.
    105 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
    106   RUNTIME_ASSERT(obj->IsNumber());                                   \
    107   type name = NumberTo##Type(obj);
    108 
    109 
    110 // Cast the given argument to PropertyDetails and store its value in a
    111 // variable with the given name.  If the argument is not a Smi call
    112 // IllegalOperation and return.
    113 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
    114   RUNTIME_ASSERT(args[index]->IsSmi());                              \
    115   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
    116 
    117 
    118 // Assert that the given argument has a valid value for a StrictModeFlag
    119 // and store it in a StrictModeFlag variable with the given name.
    120 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
    121   RUNTIME_ASSERT(args[index]->IsSmi());                              \
    122   RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
    123                  args.smi_at(index) == kNonStrictMode);              \
    124   StrictModeFlag name =                                              \
    125       static_cast<StrictModeFlag>(args.smi_at(index));
    126 
    127 
    128 // Assert that the given argument has a valid value for a LanguageMode
    129 // and store it in a LanguageMode variable with the given name.
    130 #define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
    131   ASSERT(args[index]->IsSmi());                                      \
    132   ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
    133          args.smi_at(index) == STRICT_MODE ||                        \
    134          args.smi_at(index) == EXTENDED_MODE);                       \
    135   LanguageMode name =                                                \
    136       static_cast<LanguageMode>(args.smi_at(index));
    137 
    138 
    139 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
    140                                                    JSObject* boilerplate) {
    141   StackLimitCheck check(isolate);
    142   if (check.HasOverflowed()) return isolate->StackOverflow();
    143 
    144   Heap* heap = isolate->heap();
    145   Object* result;
    146   { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
    147     if (!maybe_result->ToObject(&result)) return maybe_result;
    148   }
    149   JSObject* copy = JSObject::cast(result);
    150 
    151   // Deep copy local properties.
    152   if (copy->HasFastProperties()) {
    153     FixedArray* properties = copy->properties();
    154     for (int i = 0; i < properties->length(); i++) {
    155       Object* value = properties->get(i);
    156       if (value->IsJSObject()) {
    157         JSObject* js_object = JSObject::cast(value);
    158         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
    159           if (!maybe_result->ToObject(&result)) return maybe_result;
    160         }
    161         properties->set(i, result);
    162       }
    163     }
    164     int nof = copy->map()->inobject_properties();
    165     for (int i = 0; i < nof; i++) {
    166       Object* value = copy->InObjectPropertyAt(i);
    167       if (value->IsJSObject()) {
    168         JSObject* js_object = JSObject::cast(value);
    169         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
    170           if (!maybe_result->ToObject(&result)) return maybe_result;
    171         }
    172         copy->InObjectPropertyAtPut(i, result);
    173       }
    174     }
    175   } else {
    176     { MaybeObject* maybe_result =
    177           heap->AllocateFixedArray(copy->NumberOfLocalProperties());
    178       if (!maybe_result->ToObject(&result)) return maybe_result;
    179     }
    180     FixedArray* names = FixedArray::cast(result);
    181     copy->GetLocalPropertyNames(names, 0);
    182     for (int i = 0; i < names->length(); i++) {
    183       ASSERT(names->get(i)->IsString());
    184       String* key_string = String::cast(names->get(i));
    185       PropertyAttributes attributes =
    186           copy->GetLocalPropertyAttribute(key_string);
    187       // Only deep copy fields from the object literal expression.
    188       // In particular, don't try to copy the length attribute of
    189       // an array.
    190       if (attributes != NONE) continue;
    191       Object* value =
    192           copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
    193       if (value->IsJSObject()) {
    194         JSObject* js_object = JSObject::cast(value);
    195         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
    196           if (!maybe_result->ToObject(&result)) return maybe_result;
    197         }
    198         { MaybeObject* maybe_result =
    199               // Creating object copy for literals. No strict mode needed.
    200               copy->SetProperty(key_string, result, NONE, kNonStrictMode);
    201           if (!maybe_result->ToObject(&result)) return maybe_result;
    202         }
    203       }
    204     }
    205   }
    206 
    207   // Deep copy local elements.
    208   // Pixel elements cannot be created using an object literal.
    209   ASSERT(!copy->HasExternalArrayElements());
    210   switch (copy->GetElementsKind()) {
    211     case FAST_SMI_ONLY_ELEMENTS:
    212     case FAST_ELEMENTS: {
    213       FixedArray* elements = FixedArray::cast(copy->elements());
    214       if (elements->map() == heap->fixed_cow_array_map()) {
    215         isolate->counters()->cow_arrays_created_runtime()->Increment();
    216 #ifdef DEBUG
    217         for (int i = 0; i < elements->length(); i++) {
    218           ASSERT(!elements->get(i)->IsJSObject());
    219         }
    220 #endif
    221       } else {
    222         for (int i = 0; i < elements->length(); i++) {
    223           Object* value = elements->get(i);
    224           ASSERT(value->IsSmi() ||
    225                  value->IsTheHole() ||
    226                  (copy->GetElementsKind() == FAST_ELEMENTS));
    227           if (value->IsJSObject()) {
    228             JSObject* js_object = JSObject::cast(value);
    229             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
    230                                                               js_object);
    231               if (!maybe_result->ToObject(&result)) return maybe_result;
    232             }
    233             elements->set(i, result);
    234           }
    235         }
    236       }
    237       break;
    238     }
    239     case DICTIONARY_ELEMENTS: {
    240       SeededNumberDictionary* element_dictionary = copy->element_dictionary();
    241       int capacity = element_dictionary->Capacity();
    242       for (int i = 0; i < capacity; i++) {
    243         Object* k = element_dictionary->KeyAt(i);
    244         if (element_dictionary->IsKey(k)) {
    245           Object* value = element_dictionary->ValueAt(i);
    246           if (value->IsJSObject()) {
    247             JSObject* js_object = JSObject::cast(value);
    248             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
    249                                                               js_object);
    250               if (!maybe_result->ToObject(&result)) return maybe_result;
    251             }
    252             element_dictionary->ValueAtPut(i, result);
    253           }
    254         }
    255       }
    256       break;
    257     }
    258     case NON_STRICT_ARGUMENTS_ELEMENTS:
    259       UNIMPLEMENTED();
    260       break;
    261     case EXTERNAL_PIXEL_ELEMENTS:
    262     case EXTERNAL_BYTE_ELEMENTS:
    263     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
    264     case EXTERNAL_SHORT_ELEMENTS:
    265     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
    266     case EXTERNAL_INT_ELEMENTS:
    267     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
    268     case EXTERNAL_FLOAT_ELEMENTS:
    269     case EXTERNAL_DOUBLE_ELEMENTS:
    270     case FAST_DOUBLE_ELEMENTS:
    271       // No contained objects, nothing to do.
    272       break;
    273   }
    274   return copy;
    275 }
    276 
    277 
    278 static Handle<Map> ComputeObjectLiteralMap(
    279     Handle<Context> context,
    280     Handle<FixedArray> constant_properties,
    281     bool* is_result_from_cache) {
    282   Isolate* isolate = context->GetIsolate();
    283   int properties_length = constant_properties->length();
    284   int number_of_properties = properties_length / 2;
    285   // Check that there are only symbols and array indices among keys.
    286   int number_of_symbol_keys = 0;
    287   for (int p = 0; p != properties_length; p += 2) {
    288     Object* key = constant_properties->get(p);
    289     uint32_t element_index = 0;
    290     if (key->IsSymbol()) {
    291       number_of_symbol_keys++;
    292     } else if (key->ToArrayIndex(&element_index)) {
    293       // An index key does not require space in the property backing store.
    294       number_of_properties--;
    295     } else {
    296       // Bail out as a non-symbol non-index key makes caching impossible.
    297       // ASSERT to make sure that the if condition after the loop is false.
    298       ASSERT(number_of_symbol_keys != number_of_properties);
    299       break;
    300     }
    301   }
    302   // If we only have symbols and array indices among keys then we can
    303   // use the map cache in the global context.
    304   const int kMaxKeys = 10;
    305   if ((number_of_symbol_keys == number_of_properties) &&
    306       (number_of_symbol_keys < kMaxKeys)) {
    307     // Create the fixed array with the key.
    308     Handle<FixedArray> keys =
    309         isolate->factory()->NewFixedArray(number_of_symbol_keys);
    310     if (number_of_symbol_keys > 0) {
    311       int index = 0;
    312       for (int p = 0; p < properties_length; p += 2) {
    313         Object* key = constant_properties->get(p);
    314         if (key->IsSymbol()) {
    315           keys->set(index++, key);
    316         }
    317       }
    318       ASSERT(index == number_of_symbol_keys);
    319     }
    320     *is_result_from_cache = true;
    321     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
    322   }
    323   *is_result_from_cache = false;
    324   return isolate->factory()->CopyMap(
    325       Handle<Map>(context->object_function()->initial_map()),
    326       number_of_properties);
    327 }
    328 
    329 
    330 static Handle<Object> CreateLiteralBoilerplate(
    331     Isolate* isolate,
    332     Handle<FixedArray> literals,
    333     Handle<FixedArray> constant_properties);
    334 
    335 
    336 static Handle<Object> CreateObjectLiteralBoilerplate(
    337     Isolate* isolate,
    338     Handle<FixedArray> literals,
    339     Handle<FixedArray> constant_properties,
    340     bool should_have_fast_elements,
    341     bool has_function_literal) {
    342   // Get the global context from the literals array.  This is the
    343   // context in which the function was created and we use the object
    344   // function from this context to create the object literal.  We do
    345   // not use the object function from the current global context
    346   // because this might be the object function from another context
    347   // which we should not have access to.
    348   Handle<Context> context =
    349       Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
    350 
    351   // In case we have function literals, we want the object to be in
    352   // slow properties mode for now. We don't go in the map cache because
    353   // maps with constant functions can't be shared if the functions are
    354   // not the same (which is the common case).
    355   bool is_result_from_cache = false;
    356   Handle<Map> map = has_function_literal
    357       ? Handle<Map>(context->object_function()->initial_map())
    358       : ComputeObjectLiteralMap(context,
    359                                 constant_properties,
    360                                 &is_result_from_cache);
    361 
    362   Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
    363 
    364   // Normalize the elements of the boilerplate to save space if needed.
    365   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
    366 
    367   // Add the constant properties to the boilerplate.
    368   int length = constant_properties->length();
    369   bool should_transform =
    370       !is_result_from_cache && boilerplate->HasFastProperties();
    371   if (should_transform || has_function_literal) {
    372     // Normalize the properties of object to avoid n^2 behavior
    373     // when extending the object multiple properties. Indicate the number of
    374     // properties to be added.
    375     JSObject::NormalizeProperties(
    376         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
    377   }
    378 
    379   for (int index = 0; index < length; index +=2) {
    380     Handle<Object> key(constant_properties->get(index+0), isolate);
    381     Handle<Object> value(constant_properties->get(index+1), isolate);
    382     if (value->IsFixedArray()) {
    383       // The value contains the constant_properties of a
    384       // simple object or array literal.
    385       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
    386       value = CreateLiteralBoilerplate(isolate, literals, array);
    387       if (value.is_null()) return value;
    388     }
    389     Handle<Object> result;
    390     uint32_t element_index = 0;
    391     if (key->IsSymbol()) {
    392       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
    393         // Array index as string (uint32).
    394         result = JSObject::SetOwnElement(
    395             boilerplate, element_index, value, kNonStrictMode);
    396       } else {
    397         Handle<String> name(String::cast(*key));
    398         ASSERT(!name->AsArrayIndex(&element_index));
    399         result = JSObject::SetLocalPropertyIgnoreAttributes(
    400             boilerplate, name, value, NONE);
    401       }
    402     } else if (key->ToArrayIndex(&element_index)) {
    403       // Array index (uint32).
    404       result = JSObject::SetOwnElement(
    405           boilerplate, element_index, value, kNonStrictMode);
    406     } else {
    407       // Non-uint32 number.
    408       ASSERT(key->IsNumber());
    409       double num = key->Number();
    410       char arr[100];
    411       Vector<char> buffer(arr, ARRAY_SIZE(arr));
    412       const char* str = DoubleToCString(num, buffer);
    413       Handle<String> name =
    414           isolate->factory()->NewStringFromAscii(CStrVector(str));
    415       result = JSObject::SetLocalPropertyIgnoreAttributes(
    416           boilerplate, name, value, NONE);
    417     }
    418     // If setting the property on the boilerplate throws an
    419     // exception, the exception is converted to an empty handle in
    420     // the handle based operations.  In that case, we need to
    421     // convert back to an exception.
    422     if (result.is_null()) return result;
    423   }
    424 
    425   // Transform to fast properties if necessary. For object literals with
    426   // containing function literals we defer this operation until after all
    427   // computed properties have been assigned so that we can generate
    428   // constant function properties.
    429   if (should_transform && !has_function_literal) {
    430     JSObject::TransformToFastProperties(
    431         boilerplate, boilerplate->map()->unused_property_fields());
    432   }
    433 
    434   return boilerplate;
    435 }
    436 
    437 
    438 MaybeObject* TransitionElements(Handle<Object> object,
    439                                 ElementsKind to_kind,
    440                                 Isolate* isolate) {
    441   HandleScope scope(isolate);
    442   if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
    443   ElementsKind from_kind =
    444       Handle<JSObject>::cast(object)->map()->elements_kind();
    445   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
    446     Handle<Object> result = JSObject::TransitionElementsKind(
    447         Handle<JSObject>::cast(object), to_kind);
    448     if (result.is_null()) return isolate->ThrowIllegalOperation();
    449     return *result;
    450   }
    451   return isolate->ThrowIllegalOperation();
    452 }
    453 
    454 
    455 static const int kSmiOnlyLiteralMinimumLength = 1024;
    456 
    457 
    458 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
    459     Isolate* isolate,
    460     Handle<FixedArray> literals,
    461     Handle<FixedArray> elements) {
    462   // Create the JSArray.
    463   Handle<JSFunction> constructor(
    464       JSFunction::GlobalContextFromLiterals(*literals)->array_function());
    465   Handle<JSArray> object =
    466       Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor));
    467 
    468   ElementsKind constant_elements_kind =
    469       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
    470   Handle<FixedArrayBase> constant_elements_values(
    471       FixedArrayBase::cast(elements->get(1)));
    472 
    473   Context* global_context = isolate->context()->global_context();
    474   if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) {
    475     object->set_map(Map::cast(global_context->smi_js_array_map()));
    476   } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
    477     object->set_map(Map::cast(global_context->double_js_array_map()));
    478   } else {
    479     object->set_map(Map::cast(global_context->object_js_array_map()));
    480   }
    481 
    482   Handle<FixedArrayBase> copied_elements_values;
    483   if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
    484     ASSERT(FLAG_smi_only_arrays);
    485     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
    486         Handle<FixedDoubleArray>::cast(constant_elements_values));
    487   } else {
    488     ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
    489            constant_elements_kind == FAST_ELEMENTS);
    490     const bool is_cow =
    491         (constant_elements_values->map() ==
    492          isolate->heap()->fixed_cow_array_map());
    493     if (is_cow) {
    494       copied_elements_values = constant_elements_values;
    495 #if DEBUG
    496       Handle<FixedArray> fixed_array_values =
    497           Handle<FixedArray>::cast(copied_elements_values);
    498       for (int i = 0; i < fixed_array_values->length(); i++) {
    499         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
    500       }
    501 #endif
    502     } else {
    503       Handle<FixedArray> fixed_array_values =
    504           Handle<FixedArray>::cast(constant_elements_values);
    505       Handle<FixedArray> fixed_array_values_copy =
    506           isolate->factory()->CopyFixedArray(fixed_array_values);
    507       copied_elements_values = fixed_array_values_copy;
    508       for (int i = 0; i < fixed_array_values->length(); i++) {
    509         Object* current = fixed_array_values->get(i);
    510         if (current->IsFixedArray()) {
    511           // The value contains the constant_properties of a
    512           // simple object or array literal.
    513           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
    514           Handle<Object> result =
    515               CreateLiteralBoilerplate(isolate, literals, fa);
    516           if (result.is_null()) return result;
    517           fixed_array_values_copy->set(i, *result);
    518         }
    519       }
    520     }
    521   }
    522   object->set_elements(*copied_elements_values);
    523   object->set_length(Smi::FromInt(copied_elements_values->length()));
    524 
    525   //  Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is
    526   //  on or the object is larger than the threshold.
    527   if (!FLAG_smi_only_arrays &&
    528       constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) {
    529     if (object->GetElementsKind() != FAST_ELEMENTS) {
    530       CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
    531     }
    532   }
    533 
    534   return object;
    535 }
    536 
    537 
    538 static Handle<Object> CreateLiteralBoilerplate(
    539     Isolate* isolate,
    540     Handle<FixedArray> literals,
    541     Handle<FixedArray> array) {
    542   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
    543   const bool kHasNoFunctionLiteral = false;
    544   switch (CompileTimeValue::GetType(array)) {
    545     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
    546       return CreateObjectLiteralBoilerplate(isolate,
    547                                             literals,
    548                                             elements,
    549                                             true,
    550                                             kHasNoFunctionLiteral);
    551     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
    552       return CreateObjectLiteralBoilerplate(isolate,
    553                                             literals,
    554                                             elements,
    555                                             false,
    556                                             kHasNoFunctionLiteral);
    557     case CompileTimeValue::ARRAY_LITERAL:
    558       return Runtime::CreateArrayLiteralBoilerplate(
    559           isolate, literals, elements);
    560     default:
    561       UNREACHABLE();
    562       return Handle<Object>::null();
    563   }
    564 }
    565 
    566 
    567 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
    568   HandleScope scope(isolate);
    569   ASSERT(args.length() == 4);
    570   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
    571   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
    572   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
    573   CONVERT_SMI_ARG_CHECKED(flags, 3);
    574   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
    575   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
    576 
    577   // Check if boilerplate exists. If not, create it first.
    578   Handle<Object> boilerplate(literals->get(literals_index), isolate);
    579   if (*boilerplate == isolate->heap()->undefined_value()) {
    580     boilerplate = CreateObjectLiteralBoilerplate(isolate,
    581                                                  literals,
    582                                                  constant_properties,
    583                                                  should_have_fast_elements,
    584                                                  has_function_literal);
    585     if (boilerplate.is_null()) return Failure::Exception();
    586     // Update the functions literal and return the boilerplate.
    587     literals->set(literals_index, *boilerplate);
    588   }
    589   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
    590 }
    591 
    592 
    593 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
    594   HandleScope scope(isolate);
    595   ASSERT(args.length() == 4);
    596   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
    597   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
    598   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
    599   CONVERT_SMI_ARG_CHECKED(flags, 3);
    600   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
    601   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
    602 
    603   // Check if boilerplate exists. If not, create it first.
    604   Handle<Object> boilerplate(literals->get(literals_index), isolate);
    605   if (*boilerplate == isolate->heap()->undefined_value()) {
    606     boilerplate = CreateObjectLiteralBoilerplate(isolate,
    607                                                  literals,
    608                                                  constant_properties,
    609                                                  should_have_fast_elements,
    610                                                  has_function_literal);
    611     if (boilerplate.is_null()) return Failure::Exception();
    612     // Update the functions literal and return the boilerplate.
    613     literals->set(literals_index, *boilerplate);
    614   }
    615   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
    616 }
    617 
    618 
    619 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
    620   HandleScope scope(isolate);
    621   ASSERT(args.length() == 3);
    622   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
    623   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
    624   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
    625 
    626   // Check if boilerplate exists. If not, create it first.
    627   Handle<Object> boilerplate(literals->get(literals_index), isolate);
    628   if (*boilerplate == isolate->heap()->undefined_value()) {
    629     boilerplate =
    630         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
    631     if (boilerplate.is_null()) return Failure::Exception();
    632     // Update the functions literal and return the boilerplate.
    633     literals->set(literals_index, *boilerplate);
    634   }
    635   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
    636 }
    637 
    638 
    639 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
    640   HandleScope scope(isolate);
    641   ASSERT(args.length() == 3);
    642   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
    643   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
    644   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
    645 
    646   // Check if boilerplate exists. If not, create it first.
    647   Handle<Object> boilerplate(literals->get(literals_index), isolate);
    648   if (*boilerplate == isolate->heap()->undefined_value()) {
    649     ASSERT(*elements != isolate->heap()->empty_fixed_array());
    650     boilerplate =
    651         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
    652     if (boilerplate.is_null()) return Failure::Exception();
    653     // Update the functions literal and return the boilerplate.
    654     literals->set(literals_index, *boilerplate);
    655   }
    656   if (JSObject::cast(*boilerplate)->elements()->map() ==
    657       isolate->heap()->fixed_cow_array_map()) {
    658     isolate->counters()->cow_arrays_created_runtime()->Increment();
    659   }
    660   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
    661 }
    662 
    663 
    664 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
    665   ASSERT(args.length() == 2);
    666   Object* handler = args[0];
    667   Object* prototype = args[1];
    668   Object* used_prototype =
    669       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
    670   return isolate->heap()->AllocateJSProxy(handler, used_prototype);
    671 }
    672 
    673 
    674 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
    675   ASSERT(args.length() == 4);
    676   Object* handler = args[0];
    677   Object* call_trap = args[1];
    678   Object* construct_trap = args[2];
    679   Object* prototype = args[3];
    680   Object* used_prototype =
    681       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
    682   return isolate->heap()->AllocateJSFunctionProxy(
    683       handler, call_trap, construct_trap, used_prototype);
    684 }
    685 
    686 
    687 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
    688   ASSERT(args.length() == 1);
    689   Object* obj = args[0];
    690   return isolate->heap()->ToBoolean(obj->IsJSProxy());
    691 }
    692 
    693 
    694 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
    695   ASSERT(args.length() == 1);
    696   Object* obj = args[0];
    697   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
    698 }
    699 
    700 
    701 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
    702   ASSERT(args.length() == 1);
    703   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
    704   return proxy->handler();
    705 }
    706 
    707 
    708 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
    709   ASSERT(args.length() == 1);
    710   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
    711   return proxy->call_trap();
    712 }
    713 
    714 
    715 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
    716   ASSERT(args.length() == 1);
    717   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
    718   return proxy->construct_trap();
    719 }
    720 
    721 
    722 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
    723   ASSERT(args.length() == 1);
    724   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
    725   proxy->Fix();
    726   return isolate->heap()->undefined_value();
    727 }
    728 
    729 
    730 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
    731   HandleScope scope(isolate);
    732   ASSERT(args.length() == 1);
    733   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
    734   Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
    735   holder->set_table(*table);
    736   return *holder;
    737 }
    738 
    739 
    740 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
    741   HandleScope scope(isolate);
    742   ASSERT(args.length() == 2);
    743   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
    744   Handle<Object> key(args[1]);
    745   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
    746   table = ObjectHashSetAdd(table, key);
    747   holder->set_table(*table);
    748   return isolate->heap()->undefined_symbol();
    749 }
    750 
    751 
    752 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
    753   HandleScope scope(isolate);
    754   ASSERT(args.length() == 2);
    755   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
    756   Handle<Object> key(args[1]);
    757   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
    758   return isolate->heap()->ToBoolean(table->Contains(*key));
    759 }
    760 
    761 
    762 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
    763   HandleScope scope(isolate);
    764   ASSERT(args.length() == 2);
    765   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
    766   Handle<Object> key(args[1]);
    767   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
    768   table = ObjectHashSetRemove(table, key);
    769   holder->set_table(*table);
    770   return isolate->heap()->undefined_symbol();
    771 }
    772 
    773 
    774 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
    775   HandleScope scope(isolate);
    776   ASSERT(args.length() == 1);
    777   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
    778   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
    779   holder->set_table(*table);
    780   return *holder;
    781 }
    782 
    783 
    784 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
    785   HandleScope scope(isolate);
    786   ASSERT(args.length() == 2);
    787   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
    788   Handle<Object> key(args[1]);
    789   return ObjectHashTable::cast(holder->table())->Lookup(*key);
    790 }
    791 
    792 
    793 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
    794   HandleScope scope(isolate);
    795   ASSERT(args.length() == 3);
    796   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
    797   Handle<Object> key(args[1]);
    798   Handle<Object> value(args[2]);
    799   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
    800   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
    801   holder->set_table(*new_table);
    802   return *value;
    803 }
    804 
    805 
    806 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
    807   HandleScope scope(isolate);
    808   ASSERT(args.length() == 1);
    809   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
    810   ASSERT(weakmap->map()->inobject_properties() == 0);
    811   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
    812   weakmap->set_table(*table);
    813   weakmap->set_next(Smi::FromInt(0));
    814   return *weakmap;
    815 }
    816 
    817 
    818 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
    819   NoHandleAllocation ha;
    820   ASSERT(args.length() == 2);
    821   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
    822   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
    823   return ObjectHashTable::cast(weakmap->table())->Lookup(*key);
    824 }
    825 
    826 
    827 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
    828   HandleScope scope(isolate);
    829   ASSERT(args.length() == 3);
    830   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
    831   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
    832   Handle<Object> value(args[2]);
    833   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
    834   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
    835   weakmap->set_table(*new_table);
    836   return *value;
    837 }
    838 
    839 
    840 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
    841   NoHandleAllocation ha;
    842   ASSERT(args.length() == 1);
    843   Object* obj = args[0];
    844   if (!obj->IsJSObject()) return isolate->heap()->null_value();
    845   return JSObject::cast(obj)->class_name();
    846 }
    847 
    848 
    849 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
    850   NoHandleAllocation ha;
    851   ASSERT(args.length() == 1);
    852   CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
    853   Object* obj = input_obj;
    854   // We don't expect access checks to be needed on JSProxy objects.
    855   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
    856   do {
    857     if (obj->IsAccessCheckNeeded() &&
    858         !isolate->MayNamedAccess(JSObject::cast(obj),
    859                                  isolate->heap()->Proto_symbol(),
    860                                  v8::ACCESS_GET)) {
    861       isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
    862       return isolate->heap()->undefined_value();
    863     }
    864     obj = obj->GetPrototype();
    865   } while (obj->IsJSObject() &&
    866            JSObject::cast(obj)->map()->is_hidden_prototype());
    867   return obj;
    868 }
    869 
    870 
    871 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
    872   NoHandleAllocation ha;
    873   ASSERT(args.length() == 2);
    874   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
    875   Object* O = args[0];
    876   Object* V = args[1];
    877   while (true) {
    878     Object* prototype = V->GetPrototype();
    879     if (prototype->IsNull()) return isolate->heap()->false_value();
    880     if (O == prototype) return isolate->heap()->true_value();
    881     V = prototype;
    882   }
    883 }
    884 
    885 
    886 // Recursively traverses hidden prototypes if property is not found
    887 static void GetOwnPropertyImplementation(JSObject* obj,
    888                                          String* name,
    889                                          LookupResult* result) {
    890   obj->LocalLookupRealNamedProperty(name, result);
    891 
    892   if (!result->IsProperty()) {
    893     Object* proto = obj->GetPrototype();
    894     if (proto->IsJSObject() &&
    895       JSObject::cast(proto)->map()->is_hidden_prototype())
    896       GetOwnPropertyImplementation(JSObject::cast(proto),
    897                                    name, result);
    898   }
    899 }
    900 
    901 
    902 static bool CheckAccessException(LookupResult* result,
    903                                  v8::AccessType access_type) {
    904   if (result->type() == CALLBACKS) {
    905     Object* callback = result->GetCallbackObject();
    906     if (callback->IsAccessorInfo()) {
    907       AccessorInfo* info = AccessorInfo::cast(callback);
    908       bool can_access =
    909           (access_type == v8::ACCESS_HAS &&
    910               (info->all_can_read() || info->all_can_write())) ||
    911           (access_type == v8::ACCESS_GET && info->all_can_read()) ||
    912           (access_type == v8::ACCESS_SET && info->all_can_write());
    913       return can_access;
    914     }
    915   }
    916 
    917   return false;
    918 }
    919 
    920 
    921 static bool CheckAccess(JSObject* obj,
    922                         String* name,
    923                         LookupResult* result,
    924                         v8::AccessType access_type) {
    925   ASSERT(result->IsProperty());
    926 
    927   JSObject* holder = result->holder();
    928   JSObject* current = obj;
    929   Isolate* isolate = obj->GetIsolate();
    930   while (true) {
    931     if (current->IsAccessCheckNeeded() &&
    932         !isolate->MayNamedAccess(current, name, access_type)) {
    933       // Access check callback denied the access, but some properties
    934       // can have a special permissions which override callbacks descision
    935       // (currently see v8::AccessControl).
    936       break;
    937     }
    938 
    939     if (current == holder) {
    940       return true;
    941     }
    942 
    943     current = JSObject::cast(current->GetPrototype());
    944   }
    945 
    946   // API callbacks can have per callback access exceptions.
    947   switch (result->type()) {
    948     case CALLBACKS: {
    949       if (CheckAccessException(result, access_type)) {
    950         return true;
    951       }
    952       break;
    953     }
    954     case INTERCEPTOR: {
    955       // If the object has an interceptor, try real named properties.
    956       // Overwrite the result to fetch the correct property later.
    957       holder->LookupRealNamedProperty(name, result);
    958       if (result->IsProperty()) {
    959         if (CheckAccessException(result, access_type)) {
    960           return true;
    961         }
    962       }
    963       break;
    964     }
    965     default:
    966       break;
    967   }
    968 
    969   isolate->ReportFailedAccessCheck(current, access_type);
    970   return false;
    971 }
    972 
    973 
    974 // TODO(1095): we should traverse hidden prototype hierachy as well.
    975 static bool CheckElementAccess(JSObject* obj,
    976                                uint32_t index,
    977                                v8::AccessType access_type) {
    978   if (obj->IsAccessCheckNeeded() &&
    979       !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
    980     return false;
    981   }
    982 
    983   return true;
    984 }
    985 
    986 
    987 // Enumerator used as indices into the array returned from GetOwnProperty
    988 enum PropertyDescriptorIndices {
    989   IS_ACCESSOR_INDEX,
    990   VALUE_INDEX,
    991   GETTER_INDEX,
    992   SETTER_INDEX,
    993   WRITABLE_INDEX,
    994   ENUMERABLE_INDEX,
    995   CONFIGURABLE_INDEX,
    996   DESCRIPTOR_SIZE
    997 };
    998 
    999 
   1000 static MaybeObject* GetOwnProperty(Isolate* isolate,
   1001                                    Handle<JSObject> obj,
   1002                                    Handle<String> name) {
   1003   Heap* heap = isolate->heap();
   1004   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
   1005   Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
   1006   LookupResult result(isolate);
   1007   // This could be an element.
   1008   uint32_t index;
   1009   if (name->AsArrayIndex(&index)) {
   1010     switch (obj->HasLocalElement(index)) {
   1011       case JSObject::UNDEFINED_ELEMENT:
   1012         return heap->undefined_value();
   1013 
   1014       case JSObject::STRING_CHARACTER_ELEMENT: {
   1015         // Special handling of string objects according to ECMAScript 5
   1016         // 15.5.5.2. Note that this might be a string object with elements
   1017         // other than the actual string value. This is covered by the
   1018         // subsequent cases.
   1019         Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
   1020         Handle<String> str(String::cast(js_value->value()));
   1021         Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
   1022 
   1023         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
   1024         elms->set(VALUE_INDEX, *substr);
   1025         elms->set(WRITABLE_INDEX, heap->false_value());
   1026         elms->set(ENUMERABLE_INDEX,  heap->true_value());
   1027         elms->set(CONFIGURABLE_INDEX, heap->false_value());
   1028         return *desc;
   1029       }
   1030 
   1031       case JSObject::INTERCEPTED_ELEMENT:
   1032       case JSObject::FAST_ELEMENT: {
   1033         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
   1034         Handle<Object> value = Object::GetElement(obj, index);
   1035         RETURN_IF_EMPTY_HANDLE(isolate, value);
   1036         elms->set(VALUE_INDEX, *value);
   1037         elms->set(WRITABLE_INDEX, heap->true_value());
   1038         elms->set(ENUMERABLE_INDEX,  heap->true_value());
   1039         elms->set(CONFIGURABLE_INDEX, heap->true_value());
   1040         return *desc;
   1041       }
   1042 
   1043       case JSObject::DICTIONARY_ELEMENT: {
   1044         Handle<JSObject> holder = obj;
   1045         if (obj->IsJSGlobalProxy()) {
   1046           Object* proto = obj->GetPrototype();
   1047           if (proto->IsNull()) return heap->undefined_value();
   1048           ASSERT(proto->IsJSGlobalObject());
   1049           holder = Handle<JSObject>(JSObject::cast(proto));
   1050         }
   1051         FixedArray* elements = FixedArray::cast(holder->elements());
   1052         SeededNumberDictionary* dictionary = NULL;
   1053         if (elements->map() == heap->non_strict_arguments_elements_map()) {
   1054           dictionary = SeededNumberDictionary::cast(elements->get(1));
   1055         } else {
   1056           dictionary = SeededNumberDictionary::cast(elements);
   1057         }
   1058         int entry = dictionary->FindEntry(index);
   1059         ASSERT(entry != SeededNumberDictionary::kNotFound);
   1060         PropertyDetails details = dictionary->DetailsAt(entry);
   1061         switch (details.type()) {
   1062           case CALLBACKS: {
   1063             // This is an accessor property with getter and/or setter.
   1064             AccessorPair* accessors =
   1065                 AccessorPair::cast(dictionary->ValueAt(entry));
   1066             elms->set(IS_ACCESSOR_INDEX, heap->true_value());
   1067             if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
   1068               elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
   1069             }
   1070             if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
   1071               elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
   1072             }
   1073             break;
   1074           }
   1075           case NORMAL: {
   1076             // This is a data property.
   1077             elms->set(IS_ACCESSOR_INDEX, heap->false_value());
   1078             Handle<Object> value = Object::GetElement(obj, index);
   1079             ASSERT(!value.is_null());
   1080             elms->set(VALUE_INDEX, *value);
   1081             elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
   1082             break;
   1083           }
   1084           default:
   1085             UNREACHABLE();
   1086             break;
   1087         }
   1088         elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
   1089         elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
   1090         return *desc;
   1091       }
   1092     }
   1093   }
   1094 
   1095   // Use recursive implementation to also traverse hidden prototypes
   1096   GetOwnPropertyImplementation(*obj, *name, &result);
   1097 
   1098   if (!result.IsProperty()) {
   1099     return heap->undefined_value();
   1100   }
   1101 
   1102   if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
   1103     return heap->false_value();
   1104   }
   1105 
   1106   elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
   1107   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
   1108 
   1109   bool is_js_accessor = (result.type() == CALLBACKS) &&
   1110                         (result.GetCallbackObject()->IsAccessorPair());
   1111 
   1112   if (is_js_accessor) {
   1113     // __defineGetter__/__defineSetter__ callback.
   1114     elms->set(IS_ACCESSOR_INDEX, heap->true_value());
   1115 
   1116     AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
   1117     if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
   1118       elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
   1119     }
   1120     if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
   1121       elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
   1122     }
   1123   } else {
   1124     elms->set(IS_ACCESSOR_INDEX, heap->false_value());
   1125     elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
   1126 
   1127     PropertyAttributes attrs;
   1128     Object* value;
   1129     // GetProperty will check access and report any violations.
   1130     { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
   1131       if (!maybe_value->ToObject(&value)) return maybe_value;
   1132     }
   1133     elms->set(VALUE_INDEX, value);
   1134   }
   1135 
   1136   return *desc;
   1137 }
   1138 
   1139 
   1140 // Returns an array with the property description:
   1141 //  if args[1] is not a property on args[0]
   1142 //          returns undefined
   1143 //  if args[1] is a data property on args[0]
   1144 //         [false, value, Writeable, Enumerable, Configurable]
   1145 //  if args[1] is an accessor on args[0]
   1146 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
   1147 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
   1148   ASSERT(args.length() == 2);
   1149   HandleScope scope(isolate);
   1150   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
   1151   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
   1152   return GetOwnProperty(isolate, obj, name);
   1153 }
   1154 
   1155 
   1156 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
   1157   ASSERT(args.length() == 1);
   1158   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   1159   return obj->PreventExtensions();
   1160 }
   1161 
   1162 
   1163 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
   1164   ASSERT(args.length() == 1);
   1165   CONVERT_ARG_CHECKED(JSObject, obj, 0);
   1166   if (obj->IsJSGlobalProxy()) {
   1167     Object* proto = obj->GetPrototype();
   1168     if (proto->IsNull()) return isolate->heap()->false_value();
   1169     ASSERT(proto->IsJSGlobalObject());
   1170     obj = JSObject::cast(proto);
   1171   }
   1172   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
   1173 }
   1174 
   1175 
   1176 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
   1177   HandleScope scope(isolate);
   1178   ASSERT(args.length() == 3);
   1179   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
   1180   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
   1181   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
   1182   Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
   1183   if (result.is_null()) return Failure::Exception();
   1184   return *result;
   1185 }
   1186 
   1187 
   1188 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
   1189   HandleScope scope(isolate);
   1190   ASSERT(args.length() == 1);
   1191   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
   1192   return *isolate->factory()->CreateApiFunction(data);
   1193 }
   1194 
   1195 
   1196 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
   1197   ASSERT(args.length() == 1);
   1198   Object* arg = args[0];
   1199   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
   1200   return isolate->heap()->ToBoolean(result);
   1201 }
   1202 
   1203 
   1204 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
   1205   ASSERT(args.length() == 2);
   1206   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
   1207   CONVERT_SMI_ARG_CHECKED(index, 1)
   1208   int offset = index * kPointerSize + HeapObject::kHeaderSize;
   1209   InstanceType type = templ->map()->instance_type();
   1210   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
   1211                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
   1212   RUNTIME_ASSERT(offset > 0);
   1213   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
   1214     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
   1215   } else {
   1216     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
   1217   }
   1218   return *HeapObject::RawField(templ, offset);
   1219 }
   1220 
   1221 
   1222 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
   1223   ASSERT(args.length() == 1);
   1224   CONVERT_ARG_CHECKED(HeapObject, object, 0);
   1225   Map* old_map = object->map();
   1226   bool needs_access_checks = old_map->is_access_check_needed();
   1227   if (needs_access_checks) {
   1228     // Copy map so it won't interfere constructor's initial map.
   1229     Object* new_map;
   1230     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
   1231       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   1232     }
   1233 
   1234     Map::cast(new_map)->set_is_access_check_needed(false);
   1235     object->set_map(Map::cast(new_map));
   1236   }
   1237   return isolate->heap()->ToBoolean(needs_access_checks);
   1238 }
   1239 
   1240 
   1241 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
   1242   ASSERT(args.length() == 1);
   1243   CONVERT_ARG_CHECKED(HeapObject, object, 0);
   1244   Map* old_map = object->map();
   1245   if (!old_map->is_access_check_needed()) {
   1246     // Copy map so it won't interfere constructor's initial map.
   1247     Object* new_map;
   1248     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
   1249       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   1250     }
   1251 
   1252     Map::cast(new_map)->set_is_access_check_needed(true);
   1253     object->set_map(Map::cast(new_map));
   1254   }
   1255   return isolate->heap()->undefined_value();
   1256 }
   1257 
   1258 
   1259 static Failure* ThrowRedeclarationError(Isolate* isolate,
   1260                                         const char* type,
   1261                                         Handle<String> name) {
   1262   HandleScope scope(isolate);
   1263   Handle<Object> type_handle =
   1264       isolate->factory()->NewStringFromAscii(CStrVector(type));
   1265   Handle<Object> args[2] = { type_handle, name };
   1266   Handle<Object> error =
   1267       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
   1268   return isolate->Throw(*error);
   1269 }
   1270 
   1271 
   1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
   1273   ASSERT(args.length() == 3);
   1274   HandleScope scope(isolate);
   1275   Handle<GlobalObject> global = Handle<GlobalObject>(
   1276       isolate->context()->global());
   1277 
   1278   Handle<Context> context = args.at<Context>(0);
   1279   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
   1280   CONVERT_SMI_ARG_CHECKED(flags, 2);
   1281 
   1282   // Traverse the name/value pairs and set the properties.
   1283   int length = pairs->length();
   1284   for (int i = 0; i < length; i += 2) {
   1285     HandleScope scope(isolate);
   1286     Handle<String> name(String::cast(pairs->get(i)));
   1287     Handle<Object> value(pairs->get(i + 1), isolate);
   1288 
   1289     // We have to declare a global const property. To capture we only
   1290     // assign to it when evaluating the assignment for "const x =
   1291     // <expr>" the initial value is the hole.
   1292     bool is_const_property = value->IsTheHole();
   1293     bool is_function_declaration = false;
   1294     if (value->IsUndefined() || is_const_property) {
   1295       // Lookup the property in the global object, and don't set the
   1296       // value of the variable if the property is already there.
   1297       LookupResult lookup(isolate);
   1298       global->Lookup(*name, &lookup);
   1299       if (lookup.IsProperty()) {
   1300         // We found an existing property. Unless it was an interceptor
   1301         // that claims the property is absent, skip this declaration.
   1302         if (lookup.type() != INTERCEPTOR) {
   1303           continue;
   1304         }
   1305         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
   1306         if (attributes != ABSENT) {
   1307           continue;
   1308         }
   1309         // Fall-through and introduce the absent property by using
   1310         // SetProperty.
   1311       }
   1312     } else {
   1313       is_function_declaration = true;
   1314       // Copy the function and update its context. Use it as value.
   1315       Handle<SharedFunctionInfo> shared =
   1316           Handle<SharedFunctionInfo>::cast(value);
   1317       Handle<JSFunction> function =
   1318           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
   1319                                                                 context,
   1320                                                                 TENURED);
   1321       value = function;
   1322     }
   1323 
   1324     LookupResult lookup(isolate);
   1325     global->LocalLookup(*name, &lookup);
   1326 
   1327     // Compute the property attributes. According to ECMA-262, section
   1328     // 13, page 71, the property must be read-only and
   1329     // non-deletable. However, neither SpiderMonkey nor KJS creates the
   1330     // property as read-only, so we don't either.
   1331     int attr = NONE;
   1332     if (!DeclareGlobalsEvalFlag::decode(flags)) {
   1333       attr |= DONT_DELETE;
   1334     }
   1335     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
   1336     if (is_const_property || (is_native && is_function_declaration)) {
   1337       attr |= READ_ONLY;
   1338     }
   1339 
   1340     LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
   1341 
   1342     // Safari does not allow the invocation of callback setters for
   1343     // function declarations. To mimic this behavior, we do not allow
   1344     // the invocation of setters for function values. This makes a
   1345     // difference for global functions with the same names as event
   1346     // handlers such as "function onload() {}". Firefox does call the
   1347     // onload setter in those case and Safari does not. We follow
   1348     // Safari for compatibility.
   1349     if (is_function_declaration) {
   1350       if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
   1351         // Do not overwrite READ_ONLY properties.
   1352         if (lookup.GetAttributes() & READ_ONLY) {
   1353           if (language_mode != CLASSIC_MODE) {
   1354             Handle<Object> args[] = { name };
   1355             return isolate->Throw(*isolate->factory()->NewTypeError(
   1356                 "strict_cannot_assign", HandleVector(args, ARRAY_SIZE(args))));
   1357           }
   1358           continue;
   1359         }
   1360         // Do not change DONT_DELETE to false from true.
   1361         attr |= lookup.GetAttributes() & DONT_DELETE;
   1362       }
   1363       PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
   1364 
   1365       RETURN_IF_EMPTY_HANDLE(
   1366           isolate,
   1367           JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
   1368                                                      attributes));
   1369     } else {
   1370       RETURN_IF_EMPTY_HANDLE(
   1371           isolate,
   1372           JSReceiver::SetProperty(global, name, value,
   1373                                   static_cast<PropertyAttributes>(attr),
   1374                                   language_mode == CLASSIC_MODE
   1375                                       ? kNonStrictMode : kStrictMode));
   1376     }
   1377   }
   1378 
   1379   ASSERT(!isolate->has_pending_exception());
   1380   return isolate->heap()->undefined_value();
   1381 }
   1382 
   1383 
   1384 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
   1385   HandleScope scope(isolate);
   1386   ASSERT(args.length() == 4);
   1387 
   1388   // Declarations are always made in a function or global context.  In the
   1389   // case of eval code, the context passed is the context of the caller,
   1390   // which may be some nested context and not the declaration context.
   1391   RUNTIME_ASSERT(args[0]->IsContext());
   1392   Handle<Context> context(Context::cast(args[0])->declaration_context());
   1393 
   1394   Handle<String> name(String::cast(args[1]));
   1395   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
   1396   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
   1397   Handle<Object> initial_value(args[3], isolate);
   1398 
   1399   int index;
   1400   PropertyAttributes attributes;
   1401   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
   1402   BindingFlags binding_flags;
   1403   Handle<Object> holder =
   1404       context->Lookup(name, flags, &index, &attributes, &binding_flags);
   1405 
   1406   if (attributes != ABSENT) {
   1407     // The name was declared before; check for conflicting re-declarations.
   1408     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
   1409       // Functions are not read-only.
   1410       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
   1411       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
   1412       return ThrowRedeclarationError(isolate, type, name);
   1413     }
   1414 
   1415     // Initialize it if necessary.
   1416     if (*initial_value != NULL) {
   1417       if (index >= 0) {
   1418         ASSERT(holder.is_identical_to(context));
   1419         if (((attributes & READ_ONLY) == 0) ||
   1420             context->get(index)->IsTheHole()) {
   1421           context->set(index, *initial_value);
   1422         }
   1423       } else {
   1424         // Slow case: The property is in the context extension object of a
   1425         // function context or the global object of a global context.
   1426         Handle<JSObject> object = Handle<JSObject>::cast(holder);
   1427         RETURN_IF_EMPTY_HANDLE(
   1428             isolate,
   1429             JSReceiver::SetProperty(object, name, initial_value, mode,
   1430                                     kNonStrictMode));
   1431       }
   1432     }
   1433 
   1434   } else {
   1435     // The property is not in the function context. It needs to be
   1436     // "declared" in the function context's extension context or as a
   1437     // property of the the global object.
   1438     Handle<JSObject> object;
   1439     if (context->has_extension()) {
   1440       object = Handle<JSObject>(JSObject::cast(context->extension()));
   1441     } else {
   1442       // Context extension objects are allocated lazily.
   1443       ASSERT(context->IsFunctionContext());
   1444       object = isolate->factory()->NewJSObject(
   1445           isolate->context_extension_function());
   1446       context->set_extension(*object);
   1447     }
   1448     ASSERT(*object != NULL);
   1449 
   1450     // Declare the property by setting it to the initial value if provided,
   1451     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
   1452     // constant declarations).
   1453     ASSERT(!object->HasLocalProperty(*name));
   1454     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
   1455     if (*initial_value != NULL) value = initial_value;
   1456     // Declaring a const context slot is a conflicting declaration if
   1457     // there is a callback with that name in a prototype. It is
   1458     // allowed to introduce const variables in
   1459     // JSContextExtensionObjects. They are treated specially in
   1460     // SetProperty and no setters are invoked for those since they are
   1461     // not real JSObjects.
   1462     if (initial_value->IsTheHole() &&
   1463         !object->IsJSContextExtensionObject()) {
   1464       LookupResult lookup(isolate);
   1465       object->Lookup(*name, &lookup);
   1466       if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
   1467         return ThrowRedeclarationError(isolate, "const", name);
   1468       }
   1469     }
   1470     RETURN_IF_EMPTY_HANDLE(
   1471         isolate,
   1472         JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
   1473   }
   1474 
   1475   return isolate->heap()->undefined_value();
   1476 }
   1477 
   1478 
   1479 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
   1480   NoHandleAllocation nha;
   1481   // args[0] == name
   1482   // args[1] == language_mode
   1483   // args[2] == value (optional)
   1484 
   1485   // Determine if we need to assign to the variable if it already
   1486   // exists (based on the number of arguments).
   1487   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
   1488   bool assign = args.length() == 3;
   1489 
   1490   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   1491   GlobalObject* global = isolate->context()->global();
   1492   RUNTIME_ASSERT(args[1]->IsSmi());
   1493   CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
   1494   StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
   1495       ? kNonStrictMode : kStrictMode;
   1496 
   1497   // According to ECMA-262, section 12.2, page 62, the property must
   1498   // not be deletable.
   1499   PropertyAttributes attributes = DONT_DELETE;
   1500 
   1501   // Lookup the property locally in the global object. If it isn't
   1502   // there, there is a property with this name in the prototype chain.
   1503   // We follow Safari and Firefox behavior and only set the property
   1504   // locally if there is an explicit initialization value that we have
   1505   // to assign to the property.
   1506   // Note that objects can have hidden prototypes, so we need to traverse
   1507   // the whole chain of hidden prototypes to do a 'local' lookup.
   1508   Object* object = global;
   1509   LookupResult lookup(isolate);
   1510   while (object->IsJSObject() &&
   1511          JSObject::cast(object)->map()->is_hidden_prototype()) {
   1512     JSObject* raw_holder = JSObject::cast(object);
   1513     raw_holder->LocalLookup(*name, &lookup);
   1514     if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
   1515       HandleScope handle_scope(isolate);
   1516       Handle<JSObject> holder(raw_holder);
   1517       PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
   1518       // Update the raw pointer in case it's changed due to GC.
   1519       raw_holder = *holder;
   1520       if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
   1521         // Found an interceptor that's not read only.
   1522         if (assign) {
   1523           return raw_holder->SetProperty(
   1524               &lookup, *name, args[2], attributes, strict_mode_flag);
   1525         } else {
   1526           return isolate->heap()->undefined_value();
   1527         }
   1528       }
   1529     }
   1530     object = raw_holder->GetPrototype();
   1531   }
   1532 
   1533   // Reload global in case the loop above performed a GC.
   1534   global = isolate->context()->global();
   1535   if (assign) {
   1536     return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
   1537   }
   1538   return isolate->heap()->undefined_value();
   1539 }
   1540 
   1541 
   1542 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
   1543   // All constants are declared with an initial value. The name
   1544   // of the constant is the first argument and the initial value
   1545   // is the second.
   1546   RUNTIME_ASSERT(args.length() == 2);
   1547   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   1548   Handle<Object> value = args.at<Object>(1);
   1549 
   1550   // Get the current global object from top.
   1551   GlobalObject* global = isolate->context()->global();
   1552 
   1553   // According to ECMA-262, section 12.2, page 62, the property must
   1554   // not be deletable. Since it's a const, it must be READ_ONLY too.
   1555   PropertyAttributes attributes =
   1556       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
   1557 
   1558   // Lookup the property locally in the global object. If it isn't
   1559   // there, we add the property and take special precautions to always
   1560   // add it as a local property even in case of callbacks in the
   1561   // prototype chain (this rules out using SetProperty).
   1562   // We use SetLocalPropertyIgnoreAttributes instead
   1563   LookupResult lookup(isolate);
   1564   global->LocalLookup(*name, &lookup);
   1565   if (!lookup.IsProperty()) {
   1566     return global->SetLocalPropertyIgnoreAttributes(*name,
   1567                                                     *value,
   1568                                                     attributes);
   1569   }
   1570 
   1571   if (!lookup.IsReadOnly()) {
   1572     // Restore global object from context (in case of GC) and continue
   1573     // with setting the value.
   1574     HandleScope handle_scope(isolate);
   1575     Handle<GlobalObject> global(isolate->context()->global());
   1576 
   1577     // BUG 1213575: Handle the case where we have to set a read-only
   1578     // property through an interceptor and only do it if it's
   1579     // uninitialized, e.g. the hole. Nirk...
   1580     // Passing non-strict mode because the property is writable.
   1581     RETURN_IF_EMPTY_HANDLE(
   1582         isolate,
   1583         JSReceiver::SetProperty(global, name, value, attributes,
   1584                                 kNonStrictMode));
   1585     return *value;
   1586   }
   1587 
   1588   // Set the value, but only if we're assigning the initial value to a
   1589   // constant. For now, we determine this by checking if the
   1590   // current value is the hole.
   1591   // Strict mode handling not needed (const is disallowed in strict mode).
   1592   PropertyType type = lookup.type();
   1593   if (type == FIELD) {
   1594     FixedArray* properties = global->properties();
   1595     int index = lookup.GetFieldIndex();
   1596     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
   1597       properties->set(index, *value);
   1598     }
   1599   } else if (type == NORMAL) {
   1600     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
   1601         !lookup.IsReadOnly()) {
   1602       global->SetNormalizedProperty(&lookup, *value);
   1603     }
   1604   } else {
   1605     // Ignore re-initialization of constants that have already been
   1606     // assigned a function value.
   1607     ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
   1608   }
   1609 
   1610   // Use the set value as the result of the operation.
   1611   return *value;
   1612 }
   1613 
   1614 
   1615 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
   1616   HandleScope scope(isolate);
   1617   ASSERT(args.length() == 3);
   1618 
   1619   Handle<Object> value(args[0], isolate);
   1620   ASSERT(!value->IsTheHole());
   1621 
   1622   // Initializations are always done in a function or global context.
   1623   RUNTIME_ASSERT(args[1]->IsContext());
   1624   Handle<Context> context(Context::cast(args[1])->declaration_context());
   1625 
   1626   Handle<String> name(String::cast(args[2]));
   1627 
   1628   int index;
   1629   PropertyAttributes attributes;
   1630   ContextLookupFlags flags = FOLLOW_CHAINS;
   1631   BindingFlags binding_flags;
   1632   Handle<Object> holder =
   1633       context->Lookup(name, flags, &index, &attributes, &binding_flags);
   1634 
   1635   if (index >= 0) {
   1636     ASSERT(holder->IsContext());
   1637     // Property was found in a context.  Perform the assignment if we
   1638     // found some non-constant or an uninitialized constant.
   1639     Handle<Context> context = Handle<Context>::cast(holder);
   1640     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
   1641       context->set(index, *value);
   1642     }
   1643     return *value;
   1644   }
   1645 
   1646   // The property could not be found, we introduce it as a property of the
   1647   // global object.
   1648   if (attributes == ABSENT) {
   1649     Handle<JSObject> global = Handle<JSObject>(
   1650         isolate->context()->global());
   1651     // Strict mode not needed (const disallowed in strict mode).
   1652     RETURN_IF_EMPTY_HANDLE(
   1653         isolate,
   1654         JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
   1655     return *value;
   1656   }
   1657 
   1658   // The property was present in some function's context extension object,
   1659   // as a property on the subject of a with, or as a property of the global
   1660   // object.
   1661   //
   1662   // In most situations, eval-introduced consts should still be present in
   1663   // the context extension object.  However, because declaration and
   1664   // initialization are separate, the property might have been deleted
   1665   // before we reach the initialization point.
   1666   //
   1667   // Example:
   1668   //
   1669   //    function f() { eval("delete x; const x;"); }
   1670   //
   1671   // In that case, the initialization behaves like a normal assignment.
   1672   Handle<JSObject> object = Handle<JSObject>::cast(holder);
   1673 
   1674   if (*object == context->extension()) {
   1675     // This is the property that was introduced by the const declaration.
   1676     // Set it if it hasn't been set before.  NOTE: We cannot use
   1677     // GetProperty() to get the current value as it 'unholes' the value.
   1678     LookupResult lookup(isolate);
   1679     object->LocalLookupRealNamedProperty(*name, &lookup);
   1680     ASSERT(lookup.IsFound());  // the property was declared
   1681     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
   1682 
   1683     PropertyType type = lookup.type();
   1684     if (type == FIELD) {
   1685       FixedArray* properties = object->properties();
   1686       int index = lookup.GetFieldIndex();
   1687       if (properties->get(index)->IsTheHole()) {
   1688         properties->set(index, *value);
   1689       }
   1690     } else if (type == NORMAL) {
   1691       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
   1692         object->SetNormalizedProperty(&lookup, *value);
   1693       }
   1694     } else {
   1695       // We should not reach here. Any real, named property should be
   1696       // either a field or a dictionary slot.
   1697       UNREACHABLE();
   1698     }
   1699   } else {
   1700     // The property was found on some other object.  Set it if it is not a
   1701     // read-only property.
   1702     if ((attributes & READ_ONLY) == 0) {
   1703       // Strict mode not needed (const disallowed in strict mode).
   1704       RETURN_IF_EMPTY_HANDLE(
   1705           isolate,
   1706           JSReceiver::SetProperty(object, name, value, attributes,
   1707                                   kNonStrictMode));
   1708     }
   1709   }
   1710 
   1711   return *value;
   1712 }
   1713 
   1714 
   1715 RUNTIME_FUNCTION(MaybeObject*,
   1716                  Runtime_OptimizeObjectForAddingMultipleProperties) {
   1717   HandleScope scope(isolate);
   1718   ASSERT(args.length() == 2);
   1719   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   1720   CONVERT_SMI_ARG_CHECKED(properties, 1);
   1721   if (object->HasFastProperties()) {
   1722     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
   1723   }
   1724   return *object;
   1725 }
   1726 
   1727 
   1728 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
   1729   HandleScope scope(isolate);
   1730   ASSERT(args.length() == 4);
   1731   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
   1732   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
   1733   // Due to the way the JS calls are constructed this must be less than the
   1734   // length of a string, i.e. it is always a Smi.  We check anyway for security.
   1735   CONVERT_SMI_ARG_CHECKED(index, 2);
   1736   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
   1737   RUNTIME_ASSERT(last_match_info->HasFastElements());
   1738   RUNTIME_ASSERT(index >= 0);
   1739   RUNTIME_ASSERT(index <= subject->length());
   1740   isolate->counters()->regexp_entry_runtime()->Increment();
   1741   Handle<Object> result = RegExpImpl::Exec(regexp,
   1742                                            subject,
   1743                                            index,
   1744                                            last_match_info);
   1745   if (result.is_null()) return Failure::Exception();
   1746   return *result;
   1747 }
   1748 
   1749 
   1750 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
   1751   ASSERT(args.length() == 3);
   1752   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
   1753   if (elements_count < 0 ||
   1754       elements_count > FixedArray::kMaxLength ||
   1755       !Smi::IsValid(elements_count)) {
   1756     return isolate->ThrowIllegalOperation();
   1757   }
   1758   Object* new_object;
   1759   { MaybeObject* maybe_new_object =
   1760         isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
   1761     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
   1762   }
   1763   FixedArray* elements = FixedArray::cast(new_object);
   1764   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
   1765       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
   1766     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
   1767   }
   1768   {
   1769     AssertNoAllocation no_gc;
   1770     HandleScope scope(isolate);
   1771     reinterpret_cast<HeapObject*>(new_object)->
   1772         set_map(isolate->global_context()->regexp_result_map());
   1773   }
   1774   JSArray* array = JSArray::cast(new_object);
   1775   array->set_properties(isolate->heap()->empty_fixed_array());
   1776   array->set_elements(elements);
   1777   array->set_length(Smi::FromInt(elements_count));
   1778   // Write in-object properties after the length of the array.
   1779   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
   1780   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
   1781   return array;
   1782 }
   1783 
   1784 
   1785 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
   1786   AssertNoAllocation no_alloc;
   1787   ASSERT(args.length() == 5);
   1788   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
   1789   CONVERT_ARG_CHECKED(String, source, 1);
   1790 
   1791   Object* global = args[2];
   1792   if (!global->IsTrue()) global = isolate->heap()->false_value();
   1793 
   1794   Object* ignoreCase = args[3];
   1795   if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
   1796 
   1797   Object* multiline = args[4];
   1798   if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
   1799 
   1800   Map* map = regexp->map();
   1801   Object* constructor = map->constructor();
   1802   if (constructor->IsJSFunction() &&
   1803       JSFunction::cast(constructor)->initial_map() == map) {
   1804     // If we still have the original map, set in-object properties directly.
   1805     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
   1806     // Both true and false are immovable immortal objects so no need for write
   1807     // barrier.
   1808     regexp->InObjectPropertyAtPut(
   1809         JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
   1810     regexp->InObjectPropertyAtPut(
   1811         JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
   1812     regexp->InObjectPropertyAtPut(
   1813         JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
   1814     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
   1815                                   Smi::FromInt(0),
   1816                                   SKIP_WRITE_BARRIER);  // It's a Smi.
   1817     return regexp;
   1818   }
   1819 
   1820   // Map has changed, so use generic, but slower, method.
   1821   PropertyAttributes final =
   1822       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
   1823   PropertyAttributes writable =
   1824       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
   1825   Heap* heap = isolate->heap();
   1826   MaybeObject* result;
   1827   result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
   1828                                                     source,
   1829                                                     final);
   1830   ASSERT(!result->IsFailure());
   1831   result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
   1832                                                     global,
   1833                                                     final);
   1834   ASSERT(!result->IsFailure());
   1835   result =
   1836       regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
   1837                                                ignoreCase,
   1838                                                final);
   1839   ASSERT(!result->IsFailure());
   1840   result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
   1841                                                     multiline,
   1842                                                     final);
   1843   ASSERT(!result->IsFailure());
   1844   result =
   1845       regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
   1846                                                Smi::FromInt(0),
   1847                                                writable);
   1848   ASSERT(!result->IsFailure());
   1849   USE(result);
   1850   return regexp;
   1851 }
   1852 
   1853 
   1854 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
   1855   HandleScope scope(isolate);
   1856   ASSERT(args.length() == 1);
   1857   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
   1858   // This is necessary to enable fast checks for absence of elements
   1859   // on Array.prototype and below.
   1860   prototype->set_elements(isolate->heap()->empty_fixed_array());
   1861   return Smi::FromInt(0);
   1862 }
   1863 
   1864 
   1865 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
   1866                                          Handle<JSObject> holder,
   1867                                          const char* name,
   1868                                          Builtins::Name builtin_name) {
   1869   Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
   1870   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
   1871   Handle<JSFunction> optimized =
   1872       isolate->factory()->NewFunction(key,
   1873                                       JS_OBJECT_TYPE,
   1874                                       JSObject::kHeaderSize,
   1875                                       code,
   1876                                       false);
   1877   optimized->shared()->DontAdaptArguments();
   1878   JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
   1879   return optimized;
   1880 }
   1881 
   1882 
   1883 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
   1884   HandleScope scope(isolate);
   1885   ASSERT(args.length() == 1);
   1886   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
   1887 
   1888   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
   1889   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
   1890   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
   1891   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
   1892   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
   1893   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
   1894   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
   1895 
   1896   return *holder;
   1897 }
   1898 
   1899 
   1900 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
   1901   ASSERT(args.length() == 1);
   1902   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
   1903 
   1904   if (!callable->IsJSFunction()) {
   1905     HandleScope scope(isolate);
   1906     bool threw = false;
   1907     Handle<Object> delegate =
   1908         Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
   1909     if (threw) return Failure::Exception();
   1910     callable = JSFunction::cast(*delegate);
   1911   }
   1912   JSFunction* function = JSFunction::cast(callable);
   1913 
   1914   SharedFunctionInfo* shared = function->shared();
   1915   if (shared->native() || !shared->is_classic_mode()) {
   1916     return isolate->heap()->undefined_value();
   1917   }
   1918   // Returns undefined for strict or native functions, or
   1919   // the associated global receiver for "normal" functions.
   1920 
   1921   Context* global_context =
   1922       function->context()->global()->global_context();
   1923   return global_context->global()->global_receiver();
   1924 }
   1925 
   1926 
   1927 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
   1928   HandleScope scope(isolate);
   1929   ASSERT(args.length() == 4);
   1930   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
   1931   int index = args.smi_at(1);
   1932   Handle<String> pattern = args.at<String>(2);
   1933   Handle<String> flags = args.at<String>(3);
   1934 
   1935   // Get the RegExp function from the context in the literals array.
   1936   // This is the RegExp function from the context in which the
   1937   // function was created.  We do not use the RegExp function from the
   1938   // current global context because this might be the RegExp function
   1939   // from another context which we should not have access to.
   1940   Handle<JSFunction> constructor =
   1941       Handle<JSFunction>(
   1942           JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
   1943   // Compute the regular expression literal.
   1944   bool has_pending_exception;
   1945   Handle<Object> regexp =
   1946       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
   1947                                       &has_pending_exception);
   1948   if (has_pending_exception) {
   1949     ASSERT(isolate->has_pending_exception());
   1950     return Failure::Exception();
   1951   }
   1952   literals->set(index, *regexp);
   1953   return *regexp;
   1954 }
   1955 
   1956 
   1957 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
   1958   NoHandleAllocation ha;
   1959   ASSERT(args.length() == 1);
   1960 
   1961   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   1962   return f->shared()->name();
   1963 }
   1964 
   1965 
   1966 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
   1967   NoHandleAllocation ha;
   1968   ASSERT(args.length() == 2);
   1969 
   1970   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   1971   CONVERT_ARG_CHECKED(String, name, 1);
   1972   f->shared()->set_name(name);
   1973   return isolate->heap()->undefined_value();
   1974 }
   1975 
   1976 
   1977 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
   1978   NoHandleAllocation ha;
   1979   ASSERT(args.length() == 1);
   1980   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   1981   return isolate->heap()->ToBoolean(
   1982       f->shared()->name_should_print_as_anonymous());
   1983 }
   1984 
   1985 
   1986 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
   1987   NoHandleAllocation ha;
   1988   ASSERT(args.length() == 1);
   1989   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   1990   f->shared()->set_name_should_print_as_anonymous(true);
   1991   return isolate->heap()->undefined_value();
   1992 }
   1993 
   1994 
   1995 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
   1996   NoHandleAllocation ha;
   1997   ASSERT(args.length() == 1);
   1998 
   1999   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   2000   Object* obj = f->RemovePrototype();
   2001   if (obj->IsFailure()) return obj;
   2002 
   2003   return isolate->heap()->undefined_value();
   2004 }
   2005 
   2006 
   2007 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
   2008   HandleScope scope(isolate);
   2009   ASSERT(args.length() == 1);
   2010 
   2011   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   2012   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
   2013   if (!script->IsScript()) return isolate->heap()->undefined_value();
   2014 
   2015   return *GetScriptWrapper(Handle<Script>::cast(script));
   2016 }
   2017 
   2018 
   2019 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
   2020   HandleScope scope(isolate);
   2021   ASSERT(args.length() == 1);
   2022 
   2023   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
   2024   Handle<SharedFunctionInfo> shared(f->shared());
   2025   return *shared->GetSourceCode();
   2026 }
   2027 
   2028 
   2029 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
   2030   NoHandleAllocation ha;
   2031   ASSERT(args.length() == 1);
   2032 
   2033   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   2034   int pos = fun->shared()->start_position();
   2035   return Smi::FromInt(pos);
   2036 }
   2037 
   2038 
   2039 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
   2040   ASSERT(args.length() == 2);
   2041 
   2042   CONVERT_ARG_CHECKED(Code, code, 0);
   2043   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
   2044 
   2045   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
   2046 
   2047   Address pc = code->address() + offset;
   2048   return Smi::FromInt(code->SourcePosition(pc));
   2049 }
   2050 
   2051 
   2052 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
   2053   NoHandleAllocation ha;
   2054   ASSERT(args.length() == 2);
   2055 
   2056   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   2057   CONVERT_ARG_CHECKED(String, name, 1);
   2058   fun->SetInstanceClassName(name);
   2059   return isolate->heap()->undefined_value();
   2060 }
   2061 
   2062 
   2063 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
   2064   NoHandleAllocation ha;
   2065   ASSERT(args.length() == 2);
   2066 
   2067   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   2068   CONVERT_SMI_ARG_CHECKED(length, 1);
   2069   fun->shared()->set_length(length);
   2070   return isolate->heap()->undefined_value();
   2071 }
   2072 
   2073 
   2074 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
   2075   NoHandleAllocation ha;
   2076   ASSERT(args.length() == 2);
   2077 
   2078   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   2079   ASSERT(fun->should_have_prototype());
   2080   Object* obj;
   2081   { MaybeObject* maybe_obj =
   2082         Accessors::FunctionSetPrototype(fun, args[1], NULL);
   2083     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   2084   }
   2085   return args[0];  // return TOS
   2086 }
   2087 
   2088 
   2089 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
   2090   NoHandleAllocation ha;
   2091   RUNTIME_ASSERT(args.length() == 1);
   2092   CONVERT_ARG_CHECKED(JSFunction, function, 0);
   2093 
   2094   MaybeObject* maybe_name =
   2095       isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
   2096   String* name;
   2097   if (!maybe_name->To(&name)) return maybe_name;
   2098 
   2099   if (function->HasFastProperties()) {
   2100     // Construct a new field descriptor with updated attributes.
   2101     DescriptorArray* instance_desc = function->map()->instance_descriptors();
   2102     int index = instance_desc->Search(name);
   2103     ASSERT(index != DescriptorArray::kNotFound);
   2104     PropertyDetails details(instance_desc->GetDetails(index));
   2105     CallbacksDescriptor new_desc(name,
   2106         instance_desc->GetValue(index),
   2107         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
   2108         details.index());
   2109     // Construct a new field descriptors array containing the new descriptor.
   2110     Object* descriptors_unchecked;
   2111     { MaybeObject* maybe_descriptors_unchecked =
   2112         instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
   2113       if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
   2114         return maybe_descriptors_unchecked;
   2115       }
   2116     }
   2117     DescriptorArray* new_descriptors =
   2118         DescriptorArray::cast(descriptors_unchecked);
   2119     // Create a new map featuring the new field descriptors array.
   2120     Object* map_unchecked;
   2121     { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
   2122       if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
   2123         return maybe_map_unchecked;
   2124       }
   2125     }
   2126     Map* new_map = Map::cast(map_unchecked);
   2127     new_map->set_instance_descriptors(new_descriptors);
   2128     function->set_map(new_map);
   2129   } else {  // Dictionary properties.
   2130     // Directly manipulate the property details.
   2131     int entry = function->property_dictionary()->FindEntry(name);
   2132     ASSERT(entry != StringDictionary::kNotFound);
   2133     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
   2134     PropertyDetails new_details(
   2135         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
   2136         details.type(),
   2137         details.index());
   2138     function->property_dictionary()->DetailsAtPut(entry, new_details);
   2139   }
   2140   return function;
   2141 }
   2142 
   2143 
   2144 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
   2145   NoHandleAllocation ha;
   2146   ASSERT(args.length() == 1);
   2147 
   2148   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   2149   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
   2150 }
   2151 
   2152 
   2153 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
   2154   NoHandleAllocation ha;
   2155   ASSERT(args.length() == 1);
   2156 
   2157   CONVERT_ARG_CHECKED(JSFunction, f, 0);
   2158   return isolate->heap()->ToBoolean(f->IsBuiltin());
   2159 }
   2160 
   2161 
   2162 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
   2163   HandleScope scope(isolate);
   2164   ASSERT(args.length() == 2);
   2165 
   2166   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
   2167   Handle<Object> code = args.at<Object>(1);
   2168 
   2169   Handle<Context> context(target->context());
   2170 
   2171   if (!code->IsNull()) {
   2172     RUNTIME_ASSERT(code->IsJSFunction());
   2173     Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
   2174     Handle<SharedFunctionInfo> shared(fun->shared());
   2175 
   2176     if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
   2177       return Failure::Exception();
   2178     }
   2179     // Since we don't store the source for this we should never
   2180     // optimize this.
   2181     shared->code()->set_optimizable(false);
   2182     // Set the code, scope info, formal parameter count,
   2183     // and the length of the target function.
   2184     target->shared()->set_code(shared->code());
   2185     target->ReplaceCode(shared->code());
   2186     target->shared()->set_scope_info(shared->scope_info());
   2187     target->shared()->set_length(shared->length());
   2188     target->shared()->set_formal_parameter_count(
   2189         shared->formal_parameter_count());
   2190     // Set the source code of the target function to undefined.
   2191     // SetCode is only used for built-in constructors like String,
   2192     // Array, and Object, and some web code
   2193     // doesn't like seeing source code for constructors.
   2194     target->shared()->set_script(isolate->heap()->undefined_value());
   2195     target->shared()->code()->set_optimizable(false);
   2196     // Clear the optimization hints related to the compiled code as these are no
   2197     // longer valid when the code is overwritten.
   2198     target->shared()->ClearThisPropertyAssignmentsInfo();
   2199     context = Handle<Context>(fun->context());
   2200 
   2201     // Make sure we get a fresh copy of the literal vector to avoid
   2202     // cross context contamination.
   2203     int number_of_literals = fun->NumberOfLiterals();
   2204     Handle<FixedArray> literals =
   2205         isolate->factory()->NewFixedArray(number_of_literals, TENURED);
   2206     if (number_of_literals > 0) {
   2207       // Insert the object, regexp and array functions in the literals
   2208       // array prefix.  These are the functions that will be used when
   2209       // creating object, regexp and array literals.
   2210       literals->set(JSFunction::kLiteralGlobalContextIndex,
   2211                     context->global_context());
   2212     }
   2213     target->set_literals(*literals);
   2214     target->set_next_function_link(isolate->heap()->undefined_value());
   2215 
   2216     if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) {
   2217       isolate->logger()->LogExistingFunction(
   2218           shared, Handle<Code>(shared->code()));
   2219     }
   2220   }
   2221 
   2222   target->set_context(*context);
   2223   return *target;
   2224 }
   2225 
   2226 
   2227 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
   2228   HandleScope scope(isolate);
   2229   ASSERT(args.length() == 2);
   2230   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
   2231   CONVERT_SMI_ARG_CHECKED(num, 1);
   2232   RUNTIME_ASSERT(num >= 0);
   2233   SetExpectedNofProperties(function, num);
   2234   return isolate->heap()->undefined_value();
   2235 }
   2236 
   2237 
   2238 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
   2239                                                  Object* char_code) {
   2240   uint32_t code;
   2241   if (char_code->ToArrayIndex(&code)) {
   2242     if (code <= 0xffff) {
   2243       return isolate->heap()->LookupSingleCharacterStringFromCode(code);
   2244     }
   2245   }
   2246   return isolate->heap()->empty_string();
   2247 }
   2248 
   2249 
   2250 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
   2251   NoHandleAllocation ha;
   2252   ASSERT(args.length() == 2);
   2253 
   2254   CONVERT_ARG_CHECKED(String, subject, 0);
   2255   Object* index = args[1];
   2256   RUNTIME_ASSERT(index->IsNumber());
   2257 
   2258   uint32_t i = 0;
   2259   if (index->IsSmi()) {
   2260     int value = Smi::cast(index)->value();
   2261     if (value < 0) return isolate->heap()->nan_value();
   2262     i = value;
   2263   } else {
   2264     ASSERT(index->IsHeapNumber());
   2265     double value = HeapNumber::cast(index)->value();
   2266     i = static_cast<uint32_t>(DoubleToInteger(value));
   2267   }
   2268 
   2269   // Flatten the string.  If someone wants to get a char at an index
   2270   // in a cons string, it is likely that more indices will be
   2271   // accessed.
   2272   Object* flat;
   2273   { MaybeObject* maybe_flat = subject->TryFlatten();
   2274     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
   2275   }
   2276   subject = String::cast(flat);
   2277 
   2278   if (i >= static_cast<uint32_t>(subject->length())) {
   2279     return isolate->heap()->nan_value();
   2280   }
   2281 
   2282   return Smi::FromInt(subject->Get(i));
   2283 }
   2284 
   2285 
   2286 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
   2287   NoHandleAllocation ha;
   2288   ASSERT(args.length() == 1);
   2289   return CharFromCode(isolate, args[0]);
   2290 }
   2291 
   2292 
   2293 class FixedArrayBuilder {
   2294  public:
   2295   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
   2296       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
   2297         length_(0),
   2298         has_non_smi_elements_(false) {
   2299     // Require a non-zero initial size. Ensures that doubling the size to
   2300     // extend the array will work.
   2301     ASSERT(initial_capacity > 0);
   2302   }
   2303 
   2304   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
   2305       : array_(backing_store),
   2306         length_(0),
   2307         has_non_smi_elements_(false) {
   2308     // Require a non-zero initial size. Ensures that doubling the size to
   2309     // extend the array will work.
   2310     ASSERT(backing_store->length() > 0);
   2311   }
   2312 
   2313   bool HasCapacity(int elements) {
   2314     int length = array_->length();
   2315     int required_length = length_ + elements;
   2316     return (length >= required_length);
   2317   }
   2318 
   2319   void EnsureCapacity(int elements) {
   2320     int length = array_->length();
   2321     int required_length = length_ + elements;
   2322     if (length < required_length) {
   2323       int new_length = length;
   2324       do {
   2325         new_length *= 2;
   2326       } while (new_length < required_length);
   2327       Handle<FixedArray> extended_array =
   2328           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
   2329       array_->CopyTo(0, *extended_array, 0, length_);
   2330       array_ = extended_array;
   2331     }
   2332   }
   2333 
   2334   void Add(Object* value) {
   2335     ASSERT(!value->IsSmi());
   2336     ASSERT(length_ < capacity());
   2337     array_->set(length_, value);
   2338     length_++;
   2339     has_non_smi_elements_ = true;
   2340   }
   2341 
   2342   void Add(Smi* value) {
   2343     ASSERT(value->IsSmi());
   2344     ASSERT(length_ < capacity());
   2345     array_->set(length_, value);
   2346     length_++;
   2347   }
   2348 
   2349   Handle<FixedArray> array() {
   2350     return array_;
   2351   }
   2352 
   2353   int length() {
   2354     return length_;
   2355   }
   2356 
   2357   int capacity() {
   2358     return array_->length();
   2359   }
   2360 
   2361   Handle<JSArray> ToJSArray() {
   2362     Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
   2363     result_array->set_length(Smi::FromInt(length_));
   2364     return result_array;
   2365   }
   2366 
   2367   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
   2368     FACTORY->SetContent(target_array, array_);
   2369     target_array->set_length(Smi::FromInt(length_));
   2370     return target_array;
   2371   }
   2372 
   2373  private:
   2374   Handle<FixedArray> array_;
   2375   int length_;
   2376   bool has_non_smi_elements_;
   2377 };
   2378 
   2379 
   2380 // Forward declarations.
   2381 const int kStringBuilderConcatHelperLengthBits = 11;
   2382 const int kStringBuilderConcatHelperPositionBits = 19;
   2383 
   2384 template <typename schar>
   2385 static inline void StringBuilderConcatHelper(String*,
   2386                                              schar*,
   2387                                              FixedArray*,
   2388                                              int);
   2389 
   2390 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
   2391     StringBuilderSubstringLength;
   2392 typedef BitField<int,
   2393                  kStringBuilderConcatHelperLengthBits,
   2394                  kStringBuilderConcatHelperPositionBits>
   2395     StringBuilderSubstringPosition;
   2396 
   2397 
   2398 class ReplacementStringBuilder {
   2399  public:
   2400   ReplacementStringBuilder(Heap* heap,
   2401                            Handle<String> subject,
   2402                            int estimated_part_count)
   2403       : heap_(heap),
   2404         array_builder_(heap->isolate(), estimated_part_count),
   2405         subject_(subject),
   2406         character_count_(0),
   2407         is_ascii_(subject->IsAsciiRepresentation()) {
   2408     // Require a non-zero initial size. Ensures that doubling the size to
   2409     // extend the array will work.
   2410     ASSERT(estimated_part_count > 0);
   2411   }
   2412 
   2413   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
   2414                                      int from,
   2415                                      int to) {
   2416     ASSERT(from >= 0);
   2417     int length = to - from;
   2418     ASSERT(length > 0);
   2419     if (StringBuilderSubstringLength::is_valid(length) &&
   2420         StringBuilderSubstringPosition::is_valid(from)) {
   2421       int encoded_slice = StringBuilderSubstringLength::encode(length) |
   2422           StringBuilderSubstringPosition::encode(from);
   2423       builder->Add(Smi::FromInt(encoded_slice));
   2424     } else {
   2425       // Otherwise encode as two smis.
   2426       builder->Add(Smi::FromInt(-length));
   2427       builder->Add(Smi::FromInt(from));
   2428     }
   2429   }
   2430 
   2431 
   2432   void EnsureCapacity(int elements) {
   2433     array_builder_.EnsureCapacity(elements);
   2434   }
   2435 
   2436 
   2437   void AddSubjectSlice(int from, int to) {
   2438     AddSubjectSlice(&array_builder_, from, to);
   2439     IncrementCharacterCount(to - from);
   2440   }
   2441 
   2442 
   2443   void AddString(Handle<String> string) {
   2444     int length = string->length();
   2445     ASSERT(length > 0);
   2446     AddElement(*string);
   2447     if (!string->IsAsciiRepresentation()) {
   2448       is_ascii_ = false;
   2449     }
   2450     IncrementCharacterCount(length);
   2451   }
   2452 
   2453 
   2454   Handle<String> ToString() {
   2455     if (array_builder_.length() == 0) {
   2456       return heap_->isolate()->factory()->empty_string();
   2457     }
   2458 
   2459     Handle<String> joined_string;
   2460     if (is_ascii_) {
   2461       Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
   2462       AssertNoAllocation no_alloc;
   2463       char* char_buffer = seq->GetChars();
   2464       StringBuilderConcatHelper(*subject_,
   2465                                 char_buffer,
   2466                                 *array_builder_.array(),
   2467                                 array_builder_.length());
   2468       joined_string = Handle<String>::cast(seq);
   2469     } else {
   2470       // Non-ASCII.
   2471       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
   2472       AssertNoAllocation no_alloc;
   2473       uc16* char_buffer = seq->GetChars();
   2474       StringBuilderConcatHelper(*subject_,
   2475                                 char_buffer,
   2476                                 *array_builder_.array(),
   2477                                 array_builder_.length());
   2478       joined_string = Handle<String>::cast(seq);
   2479     }
   2480     return joined_string;
   2481   }
   2482 
   2483 
   2484   void IncrementCharacterCount(int by) {
   2485     if (character_count_ > String::kMaxLength - by) {
   2486       V8::FatalProcessOutOfMemory("String.replace result too large.");
   2487     }
   2488     character_count_ += by;
   2489   }
   2490 
   2491   Handle<JSArray> GetParts() {
   2492     return array_builder_.ToJSArray();
   2493   }
   2494 
   2495  private:
   2496   Handle<SeqAsciiString> NewRawAsciiString(int length) {
   2497     return heap_->isolate()->factory()->NewRawAsciiString(length);
   2498   }
   2499 
   2500 
   2501   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
   2502     return heap_->isolate()->factory()->NewRawTwoByteString(length);
   2503   }
   2504 
   2505 
   2506   void AddElement(Object* element) {
   2507     ASSERT(element->IsSmi() || element->IsString());
   2508     ASSERT(array_builder_.capacity() > array_builder_.length());
   2509     array_builder_.Add(element);
   2510   }
   2511 
   2512   Heap* heap_;
   2513   FixedArrayBuilder array_builder_;
   2514   Handle<String> subject_;
   2515   int character_count_;
   2516   bool is_ascii_;
   2517 };
   2518 
   2519 
   2520 class CompiledReplacement {
   2521  public:
   2522   CompiledReplacement()
   2523       : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
   2524 
   2525   void Compile(Handle<String> replacement,
   2526                int capture_count,
   2527                int subject_length);
   2528 
   2529   void Apply(ReplacementStringBuilder* builder,
   2530              int match_from,
   2531              int match_to,
   2532              Handle<JSArray> last_match_info);
   2533 
   2534   // Number of distinct parts of the replacement pattern.
   2535   int parts() {
   2536     return parts_.length();
   2537   }
   2538 
   2539   bool simple_hint() {
   2540     return simple_hint_;
   2541   }
   2542 
   2543  private:
   2544   enum PartType {
   2545     SUBJECT_PREFIX = 1,
   2546     SUBJECT_SUFFIX,
   2547     SUBJECT_CAPTURE,
   2548     REPLACEMENT_SUBSTRING,
   2549     REPLACEMENT_STRING,
   2550 
   2551     NUMBER_OF_PART_TYPES
   2552   };
   2553 
   2554   struct ReplacementPart {
   2555     static inline ReplacementPart SubjectMatch() {
   2556       return ReplacementPart(SUBJECT_CAPTURE, 0);
   2557     }
   2558     static inline ReplacementPart SubjectCapture(int capture_index) {
   2559       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
   2560     }
   2561     static inline ReplacementPart SubjectPrefix() {
   2562       return ReplacementPart(SUBJECT_PREFIX, 0);
   2563     }
   2564     static inline ReplacementPart SubjectSuffix(int subject_length) {
   2565       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
   2566     }
   2567     static inline ReplacementPart ReplacementString() {
   2568       return ReplacementPart(REPLACEMENT_STRING, 0);
   2569     }
   2570     static inline ReplacementPart ReplacementSubString(int from, int to) {
   2571       ASSERT(from >= 0);
   2572       ASSERT(to > from);
   2573       return ReplacementPart(-from, to);
   2574     }
   2575 
   2576     // If tag <= 0 then it is the negation of a start index of a substring of
   2577     // the replacement pattern, otherwise it's a value from PartType.
   2578     ReplacementPart(int tag, int data)
   2579         : tag(tag), data(data) {
   2580       // Must be non-positive or a PartType value.
   2581       ASSERT(tag < NUMBER_OF_PART_TYPES);
   2582     }
   2583     // Either a value of PartType or a non-positive number that is
   2584     // the negation of an index into the replacement string.
   2585     int tag;
   2586     // The data value's interpretation depends on the value of tag:
   2587     // tag == SUBJECT_PREFIX ||
   2588     // tag == SUBJECT_SUFFIX:  data is unused.
   2589     // tag == SUBJECT_CAPTURE: data is the number of the capture.
   2590     // tag == REPLACEMENT_SUBSTRING ||
   2591     // tag == REPLACEMENT_STRING:    data is index into array of substrings
   2592     //                               of the replacement string.
   2593     // tag <= 0: Temporary representation of the substring of the replacement
   2594     //           string ranging over -tag .. data.
   2595     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
   2596     //           substring objects.
   2597     int data;
   2598   };
   2599 
   2600   template<typename Char>
   2601   static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
   2602                                       Vector<Char> characters,
   2603                                       int capture_count,
   2604                                       int subject_length) {
   2605     int length = characters.length();
   2606     int last = 0;
   2607     for (int i = 0; i < length; i++) {
   2608       Char c = characters[i];
   2609       if (c == '$') {
   2610         int next_index = i + 1;
   2611         if (next_index == length) {  // No next character!
   2612           break;
   2613         }
   2614         Char c2 = characters[next_index];
   2615         switch (c2) {
   2616         case '$':
   2617           if (i > last) {
   2618             // There is a substring before. Include the first "$".
   2619             parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
   2620             last = next_index + 1;  // Continue after the second "$".
   2621           } else {
   2622             // Let the next substring start with the second "$".
   2623             last = next_index;
   2624           }
   2625           i = next_index;
   2626           break;
   2627         case '`':
   2628           if (i > last) {
   2629             parts->Add(ReplacementPart::ReplacementSubString(last, i));
   2630           }
   2631           parts->Add(ReplacementPart::SubjectPrefix());
   2632           i = next_index;
   2633           last = i + 1;
   2634           break;
   2635         case '\'':
   2636           if (i > last) {
   2637             parts->Add(ReplacementPart::ReplacementSubString(last, i));
   2638           }
   2639           parts->Add(ReplacementPart::SubjectSuffix(subject_length));
   2640           i = next_index;
   2641           last = i + 1;
   2642           break;
   2643         case '&':
   2644           if (i > last) {
   2645             parts->Add(ReplacementPart::ReplacementSubString(last, i));
   2646           }
   2647           parts->Add(ReplacementPart::SubjectMatch());
   2648           i = next_index;
   2649           last = i + 1;
   2650           break;
   2651         case '0':
   2652         case '1':
   2653         case '2':
   2654         case '3':
   2655         case '4':
   2656         case '5':
   2657         case '6':
   2658         case '7':
   2659         case '8':
   2660         case '9': {
   2661           int capture_ref = c2 - '0';
   2662           if (capture_ref > capture_count) {
   2663             i = next_index;
   2664             continue;
   2665           }
   2666           int second_digit_index = next_index + 1;
   2667           if (second_digit_index < length) {
   2668             // Peek ahead to see if we have two digits.
   2669             Char c3 = characters[second_digit_index];
   2670             if ('0' <= c3 && c3 <= '9') {  // Double digits.
   2671               int double_digit_ref = capture_ref * 10 + c3 - '0';
   2672               if (double_digit_ref <= capture_count) {
   2673                 next_index = second_digit_index;
   2674                 capture_ref = double_digit_ref;
   2675               }
   2676             }
   2677           }
   2678           if (capture_ref > 0) {
   2679             if (i > last) {
   2680               parts->Add(ReplacementPart::ReplacementSubString(last, i));
   2681             }
   2682             ASSERT(capture_ref <= capture_count);
   2683             parts->Add(ReplacementPart::SubjectCapture(capture_ref));
   2684             last = next_index + 1;
   2685           }
   2686           i = next_index;
   2687           break;
   2688         }
   2689         default:
   2690           i = next_index;
   2691           break;
   2692         }
   2693       }
   2694     }
   2695     if (length > last) {
   2696       if (last == 0) {
   2697         parts->Add(ReplacementPart::ReplacementString());
   2698         return true;
   2699       } else {
   2700         parts->Add(ReplacementPart::ReplacementSubString(last, length));
   2701       }
   2702     }
   2703     return false;
   2704   }
   2705 
   2706   ZoneList<ReplacementPart> parts_;
   2707   ZoneList<Handle<String> > replacement_substrings_;
   2708   bool simple_hint_;
   2709 };
   2710 
   2711 
   2712 void CompiledReplacement::Compile(Handle<String> replacement,
   2713                                   int capture_count,
   2714                                   int subject_length) {
   2715   {
   2716     AssertNoAllocation no_alloc;
   2717     String::FlatContent content = replacement->GetFlatContent();
   2718     ASSERT(content.IsFlat());
   2719     if (content.IsAscii()) {
   2720       simple_hint_ = ParseReplacementPattern(&parts_,
   2721                                              content.ToAsciiVector(),
   2722                                              capture_count,
   2723                                              subject_length);
   2724     } else {
   2725       ASSERT(content.IsTwoByte());
   2726       simple_hint_ = ParseReplacementPattern(&parts_,
   2727                                              content.ToUC16Vector(),
   2728                                              capture_count,
   2729                                              subject_length);
   2730     }
   2731   }
   2732   Isolate* isolate = replacement->GetIsolate();
   2733   // Find substrings of replacement string and create them as String objects.
   2734   int substring_index = 0;
   2735   for (int i = 0, n = parts_.length(); i < n; i++) {
   2736     int tag = parts_[i].tag;
   2737     if (tag <= 0) {  // A replacement string slice.
   2738       int from = -tag;
   2739       int to = parts_[i].data;
   2740       replacement_substrings_.Add(
   2741           isolate->factory()->NewSubString(replacement, from, to));
   2742       parts_[i].tag = REPLACEMENT_SUBSTRING;
   2743       parts_[i].data = substring_index;
   2744       substring_index++;
   2745     } else if (tag == REPLACEMENT_STRING) {
   2746       replacement_substrings_.Add(replacement);
   2747       parts_[i].data = substring_index;
   2748       substring_index++;
   2749     }
   2750   }
   2751 }
   2752 
   2753 
   2754 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
   2755                                 int match_from,
   2756                                 int match_to,
   2757                                 Handle<JSArray> last_match_info) {
   2758   for (int i = 0, n = parts_.length(); i < n; i++) {
   2759     ReplacementPart part = parts_[i];
   2760     switch (part.tag) {
   2761       case SUBJECT_PREFIX:
   2762         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
   2763         break;
   2764       case SUBJECT_SUFFIX: {
   2765         int subject_length = part.data;
   2766         if (match_to < subject_length) {
   2767           builder->AddSubjectSlice(match_to, subject_length);
   2768         }
   2769         break;
   2770       }
   2771       case SUBJECT_CAPTURE: {
   2772         int capture = part.data;
   2773         FixedArray* match_info = FixedArray::cast(last_match_info->elements());
   2774         int from = RegExpImpl::GetCapture(match_info, capture * 2);
   2775         int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
   2776         if (from >= 0 && to > from) {
   2777           builder->AddSubjectSlice(from, to);
   2778         }
   2779         break;
   2780       }
   2781       case REPLACEMENT_SUBSTRING:
   2782       case REPLACEMENT_STRING:
   2783         builder->AddString(replacement_substrings_[part.data]);
   2784         break;
   2785       default:
   2786         UNREACHABLE();
   2787     }
   2788   }
   2789 }
   2790 
   2791 
   2792 void FindAsciiStringIndices(Vector<const char> subject,
   2793                             char pattern,
   2794                             ZoneList<int>* indices,
   2795                             unsigned int limit) {
   2796   ASSERT(limit > 0);
   2797   // Collect indices of pattern in subject using memchr.
   2798   // Stop after finding at most limit values.
   2799   const char* subject_start = reinterpret_cast<const char*>(subject.start());
   2800   const char* subject_end = subject_start + subject.length();
   2801   const char* pos = subject_start;
   2802   while (limit > 0) {
   2803     pos = reinterpret_cast<const char*>(
   2804         memchr(pos, pattern, subject_end - pos));
   2805     if (pos == NULL) return;
   2806     indices->Add(static_cast<int>(pos - subject_start));
   2807     pos++;
   2808     limit--;
   2809   }
   2810 }
   2811 
   2812 
   2813 template <typename SubjectChar, typename PatternChar>
   2814 void FindStringIndices(Isolate* isolate,
   2815                        Vector<const SubjectChar> subject,
   2816                        Vector<const PatternChar> pattern,
   2817                        ZoneList<int>* indices,
   2818                        unsigned int limit) {
   2819   ASSERT(limit > 0);
   2820   // Collect indices of pattern in subject.
   2821   // Stop after finding at most limit values.
   2822   int pattern_length = pattern.length();
   2823   int index = 0;
   2824   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
   2825   while (limit > 0) {
   2826     index = search.Search(subject, index);
   2827     if (index < 0) return;
   2828     indices->Add(index);
   2829     index += pattern_length;
   2830     limit--;
   2831   }
   2832 }
   2833 
   2834 
   2835 void FindStringIndicesDispatch(Isolate* isolate,
   2836                                String* subject,
   2837                                String* pattern,
   2838                                ZoneList<int>* indices,
   2839                                unsigned int limit) {
   2840   {
   2841     AssertNoAllocation no_gc;
   2842     String::FlatContent subject_content = subject->GetFlatContent();
   2843     String::FlatContent pattern_content = pattern->GetFlatContent();
   2844     ASSERT(subject_content.IsFlat());
   2845     ASSERT(pattern_content.IsFlat());
   2846     if (subject_content.IsAscii()) {
   2847       Vector<const char> subject_vector = subject_content.ToAsciiVector();
   2848       if (pattern_content.IsAscii()) {
   2849         Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
   2850         if (pattern_vector.length() == 1) {
   2851           FindAsciiStringIndices(subject_vector,
   2852                                  pattern_vector[0],
   2853                                  indices,
   2854                                  limit);
   2855         } else {
   2856           FindStringIndices(isolate,
   2857                             subject_vector,
   2858                             pattern_vector,
   2859                             indices,
   2860                             limit);
   2861         }
   2862       } else {
   2863         FindStringIndices(isolate,
   2864                           subject_vector,
   2865                           pattern_content.ToUC16Vector(),
   2866                           indices,
   2867                           limit);
   2868       }
   2869     } else {
   2870       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
   2871       if (pattern_content.IsAscii()) {
   2872         FindStringIndices(isolate,
   2873                           subject_vector,
   2874                           pattern_content.ToAsciiVector(),
   2875                           indices,
   2876                           limit);
   2877       } else {
   2878         FindStringIndices(isolate,
   2879                           subject_vector,
   2880                           pattern_content.ToUC16Vector(),
   2881                           indices,
   2882                           limit);
   2883       }
   2884     }
   2885   }
   2886 }
   2887 
   2888 
   2889 template<typename ResultSeqString>
   2890 MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString(
   2891     Isolate* isolate,
   2892     Handle<String> subject,
   2893     Handle<JSRegExp> pattern_regexp,
   2894     Handle<String> replacement) {
   2895   ASSERT(subject->IsFlat());
   2896   ASSERT(replacement->IsFlat());
   2897 
   2898   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
   2899   ZoneList<int> indices(8);
   2900   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
   2901   String* pattern =
   2902       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
   2903   int subject_len = subject->length();
   2904   int pattern_len = pattern->length();
   2905   int replacement_len = replacement->length();
   2906 
   2907   FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
   2908 
   2909   int matches = indices.length();
   2910   if (matches == 0) return *subject;
   2911 
   2912   int result_len = (replacement_len - pattern_len) * matches + subject_len;
   2913   int subject_pos = 0;
   2914   int result_pos = 0;
   2915 
   2916   Handle<ResultSeqString> result;
   2917   if (ResultSeqString::kHasAsciiEncoding) {
   2918     result = Handle<ResultSeqString>::cast(
   2919         isolate->factory()->NewRawAsciiString(result_len));
   2920   } else {
   2921     result = Handle<ResultSeqString>::cast(
   2922         isolate->factory()->NewRawTwoByteString(result_len));
   2923   }
   2924 
   2925   for (int i = 0; i < matches; i++) {
   2926     // Copy non-matched subject content.
   2927     if (subject_pos < indices.at(i)) {
   2928       String::WriteToFlat(*subject,
   2929                           result->GetChars() + result_pos,
   2930                           subject_pos,
   2931                           indices.at(i));
   2932       result_pos += indices.at(i) - subject_pos;
   2933     }
   2934 
   2935     // Replace match.
   2936     if (replacement_len > 0) {
   2937       String::WriteToFlat(*replacement,
   2938                           result->GetChars() + result_pos,
   2939                           0,
   2940                           replacement_len);
   2941       result_pos += replacement_len;
   2942     }
   2943 
   2944     subject_pos = indices.at(i) + pattern_len;
   2945   }
   2946   // Add remaining subject content at the end.
   2947   if (subject_pos < subject_len) {
   2948     String::WriteToFlat(*subject,
   2949                         result->GetChars() + result_pos,
   2950                         subject_pos,
   2951                         subject_len);
   2952   }
   2953   return *result;
   2954 }
   2955 
   2956 
   2957 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
   2958     Isolate* isolate,
   2959     String* subject,
   2960     JSRegExp* regexp,
   2961     String* replacement,
   2962     JSArray* last_match_info) {
   2963   ASSERT(subject->IsFlat());
   2964   ASSERT(replacement->IsFlat());
   2965 
   2966   HandleScope handles(isolate);
   2967 
   2968   int length = subject->length();
   2969   Handle<String> subject_handle(subject);
   2970   Handle<JSRegExp> regexp_handle(regexp);
   2971   Handle<String> replacement_handle(replacement);
   2972   Handle<JSArray> last_match_info_handle(last_match_info);
   2973   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
   2974                                           subject_handle,
   2975                                           0,
   2976                                           last_match_info_handle);
   2977   if (match.is_null()) {
   2978     return Failure::Exception();
   2979   }
   2980   if (match->IsNull()) {
   2981     return *subject_handle;
   2982   }
   2983 
   2984   int capture_count = regexp_handle->CaptureCount();
   2985 
   2986   // CompiledReplacement uses zone allocation.
   2987   ZoneScope zone(isolate, DELETE_ON_EXIT);
   2988   CompiledReplacement compiled_replacement;
   2989   compiled_replacement.Compile(replacement_handle,
   2990                                capture_count,
   2991                                length);
   2992 
   2993   bool is_global = regexp_handle->GetFlags().is_global();
   2994 
   2995   // Shortcut for simple non-regexp global replacements
   2996   if (is_global &&
   2997       regexp_handle->TypeTag() == JSRegExp::ATOM &&
   2998       compiled_replacement.simple_hint()) {
   2999     if (subject_handle->HasOnlyAsciiChars() &&
   3000         replacement_handle->HasOnlyAsciiChars()) {
   3001       return StringReplaceStringWithString<SeqAsciiString>(
   3002           isolate, subject_handle, regexp_handle, replacement_handle);
   3003     } else {
   3004       return StringReplaceStringWithString<SeqTwoByteString>(
   3005           isolate, subject_handle, regexp_handle, replacement_handle);
   3006     }
   3007   }
   3008 
   3009   // Guessing the number of parts that the final result string is built
   3010   // from. Global regexps can match any number of times, so we guess
   3011   // conservatively.
   3012   int expected_parts =
   3013       (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
   3014   ReplacementStringBuilder builder(isolate->heap(),
   3015                                    subject_handle,
   3016                                    expected_parts);
   3017 
   3018   // Index of end of last match.
   3019   int prev = 0;
   3020 
   3021   // Number of parts added by compiled replacement plus preceeding
   3022   // string and possibly suffix after last match.  It is possible for
   3023   // all components to use two elements when encoded as two smis.
   3024   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
   3025   bool matched = true;
   3026   do {
   3027     ASSERT(last_match_info_handle->HasFastElements());
   3028     // Increase the capacity of the builder before entering local handle-scope,
   3029     // so its internal buffer can safely allocate a new handle if it grows.
   3030     builder.EnsureCapacity(parts_added_per_loop);
   3031 
   3032     HandleScope loop_scope(isolate);
   3033     int start, end;
   3034     {
   3035       AssertNoAllocation match_info_array_is_not_in_a_handle;
   3036       FixedArray* match_info_array =
   3037           FixedArray::cast(last_match_info_handle->elements());
   3038 
   3039       ASSERT_EQ(capture_count * 2 + 2,
   3040                 RegExpImpl::GetLastCaptureCount(match_info_array));
   3041       start = RegExpImpl::GetCapture(match_info_array, 0);
   3042       end = RegExpImpl::GetCapture(match_info_array, 1);
   3043     }
   3044 
   3045     if (prev < start) {
   3046       builder.AddSubjectSlice(prev, start);
   3047     }
   3048     compiled_replacement.Apply(&builder,
   3049                                start,
   3050                                end,
   3051                                last_match_info_handle);
   3052     prev = end;
   3053 
   3054     // Only continue checking for global regexps.
   3055     if (!is_global) break;
   3056 
   3057     // Continue from where the match ended, unless it was an empty match.
   3058     int next = end;
   3059     if (start == end) {
   3060       next = end + 1;
   3061       if (next > length) break;
   3062     }
   3063 
   3064     match = RegExpImpl::Exec(regexp_handle,
   3065                              subject_handle,
   3066                              next,
   3067                              last_match_info_handle);
   3068     if (match.is_null()) {
   3069       return Failure::Exception();
   3070     }
   3071     matched = !match->IsNull();
   3072   } while (matched);
   3073 
   3074   if (prev < length) {
   3075     builder.AddSubjectSlice(prev, length);
   3076   }
   3077 
   3078   return *(builder.ToString());
   3079 }
   3080 
   3081 
   3082 template <typename ResultSeqString>
   3083 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
   3084     Isolate* isolate,
   3085     String* subject,
   3086     JSRegExp* regexp,
   3087     JSArray* last_match_info) {
   3088   ASSERT(subject->IsFlat());
   3089 
   3090   HandleScope handles(isolate);
   3091 
   3092   Handle<String> subject_handle(subject);
   3093   Handle<JSRegExp> regexp_handle(regexp);
   3094 
   3095   // Shortcut for simple non-regexp global replacements
   3096   if (regexp_handle->GetFlags().is_global() &&
   3097       regexp_handle->TypeTag() == JSRegExp::ATOM) {
   3098     Handle<String> empty_string_handle(HEAP->empty_string());
   3099     if (subject_handle->HasOnlyAsciiChars()) {
   3100       return StringReplaceStringWithString<SeqAsciiString>(
   3101           isolate, subject_handle, regexp_handle, empty_string_handle);
   3102     } else {
   3103       return StringReplaceStringWithString<SeqTwoByteString>(
   3104           isolate, subject_handle, regexp_handle, empty_string_handle);
   3105     }
   3106   }
   3107 
   3108   Handle<JSArray> last_match_info_handle(last_match_info);
   3109   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
   3110                                           subject_handle,
   3111                                           0,
   3112                                           last_match_info_handle);
   3113   if (match.is_null()) return Failure::Exception();
   3114   if (match->IsNull()) return *subject_handle;
   3115 
   3116   ASSERT(last_match_info_handle->HasFastElements());
   3117 
   3118   int start, end;
   3119   {
   3120     AssertNoAllocation match_info_array_is_not_in_a_handle;
   3121     FixedArray* match_info_array =
   3122         FixedArray::cast(last_match_info_handle->elements());
   3123 
   3124     start = RegExpImpl::GetCapture(match_info_array, 0);
   3125     end = RegExpImpl::GetCapture(match_info_array, 1);
   3126   }
   3127 
   3128   int length = subject_handle->length();
   3129   int new_length = length - (end - start);
   3130   if (new_length == 0) {
   3131     return isolate->heap()->empty_string();
   3132   }
   3133   Handle<ResultSeqString> answer;
   3134   if (ResultSeqString::kHasAsciiEncoding) {
   3135     answer = Handle<ResultSeqString>::cast(
   3136         isolate->factory()->NewRawAsciiString(new_length));
   3137   } else {
   3138     answer = Handle<ResultSeqString>::cast(
   3139         isolate->factory()->NewRawTwoByteString(new_length));
   3140   }
   3141 
   3142   // If the regexp isn't global, only match once.
   3143   if (!regexp_handle->GetFlags().is_global()) {
   3144     if (start > 0) {
   3145       String::WriteToFlat(*subject_handle,
   3146                           answer->GetChars(),
   3147                           0,
   3148                           start);
   3149     }
   3150     if (end < length) {
   3151       String::WriteToFlat(*subject_handle,
   3152                           answer->GetChars() + start,
   3153                           end,
   3154                           length);
   3155     }
   3156     return *answer;
   3157   }
   3158 
   3159   int prev = 0;  // Index of end of last match.
   3160   int next = 0;  // Start of next search (prev unless last match was empty).
   3161   int position = 0;
   3162 
   3163   do {
   3164     if (prev < start) {
   3165       // Add substring subject[prev;start] to answer string.
   3166       String::WriteToFlat(*subject_handle,
   3167                           answer->GetChars() + position,
   3168                           prev,
   3169                           start);
   3170       position += start - prev;
   3171     }
   3172     prev = end;
   3173     next = end;
   3174     // Continue from where the match ended, unless it was an empty match.
   3175     if (start == end) {
   3176       next++;
   3177       if (next > length) break;
   3178     }
   3179     match = RegExpImpl::Exec(regexp_handle,
   3180                              subject_handle,
   3181                              next,
   3182                              last_match_info_handle);
   3183     if (match.is_null()) return Failure::Exception();
   3184     if (match->IsNull()) break;
   3185 
   3186     ASSERT(last_match_info_handle->HasFastElements());
   3187     HandleScope loop_scope(isolate);
   3188     {
   3189       AssertNoAllocation match_info_array_is_not_in_a_handle;
   3190       FixedArray* match_info_array =
   3191           FixedArray::cast(last_match_info_handle->elements());
   3192       start = RegExpImpl::GetCapture(match_info_array, 0);
   3193       end = RegExpImpl::GetCapture(match_info_array, 1);
   3194     }
   3195   } while (true);
   3196 
   3197   if (prev < length) {
   3198     // Add substring subject[prev;length] to answer string.
   3199     String::WriteToFlat(*subject_handle,
   3200                         answer->GetChars() + position,
   3201                         prev,
   3202                         length);
   3203     position += length - prev;
   3204   }
   3205 
   3206   if (position == 0) {
   3207     return isolate->heap()->empty_string();
   3208   }
   3209 
   3210   // Shorten string and fill
   3211   int string_size = ResultSeqString::SizeFor(position);
   3212   int allocated_string_size = ResultSeqString::SizeFor(new_length);
   3213   int delta = allocated_string_size - string_size;
   3214 
   3215   answer->set_length(position);
   3216   if (delta == 0) return *answer;
   3217 
   3218   Address end_of_string = answer->address() + string_size;
   3219   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
   3220   if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
   3221     MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
   3222   }
   3223 
   3224   return *answer;
   3225 }
   3226 
   3227 
   3228 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
   3229   ASSERT(args.length() == 4);
   3230 
   3231   CONVERT_ARG_CHECKED(String, subject, 0);
   3232   if (!subject->IsFlat()) {
   3233     Object* flat_subject;
   3234     { MaybeObject* maybe_flat_subject = subject->TryFlatten();
   3235       if (!maybe_flat_subject->ToObject(&flat_subject)) {
   3236         return maybe_flat_subject;
   3237       }
   3238     }
   3239     subject = String::cast(flat_subject);
   3240   }
   3241 
   3242   CONVERT_ARG_CHECKED(String, replacement, 2);
   3243   if (!replacement->IsFlat()) {
   3244     Object* flat_replacement;
   3245     { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
   3246       if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
   3247         return maybe_flat_replacement;
   3248       }
   3249     }
   3250     replacement = String::cast(flat_replacement);
   3251   }
   3252 
   3253   CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
   3254   CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
   3255 
   3256   ASSERT(last_match_info->HasFastElements());
   3257 
   3258   if (replacement->length() == 0) {
   3259     if (subject->HasOnlyAsciiChars()) {
   3260       return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
   3261           isolate, subject, regexp, last_match_info);
   3262     } else {
   3263       return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
   3264           isolate, subject, regexp, last_match_info);
   3265     }
   3266   }
   3267 
   3268   return StringReplaceRegExpWithString(isolate,
   3269                                        subject,
   3270                                        regexp,
   3271                                        replacement,
   3272                                        last_match_info);
   3273 }
   3274 
   3275 
   3276 Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
   3277                                                        Handle<String> subject,
   3278                                                        Handle<String> search,
   3279                                                        Handle<String> replace,
   3280                                                        bool* found,
   3281                                                        int recursion_limit) {
   3282   if (recursion_limit == 0) return Handle<String>::null();
   3283   if (subject->IsConsString()) {
   3284     ConsString* cons = ConsString::cast(*subject);
   3285     Handle<String> first = Handle<String>(cons->first());
   3286     Handle<String> second = Handle<String>(cons->second());
   3287     Handle<String> new_first =
   3288         StringReplaceOneCharWithString(isolate,
   3289                                        first,
   3290                                        search,
   3291                                        replace,
   3292                                        found,
   3293                                        recursion_limit - 1);
   3294     if (*found) return isolate->factory()->NewConsString(new_first, second);
   3295     if (new_first.is_null()) return new_first;
   3296 
   3297     Handle<String> new_second =
   3298         StringReplaceOneCharWithString(isolate,
   3299                                        second,
   3300                                        search,
   3301                                        replace,
   3302                                        found,
   3303                                        recursion_limit - 1);
   3304     if (*found) return isolate->factory()->NewConsString(first, new_second);
   3305     if (new_second.is_null()) return new_second;
   3306 
   3307     return subject;
   3308   } else {
   3309     int index = StringMatch(isolate, subject, search, 0);
   3310     if (index == -1) return subject;
   3311     *found = true;
   3312     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
   3313     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
   3314     Handle<String> second =
   3315         isolate->factory()->NewSubString(subject, index + 1, subject->length());
   3316     return isolate->factory()->NewConsString(cons1, second);
   3317   }
   3318 }
   3319 
   3320 
   3321 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
   3322   ASSERT(args.length() == 3);
   3323   HandleScope scope(isolate);
   3324   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
   3325   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
   3326   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
   3327 
   3328   // If the cons string tree is too deep, we simply abort the recursion and
   3329   // retry with a flattened subject string.
   3330   const int kRecursionLimit = 0x1000;
   3331   bool found = false;
   3332   Handle<String> result =
   3333       Runtime::StringReplaceOneCharWithString(isolate,
   3334                                               subject,
   3335                                               search,
   3336                                               replace,
   3337                                               &found,
   3338                                               kRecursionLimit);
   3339   if (!result.is_null()) return *result;
   3340   return *Runtime::StringReplaceOneCharWithString(isolate,
   3341                                                   FlattenGetString(subject),
   3342                                                   search,
   3343                                                   replace,
   3344                                                   &found,
   3345                                                   kRecursionLimit);
   3346 }
   3347 
   3348 
   3349 // Perform string match of pattern on subject, starting at start index.
   3350 // Caller must ensure that 0 <= start_index <= sub->length(),
   3351 // and should check that pat->length() + start_index <= sub->length().
   3352 int Runtime::StringMatch(Isolate* isolate,
   3353                          Handle<String> sub,
   3354                          Handle<String> pat,
   3355                          int start_index) {
   3356   ASSERT(0 <= start_index);
   3357   ASSERT(start_index <= sub->length());
   3358 
   3359   int pattern_length = pat->length();
   3360   if (pattern_length == 0) return start_index;
   3361 
   3362   int subject_length = sub->length();
   3363   if (start_index + pattern_length > subject_length) return -1;
   3364 
   3365   if (!sub->IsFlat()) FlattenString(sub);
   3366   if (!pat->IsFlat()) FlattenString(pat);
   3367 
   3368   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
   3369   // Extract flattened substrings of cons strings before determining asciiness.
   3370   String::FlatContent seq_sub = sub->GetFlatContent();
   3371   String::FlatContent seq_pat = pat->GetFlatContent();
   3372 
   3373   // dispatch on type of strings
   3374   if (seq_pat.IsAscii()) {
   3375     Vector<const char> pat_vector = seq_pat.ToAsciiVector();
   3376     if (seq_sub.IsAscii()) {
   3377       return SearchString(isolate,
   3378                           seq_sub.ToAsciiVector(),
   3379                           pat_vector,
   3380                           start_index);
   3381     }
   3382     return SearchString(isolate,
   3383                         seq_sub.ToUC16Vector(),
   3384                         pat_vector,
   3385                         start_index);
   3386   }
   3387   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
   3388   if (seq_sub.IsAscii()) {
   3389     return SearchString(isolate,
   3390                         seq_sub.ToAsciiVector(),
   3391                         pat_vector,
   3392                         start_index);
   3393   }
   3394   return SearchString(isolate,
   3395                       seq_sub.ToUC16Vector(),
   3396                       pat_vector,
   3397                       start_index);
   3398 }
   3399 
   3400 
   3401 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
   3402   HandleScope scope(isolate);  // create a new handle scope
   3403   ASSERT(args.length() == 3);
   3404 
   3405   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
   3406   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
   3407 
   3408   Object* index = args[2];
   3409   uint32_t start_index;
   3410   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
   3411 
   3412   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
   3413   int position =
   3414       Runtime::StringMatch(isolate, sub, pat, start_index);
   3415   return Smi::FromInt(position);
   3416 }
   3417 
   3418 
   3419 template <typename schar, typename pchar>
   3420 static int StringMatchBackwards(Vector<const schar> subject,
   3421                                 Vector<const pchar> pattern,
   3422                                 int idx) {
   3423   int pattern_length = pattern.length();
   3424   ASSERT(pattern_length >= 1);
   3425   ASSERT(idx + pattern_length <= subject.length());
   3426 
   3427   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
   3428     for (int i = 0; i < pattern_length; i++) {
   3429       uc16 c = pattern[i];
   3430       if (c > String::kMaxAsciiCharCode) {
   3431         return -1;
   3432       }
   3433     }
   3434   }
   3435 
   3436   pchar pattern_first_char = pattern[0];
   3437   for (int i = idx; i >= 0; i--) {
   3438     if (subject[i] != pattern_first_char) continue;
   3439     int j = 1;
   3440     while (j < pattern_length) {
   3441       if (pattern[j] != subject[i+j]) {
   3442         break;
   3443       }
   3444       j++;
   3445     }
   3446     if (j == pattern_length) {
   3447       return i;
   3448     }
   3449   }
   3450   return -1;
   3451 }
   3452 
   3453 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
   3454   HandleScope scope(isolate);  // create a new handle scope
   3455   ASSERT(args.length() == 3);
   3456 
   3457   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
   3458   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
   3459 
   3460   Object* index = args[2];
   3461   uint32_t start_index;
   3462   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
   3463 
   3464   uint32_t pat_length = pat->length();
   3465   uint32_t sub_length = sub->length();
   3466 
   3467   if (start_index + pat_length > sub_length) {
   3468     start_index = sub_length - pat_length;
   3469   }
   3470 
   3471   if (pat_length == 0) {
   3472     return Smi::FromInt(start_index);
   3473   }
   3474 
   3475   if (!sub->IsFlat()) FlattenString(sub);
   3476   if (!pat->IsFlat()) FlattenString(pat);
   3477 
   3478   int position = -1;
   3479   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
   3480 
   3481   String::FlatContent sub_content = sub->GetFlatContent();
   3482   String::FlatContent pat_content = pat->GetFlatContent();
   3483 
   3484   if (pat_content.IsAscii()) {
   3485     Vector<const char> pat_vector = pat_content.ToAsciiVector();
   3486     if (sub_content.IsAscii()) {
   3487       position = StringMatchBackwards(sub_content.ToAsciiVector(),
   3488                                       pat_vector,
   3489                                       start_index);
   3490     } else {
   3491       position = StringMatchBackwards(sub_content.ToUC16Vector(),
   3492                                       pat_vector,
   3493                                       start_index);
   3494     }
   3495   } else {
   3496     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
   3497     if (sub_content.IsAscii()) {
   3498       position = StringMatchBackwards(sub_content.ToAsciiVector(),
   3499                                       pat_vector,
   3500                                       start_index);
   3501     } else {
   3502       position = StringMatchBackwards(sub_content.ToUC16Vector(),
   3503                                       pat_vector,
   3504                                       start_index);
   3505     }
   3506   }
   3507 
   3508   return Smi::FromInt(position);
   3509 }
   3510 
   3511 
   3512 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
   3513   NoHandleAllocation ha;
   3514   ASSERT(args.length() == 2);
   3515 
   3516   CONVERT_ARG_CHECKED(String, str1, 0);
   3517   CONVERT_ARG_CHECKED(String, str2, 1);
   3518 
   3519   if (str1 == str2) return Smi::FromInt(0);  // Equal.
   3520   int str1_length = str1->length();
   3521   int str2_length = str2->length();
   3522 
   3523   // Decide trivial cases without flattening.
   3524   if (str1_length == 0) {
   3525     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
   3526     return Smi::FromInt(-str2_length);
   3527   } else {
   3528     if (str2_length == 0) return Smi::FromInt(str1_length);
   3529   }
   3530 
   3531   int end = str1_length < str2_length ? str1_length : str2_length;
   3532 
   3533   // No need to flatten if we are going to find the answer on the first
   3534   // character.  At this point we know there is at least one character
   3535   // in each string, due to the trivial case handling above.
   3536   int d = str1->Get(0) - str2->Get(0);
   3537   if (d != 0) return Smi::FromInt(d);
   3538 
   3539   str1->TryFlatten();
   3540   str2->TryFlatten();
   3541 
   3542   StringInputBuffer& buf1 =
   3543       *isolate->runtime_state()->string_locale_compare_buf1();
   3544   StringInputBuffer& buf2 =
   3545       *isolate->runtime_state()->string_locale_compare_buf2();
   3546 
   3547   buf1.Reset(str1);
   3548   buf2.Reset(str2);
   3549 
   3550   for (int i = 0; i < end; i++) {
   3551     uint16_t char1 = buf1.GetNext();
   3552     uint16_t char2 = buf2.GetNext();
   3553     if (char1 != char2) return Smi::FromInt(char1 - char2);
   3554   }
   3555 
   3556   return Smi::FromInt(str1_length - str2_length);
   3557 }
   3558 
   3559 
   3560 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
   3561   NoHandleAllocation ha;
   3562   ASSERT(args.length() == 3);
   3563 
   3564   CONVERT_ARG_CHECKED(String, value, 0);
   3565   int start, end;
   3566   // We have a fast integer-only case here to avoid a conversion to double in
   3567   // the common case where from and to are Smis.
   3568   if (args[1]->IsSmi() && args[2]->IsSmi()) {
   3569     CONVERT_SMI_ARG_CHECKED(from_number, 1);
   3570     CONVERT_SMI_ARG_CHECKED(to_number, 2);
   3571     start = from_number;
   3572     end = to_number;
   3573   } else {
   3574     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
   3575     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
   3576     start = FastD2I(from_number);
   3577     end = FastD2I(to_number);
   3578   }
   3579   RUNTIME_ASSERT(end >= start);
   3580   RUNTIME_ASSERT(start >= 0);
   3581   RUNTIME_ASSERT(end <= value->length());
   3582   isolate->counters()->sub_string_runtime()->Increment();
   3583   return value->SubString(start, end);
   3584 }
   3585 
   3586 
   3587 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
   3588   ASSERT_EQ(3, args.length());
   3589 
   3590   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
   3591   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
   3592   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
   3593   HandleScope handles;
   3594 
   3595   Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
   3596 
   3597   if (match.is_null()) {
   3598     return Failure::Exception();
   3599   }
   3600   if (match->IsNull()) {
   3601     return isolate->heap()->null_value();
   3602   }
   3603   int length = subject->length();
   3604 
   3605   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
   3606   ZoneList<int> offsets(8);
   3607   int start;
   3608   int end;
   3609   do {
   3610     {
   3611       AssertNoAllocation no_alloc;
   3612       FixedArray* elements = FixedArray::cast(regexp_info->elements());
   3613       start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
   3614       end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
   3615     }
   3616     offsets.Add(start);
   3617     offsets.Add(end);
   3618     if (start == end) if (++end > length) break;
   3619     match = RegExpImpl::Exec(regexp, subject, end, regexp_info);
   3620     if (match.is_null()) {
   3621       return Failure::Exception();
   3622     }
   3623   } while (!match->IsNull());
   3624   int matches = offsets.length() / 2;
   3625   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
   3626   Handle<String> substring = isolate->factory()->
   3627     NewSubString(subject, offsets.at(0), offsets.at(1));
   3628   elements->set(0, *substring);
   3629   for (int i = 1; i < matches ; i++) {
   3630     int from = offsets.at(i * 2);
   3631     int to = offsets.at(i * 2 + 1);
   3632     Handle<String> substring = isolate->factory()->
   3633         NewProperSubString(subject, from, to);
   3634     elements->set(i, *substring);
   3635   }
   3636   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
   3637   result->set_length(Smi::FromInt(matches));
   3638   return *result;
   3639 }
   3640 
   3641 
   3642 // Two smis before and after the match, for very long strings.
   3643 const int kMaxBuilderEntriesPerRegExpMatch = 5;
   3644 
   3645 
   3646 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
   3647                                        Handle<JSArray> last_match_info,
   3648                                        int match_start,
   3649                                        int match_end) {
   3650   // Fill last_match_info with a single capture.
   3651   last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
   3652   AssertNoAllocation no_gc;
   3653   FixedArray* elements = FixedArray::cast(last_match_info->elements());
   3654   RegExpImpl::SetLastCaptureCount(elements, 2);
   3655   RegExpImpl::SetLastInput(elements, *subject);
   3656   RegExpImpl::SetLastSubject(elements, *subject);
   3657   RegExpImpl::SetCapture(elements, 0, match_start);
   3658   RegExpImpl::SetCapture(elements, 1, match_end);
   3659 }
   3660 
   3661 
   3662 template <typename SubjectChar, typename PatternChar>
   3663 static bool SearchStringMultiple(Isolate* isolate,
   3664                                  Vector<const SubjectChar> subject,
   3665                                  Vector<const PatternChar> pattern,
   3666                                  String* pattern_string,
   3667                                  FixedArrayBuilder* builder,
   3668                                  int* match_pos) {
   3669   int pos = *match_pos;
   3670   int subject_length = subject.length();
   3671   int pattern_length = pattern.length();
   3672   int max_search_start = subject_length - pattern_length;
   3673   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
   3674   while (pos <= max_search_start) {
   3675     if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
   3676       *match_pos = pos;
   3677       return false;
   3678     }
   3679     // Position of end of previous match.
   3680     int match_end = pos + pattern_length;
   3681     int new_pos = search.Search(subject, match_end);
   3682     if (new_pos >= 0) {
   3683       // A match.
   3684       if (new_pos > match_end) {
   3685         ReplacementStringBuilder::AddSubjectSlice(builder,
   3686             match_end,
   3687             new_pos);
   3688       }
   3689       pos = new_pos;
   3690       builder->Add(pattern_string);
   3691     } else {
   3692       break;
   3693     }
   3694   }
   3695 
   3696   if (pos < max_search_start) {
   3697     ReplacementStringBuilder::AddSubjectSlice(builder,
   3698                                               pos + pattern_length,
   3699                                               subject_length);
   3700   }
   3701   *match_pos = pos;
   3702   return true;
   3703 }
   3704 
   3705 
   3706 static bool SearchStringMultiple(Isolate* isolate,
   3707                                  Handle<String> subject,
   3708                                  Handle<String> pattern,
   3709                                  Handle<JSArray> last_match_info,
   3710                                  FixedArrayBuilder* builder) {
   3711   ASSERT(subject->IsFlat());
   3712   ASSERT(pattern->IsFlat());
   3713 
   3714   // Treating as if a previous match was before first character.
   3715   int match_pos = -pattern->length();
   3716 
   3717   for (;;) {  // Break when search complete.
   3718     builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
   3719     AssertNoAllocation no_gc;
   3720     String::FlatContent subject_content = subject->GetFlatContent();
   3721     String::FlatContent pattern_content = pattern->GetFlatContent();
   3722     if (subject_content.IsAscii()) {
   3723       Vector<const char> subject_vector = subject_content.ToAsciiVector();
   3724       if (pattern_content.IsAscii()) {
   3725         if (SearchStringMultiple(isolate,
   3726                                  subject_vector,
   3727                                  pattern_content.ToAsciiVector(),
   3728                                  *pattern,
   3729                                  builder,
   3730                                  &match_pos)) break;
   3731       } else {
   3732         if (SearchStringMultiple(isolate,
   3733                                  subject_vector,
   3734                                  pattern_content.ToUC16Vector(),
   3735                                  *pattern,
   3736                                  builder,
   3737                                  &match_pos)) break;
   3738       }
   3739     } else {
   3740       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
   3741       if (pattern_content.IsAscii()) {
   3742         if (SearchStringMultiple(isolate,
   3743                                  subject_vector,
   3744                                  pattern_content.ToAsciiVector(),
   3745                                  *pattern,
   3746                                  builder,
   3747                                  &match_pos)) break;
   3748       } else {
   3749         if (SearchStringMultiple(isolate,
   3750                                  subject_vector,
   3751                                  pattern_content.ToUC16Vector(),
   3752                                  *pattern,
   3753                                  builder,
   3754                                  &match_pos)) break;
   3755       }
   3756     }
   3757   }
   3758 
   3759   if (match_pos >= 0) {
   3760     SetLastMatchInfoNoCaptures(subject,
   3761                                last_match_info,
   3762                                match_pos,
   3763                                match_pos + pattern->length());
   3764     return true;
   3765   }
   3766   return false;  // No matches at all.
   3767 }
   3768 
   3769 
   3770 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
   3771     Isolate* isolate,
   3772     Handle<String> subject,
   3773     Handle<JSRegExp> regexp,
   3774     Handle<JSArray> last_match_array,
   3775     FixedArrayBuilder* builder) {
   3776   ASSERT(subject->IsFlat());
   3777   int match_start = -1;
   3778   int match_end = 0;
   3779   int pos = 0;
   3780   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
   3781   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
   3782 
   3783   OffsetsVector registers(required_registers, isolate);
   3784   Vector<int32_t> register_vector(registers.vector(), registers.length());
   3785   int subject_length = subject->length();
   3786   bool first = true;
   3787 
   3788   for (;;) {  // Break on failure, return on exception.
   3789     RegExpImpl::IrregexpResult result =
   3790         RegExpImpl::IrregexpExecOnce(regexp,
   3791                                      subject,
   3792                                      pos,
   3793                                      register_vector);
   3794     if (result == RegExpImpl::RE_SUCCESS) {
   3795       match_start = register_vector[0];
   3796       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
   3797       if (match_end < match_start) {
   3798         ReplacementStringBuilder::AddSubjectSlice(builder,
   3799                                                   match_end,
   3800                                                   match_start);
   3801       }
   3802       match_end = register_vector[1];
   3803       HandleScope loop_scope(isolate);
   3804       if (!first) {
   3805         builder->Add(*isolate->factory()->NewProperSubString(subject,
   3806                                                              match_start,
   3807                                                              match_end));
   3808       } else {
   3809         builder->Add(*isolate->factory()->NewSubString(subject,
   3810                                                        match_start,
   3811                                                        match_end));
   3812       }
   3813       if (match_start != match_end) {
   3814         pos = match_end;
   3815       } else {
   3816         pos = match_end + 1;
   3817         if (pos > subject_length) break;
   3818       }
   3819     } else if (result == RegExpImpl::RE_FAILURE) {
   3820       break;
   3821     } else {
   3822       ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
   3823       return result;
   3824     }
   3825     first = false;
   3826   }
   3827 
   3828   if (match_start >= 0) {
   3829     if (match_end < subject_length) {
   3830       ReplacementStringBuilder::AddSubjectSlice(builder,
   3831                                                 match_end,
   3832                                                 subject_length);
   3833     }
   3834     SetLastMatchInfoNoCaptures(subject,
   3835                                last_match_array,
   3836                                match_start,
   3837                                match_end);
   3838     return RegExpImpl::RE_SUCCESS;
   3839   } else {
   3840     return RegExpImpl::RE_FAILURE;  // No matches at all.
   3841   }
   3842 }
   3843 
   3844 
   3845 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
   3846     Isolate* isolate,
   3847     Handle<String> subject,
   3848     Handle<JSRegExp> regexp,
   3849     Handle<JSArray> last_match_array,
   3850     FixedArrayBuilder* builder) {
   3851 
   3852   ASSERT(subject->IsFlat());
   3853   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
   3854   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
   3855 
   3856   OffsetsVector registers(required_registers, isolate);
   3857   Vector<int32_t> register_vector(registers.vector(), registers.length());
   3858 
   3859   RegExpImpl::IrregexpResult result =
   3860       RegExpImpl::IrregexpExecOnce(regexp,
   3861                                    subject,
   3862                                    0,
   3863                                    register_vector);
   3864 
   3865   int capture_count = regexp->CaptureCount();
   3866   int subject_length = subject->length();
   3867 
   3868   // Position to search from.
   3869   int pos = 0;
   3870   // End of previous match. Differs from pos if match was empty.
   3871   int match_end = 0;
   3872   if (result == RegExpImpl::RE_SUCCESS) {
   3873     // Need to keep a copy of the previous match for creating last_match_info
   3874     // at the end, so we have two vectors that we swap between.
   3875     OffsetsVector registers2(required_registers, isolate);
   3876     Vector<int> prev_register_vector(registers2.vector(), registers2.length());
   3877     bool first = true;
   3878     do {
   3879       int match_start = register_vector[0];
   3880       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
   3881       if (match_end < match_start) {
   3882         ReplacementStringBuilder::AddSubjectSlice(builder,
   3883                                                   match_end,
   3884                                                   match_start);
   3885       }
   3886       match_end = register_vector[1];
   3887 
   3888       {
   3889         // Avoid accumulating new handles inside loop.
   3890         HandleScope temp_scope(isolate);
   3891         // Arguments array to replace function is match, captures, index and
   3892         // subject, i.e., 3 + capture count in total.
   3893         Handle<FixedArray> elements =
   3894             isolate->factory()->NewFixedArray(3 + capture_count);
   3895         Handle<String> match;
   3896         if (!first) {
   3897           match = isolate->factory()->NewProperSubString(subject,
   3898                                                          match_start,
   3899                                                          match_end);
   3900         } else {
   3901           match = isolate->factory()->NewSubString(subject,
   3902                                                    match_start,
   3903                                                    match_end);
   3904         }
   3905         elements->set(0, *match);
   3906         for (int i = 1; i <= capture_count; i++) {
   3907           int start = register_vector[i * 2];
   3908           if (start >= 0) {
   3909             int end = register_vector[i * 2 + 1];
   3910             ASSERT(start <= end);
   3911             Handle<String> substring;
   3912             if (!first) {
   3913               substring = isolate->factory()->NewProperSubString(subject,
   3914                                                                  start,
   3915                                                                  end);
   3916             } else {
   3917               substring = isolate->factory()->NewSubString(subject, start, end);
   3918             }
   3919             elements->set(i, *substring);
   3920           } else {
   3921             ASSERT(register_vector[i * 2 + 1] < 0);
   3922             elements->set(i, isolate->heap()->undefined_value());
   3923           }
   3924         }
   3925         elements->set(capture_count + 1, Smi::FromInt(match_start));
   3926         elements->set(capture_count + 2, *subject);
   3927         builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
   3928       }
   3929       // Swap register vectors, so the last successful match is in
   3930       // prev_register_vector.
   3931       Vector<int32_t> tmp = prev_register_vector;
   3932       prev_register_vector = register_vector;
   3933       register_vector = tmp;
   3934 
   3935       if (match_end > match_start) {
   3936         pos = match_end;
   3937       } else {
   3938         pos = match_end + 1;
   3939         if (pos > subject_length) {
   3940           break;
   3941         }
   3942       }
   3943 
   3944       result = RegExpImpl::IrregexpExecOnce(regexp,
   3945                                             subject,
   3946                                             pos,
   3947                                             register_vector);
   3948       first = false;
   3949     } while (result == RegExpImpl::RE_SUCCESS);
   3950 
   3951     if (result != RegExpImpl::RE_EXCEPTION) {
   3952       // Finished matching, with at least one match.
   3953       if (match_end < subject_length) {
   3954         ReplacementStringBuilder::AddSubjectSlice(builder,
   3955                                                   match_end,
   3956                                                   subject_length);
   3957       }
   3958 
   3959       int last_match_capture_count = (capture_count + 1) * 2;
   3960       int last_match_array_size =
   3961           last_match_capture_count + RegExpImpl::kLastMatchOverhead;
   3962       last_match_array->EnsureSize(last_match_array_size);
   3963       AssertNoAllocation no_gc;
   3964       FixedArray* elements = FixedArray::cast(last_match_array->elements());
   3965       RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
   3966       RegExpImpl::SetLastSubject(elements, *subject);
   3967       RegExpImpl::SetLastInput(elements, *subject);
   3968       for (int i = 0; i < last_match_capture_count; i++) {
   3969         RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
   3970       }
   3971       return RegExpImpl::RE_SUCCESS;
   3972     }
   3973   }
   3974   // No matches at all, return failure or exception result directly.
   3975   return result;
   3976 }
   3977 
   3978 
   3979 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
   3980   ASSERT(args.length() == 4);
   3981   HandleScope handles(isolate);
   3982 
   3983   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
   3984   if (!subject->IsFlat()) FlattenString(subject);
   3985   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
   3986   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
   3987   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
   3988 
   3989   ASSERT(last_match_info->HasFastElements());
   3990   ASSERT(regexp->GetFlags().is_global());
   3991   Handle<FixedArray> result_elements;
   3992   if (result_array->HasFastElements()) {
   3993     result_elements =
   3994         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
   3995   }
   3996   if (result_elements.is_null() || result_elements->length() < 16) {
   3997     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
   3998   }
   3999   FixedArrayBuilder builder(result_elements);
   4000 
   4001   if (regexp->TypeTag() == JSRegExp::ATOM) {
   4002     Handle<