OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 1916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1927 return false; | 1927 return false; |
1928 } | 1928 } |
1929 // Otherwise, properties will need to be moved to the backing store. | 1929 // Otherwise, properties will need to be moved to the backing store. |
1930 return true; | 1930 return true; |
1931 } | 1931 } |
1932 | 1932 |
1933 | 1933 |
1934 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { | 1934 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { |
1935 Isolate* isolate = parent->GetIsolate(); | 1935 Isolate* isolate = parent->GetIsolate(); |
1936 Handle<Name> name = isolate->factory()->elements_transition_symbol(); | 1936 Handle<Name> name = isolate->factory()->elements_transition_symbol(); |
1937 ConnectTransition(parent, child, name, FULL_TRANSITION); | 1937 ConnectTransition(parent, child, name, SPECIAL_TRANSITION); |
1938 } | 1938 } |
1939 | 1939 |
1940 | 1940 |
1941 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { | 1941 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
1942 if (object->map() == *new_map) return; | 1942 if (object->map() == *new_map) return; |
1943 if (object->HasFastProperties()) { | 1943 if (object->HasFastProperties()) { |
1944 if (!new_map->is_dictionary_map()) { | 1944 if (!new_map->is_dictionary_map()) { |
1945 Handle<Map> old_map(object->map()); | 1945 Handle<Map> old_map(object->map()); |
1946 MigrateFastToFast(object, new_map); | 1946 MigrateFastToFast(object, new_map); |
1947 if (old_map->is_prototype_map()) { | 1947 if (old_map->is_prototype_map()) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2221 deprecate(); | 2221 deprecate(); |
2222 dependent_code()->DeoptimizeDependentCodeGroup( | 2222 dependent_code()->DeoptimizeDependentCodeGroup( |
2223 GetIsolate(), DependentCode::kTransitionGroup); | 2223 GetIsolate(), DependentCode::kTransitionGroup); |
2224 NotifyLeafMapLayoutChange(); | 2224 NotifyLeafMapLayoutChange(); |
2225 } | 2225 } |
2226 | 2226 |
2227 | 2227 |
2228 // Invalidates a transition target at |key|, and installs |new_descriptors| over | 2228 // Invalidates a transition target at |key|, and installs |new_descriptors| over |
2229 // the current instance_descriptors to ensure proper sharing of descriptor | 2229 // the current instance_descriptors to ensure proper sharing of descriptor |
2230 // arrays. | 2230 // arrays. |
2231 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) { | 2231 void Map::DeprecateTarget(PropertyType type, Name* key, |
| 2232 PropertyAttributes attributes, |
| 2233 DescriptorArray* new_descriptors) { |
2232 if (HasTransitionArray()) { | 2234 if (HasTransitionArray()) { |
2233 TransitionArray* transitions = this->transitions(); | 2235 TransitionArray* transitions = this->transitions(); |
2234 int transition = transitions->Search(key); | 2236 int transition = transitions->Search(type, key, attributes); |
2235 if (transition != TransitionArray::kNotFound) { | 2237 if (transition != TransitionArray::kNotFound) { |
2236 transitions->GetTarget(transition)->DeprecateTransitionTree(); | 2238 transitions->GetTarget(transition)->DeprecateTransitionTree(); |
2237 } | 2239 } |
2238 } | 2240 } |
2239 | 2241 |
2240 // Don't overwrite the empty descriptor array. | 2242 // Don't overwrite the empty descriptor array. |
2241 if (NumberOfOwnDescriptors() == 0) return; | 2243 if (NumberOfOwnDescriptors() == 0) return; |
2242 | 2244 |
2243 DescriptorArray* to_replace = instance_descriptors(); | 2245 DescriptorArray* to_replace = instance_descriptors(); |
2244 Map* current = this; | 2246 Map* current = this; |
(...skipping 26 matching lines...) Expand all Loading... |
2271 DisallowHeapAllocation no_allocation; | 2273 DisallowHeapAllocation no_allocation; |
2272 | 2274 |
2273 // This can only be called on roots of transition trees. | 2275 // This can only be called on roots of transition trees. |
2274 DCHECK(GetBackPointer()->IsUndefined()); | 2276 DCHECK(GetBackPointer()->IsUndefined()); |
2275 | 2277 |
2276 Map* current = this; | 2278 Map* current = this; |
2277 | 2279 |
2278 for (int i = verbatim; i < length; i++) { | 2280 for (int i = verbatim; i < length; i++) { |
2279 if (!current->HasTransitionArray()) break; | 2281 if (!current->HasTransitionArray()) break; |
2280 Name* name = descriptors->GetKey(i); | 2282 Name* name = descriptors->GetKey(i); |
| 2283 PropertyDetails details = descriptors->GetDetails(i); |
2281 TransitionArray* transitions = current->transitions(); | 2284 TransitionArray* transitions = current->transitions(); |
2282 int transition = transitions->Search(name); | 2285 int transition = |
| 2286 transitions->Search(details.type(), name, details.attributes()); |
2283 if (transition == TransitionArray::kNotFound) break; | 2287 if (transition == TransitionArray::kNotFound) break; |
2284 | 2288 |
2285 Map* next = transitions->GetTarget(transition); | 2289 Map* next = transitions->GetTarget(transition); |
2286 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2290 DescriptorArray* next_descriptors = next->instance_descriptors(); |
2287 | 2291 |
2288 PropertyDetails details = descriptors->GetDetails(i); | |
2289 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2292 PropertyDetails next_details = next_descriptors->GetDetails(i); |
2290 if (details.type() != next_details.type()) break; | 2293 if (details.type() != next_details.type()) break; |
2291 if (details.attributes() != next_details.attributes()) break; | 2294 if (details.attributes() != next_details.attributes()) break; |
2292 if (!details.representation().Equals(next_details.representation())) break; | 2295 if (!details.representation().Equals(next_details.representation())) break; |
2293 if (next_details.type() == FIELD) { | 2296 if (next_details.type() == FIELD) { |
2294 if (!descriptors->GetFieldType(i)->NowIs( | 2297 if (!descriptors->GetFieldType(i)->NowIs( |
2295 next_descriptors->GetFieldType(i))) break; | 2298 next_descriptors->GetFieldType(i))) break; |
2296 } else { | 2299 } else { |
2297 if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break; | 2300 if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break; |
2298 } | 2301 } |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2468 (old_details.type() == FIELD && | 2471 (old_details.type() == FIELD && |
2469 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || | 2472 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || |
2470 !new_representation.fits_into(old_details.representation())))) { | 2473 !new_representation.fits_into(old_details.representation())))) { |
2471 return CopyGeneralizeAllRepresentations( | 2474 return CopyGeneralizeAllRepresentations( |
2472 old_map, modify_index, store_mode, "root modification"); | 2475 old_map, modify_index, store_mode, "root modification"); |
2473 } | 2476 } |
2474 } | 2477 } |
2475 | 2478 |
2476 Handle<Map> target_map = root_map; | 2479 Handle<Map> target_map = root_map; |
2477 for (int i = root_nof; i < old_nof; ++i) { | 2480 for (int i = root_nof; i < old_nof; ++i) { |
2478 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); | 2481 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2482 int j = target_map->SearchTransition(old_details.type(), |
| 2483 old_descriptors->GetKey(i), |
| 2484 old_details.attributes()); |
2479 if (j == TransitionArray::kNotFound) break; | 2485 if (j == TransitionArray::kNotFound) break; |
2480 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2486 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
2481 Handle<DescriptorArray> tmp_descriptors = handle( | 2487 Handle<DescriptorArray> tmp_descriptors = handle( |
2482 tmp_map->instance_descriptors(), isolate); | 2488 tmp_map->instance_descriptors(), isolate); |
2483 | 2489 |
2484 // Check if target map is incompatible. | 2490 // Check if target map is incompatible. |
2485 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2486 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2491 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2487 PropertyType old_type = old_details.type(); | 2492 PropertyType old_type = old_details.type(); |
2488 PropertyType tmp_type = tmp_details.type(); | 2493 PropertyType tmp_type = tmp_details.type(); |
2489 if (tmp_details.attributes() != old_details.attributes() || | 2494 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
2490 ((tmp_type == CALLBACKS || old_type == CALLBACKS) && | 2495 if ((tmp_type == CALLBACKS || old_type == CALLBACKS) && |
2491 (tmp_type != old_type || | 2496 (tmp_type != old_type || |
2492 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { | 2497 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
2493 return CopyGeneralizeAllRepresentations( | 2498 return CopyGeneralizeAllRepresentations( |
2494 old_map, modify_index, store_mode, "incompatible"); | 2499 old_map, modify_index, store_mode, "incompatible"); |
2495 } | 2500 } |
2496 Representation old_representation = old_details.representation(); | 2501 Representation old_representation = old_details.representation(); |
2497 Representation tmp_representation = tmp_details.representation(); | 2502 Representation tmp_representation = tmp_details.representation(); |
2498 if (!old_representation.fits_into(tmp_representation) || | 2503 if (!old_representation.fits_into(tmp_representation) || |
2499 (!new_representation.fits_into(tmp_representation) && | 2504 (!new_representation.fits_into(tmp_representation) && |
2500 modify_index == i)) { | 2505 modify_index == i)) { |
2501 break; | 2506 break; |
2502 } | 2507 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2534 DCHECK(new_representation.fits_into( | 2539 DCHECK(new_representation.fits_into( |
2535 target_descriptors->GetDetails(modify_index).representation())); | 2540 target_descriptors->GetDetails(modify_index).representation())); |
2536 DCHECK(target_descriptors->GetDetails(modify_index).type() != FIELD || | 2541 DCHECK(target_descriptors->GetDetails(modify_index).type() != FIELD || |
2537 new_field_type->NowIs( | 2542 new_field_type->NowIs( |
2538 target_descriptors->GetFieldType(modify_index))); | 2543 target_descriptors->GetFieldType(modify_index))); |
2539 return target_map; | 2544 return target_map; |
2540 } | 2545 } |
2541 | 2546 |
2542 // Find the last compatible target map in the transition tree. | 2547 // Find the last compatible target map in the transition tree. |
2543 for (int i = target_nof; i < old_nof; ++i) { | 2548 for (int i = target_nof; i < old_nof; ++i) { |
2544 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); | 2549 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2550 int j = target_map->SearchTransition(old_details.type(), |
| 2551 old_descriptors->GetKey(i), |
| 2552 old_details.attributes()); |
2545 if (j == TransitionArray::kNotFound) break; | 2553 if (j == TransitionArray::kNotFound) break; |
2546 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2554 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
2547 Handle<DescriptorArray> tmp_descriptors( | 2555 Handle<DescriptorArray> tmp_descriptors( |
2548 tmp_map->instance_descriptors(), isolate); | 2556 tmp_map->instance_descriptors(), isolate); |
2549 | 2557 |
2550 // Check if target map is compatible. | 2558 // Check if target map is compatible. |
2551 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2552 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2559 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2553 if (tmp_details.attributes() != old_details.attributes() || | 2560 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
2554 ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && | 2561 if ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && |
2555 (tmp_details.type() != old_details.type() || | 2562 (tmp_details.type() != old_details.type() || |
2556 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { | 2563 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
2557 return CopyGeneralizeAllRepresentations( | 2564 return CopyGeneralizeAllRepresentations( |
2558 old_map, modify_index, store_mode, "incompatible"); | 2565 old_map, modify_index, store_mode, "incompatible"); |
2559 } | 2566 } |
2560 target_map = tmp_map; | 2567 target_map = tmp_map; |
2561 } | 2568 } |
2562 target_nof = target_map->NumberOfOwnDescriptors(); | 2569 target_nof = target_map->NumberOfOwnDescriptors(); |
2563 target_descriptors = handle(target_map->instance_descriptors(), isolate); | 2570 target_descriptors = handle(target_map->instance_descriptors(), isolate); |
2564 | 2571 |
2565 // Allocate a new descriptor array large enough to hold the required | 2572 // Allocate a new descriptor array large enough to hold the required |
2566 // descriptors, with minimally the exact same size as the old descriptor | 2573 // descriptors, with minimally the exact same size as the old descriptor |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2678 new_descriptors->Sort(); | 2685 new_descriptors->Sort(); |
2679 | 2686 |
2680 DCHECK(store_mode != FORCE_FIELD || | 2687 DCHECK(store_mode != FORCE_FIELD || |
2681 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2688 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2682 | 2689 |
2683 Handle<Map> split_map(root_map->FindLastMatchMap( | 2690 Handle<Map> split_map(root_map->FindLastMatchMap( |
2684 root_nof, old_nof, *new_descriptors), isolate); | 2691 root_nof, old_nof, *new_descriptors), isolate); |
2685 int split_nof = split_map->NumberOfOwnDescriptors(); | 2692 int split_nof = split_map->NumberOfOwnDescriptors(); |
2686 DCHECK_NE(old_nof, split_nof); | 2693 DCHECK_NE(old_nof, split_nof); |
2687 | 2694 |
2688 split_map->DeprecateTarget( | 2695 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); |
2689 old_descriptors->GetKey(split_nof), *new_descriptors); | 2696 split_map->DeprecateTarget(split_prop_details.type(), |
| 2697 old_descriptors->GetKey(split_nof), |
| 2698 split_prop_details.attributes(), *new_descriptors); |
2690 | 2699 |
2691 if (FLAG_trace_generalization) { | 2700 if (FLAG_trace_generalization) { |
2692 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2701 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2693 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2702 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
2694 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | 2703 Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
2695 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | 2704 ? handle(old_descriptors->GetFieldType(modify_index), isolate) |
2696 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | 2705 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), |
2697 isolate), isolate); | 2706 isolate), isolate); |
2698 Handle<HeapType> new_field_type = (new_details.type() == FIELD) | 2707 Handle<HeapType> new_field_type = (new_details.type() == FIELD) |
2699 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | 2708 ? handle(new_descriptors->GetFieldType(modify_index), isolate) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2768 // Check the state of the root map. | 2777 // Check the state of the root map. |
2769 Map* root_map = old_map->FindRootMap(); | 2778 Map* root_map = old_map->FindRootMap(); |
2770 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); | 2779 if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>(); |
2771 int root_nof = root_map->NumberOfOwnDescriptors(); | 2780 int root_nof = root_map->NumberOfOwnDescriptors(); |
2772 | 2781 |
2773 int old_nof = old_map->NumberOfOwnDescriptors(); | 2782 int old_nof = old_map->NumberOfOwnDescriptors(); |
2774 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2783 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2775 | 2784 |
2776 Map* new_map = root_map; | 2785 Map* new_map = root_map; |
2777 for (int i = root_nof; i < old_nof; ++i) { | 2786 for (int i = root_nof; i < old_nof; ++i) { |
2778 int j = new_map->SearchTransition(old_descriptors->GetKey(i)); | 2787 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2788 int j = new_map->SearchTransition(old_details.type(), |
| 2789 old_descriptors->GetKey(i), |
| 2790 old_details.attributes()); |
2779 if (j == TransitionArray::kNotFound) return MaybeHandle<Map>(); | 2791 if (j == TransitionArray::kNotFound) return MaybeHandle<Map>(); |
2780 new_map = new_map->GetTransition(j); | 2792 new_map = new_map->GetTransition(j); |
2781 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2793 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
2782 | 2794 |
2783 PropertyDetails new_details = new_descriptors->GetDetails(i); | 2795 PropertyDetails new_details = new_descriptors->GetDetails(i); |
2784 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2785 if (old_details.attributes() != new_details.attributes() || | 2796 if (old_details.attributes() != new_details.attributes() || |
2786 !old_details.representation().fits_into(new_details.representation())) { | 2797 !old_details.representation().fits_into(new_details.representation())) { |
2787 return MaybeHandle<Map>(); | 2798 return MaybeHandle<Map>(); |
2788 } | 2799 } |
2789 PropertyType new_type = new_details.type(); | 2800 PropertyType new_type = new_details.type(); |
2790 PropertyType old_type = old_details.type(); | 2801 PropertyType old_type = old_details.type(); |
2791 Object* new_value = new_descriptors->GetValue(i); | 2802 Object* new_value = new_descriptors->GetValue(i); |
2792 Object* old_value = old_descriptors->GetValue(i); | 2803 Object* old_value = old_descriptors->GetValue(i); |
2793 switch (new_type) { | 2804 switch (new_type) { |
2794 case FIELD: | 2805 case FIELD: |
(...skipping 2578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5373 new_element_dictionary = CopyFastElementsToDictionary( | 5384 new_element_dictionary = CopyFastElementsToDictionary( |
5374 handle(object->elements()), length, new_element_dictionary); | 5385 handle(object->elements()), length, new_element_dictionary); |
5375 } else { | 5386 } else { |
5376 // No existing elements, use a pre-allocated empty backing store | 5387 // No existing elements, use a pre-allocated empty backing store |
5377 new_element_dictionary = | 5388 new_element_dictionary = |
5378 isolate->factory()->empty_slow_element_dictionary(); | 5389 isolate->factory()->empty_slow_element_dictionary(); |
5379 } | 5390 } |
5380 } | 5391 } |
5381 | 5392 |
5382 Handle<Map> old_map(object->map(), isolate); | 5393 Handle<Map> old_map(object->map(), isolate); |
5383 int transition_index = old_map->SearchTransition( | 5394 int transition_index = |
5384 isolate->heap()->frozen_symbol()); | 5395 old_map->SearchSpecialTransition(isolate->heap()->frozen_symbol()); |
5385 if (transition_index != TransitionArray::kNotFound) { | 5396 if (transition_index != TransitionArray::kNotFound) { |
5386 Handle<Map> transition_map(old_map->GetTransition(transition_index)); | 5397 Handle<Map> transition_map(old_map->GetTransition(transition_index)); |
5387 DCHECK(transition_map->has_dictionary_elements()); | 5398 DCHECK(transition_map->has_dictionary_elements()); |
5388 DCHECK(transition_map->is_frozen()); | 5399 DCHECK(transition_map->is_frozen()); |
5389 DCHECK(!transition_map->is_extensible()); | 5400 DCHECK(!transition_map->is_extensible()); |
5390 JSObject::MigrateToMap(object, transition_map); | 5401 JSObject::MigrateToMap(object, transition_map); |
5391 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5402 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5392 // Create a new descriptor array with fully-frozen properties | 5403 // Create a new descriptor array with fully-frozen properties |
5393 Handle<Map> new_map = Map::CopyForFreeze(old_map); | 5404 Handle<Map> new_map = Map::CopyForFreeze(old_map); |
5394 JSObject::MigrateToMap(object, new_map); | 5405 JSObject::MigrateToMap(object, new_map); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5426 } | 5437 } |
5427 | 5438 |
5428 | 5439 |
5429 void JSObject::SetObserved(Handle<JSObject> object) { | 5440 void JSObject::SetObserved(Handle<JSObject> object) { |
5430 DCHECK(!object->IsJSGlobalProxy()); | 5441 DCHECK(!object->IsJSGlobalProxy()); |
5431 DCHECK(!object->IsJSGlobalObject()); | 5442 DCHECK(!object->IsJSGlobalObject()); |
5432 Isolate* isolate = object->GetIsolate(); | 5443 Isolate* isolate = object->GetIsolate(); |
5433 Handle<Map> new_map; | 5444 Handle<Map> new_map; |
5434 Handle<Map> old_map(object->map(), isolate); | 5445 Handle<Map> old_map(object->map(), isolate); |
5435 DCHECK(!old_map->is_observed()); | 5446 DCHECK(!old_map->is_observed()); |
5436 int transition_index = old_map->SearchTransition( | 5447 int transition_index = |
5437 isolate->heap()->observed_symbol()); | 5448 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); |
5438 if (transition_index != TransitionArray::kNotFound) { | 5449 if (transition_index != TransitionArray::kNotFound) { |
5439 new_map = handle(old_map->GetTransition(transition_index), isolate); | 5450 new_map = handle(old_map->GetTransition(transition_index), isolate); |
5440 DCHECK(new_map->is_observed()); | 5451 DCHECK(new_map->is_observed()); |
5441 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5452 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
5442 new_map = Map::CopyForObserved(old_map); | 5453 new_map = Map::CopyForObserved(old_map); |
5443 } else { | 5454 } else { |
5444 new_map = Map::Copy(old_map); | 5455 new_map = Map::Copy(old_map); |
5445 new_map->set_is_observed(); | 5456 new_map->set_is_observed(); |
5446 } | 5457 } |
5447 JSObject::MigrateToMap(object, new_map); | 5458 JSObject::MigrateToMap(object, new_map); |
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6594 } | 6605 } |
6595 } | 6606 } |
6596 | 6607 |
6597 { | 6608 { |
6598 DisallowHeapAllocation no_gc; | 6609 DisallowHeapAllocation no_gc; |
6599 descriptors->Append(descriptor); | 6610 descriptors->Append(descriptor); |
6600 result->InitializeDescriptors(*descriptors); | 6611 result->InitializeDescriptors(*descriptors); |
6601 } | 6612 } |
6602 | 6613 |
6603 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); | 6614 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
6604 ConnectTransition(map, result, name, SIMPLE_TRANSITION); | 6615 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
6605 | 6616 |
6606 return result; | 6617 return result; |
6607 } | 6618 } |
6608 | 6619 |
6609 | 6620 |
6610 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 6621 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
6611 Handle<Name> name, SimpleTransitionFlag flag) { | 6622 Handle<Name> name, SimpleTransitionFlag flag) { |
6612 parent->set_owns_descriptors(false); | 6623 parent->set_owns_descriptors(false); |
6613 if (parent->is_prototype_map()) { | 6624 if (parent->is_prototype_map()) { |
6614 DCHECK(child->is_prototype_map()); | 6625 DCHECK(child->is_prototype_map()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6670 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { | 6681 if (descriptors->GetDetails(new_descriptor).type() == FIELD) { |
6671 unused_property_fields = map->unused_property_fields() - 1; | 6682 unused_property_fields = map->unused_property_fields() - 1; |
6672 if (unused_property_fields < 0) { | 6683 if (unused_property_fields < 0) { |
6673 unused_property_fields += JSObject::kFieldsAdded; | 6684 unused_property_fields += JSObject::kFieldsAdded; |
6674 } | 6685 } |
6675 } | 6686 } |
6676 | 6687 |
6677 result->set_unused_property_fields(unused_property_fields); | 6688 result->set_unused_property_fields(unused_property_fields); |
6678 | 6689 |
6679 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); | 6690 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
6680 ConnectTransition(map, result, name, SIMPLE_TRANSITION); | 6691 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
6681 | 6692 |
6682 return result; | 6693 return result; |
6683 } | 6694 } |
6684 | 6695 |
6685 | 6696 |
6686 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, | 6697 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
6687 TransitionFlag flag) { | 6698 TransitionFlag flag) { |
6688 if (flag == INSERT_TRANSITION) { | 6699 if (flag == INSERT_TRANSITION) { |
6689 DCHECK(!map->HasElementsTransition() || | 6700 DCHECK(!map->HasElementsTransition() || |
6690 ((map->elements_transition_map()->elements_kind() == | 6701 ((map->elements_transition_map()->elements_kind() == |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6744 new_map = Copy(map); | 6755 new_map = Copy(map); |
6745 } | 6756 } |
6746 | 6757 |
6747 new_map->set_is_observed(); | 6758 new_map->set_is_observed(); |
6748 if (map->owns_descriptors()) { | 6759 if (map->owns_descriptors()) { |
6749 new_map->InitializeDescriptors(map->instance_descriptors()); | 6760 new_map->InitializeDescriptors(map->instance_descriptors()); |
6750 } | 6761 } |
6751 | 6762 |
6752 if (map->CanHaveMoreTransitions()) { | 6763 if (map->CanHaveMoreTransitions()) { |
6753 Handle<Name> name = isolate->factory()->observed_symbol(); | 6764 Handle<Name> name = isolate->factory()->observed_symbol(); |
6754 ConnectTransition(map, new_map, name, FULL_TRANSITION); | 6765 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
6755 } | 6766 } |
6756 return new_map; | 6767 return new_map; |
6757 } | 6768 } |
6758 | 6769 |
6759 | 6770 |
6760 Handle<Map> Map::Copy(Handle<Map> map) { | 6771 Handle<Map> Map::Copy(Handle<Map> map) { |
6761 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 6772 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
6762 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6773 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
6763 Handle<DescriptorArray> new_descriptors = | 6774 Handle<DescriptorArray> new_descriptors = |
6764 DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors); | 6775 DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors); |
6765 return CopyReplaceDescriptors( | 6776 return CopyReplaceDescriptors(map, new_descriptors, OMIT_TRANSITION, |
6766 map, new_descriptors, OMIT_TRANSITION, MaybeHandle<Name>()); | 6777 MaybeHandle<Name>(), SPECIAL_TRANSITION); |
6767 } | 6778 } |
6768 | 6779 |
6769 | 6780 |
6770 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { | 6781 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { |
6771 Handle<Map> copy = Copy(handle(isolate->object_function()->initial_map())); | 6782 Handle<Map> copy = Copy(handle(isolate->object_function()->initial_map())); |
6772 | 6783 |
6773 // Check that we do not overflow the instance size when adding the extra | 6784 // Check that we do not overflow the instance size when adding the extra |
6774 // inobject properties. If the instance size overflows, we allocate as many | 6785 // inobject properties. If the instance size overflows, we allocate as many |
6775 // properties as we can as inobject properties. | 6786 // properties as we can as inobject properties. |
6776 int max_extra_properties = | 6787 int max_extra_properties = |
(...skipping 14 matching lines...) Expand all Loading... |
6791 return copy; | 6802 return copy; |
6792 } | 6803 } |
6793 | 6804 |
6794 | 6805 |
6795 Handle<Map> Map::CopyForFreeze(Handle<Map> map) { | 6806 Handle<Map> Map::CopyForFreeze(Handle<Map> map) { |
6796 int num_descriptors = map->NumberOfOwnDescriptors(); | 6807 int num_descriptors = map->NumberOfOwnDescriptors(); |
6797 Isolate* isolate = map->GetIsolate(); | 6808 Isolate* isolate = map->GetIsolate(); |
6798 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( | 6809 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( |
6799 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); | 6810 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); |
6800 Handle<Map> new_map = CopyReplaceDescriptors( | 6811 Handle<Map> new_map = CopyReplaceDescriptors( |
6801 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol()); | 6812 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol(), |
| 6813 SPECIAL_TRANSITION); |
6802 new_map->freeze(); | 6814 new_map->freeze(); |
6803 new_map->set_is_extensible(false); | 6815 new_map->set_is_extensible(false); |
6804 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 6816 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
6805 return new_map; | 6817 return new_map; |
6806 } | 6818 } |
6807 | 6819 |
6808 | 6820 |
6809 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { | 6821 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { |
6810 PropertyDetails details = GetDetails(descriptor); | 6822 PropertyDetails details = GetDetails(descriptor); |
6811 switch (details.type()) { | 6823 switch (details.type()) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6855 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 6867 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
6856 Handle<Object> value, | 6868 Handle<Object> value, |
6857 PropertyAttributes attributes, | 6869 PropertyAttributes attributes, |
6858 StoreFromKeyed store_mode) { | 6870 StoreFromKeyed store_mode) { |
6859 // Dictionary maps can always have additional data properties. | 6871 // Dictionary maps can always have additional data properties. |
6860 if (map->is_dictionary_map()) return map; | 6872 if (map->is_dictionary_map()) return map; |
6861 | 6873 |
6862 // Migrate to the newest map before storing the property. | 6874 // Migrate to the newest map before storing the property. |
6863 map = Update(map); | 6875 map = Update(map); |
6864 | 6876 |
6865 int index = map->SearchTransition(*name); | 6877 int index = map->SearchTransition(FIELD, *name, attributes); |
6866 if (index != TransitionArray::kNotFound) { | 6878 if (index != TransitionArray::kNotFound) { |
6867 Handle<Map> transition(map->GetTransition(index)); | 6879 Handle<Map> transition(map->GetTransition(index)); |
6868 int descriptor = transition->LastAdded(); | 6880 int descriptor = transition->LastAdded(); |
6869 | 6881 |
6870 // TODO(verwaest): Handle attributes better. | 6882 DCHECK_EQ(attributes, transition->instance_descriptors() |
6871 DescriptorArray* descriptors = transition->instance_descriptors(); | 6883 ->GetDetails(descriptor) |
6872 if (descriptors->GetDetails(descriptor).attributes() != attributes) { | 6884 .attributes()); |
6873 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); | |
6874 } | |
6875 | 6885 |
6876 return Map::PrepareForDataProperty(transition, descriptor, value); | 6886 return Map::PrepareForDataProperty(transition, descriptor, value); |
6877 } | 6887 } |
6878 | 6888 |
6879 TransitionFlag flag = INSERT_TRANSITION; | 6889 TransitionFlag flag = INSERT_TRANSITION; |
6880 MaybeHandle<Map> maybe_map; | 6890 MaybeHandle<Map> maybe_map; |
6881 if (value->IsJSFunction()) { | 6891 if (value->IsJSFunction()) { |
6882 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); | 6892 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); |
6883 } else if (!map->TooManyFastProperties(store_mode)) { | 6893 } else if (!map->TooManyFastProperties(store_mode)) { |
6884 Isolate* isolate = name->GetIsolate(); | 6894 Isolate* isolate = name->GetIsolate(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6924 return map; | 6934 return map; |
6925 } | 6935 } |
6926 | 6936 |
6927 // Migrate to the newest map before transitioning to the new property. | 6937 // Migrate to the newest map before transitioning to the new property. |
6928 map = Update(map); | 6938 map = Update(map); |
6929 | 6939 |
6930 PropertyNormalizationMode mode = map->is_prototype_map() | 6940 PropertyNormalizationMode mode = map->is_prototype_map() |
6931 ? KEEP_INOBJECT_PROPERTIES | 6941 ? KEEP_INOBJECT_PROPERTIES |
6932 : CLEAR_INOBJECT_PROPERTIES; | 6942 : CLEAR_INOBJECT_PROPERTIES; |
6933 | 6943 |
6934 int index = map->SearchTransition(*name); | 6944 int index = map->SearchTransition(CALLBACKS, *name, attributes); |
6935 if (index != TransitionArray::kNotFound) { | 6945 if (index != TransitionArray::kNotFound) { |
6936 Handle<Map> transition(map->GetTransition(index)); | 6946 Handle<Map> transition(map->GetTransition(index)); |
6937 DescriptorArray* descriptors = transition->instance_descriptors(); | 6947 DescriptorArray* descriptors = transition->instance_descriptors(); |
6938 // Fast path, assume that we're modifying the last added descriptor. | |
6939 int descriptor = transition->LastAdded(); | 6948 int descriptor = transition->LastAdded(); |
6940 if (descriptors->GetKey(descriptor) != *name) { | 6949 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
6941 // If not, search for the descriptor. | |
6942 descriptor = descriptors->SearchWithCache(*name, *transition); | |
6943 } | |
6944 | 6950 |
6945 if (descriptors->GetDetails(descriptor).type() != CALLBACKS) { | 6951 DCHECK_EQ(CALLBACKS, descriptors->GetDetails(descriptor).type()); |
6946 return Map::Normalize(map, mode); | 6952 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
6947 } | |
6948 | |
6949 // TODO(verwaest): Handle attributes better. | |
6950 if (descriptors->GetDetails(descriptor).attributes() != attributes) { | |
6951 return Map::Normalize(map, mode); | |
6952 } | |
6953 | 6953 |
6954 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); | 6954 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
6955 if (!maybe_pair->IsAccessorPair()) { | 6955 if (!maybe_pair->IsAccessorPair()) { |
6956 return Map::Normalize(map, mode); | 6956 return Map::Normalize(map, mode); |
6957 } | 6957 } |
6958 | 6958 |
6959 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair); | 6959 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair); |
6960 if (pair->get(component) != *accessor) { | 6960 if (pair->get(component) != *accessor) { |
6961 return Map::Normalize(map, mode); | 6961 return Map::Normalize(map, mode); |
6962 } | 6962 } |
6963 | 6963 |
6964 return transition; | 6964 return transition; |
6965 } | 6965 } |
6966 | 6966 |
6967 Handle<AccessorPair> pair; | 6967 Handle<AccessorPair> pair; |
6968 DescriptorArray* old_descriptors = map->instance_descriptors(); | 6968 DescriptorArray* old_descriptors = map->instance_descriptors(); |
6969 int descriptor = old_descriptors->SearchWithCache(*name, *map); | 6969 int descriptor = old_descriptors->SearchWithCache(*name, *map); |
6970 if (descriptor != DescriptorArray::kNotFound) { | 6970 if (descriptor != DescriptorArray::kNotFound) { |
| 6971 if (descriptor != map->LastAdded()) { |
| 6972 return Map::Normalize(map, mode); |
| 6973 } |
6971 PropertyDetails old_details = old_descriptors->GetDetails(descriptor); | 6974 PropertyDetails old_details = old_descriptors->GetDetails(descriptor); |
6972 if (old_details.type() != CALLBACKS) { | 6975 if (old_details.type() != CALLBACKS) { |
6973 return Map::Normalize(map, mode); | 6976 return Map::Normalize(map, mode); |
6974 } | 6977 } |
6975 | 6978 |
6976 if (old_details.attributes() != attributes) { | 6979 if (old_details.attributes() != attributes) { |
6977 return Map::Normalize(map, mode); | 6980 return Map::Normalize(map, mode); |
6978 } | 6981 } |
6979 | 6982 |
6980 Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate); | 6983 Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7015 if (flag == INSERT_TRANSITION && | 7018 if (flag == INSERT_TRANSITION && |
7016 map->owns_descriptors() && | 7019 map->owns_descriptors() && |
7017 map->CanHaveMoreTransitions()) { | 7020 map->CanHaveMoreTransitions()) { |
7018 return ShareDescriptor(map, descriptors, descriptor); | 7021 return ShareDescriptor(map, descriptors, descriptor); |
7019 } | 7022 } |
7020 | 7023 |
7021 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 7024 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
7022 descriptors, map->NumberOfOwnDescriptors(), 1); | 7025 descriptors, map->NumberOfOwnDescriptors(), 1); |
7023 new_descriptors->Append(descriptor); | 7026 new_descriptors->Append(descriptor); |
7024 | 7027 |
7025 return CopyReplaceDescriptors( | 7028 return CopyReplaceDescriptors(map, new_descriptors, flag, |
7026 map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION); | 7029 descriptor->GetKey(), |
| 7030 SIMPLE_PROPERTY_TRANSITION); |
7027 } | 7031 } |
7028 | 7032 |
7029 | 7033 |
7030 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, | 7034 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, |
7031 Descriptor* descriptor, | 7035 Descriptor* descriptor, |
7032 TransitionFlag flag) { | 7036 TransitionFlag flag) { |
7033 Handle<DescriptorArray> old_descriptors(map->instance_descriptors()); | 7037 Handle<DescriptorArray> old_descriptors(map->instance_descriptors()); |
7034 | 7038 |
7035 // Ensure the key is unique. | 7039 // Ensure the key is unique. |
7036 descriptor->KeyToUniqueName(); | 7040 descriptor->KeyToUniqueName(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7110 Handle<Name> key = descriptor->GetKey(); | 7114 Handle<Name> key = descriptor->GetKey(); |
7111 DCHECK(*key == descriptors->GetKey(insertion_index)); | 7115 DCHECK(*key == descriptors->GetKey(insertion_index)); |
7112 | 7116 |
7113 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 7117 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
7114 descriptors, map->NumberOfOwnDescriptors()); | 7118 descriptors, map->NumberOfOwnDescriptors()); |
7115 | 7119 |
7116 new_descriptors->Replace(insertion_index, descriptor); | 7120 new_descriptors->Replace(insertion_index, descriptor); |
7117 | 7121 |
7118 SimpleTransitionFlag simple_flag = | 7122 SimpleTransitionFlag simple_flag = |
7119 (insertion_index == descriptors->number_of_descriptors() - 1) | 7123 (insertion_index == descriptors->number_of_descriptors() - 1) |
7120 ? SIMPLE_TRANSITION | 7124 ? SIMPLE_PROPERTY_TRANSITION |
7121 : FULL_TRANSITION; | 7125 : PROPERTY_TRANSITION; |
7122 return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag); | 7126 return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag); |
7123 } | 7127 } |
7124 | 7128 |
7125 | 7129 |
7126 void Map::UpdateCodeCache(Handle<Map> map, | 7130 void Map::UpdateCodeCache(Handle<Map> map, |
7127 Handle<Name> name, | 7131 Handle<Name> name, |
7128 Handle<Code> code) { | 7132 Handle<Code> code) { |
7129 Isolate* isolate = map->GetIsolate(); | 7133 Isolate* isolate = map->GetIsolate(); |
7130 HandleScope scope(isolate); | 7134 HandleScope scope(isolate); |
7131 // Allocate the code cache if not present. | 7135 // Allocate the code cache if not present. |
(...skipping 9433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16565 Handle<DependentCode> codes = | 16569 Handle<DependentCode> codes = |
16566 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 16570 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
16567 DependentCode::kPropertyCellChangedGroup, | 16571 DependentCode::kPropertyCellChangedGroup, |
16568 info->object_wrapper()); | 16572 info->object_wrapper()); |
16569 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 16573 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
16570 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16574 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
16571 cell, info->zone()); | 16575 cell, info->zone()); |
16572 } | 16576 } |
16573 | 16577 |
16574 } } // namespace v8::internal | 16578 } } // namespace v8::internal |
OLD | NEW |