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(!old_map->HasTransitionArray()); | 1903 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( |
| 1904 old_map->raw_transitions())); |
1904 DCHECK(new_map->GetBackPointer()->IsUndefined()); | 1905 DCHECK(new_map->GetBackPointer()->IsUndefined()); |
1905 } | 1906 } |
1906 } else { | 1907 } else { |
1907 MigrateFastToSlow(object, new_map, 0); | 1908 MigrateFastToSlow(object, new_map, 0); |
1908 } | 1909 } |
1909 } else { | 1910 } else { |
1910 // For slow-to-fast migrations JSObject::TransformToFastProperties() | 1911 // For slow-to-fast migrations JSObject::TransformToFastProperties() |
1911 // must be used instead. | 1912 // must be used instead. |
1912 CHECK(new_map->is_dictionary_map()); | 1913 CHECK(new_map->is_dictionary_map()); |
1913 | 1914 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2179 details.representation(), Representation::Tagged(), field_type, | 2180 details.representation(), Representation::Tagged(), field_type, |
2180 HeapType::Any()); | 2181 HeapType::Any()); |
2181 } | 2182 } |
2182 } | 2183 } |
2183 return new_map; | 2184 return new_map; |
2184 } | 2185 } |
2185 | 2186 |
2186 | 2187 |
2187 void Map::DeprecateTransitionTree() { | 2188 void Map::DeprecateTransitionTree() { |
2188 if (is_deprecated()) return; | 2189 if (is_deprecated()) return; |
2189 if (HasTransitionArray()) { | 2190 Object* transitions = raw_transitions(); |
2190 TransitionArray* transitions = this->transitions(); | 2191 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
2191 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2192 for (int i = 0; i < num_transitions; ++i) { |
2192 transitions->GetTarget(i)->DeprecateTransitionTree(); | 2193 TransitionArray::GetTarget(transitions, 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 if (HasTransitionArray()) { | 2218 Map* maybe_transition = |
2219 TransitionArray* transitions = this->transitions(); | 2219 TransitionArray::SearchTransition(this, kind, key, attributes); |
2220 int transition = transitions->Search(kind, key, attributes); | 2220 if (maybe_transition != NULL) { |
2221 if (transition != TransitionArray::kNotFound) { | 2221 maybe_transition->DeprecateTransitionTree(); |
2222 transitions->GetTarget(transition)->DeprecateTransitionTree(); | 2222 transition_target_deprecated = true; |
2223 transition_target_deprecated = true; | |
2224 } | |
2225 } | 2223 } |
2226 | 2224 |
2227 // Don't overwrite the empty descriptor array. | 2225 // Don't overwrite the empty descriptor array. |
2228 if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated; | 2226 if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated; |
2229 | 2227 |
2230 DescriptorArray* to_replace = instance_descriptors(); | 2228 DescriptorArray* to_replace = instance_descriptors(); |
2231 Map* current = this; | 2229 Map* current = this; |
2232 GetHeap()->incremental_marking()->RecordWrites(to_replace); | 2230 GetHeap()->incremental_marking()->RecordWrites(to_replace); |
2233 while (current->instance_descriptors() == to_replace) { | 2231 while (current->instance_descriptors() == to_replace) { |
2234 current->SetEnumLength(kInvalidEnumCacheSentinel); | 2232 current->SetEnumLength(kInvalidEnumCacheSentinel); |
(...skipping 22 matching lines...) Expand all Loading... |
2257 int length, | 2255 int length, |
2258 DescriptorArray* descriptors) { | 2256 DescriptorArray* descriptors) { |
2259 DisallowHeapAllocation no_allocation; | 2257 DisallowHeapAllocation no_allocation; |
2260 | 2258 |
2261 // This can only be called on roots of transition trees. | 2259 // This can only be called on roots of transition trees. |
2262 DCHECK_EQ(verbatim, NumberOfOwnDescriptors()); | 2260 DCHECK_EQ(verbatim, NumberOfOwnDescriptors()); |
2263 | 2261 |
2264 Map* current = this; | 2262 Map* current = this; |
2265 | 2263 |
2266 for (int i = verbatim; i < length; i++) { | 2264 for (int i = verbatim; i < length; i++) { |
2267 if (!current->HasTransitionArray()) break; | |
2268 Name* name = descriptors->GetKey(i); | 2265 Name* name = descriptors->GetKey(i); |
2269 PropertyDetails details = descriptors->GetDetails(i); | 2266 PropertyDetails details = descriptors->GetDetails(i); |
2270 TransitionArray* transitions = current->transitions(); | 2267 Map* next = TransitionArray::SearchTransition(current, details.kind(), name, |
2271 int transition = | 2268 details.attributes()); |
2272 transitions->Search(details.kind(), name, details.attributes()); | 2269 if (next == NULL) break; |
2273 if (transition == TransitionArray::kNotFound) break; | |
2274 | |
2275 Map* next = transitions->GetTarget(transition); | |
2276 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2270 DescriptorArray* next_descriptors = next->instance_descriptors(); |
2277 | 2271 |
2278 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2272 PropertyDetails next_details = next_descriptors->GetDetails(i); |
2279 DCHECK_EQ(details.kind(), next_details.kind()); | 2273 DCHECK_EQ(details.kind(), next_details.kind()); |
2280 DCHECK_EQ(details.attributes(), next_details.attributes()); | 2274 DCHECK_EQ(details.attributes(), next_details.attributes()); |
2281 if (details.location() != next_details.location()) break; | 2275 if (details.location() != next_details.location()) break; |
2282 if (!details.representation().Equals(next_details.representation())) break; | 2276 if (!details.representation().Equals(next_details.representation())) break; |
2283 | 2277 |
2284 if (next_details.location() == kField) { | 2278 if (next_details.location() == kField) { |
2285 HeapType* next_field_type = next_descriptors->GetFieldType(i); | 2279 HeapType* next_field_type = next_descriptors->GetFieldType(i); |
(...skipping 27 matching lines...) Expand all Loading... |
2313 } | 2307 } |
2314 | 2308 |
2315 | 2309 |
2316 void Map::UpdateFieldType(int descriptor, Handle<Name> name, | 2310 void Map::UpdateFieldType(int descriptor, Handle<Name> name, |
2317 Representation new_representation, | 2311 Representation new_representation, |
2318 Handle<Object> new_wrapped_type) { | 2312 Handle<Object> new_wrapped_type) { |
2319 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); | 2313 DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell()); |
2320 DisallowHeapAllocation no_allocation; | 2314 DisallowHeapAllocation no_allocation; |
2321 PropertyDetails details = instance_descriptors()->GetDetails(descriptor); | 2315 PropertyDetails details = instance_descriptors()->GetDetails(descriptor); |
2322 if (details.type() != DATA) return; | 2316 if (details.type() != DATA) return; |
2323 if (HasTransitionArray()) { | 2317 Object* transitions = raw_transitions(); |
2324 TransitionArray* transitions = this->transitions(); | 2318 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
2325 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | 2319 for (int i = 0; i < num_transitions; ++i) { |
2326 transitions->GetTarget(i)->UpdateFieldType( | 2320 Map* target = TransitionArray::GetTarget(transitions, i); |
2327 descriptor, name, new_representation, new_wrapped_type); | 2321 target->UpdateFieldType(descriptor, name, new_representation, |
2328 } | 2322 new_wrapped_type); |
2329 } | 2323 } |
2330 // It is allowed to change representation here only from None to something. | 2324 // It is allowed to change representation here only from None to something. |
2331 DCHECK(details.representation().Equals(new_representation) || | 2325 DCHECK(details.representation().Equals(new_representation) || |
2332 details.representation().IsNone()); | 2326 details.representation().IsNone()); |
2333 | 2327 |
2334 // Skip if already updated the shared descriptor. | 2328 // Skip if already updated the shared descriptor. |
2335 if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return; | 2329 if (instance_descriptors()->GetValue(descriptor) == *new_wrapped_type) return; |
2336 DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), | 2330 DataDescriptor d(name, instance_descriptors()->GetFieldIndex(descriptor), |
2337 new_wrapped_type, details.attributes(), new_representation); | 2331 new_wrapped_type, details.attributes(), new_representation); |
2338 instance_descriptors()->Replace(descriptor, &d); | 2332 instance_descriptors()->Replace(descriptor, &d); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2558 next_representation = | 2552 next_representation = |
2559 next_representation.generalize(old_details.representation()); | 2553 next_representation.generalize(old_details.representation()); |
2560 } | 2554 } |
2561 | 2555 |
2562 } else { | 2556 } else { |
2563 next_kind = old_details.kind(); | 2557 next_kind = old_details.kind(); |
2564 next_location = old_details.location(); | 2558 next_location = old_details.location(); |
2565 next_attributes = old_details.attributes(); | 2559 next_attributes = old_details.attributes(); |
2566 next_representation = old_details.representation(); | 2560 next_representation = old_details.representation(); |
2567 } | 2561 } |
2568 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), | 2562 Map* transition = TransitionArray::SearchTransition( |
2569 next_attributes); | 2563 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); |
2570 if (j == TransitionArray::kNotFound) break; | 2564 if (transition == NULL) break; |
2571 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2565 Handle<Map> tmp_map(transition, isolate); |
| 2566 |
2572 Handle<DescriptorArray> tmp_descriptors = handle( | 2567 Handle<DescriptorArray> tmp_descriptors = handle( |
2573 tmp_map->instance_descriptors(), isolate); | 2568 tmp_map->instance_descriptors(), isolate); |
2574 | 2569 |
2575 // Check if target map is incompatible. | 2570 // Check if target map is incompatible. |
2576 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2571 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2577 DCHECK_EQ(next_kind, tmp_details.kind()); | 2572 DCHECK_EQ(next_kind, tmp_details.kind()); |
2578 DCHECK_EQ(next_attributes, tmp_details.attributes()); | 2573 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
2579 if (next_kind == kAccessor && | 2574 if (next_kind == kAccessor && |
2580 !EqualImmutableValues(old_descriptors->GetValue(i), | 2575 !EqualImmutableValues(old_descriptors->GetValue(i), |
2581 tmp_descriptors->GetValue(i))) { | 2576 tmp_descriptors->GetValue(i))) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2646 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2641 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2647 PropertyKind next_kind; | 2642 PropertyKind next_kind; |
2648 PropertyAttributes next_attributes; | 2643 PropertyAttributes next_attributes; |
2649 if (modify_index == i) { | 2644 if (modify_index == i) { |
2650 next_kind = new_kind; | 2645 next_kind = new_kind; |
2651 next_attributes = new_attributes; | 2646 next_attributes = new_attributes; |
2652 } else { | 2647 } else { |
2653 next_kind = old_details.kind(); | 2648 next_kind = old_details.kind(); |
2654 next_attributes = old_details.attributes(); | 2649 next_attributes = old_details.attributes(); |
2655 } | 2650 } |
2656 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), | 2651 Map* transition = TransitionArray::SearchTransition( |
2657 next_attributes); | 2652 *target_map, next_kind, old_descriptors->GetKey(i), next_attributes); |
2658 if (j == TransitionArray::kNotFound) break; | 2653 if (transition == NULL) break; |
2659 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2654 Handle<Map> tmp_map(transition, isolate); |
2660 Handle<DescriptorArray> tmp_descriptors( | 2655 Handle<DescriptorArray> tmp_descriptors( |
2661 tmp_map->instance_descriptors(), isolate); | 2656 tmp_map->instance_descriptors(), isolate); |
2662 | 2657 |
2663 // Check if target map is compatible. | 2658 // Check if target map is compatible. |
2664 #ifdef DEBUG | 2659 #ifdef DEBUG |
2665 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2660 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2666 DCHECK_EQ(next_kind, tmp_details.kind()); | 2661 DCHECK_EQ(next_kind, tmp_details.kind()); |
2667 DCHECK_EQ(next_attributes, tmp_details.attributes()); | 2662 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
2668 #endif | 2663 #endif |
2669 if (next_kind == kAccessor && | 2664 if (next_kind == kAccessor && |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2887 split_kind = split_prop_details.kind(); | 2882 split_kind = split_prop_details.kind(); |
2888 split_attributes = split_prop_details.attributes(); | 2883 split_attributes = split_prop_details.attributes(); |
2889 } | 2884 } |
2890 bool transition_target_deprecated = split_map->DeprecateTarget( | 2885 bool transition_target_deprecated = split_map->DeprecateTarget( |
2891 split_kind, old_descriptors->GetKey(split_nof), split_attributes, | 2886 split_kind, old_descriptors->GetKey(split_nof), split_attributes, |
2892 *new_descriptors, *new_layout_descriptor); | 2887 *new_descriptors, *new_layout_descriptor); |
2893 | 2888 |
2894 // If |transition_target_deprecated| is true then the transition array | 2889 // If |transition_target_deprecated| is true then the transition array |
2895 // already contains entry for given descriptor. This means that the transition | 2890 // already contains entry for given descriptor. This means that the transition |
2896 // could be inserted regardless of whether transitions array is full or not. | 2891 // could be inserted regardless of whether transitions array is full or not. |
2897 if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) { | 2892 if (!transition_target_deprecated && |
| 2893 !TransitionArray::CanHaveMoreTransitions(split_map)) { |
2898 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2894 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2899 new_kind, new_attributes, | 2895 new_kind, new_attributes, |
2900 "GenAll_CantHaveMoreTransitions"); | 2896 "GenAll_CantHaveMoreTransitions"); |
2901 } | 2897 } |
2902 | 2898 |
2903 if (FLAG_trace_generalization && modify_index >= 0) { | 2899 if (FLAG_trace_generalization && modify_index >= 0) { |
2904 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2900 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2905 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2901 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
2906 Handle<HeapType> old_field_type = | 2902 Handle<HeapType> old_field_type = |
2907 (old_details.type() == DATA) | 2903 (old_details.type() == DATA) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2960 Map* root_map = old_map->FindRootMap(); | 2956 Map* root_map = old_map->FindRootMap(); |
2961 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); | 2957 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); |
2962 int root_nof = root_map->NumberOfOwnDescriptors(); | 2958 int root_nof = root_map->NumberOfOwnDescriptors(); |
2963 | 2959 |
2964 int old_nof = old_map->NumberOfOwnDescriptors(); | 2960 int old_nof = old_map->NumberOfOwnDescriptors(); |
2965 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2961 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2966 | 2962 |
2967 Map* new_map = root_map; | 2963 Map* new_map = root_map; |
2968 for (int i = root_nof; i < old_nof; ++i) { | 2964 for (int i = root_nof; i < old_nof; ++i) { |
2969 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2965 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2970 int j = new_map->SearchTransition(old_details.kind(), | 2966 Map* transition = TransitionArray::SearchTransition( |
2971 old_descriptors->GetKey(i), | 2967 new_map, old_details.kind(), old_descriptors->GetKey(i), |
2972 old_details.attributes()); | 2968 old_details.attributes()); |
2973 if (j == TransitionArray::kNotFound) return MaybeHandle<Map>(); | 2969 if (transition == NULL) return MaybeHandle<Map>(); |
2974 new_map = new_map->GetTransition(j); | 2970 new_map = transition; |
2975 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2971 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
2976 | 2972 |
2977 PropertyDetails new_details = new_descriptors->GetDetails(i); | 2973 PropertyDetails new_details = new_descriptors->GetDetails(i); |
2978 DCHECK_EQ(old_details.kind(), new_details.kind()); | 2974 DCHECK_EQ(old_details.kind(), new_details.kind()); |
2979 DCHECK_EQ(old_details.attributes(), new_details.attributes()); | 2975 DCHECK_EQ(old_details.attributes(), new_details.attributes()); |
2980 if (!old_details.representation().fits_into(new_details.representation())) { | 2976 if (!old_details.representation().fits_into(new_details.representation())) { |
2981 return MaybeHandle<Map>(); | 2977 return MaybeHandle<Map>(); |
2982 } | 2978 } |
2983 switch (new_details.type()) { | 2979 switch (new_details.type()) { |
2984 case DATA: { | 2980 case DATA: { |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3606 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) | 3602 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) |
3607 ? to_kind | 3603 ? to_kind |
3608 : TERMINAL_FAST_ELEMENTS_KIND; | 3604 : TERMINAL_FAST_ELEMENTS_KIND; |
3609 | 3605 |
3610 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data | 3606 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data |
3611 // allows to change elements from arbitrary kind to any ExternalArray | 3607 // allows to change elements from arbitrary kind to any ExternalArray |
3612 // elements kind. Satisfy its requirements, checking whether we already | 3608 // elements kind. Satisfy its requirements, checking whether we already |
3613 // have the cached transition. | 3609 // have the cached transition. |
3614 if (IsExternalArrayElementsKind(to_kind) && | 3610 if (IsExternalArrayElementsKind(to_kind) && |
3615 !IsFixedTypedArrayElementsKind(map->elements_kind())) { | 3611 !IsFixedTypedArrayElementsKind(map->elements_kind())) { |
3616 if (map->HasElementsTransition()) { | 3612 Map* next_map = map->ElementsTransitionMap(); |
3617 Map* next_map = map->elements_transition_map(); | 3613 if (next_map != NULL && next_map->elements_kind() == to_kind) { |
3618 if (next_map->elements_kind() == to_kind) return next_map; | 3614 return next_map; |
3619 } | 3615 } |
3620 return map; | 3616 return map; |
3621 } | 3617 } |
3622 | 3618 |
3623 ElementsKind kind = map->elements_kind(); | 3619 ElementsKind kind = map->elements_kind(); |
3624 while (kind != target_kind) { | 3620 while (kind != target_kind) { |
3625 kind = GetNextTransitionElementsKind(kind); | 3621 kind = GetNextTransitionElementsKind(kind); |
3626 if (!current_map->HasElementsTransition()) return current_map; | 3622 Map* next_map = current_map->ElementsTransitionMap(); |
3627 current_map = current_map->elements_transition_map(); | 3623 if (next_map == NULL) return current_map; |
| 3624 current_map = next_map; |
3628 } | 3625 } |
3629 | 3626 |
3630 if (to_kind != kind && current_map->HasElementsTransition()) { | 3627 Map* next_map = current_map->ElementsTransitionMap(); |
| 3628 if (to_kind != kind && next_map != NULL) { |
3631 DCHECK(to_kind == DICTIONARY_ELEMENTS); | 3629 DCHECK(to_kind == DICTIONARY_ELEMENTS); |
3632 Map* next_map = current_map->elements_transition_map(); | |
3633 if (next_map->elements_kind() == to_kind) return next_map; | 3630 if (next_map->elements_kind() == to_kind) return next_map; |
3634 } | 3631 } |
3635 | 3632 |
3636 DCHECK(current_map->elements_kind() == target_kind); | 3633 DCHECK(current_map->elements_kind() == target_kind); |
3637 return current_map; | 3634 return current_map; |
3638 } | 3635 } |
3639 | 3636 |
3640 | 3637 |
3641 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { | 3638 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { |
3642 Map* to_map = FindClosestElementsTransition(this, to_kind); | 3639 Map* to_map = FindClosestElementsTransition(this, to_kind); |
(...skipping 2079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5722 if (attrs == NONE) { | 5719 if (attrs == NONE) { |
5723 transition_marker = isolate->factory()->nonextensible_symbol(); | 5720 transition_marker = isolate->factory()->nonextensible_symbol(); |
5724 } else if (attrs == SEALED) { | 5721 } else if (attrs == SEALED) { |
5725 transition_marker = isolate->factory()->sealed_symbol(); | 5722 transition_marker = isolate->factory()->sealed_symbol(); |
5726 } else { | 5723 } else { |
5727 DCHECK(attrs == FROZEN); | 5724 DCHECK(attrs == FROZEN); |
5728 transition_marker = isolate->factory()->frozen_symbol(); | 5725 transition_marker = isolate->factory()->frozen_symbol(); |
5729 } | 5726 } |
5730 | 5727 |
5731 Handle<Map> old_map(object->map(), isolate); | 5728 Handle<Map> old_map(object->map(), isolate); |
5732 int transition_index = old_map->SearchSpecialTransition(*transition_marker); | 5729 Map* transition = |
5733 if (transition_index != TransitionArray::kNotFound) { | 5730 TransitionArray::SearchSpecial(*old_map, *transition_marker); |
5734 Handle<Map> transition_map(old_map->GetTransition(transition_index)); | 5731 if (transition != NULL) { |
| 5732 Handle<Map> transition_map(transition, isolate); |
5735 DCHECK(transition_map->has_dictionary_elements()); | 5733 DCHECK(transition_map->has_dictionary_elements()); |
5736 DCHECK(!transition_map->is_extensible()); | 5734 DCHECK(!transition_map->is_extensible()); |
5737 JSObject::MigrateToMap(object, transition_map); | 5735 JSObject::MigrateToMap(object, transition_map); |
5738 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5736 } else if (object->HasFastProperties() && |
| 5737 TransitionArray::CanHaveMoreTransitions(old_map)) { |
5739 // Create a new descriptor array with the appropriate property attributes | 5738 // Create a new descriptor array with the appropriate property attributes |
5740 Handle<Map> new_map = Map::CopyForPreventExtensions( | 5739 Handle<Map> new_map = Map::CopyForPreventExtensions( |
5741 old_map, attrs, transition_marker, "CopyForPreventExtensions"); | 5740 old_map, attrs, transition_marker, "CopyForPreventExtensions"); |
5742 JSObject::MigrateToMap(object, new_map); | 5741 JSObject::MigrateToMap(object, new_map); |
5743 } else { | 5742 } else { |
5744 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); | 5743 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); |
5745 // Slow path: need to normalize properties for safety | 5744 // Slow path: need to normalize properties for safety |
5746 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, | 5745 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, |
5747 "SlowPreventExtensions"); | 5746 "SlowPreventExtensions"); |
5748 | 5747 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5787 } | 5786 } |
5788 | 5787 |
5789 | 5788 |
5790 void JSObject::SetObserved(Handle<JSObject> object) { | 5789 void JSObject::SetObserved(Handle<JSObject> object) { |
5791 DCHECK(!object->IsJSGlobalProxy()); | 5790 DCHECK(!object->IsJSGlobalProxy()); |
5792 DCHECK(!object->IsJSGlobalObject()); | 5791 DCHECK(!object->IsJSGlobalObject()); |
5793 Isolate* isolate = object->GetIsolate(); | 5792 Isolate* isolate = object->GetIsolate(); |
5794 Handle<Map> new_map; | 5793 Handle<Map> new_map; |
5795 Handle<Map> old_map(object->map(), isolate); | 5794 Handle<Map> old_map(object->map(), isolate); |
5796 DCHECK(!old_map->is_observed()); | 5795 DCHECK(!old_map->is_observed()); |
5797 int transition_index = | 5796 Map* transition = TransitionArray::SearchSpecial( |
5798 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); | 5797 *old_map, isolate->heap()->observed_symbol()); |
5799 if (transition_index != TransitionArray::kNotFound) { | 5798 if (transition != NULL) { |
5800 new_map = handle(old_map->GetTransition(transition_index), isolate); | 5799 new_map = handle(transition, isolate); |
5801 DCHECK(new_map->is_observed()); | 5800 DCHECK(new_map->is_observed()); |
5802 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5801 } else if (object->HasFastProperties() && |
| 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 if (!map->HasTransitionArray()) return; | 7021 Object* transitions = map->raw_transitions(); |
7022 TransitionArray* transitions = map->transitions(); | 7022 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
7023 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | 7023 for (int i = -0; i < num_transitions; ++i) { |
7024 Map* target = transitions->GetTarget(i); | 7024 Map* target = TransitionArray::GetTarget(transitions, i); |
7025 Map::TraceTransition("Transition", map, target, transitions->GetKey(i)); | 7025 Name* key = TransitionArray::GetKey(transitions, i); |
| 7026 Map::TraceTransition("Transition", map, target, key); |
7026 Map::TraceAllTransitions(target); | 7027 Map::TraceAllTransitions(target); |
7027 } | 7028 } |
7028 } | 7029 } |
7029 | 7030 |
7030 #endif // TRACE_MAPS | 7031 #endif // TRACE_MAPS |
7031 | 7032 |
7032 | 7033 |
7033 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 7034 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
7034 Handle<Name> name, SimpleTransitionFlag flag) { | 7035 Handle<Name> name, SimpleTransitionFlag flag) { |
7035 parent->set_owns_descriptors(false); | 7036 parent->set_owns_descriptors(false); |
7036 if (parent->is_prototype_map()) { | 7037 if (parent->is_prototype_map()) { |
7037 DCHECK(child->is_prototype_map()); | 7038 DCHECK(child->is_prototype_map()); |
7038 #if TRACE_MAPS | 7039 #if TRACE_MAPS |
7039 Map::TraceTransition("NoTransition", *parent, *child, *name); | 7040 Map::TraceTransition("NoTransition", *parent, *child, *name); |
7040 #endif | 7041 #endif |
7041 } else { | 7042 } else { |
7042 Handle<TransitionArray> transitions = | 7043 TransitionArray::Insert(parent, name, child, flag); |
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); | |
7049 if (child->prototype()->IsJSObject()) { | 7044 if (child->prototype()->IsJSObject()) { |
7050 Handle<JSObject> proto(JSObject::cast(child->prototype())); | 7045 Handle<JSObject> proto(JSObject::cast(child->prototype())); |
7051 if (!child->ShouldRegisterAsPrototypeUser(proto)) { | 7046 if (!child->ShouldRegisterAsPrototypeUser(proto)) { |
7052 JSObject::UnregisterPrototypeUser(proto, child); | 7047 JSObject::UnregisterPrototypeUser(proto, child); |
7053 } | 7048 } |
7054 } | 7049 } |
7055 #if TRACE_MAPS | 7050 #if TRACE_MAPS |
7056 Map::TraceTransition("Transition", *parent, *child, *name); | 7051 Map::TraceTransition("Transition", *parent, *child, *name); |
7057 #endif | 7052 #endif |
7058 } | 7053 } |
7059 } | 7054 } |
7060 | 7055 |
7061 | 7056 |
7062 Handle<Map> Map::CopyReplaceDescriptors( | 7057 Handle<Map> Map::CopyReplaceDescriptors( |
7063 Handle<Map> map, Handle<DescriptorArray> descriptors, | 7058 Handle<Map> map, Handle<DescriptorArray> descriptors, |
7064 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, | 7059 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, |
7065 MaybeHandle<Name> maybe_name, const char* reason, | 7060 MaybeHandle<Name> maybe_name, const char* reason, |
7066 SimpleTransitionFlag simple_flag) { | 7061 SimpleTransitionFlag simple_flag) { |
7067 DCHECK(descriptors->IsSortedNoDuplicates()); | 7062 DCHECK(descriptors->IsSortedNoDuplicates()); |
7068 | 7063 |
7069 Handle<Map> result = CopyDropDescriptors(map); | 7064 Handle<Map> result = CopyDropDescriptors(map); |
7070 | 7065 |
7071 if (!map->is_prototype_map()) { | 7066 if (!map->is_prototype_map()) { |
7072 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 7067 if (flag == INSERT_TRANSITION && |
| 7068 TransitionArray::CanHaveMoreTransitions(map)) { |
7073 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7069 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7074 | 7070 |
7075 Handle<Name> name; | 7071 Handle<Name> name; |
7076 CHECK(maybe_name.ToHandle(&name)); | 7072 CHECK(maybe_name.ToHandle(&name)); |
7077 ConnectTransition(map, result, name, simple_flag); | 7073 ConnectTransition(map, result, name, simple_flag); |
7078 } else { | 7074 } else { |
7079 int length = descriptors->number_of_descriptors(); | 7075 int length = descriptors->number_of_descriptors(); |
7080 for (int i = 0; i < length; i++) { | 7076 for (int i = 0; i < length; i++) { |
7081 descriptors->SetRepresentation(i, Representation::Tagged()); | 7077 descriptors->SetRepresentation(i, Representation::Tagged()); |
7082 if (descriptors->GetDetails(i).type() == DATA) { | 7078 if (descriptors->GetDetails(i).type() == DATA) { |
7083 descriptors->SetValue(i, HeapType::Any()); | 7079 descriptors->SetValue(i, HeapType::Any()); |
7084 } | 7080 } |
7085 } | 7081 } |
7086 result->InitializeDescriptors(*descriptors, | 7082 result->InitializeDescriptors(*descriptors, |
7087 LayoutDescriptor::FastPointerLayout()); | 7083 LayoutDescriptor::FastPointerLayout()); |
7088 } | 7084 } |
7089 } else { | 7085 } else { |
7090 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7086 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7091 } | 7087 } |
7092 #if TRACE_MAPS | 7088 #if TRACE_MAPS |
7093 if (FLAG_trace_maps && | 7089 if (FLAG_trace_maps && |
7094 // Mirror conditions above that did not call ConnectTransition(). | 7090 // Mirror conditions above that did not call ConnectTransition(). |
7095 (map->is_prototype_map() || | 7091 (map->is_prototype_map() || |
7096 !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) { | 7092 !(flag == INSERT_TRANSITION && |
| 7093 TransitionArray::CanHaveMoreTransitions(map)))) { |
7097 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", | 7094 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", |
7098 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), | 7095 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), |
7099 reason); | 7096 reason); |
7100 } | 7097 } |
7101 #endif | 7098 #endif |
7102 | 7099 |
7103 return result; | 7100 return result; |
7104 } | 7101 } |
7105 | 7102 |
7106 | 7103 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7144 | 7141 |
7145 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); | 7142 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
7146 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); | 7143 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
7147 | 7144 |
7148 return result; | 7145 return result; |
7149 } | 7146 } |
7150 | 7147 |
7151 | 7148 |
7152 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 7149 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
7153 TransitionFlag flag) { | 7150 TransitionFlag flag) { |
| 7151 Map* maybe_elements_transition_map = NULL; |
7154 if (flag == INSERT_TRANSITION) { | 7152 if (flag == INSERT_TRANSITION) { |
7155 DCHECK(!map->HasElementsTransition() || | 7153 maybe_elements_transition_map = map->ElementsTransitionMap(); |
7156 ((map->elements_transition_map()->elements_kind() == | 7154 DCHECK( |
7157 DICTIONARY_ELEMENTS || | 7155 maybe_elements_transition_map == NULL || |
| 7156 ((maybe_elements_transition_map->elements_kind() == |
| 7157 DICTIONARY_ELEMENTS || |
7158 IsExternalArrayElementsKind( | 7158 IsExternalArrayElementsKind( |
7159 map->elements_transition_map()->elements_kind())) && | 7159 maybe_elements_transition_map->elements_kind())) && |
7160 (kind == DICTIONARY_ELEMENTS || | 7160 (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind)))); |
7161 IsExternalArrayElementsKind(kind)))); | |
7162 DCHECK(!IsFastElementsKind(kind) || | 7161 DCHECK(!IsFastElementsKind(kind) || |
7163 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); | 7162 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
7164 DCHECK(kind != map->elements_kind()); | 7163 DCHECK(kind != map->elements_kind()); |
7165 } | 7164 } |
7166 | 7165 |
7167 bool insert_transition = flag == INSERT_TRANSITION && | 7166 bool insert_transition = flag == INSERT_TRANSITION && |
7168 map->CanHaveMoreTransitions() && | 7167 TransitionArray::CanHaveMoreTransitions(map) && |
7169 !map->HasElementsTransition(); | 7168 maybe_elements_transition_map == NULL; |
7170 | 7169 |
7171 if (insert_transition) { | 7170 if (insert_transition) { |
7172 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); | 7171 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); |
7173 new_map->set_elements_kind(kind); | 7172 new_map->set_elements_kind(kind); |
7174 | 7173 |
7175 ConnectElementsTransition(map, new_map); | 7174 ConnectElementsTransition(map, new_map); |
7176 | 7175 |
7177 return new_map; | 7176 return new_map; |
7178 } | 7177 } |
7179 | 7178 |
7180 // Create a new free-floating map only if we are not allowed to store it. | 7179 // Create a new free-floating map only if we are not allowed to store it. |
7181 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); | 7180 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); |
7182 new_map->set_elements_kind(kind); | 7181 new_map->set_elements_kind(kind); |
7183 return new_map; | 7182 return new_map; |
7184 } | 7183 } |
7185 | 7184 |
7186 | 7185 |
7187 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 7186 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
7188 DCHECK(!map->is_observed()); | 7187 DCHECK(!map->is_observed()); |
7189 | 7188 |
7190 Isolate* isolate = map->GetIsolate(); | 7189 Isolate* isolate = map->GetIsolate(); |
7191 | 7190 |
7192 bool insert_transition = | 7191 bool insert_transition = |
7193 map->CanHaveMoreTransitions() && !map->is_prototype_map(); | 7192 TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map(); |
7194 | 7193 |
7195 if (insert_transition) { | 7194 if (insert_transition) { |
7196 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); | 7195 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); |
7197 new_map->set_is_observed(); | 7196 new_map->set_is_observed(); |
7198 | 7197 |
7199 Handle<Name> name = isolate->factory()->observed_symbol(); | 7198 Handle<Name> name = isolate->factory()->observed_symbol(); |
7200 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); | 7199 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
7201 return new_map; | 7200 return new_map; |
7202 } | 7201 } |
7203 | 7202 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7349 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 7348 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
7350 Handle<Object> value, | 7349 Handle<Object> value, |
7351 PropertyAttributes attributes, | 7350 PropertyAttributes attributes, |
7352 StoreFromKeyed store_mode) { | 7351 StoreFromKeyed store_mode) { |
7353 // Dictionary maps can always have additional data properties. | 7352 // Dictionary maps can always have additional data properties. |
7354 if (map->is_dictionary_map()) return map; | 7353 if (map->is_dictionary_map()) return map; |
7355 | 7354 |
7356 // Migrate to the newest map before storing the property. | 7355 // Migrate to the newest map before storing the property. |
7357 map = Update(map); | 7356 map = Update(map); |
7358 | 7357 |
7359 int index = map->SearchTransition(kData, *name, attributes); | 7358 Map* maybe_transition = |
7360 if (index != TransitionArray::kNotFound) { | 7359 TransitionArray::SearchTransition(*map, kData, *name, attributes); |
7361 Handle<Map> transition(map->GetTransition(index)); | 7360 if (maybe_transition != NULL) { |
| 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 int index = map->SearchTransition(kAccessor, *name, attributes); | 7450 Map* maybe_transition = |
7451 if (index != TransitionArray::kNotFound) { | 7451 TransitionArray::SearchTransition(*map, kAccessor, *name, attributes); |
7452 Handle<Map> transition(map->GetTransition(index)); | 7452 if (maybe_transition != NULL) { |
| 7453 Handle<Map> transition(maybe_transition, isolate); |
7453 DescriptorArray* descriptors = transition->instance_descriptors(); | 7454 DescriptorArray* descriptors = transition->instance_descriptors(); |
7454 int descriptor = transition->LastAdded(); | 7455 int descriptor = transition->LastAdded(); |
7455 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); | 7456 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
7456 | 7457 |
7457 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); | 7458 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); |
7458 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); | 7459 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
7459 | 7460 |
7460 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); | 7461 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
7461 if (!maybe_pair->IsAccessorPair()) { | 7462 if (!maybe_pair->IsAccessorPair()) { |
7462 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); | 7463 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7514 | 7515 |
7515 | 7516 |
7516 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, | 7517 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
7517 Descriptor* descriptor, | 7518 Descriptor* descriptor, |
7518 TransitionFlag flag) { | 7519 TransitionFlag flag) { |
7519 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 7520 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
7520 | 7521 |
7521 // Ensure the key is unique. | 7522 // Ensure the key is unique. |
7522 descriptor->KeyToUniqueName(); | 7523 descriptor->KeyToUniqueName(); |
7523 | 7524 |
7524 if (flag == INSERT_TRANSITION && | 7525 if (flag == INSERT_TRANSITION && map->owns_descriptors() && |
7525 map->owns_descriptors() && | 7526 TransitionArray::CanHaveMoreTransitions(map)) { |
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 | |
7722 void CodeCache::Update( | 7690 void CodeCache::Update( |
7723 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | 7691 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { |
7724 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 7692 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
7725 // a large number and therefore they need to go into a hash table. They are | 7693 // a large number and therefore they need to go into a hash table. They are |
7726 // used to load global properties from cells. | 7694 // used to load global properties from cells. |
7727 if (code->type() == Code::NORMAL) { | 7695 if (code->type() == Code::NORMAL) { |
7728 // Make sure that a hash table is allocated for the normal load code cache. | 7696 // Make sure that a hash table is allocated for the normal load code cache. |
7729 if (code_cache->normal_type_cache()->IsUndefined()) { | 7697 if (code_cache->normal_type_cache()->IsUndefined()) { |
7730 Handle<Object> result = | 7698 Handle<Object> result = |
7731 CodeCacheHashTable::New(code_cache->GetIsolate(), | 7699 CodeCacheHashTable::New(code_cache->GetIsolate(), |
(...skipping 2153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9885 | 9853 |
9886 | 9854 |
9887 void JSFunction::CompleteInobjectSlackTracking() { | 9855 void JSFunction::CompleteInobjectSlackTracking() { |
9888 DCHECK(has_initial_map()); | 9856 DCHECK(has_initial_map()); |
9889 Map* map = initial_map(); | 9857 Map* map = initial_map(); |
9890 | 9858 |
9891 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); | 9859 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); |
9892 map->set_counter(Map::kRetainingCounterStart); | 9860 map->set_counter(Map::kRetainingCounterStart); |
9893 | 9861 |
9894 int slack = map->unused_property_fields(); | 9862 int slack = map->unused_property_fields(); |
9895 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 9863 TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack); |
9896 if (slack != 0) { | 9864 if (slack != 0) { |
9897 // Resize the initial map and all maps in its transition tree. | 9865 // Resize the initial map and all maps in its transition tree. |
9898 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 9866 TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack); |
9899 } | 9867 } |
9900 } | 9868 } |
9901 | 9869 |
9902 | 9870 |
9903 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { | 9871 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { |
9904 DisallowHeapAllocation no_gc; | 9872 DisallowHeapAllocation no_gc; |
9905 if (!object->HasFastProperties()) return false; | 9873 if (!object->HasFastProperties()) return false; |
9906 Map* map = object->map(); | 9874 Map* map = object->map(); |
9907 if (map->is_prototype_map()) return false; | 9875 if (map->is_prototype_map()) return false; |
9908 DescriptorArray* descriptors = map->instance_descriptors(); | 9876 DescriptorArray* descriptors = map->instance_descriptors(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10041 kElementsKindCount, TENURED); | 10009 kElementsKindCount, TENURED); |
10042 | 10010 |
10043 Handle<Map> current_map = initial_map; | 10011 Handle<Map> current_map = initial_map; |
10044 ElementsKind kind = current_map->elements_kind(); | 10012 ElementsKind kind = current_map->elements_kind(); |
10045 DCHECK(kind == GetInitialFastElementsKind()); | 10013 DCHECK(kind == GetInitialFastElementsKind()); |
10046 maps->set(kind, *current_map); | 10014 maps->set(kind, *current_map); |
10047 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 10015 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
10048 i < kFastElementsKindCount; ++i) { | 10016 i < kFastElementsKindCount; ++i) { |
10049 Handle<Map> new_map; | 10017 Handle<Map> new_map; |
10050 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); | 10018 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
10051 if (current_map->HasElementsTransition()) { | 10019 Map* maybe_elements_transition = current_map->ElementsTransitionMap(); |
10052 new_map = handle(current_map->elements_transition_map()); | 10020 if (maybe_elements_transition != NULL) { |
| 10021 new_map = handle(maybe_elements_transition); |
10053 DCHECK(new_map->elements_kind() == next_kind); | 10022 DCHECK(new_map->elements_kind() == next_kind); |
10054 } else { | 10023 } else { |
10055 new_map = Map::CopyAsElementsKind( | 10024 new_map = Map::CopyAsElementsKind( |
10056 current_map, next_kind, INSERT_TRANSITION); | 10025 current_map, next_kind, INSERT_TRANSITION); |
10057 } | 10026 } |
10058 maps->set(next_kind, *new_map); | 10027 maps->set(next_kind, *new_map); |
10059 current_map = new_map; | 10028 current_map = new_map; |
10060 } | 10029 } |
10061 native_context->set_js_array_maps(*maps); | 10030 native_context->set_js_array_maps(*maps); |
10062 return initial_map; | 10031 return initial_map; |
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11963 Object); | 11932 Object); |
11964 } | 11933 } |
11965 | 11934 |
11966 RETURN_ON_EXCEPTION( | 11935 RETURN_ON_EXCEPTION( |
11967 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); | 11936 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); |
11968 | 11937 |
11969 return hresult; | 11938 return hresult; |
11970 } | 11939 } |
11971 | 11940 |
11972 | 11941 |
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 | |
12044 // static | 11942 // static |
12045 void Map::AddDependentCompilationInfo(Handle<Map> map, | 11943 void Map::AddDependentCompilationInfo(Handle<Map> map, |
12046 DependentCode::DependencyGroup group, | 11944 DependentCode::DependencyGroup group, |
12047 CompilationInfo* info) { | 11945 CompilationInfo* info) { |
12048 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 11946 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
12049 handle(map->dependent_code(), info->isolate()), group, | 11947 handle(map->dependent_code(), info->isolate()), group, |
12050 info->object_wrapper()); | 11948 info->object_wrapper()); |
12051 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); | 11949 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); |
12052 info->dependencies(group)->Add(map, info->zone()); | 11950 info->dependencies(group)->Add(map, info->zone()); |
12053 } | 11951 } |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12339 return "allocation-site-transition-changed"; | 12237 return "allocation-site-transition-changed"; |
12340 } | 12238 } |
12341 UNREACHABLE(); | 12239 UNREACHABLE(); |
12342 return "?"; | 12240 return "?"; |
12343 } | 12241 } |
12344 | 12242 |
12345 | 12243 |
12346 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, | 12244 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, |
12347 Handle<Object> prototype, | 12245 Handle<Object> prototype, |
12348 PrototypeOptimizationMode mode) { | 12246 PrototypeOptimizationMode mode) { |
12349 Handle<Map> new_map = GetPrototypeTransition(map, prototype); | 12247 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype); |
12350 if (new_map.is_null()) { | 12248 if (new_map.is_null()) { |
12351 new_map = Copy(map, "TransitionToPrototype"); | 12249 new_map = Copy(map, "TransitionToPrototype"); |
12352 PutPrototypeTransition(map, prototype, new_map); | 12250 TransitionArray::PutPrototypeTransition(map, prototype, new_map); |
12353 new_map->SetPrototype(prototype, mode); | 12251 new_map->SetPrototype(prototype, mode); |
12354 } | 12252 } |
12355 return new_map; | 12253 return new_map; |
12356 } | 12254 } |
12357 | 12255 |
12358 | 12256 |
12359 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, | 12257 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
12360 Handle<Object> value, | 12258 Handle<Object> value, |
12361 bool from_javascript) { | 12259 bool from_javascript) { |
12362 #ifdef DEBUG | 12260 #ifdef DEBUG |
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17166 CompilationInfo* info) { | 17064 CompilationInfo* info) { |
17167 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17065 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17168 handle(cell->dependent_code(), info->isolate()), | 17066 handle(cell->dependent_code(), info->isolate()), |
17169 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17067 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17170 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17068 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17171 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17069 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17172 cell, info->zone()); | 17070 cell, info->zone()); |
17173 } | 17071 } |
17174 | 17072 |
17175 } } // namespace v8::internal | 17073 } } // namespace v8::internal |
OLD | NEW |