OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2418 Map* Map::FindRootMap() { | 2418 Map* Map::FindRootMap() { |
2419 Map* result = this; | 2419 Map* result = this; |
2420 while (true) { | 2420 while (true) { |
2421 Object* back = result->GetBackPointer(); | 2421 Object* back = result->GetBackPointer(); |
2422 if (back->IsUndefined()) return result; | 2422 if (back->IsUndefined()) return result; |
2423 result = Map::cast(back); | 2423 result = Map::cast(back); |
2424 } | 2424 } |
2425 } | 2425 } |
2426 | 2426 |
2427 | 2427 |
| 2428 // Returns NULL if the updated map is incompatible. |
| 2429 Map* Map::FindUpdatedMap(int verbatim, |
| 2430 int length, |
| 2431 DescriptorArray* descriptors) { |
| 2432 DisallowHeapAllocation no_allocation; |
| 2433 |
| 2434 // This can only be called on roots of transition trees. |
| 2435 ASSERT(GetBackPointer()->IsUndefined()); |
| 2436 |
| 2437 Map* current = this; |
| 2438 |
| 2439 for (int i = verbatim; i < length; i++) { |
| 2440 if (!current->HasTransitionArray()) break; |
| 2441 Name* name = descriptors->GetKey(i); |
| 2442 TransitionArray* transitions = current->transitions(); |
| 2443 int transition = transitions->Search(name); |
| 2444 if (transition == TransitionArray::kNotFound) break; |
| 2445 current = transitions->GetTarget(transition); |
| 2446 PropertyDetails details = descriptors->GetDetails(i); |
| 2447 PropertyDetails target_details = |
| 2448 current->instance_descriptors()->GetDetails(i); |
| 2449 if (details.attributes() != target_details.attributes()) return NULL; |
| 2450 if (details.type() == CALLBACKS) { |
| 2451 if (target_details.type() != CALLBACKS) return NULL; |
| 2452 if (descriptors->GetValue(i) != |
| 2453 current->instance_descriptors()->GetValue(i)) { |
| 2454 return NULL; |
| 2455 } |
| 2456 } else if (target_details.type() == CALLBACKS) { |
| 2457 return NULL; |
| 2458 } |
| 2459 } |
| 2460 |
| 2461 return current; |
| 2462 } |
| 2463 |
| 2464 |
2428 Map* Map::FindLastMatchMap(int verbatim, | 2465 Map* Map::FindLastMatchMap(int verbatim, |
2429 int length, | 2466 int length, |
2430 DescriptorArray* descriptors) { | 2467 DescriptorArray* descriptors) { |
2431 DisallowHeapAllocation no_allocation; | 2468 DisallowHeapAllocation no_allocation; |
2432 | 2469 |
2433 // This can only be called on roots of transition trees. | 2470 // This can only be called on roots of transition trees. |
2434 ASSERT(GetBackPointer()->IsUndefined()); | 2471 ASSERT(GetBackPointer()->IsUndefined()); |
2435 | 2472 |
2436 Map* current = this; | 2473 Map* current = this; |
2437 | 2474 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 } | 2545 } |
2509 return HeapType::Any(isolate); | 2546 return HeapType::Any(isolate); |
2510 } | 2547 } |
2511 | 2548 |
2512 | 2549 |
2513 // static | 2550 // static |
2514 void Map::GeneralizeFieldType(Handle<Map> map, | 2551 void Map::GeneralizeFieldType(Handle<Map> map, |
2515 int modify_index, | 2552 int modify_index, |
2516 Handle<HeapType> new_field_type) { | 2553 Handle<HeapType> new_field_type) { |
2517 Isolate* isolate = map->GetIsolate(); | 2554 Isolate* isolate = map->GetIsolate(); |
| 2555 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); |
| 2556 Handle<DescriptorArray> descriptors( |
| 2557 field_owner->instance_descriptors(), isolate); |
2518 | 2558 |
2519 // Check if we actually need to generalize the field type at all. | 2559 // Check if we actually need to generalize the field type at all. |
2520 Handle<HeapType> old_field_type( | 2560 Handle<HeapType> old_field_type( |
2521 map->instance_descriptors()->GetFieldType(modify_index), isolate); | 2561 descriptors->GetFieldType(modify_index), isolate); |
2522 if (new_field_type->NowIs(old_field_type)) { | 2562 if (new_field_type->NowIs(old_field_type)) { |
2523 ASSERT(Map::GeneralizeFieldType(old_field_type, | 2563 ASSERT(Map::GeneralizeFieldType(old_field_type, |
2524 new_field_type, | 2564 new_field_type, |
2525 isolate)->NowIs(old_field_type)); | 2565 isolate)->NowIs(old_field_type)); |
2526 return; | 2566 return; |
2527 } | 2567 } |
2528 | 2568 |
2529 // Determine the field owner. | |
2530 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | |
2531 Handle<DescriptorArray> descriptors( | |
2532 field_owner->instance_descriptors(), isolate); | |
2533 ASSERT_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); | |
2534 | |
2535 // Determine the generalized new field type. | 2569 // Determine the generalized new field type. |
2536 new_field_type = Map::GeneralizeFieldType( | 2570 new_field_type = Map::GeneralizeFieldType( |
2537 old_field_type, new_field_type, isolate); | 2571 old_field_type, new_field_type, isolate); |
2538 | 2572 |
2539 PropertyDetails details = descriptors->GetDetails(modify_index); | 2573 PropertyDetails details = descriptors->GetDetails(modify_index); |
2540 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | 2574 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), |
2541 descriptors->GetFieldIndex(modify_index), | 2575 descriptors->GetFieldIndex(modify_index), |
2542 new_field_type, | 2576 new_field_type, |
2543 details.attributes(), | 2577 details.attributes(), |
2544 details.representation()); | 2578 details.representation()); |
(...skipping 12 matching lines...) Expand all Loading... |
2557 } | 2591 } |
2558 | 2592 |
2559 | 2593 |
2560 // Generalize the representation of the descriptor at |modify_index|. | 2594 // Generalize the representation of the descriptor at |modify_index|. |
2561 // This method rewrites the transition tree to reflect the new change. To avoid | 2595 // This method rewrites the transition tree to reflect the new change. To avoid |
2562 // high degrees over polymorphism, and to stabilize quickly, on every rewrite | 2596 // high degrees over polymorphism, and to stabilize quickly, on every rewrite |
2563 // the new type is deduced by merging the current type with any potential new | 2597 // the new type is deduced by merging the current type with any potential new |
2564 // (partial) version of the type in the transition tree. | 2598 // (partial) version of the type in the transition tree. |
2565 // To do this, on each rewrite: | 2599 // To do this, on each rewrite: |
2566 // - Search the root of the transition tree using FindRootMap. | 2600 // - Search the root of the transition tree using FindRootMap. |
2567 // - Find |target_map|, the newest matching version of this map using the keys | 2601 // - Find |updated|, the newest matching version of this map using |
2568 // in the |old_map|'s descriptor array to walk the transition tree. | 2602 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
2569 // - Merge/generalize the descriptor array of the |old_map| and |target_map|. | 2603 // walk the transition tree. |
2570 // - Generalize the |modify_index| descriptor using |new_representation| and | 2604 // - Merge/generalize the descriptor array of the current map and |updated|. |
2571 // |new_field_type|. | 2605 // - Generalize the |modify_index| descriptor using |new_representation|. |
2572 // - Walk the tree again starting from the root towards |target_map|. Stop at | 2606 // - Walk the tree again starting from the root towards |updated|. Stop at |
2573 // |split_map|, the first map who's descriptor array does not match the merged | 2607 // |split_map|, the first map who's descriptor array does not match the merged |
2574 // descriptor array. | 2608 // descriptor array. |
2575 // - If |target_map| == |split_map|, |target_map| is in the expected state. | 2609 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2576 // Return it. | 2610 // - Otherwise, invalidate the outdated transition target from |updated|, and |
2577 // - Otherwise, invalidate the outdated transition target from |target_map|, and | |
2578 // replace its transition tree with a new branch for the updated descriptors. | 2611 // replace its transition tree with a new branch for the updated descriptors. |
2579 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2612 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
2580 int modify_index, | 2613 int modify_index, |
2581 Representation new_representation, | 2614 Representation new_representation, |
2582 Handle<HeapType> new_field_type, | 2615 Handle<HeapType> new_field_type, |
2583 StoreMode store_mode) { | 2616 StoreMode store_mode) { |
2584 Isolate* isolate = old_map->GetIsolate(); | 2617 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
2585 | |
2586 Handle<DescriptorArray> old_descriptors( | |
2587 old_map->instance_descriptors(), isolate); | |
2588 int old_nof = old_map->NumberOfOwnDescriptors(); | |
2589 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2618 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2590 Representation old_representation = old_details.representation(); | 2619 Representation old_representation = old_details.representation(); |
2591 | 2620 |
2592 // It's fine to transition from None to anything but double without any | 2621 // It's fine to transition from None to anything but double without any |
2593 // modification to the object, because the default uninitialized value for | 2622 // modification to the object, because the default uninitialized value for |
2594 // representation None can be overwritten by both smi and tagged values. | 2623 // representation None can be overwritten by both smi and tagged values. |
2595 // Doubles, however, would require a box allocation. | 2624 // Doubles, however, would require a box allocation. |
2596 if (old_representation.IsNone() && | 2625 if (old_representation.IsNone() && |
2597 !new_representation.IsNone() && | 2626 !new_representation.IsNone() && |
2598 !new_representation.IsDouble()) { | 2627 !new_representation.IsDouble()) { |
2599 ASSERT(old_details.type() == FIELD); | 2628 ASSERT(old_details.type() == FIELD); |
2600 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( | 2629 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( |
2601 HeapType::None())); | 2630 HeapType::None())); |
2602 if (FLAG_trace_generalization) { | 2631 if (FLAG_trace_generalization) { |
2603 old_map->PrintGeneralization( | 2632 old_map->PrintGeneralization( |
2604 stdout, "uninitialized field", | 2633 stdout, "uninitialized field", |
2605 modify_index, old_map->NumberOfOwnDescriptors(), | 2634 modify_index, old_map->NumberOfOwnDescriptors(), |
2606 old_map->NumberOfOwnDescriptors(), false, | 2635 old_map->NumberOfOwnDescriptors(), false, |
2607 old_representation, new_representation, | 2636 old_representation, new_representation, |
2608 old_descriptors->GetFieldType(modify_index), *new_field_type); | 2637 old_descriptors->GetFieldType(modify_index), *new_field_type); |
2609 } | 2638 } |
2610 old_descriptors->SetRepresentation(modify_index, new_representation); | 2639 old_descriptors->SetRepresentation(modify_index, new_representation); |
2611 old_descriptors->SetValue(modify_index, *new_field_type); | 2640 old_descriptors->SetValue(modify_index, *new_field_type); |
2612 return old_map; | 2641 return old_map; |
2613 } | 2642 } |
2614 | 2643 |
| 2644 if (new_representation.Equals(old_representation) && |
| 2645 old_details.type() == FIELD) { |
| 2646 Map::GeneralizeFieldType(old_map, modify_index, new_field_type); |
| 2647 return old_map; |
| 2648 } |
| 2649 |
| 2650 Handle<Map> root_map(old_map->FindRootMap()); |
| 2651 |
2615 // Check the state of the root map. | 2652 // Check the state of the root map. |
2616 Handle<Map> root_map(old_map->FindRootMap(), isolate); | |
2617 if (!old_map->EquivalentToForTransition(*root_map)) { | 2653 if (!old_map->EquivalentToForTransition(*root_map)) { |
2618 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2654 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2619 old_details.attributes(), "not equivalent"); | 2655 old_details.attributes(), "not equivalent"); |
2620 } | 2656 } |
2621 int root_nof = root_map->NumberOfOwnDescriptors(); | 2657 |
2622 if (modify_index < root_nof) { | 2658 int verbatim = root_map->NumberOfOwnDescriptors(); |
2623 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2659 |
2624 if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) || | 2660 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
2625 (old_details.type() == FIELD && | 2661 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2626 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || | 2662 old_details.attributes(), "root modification"); |
2627 !new_representation.fits_into(old_details.representation())))) { | |
2628 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | |
2629 old_details.attributes(), "root modification"); | |
2630 } | |
2631 } | 2663 } |
2632 | 2664 |
2633 Handle<Map> target_map = root_map; | 2665 int descriptors = old_map->NumberOfOwnDescriptors(); |
2634 for (int i = root_nof; i < old_nof; ++i) { | 2666 Map* raw_updated = root_map->FindUpdatedMap( |
2635 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); | 2667 verbatim, descriptors, *old_descriptors); |
2636 if (j == TransitionArray::kNotFound) break; | 2668 if (raw_updated == NULL) { |
2637 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2669 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2638 Handle<DescriptorArray> tmp_descriptors = handle( | 2670 old_details.attributes(), "incompatible"); |
2639 tmp_map->instance_descriptors(), isolate); | |
2640 | |
2641 // Check if target map is incompatible. | |
2642 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2643 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | |
2644 PropertyType old_type = old_details.type(); | |
2645 PropertyType tmp_type = tmp_details.type(); | |
2646 if (tmp_details.attributes() != old_details.attributes() || | |
2647 ((tmp_type == CALLBACKS || old_type == CALLBACKS) && | |
2648 (tmp_type != old_type || | |
2649 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { | |
2650 return CopyGeneralizeAllRepresentations( | |
2651 old_map, modify_index, store_mode, | |
2652 old_details.attributes(), "incompatible"); | |
2653 } | |
2654 Representation old_representation = old_details.representation(); | |
2655 Representation tmp_representation = tmp_details.representation(); | |
2656 if (!old_representation.fits_into(tmp_representation) || | |
2657 (!new_representation.fits_into(tmp_representation) && | |
2658 modify_index == i)) { | |
2659 break; | |
2660 } | |
2661 if (tmp_type == FIELD) { | |
2662 // Generalize the field type as necessary. | |
2663 Handle<HeapType> old_field_type = (old_type == FIELD) | |
2664 ? handle(old_descriptors->GetFieldType(i), isolate) | |
2665 : old_descriptors->GetValue(i)->OptimalType( | |
2666 isolate, tmp_representation); | |
2667 if (modify_index == i) { | |
2668 old_field_type = GeneralizeFieldType( | |
2669 new_field_type, old_field_type, isolate); | |
2670 } | |
2671 GeneralizeFieldType(tmp_map, i, old_field_type); | |
2672 } else if (tmp_type == CONSTANT) { | |
2673 if (old_type != CONSTANT || | |
2674 old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { | |
2675 break; | |
2676 } | |
2677 } else { | |
2678 ASSERT_EQ(tmp_type, old_type); | |
2679 ASSERT_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i)); | |
2680 } | |
2681 target_map = tmp_map; | |
2682 } | 2671 } |
2683 | 2672 |
2684 // Directly change the map if the target map is more general. | 2673 Handle<Map> updated(raw_updated); |
2685 Handle<DescriptorArray> target_descriptors( | 2674 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
2686 target_map->instance_descriptors(), isolate); | 2675 |
2687 int target_nof = target_map->NumberOfOwnDescriptors(); | 2676 int valid = updated->NumberOfOwnDescriptors(); |
2688 if (target_nof == old_nof && | 2677 |
2689 (store_mode != FORCE_FIELD || | 2678 // Directly change the map if the target map is more general. Ensure that the |
2690 target_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2679 // target type of the modify_index is a FIELD, unless we are migrating. |
2691 ASSERT(modify_index < target_nof); | 2680 if (updated_descriptors->IsMoreGeneralThan( |
2692 ASSERT(new_representation.fits_into( | 2681 verbatim, valid, descriptors, *old_descriptors) && |
2693 target_descriptors->GetDetails(modify_index).representation())); | 2682 (store_mode == ALLOW_AS_CONSTANT || |
2694 ASSERT(target_descriptors->GetDetails(modify_index).type() != FIELD || | 2683 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2695 new_field_type->NowIs( | 2684 Representation updated_representation = |
2696 target_descriptors->GetFieldType(modify_index))); | 2685 updated_descriptors->GetDetails(modify_index).representation(); |
2697 return target_map; | 2686 if (new_representation.fits_into(updated_representation)) return updated; |
2698 } | 2687 } |
2699 | 2688 |
2700 // Find the last compatible target map in the transition tree. | 2689 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
2701 for (int i = target_nof; i < old_nof; ++i) { | 2690 updated, verbatim, valid, descriptors, modify_index, |
2702 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); | 2691 store_mode, old_map); |
2703 if (j == TransitionArray::kNotFound) break; | 2692 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
2704 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2693 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2705 Handle<DescriptorArray> tmp_descriptors( | |
2706 tmp_map->instance_descriptors(), isolate); | |
2707 | 2694 |
2708 // Check if target map is compatible. | 2695 Isolate* isolate = new_descriptors->GetIsolate(); |
2709 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2696 old_representation = |
2710 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2697 new_descriptors->GetDetails(modify_index).representation(); |
2711 if (tmp_details.attributes() != old_details.attributes() || | 2698 Representation updated_representation = |
2712 ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && | 2699 new_representation.generalize(old_representation); |
2713 (tmp_details.type() != old_details.type() || | 2700 if (!updated_representation.Equals(old_representation)) { |
2714 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { | 2701 new_descriptors->SetRepresentation(modify_index, updated_representation); |
2715 return CopyGeneralizeAllRepresentations( | |
2716 old_map, modify_index, store_mode, | |
2717 old_details.attributes(), "incompatible"); | |
2718 } | |
2719 target_map = tmp_map; | |
2720 } | 2702 } |
2721 target_nof = target_map->NumberOfOwnDescriptors(); | 2703 if (new_descriptors->GetDetails(modify_index).type() == FIELD) { |
2722 target_descriptors = handle(target_map->instance_descriptors(), isolate); | 2704 Handle<HeapType> field_type( |
2723 | 2705 new_descriptors->GetFieldType(modify_index), isolate); |
2724 // Allocate a new descriptor array large enough to hold the required | 2706 new_field_type = Map::GeneralizeFieldType( |
2725 // descriptors, with minimally the exact same size as the old descriptor | 2707 field_type, new_field_type, isolate); |
2726 // array. | 2708 new_descriptors->SetValue(modify_index, *new_field_type); |
2727 int new_slack = Max( | |
2728 old_nof, old_descriptors->number_of_descriptors()) - old_nof; | |
2729 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( | |
2730 isolate, old_nof, new_slack); | |
2731 ASSERT(new_descriptors->length() > target_descriptors->length() || | |
2732 new_descriptors->NumberOfSlackDescriptors() > 0 || | |
2733 new_descriptors->number_of_descriptors() == | |
2734 old_descriptors->number_of_descriptors()); | |
2735 ASSERT(new_descriptors->number_of_descriptors() == old_nof); | |
2736 | |
2737 // 0 -> |root_nof| | |
2738 int current_offset = 0; | |
2739 for (int i = 0; i < root_nof; ++i) { | |
2740 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2741 if (old_details.type() == FIELD) current_offset++; | |
2742 Descriptor d(handle(old_descriptors->GetKey(i), isolate), | |
2743 handle(old_descriptors->GetValue(i), isolate), | |
2744 old_details); | |
2745 new_descriptors->Set(i, &d); | |
2746 } | 2709 } |
2747 | 2710 |
2748 // |root_nof| -> |target_nof| | 2711 Handle<Map> split_map(root_map->FindLastMatchMap( |
2749 for (int i = root_nof; i < target_nof; ++i) { | 2712 verbatim, descriptors, *new_descriptors)); |
2750 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); | |
2751 PropertyDetails old_details = old_descriptors->GetDetails(i); | |
2752 PropertyDetails target_details = target_descriptors->GetDetails(i); | |
2753 target_details = target_details.CopyWithRepresentation( | |
2754 old_details.representation().generalize( | |
2755 target_details.representation())); | |
2756 if (modify_index == i) { | |
2757 target_details = target_details.CopyWithRepresentation( | |
2758 new_representation.generalize(target_details.representation())); | |
2759 } | |
2760 if (old_details.type() == FIELD || | |
2761 target_details.type() == FIELD || | |
2762 (modify_index == i && store_mode == FORCE_FIELD) || | |
2763 (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | |
2764 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | |
2765 ? handle(old_descriptors->GetFieldType(i), isolate) | |
2766 : old_descriptors->GetValue(i)->OptimalType( | |
2767 isolate, target_details.representation()); | |
2768 Handle<HeapType> target_field_type = (target_details.type() == FIELD) | |
2769 ? handle(target_descriptors->GetFieldType(i), isolate) | |
2770 : target_descriptors->GetValue(i)->OptimalType( | |
2771 isolate, target_details.representation()); | |
2772 target_field_type = GeneralizeFieldType( | |
2773 target_field_type, old_field_type, isolate); | |
2774 if (modify_index == i) { | |
2775 target_field_type = GeneralizeFieldType( | |
2776 target_field_type, new_field_type, isolate); | |
2777 } | |
2778 FieldDescriptor d(target_key, | |
2779 current_offset++, | |
2780 target_field_type, | |
2781 target_details.attributes(), | |
2782 target_details.representation()); | |
2783 new_descriptors->Set(i, &d); | |
2784 } else { | |
2785 ASSERT_NE(FIELD, target_details.type()); | |
2786 Descriptor d(target_key, | |
2787 handle(target_descriptors->GetValue(i), isolate), | |
2788 target_details); | |
2789 new_descriptors->Set(i, &d); | |
2790 } | |
2791 } | |
2792 | 2713 |
2793 // |target_nof| -> |old_nof| | 2714 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2794 for (int i = target_nof; i < old_nof; ++i) { | 2715 // This is shadowed by |updated_descriptors| being more general than |
2795 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2716 // |old_descriptors|. |
2796 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); | 2717 ASSERT(descriptors != split_descriptors); |
2797 if (modify_index == i) { | |
2798 old_details = old_details.CopyWithRepresentation( | |
2799 new_representation.generalize(old_details.representation())); | |
2800 } | |
2801 if (old_details.type() == FIELD) { | |
2802 Handle<HeapType> old_field_type( | |
2803 old_descriptors->GetFieldType(i), isolate); | |
2804 if (modify_index == i) { | |
2805 old_field_type = GeneralizeFieldType( | |
2806 old_field_type, new_field_type, isolate); | |
2807 } | |
2808 FieldDescriptor d(old_key, | |
2809 current_offset++, | |
2810 old_field_type, | |
2811 old_details.attributes(), | |
2812 old_details.representation()); | |
2813 new_descriptors->Set(i, &d); | |
2814 } else { | |
2815 ASSERT(old_details.type() == CONSTANT || old_details.type() == CALLBACKS); | |
2816 if (modify_index == i && store_mode == FORCE_FIELD) { | |
2817 FieldDescriptor d(old_key, | |
2818 current_offset++, | |
2819 GeneralizeFieldType( | |
2820 old_descriptors->GetValue(i)->OptimalType( | |
2821 isolate, old_details.representation()), | |
2822 new_field_type, isolate), | |
2823 old_details.attributes(), | |
2824 old_details.representation()); | |
2825 new_descriptors->Set(i, &d); | |
2826 } else { | |
2827 ASSERT_NE(FIELD, old_details.type()); | |
2828 Descriptor d(old_key, | |
2829 handle(old_descriptors->GetValue(i), isolate), | |
2830 old_details); | |
2831 new_descriptors->Set(i, &d); | |
2832 } | |
2833 } | |
2834 } | |
2835 | 2718 |
2836 new_descriptors->Sort(); | 2719 int descriptor = split_descriptors; |
2837 | |
2838 ASSERT(store_mode != FORCE_FIELD || | |
2839 new_descriptors->GetDetails(modify_index).type() == FIELD); | |
2840 | |
2841 Handle<Map> split_map(root_map->FindLastMatchMap( | |
2842 root_nof, old_nof, *new_descriptors), isolate); | |
2843 int split_nof = split_map->NumberOfOwnDescriptors(); | |
2844 ASSERT_NE(old_nof, split_nof); | |
2845 | |
2846 split_map->DeprecateTarget( | 2720 split_map->DeprecateTarget( |
2847 old_descriptors->GetKey(split_nof), *new_descriptors); | 2721 old_descriptors->GetKey(descriptor), *new_descriptors); |
2848 | 2722 |
2849 if (FLAG_trace_generalization) { | 2723 if (FLAG_trace_generalization) { |
2850 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2724 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2851 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2725 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
2852 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | 2726 Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
2853 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | 2727 ? handle(old_descriptors->GetFieldType(modify_index), isolate) |
2854 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | 2728 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), |
2855 isolate), isolate); | 2729 isolate), isolate); |
2856 Handle<HeapType> new_field_type = (new_details.type() == FIELD) | 2730 Handle<HeapType> new_field_type = (new_details.type() == FIELD) |
2857 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | 2731 ? handle(new_descriptors->GetFieldType(modify_index), isolate) |
2858 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), | 2732 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), |
2859 isolate), isolate); | 2733 isolate), isolate); |
2860 old_map->PrintGeneralization( | 2734 old_map->PrintGeneralization( |
2861 stdout, "", modify_index, split_nof, old_nof, | 2735 stdout, "", modify_index, descriptor, descriptors, |
2862 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2736 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, |
2863 old_details.representation(), new_details.representation(), | 2737 old_details.representation(), new_details.representation(), |
2864 *old_field_type, *new_field_type); | 2738 *old_field_type, *new_field_type); |
2865 } | 2739 } |
2866 | 2740 |
2867 // Add missing transitions. | 2741 // Add missing transitions. |
2868 Handle<Map> new_map = split_map; | 2742 Handle<Map> new_map = split_map; |
2869 for (int i = split_nof; i < old_nof; ++i) { | 2743 for (; descriptor < descriptors; descriptor++) { |
2870 new_map = CopyInstallDescriptors(new_map, i, new_descriptors); | 2744 new_map = CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
2871 } | 2745 } |
| 2746 |
2872 new_map->set_owns_descriptors(true); | 2747 new_map->set_owns_descriptors(true); |
2873 return new_map; | 2748 return new_map; |
2874 } | 2749 } |
2875 | 2750 |
2876 | 2751 |
2877 // Generalize the representation of all FIELD descriptors. | 2752 // Generalize the representation of all FIELD descriptors. |
2878 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 2753 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
2879 Handle<Map> map) { | 2754 Handle<Map> map) { |
2880 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2755 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
2881 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { | 2756 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { |
(...skipping 5633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8515 const WhitenessWitness& witness) { | 8390 const WhitenessWitness& witness) { |
8516 Object* value = src->GetValue(index); | 8391 Object* value = src->GetValue(index); |
8517 PropertyDetails details = src->GetDetails(index); | 8392 PropertyDetails details = src->GetDetails(index); |
8518 Descriptor desc(handle(src->GetKey(index)), | 8393 Descriptor desc(handle(src->GetKey(index)), |
8519 handle(value, src->GetIsolate()), | 8394 handle(value, src->GetIsolate()), |
8520 details); | 8395 details); |
8521 Set(index, &desc, witness); | 8396 Set(index, &desc, witness); |
8522 } | 8397 } |
8523 | 8398 |
8524 | 8399 |
| 8400 // Creates a new descriptor array by merging the descriptor array of |right_map| |
| 8401 // into the (at least partly) updated descriptor array of |left_map|. |
| 8402 // The method merges two descriptor array in three parts. Both descriptor arrays |
| 8403 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
| 8404 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
| 8405 // representation are generalized from both |left_map| and |right_map|. Beyond |
| 8406 // |valid|, the descriptors are copied verbatim from |right_map| up to |
| 8407 // |new_size|. |
| 8408 // In case of incompatible types, the type and representation of |right_map| is |
| 8409 // used. |
| 8410 Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map, |
| 8411 int verbatim, |
| 8412 int valid, |
| 8413 int new_size, |
| 8414 int modify_index, |
| 8415 StoreMode store_mode, |
| 8416 Handle<Map> right_map) { |
| 8417 ASSERT(verbatim <= valid); |
| 8418 ASSERT(valid <= new_size); |
| 8419 |
| 8420 // Allocate a new descriptor array large enough to hold the required |
| 8421 // descriptors, with minimally the exact same size as this descriptor array. |
| 8422 Isolate* isolate = left_map->GetIsolate(); |
| 8423 Handle<DescriptorArray> left(left_map->instance_descriptors()); |
| 8424 Handle<DescriptorArray> right(right_map->instance_descriptors()); |
| 8425 Handle<DescriptorArray> result = DescriptorArray::Allocate( |
| 8426 isolate, |
| 8427 new_size, |
| 8428 Max(new_size, right->number_of_descriptors()) - new_size); |
| 8429 ASSERT(result->length() > left->length() || |
| 8430 result->NumberOfSlackDescriptors() > 0 || |
| 8431 result->number_of_descriptors() == right->number_of_descriptors()); |
| 8432 ASSERT(result->number_of_descriptors() == new_size); |
| 8433 |
| 8434 int descriptor; |
| 8435 |
| 8436 // 0 -> |verbatim| |
| 8437 int current_offset = 0; |
| 8438 for (descriptor = 0; descriptor < verbatim; descriptor++) { |
| 8439 if (left->GetDetails(descriptor).type() == FIELD) current_offset++; |
| 8440 Descriptor d(handle(right->GetKey(descriptor)), |
| 8441 handle(right->GetValue(descriptor), right->GetIsolate()), |
| 8442 right->GetDetails(descriptor)); |
| 8443 result->Set(descriptor, &d); |
| 8444 } |
| 8445 |
| 8446 // |verbatim| -> |valid| |
| 8447 for (; descriptor < valid; descriptor++) { |
| 8448 PropertyDetails left_details = left->GetDetails(descriptor); |
| 8449 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8450 if (left_details.type() == FIELD || right_details.type() == FIELD || |
| 8451 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
| 8452 (left_details.type() == CONSTANT && |
| 8453 right_details.type() == CONSTANT && |
| 8454 left->GetValue(descriptor) != right->GetValue(descriptor))) { |
| 8455 ASSERT(left_details.type() == CONSTANT || left_details.type() == FIELD); |
| 8456 ASSERT(right_details.type() == CONSTANT || right_details.type() == FIELD); |
| 8457 Representation representation = left_details.representation().generalize( |
| 8458 right_details.representation()); |
| 8459 Handle<HeapType> left_type = (left_details.type() == FIELD) |
| 8460 ? handle(left->GetFieldType(descriptor), isolate) |
| 8461 : left->GetValue(descriptor)->OptimalType(isolate, representation); |
| 8462 Handle<HeapType> right_type = (right_details.type() == FIELD) |
| 8463 ? handle(right->GetFieldType(descriptor), isolate) |
| 8464 : right->GetValue(descriptor)->OptimalType(isolate, representation); |
| 8465 Handle<HeapType> field_type = Map::GeneralizeFieldType( |
| 8466 left_type, right_type, isolate); |
| 8467 FieldDescriptor d(handle(left->GetKey(descriptor), isolate), |
| 8468 current_offset++, |
| 8469 field_type, |
| 8470 right_details.attributes(), |
| 8471 representation); |
| 8472 result->Set(descriptor, &d); |
| 8473 } else { |
| 8474 Descriptor d(handle(right->GetKey(descriptor), isolate), |
| 8475 handle(right->GetValue(descriptor), isolate), |
| 8476 right_details); |
| 8477 result->Set(descriptor, &d); |
| 8478 } |
| 8479 } |
| 8480 |
| 8481 // |valid| -> |new_size| |
| 8482 for (; descriptor < new_size; descriptor++) { |
| 8483 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8484 if (right_details.type() == FIELD) { |
| 8485 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), |
| 8486 current_offset++, |
| 8487 handle(right->GetFieldType(descriptor), isolate), |
| 8488 right_details.attributes(), |
| 8489 right_details.representation()); |
| 8490 result->Set(descriptor, &d); |
| 8491 } else if (store_mode == FORCE_FIELD && descriptor == modify_index) { |
| 8492 ASSERT_EQ(CONSTANT, right_details.type()); |
| 8493 Representation field_representation = right_details.representation(); |
| 8494 Handle<HeapType> field_type = right->GetValue(descriptor)->OptimalType( |
| 8495 isolate, field_representation); |
| 8496 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), |
| 8497 current_offset++, |
| 8498 field_type, |
| 8499 right_details.attributes(), |
| 8500 field_representation); |
| 8501 result->Set(descriptor, &d); |
| 8502 } else { |
| 8503 Descriptor d(handle(right->GetKey(descriptor), isolate), |
| 8504 handle(right->GetValue(descriptor), isolate), |
| 8505 right_details); |
| 8506 result->Set(descriptor, &d); |
| 8507 } |
| 8508 } |
| 8509 |
| 8510 result->Sort(); |
| 8511 return result; |
| 8512 } |
| 8513 |
| 8514 |
| 8515 // Checks whether a merge of |other| into |this| would return a copy of |this|. |
| 8516 bool DescriptorArray::IsMoreGeneralThan(int verbatim, |
| 8517 int valid, |
| 8518 int new_size, |
| 8519 DescriptorArray* other) { |
| 8520 ASSERT(verbatim <= valid); |
| 8521 ASSERT(valid <= new_size); |
| 8522 if (valid != new_size) return false; |
| 8523 |
| 8524 for (int descriptor = verbatim; descriptor < valid; descriptor++) { |
| 8525 PropertyDetails details = GetDetails(descriptor); |
| 8526 PropertyDetails other_details = other->GetDetails(descriptor); |
| 8527 if (!other_details.representation().fits_into(details.representation())) { |
| 8528 return false; |
| 8529 } |
| 8530 if (details.type() == CONSTANT) { |
| 8531 if (other_details.type() != CONSTANT) return false; |
| 8532 if (GetValue(descriptor) != other->GetValue(descriptor)) return false; |
| 8533 } else if (details.type() == FIELD && other_details.type() == FIELD) { |
| 8534 if (!other->GetFieldType(descriptor)->NowIs(GetFieldType(descriptor))) { |
| 8535 return false; |
| 8536 } |
| 8537 } |
| 8538 } |
| 8539 |
| 8540 return true; |
| 8541 } |
| 8542 |
| 8543 |
8525 // We need the whiteness witness since sort will reshuffle the entries in the | 8544 // We need the whiteness witness since sort will reshuffle the entries in the |
8526 // descriptor array. If the descriptor array were to be black, the shuffling | 8545 // descriptor array. If the descriptor array were to be black, the shuffling |
8527 // would move a slot that was already recorded as pointing into an evacuation | 8546 // would move a slot that was already recorded as pointing into an evacuation |
8528 // candidate. This would result in missing updates upon evacuation. | 8547 // candidate. This would result in missing updates upon evacuation. |
8529 void DescriptorArray::Sort() { | 8548 void DescriptorArray::Sort() { |
8530 // In-place heap sort. | 8549 // In-place heap sort. |
8531 int len = number_of_descriptors(); | 8550 int len = number_of_descriptors(); |
8532 // Reset sorting since the descriptor array might contain invalid pointers. | 8551 // Reset sorting since the descriptor array might contain invalid pointers. |
8533 for (int i = 0; i < len; ++i) SetSortedKey(i, i); | 8552 for (int i = 0; i < len; ++i) SetSortedKey(i, i); |
8534 // Bottom-up max-heap construction. | 8553 // Bottom-up max-heap construction. |
(...skipping 8788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17323 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17342 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17324 static const char* error_messages_[] = { | 17343 static const char* error_messages_[] = { |
17325 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17344 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17326 }; | 17345 }; |
17327 #undef ERROR_MESSAGES_TEXTS | 17346 #undef ERROR_MESSAGES_TEXTS |
17328 return error_messages_[reason]; | 17347 return error_messages_[reason]; |
17329 } | 17348 } |
17330 | 17349 |
17331 | 17350 |
17332 } } // namespace v8::internal | 17351 } } // namespace v8::internal |
OLD | NEW |