Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: src/objects.cc

Issue 980573002: Simplify and compact transitions storage (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix -Werror=pedantic ( rebase Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
3606 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind) 3602 IsFastElementsKind(to_kind) || IsExternalArrayElementsKind(to_kind)
3607 ? to_kind 3603 ? to_kind
3608 : TERMINAL_FAST_ELEMENTS_KIND; 3604 : TERMINAL_FAST_ELEMENTS_KIND;
3609 3605
3610 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data 3606 // Support for legacy API: SetIndexedPropertiesTo{External,Pixel}Data
3611 // allows to change elements from arbitrary kind to any ExternalArray 3607 // allows to change elements from arbitrary kind to any ExternalArray
3612 // elements kind. Satisfy its requirements, checking whether we already 3608 // elements kind. Satisfy its requirements, checking whether we already
3613 // have the cached transition. 3609 // have the cached transition.
3614 if (IsExternalArrayElementsKind(to_kind) && 3610 if (IsExternalArrayElementsKind(to_kind) &&
3615 !IsFixedTypedArrayElementsKind(map->elements_kind())) { 3611 !IsFixedTypedArrayElementsKind(map->elements_kind())) {
3616 if (map->HasElementsTransition()) { 3612 Map* next_map = map->ElementsTransitionMap();
3617 Map* next_map = map->elements_transition_map(); 3613 if (next_map != NULL && next_map->elements_kind() == to_kind) {
3618 if (next_map->elements_kind() == to_kind) return next_map; 3614 return next_map;
3619 } 3615 }
3620 return map; 3616 return map;
3621 } 3617 }
3622 3618
3623 ElementsKind kind = map->elements_kind(); 3619 ElementsKind kind = map->elements_kind();
3624 while (kind != target_kind) { 3620 while (kind != target_kind) {
3625 kind = GetNextTransitionElementsKind(kind); 3621 kind = GetNextTransitionElementsKind(kind);
3626 if (!current_map->HasElementsTransition()) return current_map; 3622 Map* next_map = current_map->ElementsTransitionMap();
3627 current_map = current_map->elements_transition_map(); 3623 if (next_map == NULL) return current_map;
3624 current_map = next_map;
3628 } 3625 }
3629 3626
3630 if (to_kind != kind && current_map->HasElementsTransition()) { 3627 Map* next_map = current_map->ElementsTransitionMap();
3628 if (to_kind != kind && next_map != NULL) {
3631 DCHECK(to_kind == DICTIONARY_ELEMENTS); 3629 DCHECK(to_kind == DICTIONARY_ELEMENTS);
3632 Map* next_map = current_map->elements_transition_map();
3633 if (next_map->elements_kind() == to_kind) return next_map; 3630 if (next_map->elements_kind() == to_kind) return next_map;
3634 } 3631 }
3635 3632
3636 DCHECK(current_map->elements_kind() == target_kind); 3633 DCHECK(current_map->elements_kind() == target_kind);
3637 return current_map; 3634 return current_map;
3638 } 3635 }
3639 3636
3640 3637
3641 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) { 3638 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
3642 Map* to_map = FindClosestElementsTransition(this, to_kind); 3639 Map* to_map = FindClosestElementsTransition(this, to_kind);
(...skipping 2079 matching lines...) Expand 10 before | Expand all | Expand 10 after
5722 if (attrs == NONE) { 5719 if (attrs == NONE) {
5723 transition_marker = isolate->factory()->nonextensible_symbol(); 5720 transition_marker = isolate->factory()->nonextensible_symbol();
5724 } else if (attrs == SEALED) { 5721 } else if (attrs == SEALED) {
5725 transition_marker = isolate->factory()->sealed_symbol(); 5722 transition_marker = isolate->factory()->sealed_symbol();
5726 } else { 5723 } else {
5727 DCHECK(attrs == FROZEN); 5724 DCHECK(attrs == FROZEN);
5728 transition_marker = isolate->factory()->frozen_symbol(); 5725 transition_marker = isolate->factory()->frozen_symbol();
5729 } 5726 }
5730 5727
5731 Handle<Map> old_map(object->map(), isolate); 5728 Handle<Map> old_map(object->map(), isolate);
5732 int transition_index = old_map->SearchSpecialTransition(*transition_marker); 5729 Map* transition =
5733 if (transition_index != TransitionArray::kNotFound) { 5730 TransitionArray::SearchSpecial(*old_map, *transition_marker);
5734 Handle<Map> transition_map(old_map->GetTransition(transition_index)); 5731 if (transition != NULL) {
5732 Handle<Map> transition_map(transition, isolate);
5735 DCHECK(transition_map->has_dictionary_elements()); 5733 DCHECK(transition_map->has_dictionary_elements());
5736 DCHECK(!transition_map->is_extensible()); 5734 DCHECK(!transition_map->is_extensible());
5737 JSObject::MigrateToMap(object, transition_map); 5735 JSObject::MigrateToMap(object, transition_map);
5738 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { 5736 } else if (object->HasFastProperties() &&
5737 TransitionArray::CanHaveMoreTransitions(old_map)) {
5739 // Create a new descriptor array with the appropriate property attributes 5738 // Create a new descriptor array with the appropriate property attributes
5740 Handle<Map> new_map = Map::CopyForPreventExtensions( 5739 Handle<Map> new_map = Map::CopyForPreventExtensions(
5741 old_map, attrs, transition_marker, "CopyForPreventExtensions"); 5740 old_map, attrs, transition_marker, "CopyForPreventExtensions");
5742 JSObject::MigrateToMap(object, new_map); 5741 JSObject::MigrateToMap(object, new_map);
5743 } else { 5742 } else {
5744 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); 5743 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
5745 // Slow path: need to normalize properties for safety 5744 // Slow path: need to normalize properties for safety
5746 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, 5745 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
5747 "SlowPreventExtensions"); 5746 "SlowPreventExtensions");
5748 5747
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5787 } 5786 }
5788 5787
5789 5788
5790 void JSObject::SetObserved(Handle<JSObject> object) { 5789 void JSObject::SetObserved(Handle<JSObject> object) {
5791 DCHECK(!object->IsJSGlobalProxy()); 5790 DCHECK(!object->IsJSGlobalProxy());
5792 DCHECK(!object->IsJSGlobalObject()); 5791 DCHECK(!object->IsJSGlobalObject());
5793 Isolate* isolate = object->GetIsolate(); 5792 Isolate* isolate = object->GetIsolate();
5794 Handle<Map> new_map; 5793 Handle<Map> new_map;
5795 Handle<Map> old_map(object->map(), isolate); 5794 Handle<Map> old_map(object->map(), isolate);
5796 DCHECK(!old_map->is_observed()); 5795 DCHECK(!old_map->is_observed());
5797 int transition_index = 5796 Map* transition = TransitionArray::SearchSpecial(
5798 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); 5797 *old_map, isolate->heap()->observed_symbol());
5799 if (transition_index != TransitionArray::kNotFound) { 5798 if (transition != NULL) {
5800 new_map = handle(old_map->GetTransition(transition_index), isolate); 5799 new_map = handle(transition, isolate);
5801 DCHECK(new_map->is_observed()); 5800 DCHECK(new_map->is_observed());
5802 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { 5801 } else if (object->HasFastProperties() &&
5802 TransitionArray::CanHaveMoreTransitions(old_map)) {
5803 new_map = Map::CopyForObserved(old_map); 5803 new_map = Map::CopyForObserved(old_map);
5804 } else { 5804 } else {
5805 new_map = Map::Copy(old_map, "SlowObserved"); 5805 new_map = Map::Copy(old_map, "SlowObserved");
5806 new_map->set_is_observed(); 5806 new_map->set_is_observed();
5807 } 5807 }
5808 JSObject::MigrateToMap(object, new_map); 5808 JSObject::MigrateToMap(object, new_map);
5809 } 5809 }
5810 5810
5811 5811
5812 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, 5812 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after
7011 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, 7011 PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
7012 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); 7012 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
7013 name->NameShortPrint(); 7013 name->NameShortPrint();
7014 PrintF(" ]\n"); 7014 PrintF(" ]\n");
7015 } 7015 }
7016 } 7016 }
7017 7017
7018 7018
7019 // static 7019 // static
7020 void Map::TraceAllTransitions(Map* map) { 7020 void Map::TraceAllTransitions(Map* map) {
7021 if (!map->HasTransitionArray()) return; 7021 Object* transitions = map->raw_transitions();
7022 TransitionArray* transitions = map->transitions(); 7022 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
7023 for (int i = 0; i < transitions->number_of_transitions(); ++i) { 7023 for (int i = -0; i < num_transitions; ++i) {
7024 Map* target = transitions->GetTarget(i); 7024 Map* target = TransitionArray::GetTarget(transitions, i);
7025 Map::TraceTransition("Transition", map, target, transitions->GetKey(i)); 7025 Name* key = TransitionArray::GetKey(transitions, i);
7026 Map::TraceTransition("Transition", map, target, key);
7026 Map::TraceAllTransitions(target); 7027 Map::TraceAllTransitions(target);
7027 } 7028 }
7028 } 7029 }
7029 7030
7030 #endif // TRACE_MAPS 7031 #endif // TRACE_MAPS
7031 7032
7032 7033
7033 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, 7034 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
7034 Handle<Name> name, SimpleTransitionFlag flag) { 7035 Handle<Name> name, SimpleTransitionFlag flag) {
7035 parent->set_owns_descriptors(false); 7036 parent->set_owns_descriptors(false);
7036 if (parent->is_prototype_map()) { 7037 if (parent->is_prototype_map()) {
7037 DCHECK(child->is_prototype_map()); 7038 DCHECK(child->is_prototype_map());
7038 #if TRACE_MAPS 7039 #if TRACE_MAPS
7039 Map::TraceTransition("NoTransition", *parent, *child, *name); 7040 Map::TraceTransition("NoTransition", *parent, *child, *name);
7040 #endif 7041 #endif
7041 } else { 7042 } else {
7042 Handle<TransitionArray> transitions = 7043 TransitionArray::Insert(parent, name, child, flag);
7043 TransitionArray::Insert(parent, name, child, flag);
7044 if (!parent->HasTransitionArray() ||
7045 *transitions != parent->transitions()) {
7046 parent->set_transitions(*transitions);
7047 }
7048 child->SetBackPointer(*parent);
7049 if (child->prototype()->IsJSObject()) { 7044 if (child->prototype()->IsJSObject()) {
7050 Handle<JSObject> proto(JSObject::cast(child->prototype())); 7045 Handle<JSObject> proto(JSObject::cast(child->prototype()));
7051 if (!child->ShouldRegisterAsPrototypeUser(proto)) { 7046 if (!child->ShouldRegisterAsPrototypeUser(proto)) {
7052 JSObject::UnregisterPrototypeUser(proto, child); 7047 JSObject::UnregisterPrototypeUser(proto, child);
7053 } 7048 }
7054 } 7049 }
7055 #if TRACE_MAPS 7050 #if TRACE_MAPS
7056 Map::TraceTransition("Transition", *parent, *child, *name); 7051 Map::TraceTransition("Transition", *parent, *child, *name);
7057 #endif 7052 #endif
7058 } 7053 }
7059 } 7054 }
7060 7055
7061 7056
7062 Handle<Map> Map::CopyReplaceDescriptors( 7057 Handle<Map> Map::CopyReplaceDescriptors(
7063 Handle<Map> map, Handle<DescriptorArray> descriptors, 7058 Handle<Map> map, Handle<DescriptorArray> descriptors,
7064 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag, 7059 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
7065 MaybeHandle<Name> maybe_name, const char* reason, 7060 MaybeHandle<Name> maybe_name, const char* reason,
7066 SimpleTransitionFlag simple_flag) { 7061 SimpleTransitionFlag simple_flag) {
7067 DCHECK(descriptors->IsSortedNoDuplicates()); 7062 DCHECK(descriptors->IsSortedNoDuplicates());
7068 7063
7069 Handle<Map> result = CopyDropDescriptors(map); 7064 Handle<Map> result = CopyDropDescriptors(map);
7070 7065
7071 if (!map->is_prototype_map()) { 7066 if (!map->is_prototype_map()) {
7072 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { 7067 if (flag == INSERT_TRANSITION &&
7068 TransitionArray::CanHaveMoreTransitions(map)) {
7073 result->InitializeDescriptors(*descriptors, *layout_descriptor); 7069 result->InitializeDescriptors(*descriptors, *layout_descriptor);
7074 7070
7075 Handle<Name> name; 7071 Handle<Name> name;
7076 CHECK(maybe_name.ToHandle(&name)); 7072 CHECK(maybe_name.ToHandle(&name));
7077 ConnectTransition(map, result, name, simple_flag); 7073 ConnectTransition(map, result, name, simple_flag);
7078 } else { 7074 } else {
7079 int length = descriptors->number_of_descriptors(); 7075 int length = descriptors->number_of_descriptors();
7080 for (int i = 0; i < length; i++) { 7076 for (int i = 0; i < length; i++) {
7081 descriptors->SetRepresentation(i, Representation::Tagged()); 7077 descriptors->SetRepresentation(i, Representation::Tagged());
7082 if (descriptors->GetDetails(i).type() == DATA) { 7078 if (descriptors->GetDetails(i).type() == DATA) {
7083 descriptors->SetValue(i, HeapType::Any()); 7079 descriptors->SetValue(i, HeapType::Any());
7084 } 7080 }
7085 } 7081 }
7086 result->InitializeDescriptors(*descriptors, 7082 result->InitializeDescriptors(*descriptors,
7087 LayoutDescriptor::FastPointerLayout()); 7083 LayoutDescriptor::FastPointerLayout());
7088 } 7084 }
7089 } else { 7085 } else {
7090 result->InitializeDescriptors(*descriptors, *layout_descriptor); 7086 result->InitializeDescriptors(*descriptors, *layout_descriptor);
7091 } 7087 }
7092 #if TRACE_MAPS 7088 #if TRACE_MAPS
7093 if (FLAG_trace_maps && 7089 if (FLAG_trace_maps &&
7094 // Mirror conditions above that did not call ConnectTransition(). 7090 // Mirror conditions above that did not call ConnectTransition().
7095 (map->is_prototype_map() || 7091 (map->is_prototype_map() ||
7096 !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) { 7092 !(flag == INSERT_TRANSITION &&
7093 TransitionArray::CanHaveMoreTransitions(map)))) {
7097 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", 7094 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
7098 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), 7095 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
7099 reason); 7096 reason);
7100 } 7097 }
7101 #endif 7098 #endif
7102 7099
7103 return result; 7100 return result;
7104 } 7101 }
7105 7102
7106 7103
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
7144 7141
7145 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); 7142 Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
7146 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); 7143 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
7147 7144
7148 return result; 7145 return result;
7149 } 7146 }
7150 7147
7151 7148
7152 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, 7149 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
7153 TransitionFlag flag) { 7150 TransitionFlag flag) {
7151 Map* maybe_elements_transition_map = NULL;
7154 if (flag == INSERT_TRANSITION) { 7152 if (flag == INSERT_TRANSITION) {
7155 DCHECK(!map->HasElementsTransition() || 7153 maybe_elements_transition_map = map->ElementsTransitionMap();
7156 ((map->elements_transition_map()->elements_kind() == 7154 DCHECK(
7157 DICTIONARY_ELEMENTS || 7155 maybe_elements_transition_map == NULL ||
7156 ((maybe_elements_transition_map->elements_kind() ==
7157 DICTIONARY_ELEMENTS ||
7158 IsExternalArrayElementsKind( 7158 IsExternalArrayElementsKind(
7159 map->elements_transition_map()->elements_kind())) && 7159 maybe_elements_transition_map->elements_kind())) &&
7160 (kind == DICTIONARY_ELEMENTS || 7160 (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind))));
7161 IsExternalArrayElementsKind(kind))));
7162 DCHECK(!IsFastElementsKind(kind) || 7161 DCHECK(!IsFastElementsKind(kind) ||
7163 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind)); 7162 IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
7164 DCHECK(kind != map->elements_kind()); 7163 DCHECK(kind != map->elements_kind());
7165 } 7164 }
7166 7165
7167 bool insert_transition = flag == INSERT_TRANSITION && 7166 bool insert_transition = flag == INSERT_TRANSITION &&
7168 map->CanHaveMoreTransitions() && 7167 TransitionArray::CanHaveMoreTransitions(map) &&
7169 !map->HasElementsTransition(); 7168 maybe_elements_transition_map == NULL;
7170 7169
7171 if (insert_transition) { 7170 if (insert_transition) {
7172 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind"); 7171 Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
7173 new_map->set_elements_kind(kind); 7172 new_map->set_elements_kind(kind);
7174 7173
7175 ConnectElementsTransition(map, new_map); 7174 ConnectElementsTransition(map, new_map);
7176 7175
7177 return new_map; 7176 return new_map;
7178 } 7177 }
7179 7178
7180 // Create a new free-floating map only if we are not allowed to store it. 7179 // Create a new free-floating map only if we are not allowed to store it.
7181 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); 7180 Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
7182 new_map->set_elements_kind(kind); 7181 new_map->set_elements_kind(kind);
7183 return new_map; 7182 return new_map;
7184 } 7183 }
7185 7184
7186 7185
7187 Handle<Map> Map::CopyForObserved(Handle<Map> map) { 7186 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
7188 DCHECK(!map->is_observed()); 7187 DCHECK(!map->is_observed());
7189 7188
7190 Isolate* isolate = map->GetIsolate(); 7189 Isolate* isolate = map->GetIsolate();
7191 7190
7192 bool insert_transition = 7191 bool insert_transition =
7193 map->CanHaveMoreTransitions() && !map->is_prototype_map(); 7192 TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
7194 7193
7195 if (insert_transition) { 7194 if (insert_transition) {
7196 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved"); 7195 Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
7197 new_map->set_is_observed(); 7196 new_map->set_is_observed();
7198 7197
7199 Handle<Name> name = isolate->factory()->observed_symbol(); 7198 Handle<Name> name = isolate->factory()->observed_symbol();
7200 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); 7199 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
7201 return new_map; 7200 return new_map;
7202 } 7201 }
7203 7202
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
7349 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, 7348 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
7350 Handle<Object> value, 7349 Handle<Object> value,
7351 PropertyAttributes attributes, 7350 PropertyAttributes attributes,
7352 StoreFromKeyed store_mode) { 7351 StoreFromKeyed store_mode) {
7353 // Dictionary maps can always have additional data properties. 7352 // Dictionary maps can always have additional data properties.
7354 if (map->is_dictionary_map()) return map; 7353 if (map->is_dictionary_map()) return map;
7355 7354
7356 // Migrate to the newest map before storing the property. 7355 // Migrate to the newest map before storing the property.
7357 map = Update(map); 7356 map = Update(map);
7358 7357
7359 int index = map->SearchTransition(kData, *name, attributes); 7358 Map* maybe_transition =
7360 if (index != TransitionArray::kNotFound) { 7359 TransitionArray::SearchTransition(*map, kData, *name, attributes);
7361 Handle<Map> transition(map->GetTransition(index)); 7360 if (maybe_transition != NULL) {
7361 Handle<Map> transition(maybe_transition);
7362 int descriptor = transition->LastAdded(); 7362 int descriptor = transition->LastAdded();
7363 7363
7364 DCHECK_EQ(attributes, transition->instance_descriptors() 7364 DCHECK_EQ(attributes, transition->instance_descriptors()
7365 ->GetDetails(descriptor) 7365 ->GetDetails(descriptor)
7366 .attributes()); 7366 .attributes());
7367 7367
7368 return Map::PrepareForDataProperty(transition, descriptor, value); 7368 return Map::PrepareForDataProperty(transition, descriptor, value);
7369 } 7369 }
7370 7370
7371 TransitionFlag flag = INSERT_TRANSITION; 7371 TransitionFlag flag = INSERT_TRANSITION;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
7440 return map; 7440 return map;
7441 } 7441 }
7442 7442
7443 // Migrate to the newest map before transitioning to the new property. 7443 // Migrate to the newest map before transitioning to the new property.
7444 map = Update(map); 7444 map = Update(map);
7445 7445
7446 PropertyNormalizationMode mode = map->is_prototype_map() 7446 PropertyNormalizationMode mode = map->is_prototype_map()
7447 ? KEEP_INOBJECT_PROPERTIES 7447 ? KEEP_INOBJECT_PROPERTIES
7448 : CLEAR_INOBJECT_PROPERTIES; 7448 : CLEAR_INOBJECT_PROPERTIES;
7449 7449
7450 int index = map->SearchTransition(kAccessor, *name, attributes); 7450 Map* maybe_transition =
7451 if (index != TransitionArray::kNotFound) { 7451 TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
7452 Handle<Map> transition(map->GetTransition(index)); 7452 if (maybe_transition != NULL) {
7453 Handle<Map> transition(maybe_transition, isolate);
7453 DescriptorArray* descriptors = transition->instance_descriptors(); 7454 DescriptorArray* descriptors = transition->instance_descriptors();
7454 int descriptor = transition->LastAdded(); 7455 int descriptor = transition->LastAdded();
7455 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); 7456 DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
7456 7457
7457 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind()); 7458 DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
7458 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); 7459 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
7459 7460
7460 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); 7461 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
7461 if (!maybe_pair->IsAccessorPair()) { 7462 if (!maybe_pair->IsAccessorPair()) {
7462 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); 7463 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
7514 7515
7515 7516
7516 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, 7517 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7517 Descriptor* descriptor, 7518 Descriptor* descriptor,
7518 TransitionFlag flag) { 7519 TransitionFlag flag) {
7519 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7520 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7520 7521
7521 // Ensure the key is unique. 7522 // Ensure the key is unique.
7522 descriptor->KeyToUniqueName(); 7523 descriptor->KeyToUniqueName();
7523 7524
7524 if (flag == INSERT_TRANSITION && 7525 if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
7525 map->owns_descriptors() && 7526 TransitionArray::CanHaveMoreTransitions(map)) {
7526 map->CanHaveMoreTransitions()) {
7527 return ShareDescriptor(map, descriptors, descriptor); 7527 return ShareDescriptor(map, descriptors, descriptor);
7528 } 7528 }
7529 7529
7530 int nof = map->NumberOfOwnDescriptors(); 7530 int nof = map->NumberOfOwnDescriptors();
7531 Handle<DescriptorArray> new_descriptors = 7531 Handle<DescriptorArray> new_descriptors =
7532 DescriptorArray::CopyUpTo(descriptors, nof, 1); 7532 DescriptorArray::CopyUpTo(descriptors, nof, 1);
7533 new_descriptors->Append(descriptor); 7533 new_descriptors->Append(descriptor);
7534 7534
7535 Handle<LayoutDescriptor> new_layout_descriptor = 7535 Handle<LayoutDescriptor> new_layout_descriptor =
7536 FLAG_unbox_double_fields 7536 FLAG_unbox_double_fields
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
7680 7680
7681 7681
7682 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) { 7682 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
7683 // No GC is supposed to happen between a call to IndexInCodeCache and 7683 // No GC is supposed to happen between a call to IndexInCodeCache and
7684 // RemoveFromCodeCache so the code cache must be there. 7684 // RemoveFromCodeCache so the code cache must be there.
7685 DCHECK(!code_cache()->IsFixedArray()); 7685 DCHECK(!code_cache()->IsFixedArray());
7686 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); 7686 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
7687 } 7687 }
7688 7688
7689 7689
7690 static void TraverseTransitionTreeInternal(Map* map,
7691 Map::TraverseCallback callback,
7692 void* data) {
7693 if (map->HasTransitionArray()) {
7694 TransitionArray* transitions = map->transitions();
7695 if (transitions->HasPrototypeTransitions()) {
7696 FixedArray* proto_trans = transitions->GetPrototypeTransitions();
7697 Object* num_obj =
7698 proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
7699 int num = Smi::cast(num_obj)->value();
7700 for (int i = 0; i < num; ++i) {
7701 int index = Map::kProtoTransitionHeaderSize + i;
7702 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)),
7703 callback, data);
7704 }
7705 }
7706 for (int i = 0; i < transitions->number_of_transitions(); ++i) {
7707 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data);
7708 }
7709 }
7710 callback(map, data);
7711 }
7712
7713
7714 // Traverse the transition tree in postorder.
7715 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
7716 // Make sure that we do not allocate in the callback.
7717 DisallowHeapAllocation no_allocation;
7718 TraverseTransitionTreeInternal(this, callback, data);
7719 }
7720
7721
7722 void CodeCache::Update( 7690 void CodeCache::Update(
7723 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { 7691 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
7724 // The number of monomorphic stubs for normal load/store/call IC's can grow to 7692 // The number of monomorphic stubs for normal load/store/call IC's can grow to
7725 // a large number and therefore they need to go into a hash table. They are 7693 // a large number and therefore they need to go into a hash table. They are
7726 // used to load global properties from cells. 7694 // used to load global properties from cells.
7727 if (code->type() == Code::NORMAL) { 7695 if (code->type() == Code::NORMAL) {
7728 // Make sure that a hash table is allocated for the normal load code cache. 7696 // Make sure that a hash table is allocated for the normal load code cache.
7729 if (code_cache->normal_type_cache()->IsUndefined()) { 7697 if (code_cache->normal_type_cache()->IsUndefined()) {
7730 Handle<Object> result = 7698 Handle<Object> result =
7731 CodeCacheHashTable::New(code_cache->GetIsolate(), 7699 CodeCacheHashTable::New(code_cache->GetIsolate(),
(...skipping 2153 matching lines...) Expand 10 before | Expand all | Expand 10 after
9885 9853
9886 9854
9887 void JSFunction::CompleteInobjectSlackTracking() { 9855 void JSFunction::CompleteInobjectSlackTracking() {
9888 DCHECK(has_initial_map()); 9856 DCHECK(has_initial_map());
9889 Map* map = initial_map(); 9857 Map* map = initial_map();
9890 9858
9891 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1); 9859 DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
9892 map->set_counter(Map::kRetainingCounterStart); 9860 map->set_counter(Map::kRetainingCounterStart);
9893 9861
9894 int slack = map->unused_property_fields(); 9862 int slack = map->unused_property_fields();
9895 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); 9863 TransitionArray::TraverseTransitionTree(map, &GetMinInobjectSlack, &slack);
9896 if (slack != 0) { 9864 if (slack != 0) {
9897 // Resize the initial map and all maps in its transition tree. 9865 // Resize the initial map and all maps in its transition tree.
9898 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); 9866 TransitionArray::TraverseTransitionTree(map, &ShrinkInstanceSize, &slack);
9899 } 9867 }
9900 } 9868 }
9901 9869
9902 9870
9903 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) { 9871 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
9904 DisallowHeapAllocation no_gc; 9872 DisallowHeapAllocation no_gc;
9905 if (!object->HasFastProperties()) return false; 9873 if (!object->HasFastProperties()) return false;
9906 Map* map = object->map(); 9874 Map* map = object->map();
9907 if (map->is_prototype_map()) return false; 9875 if (map->is_prototype_map()) return false;
9908 DescriptorArray* descriptors = map->instance_descriptors(); 9876 DescriptorArray* descriptors = map->instance_descriptors();
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
10041 kElementsKindCount, TENURED); 10009 kElementsKindCount, TENURED);
10042 10010
10043 Handle<Map> current_map = initial_map; 10011 Handle<Map> current_map = initial_map;
10044 ElementsKind kind = current_map->elements_kind(); 10012 ElementsKind kind = current_map->elements_kind();
10045 DCHECK(kind == GetInitialFastElementsKind()); 10013 DCHECK(kind == GetInitialFastElementsKind());
10046 maps->set(kind, *current_map); 10014 maps->set(kind, *current_map);
10047 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; 10015 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
10048 i < kFastElementsKindCount; ++i) { 10016 i < kFastElementsKindCount; ++i) {
10049 Handle<Map> new_map; 10017 Handle<Map> new_map;
10050 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); 10018 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
10051 if (current_map->HasElementsTransition()) { 10019 Map* maybe_elements_transition = current_map->ElementsTransitionMap();
10052 new_map = handle(current_map->elements_transition_map()); 10020 if (maybe_elements_transition != NULL) {
10021 new_map = handle(maybe_elements_transition);
10053 DCHECK(new_map->elements_kind() == next_kind); 10022 DCHECK(new_map->elements_kind() == next_kind);
10054 } else { 10023 } else {
10055 new_map = Map::CopyAsElementsKind( 10024 new_map = Map::CopyAsElementsKind(
10056 current_map, next_kind, INSERT_TRANSITION); 10025 current_map, next_kind, INSERT_TRANSITION);
10057 } 10026 }
10058 maps->set(next_kind, *new_map); 10027 maps->set(next_kind, *new_map);
10059 current_map = new_map; 10028 current_map = new_map;
10060 } 10029 }
10061 native_context->set_js_array_maps(*maps); 10030 native_context->set_js_array_maps(*maps);
10062 return initial_map; 10031 return initial_map;
(...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after
11963 Object); 11932 Object);
11964 } 11933 }
11965 11934
11966 RETURN_ON_EXCEPTION( 11935 RETURN_ON_EXCEPTION(
11967 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object); 11936 isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
11968 11937
11969 return hresult; 11938 return hresult;
11970 } 11939 }
11971 11940
11972 11941
11973 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
11974 Handle<Object> prototype) {
11975 DisallowHeapAllocation no_gc;
11976 FixedArray* cache = map->GetPrototypeTransitions();
11977 int number_of_transitions = map->NumberOfProtoTransitions();
11978 for (int i = 0; i < number_of_transitions; i++) {
11979 Map* map = Map::cast(cache->get(kProtoTransitionHeaderSize + i));
11980 if (map->prototype() == *prototype) return handle(map);
11981 }
11982 return Handle<Map>();
11983 }
11984
11985
11986 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
11987 Handle<Object> prototype,
11988 Handle<Map> target_map) {
11989 DCHECK(target_map->IsMap());
11990 DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
11991 // Don't cache prototype transition if this map is either shared, or a map of
11992 // a prototype.
11993 if (map->is_prototype_map()) return map;
11994 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
11995
11996 const int header = kProtoTransitionHeaderSize;
11997
11998 Handle<FixedArray> cache(map->GetPrototypeTransitions());
11999 int capacity = cache->length() - header;
12000 int transitions = map->NumberOfProtoTransitions() + 1;
12001
12002 if (transitions > capacity) {
12003 // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
12004 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2);
12005 if (new_capacity == capacity) return map;
12006
12007 cache = FixedArray::CopySize(cache, header + new_capacity);
12008
12009 SetPrototypeTransitions(map, cache);
12010 }
12011
12012 // Reload number of transitions as GC might shrink them.
12013 int last = map->NumberOfProtoTransitions();
12014 int entry = header + last;
12015
12016 cache->set(entry, *target_map);
12017 map->SetNumberOfProtoTransitions(last + 1);
12018
12019 return map;
12020 }
12021
12022
12023 void Map::ZapTransitions() {
12024 TransitionArray* transition_array = transitions();
12025 // TODO(mstarzinger): Temporarily use a slower version instead of the faster
12026 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
12027 Object** data = transition_array->data_start();
12028 Object* the_hole = GetHeap()->the_hole_value();
12029 int length = transition_array->length();
12030 for (int i = 0; i < length; i++) {
12031 data[i] = the_hole;
12032 }
12033 }
12034
12035
12036 void Map::ZapPrototypeTransitions() {
12037 FixedArray* proto_transitions = GetPrototypeTransitions();
12038 MemsetPointer(proto_transitions->data_start(),
12039 GetHeap()->the_hole_value(),
12040 proto_transitions->length());
12041 }
12042
12043
12044 // static 11942 // static
12045 void Map::AddDependentCompilationInfo(Handle<Map> map, 11943 void Map::AddDependentCompilationInfo(Handle<Map> map,
12046 DependentCode::DependencyGroup group, 11944 DependentCode::DependencyGroup group,
12047 CompilationInfo* info) { 11945 CompilationInfo* info) {
12048 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( 11946 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
12049 handle(map->dependent_code(), info->isolate()), group, 11947 handle(map->dependent_code(), info->isolate()), group,
12050 info->object_wrapper()); 11948 info->object_wrapper());
12051 if (*codes != map->dependent_code()) map->set_dependent_code(*codes); 11949 if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
12052 info->dependencies(group)->Add(map, info->zone()); 11950 info->dependencies(group)->Add(map, info->zone());
12053 } 11951 }
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
12339 return "allocation-site-transition-changed"; 12237 return "allocation-site-transition-changed";
12340 } 12238 }
12341 UNREACHABLE(); 12239 UNREACHABLE();
12342 return "?"; 12240 return "?";
12343 } 12241 }
12344 12242
12345 12243
12346 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, 12244 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
12347 Handle<Object> prototype, 12245 Handle<Object> prototype,
12348 PrototypeOptimizationMode mode) { 12246 PrototypeOptimizationMode mode) {
12349 Handle<Map> new_map = GetPrototypeTransition(map, prototype); 12247 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
12350 if (new_map.is_null()) { 12248 if (new_map.is_null()) {
12351 new_map = Copy(map, "TransitionToPrototype"); 12249 new_map = Copy(map, "TransitionToPrototype");
12352 PutPrototypeTransition(map, prototype, new_map); 12250 TransitionArray::PutPrototypeTransition(map, prototype, new_map);
12353 new_map->SetPrototype(prototype, mode); 12251 new_map->SetPrototype(prototype, mode);
12354 } 12252 }
12355 return new_map; 12253 return new_map;
12356 } 12254 }
12357 12255
12358 12256
12359 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 12257 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
12360 Handle<Object> value, 12258 Handle<Object> value,
12361 bool from_javascript) { 12259 bool from_javascript) {
12362 #ifdef DEBUG 12260 #ifdef DEBUG
(...skipping 4803 matching lines...) Expand 10 before | Expand all | Expand 10 after
17166 CompilationInfo* info) { 17064 CompilationInfo* info) {
17167 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( 17065 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17168 handle(cell->dependent_code(), info->isolate()), 17066 handle(cell->dependent_code(), info->isolate()),
17169 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); 17067 DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17170 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17068 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17171 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17069 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17172 cell, info->zone()); 17070 cell, info->zone());
17173 } 17071 }
17174 17072
17175 } } // namespace v8::internal 17073 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698