Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: src/objects.cc

Issue 2601643002: [runtime] Add MapUpdater class that manages all kinds of map updates. (Closed)
Patch Set: Addressing comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698