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

Side by Side Diff: src/objects.cc

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