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