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 2054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5697 if (attrs == NONE) { | 5694 if (attrs == NONE) { |
5698 transition_marker = isolate->factory()->nonextensible_symbol(); | 5695 transition_marker = isolate->factory()->nonextensible_symbol(); |
5699 } else if (attrs == SEALED) { | 5696 } else if (attrs == SEALED) { |
5700 transition_marker = isolate->factory()->sealed_symbol(); | 5697 transition_marker = isolate->factory()->sealed_symbol(); |
5701 } else { | 5698 } else { |
5702 DCHECK(attrs == FROZEN); | 5699 DCHECK(attrs == FROZEN); |
5703 transition_marker = isolate->factory()->frozen_symbol(); | 5700 transition_marker = isolate->factory()->frozen_symbol(); |
5704 } | 5701 } |
5705 | 5702 |
5706 Handle<Map> old_map(object->map(), isolate); | 5703 Handle<Map> old_map(object->map(), isolate); |
5707 int transition_index = old_map->SearchSpecialTransition(*transition_marker); | 5704 Map* transition = |
5708 if (transition_index != TransitionArray::kNotFound) { | 5705 TransitionArray::SearchSpecial(*old_map, *transition_marker); |
5709 Handle<Map> transition_map(old_map->GetTransition(transition_index)); | 5706 if (transition != NULL) { |
| 5707 Handle<Map> transition_map(transition, isolate); |
5710 DCHECK(transition_map->has_dictionary_elements()); | 5708 DCHECK(transition_map->has_dictionary_elements()); |
5711 DCHECK(!transition_map->is_extensible()); | 5709 DCHECK(!transition_map->is_extensible()); |
5712 JSObject::MigrateToMap(object, transition_map); | 5710 JSObject::MigrateToMap(object, transition_map); |
5713 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5711 } else if (object->HasFastProperties() && |
| 5712 TransitionArray::CanHaveMoreTransitions(old_map)) { |
5714 // Create a new descriptor array with the appropriate property attributes | 5713 // Create a new descriptor array with the appropriate property attributes |
5715 Handle<Map> new_map = Map::CopyForPreventExtensions( | 5714 Handle<Map> new_map = Map::CopyForPreventExtensions( |
5716 old_map, attrs, transition_marker, "CopyForPreventExtensions"); | 5715 old_map, attrs, transition_marker, "CopyForPreventExtensions"); |
5717 JSObject::MigrateToMap(object, new_map); | 5716 JSObject::MigrateToMap(object, new_map); |
5718 } else { | 5717 } else { |
5719 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); | 5718 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); |
5720 // Slow path: need to normalize properties for safety | 5719 // Slow path: need to normalize properties for safety |
5721 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, | 5720 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, |
5722 "SlowPreventExtensions"); | 5721 "SlowPreventExtensions"); |
5723 | 5722 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5762 } | 5761 } |
5763 | 5762 |
5764 | 5763 |
5765 void JSObject::SetObserved(Handle<JSObject> object) { | 5764 void JSObject::SetObserved(Handle<JSObject> object) { |
5766 DCHECK(!object->IsJSGlobalProxy()); | 5765 DCHECK(!object->IsJSGlobalProxy()); |
5767 DCHECK(!object->IsJSGlobalObject()); | 5766 DCHECK(!object->IsJSGlobalObject()); |
5768 Isolate* isolate = object->GetIsolate(); | 5767 Isolate* isolate = object->GetIsolate(); |
5769 Handle<Map> new_map; | 5768 Handle<Map> new_map; |
5770 Handle<Map> old_map(object->map(), isolate); | 5769 Handle<Map> old_map(object->map(), isolate); |
5771 DCHECK(!old_map->is_observed()); | 5770 DCHECK(!old_map->is_observed()); |
5772 int transition_index = | 5771 Map* transition = TransitionArray::SearchSpecial( |
5773 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); | 5772 *old_map, isolate->heap()->observed_symbol()); |
5774 if (transition_index != TransitionArray::kNotFound) { | 5773 if (transition != NULL) { |
5775 new_map = handle(old_map->GetTransition(transition_index), isolate); | 5774 new_map = handle(transition, isolate); |
5776 DCHECK(new_map->is_observed()); | 5775 DCHECK(new_map->is_observed()); |
5777 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5776 } else if (object->HasFastProperties() && |
| 5777 TransitionArray::CanHaveMoreTransitions(old_map)) { |
5778 new_map = Map::CopyForObserved(old_map); | 5778 new_map = Map::CopyForObserved(old_map); |
5779 } else { | 5779 } else { |
5780 new_map = Map::Copy(old_map, "SlowObserved"); | 5780 new_map = Map::Copy(old_map, "SlowObserved"); |
5781 new_map->set_is_observed(); | 5781 new_map->set_is_observed(); |
5782 } | 5782 } |
5783 JSObject::MigrateToMap(object, new_map); | 5783 JSObject::MigrateToMap(object, new_map); |
5784 } | 5784 } |
5785 | 5785 |
5786 | 5786 |
5787 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, | 5787 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, |
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6986 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, | 6986 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, |
6987 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); | 6987 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); |
6988 name->NameShortPrint(); | 6988 name->NameShortPrint(); |
6989 PrintF(" ]\n"); | 6989 PrintF(" ]\n"); |
6990 } | 6990 } |
6991 } | 6991 } |
6992 | 6992 |
6993 | 6993 |
6994 // static | 6994 // static |
6995 void Map::TraceAllTransitions(Map* map) { | 6995 void Map::TraceAllTransitions(Map* map) { |
6996 if (!map->HasTransitionArray()) return; | 6996 Object* transitions = map->raw_transitions(); |
6997 TransitionArray* transitions = map->transitions(); | 6997 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
6998 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | 6998 for (int i = -0; i < num_transitions; ++i) { |
6999 Map* target = transitions->GetTarget(i); | 6999 Map* target = TransitionArray::GetTarget(transitions, i); |
7000 Map::TraceTransition("Transition", map, target, transitions->GetKey(i)); | 7000 Name* key = TransitionArray::GetKey(transitions, i); |
| 7001 Map::TraceTransition("Transition", map, target, key); |
7001 Map::TraceAllTransitions(target); | 7002 Map::TraceAllTransitions(target); |
7002 } | 7003 } |
7003 } | 7004 } |
7004 | 7005 |
7005 #endif // TRACE_MAPS | 7006 #endif // TRACE_MAPS |
7006 | 7007 |
7007 | 7008 |
7008 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 7009 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
7009 Handle<Name> name, SimpleTransitionFlag flag) { | 7010 Handle<Name> name, SimpleTransitionFlag flag) { |
7010 parent->set_owns_descriptors(false); | 7011 parent->set_owns_descriptors(false); |
7011 if (parent->is_prototype_map()) { | 7012 if (parent->is_prototype_map()) { |
7012 DCHECK(child->is_prototype_map()); | 7013 DCHECK(child->is_prototype_map()); |
7013 #if TRACE_MAPS | 7014 #if TRACE_MAPS |
7014 Map::TraceTransition("NoTransition", *parent, *child, *name); | 7015 Map::TraceTransition("NoTransition", *parent, *child, *name); |
7015 #endif | 7016 #endif |
7016 } else { | 7017 } else { |
7017 Handle<TransitionArray> transitions = | 7018 TransitionArray::Insert(parent, name, child, flag); |
7018 TransitionArray::Insert(parent, name, child, flag); | |
7019 if (!parent->HasTransitionArray() || | |
7020 *transitions != parent->transitions()) { | |
7021 parent->set_transitions(*transitions); | |
7022 } | |
7023 child->SetBackPointer(*parent); | |
7024 if (child->prototype()->IsJSObject()) { | 7019 if (child->prototype()->IsJSObject()) { |
7025 Handle<JSObject> proto(JSObject::cast(child->prototype())); | 7020 Handle<JSObject> proto(JSObject::cast(child->prototype())); |
7026 if (!child->ShouldRegisterAsPrototypeUser(proto)) { | 7021 if (!child->ShouldRegisterAsPrototypeUser(proto)) { |
7027 JSObject::UnregisterPrototypeUser(proto, child); | 7022 JSObject::UnregisterPrototypeUser(proto, child); |
7028 } | 7023 } |
7029 } | 7024 } |
7030 #if TRACE_MAPS | 7025 #if TRACE_MAPS |
7031 Map::TraceTransition("Transition", *parent, *child, *name); | 7026 Map::TraceTransition("Transition", *parent, *child, *name); |
7032 #endif | 7027 #endif |
7033 } | 7028 } |
7034 } | 7029 } |
7035 | 7030 |
7036 | 7031 |
7037 Handle<Map> Map::CopyReplaceDescriptors( | 7032 Handle<Map> Map::CopyReplaceDescriptors( |
7038 Handle<Map> map, Handle<DescriptorArray> descriptors, | 7033 Handle<Map> map, Handle<DescriptorArray> descriptors, |
7039 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, | 7034 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, |
7040 MaybeHandle<Name> maybe_name, const char* reason, | 7035 MaybeHandle<Name> maybe_name, const char* reason, |
7041 SimpleTransitionFlag simple_flag) { | 7036 SimpleTransitionFlag simple_flag) { |
7042 DCHECK(descriptors->IsSortedNoDuplicates()); | 7037 DCHECK(descriptors->IsSortedNoDuplicates()); |
7043 | 7038 |
7044 Handle<Map> result = CopyDropDescriptors(map); | 7039 Handle<Map> result = CopyDropDescriptors(map); |
7045 | 7040 |
7046 if (!map->is_prototype_map()) { | 7041 if (!map->is_prototype_map()) { |
7047 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 7042 if (flag == INSERT_TRANSITION && |
| 7043 TransitionArray::CanHaveMoreTransitions(map)) { |
7048 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7044 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7049 | 7045 |
7050 Handle<Name> name; | 7046 Handle<Name> name; |
7051 CHECK(maybe_name.ToHandle(&name)); | 7047 CHECK(maybe_name.ToHandle(&name)); |
7052 ConnectTransition(map, result, name, simple_flag); | 7048 ConnectTransition(map, result, name, simple_flag); |
7053 } else { | 7049 } else { |
7054 int length = descriptors->number_of_descriptors(); | 7050 int length = descriptors->number_of_descriptors(); |
7055 for (int i = 0; i < length; i++) { | 7051 for (int i = 0; i < length; i++) { |
7056 descriptors->SetRepresentation(i, Representation::Tagged()); | 7052 descriptors->SetRepresentation(i, Representation::Tagged()); |
7057 if (descriptors->GetDetails(i).type() == DATA) { | 7053 if (descriptors->GetDetails(i).type() == DATA) { |
7058 descriptors->SetValue(i, HeapType::Any()); | 7054 descriptors->SetValue(i, HeapType::Any()); |
7059 } | 7055 } |
7060 } | 7056 } |
7061 result->InitializeDescriptors(*descriptors, | 7057 result->InitializeDescriptors(*descriptors, |
7062 LayoutDescriptor::FastPointerLayout()); | 7058 LayoutDescriptor::FastPointerLayout()); |
7063 } | 7059 } |
7064 } else { | 7060 } else { |
7065 result->InitializeDescriptors(*descriptors, *layout_descriptor); | 7061 result->InitializeDescriptors(*descriptors, *layout_descriptor); |
7066 } | 7062 } |
7067 #if TRACE_MAPS | 7063 #if TRACE_MAPS |
7068 if (FLAG_trace_maps && | 7064 if (FLAG_trace_maps && |
7069 // Mirror conditions above that did not call ConnectTransition(). | 7065 // Mirror conditions above that did not call ConnectTransition(). |
7070 (map->is_prototype_map() || | 7066 (map->is_prototype_map() || |
7071 !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) { | 7067 !(flag == INSERT_TRANSITION && |
| 7068 TransitionArray::CanHaveMoreTransitions(map)))) { |
7072 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", | 7069 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", |
7073 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), | 7070 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), |
7074 reason); | 7071 reason); |
7075 } | 7072 } |
7076 #endif | 7073 #endif |
7077 | 7074 |
7078 return result; | 7075 return result; |
7079 } | 7076 } |
7080 | 7077 |
7081 | 7078 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7119 | 7116 |
7120 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); | 7117 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
7121 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); | 7118 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
7122 | 7119 |
7123 return result; | 7120 return result; |
7124 } | 7121 } |
7125 | 7122 |
7126 | 7123 |
7127 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 7124 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
7128 TransitionFlag flag) { | 7125 TransitionFlag flag) { |
| 7126 Map* maybe_elements_transition_map = NULL; |
7129 if (flag == INSERT_TRANSITION) { | 7127 if (flag == INSERT_TRANSITION) { |
7130 DCHECK(!map->HasElementsTransition() || | 7128 maybe_elements_transition_map = map->ElementsTransitionMap(); |
7131 ((map->elements_transition_map()->elements_kind() == | 7129 DCHECK( |
7132 DICTIONARY_ELEMENTS || | 7130 maybe_elements_transition_map == NULL || |
| 7131 ((maybe_elements_transition_map->elements_kind() == |
| 7132 DICTIONARY_ELEMENTS || |
7133 IsExternalArrayElementsKind( | 7133 IsExternalArrayElementsKind( |
7134 map->elements_transition_map()->elements_kind())) && | 7134 maybe_elements_transition_map->elements_kind())) && |
7135 (kind == DICTIONARY_ELEMENTS || | 7135 (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind)))); |
7136 IsExternalArrayElementsKind(kind)))); | |
7137 DCHECK(!IsFastElementsKind(kind) || | 7136 DCHECK(!IsFastElementsKind(kind) || |
7138 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); | 7137 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); |
7139 DCHECK(kind != map->elements_kind()); | 7138 DCHECK(kind != map->elements_kind()); |
7140 } | 7139 } |
7141 | 7140 |
7142 bool insert_transition = flag == INSERT_TRANSITION && | 7141 bool insert_transition = flag == INSERT_TRANSITION && |
7143 map->CanHaveMoreTransitions() && | 7142 TransitionArray::CanHaveMoreTransitions(map) && |
7144 !map->HasElementsTransition(); | 7143 maybe_elements_transition_map == NULL; |
7145 | 7144 |
7146 if (insert_transition) { | 7145 if (insert_transition) { |
7147 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); | 7146 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); |
7148 new_map->set_elements_kind(kind); | 7147 new_map->set_elements_kind(kind); |
7149 | 7148 |
7150 ConnectElementsTransition(map, new_map); | 7149 ConnectElementsTransition(map, new_map); |
7151 | 7150 |
7152 return new_map; | 7151 return new_map; |
7153 } | 7152 } |
7154 | 7153 |
7155 // Create a new free-floating map only if we are not allowed to store it. | 7154 // Create a new free-floating map only if we are not allowed to store it. |
7156 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); | 7155 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); |
7157 new_map->set_elements_kind(kind); | 7156 new_map->set_elements_kind(kind); |
7158 return new_map; | 7157 return new_map; |
7159 } | 7158 } |
7160 | 7159 |
7161 | 7160 |
7162 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 7161 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
7163 DCHECK(!map->is_observed()); | 7162 DCHECK(!map->is_observed()); |
7164 | 7163 |
7165 Isolate* isolate = map->GetIsolate(); | 7164 Isolate* isolate = map->GetIsolate(); |
7166 | 7165 |
7167 bool insert_transition = | 7166 bool insert_transition = |
7168 map->CanHaveMoreTransitions() && !map->is_prototype_map(); | 7167 TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map(); |
7169 | 7168 |
7170 if (insert_transition) { | 7169 if (insert_transition) { |
7171 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); | 7170 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); |
7172 new_map->set_is_observed(); | 7171 new_map->set_is_observed(); |
7173 | 7172 |
7174 Handle<Name> name = isolate->factory()->observed_symbol(); | 7173 Handle<Name> name = isolate->factory()->observed_symbol(); |
7175 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); | 7174 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
7176 return new_map; | 7175 return new_map; |
7177 } | 7176 } |
7178 | 7177 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7324 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 7323 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
7325 Handle<Object> value, | 7324 Handle<Object> value, |
7326 PropertyAttributes attributes, | 7325 PropertyAttributes attributes, |
7327 StoreFromKeyed store_mode) { | 7326 StoreFromKeyed store_mode) { |
7328 // Dictionary maps can always have additional data properties. | 7327 // Dictionary maps can always have additional data properties. |
7329 if (map->is_dictionary_map()) return map; | 7328 if (map->is_dictionary_map()) return map; |
7330 | 7329 |
7331 // Migrate to the newest map before storing the property. | 7330 // Migrate to the newest map before storing the property. |
7332 map = Update(map); | 7331 map = Update(map); |
7333 | 7332 |
7334 int index = map->SearchTransition(kData, *name, attributes); | 7333 Map* maybe_transition = |
7335 if (index != TransitionArray::kNotFound) { | 7334 TransitionArray::SearchTransition(*map, kData, *name, attributes); |
7336 Handle<Map> transition(map->GetTransition(index)); | 7335 if (maybe_transition != NULL) { |
| 7336 Handle<Map> transition(maybe_transition); |
7337 int descriptor = transition->LastAdded(); | 7337 int descriptor = transition->LastAdded(); |
7338 | 7338 |
7339 DCHECK_EQ(attributes, transition->instance_descriptors() | 7339 DCHECK_EQ(attributes, transition->instance_descriptors() |
7340 ->GetDetails(descriptor) | 7340 ->GetDetails(descriptor) |
7341 .attributes()); | 7341 .attributes()); |
7342 | 7342 |
7343 return Map::PrepareForDataProperty(transition, descriptor, value); | 7343 return Map::PrepareForDataProperty(transition, descriptor, value); |
7344 } | 7344 } |
7345 | 7345 |
7346 TransitionFlag flag = INSERT_TRANSITION; | 7346 TransitionFlag flag = INSERT_TRANSITION; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7415 return map; | 7415 return map; |
7416 } | 7416 } |
7417 | 7417 |
7418 // Migrate to the newest map before transitioning to the new property. | 7418 // Migrate to the newest map before transitioning to the new property. |
7419 map = Update(map); | 7419 map = Update(map); |
7420 | 7420 |
7421 PropertyNormalizationMode mode = map->is_prototype_map() | 7421 PropertyNormalizationMode mode = map->is_prototype_map() |
7422 ? KEEP_INOBJECT_PROPERTIES | 7422 ? KEEP_INOBJECT_PROPERTIES |
7423 : CLEAR_INOBJECT_PROPERTIES; | 7423 : CLEAR_INOBJECT_PROPERTIES; |
7424 | 7424 |
7425 int index = map->SearchTransition(kAccessor, *name, attributes); | 7425 Map* maybe_transition = |
7426 if (index != TransitionArray::kNotFound) { | 7426 TransitionArray::SearchTransition(*map, kAccessor, *name, attributes); |
7427 Handle<Map> transition(map->GetTransition(index)); | 7427 if (maybe_transition != NULL) { |
| 7428 Handle<Map> transition(maybe_transition, isolate); |
7428 DescriptorArray* descriptors = transition->instance_descriptors(); | 7429 DescriptorArray* descriptors = transition->instance_descriptors(); |
7429 int descriptor = transition->LastAdded(); | 7430 int descriptor = transition->LastAdded(); |
7430 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); | 7431 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
7431 | 7432 |
7432 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); | 7433 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); |
7433 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); | 7434 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
7434 | 7435 |
7435 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); | 7436 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
7436 if (!maybe_pair->IsAccessorPair()) { | 7437 if (!maybe_pair->IsAccessorPair()) { |
7437 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); | 7438 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7489 | 7490 |
7490 | 7491 |
7491 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, | 7492 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
7492 Descriptor* descriptor, | 7493 Descriptor* descriptor, |
7493 TransitionFlag flag) { | 7494 TransitionFlag flag) { |
7494 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 7495 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
7495 | 7496 |
7496 // Ensure the key is unique. | 7497 // Ensure the key is unique. |
7497 descriptor->KeyToUniqueName(); | 7498 descriptor->KeyToUniqueName(); |
7498 | 7499 |
7499 if (flag == INSERT_TRANSITION && | 7500 if (flag == INSERT_TRANSITION && map->owns_descriptors() && |
7500 map->owns_descriptors() && | 7501 TransitionArray::CanHaveMoreTransitions(map)) { |
7501 map->CanHaveMoreTransitions()) { | |
7502 return ShareDescriptor(map, descriptors, descriptor); | 7502 return ShareDescriptor(map, descriptors, descriptor); |
7503 } | 7503 } |
7504 | 7504 |
7505 int nof = map->NumberOfOwnDescriptors(); | 7505 int nof = map->NumberOfOwnDescriptors(); |
7506 Handle<DescriptorArray> new_descriptors = | 7506 Handle<DescriptorArray> new_descriptors = |
7507 DescriptorArray::CopyUpTo(descriptors, nof, 1); | 7507 DescriptorArray::CopyUpTo(descriptors, nof, 1); |
7508 new_descriptors->Append(descriptor); | 7508 new_descriptors->Append(descriptor); |
7509 | 7509 |
7510 Handle<LayoutDescriptor> new_layout_descriptor = | 7510 Handle<LayoutDescriptor> new_layout_descriptor = |
7511 FLAG_unbox_double_fields | 7511 FLAG_unbox_double_fields |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7655 | 7655 |
7656 | 7656 |
7657 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { | 7657 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { |
7658 // No GC is supposed to happen between a call to IndexInCodeCache and | 7658 // No GC is supposed to happen between a call to IndexInCodeCache and |
7659 // RemoveFromCodeCache so the code cache must be there. | 7659 // RemoveFromCodeCache so the code cache must be there. |
7660 DCHECK(!code_cache()->IsFixedArray()); | 7660 DCHECK(!code_cache()->IsFixedArray()); |
7661 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); | 7661 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
7662 } | 7662 } |
7663 | 7663 |
7664 | 7664 |
7665 static void TraverseTransitionTreeInternal(Map* map, | |
7666 Map::TraverseCallback callback, | |
7667 void* data) { | |
7668 if (map->HasTransitionArray()) { | |
7669 TransitionArray* transitions = map->transitions(); | |
7670 if (transitions->HasPrototypeTransitions()) { | |
7671 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); | |
7672 Object* num_obj = | |
7673 proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset); | |
7674 int num = Smi::cast(num_obj)->value(); | |
7675 for (int i = 0; i < num; ++i) { | |
7676 int index = Map::kProtoTransitionHeaderSize + i; | |
7677 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), | |
7678 callback, data); | |
7679 } | |
7680 } | |
7681 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | |
7682 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); | |
7683 } | |
7684 } | |
7685 callback(map, data); | |
7686 } | |
7687 | |
7688 | |
7689 // Traverse the transition tree in postorder. | |
7690 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | |
7691 // Make sure that we do not allocate in the callback. | |
7692 DisallowHeapAllocation no_allocation; | |
7693 TraverseTransitionTreeInternal(this, callback, data); | |
7694 } | |
7695 | |
7696 | |
7697 void CodeCache::Update( | 7665 void CodeCache::Update( |
7698 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | 7666 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { |
7699 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 7667 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
7700 // a large number and therefore they need to go into a hash table. They are | 7668 // a large number and therefore they need to go into a hash table. They are |
7701 // used to load global properties from cells. | 7669 // used to load global properties from cells. |
7702 if (code->type() == Code::NORMAL) { | 7670 if (code->type() == Code::NORMAL) { |
7703 // Make sure that a hash table is allocated for the normal load code cache. | 7671 // Make sure that a hash table is allocated for the normal load code cache. |
7704 if (code_cache->normal_type_cache()->IsUndefined()) { | 7672 if (code_cache->normal_type_cache()->IsUndefined()) { |
7705 Handle<Object> result = | 7673 Handle<Object> result = |
7706 CodeCacheHashTable::New(code_cache->GetIsolate(), | 7674 CodeCacheHashTable::New(code_cache->GetIsolate(), |
(...skipping 2184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9891 | 9859 |
9892 | 9860 |
9893 void JSFunction::CompleteInobjectSlackTracking() { | 9861 void JSFunction::CompleteInobjectSlackTracking() { |
9894 DCHECK(has_initial_map()); | 9862 DCHECK(has_initial_map()); |
9895 Map* map = initial_map(); | 9863 Map* map = initial_map(); |
9896 | 9864 |
9897 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); | 9865 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); |
9898 map->set_counter(Map::kRetainingCounterStart); | 9866 map->set_counter(Map::kRetainingCounterStart); |
9899 | 9867 |
9900 int slack = map->unused_property_fields(); | 9868 int slack = map->unused_property_fields(); |
9901 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 9869 TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack); |
9902 if (slack != 0) { | 9870 if (slack != 0) { |
9903 // Resize the initial map and all maps in its transition tree. | 9871 // Resize the initial map and all maps in its transition tree. |
9904 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 9872 TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack); |
9905 } | 9873 } |
9906 } | 9874 } |
9907 | 9875 |
9908 | 9876 |
9909 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { | 9877 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { |
9910 DisallowHeapAllocation no_gc; | 9878 DisallowHeapAllocation no_gc; |
9911 if (!object->HasFastProperties()) return false; | 9879 if (!object->HasFastProperties()) return false; |
9912 Map* map = object->map(); | 9880 Map* map = object->map(); |
9913 if (map->is_prototype_map()) return false; | 9881 if (map->is_prototype_map()) return false; |
9914 DescriptorArray* descriptors = map->instance_descriptors(); | 9882 DescriptorArray* descriptors = map->instance_descriptors(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10047 kElementsKindCount, TENURED); | 10015 kElementsKindCount, TENURED); |
10048 | 10016 |
10049 Handle<Map> current_map = initial_map; | 10017 Handle<Map> current_map = initial_map; |
10050 ElementsKind kind = current_map->elements_kind(); | 10018 ElementsKind kind = current_map->elements_kind(); |
10051 DCHECK(kind == GetInitialFastElementsKind()); | 10019 DCHECK(kind == GetInitialFastElementsKind()); |
10052 maps->set(kind, *current_map); | 10020 maps->set(kind, *current_map); |
10053 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 10021 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
10054 i < kFastElementsKindCount; ++i) { | 10022 i < kFastElementsKindCount; ++i) { |
10055 Handle<Map> new_map; | 10023 Handle<Map> new_map; |
10056 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); | 10024 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
10057 if (current_map->HasElementsTransition()) { | 10025 Map* maybe_elements_transition = current_map->ElementsTransitionMap(); |
10058 new_map = handle(current_map->elements_transition_map()); | 10026 if (maybe_elements_transition != NULL) { |
| 10027 new_map = handle(maybe_elements_transition); |
10059 DCHECK(new_map->elements_kind() == next_kind); | 10028 DCHECK(new_map->elements_kind() == next_kind); |
10060 } else { | 10029 } else { |
10061 new_map = Map::CopyAsElementsKind( | 10030 new_map = Map::CopyAsElementsKind( |
10062 current_map, next_kind, INSERT_TRANSITION); | 10031 current_map, next_kind, INSERT_TRANSITION); |
10063 } | 10032 } |
10064 maps->set(next_kind, *new_map); | 10033 maps->set(next_kind, *new_map); |
10065 current_map = new_map; | 10034 current_map = new_map; |
10066 } | 10035 } |
10067 native_context->set_js_array_maps(*maps); | 10036 native_context->set_js_array_maps(*maps); |
10068 return initial_map; | 10037 return initial_map; |
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11969 Object); | 11938 Object); |
11970 } | 11939 } |
11971 | 11940 |
11972 RETURN_ON_EXCEPTION( | 11941 RETURN_ON_EXCEPTION( |
11973 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); | 11942 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); |
11974 | 11943 |
11975 return hresult; | 11944 return hresult; |
11976 } | 11945 } |
11977 | 11946 |
11978 | 11947 |
11979 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, | |
11980 Handle<Object> prototype) { | |
11981 DisallowHeapAllocation no_gc; | |
11982 FixedArray* cache = map->GetPrototypeTransitions(); | |
11983 int number_of_transitions = map->NumberOfProtoTransitions(); | |
11984 for (int i = 0; i < number_of_transitions; i++) { | |
11985 Map* map = Map::cast(cache->get(kProtoTransitionHeaderSize + i)); | |
11986 if (map->prototype() == *prototype) return handle(map); | |
11987 } | |
11988 return Handle<Map>(); | |
11989 } | |
11990 | |
11991 | |
11992 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, | |
11993 Handle<Object> prototype, | |
11994 Handle<Map> target_map) { | |
11995 DCHECK(target_map->IsMap()); | |
11996 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); | |
11997 // Don't cache prototype transition if this map is either shared, or a map of | |
11998 // a prototype. | |
11999 if (map->is_prototype_map()) return map; | |
12000 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map; | |
12001 | |
12002 const int header = kProtoTransitionHeaderSize; | |
12003 | |
12004 Handle<FixedArray> cache(map->GetPrototypeTransitions()); | |
12005 int capacity = cache->length() - header; | |
12006 int transitions = map->NumberOfProtoTransitions() + 1; | |
12007 | |
12008 if (transitions > capacity) { | |
12009 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. | |
12010 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); | |
12011 if (new_capacity == capacity) return map; | |
12012 | |
12013 cache = FixedArray::CopySize(cache, header + new_capacity); | |
12014 | |
12015 SetPrototypeTransitions(map, cache); | |
12016 } | |
12017 | |
12018 // Reload number of transitions as GC might shrink them. | |
12019 int last = map->NumberOfProtoTransitions(); | |
12020 int entry = header + last; | |
12021 | |
12022 cache->set(entry, *target_map); | |
12023 map->SetNumberOfProtoTransitions(last + 1); | |
12024 | |
12025 return map; | |
12026 } | |
12027 | |
12028 | |
12029 void Map::ZapTransitions() { | |
12030 TransitionArray* transition_array = transitions(); | |
12031 // TODO(mstarzinger): Temporarily use a slower version instead of the faster | |
12032 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. | |
12033 Object** data = transition_array->data_start(); | |
12034 Object* the_hole = GetHeap()->the_hole_value(); | |
12035 int length = transition_array->length(); | |
12036 for (int i = 0; i < length; i++) { | |
12037 data[i] = the_hole; | |
12038 } | |
12039 } | |
12040 | |
12041 | |
12042 void Map::ZapPrototypeTransitions() { | |
12043 FixedArray* proto_transitions = GetPrototypeTransitions(); | |
12044 MemsetPointer(proto_transitions->data_start(), | |
12045 GetHeap()->the_hole_value(), | |
12046 proto_transitions->length()); | |
12047 } | |
12048 | |
12049 | |
12050 // static | 11948 // static |
12051 void Map::AddDependentCompilationInfo(Handle<Map> map, | 11949 void Map::AddDependentCompilationInfo(Handle<Map> map, |
12052 DependentCode::DependencyGroup group, | 11950 DependentCode::DependencyGroup group, |
12053 CompilationInfo* info) { | 11951 CompilationInfo* info) { |
12054 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 11952 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
12055 handle(map->dependent_code(), info->isolate()), group, | 11953 handle(map->dependent_code(), info->isolate()), group, |
12056 info->object_wrapper()); | 11954 info->object_wrapper()); |
12057 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); | 11955 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); |
12058 info->dependencies(group)->Add(map, info->zone()); | 11956 info->dependencies(group)->Add(map, info->zone()); |
12059 } | 11957 } |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12345 return "allocation-site-transition-changed"; | 12243 return "allocation-site-transition-changed"; |
12346 } | 12244 } |
12347 UNREACHABLE(); | 12245 UNREACHABLE(); |
12348 return "?"; | 12246 return "?"; |
12349 } | 12247 } |
12350 | 12248 |
12351 | 12249 |
12352 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, | 12250 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, |
12353 Handle<Object> prototype, | 12251 Handle<Object> prototype, |
12354 PrototypeOptimizationMode mode) { | 12252 PrototypeOptimizationMode mode) { |
12355 Handle<Map> new_map = GetPrototypeTransition(map, prototype); | 12253 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype); |
12356 if (new_map.is_null()) { | 12254 if (new_map.is_null()) { |
12357 new_map = Copy(map, "TransitionToPrototype"); | 12255 new_map = Copy(map, "TransitionToPrototype"); |
12358 PutPrototypeTransition(map, prototype, new_map); | 12256 TransitionArray::PutPrototypeTransition(map, prototype, new_map); |
12359 new_map->SetPrototype(prototype, mode); | 12257 new_map->SetPrototype(prototype, mode); |
12360 } | 12258 } |
12361 return new_map; | 12259 return new_map; |
12362 } | 12260 } |
12363 | 12261 |
12364 | 12262 |
12365 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, | 12263 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
12366 Handle<Object> value, | 12264 Handle<Object> value, |
12367 bool from_javascript) { | 12265 bool from_javascript) { |
12368 #ifdef DEBUG | 12266 #ifdef DEBUG |
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17172 CompilationInfo* info) { | 17070 CompilationInfo* info) { |
17173 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17071 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17174 handle(cell->dependent_code(), info->isolate()), | 17072 handle(cell->dependent_code(), info->isolate()), |
17175 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17073 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17176 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17074 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17177 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17075 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17178 cell, info->zone()); | 17076 cell, info->zone()); |
17179 } | 17077 } |
17180 | 17078 |
17181 } } // namespace v8::internal | 17079 } } // namespace v8::internal |
OLD | NEW |