LCOV - code coverage report
Current view: top level - src/runtime - runtime-literals.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 116 126 92.1 %
Date: 2017-04-26 Functions: 9 14 64.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/runtime/runtime-utils.h"
       6             : 
       7             : #include "src/allocation-site-scopes.h"
       8             : #include "src/arguments.h"
       9             : #include "src/ast/ast.h"
      10             : #include "src/ast/compile-time-value.h"
      11             : #include "src/isolate-inl.h"
      12             : #include "src/runtime/runtime.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17      831886 : static Handle<Map> ComputeObjectLiteralMap(
      18             :     Handle<Context> context,
      19             :     Handle<BoilerplateDescription> boilerplate_description,
      20             :     bool* is_result_from_cache) {
      21      831886 :   int number_of_properties = boilerplate_description->backing_store_size();
      22             :   Isolate* isolate = context->GetIsolate();
      23             :   return isolate->factory()->ObjectLiteralMapFromCache(
      24      831886 :       context, number_of_properties, is_result_from_cache);
      25             : }
      26             : 
      27             : MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
      28             :     Isolate* isolate, Handle<FeedbackVector> vector,
      29             :     Handle<BoilerplateDescription> boilerplate_description);
      30             : 
      31      831886 : MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
      32             :     Isolate* isolate, Handle<FeedbackVector> vector,
      33             :     Handle<BoilerplateDescription> boilerplate_description,
      34             :     bool should_have_fast_elements) {
      35      831886 :   Handle<Context> context = isolate->native_context();
      36             : 
      37             :   // In case we have function literals, we want the object to be in
      38             :   // slow properties mode for now. We don't go in the map cache because
      39             :   // maps with constant functions can't be shared if the functions are
      40             :   // not the same (which is the common case).
      41      831886 :   bool is_result_from_cache = false;
      42             :   Handle<Map> map = ComputeObjectLiteralMap(context, boilerplate_description,
      43      831886 :                                             &is_result_from_cache);
      44             : 
      45             :   PretenureFlag pretenure_flag =
      46      831886 :       isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
      47             : 
      48             :   Handle<JSObject> boilerplate =
      49      831886 :       isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
      50             : 
      51             :   // Normalize the elements of the boilerplate to save space if needed.
      52      831886 :   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
      53             : 
      54             :   // Add the constant properties to the boilerplate.
      55      831886 :   int length = boilerplate_description->size();
      56             :   bool should_transform =
      57      940248 :       !is_result_from_cache && boilerplate->HasFastProperties();
      58             :   bool should_normalize = should_transform;
      59      831886 :   if (should_normalize) {
      60             :     // TODO(verwaest): We might not want to ever normalize here.
      61             :     JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length,
      62      108362 :                                   "Boilerplate");
      63             :   }
      64             :   // TODO(verwaest): Support tracking representations in the boilerplate.
      65     2817143 :   for (int index = 0; index < length; index++) {
      66     2817142 :     Handle<Object> key(boilerplate_description->name(index), isolate);
      67     2817142 :     Handle<Object> value(boilerplate_description->value(index), isolate);
      68     2817142 :     if (value->IsBoilerplateDescription()) {
      69             :       // The value contains the boilerplate properties of a
      70             :       // simple object or array literal.
      71             :       Handle<BoilerplateDescription> boilerplate =
      72      203130 :           Handle<BoilerplateDescription>::cast(value);
      73      406260 :       ASSIGN_RETURN_ON_EXCEPTION(
      74             :           isolate, value,
      75             :           CreateLiteralBoilerplate(isolate, vector, boilerplate), Object);
      76             :     }
      77             :     MaybeHandle<Object> maybe_result;
      78     2817142 :     uint32_t element_index = 0;
      79     2817143 :     if (key->ToArrayIndex(&element_index)) {
      80             :       // Array index (uint32).
      81       30712 :       if (value->IsUninitialized(isolate)) {
      82             :         value = handle(Smi::kZero, isolate);
      83             :       }
      84             :       maybe_result = JSObject::SetOwnElementIgnoreAttributes(
      85       30712 :           boilerplate, element_index, value, NONE);
      86             :     } else {
      87             :       Handle<String> name = Handle<String>::cast(key);
      88             :       DCHECK(!name->AsArrayIndex(&element_index));
      89             :       maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name,
      90     2786431 :                                                               value, NONE);
      91             :     }
      92     2817143 :     RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
      93             :   }
      94             : 
      95             :   // Transform to fast properties if necessary. For object literals with
      96             :   // containing function literals we defer this operation until after all
      97             :   // computed properties have been assigned so that we can generate
      98             :   // constant function properties.
      99      831886 :   if (should_transform) {
     100             :     JSObject::MigrateSlowToFast(boilerplate,
     101             :                                 boilerplate->map()->unused_property_fields(),
     102      108362 :                                 "FastLiteral");
     103             :   }
     104             :   return boilerplate;
     105             : }
     106             : 
     107      394018 : static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
     108      394018 :     Isolate* isolate, Handle<FeedbackVector> vector,
     109             :     Handle<ConstantElementsPair> elements) {
     110             :   // Create the JSArray.
     111      394018 :   Handle<JSFunction> constructor = isolate->array_function();
     112             : 
     113             :   PretenureFlag pretenure_flag =
     114      394018 :       isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
     115             : 
     116             :   Handle<JSArray> object = Handle<JSArray>::cast(
     117      394018 :       isolate->factory()->NewJSObject(constructor, pretenure_flag));
     118             : 
     119             :   ElementsKind constant_elements_kind =
     120      394018 :       static_cast<ElementsKind>(elements->elements_kind());
     121             :   Handle<FixedArrayBase> constant_elements_values(elements->constant_values());
     122             : 
     123             :   {
     124             :     DisallowHeapAllocation no_gc;
     125             :     DCHECK(IsFastElementsKind(constant_elements_kind));
     126             :     Context* native_context = isolate->context()->native_context();
     127             :     Object* map =
     128             :         native_context->get(Context::ArrayMapIndex(constant_elements_kind));
     129      394018 :     object->set_map(Map::cast(map));
     130             :   }
     131             : 
     132             :   Handle<FixedArrayBase> copied_elements_values;
     133      394018 :   if (IsFastDoubleElementsKind(constant_elements_kind)) {
     134             :     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
     135        4798 :         Handle<FixedDoubleArray>::cast(constant_elements_values));
     136             :   } else {
     137             :     DCHECK(IsFastSmiOrObjectElementsKind(constant_elements_kind));
     138             :     const bool is_cow = (constant_elements_values->map() ==
     139      389220 :                          isolate->heap()->fixed_cow_array_map());
     140      389220 :     if (is_cow) {
     141             :       copied_elements_values = constant_elements_values;
     142             : #if DEBUG
     143             :       Handle<FixedArray> fixed_array_values =
     144             :           Handle<FixedArray>::cast(copied_elements_values);
     145             :       for (int i = 0; i < fixed_array_values->length(); i++) {
     146             :         DCHECK(!fixed_array_values->get(i)->IsFixedArray());
     147             :       }
     148             : #endif
     149             :     } else {
     150             :       Handle<FixedArray> fixed_array_values =
     151             :           Handle<FixedArray>::cast(constant_elements_values);
     152             :       Handle<FixedArray> fixed_array_values_copy =
     153      277872 :           isolate->factory()->CopyFixedArray(fixed_array_values);
     154             :       copied_elements_values = fixed_array_values_copy;
     155     6835621 :       FOR_WITH_HANDLE_SCOPE(
     156             :           isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
     157             :             if (fixed_array_values->get(i)->IsBoilerplateDescription()) {
     158             :               // The value contains the boilerplate properties of a
     159             :               // simple object or array literal.
     160             :               Handle<BoilerplateDescription> boilerplate(
     161             :                   BoilerplateDescription::cast(fixed_array_values->get(i)));
     162             :               Handle<Object> result;
     163             :               ASSIGN_RETURN_ON_EXCEPTION(
     164             :                   isolate, result,
     165             :                   CreateLiteralBoilerplate(isolate, vector, boilerplate),
     166             :                   Object);
     167             :               fixed_array_values_copy->set(i, *result);
     168             :             }
     169             :           });
     170             :     }
     171             :   }
     172      394018 :   object->set_elements(*copied_elements_values);
     173             :   object->set_length(Smi::FromInt(copied_elements_values->length()));
     174             : 
     175      394018 :   JSObject::ValidateElements(object);
     176             :   return object;
     177             : }
     178             : 
     179      305069 : MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
     180             :     Isolate* isolate, Handle<FeedbackVector> vector,
     181             :     Handle<BoilerplateDescription> array) {
     182      305069 :   Handle<HeapObject> elements = CompileTimeValue::GetElements(array);
     183      305069 :   switch (CompileTimeValue::GetLiteralType(array)) {
     184             :     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: {
     185             :       Handle<BoilerplateDescription> props =
     186      226491 :           Handle<BoilerplateDescription>::cast(elements);
     187      226491 :       return CreateObjectLiteralBoilerplate(isolate, vector, props, true);
     188             :     }
     189             :     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: {
     190             :       Handle<BoilerplateDescription> props =
     191         145 :           Handle<BoilerplateDescription>::cast(elements);
     192         145 :       return CreateObjectLiteralBoilerplate(isolate, vector, props, false);
     193             :     }
     194             :     case CompileTimeValue::ARRAY_LITERAL: {
     195             :       Handle<ConstantElementsPair> elems =
     196       78433 :           Handle<ConstantElementsPair>::cast(elements);
     197       78433 :       return CreateArrayLiteralBoilerplate(isolate, vector, elems);
     198             :     }
     199             :     default:
     200           0 :       UNREACHABLE();
     201             :       return MaybeHandle<Object>();
     202             :   }
     203             : }
     204             : 
     205             : 
     206      250586 : RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
     207      125293 :   HandleScope scope(isolate);
     208             :   DCHECK_EQ(4, args.length());
     209      250586 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
     210      250586 :   CONVERT_SMI_ARG_CHECKED(index, 1);
     211      250586 :   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
     212      250586 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     213      125293 :   FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
     214             : 
     215             :   // Check if boilerplate exists. If not, create it first.
     216             :   Handle<Object> boilerplate(closure->feedback_vector()->Get(literal_slot),
     217      125293 :                              isolate);
     218      125293 :   if (boilerplate->IsUndefined(isolate)) {
     219      250586 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     220             :         isolate, boilerplate, JSRegExp::New(pattern, JSRegExp::Flags(flags)));
     221      122017 :     closure->feedback_vector()->Set(literal_slot, *boilerplate);
     222             :   }
     223      244034 :   return *JSRegExp::Copy(Handle<JSRegExp>::cast(boilerplate));
     224             : }
     225             : 
     226             : 
     227    10839637 : RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
     228     5419819 :   HandleScope scope(isolate);
     229             :   DCHECK_EQ(4, args.length());
     230    10839638 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
     231    10839638 :   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
     232    10839635 :   CONVERT_ARG_HANDLE_CHECKED(BoilerplateDescription, boilerplate_description,
     233             :                              2);
     234    10839632 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     235     5419816 :   Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
     236     5419816 :   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
     237     5419816 :   bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
     238             : 
     239     5419816 :   FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
     240    10839632 :   CHECK(literals_slot.ToInt() < vector->slot_count());
     241             : 
     242             :   // Check if boilerplate exists. If not, create it first.
     243     5419817 :   Handle<Object> literal_site(vector->Get(literals_slot), isolate);
     244             :   Handle<AllocationSite> site;
     245             :   Handle<JSObject> boilerplate;
     246     5419819 :   if (literal_site->IsUndefined(isolate)) {
     247             :     Handle<Object> raw_boilerplate;
     248     1210500 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     249             :         isolate, raw_boilerplate,
     250             :         CreateObjectLiteralBoilerplate(isolate, vector, boilerplate_description,
     251             :                                        should_have_fast_elements));
     252      605250 :     boilerplate = Handle<JSObject>::cast(raw_boilerplate);
     253             : 
     254      605250 :     AllocationSiteCreationContext creation_context(isolate);
     255      605250 :     site = creation_context.EnterNewScope();
     256      605250 :     RETURN_FAILURE_ON_EXCEPTION(
     257             :         isolate, JSObject::DeepWalk(boilerplate, &creation_context));
     258      605250 :     creation_context.ExitScope(site, boilerplate);
     259             : 
     260             :     // Update the functions literal and return the boilerplate.
     261      605250 :     vector->Set(literals_slot, *site);
     262             :   } else {
     263     4814569 :     site = Handle<AllocationSite>::cast(literal_site);
     264             :     boilerplate =
     265     9629138 :         Handle<JSObject>(JSObject::cast(site->transition_info()), isolate);
     266             :   }
     267             : 
     268     5419819 :   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
     269     5419819 :   usage_context.EnterNewScope();
     270             :   MaybeHandle<Object> maybe_copy =
     271    10839636 :       JSObject::DeepCopy(boilerplate, &usage_context);
     272             :   usage_context.ExitScope(site, boilerplate);
     273    10839636 :   RETURN_RESULT_OR_FAILURE(isolate, maybe_copy);
     274             : }
     275             : 
     276     1925922 : MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
     277             :     Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot literals_slot,
     278             :     Handle<ConstantElementsPair> elements) {
     279             :   // Check if boilerplate exists. If not, create it first.
     280             :   Handle<Object> literal_site(vector->Get(literals_slot), isolate);
     281             :   Handle<AllocationSite> site;
     282     1925922 :   if (literal_site->IsUndefined(isolate)) {
     283             :     Handle<Object> boilerplate;
     284      631301 :     ASSIGN_RETURN_ON_EXCEPTION(
     285             :         isolate, boilerplate,
     286             :         CreateArrayLiteralBoilerplate(isolate, vector, elements),
     287             :         AllocationSite);
     288             : 
     289             :     AllocationSiteCreationContext creation_context(isolate);
     290      315585 :     site = creation_context.EnterNewScope();
     291      315585 :     if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
     292      631170 :                            &creation_context).is_null()) {
     293             :       return Handle<AllocationSite>::null();
     294             :     }
     295      315454 :     creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
     296             : 
     297             :     vector->Set(literals_slot, *site);
     298             :   } else {
     299             :     site = Handle<AllocationSite>::cast(literal_site);
     300             :   }
     301             : 
     302             :   return site;
     303             : }
     304             : 
     305     1925922 : static MaybeHandle<JSObject> CreateArrayLiteralImpl(
     306             :     Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot literals_slot,
     307             :     Handle<ConstantElementsPair> elements, int flags) {
     308     1925922 :   CHECK(literals_slot.ToInt() < vector->slot_count());
     309             :   Handle<AllocationSite> site;
     310     3851844 :   ASSIGN_RETURN_ON_EXCEPTION(
     311             :       isolate, site,
     312             :       GetLiteralAllocationSite(isolate, vector, literals_slot, elements),
     313             :       JSObject);
     314             : 
     315     1925791 :   bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
     316             :   Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
     317             :   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
     318     1925791 :   usage_context.EnterNewScope();
     319     1925791 :   JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
     320             :                                       ? JSObject::kNoHints
     321     1925791 :                                       : JSObject::kObjectIsShallow;
     322             :   MaybeHandle<JSObject> copy =
     323     1925791 :       JSObject::DeepCopy(boilerplate, &usage_context, hints);
     324             :   usage_context.ExitScope(site, boilerplate);
     325     1925791 :   return copy;
     326             : }
     327             : 
     328             : 
     329     3851844 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
     330     1925922 :   HandleScope scope(isolate);
     331             :   DCHECK_EQ(4, args.length());
     332     3851844 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
     333     3851844 :   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
     334     3851844 :   CONVERT_ARG_HANDLE_CHECKED(ConstantElementsPair, elements, 2);
     335     3851844 :   CONVERT_SMI_ARG_CHECKED(flags, 3);
     336             : 
     337     1925922 :   FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
     338     1925922 :   Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
     339     3851844 :   RETURN_RESULT_OR_FAILURE(
     340             :       isolate,
     341     1925922 :       CreateArrayLiteralImpl(isolate, vector, literals_slot, elements, flags));
     342             : }
     343             : 
     344             : 
     345           0 : RUNTIME_FUNCTION(Runtime_CreateArrayLiteralStubBailout) {
     346           0 :   HandleScope scope(isolate);
     347             :   DCHECK_EQ(3, args.length());
     348           0 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
     349           0 :   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
     350           0 :   CONVERT_ARG_HANDLE_CHECKED(ConstantElementsPair, elements, 2);
     351             : 
     352           0 :   Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
     353           0 :   FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
     354           0 :   RETURN_RESULT_OR_FAILURE(
     355             :       isolate, CreateArrayLiteralImpl(isolate, vector, literals_slot, elements,
     356           0 :                                       ArrayLiteral::kShallowElements));
     357             : }
     358             : 
     359             : }  // namespace internal
     360             : }  // namespace v8

Generated by: LCOV version 1.10