LCOV - code coverage report
Current view: top level - src - map-updater.h (source / functions) Hit Total Coverage
Test: app.info Lines: 3 3 100.0 %
Date: 2017-10-20 Functions: 1 1 100.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             : #ifndef V8_MAP_UPDATER_H_
       6             : #define V8_MAP_UPDATER_H_
       7             : 
       8             : #include "src/elements-kind.h"
       9             : #include "src/field-type.h"
      10             : #include "src/globals.h"
      11             : #include "src/handles.h"
      12             : #include "src/objects/map.h"
      13             : #include "src/property-details.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : // The |MapUpdater| class implements all sorts of map reconfigurations
      19             : // including changes of elements kind, property attributes, property kind,
      20             : // property location and field representations/type changes. It ensures that
      21             : // the reconfigured map and all the intermediate maps are properly integrated
      22             : // into the exising transition tree.
      23             : //
      24             : // To avoid high degrees over polymorphism, and to stabilize quickly, on every
      25             : // rewrite the new type is deduced by merging the current type with any
      26             : // potential new (partial) version of the type in the transition tree.
      27             : // To do this, on each rewrite:
      28             : // - Search the root of the transition tree using FindRootMap.
      29             : // - Find/create a |root_map| with requested |new_elements_kind|.
      30             : // - Find |target_map|, the newest matching version of this map using the
      31             : //   "updated" |old_map|'s descriptor array (i.e. whose entry at |modify_index|
      32             : //   is considered to be of |new_kind| and having |new_attributes|) to walk
      33             : //   the transition tree.
      34             : // - Merge/generalize the "updated" descriptor array of the |old_map| and
      35             : //   descriptor array of the |target_map|.
      36             : // - Generalize the |modify_index| descriptor using |new_representation| and
      37             : //   |new_field_type|.
      38             : // - Walk the tree again starting from the root towards |target_map|. Stop at
      39             : //   |split_map|, the first map who's descriptor array does not match the merged
      40             : //   descriptor array.
      41             : // - If |target_map| == |split_map|, |target_map| is in the expected state.
      42             : //   Return it.
      43             : // - Otherwise, invalidate the outdated transition target from |target_map|, and
      44             : //   replace its transition tree with a new branch for the updated descriptors.
      45             : class MapUpdater {
      46             :  public:
      47      792258 :   MapUpdater(Isolate* isolate, Handle<Map> old_map)
      48             :       : isolate_(isolate),
      49             :         old_map_(old_map),
      50             :         old_descriptors_(old_map->instance_descriptors(), isolate_),
      51             :         old_nof_(old_map_->NumberOfOwnDescriptors()),
      52             :         new_elements_kind_(old_map_->elements_kind()),
      53             :         is_transitionable_fast_elements_kind_(
      54     3169032 :             IsTransitionableFastElementsKind(new_elements_kind_)) {
      55             :     // We shouldn't try to update remote objects.
      56             :     DCHECK(!old_map->FindRootMap()->GetConstructor()->IsFunctionTemplateInfo());
      57      792258 :   }
      58             : 
      59             :   // Prepares for reconfiguring of a property at |descriptor| to data field
      60             :   // with given |attributes| and |representation|/|field_type| and
      61             :   // performs the steps 1-5.
      62             :   Handle<Map> ReconfigureToDataField(int descriptor,
      63             :                                      PropertyAttributes attributes,
      64             :                                      PropertyConstness constness,
      65             :                                      Representation representation,
      66             :                                      Handle<FieldType> field_type);
      67             : 
      68             :   // Prepares for reconfiguring elements kind and performs the steps 1-5.
      69             :   Handle<Map> ReconfigureElementsKind(ElementsKind elements_kind);
      70             : 
      71             :   // Prepares for updating deprecated map to most up-to-date non-deprecated
      72             :   // version and performs the steps 1-5.
      73             :   Handle<Map> Update();
      74             : 
      75             :  private:
      76             :   enum State { kInitialized, kAtRootMap, kAtTargetMap, kEnd };
      77             : 
      78             :   // Try to reconfigure property in-place without rebuilding transition tree
      79             :   // and creating new maps. See implementation for details.
      80             :   State TryRecofigureToDataFieldInplace();
      81             : 
      82             :   // Step 1.
      83             :   // - Search the root of the transition tree using FindRootMap.
      84             :   // - Find/create a |root_map_| with requested |new_elements_kind_|.
      85             :   State FindRootMap();
      86             : 
      87             :   // Step 2.
      88             :   // - Find |target_map_|, the newest matching version of this map using the
      89             :   //   "updated" |old_map|'s descriptor array (i.e. whose entry at
      90             :   //   |modified_descriptor_| is considered to be of |new_kind| and having
      91             :   //   |new_attributes|) to walk the transition tree.
      92             :   State FindTargetMap();
      93             : 
      94             :   // Step 3.
      95             :   // - Merge/generalize the "updated" descriptor array of the |old_map_| and
      96             :   //   descriptor array of the |target_map_|.
      97             :   // - Generalize the |modified_descriptor_| using |new_representation| and
      98             :   //   |new_field_type_|.
      99             :   Handle<DescriptorArray> BuildDescriptorArray();
     100             : 
     101             :   // Step 4.
     102             :   // - Walk the tree again starting from the root towards |target_map|. Stop at
     103             :   //   |split_map|, the first map who's descriptor array does not match the
     104             :   //   merged descriptor array.
     105             :   Handle<Map> FindSplitMap(Handle<DescriptorArray> descriptors);
     106             : 
     107             :   // Step 5.
     108             :   // - If |target_map| == |split_map|, |target_map| is in the expected state.
     109             :   //   Return it.
     110             :   // - Otherwise, invalidate the outdated transition target from |target_map|,
     111             :   //   and replace its transition tree with a new branch for the updated
     112             :   //   descriptors.
     113             :   State ConstructNewMap();
     114             : 
     115             :   // When a requested reconfiguration can not be done the result is a copy
     116             :   // of |old_map_| where every field has |Tagged| representation and |Any|
     117             :   // field type. This map is disconnected from the transition tree.
     118             :   State CopyGeneralizeAllFields(const char* reason);
     119             : 
     120             :   // Returns name of a |descriptor| property.
     121             :   inline Name* GetKey(int descriptor) const;
     122             : 
     123             :   // Returns property details of a |descriptor| in "updated" |old_descrtiptors_|
     124             :   // array.
     125             :   inline PropertyDetails GetDetails(int descriptor) const;
     126             : 
     127             :   // Returns value of a |descriptor| with kDescriptor location in "updated"
     128             :   // |old_descrtiptors_| array.
     129             :   inline Object* GetValue(int descriptor) const;
     130             : 
     131             :   // Returns field type for a |descriptor| with kField location in "updated"
     132             :   // |old_descrtiptors_| array.
     133             :   inline FieldType* GetFieldType(int descriptor) const;
     134             : 
     135             :   // If a |descriptor| property in "updated" |old_descriptors_| has kField
     136             :   // location then returns it's field type otherwise computes optimal field
     137             :   // type for the descriptor's value and |representation|. The |location|
     138             :   // value must be a pre-fetched location for |descriptor|.
     139             :   inline Handle<FieldType> GetOrComputeFieldType(
     140             :       int descriptor, PropertyLocation location,
     141             :       Representation representation) const;
     142             : 
     143             :   // If a |descriptor| property in given |descriptors| array has kField
     144             :   // location then returns it's field type otherwise computes optimal field
     145             :   // type for the descriptor's value and |representation|.
     146             :   // The |location| value must be a pre-fetched location for |descriptor|.
     147             :   inline Handle<FieldType> GetOrComputeFieldType(
     148             :       Handle<DescriptorArray> descriptors, int descriptor,
     149             :       PropertyLocation location, Representation representation);
     150             : 
     151             :   inline void GeneralizeIfTransitionableFastElementsKind(
     152             :       PropertyConstness* constness, Representation* representation,
     153             :       Handle<FieldType>* field_type);
     154             : 
     155             :   void GeneralizeField(Handle<Map> map, int modify_index,
     156             :                        PropertyConstness new_constness,
     157             :                        Representation new_representation,
     158             :                        Handle<FieldType> new_field_type);
     159             : 
     160             :   Isolate* isolate_;
     161             :   Handle<Map> old_map_;
     162             :   Handle<DescriptorArray> old_descriptors_;
     163             :   Handle<Map> root_map_;
     164             :   Handle<Map> target_map_;
     165             :   Handle<Map> result_map_;
     166             :   int old_nof_;
     167             : 
     168             :   State state_ = kInitialized;
     169             :   ElementsKind new_elements_kind_;
     170             :   bool is_transitionable_fast_elements_kind_;
     171             : 
     172             :   // If |modified_descriptor_| is not equal to -1 then the fields below form
     173             :   // an "update" of the |old_map_|'s descriptors.
     174             :   int modified_descriptor_ = -1;
     175             :   PropertyKind new_kind_ = kData;
     176             :   PropertyAttributes new_attributes_ = NONE;
     177             :   PropertyConstness new_constness_ = kMutable;
     178             :   PropertyLocation new_location_ = kField;
     179             :   Representation new_representation_ = Representation::None();
     180             : 
     181             :   // Data specific to kField location.
     182             :   Handle<FieldType> new_field_type_;
     183             : 
     184             :   // Data specific to kDescriptor location.
     185             :   Handle<Object> new_value_;
     186             : };
     187             : 
     188             : }  // namespace internal
     189             : }  // namespace v8
     190             : 
     191             : #endif  // V8_MAP_UPDATER_H_

Generated by: LCOV version 1.10