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 <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 1882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1893 if (!new_map->is_dictionary_map()) { | 1893 if (!new_map->is_dictionary_map()) { |
1894 Handle<Map> old_map(object->map()); | 1894 Handle<Map> old_map(object->map()); |
1895 MigrateFastToFast(object, new_map); | 1895 MigrateFastToFast(object, new_map); |
1896 if (old_map->is_prototype_map()) { | 1896 if (old_map->is_prototype_map()) { |
1897 // Clear out the old descriptor array to avoid problems to sharing | 1897 // Clear out the old descriptor array to avoid problems to sharing |
1898 // the descriptor array without using an explicit. | 1898 // the descriptor array without using an explicit. |
1899 old_map->InitializeDescriptors( | 1899 old_map->InitializeDescriptors( |
1900 old_map->GetHeap()->empty_descriptor_array(), | 1900 old_map->GetHeap()->empty_descriptor_array(), |
1901 LayoutDescriptor::FastPointerLayout()); | 1901 LayoutDescriptor::FastPointerLayout()); |
1902 // Ensure that no transition was inserted for prototype migrations. | 1902 // Ensure that no transition was inserted for prototype migrations. |
1903 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( | 1903 DCHECK(!old_map->HasTransitionArray()); |
1904 old_map->raw_transitions())); | |
1905 DCHECK(new_map->GetBackPointer()->IsUndefined()); | 1904 DCHECK(new_map->GetBackPointer()->IsUndefined()); |
1906 } | 1905 } |
1907 } else { | 1906 } else { |
1908 MigrateFastToSlow(object, new_map, 0); | 1907 MigrateFastToSlow(object, new_map, 0); |
1909 } | 1908 } |
1910 } else { | 1909 } else { |
1911 // For slow-to-fast migrations JSObject::TransformToFastProperties() | 1910 // For slow-to-fast migrations JSObject::TransformToFastProperties() |
1912 // must be used instead. | 1911 // must be used instead. |
1913 CHECK(new_map->is_dictionary_map()); | 1912 CHECK(new_map->is_dictionary_map()); |
1914 | 1913 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2180 details.representation(), Representation::Tagged(), field_type, | 2179 details.representation(), Representation::Tagged(), field_type, |
2181 HeapType::Any()); | 2180 HeapType::Any()); |
2182 } | 2181 } |
2183 } | 2182 } |
2184 return new_map; | 2183 return new_map; |
2185 } | 2184 } |
2186 | 2185 |
2187 | 2186 |
2188 void Map::DeprecateTransitionTree() { | 2187 void Map::DeprecateTransitionTree() { |
2189 if (is_deprecated()) return; | 2188 if (is_deprecated()) return; |
2190 Object* transitions = raw_transitions(); | 2189 if (HasTransitionArray()) { |
2191 int num_transitions = TransitionArray::NumberOfTransitions(transitions); | 2190 TransitionArray* transitions = this->transitions(); |
2192 for (int i = 0; i < num_transitions; ++i) { | 2191 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
2193 TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree(); | 2192 transitions->GetTarget(i)->DeprecateTransitionTree(); |
| 2193 } |
2194 } | 2194 } |
2195 deprecate(); | 2195 deprecate(); |
2196 dependent_code()->DeoptimizeDependentCodeGroup( | 2196 dependent_code()->DeoptimizeDependentCodeGroup( |
2197 GetIsolate(), DependentCode::kTransitionGroup); | 2197 GetIsolate(), DependentCode::kTransitionGroup); |
2198 NotifyLeafMapLayoutChange(); | 2198 NotifyLeafMapLayoutChange(); |
2199 } | 2199 } |
2200 | 2200 |
2201 | 2201 |
2202 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) { | 2202 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) { |
2203 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds. | 2203 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds. |
2204 // TODO(ishell): compare AccessorPairs. | 2204 // TODO(ishell): compare AccessorPairs. |
2205 return false; | 2205 return false; |
2206 } | 2206 } |
2207 | 2207 |
2208 | 2208 |
2209 // Invalidates a transition target at |key|, and installs |new_descriptors| over | 2209 // Invalidates a transition target at |key|, and installs |new_descriptors| over |
2210 // the current instance_descriptors to ensure proper sharing of descriptor | 2210 // the current instance_descriptors to ensure proper sharing of descriptor |
2211 // arrays. | 2211 // arrays. |
2212 // Returns true if the transition target at given key was deprecated. | 2212 // Returns true if the transition target at given key was deprecated. |
2213 bool Map::DeprecateTarget(PropertyKind kind, Name* key, | 2213 bool Map::DeprecateTarget(PropertyKind kind, Name* key, |
2214 PropertyAttributes attributes, | 2214 PropertyAttributes attributes, |
2215 DescriptorArray* new_descriptors, | 2215 DescriptorArray* new_descriptors, |
2216 LayoutDescriptor* new_layout_descriptor) { | 2216 LayoutDescriptor* new_layout_descriptor) { |
2217 bool transition_target_deprecated = false; | 2217 bool transition_target_deprecated = false; |
2218 Map* maybe_transition = | 2218 if (HasTransitionArray()) { |
2219 TransitionArray::SearchTransition(this, kind, key, attributes); | 2219 TransitionArray* transitions = this->transitions(); |
2220 if (maybe_transition != NULL) { | 2220 int transition = transitions->Search(kind, key, attributes); |
2221 maybe_transition->DeprecateTransitionTree(); | 2221 if (transition != TransitionArray::kNotFound) { |
2222 transition_target_deprecated = true; | 2222 transitions->GetTarget(transition)->DeprecateTransitionTree(); |
| 2223 transition_target_deprecated = true; |
| 2224 } |
2223 } | 2225 } |
2224 | 2226 |
2225 // Don't overwrite the empty descriptor array. | 2227 // Don't overwrite the empty descriptor array. |
2226 if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated; | 2228 if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated; |
2227 | 2229 |
2228 DescriptorArray* to_replace = instance_descriptors(); | 2230 DescriptorArray* to_replace = instance_descriptors(); |
2229 Map* current = this; | 2231 Map* current = this; |
2230 GetHeap()->incremental_marking()->RecordWrites(to_replace); | 2232 GetHeap()->incremental_marking()->RecordWrites(to_replace); |
2231 while (current->instance_descriptors() == to_replace) { | 2233 while (current->instance_descriptors() == to_replace) { |
2232 current->SetEnumLength(kInvalidEnumCacheSentinel); | 2234 current->SetEnumLength(kInvalidEnumCacheSentinel); |
(...skipping 22 matching lines...) Expand all Loading... |
2255 int length, | 2257 int length, |
2256 DescriptorArray* descriptors) { | 2258 DescriptorArray* descriptors) { |
2257 DisallowHeapAllocation no_allocation; | 2259 DisallowHeapAllocation no_allocation; |
2258 | 2260 |
2259 // This can only be called on roots of transition trees. | 2261 // This can only be called on roots of transition trees. |
2260 DCHECK_EQ(verbatim, NumberOfOwnDescriptors()); | 2262 DCHECK_EQ(verbatim, NumberOfOwnDescriptors()); |
2261 | 2263 |
2262 Map* current = this; | 2264 Map* current = this; |
2263 | 2265 |
2264 for (int i = verbatim; i < length; i++) { | 2266 for (int i = verbatim; i < length; i++) { |
| 2267 if (!current->HasTransitionArray()) break; |
2265 Name* name = descriptors->GetKey(i); | 2268 Name* name = descriptors->GetKey(i); |
2266 PropertyDetails details = descriptors->GetDetails(i); | 2269 PropertyDetails details = descriptors->GetDetails(i); |
2267 Map* next = TransitionArray::SearchTransition(current, details.kind(), name, | 2270 TransitionArray* transitions = current->transitions(); |
2268 details.attributes()); | 2271 int transition = |
2269 if (next == NULL) break; | 2272 transitions->Search(details.kind(), name, details.attributes()); |
| 2273 if (transition == TransitionArray::kNotFound) break; |
| 2274 |
| 2275 Map* next = transitions->GetTarget(transition); |
2270 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2276 DescriptorArray* next_descriptors = next->instance_descriptors(); |
2271 | 2277 |
2272 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2278 PropertyDetails next_details = next_descriptors->GetDetails(i); |
2273 DCHECK_EQ(details.kind(), next_details.kind()); | 2279 DCHECK_EQ(details.kind(), next_details.kind()); |
2274 DCHECK_EQ(details.attributes(), next_details.attributes()); | 2280 DCHECK_EQ(details.attributes(), next_details.attributes()); |
2275 if (details.location() != next_details.location()) break; | 2281 if (details.location() != next_details.location()) break; |
2276 if (!details.representation().Equals(next_details.representation())) break; | 2282 if (!details.representation().Equals(next_details.representation())) break; |
2277 | 2283 |
2278 if (next_details.location() == kField) { | 2284 if (next_details.location() == kField) { |
2279 HeapType* next_field_type = next_descriptors->GetFieldType(i); | 2285 HeapType* next_field_type = next_descriptors->GetFieldType(i); |
(...skipping 27 matching lines...) Expand all Loading... |
2307 } | 2313 } |
2308 | 2314 |
2309 | 2315 |
2310 void Map::UpdateFieldType(int descriptor, Handle<Name> name, | 2316 void Map::UpdateFieldType(int descriptor, Handle<Name> name, |
2311 Representation new_representation, | 2317 Representation new_representation, |
2312 Handle<Object> new_wrapped_type) { | 2318 Handle<Object> new_wrapped_type) { |
2313 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); | 2319 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); |
2314 DisallowHeapAllocation no_allocation; | 2320 DisallowHeapAllocation no_allocation; |
2315 PropertyDetails details = instance_descriptors()->GetDetails(descriptor); | 2321 PropertyDetails details = instance_descriptors()->GetDetails(descriptor); |
2316 if (details.type() != DATA) return; | 2322 if (details.type() != DATA) return; |
2317 Object* transitions = raw_transitions(); | 2323 if (HasTransitionArray()) { |
2318 int num_transitions = TransitionArray::NumberOfTransitions(transitions); | 2324 TransitionArray* transitions = this->transitions(); |
2319 for (int i = 0; i < num_transitions; ++i) { | 2325 for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
2320 Map* target = TransitionArray::GetTarget(transitions, i); | 2326 transitions->GetTarget(i)->UpdateFieldType( |
2321 target->UpdateFieldType(descriptor, name, new_representation, | 2327 descriptor, name, new_representation, new_wrapped_type); |
2322 new_wrapped_type); | 2328 } |
2323 } | 2329 } |
2324 // It is allowed to change representation here only from None to something. | 2330 // It is allowed to change representation here only from None to something. |
2325 DCHECK(details.representation().Equals(new_representation) || | 2331 DCHECK(details.representation().Equals(new_representation) || |
2326 details.representation().IsNone()); | 2332 details.representation().IsNone()); |
2327 | 2333 |
2328 // Skip if already updated the shared descriptor. | 2334 // Skip if already updated the shared descriptor. |
2329 if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return; | 2335 if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return; |
2330 DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), | 2336 DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), |
2331 new_wrapped_type, details.attributes(), new_representation); | 2337 new_wrapped_type, details.attributes(), new_representation); |
2332 instance_descriptors()->Replace(descriptor, &d); | 2338 instance_descriptors()->Replace(descriptor, &d); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2552 next_representation = | 2558 next_representation = |
2553 next_representation.generalize(old_details.representation()); | 2559 next_representation.generalize(old_details.representation()); |
2554 } | 2560 } |
2555 | 2561 |
2556 } else { | 2562 } else { |
2557 next_kind = old_details.kind(); | 2563 next_kind = old_details.kind(); |
2558 next_location = old_details.location(); | 2564 next_location = old_details.location(); |
2559 next_attributes = old_details.attributes(); | 2565 next_attributes = old_details.attributes(); |
2560 next_representation = old_details.representation(); | 2566 next_representation = old_details.representation(); |
2561 } | 2567 } |
2562 Map* transition = TransitionArray::SearchTransition( | 2568 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), |
2563 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); | 2569 next_attributes); |
2564 if (transition == NULL) break; | 2570 if (j == TransitionArray::kNotFound) break; |
2565 Handle<Map> tmp_map(transition, isolate); | 2571 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
2566 | |
2567 Handle<DescriptorArray> tmp_descriptors = handle( | 2572 Handle<DescriptorArray> tmp_descriptors = handle( |
2568 tmp_map->instance_descriptors(), isolate); | 2573 tmp_map->instance_descriptors(), isolate); |
2569 | 2574 |
2570 // Check if target map is incompatible. | 2575 // Check if target map is incompatible. |
2571 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2576 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2572 DCHECK_EQ(next_kind, tmp_details.kind()); | 2577 DCHECK_EQ(next_kind, tmp_details.kind()); |
2573 DCHECK_EQ(next_attributes, tmp_details.attributes()); | 2578 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
2574 if (next_kind == kAccessor && | 2579 if (next_kind == kAccessor && |
2575 !EqualImmutableValues(old_descriptors->GetValue(i), | 2580 !EqualImmutableValues(old_descriptors->GetValue(i), |
2576 tmp_descriptors->GetValue(i))) { | 2581 tmp_descriptors->GetValue(i))) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2641 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2646 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2642 PropertyKind next_kind; | 2647 PropertyKind next_kind; |
2643 PropertyAttributes next_attributes; | 2648 PropertyAttributes next_attributes; |
2644 if (modify_index == i) { | 2649 if (modify_index == i) { |
2645 next_kind = new_kind; | 2650 next_kind = new_kind; |
2646 next_attributes = new_attributes; | 2651 next_attributes = new_attributes; |
2647 } else { | 2652 } else { |
2648 next_kind = old_details.kind(); | 2653 next_kind = old_details.kind(); |
2649 next_attributes = old_details.attributes(); | 2654 next_attributes = old_details.attributes(); |
2650 } | 2655 } |
2651 Map* transition = TransitionArray::SearchTransition( | 2656 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), |
2652 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); | 2657 next_attributes); |
2653 if (transition == NULL) break; | 2658 if (j == TransitionArray::kNotFound) break; |
2654 Handle<Map> tmp_map(transition, isolate); | 2659 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
2655 Handle<DescriptorArray> tmp_descriptors( | 2660 Handle<DescriptorArray> tmp_descriptors( |
2656 tmp_map->instance_descriptors(), isolate); | 2661 tmp_map->instance_descriptors(), isolate); |
2657 | 2662 |
2658 // Check if target map is compatible. | 2663 // Check if target map is compatible. |
2659 #ifdef DEBUG | 2664 #ifdef DEBUG |
2660 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2665 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2661 DCHECK_EQ(next_kind, tmp_details.kind()); | 2666 DCHECK_EQ(next_kind, tmp_details.kind()); |
2662 DCHECK_EQ(next_attributes, tmp_details.attributes()); | 2667 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
2663 #endif | 2668 #endif |
2664 if (next_kind == kAccessor && | 2669 if (next_kind == kAccessor && |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2882 split_kind = split_prop_details.kind(); | 2887 split_kind = split_prop_details.kind(); |
2883 split_attributes = split_prop_details.attributes(); | 2888 split_attributes = split_prop_details.attributes(); |
2884 } | 2889 } |
2885 bool transition_target_deprecated = split_map->DeprecateTarget( | 2890 bool transition_target_deprecated = split_map->DeprecateTarget( |
2886 split_kind, old_descriptors->GetKey(split_nof), split_attributes, | 2891 split_kind, old_descriptors->GetKey(split_nof), split_attributes, |
2887 *new_descriptors, *new_layout_descriptor); | 2892 *new_descriptors, *new_layout_descriptor); |
2888 | 2893 |
2889 // If |transition_target_deprecated| is true then the transition array | 2894 // If |transition_target_deprecated| is true then the transition array |
2890 // already contains entry for given descriptor. This means that the transition | 2895 // already contains entry for given descriptor. This means that the transition |
2891 // could be inserted regardless of whether transitions array is full or not. | 2896 // could be inserted regardless of whether transitions array is full or not. |
2892 if (!transition_target_deprecated && | 2897 if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) { |
2893 !TransitionArray::CanHaveMoreTransitions(split_map)) { | |
2894 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2898 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2895 new_kind, new_attributes, | 2899 new_kind, new_attributes, |
2896 "GenAll_CantHaveMoreTransitions"); | 2900 "GenAll_CantHaveMoreTransitions"); |
2897 } | 2901 } |
2898 | 2902 |
2899 if (FLAG_trace_generalization && modify_index >= 0) { | 2903 if (FLAG_trace_generalization && modify_index >= 0) { |
2900 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2904 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2901 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2905 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
2902 Handle<HeapType> old_field_type = | 2906 Handle<HeapType> old_field_type = |
2903 (old_details.type() == DATA) | 2907 (old_details.type() == DATA) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2956 Map* root_map = old_map->FindRootMap(); | 2960 Map* root_map = old_map->FindRootMap(); |
2957 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); | 2961 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); |
2958 int root_nof = root_map->NumberOfOwnDescriptors(); | 2962 int root_nof = root_map->NumberOfOwnDescriptors(); |
2959 | 2963 |
2960 int old_nof = old_map->NumberOfOwnDescriptors(); | 2964 int old_nof = old_map->NumberOfOwnDescriptors(); |
2961 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2965 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2962 | 2966 |
2963 Map* new_map = root_map; | 2967 Map* new_map = root_map; |
2964 for (int i = root_nof; i < old_nof; ++i) { | 2968 for (int i = root_nof; i < old_nof; ++i) { |
2965 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2969 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2966 Map* transition = TransitionArray::SearchTransition( | 2970 int j = new_map->SearchTransition(old_details.kind(), |
2967 new_map, old_details.kind(), old_descriptors->GetKey(i), | 2971 old_descriptors->GetKey(i), |
2968 old_details.attributes()); | 2972 old_details.attributes()); |
2969 if (transition == NULL) return MaybeHandle<Map>(); | 2973 if (j == TransitionArray::kNotFound) return MaybeHandle<Map>(); |
2970 new_map = transition; | 2974 new_map = new_map->GetTransition(j); |
2971 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2975 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
2972 | 2976 |
2973 PropertyDetails new_details = new_descriptors->GetDetails(i); | 2977 PropertyDetails new_details = new_descriptors->GetDetails(i); |
2974 DCHECK_EQ(old_details.kind(), new_details.kind()); | 2978 DCHECK_EQ(old_details.kind(), new_details.kind()); |
2975 DCHECK_EQ(old_details.attributes(), new_details.attributes()); | 2979 DCHECK_EQ(old_details.attributes(), new_details.attributes()); |
2976 if (!old_details.representation().fits_into(new_details.representation())) { | 2980 if (!old_details.representation().fits_into(new_details.representation())) { |
2977 return MaybeHandle<Map>(); | 2981 return MaybeHandle<Map>(); |
2978 } | 2982 } |
2979 switch (new_details.type()) { | 2983 switch (new_details.type()) { |
2980 case DATA: { | 2984 case DATA: { |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3602 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) | 3606 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) |
3603 ? to_kind | 3607 ? to_kind |
3604 : TERMINAL_FAST_ELEMENTS_KIND; | 3608 : TERMINAL_FAST_ELEMENTS_KIND; |
3605 | 3609 |
3606 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data | 3610 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data |
3607 // allows to change elements from arbitrary kind to any ExternalArray | 3611 // allows to change elements from arbitrary kind to any ExternalArray |
3608 // elements kind. Satisfy its requirements, checking whether we already | 3612 // elements kind. Satisfy its requirements, checking whether we already |
3609 // have the cached transition. | 3613 // have the cached transition. |
3610 if (IsExternalArrayElementsKind(to_kind) && | 3614 if (IsExternalArrayElementsKind(to_kind) && |
3611 !IsFixedTypedArrayElementsKind(map->elements_kind())) { | 3615 !IsFixedTypedArrayElementsKind(map->elements_kind())) { |
3612 Map* next_map = map->ElementsTransitionMap(); | 3616 if (map->HasElementsTransition()) { |
3613 if (next_map != NULL && next_map->elements_kind() == to_kind) { | 3617 Map* next_map = map->elements_transition_map(); |
3614 return next_map; | 3618 if (next_map->elements_kind() == to_kind) return next_map; |
3615 } | 3619 } |
3616 return map; | 3620 return map; |
3617 } | 3621 } |
3618 | 3622 |
3619 ElementsKind kind = map->elements_kind(); | 3623 ElementsKind kind = map->elements_kind(); |
3620 while (kind != target_kind) { | 3624 while (kind != target_kind) { |
3621 kind = GetNextTransitionElementsKind(kind); | 3625 kind = GetNextTransitionElementsKind(kind); |
3622 Map* next_map = current_map->ElementsTransitionMap(); | 3626 if (!current_map->HasElementsTransition()) return current_map; |
3623 if (next_map == NULL) return current_map; | 3627 current_map = current_map->elements_transition_map(); |
3624 current_map = next_map; | |
3625 } | 3628 } |
3626 | 3629 |
3627 Map* next_map = current_map->ElementsTransitionMap(); | 3630 if (to_kind != kind && current_map->HasElementsTransition()) { |
3628 if (to_kind != kind && next_map != NULL) { | |
3629 DCHECK(to_kind == DICTIONARY_ELEMENTS); | 3631 DCHECK(to_kind == DICTIONARY_ELEMENTS); |
| 3632 Map* next_map = current_map->elements_transition_map(); |
3630 if (next_map->elements_kind() == to_kind) return next_map; | 3633 if (next_map->elements_kind() == to_kind) return next_map; |
3631 } | 3634 } |
3632 | 3635 |
3633 DCHECK(current_map->elements_kind() == target_kind); | 3636 DCHECK(current_map->elements_kind() == target_kind); |
3634 return current_map; | 3637 return current_map; |
3635 } | 3638 } |
3636 | 3639 |
3637 | 3640 |
3638 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 3641 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
3639 Map* to_map = FindClosestElementsTransition(this, to_kind); | 3642 Map* to_map = FindClosestElementsTransition(this, to_kind); |
(...skipping 2079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5719 if (attrs == NONE) { | 5722 if (attrs == NONE) { |
5720 transition_marker = isolate->factory()->nonextensible_symbol(); | 5723 transition_marker = isolate->factory()->nonextensible_symbol(); |
5721 } else if (attrs == SEALED) { | 5724 } else if (attrs == SEALED) { |
5722 transition_marker = isolate->factory()->sealed_symbol(); | 5725 transition_marker = isolate->factory()->sealed_symbol(); |
5723 } else { | 5726 } else { |
5724 DCHECK(attrs == FROZEN); | 5727 DCHECK(attrs == FROZEN); |
5725 transition_marker = isolate->factory()->frozen_symbol(); | 5728 transition_marker = isolate->factory()->frozen_symbol(); |
5726 } | 5729 } |
5727 | 5730 |
5728 Handle<Map> old_map(object->map(), isolate); | 5731 Handle<Map> old_map(object->map(), isolate); |
5729 Map* transition = | 5732 int transition_index = old_map->SearchSpecialTransition(*transition_marker); |
5730 TransitionArray::SearchSpecial(*old_map, *transition_marker); | 5733 if (transition_index != TransitionArray::kNotFound) { |
5731 if (transition != NULL) { | 5734 Handle<Map> transition_map(old_map->GetTransition(transition_index)); |
5732 Handle<Map> transition_map(transition, isolate); | |
5733 DCHECK(transition_map->has_dictionary_elements()); | 5735 DCHECK(transition_map->has_dictionary_elements()); |
5734 DCHECK(!transition_map->is_extensible()); | 5736 DCHECK(!transition_map->is_extensible()); |
5735 JSObject::MigrateToMap(object, transition_map); | 5737 JSObject::MigrateToMap(object, transition_map); |
5736 } else if (object->HasFastProperties() && | 5738 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5737 TransitionArray::CanHaveMoreTransitions(old_map)) { | |
5738 // Create a new descriptor array with the appropriate property attributes | 5739 // Create a new descriptor array with the appropriate property attributes |
5739 Handle<Map> new_map = Map::CopyForPreventExtensions( | 5740 Handle<Map> new_map = Map::CopyForPreventExtensions( |
5740 old_map, attrs, transition_marker, "CopyForPreventExtensions"); | 5741 old_map, attrs, transition_marker, "CopyForPreventExtensions"); |
5741 JSObject::MigrateToMap(object, new_map); | 5742 JSObject::MigrateToMap(object, new_map); |
5742 } else { | 5743 } else { |
5743 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); | 5744 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); |
5744 // Slow path: need to normalize properties for safety | 5745 // Slow path: need to normalize properties for safety |
5745 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, | 5746 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, |
5746 "SlowPreventExtensions"); | 5747 "SlowPreventExtensions"); |
5747 | 5748 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5786 } | 5787 } |
5787 | 5788 |
5788 | 5789 |
5789 void JSObject::SetObserved(Handle<JSObject> object) { | 5790 void JSObject::SetObserved(Handle<JSObject> object) { |
5790 DCHECK(!object->IsJSGlobalProxy()); | 5791 DCHECK(!object->IsJSGlobalProxy()); |
5791 DCHECK(!object->IsJSGlobalObject()); | 5792 DCHECK(!object->IsJSGlobalObject()); |
5792 Isolate* isolate = object->GetIsolate(); | 5793 Isolate* isolate = object->GetIsolate(); |
5793 Handle<Map> new_map; | 5794 Handle<Map> new_map; |
5794 Handle<Map> old_map(object->map(), isolate); | 5795 Handle<Map> old_map(object->map(), isolate); |
5795 DCHECK(!old_map->is_observed()); | 5796 DCHECK(!old_map->is_observed()); |
5796 Map* transition = TransitionArray::SearchSpecial( | 5797 int transition_index = |
5797 *old_map, isolate->heap()->observed_symbol()); | 5798 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); |
5798 if (transition != NULL) { | 5799 if (transition_index != TransitionArray::kNotFound) { |
5799 new_map = handle(transition, isolate); | 5800 new_map = handle(old_map->GetTransition(transition_index), isolate); |
5800 DCHECK(new_map->is_observed()); | 5801 DCHECK(new_map->is_observed()); |
5801 } else if (object->HasFastProperties() && | 5802 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5802 TransitionArray::CanHaveMoreTransitions(old_map)) { | |
5803 new_map = Map::CopyForObserved(old_map); | 5803 new_map = Map::CopyForObserved(old_map); |
5804 } else { | 5804 } else { |
5805 new_map = Map::Copy(old_map, "SlowObserved"); | 5805 new_map = Map::Copy(old_map, "SlowObserved"); |
5806 new_map->set_is_observed(); | 5806 new_map->set_is_observed(); |
5807 } | 5807 } |
5808 JSObject::MigrateToMap(object, new_map); | 5808 JSObject::MigrateToMap(object, new_map); |
5809 } | 5809 } |
5810 | 5810 |
5811 | 5811 |
5812 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, | 5812 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, |
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7011 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, | 7011 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, |
7012 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); | 7012 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); |
7013 name->NameShortPrint(); | 7013 name->NameShortPrint(); |
7014 PrintF(" ]\n"); | 7014 PrintF(" ]\n"); |
7015 } | 7015 } |
7016 } | 7016 } |
7017 | 7017 |
7018 | 7018 |
7019 // static | 7019 // static |
7020 void Map::TraceAllTransitions(Map* map) { | 7020 void Map::TraceAllTransitions(Map* map) { |
7021 Object* transitions = map->raw_transitions(); | 7021 if (!map->HasTransitionArray()) return; |
7022 int num_transitions = TransitionArray::NumberOfTransitions(transitions); | 7022 TransitionArray* transitions = map->transitions(); |
7023 for (int i = -0; i < num_transitions; ++i) { | 7023 for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
7024 Map* target = TransitionArray::GetTarget(transitions, i); | 7024 Map* target = transitions->GetTarget(i); |
7025 Name* key = TransitionArray::GetKey(transitions, i); | 7025 Map::TraceTransition("Transition", map, target, transitions->GetKey(i)); |
7026 Map::TraceTransition("Transition", map, target, key); | |
7027 Map::TraceAllTransitions(target); | 7026 Map::TraceAllTransitions(target); |
7028 } | 7027 } |
7029 } | 7028 } |
7030 | 7029 |
7031 #endif // TRACE_MAPS | 7030 #endif // TRACE_MAPS |
7032 | 7031 |
7033 | 7032 |
7034 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 7033 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
7035 Handle<Name> name, SimpleTransitionFlag flag) { | 7034 Handle<Name> name, SimpleTransitionFlag flag) { |
7036 parent->set_owns_descriptors(false); | 7035 parent->set_owns_descriptors(false); |
7037 if (parent->is_prototype_map()) { | 7036 if (parent->is_prototype_map()) { |
7038 DCHECK(child->is_prototype_map()); | 7037 DCHECK(child->is_prototype_map()); |
7039 #if TRACE_MAPS | 7038 #if TRACE_MAPS |
7040 Map::TraceTransition("NoTransition", *parent, *child, *name); | 7039 Map::TraceTransition("NoTransition", *parent, *child, *name); |
7041 #endif | 7040 #endif |
7042 } else { | 7041 } else { |
7043 TransitionArray::Insert(parent, name, child, flag); | 7042 Handle<TransitionArray> transitions = |
| 7043 TransitionArray::Insert(parent, name, child, flag); |
| 7044 if (!parent->HasTransitionArray() || |
| 7045 *transitions != parent->transitions()) { |
| 7046 parent->set_transitions(*transitions); |
| 7047 } |
| 7048 child->SetBackPointer(*parent); |
7044 if (child->prototype()->IsJSObject()) { | 7049 if (child->prototype()->IsJSObject()) { |
7045 Handle<JSObject> proto(JSObject::cast(child->prototype())); | 7050 Handle<JSObject> proto(JSObject::cast(child->prototype())); |
7046 if (!child->ShouldRegisterAsPrototypeUser(proto)) { | 7051 if (!child->ShouldRegisterAsPrototypeUser(proto)) { |
7047 JSObject::UnregisterPrototypeUser(proto, child); | 7052 JSObject::UnregisterPrototypeUser(proto, child); |
7048 } | 7053 } |
7049 } | 7054 } |
7050 #if TRACE_MAPS | 7055 #if TRACE_MAPS |
7051 Map::TraceTransition("Transition", *parent, *child, *name); | 7056 Map::TraceTransition("Transition", *parent, *child, *name); |
7052 #endif | 7057 #endif |
7053 } | 7058 } |
7054 } | 7059 } |
7055 | 7060 |
7056 | 7061 |
7057 Handle<Map> Map::CopyReplaceDescriptors( | 7062 Handle<Map> Map::CopyReplaceDescriptors( |
7058 Handle<Map> map, Handle<DescriptorArray> descriptors, | 7063 Handle<Map> map, Handle<DescriptorArray> descriptors, |
7059 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, | 7064 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, |
7060 MaybeHandle<Name> maybe_name, const char* reason, | 7065 MaybeHandle<Name> maybe_name, const char* reason, |
7061 SimpleTransitionFlag simple_flag) { | 7066 SimpleTransitionFlag simple_flag) { |
7062 DCHECK(descriptors->IsSortedNoDuplicates()); | 7067 DCHECK(descriptors->IsSortedNoDuplicates()); |
7063 | 7068 |
7064 Handle<Map> result = CopyDropDescriptors(map); | 7069 Handle<Map> result = CopyDropDescriptors(map); |
7065 | 7070 |
7066 if (!map->is_prototype_map()) { | 7071 if (!map->is_prototype_map()) { |
7067 if (flag == INSERT_TRANSITION && | 7072 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
7068 TransitionArray::CanHaveMoreTransitions(map)) { | |
7069 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7073 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7070 | 7074 |
7071 Handle<Name> name; | 7075 Handle<Name> name; |
7072 CHECK(maybe_name.ToHandle(&name)); | 7076 CHECK(maybe_name.ToHandle(&name)); |
7073 ConnectTransition(map, result, name, simple_flag); | 7077 ConnectTransition(map, result, name, simple_flag); |
7074 } else { | 7078 } else { |
7075 int length = descriptors->number_of_descriptors(); | 7079 int length = descriptors->number_of_descriptors(); |
7076 for (int i = 0; i < length; i++) { | 7080 for (int i = 0; i < length; i++) { |
7077 descriptors->SetRepresentation(i, Representation::Tagged()); | 7081 descriptors->SetRepresentation(i, Representation::Tagged()); |
7078 if (descriptors->GetDetails(i).type() == DATA) { | 7082 if (descriptors->GetDetails(i).type() == DATA) { |
7079 descriptors->SetValue(i, HeapType::Any()); | 7083 descriptors->SetValue(i, HeapType::Any()); |
7080 } | 7084 } |
7081 } | 7085 } |
7082 result->InitializeDescriptors(*descriptors, | 7086 result->InitializeDescriptors(*descriptors, |
7083 LayoutDescriptor::FastPointerLayout()); | 7087 LayoutDescriptor::FastPointerLayout()); |
7084 } | 7088 } |
7085 } else { | 7089 } else { |
7086 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7090 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7087 } | 7091 } |
7088 #if TRACE_MAPS | 7092 #if TRACE_MAPS |
7089 if (FLAG_trace_maps && | 7093 if (FLAG_trace_maps && |
7090 // Mirror conditions above that did not call ConnectTransition(). | 7094 // Mirror conditions above that did not call ConnectTransition(). |
7091 (map->is_prototype_map() || | 7095 (map->is_prototype_map() || |
7092 !(flag == INSERT_TRANSITION && | 7096 !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) { |
7093 TransitionArray::CanHaveMoreTransitions(map)))) { | |
7094 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", | 7097 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", |
7095 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), | 7098 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), |
7096 reason); | 7099 reason); |
7097 } | 7100 } |
7098 #endif | 7101 #endif |
7099 | 7102 |
7100 return result; | 7103 return result; |
7101 } | 7104 } |
7102 | 7105 |
7103 | 7106 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7141 | 7144 |
7142 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); | 7145 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
7143 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); | 7146 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
7144 | 7147 |
7145 return result; | 7148 return result; |
7146 } | 7149 } |
7147 | 7150 |
7148 | 7151 |
7149 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 7152 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
7150 TransitionFlag flag) { | 7153 TransitionFlag flag) { |
7151 Map* maybe_elements_transition_map = NULL; | |
7152 if (flag == INSERT_TRANSITION) { | 7154 if (flag == INSERT_TRANSITION) { |
7153 maybe_elements_transition_map = map->ElementsTransitionMap(); | 7155 DCHECK(!map->HasElementsTransition() || |
7154 DCHECK( | 7156 ((map->elements_transition_map()->elements_kind() == |
7155 maybe_elements_transition_map == NULL || | 7157 DICTIONARY_ELEMENTS || |
7156 ((maybe_elements_transition_map->elements_kind() == | |
7157 DICTIONARY_ELEMENTS || | |
7158 IsExternalArrayElementsKind( | 7158 IsExternalArrayElementsKind( |
7159 maybe_elements_transition_map->elements_kind())) && | 7159 map->elements_transition_map()->elements_kind())) && |
7160 (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind)))); | 7160 (kind == DICTIONARY_ELEMENTS || |
| 7161 IsExternalArrayElementsKind(kind)))); |
7161 DCHECK(!IsFastElementsKind(kind) || | 7162 DCHECK(!IsFastElementsKind(kind) || |
7162 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); | 7163 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
7163 DCHECK(kind != map->elements_kind()); | 7164 DCHECK(kind != map->elements_kind()); |
7164 } | 7165 } |
7165 | 7166 |
7166 bool insert_transition = flag == INSERT_TRANSITION && | 7167 bool insert_transition = flag == INSERT_TRANSITION && |
7167 TransitionArray::CanHaveMoreTransitions(map) && | 7168 map->CanHaveMoreTransitions() && |
7168 maybe_elements_transition_map == NULL; | 7169 !map->HasElementsTransition(); |
7169 | 7170 |
7170 if (insert_transition) { | 7171 if (insert_transition) { |
7171 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); | 7172 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); |
7172 new_map->set_elements_kind(kind); | 7173 new_map->set_elements_kind(kind); |
7173 | 7174 |
7174 ConnectElementsTransition(map, new_map); | 7175 ConnectElementsTransition(map, new_map); |
7175 | 7176 |
7176 return new_map; | 7177 return new_map; |
7177 } | 7178 } |
7178 | 7179 |
7179 // Create a new free-floating map only if we are not allowed to store it. | 7180 // Create a new free-floating map only if we are not allowed to store it. |
7180 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); | 7181 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); |
7181 new_map->set_elements_kind(kind); | 7182 new_map->set_elements_kind(kind); |
7182 return new_map; | 7183 return new_map; |
7183 } | 7184 } |
7184 | 7185 |
7185 | 7186 |
7186 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 7187 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
7187 DCHECK(!map->is_observed()); | 7188 DCHECK(!map->is_observed()); |
7188 | 7189 |
7189 Isolate* isolate = map->GetIsolate(); | 7190 Isolate* isolate = map->GetIsolate(); |
7190 | 7191 |
7191 bool insert_transition = | 7192 bool insert_transition = |
7192 TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map(); | 7193 map->CanHaveMoreTransitions() && !map->is_prototype_map(); |
7193 | 7194 |
7194 if (insert_transition) { | 7195 if (insert_transition) { |
7195 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); | 7196 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); |
7196 new_map->set_is_observed(); | 7197 new_map->set_is_observed(); |
7197 | 7198 |
7198 Handle<Name> name = isolate->factory()->observed_symbol(); | 7199 Handle<Name> name = isolate->factory()->observed_symbol(); |
7199 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); | 7200 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
7200 return new_map; | 7201 return new_map; |
7201 } | 7202 } |
7202 | 7203 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7348 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 7349 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
7349 Handle<Object> value, | 7350 Handle<Object> value, |
7350 PropertyAttributes attributes, | 7351 PropertyAttributes attributes, |
7351 StoreFromKeyed store_mode) { | 7352 StoreFromKeyed store_mode) { |
7352 // Dictionary maps can always have additional data properties. | 7353 // Dictionary maps can always have additional data properties. |
7353 if (map->is_dictionary_map()) return map; | 7354 if (map->is_dictionary_map()) return map; |
7354 | 7355 |
7355 // Migrate to the newest map before storing the property. | 7356 // Migrate to the newest map before storing the property. |
7356 map = Update(map); | 7357 map = Update(map); |
7357 | 7358 |
7358 Map* maybe_transition = | 7359 int index = map->SearchTransition(kData, *name, attributes); |
7359 TransitionArray::SearchTransition(*map, kData, *name, attributes); | 7360 if (index != TransitionArray::kNotFound) { |
7360 if (maybe_transition != NULL) { | 7361 Handle<Map> transition(map->GetTransition(index)); |
7361 Handle<Map> transition(maybe_transition); | |
7362 int descriptor = transition->LastAdded(); | 7362 int descriptor = transition->LastAdded(); |
7363 | 7363 |
7364 DCHECK_EQ(attributes, transition->instance_descriptors() | 7364 DCHECK_EQ(attributes, transition->instance_descriptors() |
7365 ->GetDetails(descriptor) | 7365 ->GetDetails(descriptor) |
7366 .attributes()); | 7366 .attributes()); |
7367 | 7367 |
7368 return Map::PrepareForDataProperty(transition, descriptor, value); | 7368 return Map::PrepareForDataProperty(transition, descriptor, value); |
7369 } | 7369 } |
7370 | 7370 |
7371 TransitionFlag flag = INSERT_TRANSITION; | 7371 TransitionFlag flag = INSERT_TRANSITION; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7440 return map; | 7440 return map; |
7441 } | 7441 } |
7442 | 7442 |
7443 // Migrate to the newest map before transitioning to the new property. | 7443 // Migrate to the newest map before transitioning to the new property. |
7444 map = Update(map); | 7444 map = Update(map); |
7445 | 7445 |
7446 PropertyNormalizationMode mode = map->is_prototype_map() | 7446 PropertyNormalizationMode mode = map->is_prototype_map() |
7447 ? KEEP_INOBJECT_PROPERTIES | 7447 ? KEEP_INOBJECT_PROPERTIES |
7448 : CLEAR_INOBJECT_PROPERTIES; | 7448 : CLEAR_INOBJECT_PROPERTIES; |
7449 | 7449 |
7450 Map* maybe_transition = | 7450 int index = map->SearchTransition(kAccessor, *name, attributes); |
7451 TransitionArray::SearchTransition(*map, kAccessor, *name, attributes); | 7451 if (index != TransitionArray::kNotFound) { |
7452 if (maybe_transition != NULL) { | 7452 Handle<Map> transition(map->GetTransition(index)); |
7453 Handle<Map> transition(maybe_transition, isolate); | |
7454 DescriptorArray* descriptors = transition->instance_descriptors(); | 7453 DescriptorArray* descriptors = transition->instance_descriptors(); |
7455 int descriptor = transition->LastAdded(); | 7454 int descriptor = transition->LastAdded(); |
7456 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); | 7455 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
7457 | 7456 |
7458 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); | 7457 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); |
7459 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); | 7458 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
7460 | 7459 |
7461 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); | 7460 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
7462 if (!maybe_pair->IsAccessorPair()) { | 7461 if (!maybe_pair->IsAccessorPair()) { |
7463 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); | 7462 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7515 | 7514 |
7516 | 7515 |
7517 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, | 7516 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
7518 Descriptor* descriptor, | 7517 Descriptor* descriptor, |
7519 TransitionFlag flag) { | 7518 TransitionFlag flag) { |
7520 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 7519 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
7521 | 7520 |
7522 // Ensure the key is unique. | 7521 // Ensure the key is unique. |
7523 descriptor->KeyToUniqueName(); | 7522 descriptor->KeyToUniqueName(); |
7524 | 7523 |
7525 if (flag == INSERT_TRANSITION && map->owns_descriptors() && | 7524 if (flag == INSERT_TRANSITION && |
7526 TransitionArray::CanHaveMoreTransitions(map)) { | 7525 map->owns_descriptors() && |
| 7526 map->CanHaveMoreTransitions()) { |
7527 return ShareDescriptor(map, descriptors, descriptor); | 7527 return ShareDescriptor(map, descriptors, descriptor); |
7528 } | 7528 } |
7529 | 7529 |
7530 int nof = map->NumberOfOwnDescriptors(); | 7530 int nof = map->NumberOfOwnDescriptors(); |
7531 Handle<DescriptorArray> new_descriptors = | 7531 Handle<DescriptorArray> new_descriptors = |
7532 DescriptorArray::CopyUpTo(descriptors, nof, 1); | 7532 DescriptorArray::CopyUpTo(descriptors, nof, 1); |
7533 new_descriptors->Append(descriptor); | 7533 new_descriptors->Append(descriptor); |
7534 | 7534 |
7535 Handle<LayoutDescriptor> new_layout_descriptor = | 7535 Handle<LayoutDescriptor> new_layout_descriptor = |
7536 FLAG_unbox_double_fields | 7536 FLAG_unbox_double_fields |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7680 | 7680 |
7681 | 7681 |
7682 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { | 7682 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { |
7683 // No GC is supposed to happen between a call to IndexInCodeCache and | 7683 // No GC is supposed to happen between a call to IndexInCodeCache and |
7684 // RemoveFromCodeCache so the code cache must be there. | 7684 // RemoveFromCodeCache so the code cache must be there. |
7685 DCHECK(!code_cache()->IsFixedArray()); | 7685 DCHECK(!code_cache()->IsFixedArray()); |
7686 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); | 7686 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
7687 } | 7687 } |
7688 | 7688 |
7689 | 7689 |
| 7690 static void TraverseTransitionTreeInternal(Map* map, |
| 7691 Map::TraverseCallback callback, |
| 7692 void* data) { |
| 7693 if (map->HasTransitionArray()) { |
| 7694 TransitionArray* transitions = map->transitions(); |
| 7695 if (transitions->HasPrototypeTransitions()) { |
| 7696 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); |
| 7697 Object* num_obj = |
| 7698 proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); |
| 7699 int num = Smi::cast(num_obj)->value(); |
| 7700 for (int i = 0; i < num; ++i) { |
| 7701 int index = Map::kProtoTransitionHeaderSize + i; |
| 7702 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), |
| 7703 callback, data); |
| 7704 } |
| 7705 } |
| 7706 for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
| 7707 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); |
| 7708 } |
| 7709 } |
| 7710 callback(map, data); |
| 7711 } |
| 7712 |
| 7713 |
| 7714 // Traverse the transition tree in postorder. |
| 7715 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
| 7716 // Make sure that we do not allocate in the callback. |
| 7717 DisallowHeapAllocation no_allocation; |
| 7718 TraverseTransitionTreeInternal(this, callback, data); |
| 7719 } |
| 7720 |
| 7721 |
7690 void CodeCache::Update( | 7722 void CodeCache::Update( |
7691 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | 7723 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { |
7692 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 7724 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
7693 // a large number and therefore they need to go into a hash table. They are | 7725 // a large number and therefore they need to go into a hash table. They are |
7694 // used to load global properties from cells. | 7726 // used to load global properties from cells. |
7695 if (code->type() == Code::NORMAL) { | 7727 if (code->type() == Code::NORMAL) { |
7696 // Make sure that a hash table is allocated for the normal load code cache. | 7728 // Make sure that a hash table is allocated for the normal load code cache. |
7697 if (code_cache->normal_type_cache()->IsUndefined()) { | 7729 if (code_cache->normal_type_cache()->IsUndefined()) { |
7698 Handle<Object> result = | 7730 Handle<Object> result = |
7699 CodeCacheHashTable::New(code_cache->GetIsolate(), | 7731 CodeCacheHashTable::New(code_cache->GetIsolate(), |
(...skipping 2153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9853 | 9885 |
9854 | 9886 |
9855 void JSFunction::CompleteInobjectSlackTracking() { | 9887 void JSFunction::CompleteInobjectSlackTracking() { |
9856 DCHECK(has_initial_map()); | 9888 DCHECK(has_initial_map()); |
9857 Map* map = initial_map(); | 9889 Map* map = initial_map(); |
9858 | 9890 |
9859 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); | 9891 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); |
9860 map->set_counter(Map::kRetainingCounterStart); | 9892 map->set_counter(Map::kRetainingCounterStart); |
9861 | 9893 |
9862 int slack = map->unused_property_fields(); | 9894 int slack = map->unused_property_fields(); |
9863 TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack); | 9895 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
9864 if (slack != 0) { | 9896 if (slack != 0) { |
9865 // Resize the initial map and all maps in its transition tree. | 9897 // Resize the initial map and all maps in its transition tree. |
9866 TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack); | 9898 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
9867 } | 9899 } |
9868 } | 9900 } |
9869 | 9901 |
9870 | 9902 |
9871 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { | 9903 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { |
9872 DisallowHeapAllocation no_gc; | 9904 DisallowHeapAllocation no_gc; |
9873 if (!object->HasFastProperties()) return false; | 9905 if (!object->HasFastProperties()) return false; |
9874 Map* map = object->map(); | 9906 Map* map = object->map(); |
9875 if (map->is_prototype_map()) return false; | 9907 if (map->is_prototype_map()) return false; |
9876 DescriptorArray* descriptors = map->instance_descriptors(); | 9908 DescriptorArray* descriptors = map->instance_descriptors(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10009 kElementsKindCount, TENURED); | 10041 kElementsKindCount, TENURED); |
10010 | 10042 |
10011 Handle<Map> current_map = initial_map; | 10043 Handle<Map> current_map = initial_map; |
10012 ElementsKind kind = current_map->elements_kind(); | 10044 ElementsKind kind = current_map->elements_kind(); |
10013 DCHECK(kind == GetInitialFastElementsKind()); | 10045 DCHECK(kind == GetInitialFastElementsKind()); |
10014 maps->set(kind, *current_map); | 10046 maps->set(kind, *current_map); |
10015 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 10047 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
10016 i < kFastElementsKindCount; ++i) { | 10048 i < kFastElementsKindCount; ++i) { |
10017 Handle<Map> new_map; | 10049 Handle<Map> new_map; |
10018 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); | 10050 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
10019 Map* maybe_elements_transition = current_map->ElementsTransitionMap(); | 10051 if (current_map->HasElementsTransition()) { |
10020 if (maybe_elements_transition != NULL) { | 10052 new_map = handle(current_map->elements_transition_map()); |
10021 new_map = handle(maybe_elements_transition); | |
10022 DCHECK(new_map->elements_kind() == next_kind); | 10053 DCHECK(new_map->elements_kind() == next_kind); |
10023 } else { | 10054 } else { |
10024 new_map = Map::CopyAsElementsKind( | 10055 new_map = Map::CopyAsElementsKind( |
10025 current_map, next_kind, INSERT_TRANSITION); | 10056 current_map, next_kind, INSERT_TRANSITION); |
10026 } | 10057 } |
10027 maps->set(next_kind, *new_map); | 10058 maps->set(next_kind, *new_map); |
10028 current_map = new_map; | 10059 current_map = new_map; |
10029 } | 10060 } |
10030 native_context->set_js_array_maps(*maps); | 10061 native_context->set_js_array_maps(*maps); |
10031 return initial_map; | 10062 return initial_map; |
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11932 Object); | 11963 Object); |
11933 } | 11964 } |
11934 | 11965 |
11935 RETURN_ON_EXCEPTION( | 11966 RETURN_ON_EXCEPTION( |
11936 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); | 11967 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); |
11937 | 11968 |
11938 return hresult; | 11969 return hresult; |
11939 } | 11970 } |
11940 | 11971 |
11941 | 11972 |
| 11973 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, |
| 11974 Handle<Object> prototype) { |
| 11975 DisallowHeapAllocation no_gc; |
| 11976 FixedArray* cache = map->GetPrototypeTransitions(); |
| 11977 int number_of_transitions = map->NumberOfProtoTransitions(); |
| 11978 for (int i = 0; i < number_of_transitions; i++) { |
| 11979 Map* map = Map::cast(cache->get(kProtoTransitionHeaderSize + i)); |
| 11980 if (map->prototype() == *prototype) return handle(map); |
| 11981 } |
| 11982 return Handle<Map>(); |
| 11983 } |
| 11984 |
| 11985 |
| 11986 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
| 11987 Handle<Object> prototype, |
| 11988 Handle<Map> target_map) { |
| 11989 DCHECK(target_map->IsMap()); |
| 11990 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
| 11991 // Don't cache prototype transition if this map is either shared, or a map of |
| 11992 // a prototype. |
| 11993 if (map->is_prototype_map()) return map; |
| 11994 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map; |
| 11995 |
| 11996 const int header = kProtoTransitionHeaderSize; |
| 11997 |
| 11998 Handle<FixedArray> cache(map->GetPrototypeTransitions()); |
| 11999 int capacity = cache->length() - header; |
| 12000 int transitions = map->NumberOfProtoTransitions() + 1; |
| 12001 |
| 12002 if (transitions > capacity) { |
| 12003 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. |
| 12004 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); |
| 12005 if (new_capacity == capacity) return map; |
| 12006 |
| 12007 cache = FixedArray::CopySize(cache, header + new_capacity); |
| 12008 |
| 12009 SetPrototypeTransitions(map, cache); |
| 12010 } |
| 12011 |
| 12012 // Reload number of transitions as GC might shrink them. |
| 12013 int last = map->NumberOfProtoTransitions(); |
| 12014 int entry = header + last; |
| 12015 |
| 12016 cache->set(entry, *target_map); |
| 12017 map->SetNumberOfProtoTransitions(last + 1); |
| 12018 |
| 12019 return map; |
| 12020 } |
| 12021 |
| 12022 |
| 12023 void Map::ZapTransitions() { |
| 12024 TransitionArray* transition_array = transitions(); |
| 12025 // TODO(mstarzinger): Temporarily use a slower version instead of the faster |
| 12026 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. |
| 12027 Object** data = transition_array->data_start(); |
| 12028 Object* the_hole = GetHeap()->the_hole_value(); |
| 12029 int length = transition_array->length(); |
| 12030 for (int i = 0; i < length; i++) { |
| 12031 data[i] = the_hole; |
| 12032 } |
| 12033 } |
| 12034 |
| 12035 |
| 12036 void Map::ZapPrototypeTransitions() { |
| 12037 FixedArray* proto_transitions = GetPrototypeTransitions(); |
| 12038 MemsetPointer(proto_transitions->data_start(), |
| 12039 GetHeap()->the_hole_value(), |
| 12040 proto_transitions->length()); |
| 12041 } |
| 12042 |
| 12043 |
11942 // static | 12044 // static |
11943 void Map::AddDependentCompilationInfo(Handle<Map> map, | 12045 void Map::AddDependentCompilationInfo(Handle<Map> map, |
11944 DependentCode::DependencyGroup group, | 12046 DependentCode::DependencyGroup group, |
11945 CompilationInfo* info) { | 12047 CompilationInfo* info) { |
11946 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 12048 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
11947 handle(map->dependent_code(), info->isolate()), group, | 12049 handle(map->dependent_code(), info->isolate()), group, |
11948 info->object_wrapper()); | 12050 info->object_wrapper()); |
11949 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); | 12051 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); |
11950 info->dependencies(group)->Add(map, info->zone()); | 12052 info->dependencies(group)->Add(map, info->zone()); |
11951 } | 12053 } |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12237 return "allocation-site-transition-changed"; | 12339 return "allocation-site-transition-changed"; |
12238 } | 12340 } |
12239 UNREACHABLE(); | 12341 UNREACHABLE(); |
12240 return "?"; | 12342 return "?"; |
12241 } | 12343 } |
12242 | 12344 |
12243 | 12345 |
12244 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, | 12346 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, |
12245 Handle<Object> prototype, | 12347 Handle<Object> prototype, |
12246 PrototypeOptimizationMode mode) { | 12348 PrototypeOptimizationMode mode) { |
12247 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype); | 12349 Handle<Map> new_map = GetPrototypeTransition(map, prototype); |
12248 if (new_map.is_null()) { | 12350 if (new_map.is_null()) { |
12249 new_map = Copy(map, "TransitionToPrototype"); | 12351 new_map = Copy(map, "TransitionToPrototype"); |
12250 TransitionArray::PutPrototypeTransition(map, prototype, new_map); | 12352 PutPrototypeTransition(map, prototype, new_map); |
12251 new_map->SetPrototype(prototype, mode); | 12353 new_map->SetPrototype(prototype, mode); |
12252 } | 12354 } |
12253 return new_map; | 12355 return new_map; |
12254 } | 12356 } |
12255 | 12357 |
12256 | 12358 |
12257 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, | 12359 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
12258 Handle<Object> value, | 12360 Handle<Object> value, |
12259 bool from_javascript) { | 12361 bool from_javascript) { |
12260 #ifdef DEBUG | 12362 #ifdef DEBUG |
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17064 CompilationInfo* info) { | 17166 CompilationInfo* info) { |
17065 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17167 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17066 handle(cell->dependent_code(), info->isolate()), | 17168 handle(cell->dependent_code(), info->isolate()), |
17067 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17169 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17068 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17170 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17069 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17171 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17070 cell, info->zone()); | 17172 cell, info->zone()); |
17071 } | 17173 } |
17072 | 17174 |
17073 } } // namespace v8::internal | 17175 } } // namespace v8::internal |
OLD | NEW |