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

Side by Side Diff: src/objects.cc

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