| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 #include "src/identity-map.h" | 42 #include "src/identity-map.h" |
| 43 #include "src/interpreter/bytecode-array-iterator.h" | 43 #include "src/interpreter/bytecode-array-iterator.h" |
| 44 #include "src/interpreter/bytecode-decoder.h" | 44 #include "src/interpreter/bytecode-decoder.h" |
| 45 #include "src/interpreter/interpreter.h" | 45 #include "src/interpreter/interpreter.h" |
| 46 #include "src/isolate-inl.h" | 46 #include "src/isolate-inl.h" |
| 47 #include "src/keys.h" | 47 #include "src/keys.h" |
| 48 #include "src/list.h" | 48 #include "src/list.h" |
| 49 #include "src/log.h" | 49 #include "src/log.h" |
| 50 #include "src/lookup.h" | 50 #include "src/lookup.h" |
| 51 #include "src/macro-assembler.h" | 51 #include "src/macro-assembler.h" |
| 52 #include "src/map-updater.h" |
| 52 #include "src/messages.h" | 53 #include "src/messages.h" |
| 53 #include "src/objects-body-descriptors-inl.h" | 54 #include "src/objects-body-descriptors-inl.h" |
| 54 #include "src/property-descriptor.h" | 55 #include "src/property-descriptor.h" |
| 55 #include "src/prototype.h" | 56 #include "src/prototype.h" |
| 56 #include "src/regexp/jsregexp.h" | 57 #include "src/regexp/jsregexp.h" |
| 57 #include "src/safepoint-table.h" | 58 #include "src/safepoint-table.h" |
| 58 #include "src/snapshot/code-serializer.h" | 59 #include "src/snapshot/code-serializer.h" |
| 59 #include "src/source-position-table.h" | 60 #include "src/source-position-table.h" |
| 60 #include "src/string-builder.h" | 61 #include "src/string-builder.h" |
| 61 #include "src/string-search.h" | 62 #include "src/string-search.h" |
| (...skipping 3257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3319 } else { | 3320 } else { |
| 3320 // Functions have null as a constructor, | 3321 // Functions have null as a constructor, |
| 3321 // but any JSFunction knows its context immediately. | 3322 // but any JSFunction knows its context immediately. |
| 3322 CHECK(receiver->IsJSFunction()); | 3323 CHECK(receiver->IsJSFunction()); |
| 3323 function = JSFunction::cast(receiver); | 3324 function = JSFunction::cast(receiver); |
| 3324 } | 3325 } |
| 3325 | 3326 |
| 3326 return function->context()->native_context(); | 3327 return function->context()->native_context(); |
| 3327 } | 3328 } |
| 3328 | 3329 |
| 3329 static Handle<Object> WrapType(Handle<FieldType> type) { | 3330 Handle<Object> Map::WrapType(Handle<FieldType> type) { |
| 3330 if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()); | 3331 if (type->IsClass()) return Map::WeakCellForMap(type->AsClass()); |
| 3331 return type; | 3332 return type; |
| 3332 } | 3333 } |
| 3333 | 3334 |
| 3334 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name, | 3335 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name, |
| 3335 Handle<FieldType> type, | 3336 Handle<FieldType> type, |
| 3336 PropertyAttributes attributes, | 3337 PropertyAttributes attributes, |
| 3337 Representation representation, | 3338 Representation representation, |
| 3338 TransitionFlag flag) { | 3339 TransitionFlag flag) { |
| 3339 DCHECK(DescriptorArray::kNotFound == | 3340 DCHECK(DescriptorArray::kNotFound == |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3962 for (int i = 0; i < num_transitions; ++i) { | 3963 for (int i = 0; i < num_transitions; ++i) { |
| 3963 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); | 3964 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); |
| 3964 } | 3965 } |
| 3965 deprecate(); | 3966 deprecate(); |
| 3966 dependent_code()->DeoptimizeDependentCodeGroup( | 3967 dependent_code()->DeoptimizeDependentCodeGroup( |
| 3967 GetIsolate(), DependentCode::kTransitionGroup); | 3968 GetIsolate(), DependentCode::kTransitionGroup); |
| 3968 NotifyLeafMapLayoutChange(); | 3969 NotifyLeafMapLayoutChange(); |
| 3969 } | 3970 } |
| 3970 | 3971 |
| 3971 | 3972 |
| 3972 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) { | |
| 3973 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds. | |
| 3974 // TODO(ishell): compare AccessorPairs. | |
| 3975 return false; | |
| 3976 } | |
| 3977 | |
| 3978 | |
| 3979 // Installs |new_descriptors| over the current instance_descriptors to ensure | 3973 // Installs |new_descriptors| over the current instance_descriptors to ensure |
| 3980 // proper sharing of descriptor arrays. | 3974 // proper sharing of descriptor arrays. |
| 3981 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors, | 3975 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors, |
| 3982 LayoutDescriptor* new_layout_descriptor) { | 3976 LayoutDescriptor* new_layout_descriptor) { |
| 3983 Isolate* isolate = GetIsolate(); | 3977 Isolate* isolate = GetIsolate(); |
| 3984 // Don't overwrite the empty descriptor array or initial map's descriptors. | 3978 // Don't overwrite the empty descriptor array or initial map's descriptors. |
| 3985 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) { | 3979 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) { |
| 3986 return; | 3980 return; |
| 3987 } | 3981 } |
| 3988 | 3982 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4011 DCHECK(result->owns_descriptors()); | 4005 DCHECK(result->owns_descriptors()); |
| 4012 DCHECK_EQ(result->NumberOfOwnDescriptors(), | 4006 DCHECK_EQ(result->NumberOfOwnDescriptors(), |
| 4013 result->instance_descriptors()->number_of_descriptors()); | 4007 result->instance_descriptors()->number_of_descriptors()); |
| 4014 return result; | 4008 return result; |
| 4015 } | 4009 } |
| 4016 result = Map::cast(back); | 4010 result = Map::cast(back); |
| 4017 } | 4011 } |
| 4018 } | 4012 } |
| 4019 | 4013 |
| 4020 | 4014 |
| 4021 Map* Map::FindLastMatchMap(int verbatim, | |
| 4022 int length, | |
| 4023 DescriptorArray* descriptors) { | |
| 4024 DisallowHeapAllocation no_allocation; | |
| 4025 | |
| 4026 // This can only be called on roots of transition trees. | |
| 4027 DCHECK_EQ(verbatim, NumberOfOwnDescriptors()); | |
| 4028 | |
| 4029 Map* current = this; | |
| 4030 | |
| 4031 for (int i = verbatim; i < length; i++) { | |
| 4032 Name* name = descriptors->GetKey(i); | |
| 4033 PropertyDetails details = descriptors->GetDetails(i); | |
| 4034 Map* next = TransitionArray::SearchTransition(current, details.kind(), name, | |
| 4035 details.attributes()); | |
| 4036 if (next == NULL) break; | |
| 4037 DescriptorArray* next_descriptors = next->instance_descriptors(); | |
| 4038 | |
| 4039 PropertyDetails next_details = next_descriptors->GetDetails(i); | |
| 4040 DCHECK_EQ(details.kind(), next_details.kind()); | |
| 4041 DCHECK_EQ(details.attributes(), next_details.attributes()); | |
| 4042 if (details.location() != next_details.location()) break; | |
| 4043 if (!details.representation().Equals(next_details.representation())) break; | |
| 4044 | |
| 4045 if (next_details.location() == kField) { | |
| 4046 FieldType* next_field_type = next_descriptors->GetFieldType(i); | |
| 4047 if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) { | |
| 4048 break; | |
| 4049 } | |
| 4050 } else { | |
| 4051 if (!EqualImmutableValues(descriptors->GetValue(i), | |
| 4052 next_descriptors->GetValue(i))) { | |
| 4053 break; | |
| 4054 } | |
| 4055 } | |
| 4056 current = next; | |
| 4057 } | |
| 4058 return current; | |
| 4059 } | |
| 4060 | |
| 4061 | |
| 4062 Map* Map::FindFieldOwner(int descriptor) { | 4015 Map* Map::FindFieldOwner(int descriptor) { |
| 4063 DisallowHeapAllocation no_allocation; | 4016 DisallowHeapAllocation no_allocation; |
| 4064 DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type()); | 4017 DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type()); |
| 4065 Map* result = this; | 4018 Map* result = this; |
| 4066 Isolate* isolate = GetIsolate(); | 4019 Isolate* isolate = GetIsolate(); |
| 4067 while (true) { | 4020 while (true) { |
| 4068 Object* back = result->GetBackPointer(); | 4021 Object* back = result->GetBackPointer(); |
| 4069 if (back->IsUndefined(isolate)) break; | 4022 if (back->IsUndefined(isolate)) break; |
| 4070 Map* parent = Map::cast(back); | 4023 Map* parent = Map::cast(back); |
| 4071 if (parent->NumberOfOwnDescriptors() <= descriptor) break; | 4024 if (parent->NumberOfOwnDescriptors() <= descriptor) break; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4132 if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) { | 4085 if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) { |
| 4133 return FieldType::Any(isolate); | 4086 return FieldType::Any(isolate); |
| 4134 } | 4087 } |
| 4135 if (type1->NowIs(type2)) return type2; | 4088 if (type1->NowIs(type2)) return type2; |
| 4136 if (type2->NowIs(type1)) return type1; | 4089 if (type2->NowIs(type1)) return type1; |
| 4137 return FieldType::Any(isolate); | 4090 return FieldType::Any(isolate); |
| 4138 } | 4091 } |
| 4139 | 4092 |
| 4140 | 4093 |
| 4141 // static | 4094 // static |
| 4142 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index, | 4095 void Map::GeneralizeField(Handle<Map> map, int modify_index, |
| 4143 Representation new_representation, | 4096 Representation new_representation, |
| 4144 Handle<FieldType> new_field_type) { | 4097 Handle<FieldType> new_field_type) { |
| 4145 Isolate* isolate = map->GetIsolate(); | 4098 Isolate* isolate = map->GetIsolate(); |
| 4146 | 4099 |
| 4147 // Check if we actually need to generalize the field type at all. | 4100 // Check if we actually need to generalize the field type at all. |
| 4148 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); | 4101 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); |
| 4149 Representation old_representation = | 4102 Representation old_representation = |
| 4150 old_descriptors->GetDetails(modify_index).representation(); | 4103 old_descriptors->GetDetails(modify_index).representation(); |
| 4151 Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index), | 4104 Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index), |
| 4152 isolate); | 4105 isolate); |
| 4153 | 4106 |
| 4154 if (old_representation.Equals(new_representation) && | 4107 if (old_representation.Equals(new_representation) && |
| 4155 !FieldTypeIsCleared(new_representation, *new_field_type) && | 4108 !FieldTypeIsCleared(new_representation, *new_field_type) && |
| 4156 // Checking old_field_type for being cleared is not necessary because | 4109 // Checking old_field_type for being cleared is not necessary because |
| 4157 // the NowIs check below would fail anyway in that case. | 4110 // the NowIs check below would fail anyway in that case. |
| 4158 new_field_type->NowIs(old_field_type)) { | 4111 new_field_type->NowIs(old_field_type)) { |
| 4159 DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type, | 4112 DCHECK(GeneralizeFieldType(old_representation, old_field_type, |
| 4160 new_representation, new_field_type, isolate) | 4113 new_representation, new_field_type, isolate) |
| 4161 ->NowIs(old_field_type)); | 4114 ->NowIs(old_field_type)); |
| 4162 return; | 4115 return; |
| 4163 } | 4116 } |
| 4164 | 4117 |
| 4165 // Determine the field owner. | 4118 // Determine the field owner. |
| 4166 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | 4119 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); |
| 4167 Handle<DescriptorArray> descriptors( | 4120 Handle<DescriptorArray> descriptors( |
| 4168 field_owner->instance_descriptors(), isolate); | 4121 field_owner->instance_descriptors(), isolate); |
| 4169 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); | 4122 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); |
| 4170 | 4123 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4183 | 4136 |
| 4184 if (FLAG_trace_generalization) { | 4137 if (FLAG_trace_generalization) { |
| 4185 map->PrintGeneralization( | 4138 map->PrintGeneralization( |
| 4186 stdout, "field type generalization", modify_index, | 4139 stdout, "field type generalization", modify_index, |
| 4187 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false, | 4140 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false, |
| 4188 details.representation(), details.representation(), old_field_type, | 4141 details.representation(), details.representation(), old_field_type, |
| 4189 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>()); | 4142 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>()); |
| 4190 } | 4143 } |
| 4191 } | 4144 } |
| 4192 | 4145 |
| 4193 static inline Handle<FieldType> GetFieldType( | 4146 // TODO(ishell): remove. |
| 4194 Isolate* isolate, Handle<DescriptorArray> descriptors, int descriptor, | 4147 // static |
| 4195 PropertyLocation location, Representation representation) { | 4148 Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index, |
| 4196 #ifdef DEBUG | 4149 PropertyKind new_kind, |
| 4197 PropertyDetails details = descriptors->GetDetails(descriptor); | 4150 PropertyAttributes new_attributes, |
| 4198 DCHECK_EQ(kData, details.kind()); | 4151 Representation new_representation, |
| 4199 DCHECK_EQ(details.location(), location); | 4152 Handle<FieldType> new_field_type, |
| 4200 #endif | 4153 StoreMode store_mode) { |
| 4201 if (location == kField) { | 4154 DCHECK_EQ(kData, new_kind); // Only kData case is supported. |
| 4202 return handle(descriptors->GetFieldType(descriptor), isolate); | 4155 MapUpdater mu(map->GetIsolate(), map); |
| 4203 } else { | 4156 return mu.ReconfigureToDataField(modify_index, new_attributes, |
| 4204 return descriptors->GetValue(descriptor) | 4157 new_representation, new_field_type); |
| 4205 ->OptimalType(isolate, representation); | |
| 4206 } | |
| 4207 } | 4158 } |
| 4208 | 4159 |
| 4209 // Reconfigures elements kind to |new_elements_kind| and/or property at | 4160 // TODO(ishell): remove. |
| 4210 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or | 4161 // static |
| 4211 // |new_representation|/|new_field_type|. | 4162 Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map, |
| 4212 // If |modify_index| is negative then no properties are reconfigured but the | 4163 ElementsKind new_elements_kind) { |
| 4213 // map is migrated to the up-to-date non-deprecated state. | 4164 MapUpdater mu(map->GetIsolate(), map); |
| 4214 // | 4165 return mu.ReconfigureElementsKind(new_elements_kind); |
| 4215 // This method rewrites or completes the transition tree to reflect the new | |
| 4216 // change. To avoid high degrees over polymorphism, and to stabilize quickly, | |
| 4217 // on every rewrite the new type is deduced by merging the current type with | |
| 4218 // any potential new (partial) version of the type in the transition tree. | |
| 4219 // To do this, on each rewrite: | |
| 4220 // - Search the root of the transition tree using FindRootMap. | |
| 4221 // - Find/create a |root_map| with requested |new_elements_kind|. | |
| 4222 // - Find |target_map|, the newest matching version of this map using the | |
| 4223 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at | |
| 4224 // |modify_index| is considered to be of |new_kind| and having | |
| 4225 // |new_attributes|) to walk the transition tree. | |
| 4226 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and | |
| 4227 // descriptor array of the |target_map|. | |
| 4228 // - Generalize the |modify_index| descriptor using |new_representation| and | |
| 4229 // |new_field_type|. | |
| 4230 // - Walk the tree again starting from the root towards |target_map|. Stop at | |
| 4231 // |split_map|, the first map who's descriptor array does not match the merged | |
| 4232 // descriptor array. | |
| 4233 // - If |target_map| == |split_map|, |target_map| is in the expected state. | |
| 4234 // Return it. | |
| 4235 // - Otherwise, invalidate the outdated transition target from |target_map|, and | |
| 4236 // replace its transition tree with a new branch for the updated descriptors. | |
| 4237 Handle<Map> Map::Reconfigure(Handle<Map> old_map, | |
| 4238 ElementsKind new_elements_kind, int modify_index, | |
| 4239 PropertyKind new_kind, | |
| 4240 PropertyAttributes new_attributes, | |
| 4241 Representation new_representation, | |
| 4242 Handle<FieldType> new_field_type, | |
| 4243 StoreMode store_mode) { | |
| 4244 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. | |
| 4245 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); | |
| 4246 Isolate* isolate = old_map->GetIsolate(); | |
| 4247 | |
| 4248 Handle<DescriptorArray> old_descriptors( | |
| 4249 old_map->instance_descriptors(), isolate); | |
| 4250 int old_nof = old_map->NumberOfOwnDescriptors(); | |
| 4251 | |
| 4252 // If it's just a representation generalization case (i.e. property kind and | |
| 4253 // attributes stays unchanged) it's fine to transition from None to anything | |
| 4254 // but double without any modification to the object, because the default | |
| 4255 // uninitialized value for representation None can be overwritten by both | |
| 4256 // smi and tagged values. Doubles, however, would require a box allocation. | |
| 4257 if (modify_index >= 0 && !new_representation.IsNone() && | |
| 4258 !new_representation.IsDouble() && | |
| 4259 old_map->elements_kind() == new_elements_kind) { | |
| 4260 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 4261 Representation old_representation = old_details.representation(); | |
| 4262 | |
| 4263 if (old_representation.IsNone()) { | |
| 4264 DCHECK_EQ(new_kind, old_details.kind()); | |
| 4265 DCHECK_EQ(new_attributes, old_details.attributes()); | |
| 4266 DCHECK_EQ(DATA, old_details.type()); | |
| 4267 if (FLAG_trace_generalization) { | |
| 4268 old_map->PrintGeneralization( | |
| 4269 stdout, "uninitialized field", modify_index, | |
| 4270 old_map->NumberOfOwnDescriptors(), | |
| 4271 old_map->NumberOfOwnDescriptors(), false, old_representation, | |
| 4272 new_representation, | |
| 4273 handle(old_descriptors->GetFieldType(modify_index), isolate), | |
| 4274 MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>()); | |
| 4275 } | |
| 4276 Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate); | |
| 4277 | |
| 4278 GeneralizeFieldType(field_owner, modify_index, new_representation, | |
| 4279 new_field_type); | |
| 4280 DCHECK(old_descriptors->GetDetails(modify_index) | |
| 4281 .representation() | |
| 4282 .Equals(new_representation)); | |
| 4283 DCHECK( | |
| 4284 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); | |
| 4285 return old_map; | |
| 4286 } | |
| 4287 } | |
| 4288 | |
| 4289 // Check the state of the root map. | |
| 4290 Handle<Map> root_map(old_map->FindRootMap(), isolate); | |
| 4291 if (!old_map->EquivalentToForTransition(*root_map)) { | |
| 4292 return CopyGeneralizeAllRepresentations( | |
| 4293 old_map, new_elements_kind, modify_index, store_mode, new_kind, | |
| 4294 new_attributes, "GenAll_NotEquivalent"); | |
| 4295 } | |
| 4296 | |
| 4297 ElementsKind from_kind = root_map->elements_kind(); | |
| 4298 ElementsKind to_kind = new_elements_kind; | |
| 4299 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. | |
| 4300 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && | |
| 4301 to_kind != SLOW_STRING_WRAPPER_ELEMENTS && | |
| 4302 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && | |
| 4303 !(IsTransitionableFastElementsKind(from_kind) && | |
| 4304 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { | |
| 4305 return CopyGeneralizeAllRepresentations( | |
| 4306 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4307 "GenAll_InvalidElementsTransition"); | |
| 4308 } | |
| 4309 int root_nof = root_map->NumberOfOwnDescriptors(); | |
| 4310 if (modify_index >= 0 && modify_index < root_nof) { | |
| 4311 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 4312 if (old_details.kind() != new_kind || | |
| 4313 old_details.attributes() != new_attributes) { | |
| 4314 return CopyGeneralizeAllRepresentations( | |
| 4315 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4316 "GenAll_RootModification1"); | |
| 4317 } | |
| 4318 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || | |
| 4319 (old_details.type() == DATA && | |
| 4320 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || | |
| 4321 !new_representation.fits_into(old_details.representation())))) { | |
| 4322 return CopyGeneralizeAllRepresentations( | |
| 4323 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4324 "GenAll_RootModification2"); | |
| 4325 } | |
| 4326 } | |
| 4327 | |
| 4328 // From here on, use the map with correct elements kind as root map. | |
| 4329 if (from_kind != to_kind) { | |
| 4330 root_map = Map::AsElementsKind(root_map, to_kind); | |
| 4331 } | |
| 4332 | |
| 4333 Handle<Map> target_map = root_map; | |
| 4334 for (int i = root_nof; i < old_nof; ++i) { | |
| 4335 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
| 4336 PropertyKind next_kind; | |
| 4337 PropertyLocation next_location; | |
| 4338 PropertyAttributes next_attributes; | |
| 4339 Representation next_representation; | |
| 4340 bool property_kind_reconfiguration = false; | |
| 4341 | |
| 4342 if (modify_index == i) { | |
| 4343 DCHECK_EQ(FORCE_FIELD, store_mode); | |
| 4344 property_kind_reconfiguration = old_details.kind() != new_kind; | |
| 4345 | |
| 4346 next_kind = new_kind; | |
| 4347 next_location = kField; | |
| 4348 next_attributes = new_attributes; | |
| 4349 // If property kind is not reconfigured merge the result with | |
| 4350 // representation/field type from the old descriptor. | |
| 4351 next_representation = new_representation; | |
| 4352 if (!property_kind_reconfiguration) { | |
| 4353 next_representation = | |
| 4354 next_representation.generalize(old_details.representation()); | |
| 4355 } | |
| 4356 | |
| 4357 } else { | |
| 4358 next_kind = old_details.kind(); | |
| 4359 next_location = old_details.location(); | |
| 4360 next_attributes = old_details.attributes(); | |
| 4361 next_representation = old_details.representation(); | |
| 4362 } | |
| 4363 Map* transition = TransitionArray::SearchTransition( | |
| 4364 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); | |
| 4365 if (transition == NULL) break; | |
| 4366 Handle<Map> tmp_map(transition, isolate); | |
| 4367 | |
| 4368 Handle<DescriptorArray> tmp_descriptors = handle( | |
| 4369 tmp_map->instance_descriptors(), isolate); | |
| 4370 | |
| 4371 // Check if target map is incompatible. | |
| 4372 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | |
| 4373 DCHECK_EQ(next_kind, tmp_details.kind()); | |
| 4374 DCHECK_EQ(next_attributes, tmp_details.attributes()); | |
| 4375 if (next_kind == kAccessor && | |
| 4376 !EqualImmutableValues(old_descriptors->GetValue(i), | |
| 4377 tmp_descriptors->GetValue(i))) { | |
| 4378 return CopyGeneralizeAllRepresentations( | |
| 4379 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4380 "GenAll_Incompatible"); | |
| 4381 } | |
| 4382 if (next_location == kField && tmp_details.location() == kDescriptor) break; | |
| 4383 | |
| 4384 Representation tmp_representation = tmp_details.representation(); | |
| 4385 if (!next_representation.fits_into(tmp_representation)) break; | |
| 4386 | |
| 4387 PropertyLocation old_location = old_details.location(); | |
| 4388 PropertyLocation tmp_location = tmp_details.location(); | |
| 4389 if (tmp_location == kField) { | |
| 4390 if (next_kind == kData) { | |
| 4391 Handle<FieldType> next_field_type; | |
| 4392 if (modify_index == i) { | |
| 4393 next_field_type = new_field_type; | |
| 4394 if (!property_kind_reconfiguration) { | |
| 4395 Handle<FieldType> old_field_type = | |
| 4396 GetFieldType(isolate, old_descriptors, i, | |
| 4397 old_details.location(), tmp_representation); | |
| 4398 Representation old_representation = old_details.representation(); | |
| 4399 next_field_type = GeneralizeFieldType( | |
| 4400 old_representation, old_field_type, new_representation, | |
| 4401 next_field_type, isolate); | |
| 4402 } | |
| 4403 } else { | |
| 4404 Handle<FieldType> old_field_type = | |
| 4405 GetFieldType(isolate, old_descriptors, i, old_details.location(), | |
| 4406 tmp_representation); | |
| 4407 next_field_type = old_field_type; | |
| 4408 } | |
| 4409 GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type); | |
| 4410 } | |
| 4411 } else if (old_location == kField || | |
| 4412 !EqualImmutableValues(old_descriptors->GetValue(i), | |
| 4413 tmp_descriptors->GetValue(i))) { | |
| 4414 break; | |
| 4415 } | |
| 4416 DCHECK(!tmp_map->is_deprecated()); | |
| 4417 target_map = tmp_map; | |
| 4418 } | |
| 4419 | |
| 4420 // Directly change the map if the target map is more general. | |
| 4421 Handle<DescriptorArray> target_descriptors( | |
| 4422 target_map->instance_descriptors(), isolate); | |
| 4423 int target_nof = target_map->NumberOfOwnDescriptors(); | |
| 4424 if (target_nof == old_nof && | |
| 4425 (store_mode != FORCE_FIELD || | |
| 4426 (modify_index >= 0 && | |
| 4427 target_descriptors->GetDetails(modify_index).location() == kField))) { | |
| 4428 #ifdef DEBUG | |
| 4429 if (modify_index >= 0) { | |
| 4430 PropertyDetails details = target_descriptors->GetDetails(modify_index); | |
| 4431 DCHECK_EQ(new_kind, details.kind()); | |
| 4432 DCHECK_EQ(new_attributes, details.attributes()); | |
| 4433 DCHECK(new_representation.fits_into(details.representation())); | |
| 4434 DCHECK(details.location() != kField || | |
| 4435 new_field_type->NowIs( | |
| 4436 target_descriptors->GetFieldType(modify_index))); | |
| 4437 } | |
| 4438 #endif | |
| 4439 if (*target_map != *old_map) { | |
| 4440 old_map->NotifyLeafMapLayoutChange(); | |
| 4441 } | |
| 4442 return target_map; | |
| 4443 } | |
| 4444 | |
| 4445 // Find the last compatible target map in the transition tree. | |
| 4446 for (int i = target_nof; i < old_nof; ++i) { | |
| 4447 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
| 4448 PropertyKind next_kind; | |
| 4449 PropertyAttributes next_attributes; | |
| 4450 if (modify_index == i) { | |
| 4451 next_kind = new_kind; | |
| 4452 next_attributes = new_attributes; | |
| 4453 } else { | |
| 4454 next_kind = old_details.kind(); | |
| 4455 next_attributes = old_details.attributes(); | |
| 4456 } | |
| 4457 Map* transition = TransitionArray::SearchTransition( | |
| 4458 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); | |
| 4459 if (transition == NULL) break; | |
| 4460 Handle<Map> tmp_map(transition, isolate); | |
| 4461 Handle<DescriptorArray> tmp_descriptors( | |
| 4462 tmp_map->instance_descriptors(), isolate); | |
| 4463 | |
| 4464 // Check if target map is compatible. | |
| 4465 #ifdef DEBUG | |
| 4466 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | |
| 4467 DCHECK_EQ(next_kind, tmp_details.kind()); | |
| 4468 DCHECK_EQ(next_attributes, tmp_details.attributes()); | |
| 4469 #endif | |
| 4470 if (next_kind == kAccessor && | |
| 4471 !EqualImmutableValues(old_descriptors->GetValue(i), | |
| 4472 tmp_descriptors->GetValue(i))) { | |
| 4473 return CopyGeneralizeAllRepresentations( | |
| 4474 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4475 "GenAll_Incompatible"); | |
| 4476 } | |
| 4477 DCHECK(!tmp_map->is_deprecated()); | |
| 4478 target_map = tmp_map; | |
| 4479 } | |
| 4480 target_nof = target_map->NumberOfOwnDescriptors(); | |
| 4481 target_descriptors = handle(target_map->instance_descriptors(), isolate); | |
| 4482 | |
| 4483 // Allocate a new descriptor array large enough to hold the required | |
| 4484 // descriptors, with minimally the exact same size as the old descriptor | |
| 4485 // array. | |
| 4486 int new_slack = Max( | |
| 4487 old_nof, old_descriptors->number_of_descriptors()) - old_nof; | |
| 4488 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( | |
| 4489 isolate, old_nof, new_slack); | |
| 4490 DCHECK(new_descriptors->length() > target_descriptors->length() || | |
| 4491 new_descriptors->NumberOfSlackDescriptors() > 0 || | |
| 4492 new_descriptors->number_of_descriptors() == | |
| 4493 old_descriptors->number_of_descriptors()); | |
| 4494 DCHECK(new_descriptors->number_of_descriptors() == old_nof); | |
| 4495 | |
| 4496 // 0 -> |root_nof| | |
| 4497 int current_offset = 0; | |
| 4498 for (int i = 0; i < root_nof; ++i) { | |
| 4499 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
| 4500 if (old_details.location() == kField) { | |
| 4501 current_offset += old_details.field_width_in_words(); | |
| 4502 } | |
| 4503 Descriptor d(handle(old_descriptors->GetKey(i), isolate), | |
| 4504 handle(old_descriptors->GetValue(i), isolate), | |
| 4505 old_details); | |
| 4506 new_descriptors->Set(i, &d); | |
| 4507 } | |
| 4508 | |
| 4509 // |root_nof| -> |target_nof| | |
| 4510 for (int i = root_nof; i < target_nof; ++i) { | |
| 4511 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); | |
| 4512 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
| 4513 PropertyDetails target_details = target_descriptors->GetDetails(i); | |
| 4514 | |
| 4515 PropertyKind next_kind; | |
| 4516 PropertyAttributes next_attributes; | |
| 4517 PropertyLocation next_location; | |
| 4518 Representation next_representation; | |
| 4519 bool property_kind_reconfiguration = false; | |
| 4520 | |
| 4521 if (modify_index == i) { | |
| 4522 DCHECK_EQ(FORCE_FIELD, store_mode); | |
| 4523 property_kind_reconfiguration = old_details.kind() != new_kind; | |
| 4524 | |
| 4525 next_kind = new_kind; | |
| 4526 next_attributes = new_attributes; | |
| 4527 next_location = kField; | |
| 4528 | |
| 4529 // Merge new representation/field type with ones from the target | |
| 4530 // descriptor. If property kind is not reconfigured merge the result with | |
| 4531 // representation/field type from the old descriptor. | |
| 4532 next_representation = | |
| 4533 new_representation.generalize(target_details.representation()); | |
| 4534 if (!property_kind_reconfiguration) { | |
| 4535 next_representation = | |
| 4536 next_representation.generalize(old_details.representation()); | |
| 4537 } | |
| 4538 } else { | |
| 4539 // Merge old_descriptor and target_descriptor entries. | |
| 4540 DCHECK_EQ(target_details.kind(), old_details.kind()); | |
| 4541 next_kind = target_details.kind(); | |
| 4542 next_attributes = target_details.attributes(); | |
| 4543 next_location = | |
| 4544 old_details.location() == kField || | |
| 4545 target_details.location() == kField || | |
| 4546 !EqualImmutableValues(target_descriptors->GetValue(i), | |
| 4547 old_descriptors->GetValue(i)) | |
| 4548 ? kField | |
| 4549 : kDescriptor; | |
| 4550 | |
| 4551 next_representation = old_details.representation().generalize( | |
| 4552 target_details.representation()); | |
| 4553 } | |
| 4554 DCHECK_EQ(next_kind, target_details.kind()); | |
| 4555 DCHECK_EQ(next_attributes, target_details.attributes()); | |
| 4556 | |
| 4557 if (next_location == kField) { | |
| 4558 if (next_kind == kData) { | |
| 4559 Handle<FieldType> target_field_type = | |
| 4560 GetFieldType(isolate, target_descriptors, i, | |
| 4561 target_details.location(), next_representation); | |
| 4562 | |
| 4563 Handle<FieldType> next_field_type; | |
| 4564 if (modify_index == i) { | |
| 4565 next_field_type = GeneralizeFieldType( | |
| 4566 target_details.representation(), target_field_type, | |
| 4567 new_representation, new_field_type, isolate); | |
| 4568 if (!property_kind_reconfiguration) { | |
| 4569 Handle<FieldType> old_field_type = | |
| 4570 GetFieldType(isolate, old_descriptors, i, | |
| 4571 old_details.location(), next_representation); | |
| 4572 next_field_type = GeneralizeFieldType( | |
| 4573 old_details.representation(), old_field_type, | |
| 4574 next_representation, next_field_type, isolate); | |
| 4575 } | |
| 4576 } else { | |
| 4577 Handle<FieldType> old_field_type = | |
| 4578 GetFieldType(isolate, old_descriptors, i, old_details.location(), | |
| 4579 next_representation); | |
| 4580 next_field_type = GeneralizeFieldType( | |
| 4581 old_details.representation(), old_field_type, next_representation, | |
| 4582 target_field_type, isolate); | |
| 4583 } | |
| 4584 Handle<Object> wrapped_type(WrapType(next_field_type)); | |
| 4585 Descriptor d = | |
| 4586 Descriptor::DataField(target_key, current_offset, wrapped_type, | |
| 4587 next_attributes, next_representation); | |
| 4588 current_offset += d.GetDetails().field_width_in_words(); | |
| 4589 new_descriptors->Set(i, &d); | |
| 4590 } else { | |
| 4591 UNIMPLEMENTED(); // TODO(ishell): implement. | |
| 4592 } | |
| 4593 } else { | |
| 4594 PropertyDetails details(next_attributes, next_kind, next_location, | |
| 4595 next_representation); | |
| 4596 Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate), | |
| 4597 details); | |
| 4598 new_descriptors->Set(i, &d); | |
| 4599 } | |
| 4600 } | |
| 4601 | |
| 4602 // |target_nof| -> |old_nof| | |
| 4603 for (int i = target_nof; i < old_nof; ++i) { | |
| 4604 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
| 4605 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); | |
| 4606 | |
| 4607 // Merge old_descriptor entry and modified details together. | |
| 4608 PropertyKind next_kind; | |
| 4609 PropertyAttributes next_attributes; | |
| 4610 PropertyLocation next_location; | |
| 4611 Representation next_representation; | |
| 4612 bool property_kind_reconfiguration = false; | |
| 4613 | |
| 4614 if (modify_index == i) { | |
| 4615 DCHECK_EQ(FORCE_FIELD, store_mode); | |
| 4616 // In case of property kind reconfiguration it is not necessary to | |
| 4617 // take into account representation/field type of the old descriptor. | |
| 4618 property_kind_reconfiguration = old_details.kind() != new_kind; | |
| 4619 | |
| 4620 next_kind = new_kind; | |
| 4621 next_attributes = new_attributes; | |
| 4622 next_location = kField; | |
| 4623 next_representation = new_representation; | |
| 4624 if (!property_kind_reconfiguration) { | |
| 4625 next_representation = | |
| 4626 next_representation.generalize(old_details.representation()); | |
| 4627 } | |
| 4628 } else { | |
| 4629 next_kind = old_details.kind(); | |
| 4630 next_attributes = old_details.attributes(); | |
| 4631 next_location = old_details.location(); | |
| 4632 next_representation = old_details.representation(); | |
| 4633 } | |
| 4634 | |
| 4635 if (next_location == kField) { | |
| 4636 if (next_kind == kData) { | |
| 4637 Handle<FieldType> next_field_type; | |
| 4638 if (modify_index == i) { | |
| 4639 next_field_type = new_field_type; | |
| 4640 if (!property_kind_reconfiguration) { | |
| 4641 Handle<FieldType> old_field_type = | |
| 4642 GetFieldType(isolate, old_descriptors, i, | |
| 4643 old_details.location(), next_representation); | |
| 4644 next_field_type = GeneralizeFieldType( | |
| 4645 old_details.representation(), old_field_type, | |
| 4646 next_representation, next_field_type, isolate); | |
| 4647 } | |
| 4648 } else { | |
| 4649 Handle<FieldType> old_field_type = | |
| 4650 GetFieldType(isolate, old_descriptors, i, old_details.location(), | |
| 4651 next_representation); | |
| 4652 next_field_type = old_field_type; | |
| 4653 } | |
| 4654 | |
| 4655 Handle<Object> wrapped_type(WrapType(next_field_type)); | |
| 4656 | |
| 4657 Descriptor d = | |
| 4658 Descriptor::DataField(old_key, current_offset, wrapped_type, | |
| 4659 next_attributes, next_representation); | |
| 4660 current_offset += d.GetDetails().field_width_in_words(); | |
| 4661 new_descriptors->Set(i, &d); | |
| 4662 } else { | |
| 4663 UNIMPLEMENTED(); // TODO(ishell): implement. | |
| 4664 } | |
| 4665 } else { | |
| 4666 PropertyDetails details(next_attributes, next_kind, next_location, | |
| 4667 next_representation); | |
| 4668 Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate), | |
| 4669 details); | |
| 4670 new_descriptors->Set(i, &d); | |
| 4671 } | |
| 4672 } | |
| 4673 | |
| 4674 new_descriptors->Sort(); | |
| 4675 | |
| 4676 DCHECK(store_mode != FORCE_FIELD || | |
| 4677 new_descriptors->GetDetails(modify_index).location() == kField); | |
| 4678 | |
| 4679 Handle<Map> split_map(root_map->FindLastMatchMap( | |
| 4680 root_nof, old_nof, *new_descriptors), isolate); | |
| 4681 int split_nof = split_map->NumberOfOwnDescriptors(); | |
| 4682 DCHECK_NE(old_nof, split_nof); | |
| 4683 | |
| 4684 PropertyKind split_kind; | |
| 4685 PropertyAttributes split_attributes; | |
| 4686 if (modify_index == split_nof) { | |
| 4687 split_kind = new_kind; | |
| 4688 split_attributes = new_attributes; | |
| 4689 } else { | |
| 4690 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); | |
| 4691 split_kind = split_prop_details.kind(); | |
| 4692 split_attributes = split_prop_details.attributes(); | |
| 4693 } | |
| 4694 | |
| 4695 // Invalidate a transition target at |key|. | |
| 4696 Map* maybe_transition = TransitionArray::SearchTransition( | |
| 4697 *split_map, split_kind, old_descriptors->GetKey(split_nof), | |
| 4698 split_attributes); | |
| 4699 if (maybe_transition != NULL) { | |
| 4700 maybe_transition->DeprecateTransitionTree(); | |
| 4701 } | |
| 4702 | |
| 4703 // If |maybe_transition| is not NULL then the transition array already | |
| 4704 // contains entry for given descriptor. This means that the transition | |
| 4705 // could be inserted regardless of whether transitions array is full or not. | |
| 4706 if (maybe_transition == NULL && | |
| 4707 !TransitionArray::CanHaveMoreTransitions(split_map)) { | |
| 4708 return CopyGeneralizeAllRepresentations( | |
| 4709 old_map, to_kind, modify_index, store_mode, new_kind, new_attributes, | |
| 4710 "GenAll_CantHaveMoreTransitions"); | |
| 4711 } | |
| 4712 | |
| 4713 old_map->NotifyLeafMapLayoutChange(); | |
| 4714 | |
| 4715 if (FLAG_trace_generalization && modify_index >= 0) { | |
| 4716 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 4717 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | |
| 4718 MaybeHandle<FieldType> old_field_type; | |
| 4719 MaybeHandle<FieldType> new_field_type; | |
| 4720 MaybeHandle<Object> old_value; | |
| 4721 MaybeHandle<Object> new_value; | |
| 4722 if (old_details.type() == DATA) { | |
| 4723 old_field_type = | |
| 4724 handle(old_descriptors->GetFieldType(modify_index), isolate); | |
| 4725 } else { | |
| 4726 old_value = handle(old_descriptors->GetValue(modify_index), isolate); | |
| 4727 } | |
| 4728 if (new_details.type() == DATA) { | |
| 4729 new_field_type = | |
| 4730 handle(new_descriptors->GetFieldType(modify_index), isolate); | |
| 4731 } else { | |
| 4732 new_value = handle(new_descriptors->GetValue(modify_index), isolate); | |
| 4733 } | |
| 4734 | |
| 4735 old_map->PrintGeneralization( | |
| 4736 stdout, "", modify_index, split_nof, old_nof, | |
| 4737 old_details.location() == kDescriptor && store_mode == FORCE_FIELD, | |
| 4738 old_details.representation(), new_details.representation(), | |
| 4739 old_field_type, old_value, new_field_type, new_value); | |
| 4740 } | |
| 4741 | |
| 4742 Handle<LayoutDescriptor> new_layout_descriptor = | |
| 4743 LayoutDescriptor::New(split_map, new_descriptors, old_nof); | |
| 4744 | |
| 4745 Handle<Map> new_map = | |
| 4746 AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor); | |
| 4747 | |
| 4748 // Deprecated part of the transition tree is no longer reachable, so replace | |
| 4749 // current instance descriptors in the "survived" part of the tree with | |
| 4750 // the new descriptors to maintain descriptors sharing invariant. | |
| 4751 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor); | |
| 4752 return new_map; | |
| 4753 } | 4166 } |
| 4754 | 4167 |
| 4755 | |
| 4756 // Generalize the representation of all DATA descriptors. | 4168 // Generalize the representation of all DATA descriptors. |
| 4757 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 4169 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
| 4758 Handle<Map> map) { | 4170 Handle<Map> map) { |
| 4171 Isolate* isolate = map->GetIsolate(); |
| 4172 Handle<FieldType> any_type = FieldType::Any(isolate); |
| 4173 |
| 4759 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 4174 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 4760 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { | 4175 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { |
| 4761 PropertyDetails details = descriptors->GetDetails(i); | 4176 PropertyDetails details = descriptors->GetDetails(i); |
| 4762 if (details.type() == DATA) { | 4177 if (details.type() == DATA) { |
| 4763 map = ReconfigureProperty(map, i, kData, details.attributes(), | 4178 MapUpdater mu(isolate, map); |
| 4764 Representation::Tagged(), | 4179 map = mu.ReconfigureToDataField(i, details.attributes(), |
| 4765 FieldType::Any(map->GetIsolate()), FORCE_FIELD); | 4180 Representation::Tagged(), any_type); |
| 4766 } | 4181 } |
| 4767 } | 4182 } |
| 4768 return map; | 4183 return map; |
| 4769 } | 4184 } |
| 4770 | 4185 |
| 4771 | 4186 |
| 4772 // static | 4187 // static |
| 4773 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) { | 4188 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) { |
| 4774 DisallowHeapAllocation no_allocation; | 4189 DisallowHeapAllocation no_allocation; |
| 4775 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); | 4190 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4862 } | 4277 } |
| 4863 } | 4278 } |
| 4864 if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr; | 4279 if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr; |
| 4865 return new_map; | 4280 return new_map; |
| 4866 } | 4281 } |
| 4867 | 4282 |
| 4868 | 4283 |
| 4869 // static | 4284 // static |
| 4870 Handle<Map> Map::Update(Handle<Map> map) { | 4285 Handle<Map> Map::Update(Handle<Map> map) { |
| 4871 if (!map->is_deprecated()) return map; | 4286 if (!map->is_deprecated()) return map; |
| 4872 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), | 4287 MapUpdater mu(map->GetIsolate(), map); |
| 4873 FieldType::None(map->GetIsolate()), | 4288 return mu.Update(); |
| 4874 ALLOW_IN_DESCRIPTOR); | |
| 4875 } | 4289 } |
| 4876 | 4290 |
| 4877 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, | 4291 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| 4878 ShouldThrow should_throw, | 4292 ShouldThrow should_throw, |
| 4879 Handle<Object> value) { | 4293 Handle<Object> value) { |
| 4880 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 4294 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
| 4881 return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(), | 4295 return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(), |
| 4882 should_throw, value); | 4296 should_throw, value); |
| 4883 } | 4297 } |
| 4884 | 4298 |
| (...skipping 4861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9746 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, | 9160 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor, |
| 9747 Handle<Object> value) { | 9161 Handle<Object> value) { |
| 9748 if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map; | 9162 if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map; |
| 9749 | 9163 |
| 9750 Isolate* isolate = map->GetIsolate(); | 9164 Isolate* isolate = map->GetIsolate(); |
| 9751 PropertyAttributes attributes = | 9165 PropertyAttributes attributes = |
| 9752 map->instance_descriptors()->GetDetails(descriptor).attributes(); | 9166 map->instance_descriptors()->GetDetails(descriptor).attributes(); |
| 9753 Representation representation = value->OptimalRepresentation(); | 9167 Representation representation = value->OptimalRepresentation(); |
| 9754 Handle<FieldType> type = value->OptimalType(isolate, representation); | 9168 Handle<FieldType> type = value->OptimalType(isolate, representation); |
| 9755 | 9169 |
| 9756 return Map::ReconfigureProperty(map, descriptor, kData, attributes, | 9170 MapUpdater mu(isolate, map); |
| 9757 representation, type, FORCE_FIELD); | 9171 return mu.ReconfigureToDataField(descriptor, attributes, representation, |
| 9172 type); |
| 9758 } | 9173 } |
| 9759 | 9174 |
| 9760 } // namespace | 9175 } // namespace |
| 9761 | 9176 |
| 9762 // static | 9177 // static |
| 9763 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, | 9178 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, |
| 9764 Handle<Object> value) { | 9179 Handle<Object> value) { |
| 9765 // Dictionaries can store any property value. | 9180 // Dictionaries can store any property value. |
| 9766 DCHECK(!map->is_dictionary_map()); | 9181 DCHECK(!map->is_dictionary_map()); |
| 9767 // Update to the newest map before storing the property. | 9182 // Update to the newest map before storing the property. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9840 return CopyGeneralizeAllRepresentations( | 9255 return CopyGeneralizeAllRepresentations( |
| 9841 map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes, | 9256 map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes, |
| 9842 "GenAll_AttributesMismatchProtoMap"); | 9257 "GenAll_AttributesMismatchProtoMap"); |
| 9843 } | 9258 } |
| 9844 | 9259 |
| 9845 if (FLAG_trace_generalization) { | 9260 if (FLAG_trace_generalization) { |
| 9846 map->PrintReconfiguration(stdout, descriptor, kind, attributes); | 9261 map->PrintReconfiguration(stdout, descriptor, kind, attributes); |
| 9847 } | 9262 } |
| 9848 | 9263 |
| 9849 Isolate* isolate = map->GetIsolate(); | 9264 Isolate* isolate = map->GetIsolate(); |
| 9850 Handle<Map> new_map = ReconfigureProperty( | 9265 |
| 9851 map, descriptor, kind, attributes, Representation::None(), | 9266 MapUpdater mu(isolate, map); |
| 9852 FieldType::None(isolate), FORCE_FIELD); | 9267 DCHECK_EQ(kData, kind); // Only kData case is supported so far. |
| 9268 Handle<Map> new_map = mu.ReconfigureToDataField( |
| 9269 descriptor, attributes, Representation::None(), FieldType::None(isolate)); |
| 9853 return new_map; | 9270 return new_map; |
| 9854 } | 9271 } |
| 9855 | 9272 |
| 9856 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map, | 9273 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map, |
| 9857 Handle<Name> name, int descriptor, | 9274 Handle<Name> name, int descriptor, |
| 9858 Handle<Object> getter, | 9275 Handle<Object> getter, |
| 9859 Handle<Object> setter, | 9276 Handle<Object> setter, |
| 9860 PropertyAttributes attributes) { | 9277 PropertyAttributes attributes) { |
| 9861 RuntimeCallTimerScope stats_scope( | 9278 RuntimeCallTimerScope stats_scope( |
| 9862 isolate, | 9279 isolate, |
| (...skipping 10628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20491 // depend on this. | 19908 // depend on this. |
| 20492 return DICTIONARY_ELEMENTS; | 19909 return DICTIONARY_ELEMENTS; |
| 20493 } | 19910 } |
| 20494 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 19911 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20495 return kind; | 19912 return kind; |
| 20496 } | 19913 } |
| 20497 } | 19914 } |
| 20498 | 19915 |
| 20499 } // namespace internal | 19916 } // namespace internal |
| 20500 } // namespace v8 | 19917 } // namespace v8 |
| OLD | NEW |