LCOV - code coverage report
Current view: top level - src/objects - literal-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 202 205 98.5 %
Date: 2019-04-17 Functions: 19 20 95.0 %

          Line data    Source code
       1             : // Copyright 2017 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/objects/literal-objects.h"
       6             : 
       7             : #include "src/accessors.h"
       8             : #include "src/ast/ast.h"
       9             : #include "src/heap/factory.h"
      10             : #include "src/isolate.h"
      11             : #include "src/objects-inl.h"
      12             : #include "src/objects/hash-table-inl.h"
      13             : #include "src/objects/literal-objects-inl.h"
      14             : #include "src/objects/smi.h"
      15             : #include "src/objects/struct-inl.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20     4661655 : Object ObjectBoilerplateDescription::name(int index) const {
      21             :   // get() already checks for out of bounds access, but we do not want to allow
      22             :   // access to the last element, if it is the number of properties.
      23             :   DCHECK_NE(size(), index);
      24     9323310 :   return get(2 * index + kDescriptionStartIndex);
      25             : }
      26             : 
      27     4661657 : Object ObjectBoilerplateDescription::value(int index) const {
      28     9323314 :   return get(2 * index + 1 + kDescriptionStartIndex);
      29             : }
      30             : 
      31     1965565 : void ObjectBoilerplateDescription::set_key_value(int index, Object key,
      32             :                                                  Object value) {
      33             :   DCHECK_LT(index, size());
      34             :   DCHECK_GE(index, 0);
      35     1965565 :   set(2 * index + kDescriptionStartIndex, key);
      36     1965566 :   set(2 * index + 1 + kDescriptionStartIndex, value);
      37     1965568 : }
      38             : 
      39      379819 : int ObjectBoilerplateDescription::size() const {
      40             :   DCHECK_EQ(0, (length() - kDescriptionStartIndex -
      41             :                 (this->has_number_of_properties() ? 1 : 0)) %
      42             :                    2);
      43             :   // Rounding is intended.
      44      739775 :   return (length() - kDescriptionStartIndex) / 2;
      45             : }
      46             : 
      47      364954 : int ObjectBoilerplateDescription::backing_store_size() const {
      48      364954 :   if (has_number_of_properties()) {
      49             :     // If present, the last entry contains the number of properties.
      50        4998 :     return Smi::ToInt(this->get(length() - 1));
      51             :   }
      52             :   // If the number is not given explicitly, we assume there are no
      53             :   // properties with computed names.
      54      359956 :   return size();
      55             : }
      56             : 
      57        2775 : void ObjectBoilerplateDescription::set_backing_store_size(
      58             :     Isolate* isolate, int backing_store_size) {
      59             :   DCHECK(has_number_of_properties());
      60             :   DCHECK_NE(size(), backing_store_size);
      61             :   Handle<Object> backing_store_size_obj =
      62        2775 :       isolate->factory()->NewNumberFromInt(backing_store_size);
      63        2775 :   set(length() - 1, *backing_store_size_obj);
      64        2775 : }
      65             : 
      66           0 : bool ObjectBoilerplateDescription::has_number_of_properties() const {
      67      364954 :   return (length() - kDescriptionStartIndex) % 2 != 0;
      68             : }
      69             : 
      70             : namespace {
      71             : 
      72             : inline int EncodeComputedEntry(ClassBoilerplate::ValueKind value_kind,
      73             :                                unsigned key_index) {
      74             :   using Flags = ClassBoilerplate::ComputedEntryFlags;
      75        5559 :   int flags = Flags::ValueKindBits::encode(value_kind) |
      76        5559 :               Flags::KeyIndexBits::encode(key_index);
      77             :   return flags;
      78             : }
      79             : 
      80      257627 : void AddToDescriptorArrayTemplate(
      81             :     Isolate* isolate, Handle<DescriptorArray> descriptor_array_template,
      82             :     Handle<Name> name, ClassBoilerplate::ValueKind value_kind,
      83             :     Handle<Object> value) {
      84      772881 :   int entry = descriptor_array_template->Search(
      85             :       *name, descriptor_array_template->number_of_descriptors());
      86             :   // TODO(ishell): deduplicate properties at AST level, this will allow us to
      87             :   // avoid creation of closures that will be overwritten anyway.
      88      257627 :   if (entry == DescriptorArray::kNotFound) {
      89             :     // Entry not found, add new one.
      90      257447 :     Descriptor d;
      91      257447 :     if (value_kind == ClassBoilerplate::kData) {
      92      254197 :       d = Descriptor::DataConstant(name, value, DONT_ENUM);
      93             :     } else {
      94             :       DCHECK(value_kind == ClassBoilerplate::kGetter ||
      95             :              value_kind == ClassBoilerplate::kSetter);
      96        3250 :       Handle<AccessorPair> pair = isolate->factory()->NewAccessorPair();
      97        9750 :       pair->set(value_kind == ClassBoilerplate::kGetter ? ACCESSOR_GETTER
      98             :                                                         : ACCESSOR_SETTER,
      99        3250 :                 *value);
     100        3250 :       d = Descriptor::AccessorConstant(name, pair, DONT_ENUM);
     101             :     }
     102      257447 :     descriptor_array_template->Append(&d);
     103             : 
     104             :   } else {
     105             :     // Entry found, update it.
     106         360 :     int sorted_index = descriptor_array_template->GetDetails(entry).pointer();
     107         180 :     if (value_kind == ClassBoilerplate::kData) {
     108          36 :       Descriptor d = Descriptor::DataConstant(name, value, DONT_ENUM);
     109             :       d.SetSortedKeyIndex(sorted_index);
     110          36 :       descriptor_array_template->Set(entry, &d);
     111             :     } else {
     112             :       DCHECK(value_kind == ClassBoilerplate::kGetter ||
     113             :              value_kind == ClassBoilerplate::kSetter);
     114             :       Object raw_accessor = descriptor_array_template->GetStrongValue(entry);
     115         144 :       AccessorPair pair;
     116         144 :       if (raw_accessor->IsAccessorPair()) {
     117         120 :         pair = AccessorPair::cast(raw_accessor);
     118             :       } else {
     119          24 :         Handle<AccessorPair> new_pair = isolate->factory()->NewAccessorPair();
     120          24 :         Descriptor d = Descriptor::AccessorConstant(name, new_pair, DONT_ENUM);
     121             :         d.SetSortedKeyIndex(sorted_index);
     122          24 :         descriptor_array_template->Set(entry, &d);
     123          24 :         pair = *new_pair;
     124             :       }
     125         144 :       pair->set(value_kind == ClassBoilerplate::kGetter ? ACCESSOR_GETTER
     126             :                                                         : ACCESSOR_SETTER,
     127         144 :                 *value);
     128             :     }
     129             :   }
     130      257627 : }
     131             : 
     132             : Handle<NameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
     133             :     Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
     134             :     Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
     135             :   return NameDictionary::AddNoUpdateNextEnumerationIndex(
     136       35803 :       isolate, dictionary, name, value, details, entry_out);
     137             : }
     138             : 
     139             : Handle<NumberDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
     140             :     Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t element,
     141             :     Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
     142             :   // NumberDictionary does not maintain the enumeration order, so it's
     143             :   // a normal Add().
     144             :   return NumberDictionary::Add(isolate, dictionary, element, value, details,
     145         446 :                                entry_out);
     146             : }
     147             : 
     148             : void DictionaryUpdateMaxNumberKey(Handle<NameDictionary> dictionary,
     149             :                                   Handle<Name> name) {
     150             :   // No-op for name dictionaries.
     151             : }
     152             : 
     153         446 : void DictionaryUpdateMaxNumberKey(Handle<NumberDictionary> dictionary,
     154             :                                   uint32_t element) {
     155         446 :   dictionary->UpdateMaxNumberKey(element, Handle<JSObject>());
     156             :   dictionary->set_requires_slow_elements();
     157         446 : }
     158             : 
     159             : constexpr int ComputeEnumerationIndex(int value_index) {
     160             :   // We "shift" value indices to ensure that the enumeration index for the value
     161             :   // will not overlap with minimum properties set for both class and prototype
     162             :   // objects.
     163             :   return value_index + Max(ClassBoilerplate::kMinimumClassPropertiesCount,
     164       56799 :                            ClassBoilerplate::kMinimumPrototypePropertiesCount);
     165             : }
     166             : 
     167             : inline int GetExistingValueIndex(Object value) {
     168         291 :   return value->IsSmi() ? Smi::ToInt(value) : -1;
     169             : }
     170             : 
     171             : template <typename Dictionary, typename Key>
     172       27751 : void AddToDictionaryTemplate(Isolate* isolate, Handle<Dictionary> dictionary,
     173             :                              Key key, int key_index,
     174             :                              ClassBoilerplate::ValueKind value_kind,
     175             :                              Object value) {
     176       27751 :   int entry = dictionary->FindEntry(isolate, key);
     177             : 
     178       27751 :   if (entry == kNotFound) {
     179             :     // Entry not found, add new one.
     180             :     const bool is_elements_dictionary =
     181             :         std::is_same<Dictionary, NumberDictionary>::value;
     182             :     STATIC_ASSERT(is_elements_dictionary !=
     183             :                   (std::is_same<Dictionary, NameDictionary>::value));
     184             :     int enum_order =
     185             :         is_elements_dictionary ? 0 : ComputeEnumerationIndex(key_index);
     186             :     Handle<Object> value_handle;
     187             :     PropertyDetails details(
     188             :         value_kind != ClassBoilerplate::kData ? kAccessor : kData, DONT_ENUM,
     189       27449 :         PropertyCellType::kNoCell, enum_order);
     190             : 
     191       27449 :     if (value_kind == ClassBoilerplate::kData) {
     192             :       value_handle = handle(value, isolate);
     193             :     } else {
     194             :       AccessorComponent component = value_kind == ClassBoilerplate::kGetter
     195             :                                         ? ACCESSOR_GETTER
     196        2800 :                                         : ACCESSOR_SETTER;
     197        2800 :       Handle<AccessorPair> pair(isolate->factory()->NewAccessorPair());
     198        2800 :       pair->set(component, value);
     199             :       value_handle = pair;
     200             :     }
     201             : 
     202             :     // Add value to the dictionary without updating next enumeration index.
     203             :     Handle<Dictionary> dict = DictionaryAddNoUpdateNextEnumerationIndex(
     204             :         isolate, dictionary, key, value_handle, details, &entry);
     205             :     // It is crucial to avoid dictionary reallocations because it may remove
     206             :     // potential gaps in enumeration indices values that are necessary for
     207             :     // inserting computed properties into right places in the enumeration order.
     208       27449 :     CHECK_EQ(*dict, *dictionary);
     209             : 
     210         446 :     DictionaryUpdateMaxNumberKey(dictionary, key);
     211             : 
     212             :   } else {
     213             :     // Entry found, update it.
     214         604 :     int enum_order = dictionary->DetailsAt(entry).dictionary_index();
     215         302 :     Object existing_value = dictionary->ValueAt(entry);
     216         302 :     if (value_kind == ClassBoilerplate::kData) {
     217             :       // Computed value is a normal method.
     218          99 :       if (existing_value->IsAccessorPair()) {
     219          72 :         AccessorPair current_pair = AccessorPair::cast(existing_value);
     220             : 
     221             :         int existing_getter_index =
     222             :             GetExistingValueIndex(current_pair->getter());
     223             :         int existing_setter_index =
     224             :             GetExistingValueIndex(current_pair->setter());
     225             :         // At least one of the accessors must already be defined.
     226             :         DCHECK(existing_getter_index >= 0 || existing_setter_index >= 0);
     227          72 :         if (existing_getter_index < key_index &&
     228             :             existing_setter_index < key_index) {
     229             :           // Either both getter and setter were defined before the computed
     230             :           // method or just one of them was defined before while the other one
     231             :           // was not defined yet, so overwrite property to kData.
     232             :           PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell,
     233             :                                   enum_order);
     234           0 :           dictionary->DetailsAtPut(isolate, entry, details);
     235           0 :           dictionary->ValueAtPut(entry, value);
     236             : 
     237             :         } else {
     238             :           // The data property was defined "between" accessors so the one that
     239             :           // was overwritten has to be cleared.
     240          72 :           if (existing_getter_index < key_index) {
     241             :             DCHECK_LT(key_index, existing_setter_index);
     242             :             // Getter was defined and it was done before the computed method
     243             :             // and then it was overwritten by the current computed method which
     244             :             // in turn was later overwritten by the setter method. So we clear
     245             :             // the getter.
     246          36 :             current_pair->set_getter(*isolate->factory()->null_value());
     247             : 
     248          36 :           } else if (existing_setter_index < key_index) {
     249             :             DCHECK_LT(key_index, existing_getter_index);
     250             :             // Setter was defined and it was done before the computed method
     251             :             // and then it was overwritten by the current computed method which
     252             :             // in turn was later overwritten by the getter method. So we clear
     253             :             // the setter.
     254          36 :             current_pair->set_setter(*isolate->factory()->null_value());
     255             :           }
     256             :         }
     257             :       } else {
     258             :         // Overwrite existing value if it was defined before the computed one
     259             :         // (AccessorInfo "length" property is always defined before).
     260             :         DCHECK_IMPLIES(!existing_value->IsSmi(),
     261             :                        existing_value->IsAccessorInfo());
     262             :         DCHECK_IMPLIES(!existing_value->IsSmi(),
     263             :                        AccessorInfo::cast(existing_value)->name() ==
     264             :                            *isolate->factory()->length_string());
     265          45 :         if (!existing_value->IsSmi() ||
     266             :             Smi::ToInt(existing_value) < key_index) {
     267             :           PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell,
     268             :                                   enum_order);
     269          27 :           dictionary->DetailsAtPut(isolate, entry, details);
     270          81 :           dictionary->ValueAtPut(entry, value);
     271             :         }
     272             :       }
     273             :     } else {
     274             :       AccessorComponent component = value_kind == ClassBoilerplate::kGetter
     275             :                                         ? ACCESSOR_GETTER
     276         203 :                                         : ACCESSOR_SETTER;
     277         203 :       if (existing_value->IsAccessorPair()) {
     278             :         // Update respective component of existing AccessorPair.
     279         147 :         AccessorPair current_pair = AccessorPair::cast(existing_value);
     280             : 
     281             :         int existing_component_index =
     282             :             GetExistingValueIndex(current_pair->get(component));
     283         147 :         if (existing_component_index < key_index) {
     284         120 :           current_pair->set(component, value);
     285             :         }
     286             : 
     287             :       } else {
     288             :         // Overwrite existing value with new AccessorPair.
     289          56 :         Handle<AccessorPair> pair(isolate->factory()->NewAccessorPair());
     290          56 :         pair->set(component, value);
     291             :         PropertyDetails details(kAccessor, DONT_ENUM, PropertyCellType::kNoCell,
     292             :                                 enum_order);
     293          56 :         dictionary->DetailsAtPut(isolate, entry, details);
     294         168 :         dictionary->ValueAtPut(entry, *pair);
     295             :       }
     296             :     }
     297             :   }
     298       27751 : }
     299             : 
     300             : }  // namespace
     301             : 
     302             : // Helper class that eases building of a properties, elements and computed
     303             : // properties templates.
     304       80676 : class ObjectDescriptor {
     305             :  public:
     306        5939 :   void IncComputedCount() { ++computed_count_; }
     307      282476 :   void IncPropertiesCount() { ++property_count_; }
     308         155 :   void IncElementsCount() { ++element_count_; }
     309             : 
     310             :   bool HasDictionaryProperties() const {
     311      818372 :     return computed_count_ > 0 || property_count_ > kMaxNumberOfDescriptors;
     312             :   }
     313             : 
     314             :   Handle<Object> properties_template() const {
     315             :     return HasDictionaryProperties()
     316             :                ? Handle<Object>::cast(properties_dictionary_template_)
     317       80676 :                : Handle<Object>::cast(descriptor_array_template_);
     318             :   }
     319             : 
     320             :   Handle<NumberDictionary> elements_template() const {
     321             :     return elements_dictionary_template_;
     322             :   }
     323             : 
     324             :   Handle<FixedArray> computed_properties() const {
     325             :     return computed_properties_;
     326             :   }
     327             : 
     328       80676 :   void CreateTemplates(Isolate* isolate, int slack) {
     329             :     Factory* factory = isolate->factory();
     330       80676 :     descriptor_array_template_ = factory->empty_descriptor_array();
     331       80676 :     properties_dictionary_template_ = factory->empty_property_dictionary();
     332      141150 :     if (property_count_ || HasDictionaryProperties() || slack) {
     333       80676 :       if (HasDictionaryProperties()) {
     334             :         properties_dictionary_template_ = NameDictionary::New(
     335        5622 :             isolate, property_count_ + computed_count_ + slack);
     336             :       } else {
     337             :         descriptor_array_template_ =
     338       75054 :             DescriptorArray::Allocate(isolate, 0, property_count_ + slack);
     339             :       }
     340             :     }
     341             :     elements_dictionary_template_ =
     342       80676 :         element_count_ || computed_count_
     343        5650 :             ? NumberDictionary::New(isolate, element_count_ + computed_count_)
     344      161352 :             : factory->empty_slow_element_dictionary();
     345             : 
     346             :     computed_properties_ =
     347       80676 :         computed_count_
     348             :             ? factory->NewFixedArray(computed_count_ *
     349        5610 :                                      ClassBoilerplate::kFullComputedEntrySize)
     350      161352 :             : factory->empty_fixed_array();
     351             : 
     352       80676 :     temp_handle_ = handle(Smi::kZero, isolate);
     353       80676 :   }
     354             : 
     355      197306 :   void AddConstant(Isolate* isolate, Handle<Name> name, Handle<Object> value,
     356             :                    PropertyAttributes attribs) {
     357             :     bool is_accessor = value->IsAccessorInfo();
     358             :     DCHECK(!value->IsAccessorPair());
     359      197306 :     if (HasDictionaryProperties()) {
     360        8800 :       PropertyKind kind = is_accessor ? i::kAccessor : i::kData;
     361             :       PropertyDetails details(kind, attribs, PropertyCellType::kNoCell,
     362        8800 :                               next_enumeration_index_++);
     363             :       properties_dictionary_template_ =
     364             :           DictionaryAddNoUpdateNextEnumerationIndex(
     365        8800 :               isolate, properties_dictionary_template_, name, value, details);
     366             :     } else {
     367             :       Descriptor d = is_accessor
     368             :                          ? Descriptor::AccessorConstant(name, value, attribs)
     369      188506 :                          : Descriptor::DataConstant(name, value, attribs);
     370      188506 :       descriptor_array_template_->Append(&d);
     371             :     }
     372      197306 :   }
     373             : 
     374      281864 :   void AddNamedProperty(Isolate* isolate, Handle<Name> name,
     375             :                         ClassBoilerplate::ValueKind value_kind,
     376             :                         int value_index) {
     377             :     Smi value = Smi::FromInt(value_index);
     378      281864 :     if (HasDictionaryProperties()) {
     379             :       UpdateNextEnumerationIndex(value_index);
     380             :       AddToDictionaryTemplate(isolate, properties_dictionary_template_, name,
     381       24237 :                               value_index, value_kind, value);
     382             :     } else {
     383      257627 :       *temp_handle_.location() = value->ptr();
     384             :       AddToDescriptorArrayTemplate(isolate, descriptor_array_template_, name,
     385      257627 :                                    value_kind, temp_handle_);
     386             :     }
     387      281864 :   }
     388             : 
     389             :   void AddIndexedProperty(Isolate* isolate, uint32_t element,
     390             :                           ClassBoilerplate::ValueKind value_kind,
     391             :                           int value_index) {
     392         155 :     Smi value = Smi::FromInt(value_index);
     393             :     AddToDictionaryTemplate(isolate, elements_dictionary_template_, element,
     394         155 :                             value_index, value_kind, value);
     395             :   }
     396             : 
     397        5559 :   void AddComputed(ClassBoilerplate::ValueKind value_kind, int key_index) {
     398             :     int value_index = key_index + 1;
     399             :     UpdateNextEnumerationIndex(value_index);
     400             : 
     401        5559 :     int flags = EncodeComputedEntry(value_kind, key_index);
     402        5559 :     computed_properties_->set(current_computed_index_++, Smi::FromInt(flags));
     403        5559 :   }
     404             : 
     405             :   void UpdateNextEnumerationIndex(int value_index) {
     406             :     int next_index = ComputeEnumerationIndex(value_index);
     407             :     DCHECK_LT(next_enumeration_index_, next_index);
     408       29796 :     next_enumeration_index_ = next_index;
     409             :   }
     410             : 
     411       80676 :   void Finalize(Isolate* isolate) {
     412       80676 :     if (HasDictionaryProperties()) {
     413        5622 :       properties_dictionary_template_->SetNextEnumerationIndex(
     414             :           next_enumeration_index_);
     415             :       computed_properties_ = FixedArray::ShrinkOrEmpty(
     416        5622 :           isolate, computed_properties_, current_computed_index_);
     417             :     } else {
     418             :       DCHECK(descriptor_array_template_->IsSortedNoDuplicates());
     419             :     }
     420       80676 :   }
     421             : 
     422             :  private:
     423             :   int property_count_ = 0;
     424             :   int next_enumeration_index_ = PropertyDetails::kInitialIndex;
     425             :   int element_count_ = 0;
     426             :   int computed_count_ = 0;
     427             :   int current_computed_index_ = 0;
     428             : 
     429             :   Handle<DescriptorArray> descriptor_array_template_;
     430             :   Handle<NameDictionary> properties_dictionary_template_;
     431             :   Handle<NumberDictionary> elements_dictionary_template_;
     432             :   Handle<FixedArray> computed_properties_;
     433             :   // This temporary handle is used for storing to descriptor array.
     434             :   Handle<Object> temp_handle_;
     435             : };
     436             : 
     437        3053 : void ClassBoilerplate::AddToPropertiesTemplate(
     438             :     Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
     439             :     int key_index, ClassBoilerplate::ValueKind value_kind, Object value) {
     440             :   AddToDictionaryTemplate(isolate, dictionary, name, key_index, value_kind,
     441        3053 :                           value);
     442        3053 : }
     443             : 
     444         306 : void ClassBoilerplate::AddToElementsTemplate(
     445             :     Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
     446             :     int key_index, ClassBoilerplate::ValueKind value_kind, Object value) {
     447             :   AddToDictionaryTemplate(isolate, dictionary, key, key_index, value_kind,
     448         306 :                           value);
     449         306 : }
     450             : 
     451       40338 : Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
     452             :     Isolate* isolate, ClassLiteral* expr) {
     453             :   // Create a non-caching handle scope to ensure that the temporary handle used
     454             :   // by ObjectDescriptor for passing Smis around does not corrupt handle cache
     455             :   // in CanonicalHandleScope.
     456             :   HandleScope scope(isolate);
     457             :   Factory* factory = isolate->factory();
     458             :   ObjectDescriptor static_desc;
     459             :   ObjectDescriptor instance_desc;
     460             : 
     461      617478 :   for (int i = 0; i < expr->properties()->length(); i++) {
     462      288570 :     ClassLiteral::Property* property = expr->properties()->at(i);
     463             :     ObjectDescriptor& desc =
     464      288570 :         property->is_static() ? static_desc : instance_desc;
     465      288570 :     if (property->is_computed_name()) {
     466             :       desc.IncComputedCount();
     467             :     } else {
     468      565262 :       if (property->key()->AsLiteral()->IsPropertyName()) {
     469             :         desc.IncPropertiesCount();
     470             :       } else {
     471             :         desc.IncElementsCount();
     472             :       }
     473             :     }
     474             :   }
     475             : 
     476             :   //
     477             :   // Initialize class object template.
     478             :   //
     479       40338 :   static_desc.CreateTemplates(isolate, kMinimumClassPropertiesCount);
     480             :   STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
     481             :   {
     482             :     // Add length_accessor.
     483             :     PropertyAttributes attribs =
     484             :         static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
     485       40338 :     static_desc.AddConstant(isolate, factory->length_string(),
     486       40338 :                             factory->function_length_accessor(), attribs);
     487             :   }
     488             :   {
     489             :     // Add prototype_accessor.
     490             :     PropertyAttributes attribs =
     491             :         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
     492       40338 :     static_desc.AddConstant(isolate, factory->prototype_string(),
     493       40338 :                             factory->function_prototype_accessor(), attribs);
     494             :   }
     495       40338 :   if (FunctionLiteral::NeedsHomeObject(expr->constructor())) {
     496             :     PropertyAttributes attribs =
     497             :         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
     498             :     Handle<Object> value(
     499             :         Smi::FromInt(ClassBoilerplate::kPrototypeArgumentIndex), isolate);
     500         828 :     static_desc.AddConstant(isolate, factory->home_object_symbol(), value,
     501         828 :                             attribs);
     502             :   }
     503             :   {
     504             :     Handle<ClassPositions> class_positions = factory->NewClassPositions(
     505       40338 :         expr->start_position(), expr->end_position());
     506       40338 :     static_desc.AddConstant(isolate, factory->class_positions_symbol(),
     507       40338 :                             class_positions, DONT_ENUM);
     508             :   }
     509             : 
     510             :   //
     511             :   // Initialize prototype object template.
     512             :   //
     513       40338 :   instance_desc.CreateTemplates(isolate, kMinimumPrototypePropertiesCount);
     514             :   {
     515             :     Handle<Object> value(
     516             :         Smi::FromInt(ClassBoilerplate::kConstructorArgumentIndex), isolate);
     517       40338 :     instance_desc.AddConstant(isolate, factory->constructor_string(), value,
     518       40338 :                               DONT_ENUM);
     519             :   }
     520             : 
     521             :   //
     522             :   // Fill in class boilerplate.
     523             :   //
     524             :   int dynamic_argument_index = ClassBoilerplate::kFirstDynamicArgumentIndex;
     525             : 
     526      617478 :   for (int i = 0; i < expr->properties()->length(); i++) {
     527      288570 :     ClassLiteral::Property* property = expr->properties()->at(i);
     528             : 
     529             :     ClassBoilerplate::ValueKind value_kind;
     530      288570 :     switch (property->kind()) {
     531             :       case ClassLiteral::Property::METHOD:
     532             :         value_kind = ClassBoilerplate::kData;
     533      281176 :         break;
     534             :       case ClassLiteral::Property::GETTER:
     535             :         value_kind = ClassBoilerplate::kGetter;
     536        3437 :         break;
     537             :       case ClassLiteral::Property::SETTER:
     538             :         value_kind = ClassBoilerplate::kSetter;
     539        2965 :         break;
     540             :       case ClassLiteral::Property::FIELD:
     541             :         DCHECK_IMPLIES(property->is_computed_name(), !property->is_private());
     542         992 :         if (property->is_computed_name()) {
     543         380 :           ++dynamic_argument_index;
     544             :         }
     545        6551 :         continue;
     546             :     }
     547             : 
     548             :     ObjectDescriptor& desc =
     549      287578 :         property->is_static() ? static_desc : instance_desc;
     550      287578 :     if (property->is_computed_name()) {
     551             :       int computed_name_index = dynamic_argument_index;
     552        5559 :       dynamic_argument_index += 2;  // Computed name and value indices.
     553        5559 :       desc.AddComputed(value_kind, computed_name_index);
     554        5559 :       continue;
     555             :     }
     556      282019 :     int value_index = dynamic_argument_index++;
     557             : 
     558      282019 :     Literal* key_literal = property->key()->AsLiteral();
     559             :     uint32_t index;
     560      282019 :     if (key_literal->AsArrayIndex(&index)) {
     561         155 :       desc.AddIndexedProperty(isolate, index, value_kind, value_index);
     562             : 
     563             :     } else {
     564             :       Handle<String> name = key_literal->AsRawPropertyName()->string();
     565             :       DCHECK(name->IsInternalizedString());
     566      281864 :       desc.AddNamedProperty(isolate, name, value_kind, value_index);
     567             :     }
     568             :   }
     569             : 
     570             :   // Add name accessor to the class object if necessary.
     571             :   bool install_class_name_accessor = false;
     572       40338 :   if (!expr->has_name_static_property() &&
     573             :       expr->constructor()->has_shared_name()) {
     574       36700 :     if (static_desc.HasDictionaryProperties()) {
     575             :       // Install class name accessor if necessary during class literal
     576             :       // instantiation.
     577             :       install_class_name_accessor = true;
     578             :     } else {
     579             :       // Set class name accessor if the "name" method was not added yet.
     580             :       PropertyAttributes attribs =
     581             :           static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
     582       35126 :       static_desc.AddConstant(isolate, factory->name_string(),
     583       35126 :                               factory->function_name_accessor(), attribs);
     584             :     }
     585             :   }
     586             : 
     587       40338 :   static_desc.Finalize(isolate);
     588       40338 :   instance_desc.Finalize(isolate);
     589             : 
     590             :   Handle<ClassBoilerplate> class_boilerplate =
     591       40338 :       Handle<ClassBoilerplate>::cast(factory->NewFixedArray(kBoileplateLength));
     592             : 
     593             :   class_boilerplate->set_flags(0);
     594      121014 :   class_boilerplate->set_install_class_name_accessor(
     595       40338 :       install_class_name_accessor);
     596       40338 :   class_boilerplate->set_arguments_count(dynamic_argument_index);
     597             : 
     598       80676 :   class_boilerplate->set_static_properties_template(
     599       40338 :       *static_desc.properties_template());
     600      121014 :   class_boilerplate->set_static_elements_template(
     601       40338 :       *static_desc.elements_template());
     602       80676 :   class_boilerplate->set_static_computed_properties(
     603       40338 :       *static_desc.computed_properties());
     604             : 
     605       80676 :   class_boilerplate->set_instance_properties_template(
     606       40338 :       *instance_desc.properties_template());
     607      121014 :   class_boilerplate->set_instance_elements_template(
     608       40338 :       *instance_desc.elements_template());
     609       80676 :   class_boilerplate->set_instance_computed_properties(
     610       40338 :       *instance_desc.computed_properties());
     611             : 
     612       80676 :   return scope.CloseAndEscape(class_boilerplate);
     613             : }
     614             : 
     615             : }  // namespace internal
     616      121996 : }  // namespace v8

Generated by: LCOV version 1.10