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 | |
2465 Map* Map::FindLastMatchMap(int verbatim, | 2428 Map* Map::FindLastMatchMap(int verbatim, |
2466 int length, | 2429 int length, |
2467 DescriptorArray* descriptors) { | 2430 DescriptorArray* descriptors) { |
2468 DisallowHeapAllocation no_allocation; | 2431 DisallowHeapAllocation no_allocation; |
2469 | 2432 |
2470 // This can only be called on roots of transition trees. | 2433 // This can only be called on roots of transition trees. |
2471 ASSERT(GetBackPointer()->IsUndefined()); | 2434 ASSERT(GetBackPointer()->IsUndefined()); |
2472 | 2435 |
2473 Map* current = this; | 2436 Map* current = this; |
2474 | 2437 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2545 } | 2508 } |
2546 return HeapType::Any(isolate); | 2509 return HeapType::Any(isolate); |
2547 } | 2510 } |
2548 | 2511 |
2549 | 2512 |
2550 // static | 2513 // static |
2551 void Map::GeneralizeFieldType(Handle<Map> map, | 2514 void Map::GeneralizeFieldType(Handle<Map> map, |
2552 int modify_index, | 2515 int modify_index, |
2553 Handle<HeapType> new_field_type) { | 2516 Handle<HeapType> new_field_type) { |
2554 Isolate* isolate = map->GetIsolate(); | 2517 Isolate* isolate = map->GetIsolate(); |
2555 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | |
2556 Handle<DescriptorArray> descriptors( | |
2557 field_owner->instance_descriptors(), isolate); | |
2558 | 2518 |
2559 // Check if we actually need to generalize the field type at all. | 2519 // Check if we actually need to generalize the field type at all. |
2560 Handle<HeapType> old_field_type( | 2520 Handle<HeapType> old_field_type( |
2561 descriptors->GetFieldType(modify_index), isolate); | 2521 map->instance_descriptors()->GetFieldType(modify_index), isolate); |
2562 if (new_field_type->NowIs(old_field_type)) { | 2522 if (new_field_type->NowIs(old_field_type)) { |
2563 ASSERT(Map::GeneralizeFieldType(old_field_type, | 2523 ASSERT(Map::GeneralizeFieldType(old_field_type, |
2564 new_field_type, | 2524 new_field_type, |
2565 isolate)->NowIs(old_field_type)); | 2525 isolate)->NowIs(old_field_type)); |
2566 return; | 2526 return; |
2567 } | 2527 } |
2568 | 2528 |
| 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 |
2569 // Determine the generalized new field type. | 2535 // Determine the generalized new field type. |
2570 new_field_type = Map::GeneralizeFieldType( | 2536 new_field_type = Map::GeneralizeFieldType( |
2571 old_field_type, new_field_type, isolate); | 2537 old_field_type, new_field_type, isolate); |
2572 | 2538 |
2573 PropertyDetails details = descriptors->GetDetails(modify_index); | 2539 PropertyDetails details = descriptors->GetDetails(modify_index); |
2574 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | 2540 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), |
2575 descriptors->GetFieldIndex(modify_index), | 2541 descriptors->GetFieldIndex(modify_index), |
2576 new_field_type, | 2542 new_field_type, |
2577 details.attributes(), | 2543 details.attributes(), |
2578 details.representation()); | 2544 details.representation()); |
(...skipping 12 matching lines...) Expand all Loading... |
2591 } | 2557 } |
2592 | 2558 |
2593 | 2559 |
2594 // Generalize the representation of the descriptor at |modify_index|. | 2560 // Generalize the representation of the descriptor at |modify_index|. |
2595 // This method rewrites the transition tree to reflect the new change. To avoid | 2561 // This method rewrites the transition tree to reflect the new change. To avoid |
2596 // high degrees over polymorphism, and to stabilize quickly, on every rewrite | 2562 // high degrees over polymorphism, and to stabilize quickly, on every rewrite |
2597 // the new type is deduced by merging the current type with any potential new | 2563 // the new type is deduced by merging the current type with any potential new |
2598 // (partial) version of the type in the transition tree. | 2564 // (partial) version of the type in the transition tree. |
2599 // To do this, on each rewrite: | 2565 // To do this, on each rewrite: |
2600 // - Search the root of the transition tree using FindRootMap. | 2566 // - Search the root of the transition tree using FindRootMap. |
2601 // - Find |updated|, the newest matching version of this map using | 2567 // - Find |target_map|, the newest matching version of this map using the keys |
2602 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2568 // in the |old_map|'s descriptor array to walk the transition tree. |
2603 // walk the transition tree. | 2569 // - Merge/generalize the descriptor array of the |old_map| and |target_map|. |
2604 // - Merge/generalize the descriptor array of the current map and |updated|. | 2570 // - Generalize the |modify_index| descriptor using |new_representation| and |
2605 // - Generalize the |modify_index| descriptor using |new_representation|. | 2571 // |new_field_type|. |
2606 // - Walk the tree again starting from the root towards |updated|. Stop at | 2572 // - Walk the tree again starting from the root towards |target_map|. Stop at |
2607 // |split_map|, the first map who's descriptor array does not match the merged | 2573 // |split_map|, the first map who's descriptor array does not match the merged |
2608 // descriptor array. | 2574 // descriptor array. |
2609 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2575 // - If |target_map| == |split_map|, |target_map| is in the expected state. |
2610 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2576 // Return it. |
| 2577 // - Otherwise, invalidate the outdated transition target from |target_map|, and |
2611 // replace its transition tree with a new branch for the updated descriptors. | 2578 // replace its transition tree with a new branch for the updated descriptors. |
2612 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2579 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
2613 int modify_index, | 2580 int modify_index, |
2614 Representation new_representation, | 2581 Representation new_representation, |
2615 Handle<HeapType> new_field_type, | 2582 Handle<HeapType> new_field_type, |
2616 StoreMode store_mode) { | 2583 StoreMode store_mode) { |
2617 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2584 Isolate* isolate = old_map->GetIsolate(); |
| 2585 |
| 2586 Handle<DescriptorArray> old_descriptors( |
| 2587 old_map->instance_descriptors(), isolate); |
| 2588 int old_nof = old_map->NumberOfOwnDescriptors(); |
2618 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2589 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2619 Representation old_representation = old_details.representation(); | 2590 Representation old_representation = old_details.representation(); |
2620 | 2591 |
2621 // It's fine to transition from None to anything but double without any | 2592 // It's fine to transition from None to anything but double without any |
2622 // modification to the object, because the default uninitialized value for | 2593 // modification to the object, because the default uninitialized value for |
2623 // representation None can be overwritten by both smi and tagged values. | 2594 // representation None can be overwritten by both smi and tagged values. |
2624 // Doubles, however, would require a box allocation. | 2595 // Doubles, however, would require a box allocation. |
2625 if (old_representation.IsNone() && | 2596 if (old_representation.IsNone() && |
2626 !new_representation.IsNone() && | 2597 !new_representation.IsNone() && |
2627 !new_representation.IsDouble()) { | 2598 !new_representation.IsDouble()) { |
2628 ASSERT(old_details.type() == FIELD); | 2599 ASSERT(old_details.type() == FIELD); |
2629 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( | 2600 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( |
2630 HeapType::None())); | 2601 HeapType::None())); |
2631 if (FLAG_trace_generalization) { | 2602 if (FLAG_trace_generalization) { |
2632 old_map->PrintGeneralization( | 2603 old_map->PrintGeneralization( |
2633 stdout, "uninitialized field", | 2604 stdout, "uninitialized field", |
2634 modify_index, old_map->NumberOfOwnDescriptors(), | 2605 modify_index, old_map->NumberOfOwnDescriptors(), |
2635 old_map->NumberOfOwnDescriptors(), false, | 2606 old_map->NumberOfOwnDescriptors(), false, |
2636 old_representation, new_representation, | 2607 old_representation, new_representation, |
2637 old_descriptors->GetFieldType(modify_index), *new_field_type); | 2608 old_descriptors->GetFieldType(modify_index), *new_field_type); |
2638 } | 2609 } |
2639 old_descriptors->SetRepresentation(modify_index, new_representation); | 2610 old_descriptors->SetRepresentation(modify_index, new_representation); |
2640 old_descriptors->SetValue(modify_index, *new_field_type); | 2611 old_descriptors->SetValue(modify_index, *new_field_type); |
2641 return old_map; | 2612 return old_map; |
2642 } | 2613 } |
2643 | 2614 |
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 | |
2652 // Check the state of the root map. | 2615 // Check the state of the root map. |
| 2616 Handle<Map> root_map(old_map->FindRootMap(), isolate); |
2653 if (!old_map->EquivalentToForTransition(*root_map)) { | 2617 if (!old_map->EquivalentToForTransition(*root_map)) { |
2654 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2618 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2655 old_details.attributes(), "not equivalent"); | 2619 old_details.attributes(), "not equivalent"); |
2656 } | 2620 } |
2657 | 2621 int root_nof = root_map->NumberOfOwnDescriptors(); |
2658 int verbatim = root_map->NumberOfOwnDescriptors(); | 2622 if (modify_index < root_nof) { |
2659 | 2623 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2660 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2624 if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) || |
2661 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2625 (old_details.type() == FIELD && |
2662 old_details.attributes(), "root modification"); | 2626 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || |
2663 } | 2627 !new_representation.fits_into(old_details.representation())))) { |
2664 | 2628 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2665 int descriptors = old_map->NumberOfOwnDescriptors(); | 2629 old_details.attributes(), "root modification"); |
2666 Map* raw_updated = root_map->FindUpdatedMap( | 2630 } |
2667 verbatim, descriptors, *old_descriptors); | 2631 } |
2668 if (raw_updated == NULL) { | 2632 |
2669 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2633 Handle<Map> target_map = root_map; |
2670 old_details.attributes(), "incompatible"); | 2634 for (int i = root_nof; i < old_nof; ++i) { |
2671 } | 2635 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
2672 | 2636 if (j == TransitionArray::kNotFound) break; |
2673 Handle<Map> updated(raw_updated); | 2637 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
2674 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); | 2638 Handle<DescriptorArray> tmp_descriptors = handle( |
2675 | 2639 tmp_map->instance_descriptors(), isolate); |
2676 int valid = updated->NumberOfOwnDescriptors(); | 2640 |
2677 | 2641 // Check if target map is incompatible. |
2678 // Directly change the map if the target map is more general. Ensure that the | 2642 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2679 // target type of the modify_index is a FIELD, unless we are migrating. | 2643 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
2680 if (updated_descriptors->IsMoreGeneralThan( | 2644 PropertyType old_type = old_details.type(); |
2681 verbatim, valid, descriptors, *old_descriptors) && | 2645 PropertyType tmp_type = tmp_details.type(); |
2682 (store_mode == ALLOW_AS_CONSTANT || | 2646 if (tmp_details.attributes() != old_details.attributes() || |
2683 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2647 ((tmp_type == CALLBACKS || old_type == CALLBACKS) && |
2684 Representation updated_representation = | 2648 (tmp_type != old_type || |
2685 updated_descriptors->GetDetails(modify_index).representation(); | 2649 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { |
2686 if (new_representation.fits_into(updated_representation)) return updated; | 2650 return CopyGeneralizeAllRepresentations( |
2687 } | 2651 old_map, modify_index, store_mode, |
2688 | 2652 old_details.attributes(), "incompatible"); |
2689 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( | 2653 } |
2690 updated, verbatim, valid, descriptors, modify_index, | 2654 Representation old_representation = old_details.representation(); |
2691 store_mode, old_map); | 2655 Representation tmp_representation = tmp_details.representation(); |
2692 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 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 } |
| 2683 |
| 2684 // Directly change the map if the target map is more general. |
| 2685 Handle<DescriptorArray> target_descriptors( |
| 2686 target_map->instance_descriptors(), isolate); |
| 2687 int target_nof = target_map->NumberOfOwnDescriptors(); |
| 2688 if (target_nof == old_nof && |
| 2689 (store_mode != FORCE_FIELD || |
| 2690 target_descriptors->GetDetails(modify_index).type() == FIELD)) { |
| 2691 ASSERT(modify_index < target_nof); |
| 2692 ASSERT(new_representation.fits_into( |
| 2693 target_descriptors->GetDetails(modify_index).representation())); |
| 2694 ASSERT(target_descriptors->GetDetails(modify_index).type() != FIELD || |
| 2695 new_field_type->NowIs( |
| 2696 target_descriptors->GetFieldType(modify_index))); |
| 2697 return target_map; |
| 2698 } |
| 2699 |
| 2700 // Find the last compatible target map in the transition tree. |
| 2701 for (int i = target_nof; i < old_nof; ++i) { |
| 2702 int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
| 2703 if (j == TransitionArray::kNotFound) break; |
| 2704 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| 2705 Handle<DescriptorArray> tmp_descriptors( |
| 2706 tmp_map->instance_descriptors(), isolate); |
| 2707 |
| 2708 // Check if target map is compatible. |
| 2709 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2710 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 2711 if (tmp_details.attributes() != old_details.attributes() || |
| 2712 ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && |
| 2713 (tmp_details.type() != old_details.type() || |
| 2714 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { |
| 2715 return CopyGeneralizeAllRepresentations( |
| 2716 old_map, modify_index, store_mode, |
| 2717 old_details.attributes(), "incompatible"); |
| 2718 } |
| 2719 target_map = tmp_map; |
| 2720 } |
| 2721 target_nof = target_map->NumberOfOwnDescriptors(); |
| 2722 target_descriptors = handle(target_map->instance_descriptors(), isolate); |
| 2723 |
| 2724 // Allocate a new descriptor array large enough to hold the required |
| 2725 // descriptors, with minimally the exact same size as the old descriptor |
| 2726 // array. |
| 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 } |
| 2747 |
| 2748 // |root_nof| -> |target_nof| |
| 2749 for (int i = root_nof; i < target_nof; ++i) { |
| 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 |
| 2793 // |target_nof| -> |old_nof| |
| 2794 for (int i = target_nof; i < old_nof; ++i) { |
| 2795 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2796 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); |
| 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 |
| 2836 new_descriptors->Sort(); |
| 2837 |
| 2838 ASSERT(store_mode != FORCE_FIELD || |
2693 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2839 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2694 | 2840 |
2695 Isolate* isolate = new_descriptors->GetIsolate(); | |
2696 old_representation = | |
2697 new_descriptors->GetDetails(modify_index).representation(); | |
2698 Representation updated_representation = | |
2699 new_representation.generalize(old_representation); | |
2700 if (!updated_representation.Equals(old_representation)) { | |
2701 new_descriptors->SetRepresentation(modify_index, updated_representation); | |
2702 } | |
2703 if (new_descriptors->GetDetails(modify_index).type() == FIELD) { | |
2704 Handle<HeapType> field_type( | |
2705 new_descriptors->GetFieldType(modify_index), isolate); | |
2706 new_field_type = Map::GeneralizeFieldType( | |
2707 field_type, new_field_type, isolate); | |
2708 new_descriptors->SetValue(modify_index, *new_field_type); | |
2709 } | |
2710 | |
2711 Handle<Map> split_map(root_map->FindLastMatchMap( | 2841 Handle<Map> split_map(root_map->FindLastMatchMap( |
2712 verbatim, descriptors, *new_descriptors)); | 2842 root_nof, old_nof, *new_descriptors), isolate); |
2713 | 2843 int split_nof = split_map->NumberOfOwnDescriptors(); |
2714 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2844 ASSERT_NE(old_nof, split_nof); |
2715 // This is shadowed by |updated_descriptors| being more general than | 2845 |
2716 // |old_descriptors|. | |
2717 ASSERT(descriptors != split_descriptors); | |
2718 | |
2719 int descriptor = split_descriptors; | |
2720 split_map->DeprecateTarget( | 2846 split_map->DeprecateTarget( |
2721 old_descriptors->GetKey(descriptor), *new_descriptors); | 2847 old_descriptors->GetKey(split_nof), *new_descriptors); |
2722 | 2848 |
2723 if (FLAG_trace_generalization) { | 2849 if (FLAG_trace_generalization) { |
2724 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2850 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2725 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2851 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
2726 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | 2852 Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
2727 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | 2853 ? handle(old_descriptors->GetFieldType(modify_index), isolate) |
2728 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | 2854 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), |
2729 isolate), isolate); | 2855 isolate), isolate); |
2730 Handle<HeapType> new_field_type = (new_details.type() == FIELD) | 2856 Handle<HeapType> new_field_type = (new_details.type() == FIELD) |
2731 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | 2857 ? handle(new_descriptors->GetFieldType(modify_index), isolate) |
2732 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), | 2858 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), |
2733 isolate), isolate); | 2859 isolate), isolate); |
2734 old_map->PrintGeneralization( | 2860 old_map->PrintGeneralization( |
2735 stdout, "", modify_index, descriptor, descriptors, | 2861 stdout, "", modify_index, split_nof, old_nof, |
2736 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2862 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, |
2737 old_details.representation(), new_details.representation(), | 2863 old_details.representation(), new_details.representation(), |
2738 *old_field_type, *new_field_type); | 2864 *old_field_type, *new_field_type); |
2739 } | 2865 } |
2740 | 2866 |
2741 // Add missing transitions. | 2867 // Add missing transitions. |
2742 Handle<Map> new_map = split_map; | 2868 Handle<Map> new_map = split_map; |
2743 for (; descriptor < descriptors; descriptor++) { | 2869 for (int i = split_nof; i < old_nof; ++i) { |
2744 new_map = CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2870 new_map = CopyInstallDescriptors(new_map, i, new_descriptors); |
2745 } | 2871 } |
2746 | |
2747 new_map->set_owns_descriptors(true); | 2872 new_map->set_owns_descriptors(true); |
2748 return new_map; | 2873 return new_map; |
2749 } | 2874 } |
2750 | 2875 |
2751 | 2876 |
2752 // Generalize the representation of all FIELD descriptors. | 2877 // Generalize the representation of all FIELD descriptors. |
2753 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 2878 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
2754 Handle<Map> map) { | 2879 Handle<Map> map) { |
2755 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2880 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
2756 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { | 2881 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { |
(...skipping 5633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8390 const WhitenessWitness& witness) { | 8515 const WhitenessWitness& witness) { |
8391 Object* value = src->GetValue(index); | 8516 Object* value = src->GetValue(index); |
8392 PropertyDetails details = src->GetDetails(index); | 8517 PropertyDetails details = src->GetDetails(index); |
8393 Descriptor desc(handle(src->GetKey(index)), | 8518 Descriptor desc(handle(src->GetKey(index)), |
8394 handle(value, src->GetIsolate()), | 8519 handle(value, src->GetIsolate()), |
8395 details); | 8520 details); |
8396 Set(index, &desc, witness); | 8521 Set(index, &desc, witness); |
8397 } | 8522 } |
8398 | 8523 |
8399 | 8524 |
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 | |
8544 // We need the whiteness witness since sort will reshuffle the entries in the | 8525 // We need the whiteness witness since sort will reshuffle the entries in the |
8545 // descriptor array. If the descriptor array were to be black, the shuffling | 8526 // descriptor array. If the descriptor array were to be black, the shuffling |
8546 // would move a slot that was already recorded as pointing into an evacuation | 8527 // would move a slot that was already recorded as pointing into an evacuation |
8547 // candidate. This would result in missing updates upon evacuation. | 8528 // candidate. This would result in missing updates upon evacuation. |
8548 void DescriptorArray::Sort() { | 8529 void DescriptorArray::Sort() { |
8549 // In-place heap sort. | 8530 // In-place heap sort. |
8550 int len = number_of_descriptors(); | 8531 int len = number_of_descriptors(); |
8551 // Reset sorting since the descriptor array might contain invalid pointers. | 8532 // Reset sorting since the descriptor array might contain invalid pointers. |
8552 for (int i = 0; i < len; ++i) SetSortedKey(i, i); | 8533 for (int i = 0; i < len; ++i) SetSortedKey(i, i); |
8553 // Bottom-up max-heap construction. | 8534 // Bottom-up max-heap construction. |
(...skipping 8788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17342 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17323 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17343 static const char* error_messages_[] = { | 17324 static const char* error_messages_[] = { |
17344 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17325 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17345 }; | 17326 }; |
17346 #undef ERROR_MESSAGES_TEXTS | 17327 #undef ERROR_MESSAGES_TEXTS |
17347 return error_messages_[reason]; | 17328 return error_messages_[reason]; |
17348 } | 17329 } |
17349 | 17330 |
17350 | 17331 |
17351 } } // namespace v8::internal | 17332 } } // namespace v8::internal |
OLD | NEW |