| 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 |