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

Side by Side Diff: src/objects.cc

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

Powered by Google App Engine
This is Rietveld 408576698