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