| 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 |