| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright 2014 the V8 project authors. All rights reserved. | 
 |    2 // Use of this source code is governed by a BSD-style license that can be | 
 |    3 // found in the LICENSE file. | 
 |    4  | 
 |    5 #include "src/v8.h" | 
 |    6  | 
 |    7 #include "src/allocation-site-scopes.h" | 
 |    8 #include "src/arguments.h" | 
 |    9 #include "src/ast.h" | 
 |   10 #include "src/parser.h" | 
 |   11 #include "src/runtime/runtime.h" | 
 |   12 #include "src/runtime/runtime-utils.h" | 
 |   13  | 
 |   14 namespace v8 { | 
 |   15 namespace internal { | 
 |   16  | 
 |   17 static Handle<Map> ComputeObjectLiteralMap( | 
 |   18     Handle<Context> context, Handle<FixedArray> constant_properties, | 
 |   19     bool* is_result_from_cache) { | 
 |   20   Isolate* isolate = context->GetIsolate(); | 
 |   21   int properties_length = constant_properties->length(); | 
 |   22   int number_of_properties = properties_length / 2; | 
 |   23   // Check that there are only internal strings and array indices among keys. | 
 |   24   int number_of_string_keys = 0; | 
 |   25   for (int p = 0; p != properties_length; p += 2) { | 
 |   26     Object* key = constant_properties->get(p); | 
 |   27     uint32_t element_index = 0; | 
 |   28     if (key->IsInternalizedString()) { | 
 |   29       number_of_string_keys++; | 
 |   30     } else if (key->ToArrayIndex(&element_index)) { | 
 |   31       // An index key does not require space in the property backing store. | 
 |   32       number_of_properties--; | 
 |   33     } else { | 
 |   34       // Bail out as a non-internalized-string non-index key makes caching | 
 |   35       // impossible. | 
 |   36       // DCHECK to make sure that the if condition after the loop is false. | 
 |   37       DCHECK(number_of_string_keys != number_of_properties); | 
 |   38       break; | 
 |   39     } | 
 |   40   } | 
 |   41   // If we only have internalized strings and array indices among keys then we | 
 |   42   // can use the map cache in the native context. | 
 |   43   const int kMaxKeys = 10; | 
 |   44   if ((number_of_string_keys == number_of_properties) && | 
 |   45       (number_of_string_keys < kMaxKeys)) { | 
 |   46     // Create the fixed array with the key. | 
 |   47     Handle<FixedArray> keys = | 
 |   48         isolate->factory()->NewFixedArray(number_of_string_keys); | 
 |   49     if (number_of_string_keys > 0) { | 
 |   50       int index = 0; | 
 |   51       for (int p = 0; p < properties_length; p += 2) { | 
 |   52         Object* key = constant_properties->get(p); | 
 |   53         if (key->IsInternalizedString()) { | 
 |   54           keys->set(index++, key); | 
 |   55         } | 
 |   56       } | 
 |   57       DCHECK(index == number_of_string_keys); | 
 |   58     } | 
 |   59     *is_result_from_cache = true; | 
 |   60     return isolate->factory()->ObjectLiteralMapFromCache(context, keys); | 
 |   61   } | 
 |   62   *is_result_from_cache = false; | 
 |   63   return Map::Create(isolate, number_of_properties); | 
 |   64 } | 
 |   65  | 
 |   66  | 
 |   67 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 
 |   68     Isolate* isolate, Handle<FixedArray> literals, | 
 |   69     Handle<FixedArray> constant_properties); | 
 |   70  | 
 |   71  | 
 |   72 MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate( | 
 |   73     Isolate* isolate, Handle<FixedArray> literals, | 
 |   74     Handle<FixedArray> constant_properties, bool should_have_fast_elements, | 
 |   75     bool has_function_literal) { | 
 |   76   // Get the native context from the literals array.  This is the | 
 |   77   // context in which the function was created and we use the object | 
 |   78   // function from this context to create the object literal.  We do | 
 |   79   // not use the object function from the current native context | 
 |   80   // because this might be the object function from another context | 
 |   81   // which we should not have access to. | 
 |   82   Handle<Context> context = | 
 |   83       Handle<Context>(JSFunction::NativeContextFromLiterals(*literals)); | 
 |   84  | 
 |   85   // In case we have function literals, we want the object to be in | 
 |   86   // slow properties mode for now. We don't go in the map cache because | 
 |   87   // maps with constant functions can't be shared if the functions are | 
 |   88   // not the same (which is the common case). | 
 |   89   bool is_result_from_cache = false; | 
 |   90   Handle<Map> map = has_function_literal | 
 |   91                         ? Handle<Map>(context->object_function()->initial_map()) | 
 |   92                         : ComputeObjectLiteralMap(context, constant_properties, | 
 |   93                                                   &is_result_from_cache); | 
 |   94  | 
 |   95   PretenureFlag pretenure_flag = | 
 |   96       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED; | 
 |   97  | 
 |   98   Handle<JSObject> boilerplate = | 
 |   99       isolate->factory()->NewJSObjectFromMap(map, pretenure_flag); | 
 |  100  | 
 |  101   // Normalize the elements of the boilerplate to save space if needed. | 
 |  102   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate); | 
 |  103  | 
 |  104   // Add the constant properties to the boilerplate. | 
 |  105   int length = constant_properties->length(); | 
 |  106   bool should_transform = | 
 |  107       !is_result_from_cache && boilerplate->HasFastProperties(); | 
 |  108   bool should_normalize = should_transform || has_function_literal; | 
 |  109   if (should_normalize) { | 
 |  110     // TODO(verwaest): We might not want to ever normalize here. | 
 |  111     JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, | 
 |  112                                   length / 2); | 
 |  113   } | 
 |  114   // TODO(verwaest): Support tracking representations in the boilerplate. | 
 |  115   for (int index = 0; index < length; index += 2) { | 
 |  116     Handle<Object> key(constant_properties->get(index + 0), isolate); | 
 |  117     Handle<Object> value(constant_properties->get(index + 1), isolate); | 
 |  118     if (value->IsFixedArray()) { | 
 |  119       // The value contains the constant_properties of a | 
 |  120       // simple object or array literal. | 
 |  121       Handle<FixedArray> array = Handle<FixedArray>::cast(value); | 
 |  122       ASSIGN_RETURN_ON_EXCEPTION( | 
 |  123           isolate, value, CreateLiteralBoilerplate(isolate, literals, array), | 
 |  124           Object); | 
 |  125     } | 
 |  126     MaybeHandle<Object> maybe_result; | 
 |  127     uint32_t element_index = 0; | 
 |  128     if (key->IsInternalizedString()) { | 
 |  129       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { | 
 |  130         // Array index as string (uint32). | 
 |  131         if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate); | 
 |  132         maybe_result = | 
 |  133             JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY); | 
 |  134       } else { | 
 |  135         Handle<String> name(String::cast(*key)); | 
 |  136         DCHECK(!name->AsArrayIndex(&element_index)); | 
 |  137         maybe_result = JSObject::SetOwnPropertyIgnoreAttributes( | 
 |  138             boilerplate, name, value, NONE); | 
 |  139       } | 
 |  140     } else if (key->ToArrayIndex(&element_index)) { | 
 |  141       // Array index (uint32). | 
 |  142       if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate); | 
 |  143       maybe_result = | 
 |  144           JSObject::SetOwnElement(boilerplate, element_index, value, SLOPPY); | 
 |  145     } else { | 
 |  146       // Non-uint32 number. | 
 |  147       DCHECK(key->IsNumber()); | 
 |  148       double num = key->Number(); | 
 |  149       char arr[100]; | 
 |  150       Vector<char> buffer(arr, arraysize(arr)); | 
 |  151       const char* str = DoubleToCString(num, buffer); | 
 |  152       Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str); | 
 |  153       maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, | 
 |  154                                                               value, NONE); | 
 |  155     } | 
 |  156     // If setting the property on the boilerplate throws an | 
 |  157     // exception, the exception is converted to an empty handle in | 
 |  158     // the handle based operations.  In that case, we need to | 
 |  159     // convert back to an exception. | 
 |  160     RETURN_ON_EXCEPTION(isolate, maybe_result, Object); | 
 |  161   } | 
 |  162  | 
 |  163   // Transform to fast properties if necessary. For object literals with | 
 |  164   // containing function literals we defer this operation until after all | 
 |  165   // computed properties have been assigned so that we can generate | 
 |  166   // constant function properties. | 
 |  167   if (should_transform && !has_function_literal) { | 
 |  168     JSObject::MigrateSlowToFast(boilerplate, | 
 |  169                                 boilerplate->map()->unused_property_fields()); | 
 |  170   } | 
 |  171  | 
 |  172   return boilerplate; | 
 |  173 } | 
 |  174  | 
 |  175  | 
 |  176 MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate( | 
 |  177     Isolate* isolate, Handle<FixedArray> literals, | 
 |  178     Handle<FixedArray> elements) { | 
 |  179   // Create the JSArray. | 
 |  180   Handle<JSFunction> constructor( | 
 |  181       JSFunction::NativeContextFromLiterals(*literals)->array_function()); | 
 |  182  | 
 |  183   PretenureFlag pretenure_flag = | 
 |  184       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED; | 
 |  185  | 
 |  186   Handle<JSArray> object = Handle<JSArray>::cast( | 
 |  187       isolate->factory()->NewJSObject(constructor, pretenure_flag)); | 
 |  188  | 
 |  189   ElementsKind constant_elements_kind = | 
 |  190       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); | 
 |  191   Handle<FixedArrayBase> constant_elements_values( | 
 |  192       FixedArrayBase::cast(elements->get(1))); | 
 |  193  | 
 |  194   { | 
 |  195     DisallowHeapAllocation no_gc; | 
 |  196     DCHECK(IsFastElementsKind(constant_elements_kind)); | 
 |  197     Context* native_context = isolate->context()->native_context(); | 
 |  198     Object* maps_array = native_context->js_array_maps(); | 
 |  199     DCHECK(!maps_array->IsUndefined()); | 
 |  200     Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind); | 
 |  201     object->set_map(Map::cast(map)); | 
 |  202   } | 
 |  203  | 
 |  204   Handle<FixedArrayBase> copied_elements_values; | 
 |  205   if (IsFastDoubleElementsKind(constant_elements_kind)) { | 
 |  206     copied_elements_values = isolate->factory()->CopyFixedDoubleArray( | 
 |  207         Handle<FixedDoubleArray>::cast(constant_elements_values)); | 
 |  208   } else { | 
 |  209     DCHECK(IsFastSmiOrObjectElementsKind(constant_elements_kind)); | 
 |  210     const bool is_cow = (constant_elements_values->map() == | 
 |  211                          isolate->heap()->fixed_cow_array_map()); | 
 |  212     if (is_cow) { | 
 |  213       copied_elements_values = constant_elements_values; | 
 |  214 #if DEBUG | 
 |  215       Handle<FixedArray> fixed_array_values = | 
 |  216           Handle<FixedArray>::cast(copied_elements_values); | 
 |  217       for (int i = 0; i < fixed_array_values->length(); i++) { | 
 |  218         DCHECK(!fixed_array_values->get(i)->IsFixedArray()); | 
 |  219       } | 
 |  220 #endif | 
 |  221     } else { | 
 |  222       Handle<FixedArray> fixed_array_values = | 
 |  223           Handle<FixedArray>::cast(constant_elements_values); | 
 |  224       Handle<FixedArray> fixed_array_values_copy = | 
 |  225           isolate->factory()->CopyFixedArray(fixed_array_values); | 
 |  226       copied_elements_values = fixed_array_values_copy; | 
 |  227       for (int i = 0; i < fixed_array_values->length(); i++) { | 
 |  228         if (fixed_array_values->get(i)->IsFixedArray()) { | 
 |  229           // The value contains the constant_properties of a | 
 |  230           // simple object or array literal. | 
 |  231           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i))); | 
 |  232           Handle<Object> result; | 
 |  233           ASSIGN_RETURN_ON_EXCEPTION( | 
 |  234               isolate, result, CreateLiteralBoilerplate(isolate, literals, fa), | 
 |  235               Object); | 
 |  236           fixed_array_values_copy->set(i, *result); | 
 |  237         } | 
 |  238       } | 
 |  239     } | 
 |  240   } | 
 |  241   object->set_elements(*copied_elements_values); | 
 |  242   object->set_length(Smi::FromInt(copied_elements_values->length())); | 
 |  243  | 
 |  244   JSObject::ValidateElements(object); | 
 |  245   return object; | 
 |  246 } | 
 |  247  | 
 |  248  | 
 |  249 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( | 
 |  250     Isolate* isolate, Handle<FixedArray> literals, Handle<FixedArray> array) { | 
 |  251   Handle<FixedArray> elements = CompileTimeValue::GetElements(array); | 
 |  252   const bool kHasNoFunctionLiteral = false; | 
 |  253   switch (CompileTimeValue::GetLiteralType(array)) { | 
 |  254     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: | 
 |  255       return CreateObjectLiteralBoilerplate(isolate, literals, elements, true, | 
 |  256                                             kHasNoFunctionLiteral); | 
 |  257     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: | 
 |  258       return CreateObjectLiteralBoilerplate(isolate, literals, elements, false, | 
 |  259                                             kHasNoFunctionLiteral); | 
 |  260     case CompileTimeValue::ARRAY_LITERAL: | 
 |  261       return Runtime::CreateArrayLiteralBoilerplate(isolate, literals, | 
 |  262                                                     elements); | 
 |  263     default: | 
 |  264       UNREACHABLE(); | 
 |  265       return MaybeHandle<Object>(); | 
 |  266   } | 
 |  267 } | 
 |  268  | 
 |  269  | 
 |  270 RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) { | 
 |  271   HandleScope scope(isolate); | 
 |  272   DCHECK(args.length() == 4); | 
 |  273   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); | 
 |  274   CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 
 |  275   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2); | 
 |  276   CONVERT_SMI_ARG_CHECKED(flags, 3); | 
 |  277   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; | 
 |  278   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; | 
 |  279  | 
 |  280   RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length()); | 
 |  281  | 
 |  282   // Check if boilerplate exists. If not, create it first. | 
 |  283   Handle<Object> literal_site(literals->get(literals_index), isolate); | 
 |  284   Handle<AllocationSite> site; | 
 |  285   Handle<JSObject> boilerplate; | 
 |  286   if (*literal_site == isolate->heap()->undefined_value()) { | 
 |  287     Handle<Object> raw_boilerplate; | 
 |  288     ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
 |  289         isolate, raw_boilerplate, | 
 |  290         CreateObjectLiteralBoilerplate(isolate, literals, constant_properties, | 
 |  291                                        should_have_fast_elements, | 
 |  292                                        has_function_literal)); | 
 |  293     boilerplate = Handle<JSObject>::cast(raw_boilerplate); | 
 |  294  | 
 |  295     AllocationSiteCreationContext creation_context(isolate); | 
 |  296     site = creation_context.EnterNewScope(); | 
 |  297     RETURN_FAILURE_ON_EXCEPTION( | 
 |  298         isolate, JSObject::DeepWalk(boilerplate, &creation_context)); | 
 |  299     creation_context.ExitScope(site, boilerplate); | 
 |  300  | 
 |  301     // Update the functions literal and return the boilerplate. | 
 |  302     literals->set(literals_index, *site); | 
 |  303   } else { | 
 |  304     site = Handle<AllocationSite>::cast(literal_site); | 
 |  305     boilerplate = | 
 |  306         Handle<JSObject>(JSObject::cast(site->transition_info()), isolate); | 
 |  307   } | 
 |  308  | 
 |  309   AllocationSiteUsageContext usage_context(isolate, site, true); | 
 |  310   usage_context.EnterNewScope(); | 
 |  311   MaybeHandle<Object> maybe_copy = | 
 |  312       JSObject::DeepCopy(boilerplate, &usage_context); | 
 |  313   usage_context.ExitScope(site, boilerplate); | 
 |  314   Handle<Object> copy; | 
 |  315   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy); | 
 |  316   return *copy; | 
 |  317 } | 
 |  318  | 
 |  319  | 
 |  320 MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite( | 
 |  321     Isolate* isolate, Handle<FixedArray> literals, int literals_index, | 
 |  322     Handle<FixedArray> elements) { | 
 |  323   // Check if boilerplate exists. If not, create it first. | 
 |  324   Handle<Object> literal_site(literals->get(literals_index), isolate); | 
 |  325   Handle<AllocationSite> site; | 
 |  326   if (*literal_site == isolate->heap()->undefined_value()) { | 
 |  327     DCHECK(*elements != isolate->heap()->empty_fixed_array()); | 
 |  328     Handle<Object> boilerplate; | 
 |  329     ASSIGN_RETURN_ON_EXCEPTION( | 
 |  330         isolate, boilerplate, | 
 |  331         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements), | 
 |  332         AllocationSite); | 
 |  333  | 
 |  334     AllocationSiteCreationContext creation_context(isolate); | 
 |  335     site = creation_context.EnterNewScope(); | 
 |  336     if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate), | 
 |  337                            &creation_context).is_null()) { | 
 |  338       return Handle<AllocationSite>::null(); | 
 |  339     } | 
 |  340     creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate)); | 
 |  341  | 
 |  342     literals->set(literals_index, *site); | 
 |  343   } else { | 
 |  344     site = Handle<AllocationSite>::cast(literal_site); | 
 |  345   } | 
 |  346  | 
 |  347   return site; | 
 |  348 } | 
 |  349  | 
 |  350  | 
 |  351 static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* isolate, | 
 |  352                                                     Handle<FixedArray> literals, | 
 |  353                                                     int literals_index, | 
 |  354                                                     Handle<FixedArray> elements, | 
 |  355                                                     int flags) { | 
 |  356   RUNTIME_ASSERT_HANDLIFIED( | 
 |  357       literals_index >= 0 && literals_index < literals->length(), JSObject); | 
 |  358   Handle<AllocationSite> site; | 
 |  359   ASSIGN_RETURN_ON_EXCEPTION( | 
 |  360       isolate, site, | 
 |  361       GetLiteralAllocationSite(isolate, literals, literals_index, elements), | 
 |  362       JSObject); | 
 |  363  | 
 |  364   bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0; | 
 |  365   Handle<JSObject> boilerplate(JSObject::cast(site->transition_info())); | 
 |  366   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos); | 
 |  367   usage_context.EnterNewScope(); | 
 |  368   JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0 | 
 |  369                                       ? JSObject::kNoHints | 
 |  370                                       : JSObject::kObjectIsShallow; | 
 |  371   MaybeHandle<JSObject> copy = | 
 |  372       JSObject::DeepCopy(boilerplate, &usage_context, hints); | 
 |  373   usage_context.ExitScope(site, boilerplate); | 
 |  374   return copy; | 
 |  375 } | 
 |  376  | 
 |  377  | 
 |  378 RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) { | 
 |  379   HandleScope scope(isolate); | 
 |  380   DCHECK(args.length() == 4); | 
 |  381   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); | 
 |  382   CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 
 |  383   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); | 
 |  384   CONVERT_SMI_ARG_CHECKED(flags, 3); | 
 |  385  | 
 |  386   Handle<JSObject> result; | 
 |  387   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
 |  388       isolate, result, CreateArrayLiteralImpl(isolate, literals, literals_index, | 
 |  389                                               elements, flags)); | 
 |  390   return *result; | 
 |  391 } | 
 |  392  | 
 |  393  | 
 |  394 RUNTIME_FUNCTION(Runtime_CreateArrayLiteralStubBailout) { | 
 |  395   HandleScope scope(isolate); | 
 |  396   DCHECK(args.length() == 3); | 
 |  397   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); | 
 |  398   CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 
 |  399   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); | 
 |  400  | 
 |  401   Handle<JSObject> result; | 
 |  402   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
 |  403       isolate, result, | 
 |  404       CreateArrayLiteralImpl(isolate, literals, literals_index, elements, | 
 |  405                              ArrayLiteral::kShallowElements)); | 
 |  406   return *result; | 
 |  407 } | 
 |  408  | 
 |  409  | 
 |  410 RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement) { | 
 |  411   HandleScope scope(isolate); | 
 |  412   RUNTIME_ASSERT(args.length() == 5); | 
 |  413   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 
 |  414   CONVERT_SMI_ARG_CHECKED(store_index, 1); | 
 |  415   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 
 |  416   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3); | 
 |  417   CONVERT_SMI_ARG_CHECKED(literal_index, 4); | 
 |  418  | 
 |  419   Object* raw_literal_cell = literals->get(literal_index); | 
 |  420   JSArray* boilerplate = NULL; | 
 |  421   if (raw_literal_cell->IsAllocationSite()) { | 
 |  422     AllocationSite* site = AllocationSite::cast(raw_literal_cell); | 
 |  423     boilerplate = JSArray::cast(site->transition_info()); | 
 |  424   } else { | 
 |  425     boilerplate = JSArray::cast(raw_literal_cell); | 
 |  426   } | 
 |  427   Handle<JSArray> boilerplate_object(boilerplate); | 
 |  428   ElementsKind elements_kind = object->GetElementsKind(); | 
 |  429   DCHECK(IsFastElementsKind(elements_kind)); | 
 |  430   // Smis should never trigger transitions. | 
 |  431   DCHECK(!value->IsSmi()); | 
 |  432  | 
 |  433   if (value->IsNumber()) { | 
 |  434     DCHECK(IsFastSmiElementsKind(elements_kind)); | 
 |  435     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind) | 
 |  436                                          ? FAST_HOLEY_DOUBLE_ELEMENTS | 
 |  437                                          : FAST_DOUBLE_ELEMENTS; | 
 |  438     if (IsMoreGeneralElementsKindTransition( | 
 |  439             boilerplate_object->GetElementsKind(), transitioned_kind)) { | 
 |  440       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); | 
 |  441     } | 
 |  442     JSObject::TransitionElementsKind(object, transitioned_kind); | 
 |  443     DCHECK(IsFastDoubleElementsKind(object->GetElementsKind())); | 
 |  444     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements()); | 
 |  445     HeapNumber* number = HeapNumber::cast(*value); | 
 |  446     double_array->set(store_index, number->Number()); | 
 |  447   } else { | 
 |  448     if (!IsFastObjectElementsKind(elements_kind)) { | 
 |  449       ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind) | 
 |  450                                            ? FAST_HOLEY_ELEMENTS | 
 |  451                                            : FAST_ELEMENTS; | 
 |  452       JSObject::TransitionElementsKind(object, transitioned_kind); | 
 |  453       ElementsKind boilerplate_elements_kind = | 
 |  454           boilerplate_object->GetElementsKind(); | 
 |  455       if (IsMoreGeneralElementsKindTransition(boilerplate_elements_kind, | 
 |  456                                               transitioned_kind)) { | 
 |  457         JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind); | 
 |  458       } | 
 |  459     } | 
 |  460     FixedArray* object_array = FixedArray::cast(object->elements()); | 
 |  461     object_array->set(store_index, *value); | 
 |  462   } | 
 |  463   return *object; | 
 |  464 } | 
 |  465 } | 
 |  466 }  // namespace v8::internal | 
| OLD | NEW |