LCOV - code coverage report
Current view: top level - src/runtime - runtime-literals.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 201 211 95.3 %
Date: 2019-02-19 Functions: 25 30 83.3 %

          Line data    Source code
       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/allocation-site-scopes-inl.h"
       6             : #include "src/arguments-inl.h"
       7             : #include "src/ast/ast.h"
       8             : #include "src/counters.h"
       9             : #include "src/isolate-inl.h"
      10             : #include "src/objects/hash-table-inl.h"
      11             : #include "src/objects/heap-number-inl.h"
      12             : #include "src/objects/heap-object-inl.h"
      13             : #include "src/objects/js-regexp-inl.h"
      14             : #include "src/objects/literal-objects-inl.h"
      15             : #include "src/runtime/runtime-utils.h"
      16             : #include "src/runtime/runtime.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : namespace {
      22             : 
      23       78925 : bool IsUninitializedLiteralSite(Object literal_site) {
      24       78925 :   return literal_site == Smi::kZero;
      25             : }
      26             : 
      27      870960 : bool HasBoilerplate(Handle<Object> literal_site) {
      28     1741922 :   return !literal_site->IsSmi();
      29             : }
      30             : 
      31      143477 : void PreInitializeLiteralSite(Handle<FeedbackVector> vector,
      32             :                               FeedbackSlot slot) {
      33      286957 :   vector->Set(slot, Smi::FromInt(1));
      34      143479 : }
      35             : 
      36             : Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
      37             :                                       Handle<Object> description,
      38             :                                       PretenureFlag pretenure_flag);
      39             : 
      40             : enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };
      41             : 
      42             : template <class ContextObject>
      43             : class JSObjectWalkVisitor {
      44             :  public:
      45             :   JSObjectWalkVisitor(ContextObject* site_context, DeepCopyHints hints)
      46      826943 :       : site_context_(site_context), hints_(hints) {}
      47             : 
      48             :   V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> StructureWalk(
      49             :       Handle<JSObject> object);
      50             : 
      51             :  protected:
      52      963268 :   V8_WARN_UNUSED_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
      53      630801 :       Handle<JSObject> object, Handle<JSObject> value) {
      54             :     // Dont create allocation sites for nested object literals
      55     1926536 :     if (!value->IsJSArray()) {
      56      306254 :       return StructureWalk(value);
      57             :     }
      58             : 
      59      630801 :     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
      60      657014 :     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
      61       15680 :     site_context()->ExitScope(current_site, value);
      62      657014 :     return copy_of_value;
      63             :   }
      64             : 
      65             :   inline ContextObject* site_context() { return site_context_; }
      66     1790207 :   inline Isolate* isolate() { return site_context()->isolate(); }
      67             : 
      68             :  private:
      69             :   ContextObject* site_context_;
      70             :   const DeepCopyHints hints_;
      71             : };
      72             : 
      73             : template <class ContextObject>
      74     1790207 : MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
      75     3064934 :     Handle<JSObject> object) {
      76             :   Isolate* isolate = this->isolate();
      77             :   bool copying = ContextObject::kCopying;
      78     1790207 :   bool shallow = hints_ == kObjectIsShallow;
      79             : 
      80     1790207 :   if (!shallow) {
      81             :     StackLimitCheck check(isolate);
      82             : 
      83     1691697 :     if (check.HasOverflowed()) {
      84          51 :       isolate->StackOverflow();
      85          51 :       return MaybeHandle<JSObject>();
      86             :     }
      87             :   }
      88             : 
      89     1790154 :   if (object->map()->is_deprecated()) {
      90         800 :     JSObject::MigrateInstance(object);
      91             :   }
      92             : 
      93             :   Handle<JSObject> copy;
      94             :   if (copying) {
      95             :     // JSFunction objects are not allowed to be in normal boilerplates at all.
      96             :     DCHECK(!object->IsJSFunction());
      97             :     Handle<AllocationSite> site_to_pass;
      98     1594310 :     if (site_context()->ShouldCreateMemento(object)) {
      99     1470624 :       site_to_pass = site_context()->current();
     100             :     }
     101     1594312 :     copy = isolate->factory()->CopyJSObjectWithAllocationSite(object,
     102             :                                                               site_to_pass);
     103             :   } else {
     104             :     copy = object;
     105             :   }
     106             : 
     107             :   DCHECK(copying || copy.is_identical_to(object));
     108             : 
     109     1790160 :   if (shallow) return copy;
     110             : 
     111             :   HandleScope scope(isolate);
     112             : 
     113             :   // Deep copy own properties. Arrays only have 1 property "length".
     114     3383296 :   if (!copy->IsJSArray()) {
     115      637296 :     if (copy->HasFastProperties()) {
     116             :       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors(),
     117     1274185 :                                           isolate);
     118             :       int limit = copy->map()->NumberOfOwnDescriptors();
     119     1359778 :       for (int i = 0; i < limit; i++) {
     120             :         DCHECK_EQ(kField, descriptors->GetDetails(i).location());
     121             :         DCHECK_EQ(kData, descriptors->GetDetails(i).kind());
     122      722693 :         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
     123      727674 :         if (copy->IsUnboxedDoubleField(index)) continue;
     124      717717 :         Object raw = copy->RawFastPropertyAt(index);
     125      717716 :         if (raw->IsJSObject()) {
     126             :           Handle<JSObject> value(JSObject::cast(raw), isolate);
     127      694430 :           ASSIGN_RETURN_ON_EXCEPTION(
     128             :               isolate, value, VisitElementOrProperty(copy, value), JSObject);
     129      626282 :           if (copying) copy->FastPropertyAtPut(index, *value);
     130      132780 :         } else if (copying && raw->IsMutableHeapNumber()) {
     131             :           DCHECK(descriptors->GetDetails(i).representation().IsDouble());
     132             :           uint64_t double_value = MutableHeapNumber::cast(raw)->value_as_bits();
     133             :           auto value =
     134           0 :               isolate->factory()->NewMutableHeapNumberFromBits(double_value);
     135           0 :           copy->FastPropertyAtPut(index, *value);
     136             :         }
     137             :       }
     138             :     } else {
     139         404 :       Handle<NameDictionary> dict(copy->property_dictionary(), isolate);
     140     1476436 :       for (int i = 0; i < dict->Capacity(); i++) {
     141      738016 :         Object raw = dict->ValueAt(i);
     142     1476032 :         if (!raw->IsJSObject()) continue;
     143             :         DCHECK(dict->KeyAt(i)->IsName());
     144             :         Handle<JSObject> value(JSObject::cast(raw), isolate);
     145           0 :         ASSIGN_RETURN_ON_EXCEPTION(
     146             :             isolate, value, VisitElementOrProperty(copy, value), JSObject);
     147           0 :         if (copying) dict->ValueAtPut(i, *value);
     148             :       }
     149             :     }
     150             : 
     151             :     // Assume non-arrays don't end up having elements.
     152     1274575 :     if (copy->elements()->length() == 0) return copy;
     153             :   }
     154             : 
     155             :   // Deep copy own elements.
     156     1055728 :   switch (copy->GetElementsKind()) {
     157             :     case PACKED_ELEMENTS:
     158             :     case HOLEY_ELEMENTS: {
     159      937638 :       Handle<FixedArray> elements(FixedArray::cast(copy->elements()), isolate);
     160      468819 :       if (elements->map() == ReadOnlyRoots(isolate).fixed_cow_array_map()) {
     161             : #ifdef DEBUG
     162             :         for (int i = 0; i < elements->length(); i++) {
     163             :           DCHECK(!elements->get(i)->IsJSObject());
     164             :         }
     165             : #endif
     166             :       } else {
     167     6801624 :         for (int i = 0; i < elements->length(); i++) {
     168     3178047 :           Object raw = elements->get(i);
     169     5740491 :           if (!raw->IsJSObject()) continue;
     170             :           Handle<JSObject> value(JSObject::cast(raw), isolate);
     171     1231206 :           ASSIGN_RETURN_ON_EXCEPTION(
     172             :               isolate, value, VisitElementOrProperty(copy, value), JSObject);
     173     1149038 :           if (copying) elements->set(i, *value);
     174             :         }
     175             :       }
     176             :       break;
     177             :     }
     178             :     case DICTIONARY_ELEMENTS: {
     179             :       Handle<NumberDictionary> element_dictionary(copy->element_dictionary(),
     180         758 :                                                   isolate);
     181         379 :       int capacity = element_dictionary->Capacity();
     182        6815 :       for (int i = 0; i < capacity; i++) {
     183        6436 :         Object raw = element_dictionary->ValueAt(i);
     184       12422 :         if (!raw->IsJSObject()) continue;
     185             :         Handle<JSObject> value(JSObject::cast(raw), isolate);
     186         900 :         ASSIGN_RETURN_ON_EXCEPTION(
     187             :             isolate, value, VisitElementOrProperty(copy, value), JSObject);
     188         558 :         if (copying) element_dictionary->ValueAtPut(i, *value);
     189             :       }
     190             :       break;
     191             :     }
     192             :     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
     193             :     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
     194           0 :       UNIMPLEMENTED();
     195             :       break;
     196             :     case FAST_STRING_WRAPPER_ELEMENTS:
     197             :     case SLOW_STRING_WRAPPER_ELEMENTS:
     198           0 :       UNREACHABLE();
     199             :       break;
     200             : 
     201             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
     202             : 
     203             :       TYPED_ARRAYS(TYPED_ARRAY_CASE)
     204             : #undef TYPED_ARRAY_CASE
     205             :       // Typed elements cannot be created using an object literal.
     206           0 :       UNREACHABLE();
     207             :       break;
     208             : 
     209             :     case PACKED_SMI_ELEMENTS:
     210             :     case HOLEY_SMI_ELEMENTS:
     211             :     case PACKED_DOUBLE_ELEMENTS:
     212             :     case HOLEY_DOUBLE_ELEMENTS:
     213             :     case NO_ELEMENTS:
     214             :       // No contained objects, nothing to do.
     215             :       break;
     216             :   }
     217             : 
     218     1055712 :   return copy;
     219             : }
     220             : 
     221             : class DeprecationUpdateContext {
     222             :  public:
     223       27866 :   explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
     224       83722 :   Isolate* isolate() { return isolate_; }
     225             :   bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
     226             :   inline void ExitScope(Handle<AllocationSite> scope_site,
     227             :                         Handle<JSObject> object) {}
     228             :   Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
     229             :   Handle<AllocationSite> current() {
     230             :     UNREACHABLE();
     231             :     return Handle<AllocationSite>();
     232             :   }
     233             : 
     234             :   static const bool kCopying = false;
     235             : 
     236             :  private:
     237             :   Isolate* isolate_;
     238             : };
     239             : 
     240             : // AllocationSiteCreationContext aids in the creation of AllocationSites to
     241             : // accompany object literals.
     242             : class AllocationSiteCreationContext : public AllocationSiteContext {
     243             :  public:
     244             :   explicit AllocationSiteCreationContext(Isolate* isolate)
     245             :       : AllocationSiteContext(isolate) {}
     246             : 
     247      108392 :   Handle<AllocationSite> EnterNewScope() {
     248             :     Handle<AllocationSite> scope_site;
     249      216784 :     if (top().is_null()) {
     250             :       // We are creating the top level AllocationSite as opposed to a nested
     251             :       // AllocationSite.
     252       92712 :       InitializeTraversal(isolate()->factory()->NewAllocationSite(true));
     253             :       scope_site = Handle<AllocationSite>(*top(), isolate());
     254             :       if (FLAG_trace_creation_allocation_sites) {
     255             :         PrintF("*** Creating top level %s AllocationSite %p\n", "Fat",
     256             :                reinterpret_cast<void*>(scope_site->ptr()));
     257             :       }
     258             :     } else {
     259             :       DCHECK(!current().is_null());
     260       15680 :       scope_site = isolate()->factory()->NewAllocationSite(false);
     261             :       if (FLAG_trace_creation_allocation_sites) {
     262             :         PrintF(
     263             :             "*** Creating nested %s AllocationSite (top, current, new) (%p, "
     264             :             "%p, "
     265             :             "%p)\n",
     266             :             "Slim", reinterpret_cast<void*>(top()->ptr()),
     267             :             reinterpret_cast<void*>(current()->ptr()),
     268             :             reinterpret_cast<void*>(scope_site->ptr()));
     269             :       }
     270       31360 :       current()->set_nested_site(*scope_site);
     271             :       update_current_site(*scope_site);
     272             :     }
     273             :     DCHECK(!scope_site.is_null());
     274      108393 :     return scope_site;
     275             :   }
     276      108353 :   void ExitScope(Handle<AllocationSite> scope_site, Handle<JSObject> object) {
     277      216706 :     if (object.is_null()) return;
     278      216713 :     scope_site->set_boilerplate(*object);
     279             :     if (FLAG_trace_creation_allocation_sites) {
     280             :       bool top_level =
     281             :           !scope_site.is_null() && top().is_identical_to(scope_site);
     282             :       if (top_level) {
     283             :         PrintF("*** Setting AllocationSite %p transition_info %p\n",
     284             :                reinterpret_cast<void*>(scope_site->ptr()),
     285             :                reinterpret_cast<void*>(object->ptr()));
     286             :       } else {
     287             :         PrintF("*** Setting AllocationSite (%p, %p) transition_info %p\n",
     288             :                reinterpret_cast<void*>(top()->ptr()),
     289             :                reinterpret_cast<void*>(scope_site->ptr()),
     290             :                reinterpret_cast<void*>(object->ptr()));
     291             :       }
     292             :     }
     293             :   }
     294             :   static const bool kCopying = false;
     295             : };
     296             : 
     297             : MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
     298             :                                DeprecationUpdateContext* site_context) {
     299             :   JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
     300       27866 :   MaybeHandle<JSObject> result = v.StructureWalk(object);
     301             :   Handle<JSObject> for_assert;
     302             :   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
     303       27866 :   return result;
     304             : }
     305             : 
     306             : MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
     307             :                                AllocationSiteCreationContext* site_context) {
     308             :   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
     309       92713 :   MaybeHandle<JSObject> result = v.StructureWalk(object);
     310             :   Handle<JSObject> for_assert;
     311             :   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
     312       92710 :   return result;
     313             : }
     314             : 
     315             : MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
     316             :                                AllocationSiteUsageContext* site_context,
     317             :                                DeepCopyHints hints) {
     318             :   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, hints);
     319      706364 :   MaybeHandle<JSObject> copy = v.StructureWalk(object);
     320             :   Handle<JSObject> for_assert;
     321             :   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
     322      706365 :   return copy;
     323             : }
     324             : 
     325             : struct ObjectLiteralHelper {
     326      358044 :   static Handle<JSObject> Create(Isolate* isolate,
     327             :                                  Handle<HeapObject> description, int flags,
     328             :                                  PretenureFlag pretenure_flag) {
     329      358044 :     Handle<NativeContext> native_context = isolate->native_context();
     330             :     Handle<ObjectBoilerplateDescription> object_boilerplate_description =
     331      358047 :         Handle<ObjectBoilerplateDescription>::cast(description);
     332      358049 :     bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
     333      358049 :     bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
     334             : 
     335             :     // In case we have function literals, we want the object to be in
     336             :     // slow properties mode for now. We don't go in the map cache because
     337             :     // maps with constant functions can't be shared if the functions are
     338             :     // not the same (which is the common case).
     339             :     int number_of_properties =
     340      358049 :         object_boilerplate_description->backing_store_size();
     341             : 
     342             :     // Ignoring number_of_properties for force dictionary map with
     343             :     // __proto__:null.
     344             :     Handle<Map> map =
     345             :         has_null_prototype
     346      364243 :             ? handle(native_context->slow_object_with_null_prototype_map(),
     347        3096 :                      isolate)
     348             :             : isolate->factory()->ObjectLiteralMapFromCache(
     349     1067955 :                   native_context, number_of_properties);
     350             : 
     351             :     Handle<JSObject> boilerplate =
     352      716102 :         map->is_dictionary_map()
     353             :             ? isolate->factory()->NewSlowJSObjectFromMap(
     354             :                   map, number_of_properties, pretenure_flag)
     355      358052 :             : isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
     356             : 
     357             :     // Normalize the elements of the boilerplate to save space if needed.
     358      358051 :     if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
     359             : 
     360             :     // Add the constant properties to the boilerplate.
     361      358052 :     int length = object_boilerplate_description->size();
     362             :     // TODO(verwaest): Support tracking representations in the boilerplate.
     363     4996851 :     for (int index = 0; index < length; index++) {
     364     9277607 :       Handle<Object> key(object_boilerplate_description->name(index), isolate);
     365             :       Handle<Object> value(object_boilerplate_description->value(index),
     366     9277605 :                            isolate);
     367             : 
     368    18547794 :       if (value->IsObjectBoilerplateDescription() ||
     369     9270184 :           value->IsArrayBoilerplateDescription()) {
     370       34401 :         value = InnerCreateBoilerplate(isolate, value, pretenure_flag);
     371             :       }
     372     4638808 :       uint32_t element_index = 0;
     373     9277609 :       if (key->ToArrayIndex(&element_index)) {
     374             :         // Array index (uint32).
     375     4639930 :         if (value->IsUninitialized(isolate)) {
     376             :           value = handle(Smi::kZero, isolate);
     377             :         }
     378             :         JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index,
     379     2319965 :                                                 value, NONE)
     380     4639930 :             .Check();
     381             :       } else {
     382     2318840 :         Handle<String> name = Handle<String>::cast(key);
     383             :         DCHECK(!name->AsArrayIndex(&element_index));
     384     2318835 :         JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
     385     4637675 :             .Check();
     386             :       }
     387             :     }
     388             : 
     389      358048 :     if (map->is_dictionary_map() && !has_null_prototype) {
     390             :       // TODO(cbruni): avoid making the boilerplate fast again, the clone stub
     391             :       // supports dict-mode objects directly.
     392             :       JSObject::MigrateSlowToFast(boilerplate,
     393             :                                   boilerplate->map()->UnusedPropertyFields(),
     394         191 :                                   "FastLiteral");
     395             :     }
     396      358047 :     return boilerplate;
     397             :   }
     398             : };
     399             : 
     400             : struct ArrayLiteralHelper {
     401      415111 :   static Handle<JSObject> Create(Isolate* isolate,
     402             :                                  Handle<HeapObject> description, int flags,
     403             :                                  PretenureFlag pretenure_flag) {
     404             :     Handle<ArrayBoilerplateDescription> array_boilerplate_description =
     405      415111 :         Handle<ArrayBoilerplateDescription>::cast(description);
     406             : 
     407             :     ElementsKind constant_elements_kind =
     408             :         array_boilerplate_description->elements_kind();
     409             : 
     410             :     Handle<FixedArrayBase> constant_elements_values(
     411      830225 :         array_boilerplate_description->constant_elements(), isolate);
     412             : 
     413             :     // Create the JSArray.
     414             :     Handle<FixedArrayBase> copied_elements_values;
     415      415112 :     if (IsDoubleElementsKind(constant_elements_kind)) {
     416             :       copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
     417       13956 :           Handle<FixedDoubleArray>::cast(constant_elements_values));
     418             :     } else {
     419             :       DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
     420             :       const bool is_cow = (constant_elements_values->map() ==
     421             :                            ReadOnlyRoots(isolate).fixed_cow_array_map());
     422      401156 :       if (is_cow) {
     423             :         copied_elements_values = constant_elements_values;
     424             : #if DEBUG
     425             :         Handle<FixedArray> fixed_array_values =
     426             :             Handle<FixedArray>::cast(copied_elements_values);
     427             :         for (int i = 0; i < fixed_array_values->length(); i++) {
     428             :           DCHECK(!fixed_array_values->get(i)->IsFixedArray());
     429             :         }
     430             : #endif
     431             :       } else {
     432             :         Handle<FixedArray> fixed_array_values =
     433      266789 :             Handle<FixedArray>::cast(constant_elements_values);
     434             :         Handle<FixedArray> fixed_array_values_copy =
     435      266789 :             isolate->factory()->CopyFixedArray(fixed_array_values);
     436             :         copied_elements_values = fixed_array_values_copy;
     437     9477337 :         FOR_WITH_HANDLE_SCOPE(
     438             :             isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
     439             :               Handle<Object> value(fixed_array_values->get(i), isolate);
     440             : 
     441             :               if (value->IsArrayBoilerplateDescription() ||
     442             :                   value->IsObjectBoilerplateDescription()) {
     443             :                 Handle<Object> result =
     444             :                     InnerCreateBoilerplate(isolate, value, pretenure_flag);
     445             :                 fixed_array_values_copy->set(i, *result);
     446             :               }
     447             :             });
     448             :       }
     449             :     }
     450             : 
     451             :     return isolate->factory()->NewJSArrayWithElements(
     452             :         copied_elements_values, constant_elements_kind,
     453      415114 :         copied_elements_values->length(), pretenure_flag);
     454             :   }
     455             : };
     456             : 
     457       75314 : Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
     458             :                                       Handle<Object> description,
     459             :                                       PretenureFlag pretenure_flag) {
     460      150628 :   if (description->IsObjectBoilerplateDescription()) {
     461             :     Handle<ObjectBoilerplateDescription> object_boilerplate_description =
     462       33412 :         Handle<ObjectBoilerplateDescription>::cast(description);
     463             :     return ObjectLiteralHelper::Create(isolate, object_boilerplate_description,
     464             :                                        object_boilerplate_description->flags(),
     465       33412 :                                        pretenure_flag);
     466             :   } else {
     467             :     DCHECK(description->IsArrayBoilerplateDescription());
     468             :     Handle<ArrayBoilerplateDescription> array_boilerplate_description =
     469       41902 :         Handle<ArrayBoilerplateDescription>::cast(description);
     470             :     return ArrayLiteralHelper::Create(
     471             :         isolate, array_boilerplate_description,
     472       41902 :         array_boilerplate_description->elements_kind(), pretenure_flag);
     473             :   }
     474             : }
     475             : 
     476             : inline DeepCopyHints DecodeCopyHints(int flags) {
     477             :   DeepCopyHints copy_hints =
     478     1394626 :       (flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
     479             :   if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
     480             :     // Make sure we properly clone mutable heap numbers on 32-bit platforms.
     481             :     copy_hints = kNoHints;
     482             :   }
     483             :   return copy_hints;
     484             : }
     485             : 
     486             : template <typename LiteralHelper>
     487      605133 : MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
     488             :     Isolate* isolate, Handle<HeapObject> description, int flags) {
     489             :   Handle<JSObject> literal =
     490      605133 :       LiteralHelper::Create(isolate, description, flags, NOT_TENURED);
     491             :   DeepCopyHints copy_hints = DecodeCopyHints(flags);
     492      605133 :   if (copy_hints == kNoHints) {
     493             :     DeprecationUpdateContext update_context(isolate);
     494       27866 :     RETURN_ON_EXCEPTION(isolate, DeepWalk(literal, &update_context), JSObject);
     495             :   }
     496      605133 :   return literal;
     497             : }
     498             : 
     499             : template <typename LiteralHelper>
     500      789492 : MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
     501             :                                     MaybeHandle<FeedbackVector> maybe_vector,
     502             :                                     int literals_index,
     503             :                                     Handle<HeapObject> description, int flags) {
     504      789492 :   if (maybe_vector.is_null()) {
     505             :     return CreateLiteralWithoutAllocationSite<LiteralHelper>(
     506           0 :         isolate, description, flags);
     507             :   }
     508             : 
     509             :   Handle<FeedbackVector> vector = maybe_vector.ToHandleChecked();
     510             :   FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
     511      789493 :   CHECK(literals_slot.ToInt() < vector->length());
     512     1578987 :   Handle<Object> literal_site(vector->Get(literals_slot)->cast<Object>(),
     513             :                               isolate);
     514             :   DeepCopyHints copy_hints = DecodeCopyHints(flags);
     515             : 
     516             :   Handle<AllocationSite> site;
     517             :   Handle<JSObject> boilerplate;
     518             : 
     519      789493 :   if (HasBoilerplate(literal_site)) {
     520      613687 :     site = Handle<AllocationSite>::cast(literal_site);
     521     1227374 :     boilerplate = Handle<JSObject>(site->boilerplate(), isolate);
     522             :   } else {
     523             :     // Eagerly create AllocationSites for literals that contain an Array.
     524             :     bool needs_initial_allocation_site =
     525      175807 :         (flags & AggregateLiteral::kNeedsInitialAllocationSite) != 0;
     526      298204 :     if (!needs_initial_allocation_site &&
     527             :         IsUninitializedLiteralSite(*literal_site)) {
     528       83095 :       PreInitializeLiteralSite(vector, literals_slot);
     529             :       return CreateLiteralWithoutAllocationSite<LiteralHelper>(
     530      166220 :           isolate, description, flags);
     531             :     } else {
     532       92712 :       boilerplate = LiteralHelper::Create(isolate, description, flags, TENURED);
     533             :     }
     534             :     // Install AllocationSite objects.
     535             :     AllocationSiteCreationContext creation_context(isolate);
     536       92712 :     site = creation_context.EnterNewScope();
     537       92710 :     RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &creation_context),
     538             :                         JSObject);
     539       92675 :     creation_context.ExitScope(site, boilerplate);
     540             : 
     541      185358 :     vector->Set(literals_slot, *site);
     542             :   }
     543             : 
     544             :   STATIC_ASSERT(static_cast<int>(ObjectLiteral::kDisableMementos) ==
     545             :                 static_cast<int>(ArrayLiteral::kDisableMementos));
     546      706366 :   bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
     547             : 
     548             :   // Copy the existing boilerplate.
     549             :   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
     550      706366 :   usage_context.EnterNewScope();
     551             :   MaybeHandle<JSObject> copy =
     552             :       DeepCopy(boilerplate, &usage_context, copy_hints);
     553             :   usage_context.ExitScope(site, boilerplate);
     554      706365 :   return copy;
     555             : }
     556             : }  // namespace
     557             : 
     558      397341 : RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
     559      397341 :   HandleScope scope(isolate);
     560             :   DCHECK_EQ(4, args.length());
     561      794692 :   CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
     562      794694 :   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
     563      794697 :   CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
     564      794695 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     565             :   Handle<FeedbackVector> vector = Handle<FeedbackVector>();
     566      794693 :   if (!maybe_vector->IsUndefined()) {
     567             :     DCHECK(maybe_vector->IsFeedbackVector());
     568      397345 :     vector = Handle<FeedbackVector>::cast(maybe_vector);
     569             :   }
     570      794686 :   RETURN_RESULT_OR_FAILURE(
     571             :       isolate, CreateLiteral<ObjectLiteralHelper>(
     572      397339 :                    isolate, vector, literals_index, description, flags));
     573             : }
     574             : 
     575      196175 : RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite) {
     576      196175 :   HandleScope scope(isolate);
     577             :   DCHECK_EQ(2, args.length());
     578      392350 :   CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 0);
     579      392350 :   CONVERT_SMI_ARG_CHECKED(flags, 1);
     580      392350 :   RETURN_RESULT_OR_FAILURE(
     581             :       isolate, CreateLiteralWithoutAllocationSite<ObjectLiteralHelper>(
     582      196175 :                    isolate, description, flags));
     583             : }
     584             : 
     585      325866 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteralWithoutAllocationSite) {
     586      325866 :   HandleScope scope(isolate);
     587             :   DCHECK_EQ(2, args.length());
     588      651732 :   CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, description, 0);
     589      651732 :   CONVERT_SMI_ARG_CHECKED(flags, 1);
     590      651732 :   RETURN_RESULT_OR_FAILURE(
     591             :       isolate, CreateLiteralWithoutAllocationSite<ArrayLiteralHelper>(
     592      325866 :                    isolate, description, flags));
     593             : }
     594             : 
     595      392148 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
     596      392148 :   HandleScope scope(isolate);
     597             :   DCHECK_EQ(4, args.length());
     598      784298 :   CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
     599      784297 :   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
     600      784298 :   CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
     601      784298 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     602             :   Handle<FeedbackVector> vector = Handle<FeedbackVector>();
     603      784301 :   if (!maybe_vector->IsUndefined()) {
     604             :     DCHECK(maybe_vector->IsFeedbackVector());
     605      392148 :     vector = Handle<FeedbackVector>::cast(maybe_vector);
     606             :   }
     607      784301 :   RETURN_RESULT_OR_FAILURE(
     608             :       isolate, CreateLiteral<ArrayLiteralHelper>(
     609      392151 :                    isolate, vector, literals_index, elements, flags));
     610             : }
     611             : 
     612       81465 : RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
     613       81465 :   HandleScope scope(isolate);
     614             :   DCHECK_EQ(4, args.length());
     615      162930 :   CONVERT_ARG_HANDLE_CHECKED(HeapObject, maybe_vector, 0);
     616      162930 :   CONVERT_SMI_ARG_CHECKED(index, 1);
     617      162930 :   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
     618      162930 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     619       81465 :   FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
     620             :   Handle<FeedbackVector> vector = Handle<FeedbackVector>();
     621      162930 :   if (!maybe_vector->IsUndefined()) {
     622             :     DCHECK(maybe_vector->IsFeedbackVector());
     623       81465 :     vector = Handle<FeedbackVector>::cast(maybe_vector);
     624             :   }
     625             :   Handle<Object> boilerplate;
     626       81465 :   if (vector.is_null()) {
     627           0 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     628             :         isolate, boilerplate,
     629             :         JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
     630           0 :     return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
     631             :   }
     632             : 
     633             :   // Check if boilerplate exists. If not, create it first.
     634      162930 :   Handle<Object> literal_site(vector->Get(literal_slot)->cast<Object>(),
     635      162930 :                               isolate);
     636       81465 :   if (!HasBoilerplate(literal_site)) {
     637      162930 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     638             :         isolate, boilerplate,
     639             :         JSRegExp::New(isolate, pattern, JSRegExp::Flags(flags)));
     640       78925 :     if (IsUninitializedLiteralSite(*literal_site)) {
     641       60385 :       PreInitializeLiteralSite(vector, literal_slot);
     642             :       return *boilerplate;
     643             :     }
     644       18540 :     vector->Set(literal_slot, *boilerplate);
     645             :   }
     646       37080 :   return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
     647             : }
     648             : 
     649             : }  // namespace internal
     650      178779 : }  // namespace v8

Generated by: LCOV version 1.10