OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 2056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2067 DCHECK(target_inobject < inobject_properties()); | 2067 DCHECK(target_inobject < inobject_properties()); |
2068 if (target_number_of_fields <= target_inobject) { | 2068 if (target_number_of_fields <= target_inobject) { |
2069 DCHECK(target_number_of_fields + target_unused == target_inobject); | 2069 DCHECK(target_number_of_fields + target_unused == target_inobject); |
2070 return false; | 2070 return false; |
2071 } | 2071 } |
2072 // Otherwise, properties will need to be moved to the backing store. | 2072 // Otherwise, properties will need to be moved to the backing store. |
2073 return true; | 2073 return true; |
2074 } | 2074 } |
2075 | 2075 |
2076 | 2076 |
2077 Handle<TransitionArray> Map::SetElementsTransitionMap( | 2077 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { |
2078 Handle<Map> map, Handle<Map> transitioned_map) { | 2078 Isolate* isolate = parent->GetIsolate(); |
2079 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 2079 Handle<Name> name = isolate->factory()->elements_transition_symbol(); |
2080 map, | 2080 ConnectTransition(parent, child, name, FULL_TRANSITION); |
2081 map->GetIsolate()->factory()->elements_transition_symbol(), | |
2082 transitioned_map, | |
2083 FULL_TRANSITION); | |
2084 map->set_transitions(*transitions); | |
2085 return transitions; | |
2086 } | 2081 } |
2087 | 2082 |
2088 | 2083 |
2089 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { | 2084 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
2090 if (object->map() == *new_map) return; | 2085 if (object->map() == *new_map) return; |
2091 if (object->HasFastProperties()) { | 2086 if (object->HasFastProperties()) { |
2092 if (!new_map->is_dictionary_map()) { | 2087 if (!new_map->is_dictionary_map()) { |
2088 Handle<Map> old_map(object->map()); | |
2093 MigrateFastToFast(object, new_map); | 2089 MigrateFastToFast(object, new_map); |
2090 if (old_map->is_prototype_map()) { | |
2091 // Clear out the old descriptor array to avoid problems to sharing | |
2092 // the descriptor array without using an explicit. | |
2093 old_map->InitializeDescriptors( | |
2094 old_map->GetHeap()->empty_descriptor_array()); | |
2095 // Ensure that no transition was inserted for prototype migrations. | |
2096 DCHECK(!old_map->HasTransitionArray()); | |
2097 DCHECK(new_map->GetBackPointer()->IsUndefined()); | |
2098 } | |
2094 } else { | 2099 } else { |
2095 MigrateFastToSlow(object, new_map, 0); | 2100 MigrateFastToSlow(object, new_map, 0); |
2096 } | 2101 } |
2097 } else { | 2102 } else { |
2098 // For slow-to-fast migrations JSObject::TransformToFastProperties() | 2103 // For slow-to-fast migrations JSObject::TransformToFastProperties() |
2099 // must be used instead. | 2104 // must be used instead. |
2100 CHECK(new_map->is_dictionary_map()); | 2105 CHECK(new_map->is_dictionary_map()); |
2101 | 2106 |
2102 // Slow-to-slow migration is trivial. | 2107 // Slow-to-slow migration is trivial. |
2103 object->set_map(*new_map); | 2108 object->set_map(*new_map); |
(...skipping 1348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3452 } | 3457 } |
3453 | 3458 |
3454 | 3459 |
3455 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, | 3460 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, |
3456 ElementsKind to_kind) { | 3461 ElementsKind to_kind) { |
3457 DCHECK(IsTransitionElementsKind(map->elements_kind())); | 3462 DCHECK(IsTransitionElementsKind(map->elements_kind())); |
3458 | 3463 |
3459 Handle<Map> current_map = map; | 3464 Handle<Map> current_map = map; |
3460 | 3465 |
3461 ElementsKind kind = map->elements_kind(); | 3466 ElementsKind kind = map->elements_kind(); |
3462 while (kind != to_kind && !IsTerminalElementsKind(kind)) { | 3467 if (!map->is_prototype_map()) { |
3463 kind = GetNextTransitionElementsKind(kind); | 3468 while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
3464 current_map = Map::CopyAsElementsKind( | 3469 kind = GetNextTransitionElementsKind(kind); |
3465 current_map, kind, INSERT_TRANSITION); | 3470 current_map = |
3471 Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION); | |
3472 } | |
3466 } | 3473 } |
3467 | 3474 |
3468 // In case we are exiting the fast elements kind system, just add the map in | 3475 // In case we are exiting the fast elements kind system, just add the map in |
3469 // the end. | 3476 // the end. |
3470 if (kind != to_kind) { | 3477 if (kind != to_kind) { |
3471 current_map = Map::CopyAsElementsKind( | 3478 current_map = Map::CopyAsElementsKind( |
3472 current_map, to_kind, INSERT_TRANSITION); | 3479 current_map, to_kind, INSERT_TRANSITION); |
3473 } | 3480 } |
3474 | 3481 |
3475 DCHECK(current_map->elements_kind() == to_kind); | 3482 DCHECK(current_map->elements_kind() == to_kind); |
(...skipping 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5701 Handle<Map> transition_map(old_map->GetTransition(transition_index)); | 5708 Handle<Map> transition_map(old_map->GetTransition(transition_index)); |
5702 DCHECK(transition_map->has_dictionary_elements()); | 5709 DCHECK(transition_map->has_dictionary_elements()); |
5703 DCHECK(transition_map->is_frozen()); | 5710 DCHECK(transition_map->is_frozen()); |
5704 DCHECK(!transition_map->is_extensible()); | 5711 DCHECK(!transition_map->is_extensible()); |
5705 JSObject::MigrateToMap(object, transition_map); | 5712 JSObject::MigrateToMap(object, transition_map); |
5706 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5713 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5707 // Create a new descriptor array with fully-frozen properties | 5714 // Create a new descriptor array with fully-frozen properties |
5708 Handle<Map> new_map = Map::CopyForFreeze(old_map); | 5715 Handle<Map> new_map = Map::CopyForFreeze(old_map); |
5709 JSObject::MigrateToMap(object, new_map); | 5716 JSObject::MigrateToMap(object, new_map); |
5710 } else { | 5717 } else { |
5711 ASSERT(!old_map->is_prototype_map()); | 5718 DCHECK(!old_map->is_prototype_map()); |
5712 // Slow path: need to normalize properties for safety | 5719 // Slow path: need to normalize properties for safety |
5713 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5720 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
5714 | 5721 |
5715 // Create a new map, since other objects with this map may be extensible. | 5722 // Create a new map, since other objects with this map may be extensible. |
5716 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5723 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
5717 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5724 Handle<Map> new_map = Map::Copy(handle(object->map())); |
5718 new_map->freeze(); | 5725 new_map->freeze(); |
5719 new_map->set_is_extensible(false); | 5726 new_map->set_is_extensible(false); |
5720 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5727 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
5721 JSObject::MigrateToMap(object, new_map); | 5728 JSObject::MigrateToMap(object, new_map); |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7103 Handle<DescriptorArray> descriptors, | 7110 Handle<DescriptorArray> descriptors, |
7104 Descriptor* descriptor) { | 7111 Descriptor* descriptor) { |
7105 // Sanity check. This path is only to be taken if the map owns its descriptor | 7112 // Sanity check. This path is only to be taken if the map owns its descriptor |
7106 // array, implying that its NumberOfOwnDescriptors equals the number of | 7113 // array, implying that its NumberOfOwnDescriptors equals the number of |
7107 // descriptors in the descriptor array. | 7114 // descriptors in the descriptor array. |
7108 DCHECK(map->NumberOfOwnDescriptors() == | 7115 DCHECK(map->NumberOfOwnDescriptors() == |
7109 map->instance_descriptors()->number_of_descriptors()); | 7116 map->instance_descriptors()->number_of_descriptors()); |
7110 | 7117 |
7111 Handle<Map> result = CopyDropDescriptors(map); | 7118 Handle<Map> result = CopyDropDescriptors(map); |
7112 Handle<Name> name = descriptor->GetKey(); | 7119 Handle<Name> name = descriptor->GetKey(); |
7113 Handle<TransitionArray> transitions = | |
7114 TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); | |
7115 | 7120 |
7116 // Ensure there's space for the new descriptor in the shared descriptor array. | 7121 // Ensure there's space for the new descriptor in the shared descriptor array. |
7117 if (descriptors->NumberOfSlackDescriptors() == 0) { | 7122 if (descriptors->NumberOfSlackDescriptors() == 0) { |
7118 int old_size = descriptors->number_of_descriptors(); | 7123 int old_size = descriptors->number_of_descriptors(); |
7119 if (old_size == 0) { | 7124 if (old_size == 0) { |
7120 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); | 7125 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); |
7121 } else { | 7126 } else { |
7122 EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); | 7127 EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); |
7123 descriptors = handle(map->instance_descriptors()); | 7128 descriptors = handle(map->instance_descriptors()); |
7124 } | 7129 } |
7125 } | 7130 } |
7126 | 7131 |
7127 // Commit the state atomically. | 7132 { |
7128 DisallowHeapAllocation no_gc; | 7133 DisallowHeapAllocation no_gc; |
7129 | 7134 descriptors->Append(descriptor); |
7130 descriptors->Append(descriptor); | 7135 result->InitializeDescriptors(*descriptors); |
7131 result->SetBackPointer(*map); | 7136 } |
7132 result->InitializeDescriptors(*descriptors); | |
7133 | 7137 |
7134 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); | 7138 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
7135 | 7139 ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
7136 map->set_transitions(*transitions); | |
7137 map->set_owns_descriptors(false); | |
7138 | 7140 |
7139 return result; | 7141 return result; |
7140 } | 7142 } |
7141 | 7143 |
7142 | 7144 |
7145 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | |
7146 Handle<Name> name, SimpleTransitionFlag flag) { | |
7147 parent->set_owns_descriptors(false); | |
7148 if (parent->is_prototype_map()) { | |
7149 DCHECK(child->is_prototype_map()); | |
7150 } else { | |
7151 Handle<TransitionArray> transitions = | |
7152 TransitionArray::CopyInsert(parent, name, child, flag); | |
7153 parent->set_transitions(*transitions); | |
7154 child->SetBackPointer(*parent); | |
7155 } | |
7156 } | |
7157 | |
7158 | |
7143 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, | 7159 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
7144 Handle<DescriptorArray> descriptors, | 7160 Handle<DescriptorArray> descriptors, |
7145 TransitionFlag flag, | 7161 TransitionFlag flag, |
7146 MaybeHandle<Name> maybe_name, | 7162 MaybeHandle<Name> maybe_name, |
7147 SimpleTransitionFlag simple_flag) { | 7163 SimpleTransitionFlag simple_flag) { |
7148 DCHECK(descriptors->IsSortedNoDuplicates()); | 7164 DCHECK(descriptors->IsSortedNoDuplicates()); |
7149 | 7165 |
7150 Handle<Map> result = CopyDropDescriptors(map); | 7166 Handle<Map> result = CopyDropDescriptors(map); |
7151 result->InitializeDescriptors(*descriptors); | 7167 result->InitializeDescriptors(*descriptors); |
7152 | 7168 |
7153 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 7169 if (!map->is_prototype_map()) { |
7154 Handle<Name> name; | 7170 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
7155 CHECK(maybe_name.ToHandle(&name)); | 7171 Handle<Name> name; |
7156 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 7172 CHECK(maybe_name.ToHandle(&name)); |
7157 map, name, result, simple_flag); | 7173 ConnectTransition(map, result, name, simple_flag); |
7158 map->set_transitions(*transitions); | 7174 } else { |
7159 result->SetBackPointer(*map); | 7175 int length = descriptors->number_of_descriptors(); |
7160 } else { | 7176 for (int i = 0; i < length; i++) { |
7161 int length = descriptors->number_of_descriptors(); | 7177 descriptors->SetRepresentation(i, Representation::Tagged()); |
7162 for (int i = 0; i < length; i++) { | 7178 if (descriptors->GetDetails(i).type() == FIELD) { |
7163 descriptors->SetRepresentation(i, Representation::Tagged()); | 7179 descriptors->SetValue(i, HeapType::Any()); |
7164 if (descriptors->GetDetails(i).type() == FIELD) { | 7180 } |
7165 descriptors->SetValue(i, HeapType::Any()); | |
7166 } | 7181 } |
7167 } | 7182 } |
7168 } | 7183 } |
7169 | 7184 |
7170 return result; | 7185 return result; |
7171 } | 7186 } |
7172 | 7187 |
7173 | 7188 |
7174 // Since this method is used to rewrite an existing transition tree, it can | 7189 // Since this method is used to rewrite an existing transition tree, it can |
7175 // always insert transitions without checking. | 7190 // always insert transitions without checking. |
7176 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 7191 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
7177 int new_descriptor, | 7192 int new_descriptor, |
7178 Handle<DescriptorArray> descriptors) { | 7193 Handle<DescriptorArray> descriptors) { |
7179 DCHECK(descriptors->IsSortedNoDuplicates()); | 7194 DCHECK(descriptors->IsSortedNoDuplicates()); |
7180 | 7195 |
7181 Handle<Map> result = CopyDropDescriptors(map); | 7196 Handle<Map> result = CopyDropDescriptors(map); |
7182 | 7197 |
7183 result->InitializeDescriptors(*descriptors); | 7198 result->InitializeDescriptors(*descriptors); |
7184 result->SetNumberOfOwnDescriptors(new_descriptor + 1); | 7199 result->SetNumberOfOwnDescriptors(new_descriptor + 1); |
7185 | 7200 |
7186 int unused_property_fields = map->unused_property_fields(); | 7201 int unused_property_fields = map->unused_property_fields(); |
7187 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { | 7202 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { |
7188 unused_property_fields = map->unused_property_fields() - 1; | 7203 unused_property_fields = map->unused_property_fields() - 1; |
7189 if (unused_property_fields < 0) { | 7204 if (unused_property_fields < 0) { |
7190 unused_property_fields += JSObject::kFieldsAdded; | 7205 unused_property_fields += JSObject::kFieldsAdded; |
7191 } | 7206 } |
7192 } | 7207 } |
7193 | 7208 |
7194 result->set_unused_property_fields(unused_property_fields); | 7209 result->set_unused_property_fields(unused_property_fields); |
7195 result->set_owns_descriptors(false); | 7210 result->set_owns_descriptors(false); |
Igor Sheludko
2014/08/04 14:25:55
This is going to be done again in ConnectTransitio
| |
7196 | 7211 |
7197 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); | 7212 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
7198 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 7213 ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
7199 map, name, result, SIMPLE_TRANSITION); | |
7200 | |
7201 map->set_transitions(*transitions); | |
7202 result->SetBackPointer(*map); | |
7203 | 7214 |
7204 return result; | 7215 return result; |
7205 } | 7216 } |
7206 | 7217 |
7207 | 7218 |
7208 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 7219 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
7209 TransitionFlag flag) { | 7220 TransitionFlag flag) { |
7210 if (flag == INSERT_TRANSITION) { | 7221 if (flag == INSERT_TRANSITION) { |
7211 DCHECK(!map->HasElementsTransition() || | 7222 DCHECK(!map->HasElementsTransition() || |
7212 ((map->elements_transition_map()->elements_kind() == | 7223 ((map->elements_transition_map()->elements_kind() == |
7213 DICTIONARY_ELEMENTS || | 7224 DICTIONARY_ELEMENTS || |
7214 IsExternalArrayElementsKind( | 7225 IsExternalArrayElementsKind( |
7215 map->elements_transition_map()->elements_kind())) && | 7226 map->elements_transition_map()->elements_kind())) && |
7216 (kind == DICTIONARY_ELEMENTS || | 7227 (kind == DICTIONARY_ELEMENTS || |
7217 IsExternalArrayElementsKind(kind)))); | 7228 IsExternalArrayElementsKind(kind)))); |
7218 DCHECK(!IsFastElementsKind(kind) || | 7229 DCHECK(!IsFastElementsKind(kind) || |
7219 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); | 7230 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
7220 DCHECK(kind != map->elements_kind()); | 7231 DCHECK(kind != map->elements_kind()); |
7221 } | 7232 } |
7222 | 7233 |
7223 bool insert_transition = | 7234 bool insert_transition = |
7224 flag == INSERT_TRANSITION && !map->HasElementsTransition(); | 7235 flag == INSERT_TRANSITION && !map->HasElementsTransition(); |
7225 | 7236 |
7226 if (insert_transition && map->owns_descriptors()) { | 7237 if (insert_transition && map->owns_descriptors()) { |
7227 // In case the map owned its own descriptors, share the descriptors and | 7238 // In case the map owned its own descriptors, share the descriptors and |
7228 // transfer ownership to the new map. | 7239 // transfer ownership to the new map. |
7229 Handle<Map> new_map = CopyDropDescriptors(map); | 7240 Handle<Map> new_map = CopyDropDescriptors(map); |
7230 | 7241 |
7231 SetElementsTransitionMap(map, new_map); | 7242 ConnectElementsTransition(map, new_map); |
7232 | 7243 |
7233 new_map->set_elements_kind(kind); | 7244 new_map->set_elements_kind(kind); |
7234 new_map->InitializeDescriptors(map->instance_descriptors()); | 7245 new_map->InitializeDescriptors(map->instance_descriptors()); |
7235 new_map->SetBackPointer(*map); | |
7236 map->set_owns_descriptors(false); | |
7237 return new_map; | 7246 return new_map; |
7238 } | 7247 } |
7239 | 7248 |
7240 // In case the map did not own its own descriptors, a split is forced by | 7249 // In case the map did not own its own descriptors, a split is forced by |
7241 // copying the map; creating a new descriptor array cell. | 7250 // copying the map; creating a new descriptor array cell. |
7242 // Create a new free-floating map only if we are not allowed to store it. | 7251 // Create a new free-floating map only if we are not allowed to store it. |
7243 Handle<Map> new_map = Copy(map); | 7252 Handle<Map> new_map = Copy(map); |
7244 | 7253 |
7245 new_map->set_elements_kind(kind); | 7254 new_map->set_elements_kind(kind); |
7246 | 7255 |
7247 if (insert_transition) { | 7256 if (insert_transition) { |
7248 SetElementsTransitionMap(map, new_map); | 7257 ConnectElementsTransition(map, new_map); |
7249 new_map->SetBackPointer(*map); | |
7250 } | 7258 } |
7251 | 7259 |
7252 return new_map; | 7260 return new_map; |
7253 } | 7261 } |
7254 | 7262 |
7255 | 7263 |
7256 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 7264 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
7257 DCHECK(!map->is_observed()); | 7265 DCHECK(!map->is_observed()); |
7258 | 7266 |
7259 Isolate* isolate = map->GetIsolate(); | 7267 Isolate* isolate = map->GetIsolate(); |
7260 | 7268 |
7261 // In case the map owned its own descriptors, share the descriptors and | 7269 // In case the map owned its own descriptors, share the descriptors and |
7262 // transfer ownership to the new map. | 7270 // transfer ownership to the new map. |
7263 Handle<Map> new_map; | 7271 Handle<Map> new_map; |
7264 if (map->owns_descriptors()) { | 7272 if (map->owns_descriptors()) { |
7265 new_map = CopyDropDescriptors(map); | 7273 new_map = CopyDropDescriptors(map); |
7266 } else { | 7274 } else { |
7275 DCHECK(!map->is_prototype_map()); | |
7267 new_map = Copy(map); | 7276 new_map = Copy(map); |
7268 } | 7277 } |
7269 | 7278 |
7270 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | |
7271 map, isolate->factory()->observed_symbol(), new_map, FULL_TRANSITION); | |
7272 | |
7273 map->set_transitions(*transitions); | |
7274 | |
7275 new_map->set_is_observed(); | 7279 new_map->set_is_observed(); |
7276 | |
7277 if (map->owns_descriptors()) { | 7280 if (map->owns_descriptors()) { |
7278 new_map->InitializeDescriptors(map->instance_descriptors()); | 7281 new_map->InitializeDescriptors(map->instance_descriptors()); |
7279 map->set_owns_descriptors(false); | |
7280 } | 7282 } |
7281 | 7283 |
7282 new_map->SetBackPointer(*map); | 7284 Handle<Name> name = isolate->factory()->observed_symbol(); |
7285 ConnectTransition(map, new_map, name, FULL_TRANSITION); | |
7286 | |
7283 return new_map; | 7287 return new_map; |
7284 } | 7288 } |
7285 | 7289 |
7286 | 7290 |
7287 Handle<Map> Map::CopyAsPrototypeMap(Handle<Map> map) { | 7291 Handle<Map> Map::CopyAsPrototypeMap(Handle<Map> map) { |
7288 Handle<Map> result = Copy(map); | 7292 Handle<Map> result = Copy(map); |
7289 result->mark_prototype_map(); | 7293 result->mark_prototype_map(); |
7290 return result; | 7294 return result; |
7291 } | 7295 } |
7292 | 7296 |
(...skipping 4623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11916 } | 11920 } |
11917 return Handle<Map>(); | 11921 return Handle<Map>(); |
11918 } | 11922 } |
11919 | 11923 |
11920 | 11924 |
11921 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, | 11925 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
11922 Handle<Object> prototype, | 11926 Handle<Object> prototype, |
11923 Handle<Map> target_map) { | 11927 Handle<Map> target_map) { |
11924 DCHECK(target_map->IsMap()); | 11928 DCHECK(target_map->IsMap()); |
11925 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); | 11929 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
11926 // Don't cache prototype transition if this map is shared. | 11930 // Don't cache prototype transition if this map is either shared, or a map of |
11931 // a prototype. | |
11932 if (map->is_prototype_map()) return map; | |
11927 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; | 11933 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; |
11928 | 11934 |
11929 const int step = kProtoTransitionElementsPerEntry; | 11935 const int step = kProtoTransitionElementsPerEntry; |
11930 const int header = kProtoTransitionHeaderSize; | 11936 const int header = kProtoTransitionHeaderSize; |
11931 | 11937 |
11932 Handle<FixedArray> cache(map->GetPrototypeTransitions()); | 11938 Handle<FixedArray> cache(map->GetPrototypeTransitions()); |
11933 int capacity = (cache->length() - header) / step; | 11939 int capacity = (cache->length() - header) / step; |
11934 int transitions = map->NumberOfProtoTransitions() + 1; | 11940 int transitions = map->NumberOfProtoTransitions() + 1; |
11935 | 11941 |
11936 if (transitions > capacity) { | 11942 if (transitions > capacity) { |
(...skipping 5108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17045 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17051 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17046 static const char* error_messages_[] = { | 17052 static const char* error_messages_[] = { |
17047 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17053 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17048 }; | 17054 }; |
17049 #undef ERROR_MESSAGES_TEXTS | 17055 #undef ERROR_MESSAGES_TEXTS |
17050 return error_messages_[reason]; | 17056 return error_messages_[reason]; |
17051 } | 17057 } |
17052 | 17058 |
17053 | 17059 |
17054 } } // namespace v8::internal | 17060 } } // namespace v8::internal |
OLD | NEW |