OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
6 | 6 |
7 #include "vm/code_generator.h" | 7 #include "vm/code_generator.h" |
8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
11 #include "vm/longjump.h" | 11 #include "vm/longjump.h" |
12 #include "vm/object_store.h" | 12 #include "vm/object_store.h" |
13 #include "vm/report.h" | 13 #include "vm/report.h" |
14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); | 18 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); |
19 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); | 19 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); |
20 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); | 20 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); |
| 21 DECLARE_FLAG(bool, supermixin); |
21 DECLARE_FLAG(bool, use_cha_deopt); | 22 DECLARE_FLAG(bool, use_cha_deopt); |
22 | 23 |
23 | 24 |
24 bool ClassFinalizer::AllClassesFinalized() { | 25 bool ClassFinalizer::AllClassesFinalized() { |
25 ObjectStore* object_store = Isolate::Current()->object_store(); | 26 ObjectStore* object_store = Isolate::Current()->object_store(); |
26 const GrowableObjectArray& classes = | 27 const GrowableObjectArray& classes = |
27 GrowableObjectArray::Handle(object_store->pending_classes()); | 28 GrowableObjectArray::Handle(object_store->pending_classes()); |
28 return classes.Length() == 0; | 29 return classes.Length() == 0; |
29 } | 30 } |
30 | 31 |
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 | 1555 |
1555 | 1556 |
1556 // Clone the type parameters of the super class and of the mixin class of this | 1557 // Clone the type parameters of the super class and of the mixin class of this |
1557 // mixin application class and use them as the type parameters of this mixin | 1558 // mixin application class and use them as the type parameters of this mixin |
1558 // application class. Set the type arguments of the super type, of the mixin | 1559 // application class. Set the type arguments of the super type, of the mixin |
1559 // type (as well as of the interface type, which is identical to the mixin type) | 1560 // type (as well as of the interface type, which is identical to the mixin type) |
1560 // to refer to the respective type parameters of the mixin application class. | 1561 // to refer to the respective type parameters of the mixin application class. |
1561 // In other words, decorate this mixin application class with type parameters | 1562 // In other words, decorate this mixin application class with type parameters |
1562 // that forward to the super type and mixin type (and interface type). | 1563 // that forward to the super type and mixin type (and interface type). |
1563 // Example: | 1564 // Example: |
1564 // class S<T> { } | 1565 // class S<T extends BT> { } |
1565 // class M<T> { } | 1566 // class M<T extends BT> { } |
1566 // class C<E> extends S<E> with M<List<E>> { } | 1567 // class C<E extends BE> extends S<E> with M<List<E>> { } |
1567 // results in | 1568 // results in |
1568 // class S&M<T`, T> extends S<T`> implements M<T> { } // mixin == M<T> | 1569 // class S&M<T`, T extends BT> extends S<T`> implements M<T> { } |
1569 // class C<E> extends S&M<E, List<E>> { } | 1570 // class C<E extends BE> extends S&M<E, List<E>> { } |
1570 // CloneMixinAppTypeParameters decorates class S&M with type parameters T` and | 1571 // CloneMixinAppTypeParameters decorates class S&M with type parameters T` and |
1571 // T, and use them as type arguments in S<T`> and M<T>. | 1572 // T, and use them as type arguments in S<T`> and M<T>. |
| 1573 // Note that the bound BT on T of S is not applied to T` of S&M. However, the |
| 1574 // bound BT on T of M is applied to T of S&M. See comments below. |
1572 void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) { | 1575 void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) { |
1573 ASSERT(mixin_app_class.type_parameters() == TypeArguments::null()); | 1576 ASSERT(mixin_app_class.type_parameters() == TypeArguments::null()); |
1574 Isolate* isolate = Isolate::Current(); | 1577 Isolate* isolate = Isolate::Current(); |
1575 const AbstractType& super_type = AbstractType::Handle(isolate, | 1578 const AbstractType& super_type = AbstractType::Handle(isolate, |
1576 mixin_app_class.super_type()); | 1579 mixin_app_class.super_type()); |
1577 ASSERT(super_type.IsResolved()); | 1580 ASSERT(super_type.IsResolved()); |
1578 const Class& super_class = Class::Handle(isolate, super_type.type_class()); | 1581 const Class& super_class = Class::Handle(isolate, super_type.type_class()); |
1579 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 1582 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
1580 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); | 1583 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); |
1581 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); | 1584 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); |
1582 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); | 1585 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); |
1583 // The mixin class cannot be Object and this was checked earlier. | |
1584 ASSERT(!mixin_class.IsObjectClass()); | |
1585 | 1586 |
1586 // The mixin type (in raw form) should have been added to the interfaces | 1587 // The mixin type (in raw form) should have been added to the interfaces |
1587 // implemented by the mixin application class. This is necessary so that cycle | 1588 // implemented by the mixin application class. This is necessary so that cycle |
1588 // check works at compile time (type arguments are ignored) and so that | 1589 // check works at compile time (type arguments are ignored) and so that |
1589 // type tests work at runtime (by then, type arguments will have been set, see | 1590 // type tests work at runtime (by then, type arguments will have been set, see |
1590 // below). | 1591 // below). |
1591 ASSERT(mixin_app_class.interfaces() != Object::empty_array().raw()); | 1592 ASSERT(mixin_app_class.interfaces() != Object::empty_array().raw()); |
1592 | 1593 |
1593 // If both the super type and the mixin type are non generic, the mixin | 1594 // If both the super type and the mixin type are non generic, the mixin |
1594 // application class is non generic as well and we can skip type parameter | 1595 // application class is non generic as well and we can skip type parameter |
1595 // cloning. | 1596 // cloning. |
1596 bool has_uninstantiated_bounds = false; | 1597 TypeArguments& instantiator = TypeArguments::Handle(isolate); |
1597 if ((num_super_type_params + num_mixin_type_params) > 0) { | 1598 if ((num_super_type_params + num_mixin_type_params) > 0) { |
1598 // If the last ampersand in the name of the mixin application class is | 1599 // If the last ampersand in the name of the mixin application class is |
1599 // doubled, the same type parameters can propagate the type arguments to | 1600 // doubled, the same type parameters can propagate the type arguments to |
1600 // the super type and to the mixin type. | 1601 // the super type and to the mixin type. |
1601 bool share_type_params = false; | 1602 bool share_type_params = false; |
1602 if (num_super_type_params == num_mixin_type_params) { | 1603 if (num_super_type_params == num_mixin_type_params) { |
1603 const String& name = String::Handle(isolate, mixin_app_class.Name()); | 1604 const String& name = String::Handle(isolate, mixin_app_class.Name()); |
1604 for (intptr_t i = name.Length() - 1; i > 0; --i) { | 1605 for (intptr_t i = name.Length() - 1; i > 0; --i) { |
1605 if (name.CharAt(i) == '&') { | 1606 if (name.CharAt(i) == '&') { |
1606 if (name.CharAt(i - 1) == '&') { | 1607 if (name.CharAt(i - 1) == '&') { |
(...skipping 16 matching lines...) Expand all Loading... |
1623 // First, clone the super class type parameters. Rename them so that | 1624 // First, clone the super class type parameters. Rename them so that |
1624 // there can be no name conflict between the parameters of the super | 1625 // there can be no name conflict between the parameters of the super |
1625 // class and the mixin class. | 1626 // class and the mixin class. |
1626 if (!share_type_params && (num_super_type_params > 0)) { | 1627 if (!share_type_params && (num_super_type_params > 0)) { |
1627 const TypeArguments& super_type_params = | 1628 const TypeArguments& super_type_params = |
1628 TypeArguments::Handle(isolate, super_class.type_parameters()); | 1629 TypeArguments::Handle(isolate, super_class.type_parameters()); |
1629 const TypeArguments& super_type_args = TypeArguments::Handle(isolate, | 1630 const TypeArguments& super_type_args = TypeArguments::Handle(isolate, |
1630 TypeArguments::New(num_super_type_params)); | 1631 TypeArguments::New(num_super_type_params)); |
1631 // The cloned super class type parameters do not need to repeat their | 1632 // The cloned super class type parameters do not need to repeat their |
1632 // bounds, since the bound checks will be performed at the super class | 1633 // bounds, since the bound checks will be performed at the super class |
1633 // level. | 1634 // level. As a consequence, if this mixin application is used itself as a |
| 1635 // mixin in another mixin application, the bounds will be ignored, which |
| 1636 // is correct, because the other mixin application does not inherit from |
| 1637 // the super class of its mixin. Note also that the other mixin |
| 1638 // application will only mixin the last mixin type listed in the first |
| 1639 // mixin application it is mixing in. |
1634 param_bound = isolate->object_store()->object_type(); | 1640 param_bound = isolate->object_store()->object_type(); |
1635 for (intptr_t i = 0; i < num_super_type_params; i++) { | 1641 for (intptr_t i = 0; i < num_super_type_params; i++) { |
1636 param ^= super_type_params.TypeAt(i); | 1642 param ^= super_type_params.TypeAt(i); |
1637 param_name = param.name(); | 1643 param_name = param.name(); |
1638 param_name = String::Concat(param_name, Symbols::Backtick()); | 1644 param_name = String::Concat(param_name, Symbols::Backtick()); |
1639 param_name = Symbols::New(param_name); | 1645 param_name = Symbols::New(param_name); |
1640 cloned_param = TypeParameter::New(mixin_app_class, | 1646 cloned_param = TypeParameter::New(mixin_app_class, |
1641 cloned_index, | 1647 cloned_index, |
1642 param_name, | 1648 param_name, |
1643 param_bound, | 1649 param_bound, |
1644 param.token_pos()); | 1650 param.token_pos()); |
1645 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1651 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
1646 // Change the type arguments of the super type to refer to the | 1652 // Change the type arguments of the super type to refer to the |
1647 // cloned type parameters of the mixin application class. | 1653 // cloned type parameters of the mixin application class. |
1648 super_type_args.SetTypeAt(cloned_index, cloned_param); | 1654 super_type_args.SetTypeAt(cloned_index, cloned_param); |
1649 cloned_index++; | 1655 cloned_index++; |
1650 } | 1656 } |
1651 // The super type may have a BoundedType as type argument, but cannot be | 1657 // The super type may have a BoundedType as type argument, but cannot be |
1652 // a BoundedType itself. | 1658 // a BoundedType itself. |
1653 Type::Cast(super_type).set_arguments(super_type_args); | 1659 Type::Cast(super_type).set_arguments(super_type_args); |
1654 ASSERT(!super_type.IsFinalized()); | 1660 ASSERT(!super_type.IsFinalized()); |
1655 } | 1661 } |
1656 | 1662 |
1657 // Second, clone the type parameters of the mixin class. | 1663 // Second, clone the type parameters of the mixin class. |
1658 // We need to retain the parameter names of the mixin class | 1664 // We need to retain the parameter names of the mixin class |
1659 // since the code that will be compiled in the context of the | 1665 // since the code that will be compiled in the context of the |
1660 // mixin application class may refer to the type parameters | 1666 // mixin application class may refer to the type parameters |
1661 // with that name. | 1667 // with that name. We also retain the type parameter bounds. |
1662 if (num_mixin_type_params > 0) { | 1668 if (num_mixin_type_params > 0) { |
1663 const TypeArguments& mixin_params = | 1669 const TypeArguments& mixin_params = |
1664 TypeArguments::Handle(isolate, mixin_class.type_parameters()); | 1670 TypeArguments::Handle(isolate, mixin_class.type_parameters()); |
| 1671 const intptr_t offset = |
| 1672 mixin_class.NumTypeArguments() - mixin_class.NumTypeParameters(); |
1665 const TypeArguments& mixin_type_args = TypeArguments::Handle(isolate, | 1673 const TypeArguments& mixin_type_args = TypeArguments::Handle(isolate, |
1666 TypeArguments::New(num_mixin_type_params)); | 1674 TypeArguments::New(num_mixin_type_params)); |
| 1675 instantiator ^= TypeArguments::New(offset + num_mixin_type_params); |
| 1676 bool has_uninstantiated_bounds = false; |
1667 for (intptr_t i = 0; i < num_mixin_type_params; i++) { | 1677 for (intptr_t i = 0; i < num_mixin_type_params; i++) { |
1668 param ^= mixin_params.TypeAt(i); | 1678 param ^= mixin_params.TypeAt(i); |
1669 param_name = param.name(); | 1679 param_name = param.name(); |
1670 param_bound = param.bound(); // The bound will be adjusted below. | 1680 param_bound = param.bound(); // The bound will be adjusted below. |
1671 if (!param_bound.IsInstantiated()) { | 1681 if (!param_bound.IsInstantiated()) { |
1672 has_uninstantiated_bounds = true; | 1682 has_uninstantiated_bounds = true; |
1673 } | 1683 } |
1674 cloned_param = TypeParameter::New(mixin_app_class, | 1684 cloned_param = TypeParameter::New(mixin_app_class, |
1675 cloned_index, | 1685 cloned_index, // Unfinalized index. |
1676 param_name, | 1686 param_name, |
1677 param_bound, | 1687 param_bound, |
1678 param.token_pos()); | 1688 param.token_pos()); |
1679 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1689 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
1680 mixin_type_args.SetTypeAt(i, cloned_param); | 1690 mixin_type_args.SetTypeAt(i, cloned_param); // Unfinalized length. |
| 1691 instantiator.SetTypeAt(offset + i, cloned_param); // Finalized length. |
1681 cloned_index++; | 1692 cloned_index++; |
1682 } | 1693 } |
1683 | 1694 |
1684 // Third, replace the type parameters appearing in the bounds of the mixin | 1695 // Third, replace the type parameters appearing in the bounds of the mixin |
1685 // type parameters, if any, by the cloned type parameters. This can be | 1696 // type parameters, if any, by the cloned type parameters. This can be |
1686 // done by instantiating each bound using the mixin_type_args as | 1697 // done by instantiating each bound using the instantiator built above. |
1687 // instantiator. Since the mixin class must extend Object, its first type | 1698 // If the mixin class extends a generic super class, its first finalized |
1688 // parameter has index 0, therefore, the instantiator does not require | 1699 // type parameter has a non-zero index, therefore, the instantiator |
1689 // shifting. There is however an exception where the mixin class is an | 1700 // requires shifting by the offset calculated above. |
1690 // alias, in which case shifting is required and performed later in | |
1691 // ApplyMixinAppAlias. | |
1692 // Unfinalized type parameters replace finalized type parameters, which | 1701 // Unfinalized type parameters replace finalized type parameters, which |
1693 // is not a problem since they will get finalized shortly as the mixin | 1702 // is not a problem since they will get finalized shortly as the mixin |
1694 // application class gets finalized. | 1703 // application class gets finalized. |
1695 if (has_uninstantiated_bounds && !mixin_class.is_mixin_app_alias()) { | 1704 if (has_uninstantiated_bounds) { |
1696 Error& bound_error = Error::Handle(isolate); | 1705 Error& bound_error = Error::Handle(isolate); |
1697 for (intptr_t i = 0; i < num_mixin_type_params; i++) { | 1706 for (intptr_t i = 0; i < num_mixin_type_params; i++) { |
1698 param ^= mixin_type_args.TypeAt(i); | 1707 param ^= mixin_type_args.TypeAt(i); |
1699 param_bound = param.bound(); | 1708 param_bound = param.bound(); |
1700 if (!param_bound.IsInstantiated()) { | 1709 if (!param_bound.IsInstantiated()) { |
1701 // Make sure the bound is finalized before instantiating it. | 1710 // Make sure the bound is finalized before instantiating it. |
1702 if (!param_bound.IsFinalized() && | 1711 if (!param_bound.IsFinalized() && |
1703 !param_bound.IsBeingFinalized()) { | 1712 !param_bound.IsBeingFinalized()) { |
1704 param_bound = | 1713 param_bound = |
1705 FinalizeType(mixin_app_class, param_bound, kCanonicalize); | 1714 FinalizeType(mixin_app_class, param_bound, kCanonicalize); |
1706 param.set_bound(param_bound); // In case part of recursive type. | 1715 param.set_bound(param_bound); // In case part of recursive type. |
1707 } | 1716 } |
1708 param_bound = param_bound.InstantiateFrom(mixin_type_args, | 1717 param_bound = param_bound.InstantiateFrom(instantiator, |
1709 &bound_error); | 1718 &bound_error); |
1710 // The instantiator contains only TypeParameter objects and no | 1719 // The instantiator contains only TypeParameter objects and no |
1711 // BoundedType objects, so no bound error may occur. | 1720 // BoundedType objects, so no bound error may occur. |
| 1721 ASSERT(!param_bound.IsBoundedType()); |
1712 ASSERT(bound_error.IsNull()); | 1722 ASSERT(bound_error.IsNull()); |
1713 ASSERT(!param_bound.IsInstantiated()); | 1723 ASSERT(!param_bound.IsInstantiated()); |
1714 param.set_bound(param_bound); | 1724 param.set_bound(param_bound); |
1715 } | 1725 } |
1716 } | 1726 } |
1717 } | 1727 } |
1718 | 1728 |
1719 // Lastly, set the type arguments of the mixin type, which is also the | 1729 // Lastly, set the type arguments of the mixin type, which is also the |
1720 // single interface type. | 1730 // single interface type. |
1721 ASSERT(!mixin_type.IsFinalized()); | 1731 ASSERT(!mixin_type.IsFinalized()); |
1722 mixin_type.set_arguments(mixin_type_args); | 1732 mixin_type.set_arguments(mixin_type_args); |
1723 if (share_type_params) { | 1733 if (share_type_params) { |
1724 Type::Cast(super_type).set_arguments(mixin_type_args); | 1734 Type::Cast(super_type).set_arguments(mixin_type_args); |
1725 ASSERT(!super_type.IsFinalized()); | 1735 ASSERT(!super_type.IsFinalized()); |
1726 } | 1736 } |
1727 } | 1737 } |
1728 mixin_app_class.set_type_parameters(cloned_type_params); | 1738 mixin_app_class.set_type_parameters(cloned_type_params); |
1729 } | 1739 } |
1730 // If the mixin class is a mixin application alias class, we insert a new | 1740 // If the mixin class is a mixin application alias class, we insert a new |
1731 // synthesized mixin application class in the super chain of this mixin | 1741 // synthesized mixin application class in the super chain of this mixin |
1732 // application class. The new class will have the aliased mixin as actual | 1742 // application class. The new class will have the aliased mixin as actual |
1733 // mixin. | 1743 // mixin. |
1734 if (mixin_class.is_mixin_app_alias()) { | 1744 if (mixin_class.is_mixin_app_alias()) { |
1735 ApplyMixinAppAlias(mixin_app_class, has_uninstantiated_bounds); | 1745 ApplyMixinAppAlias(mixin_app_class, instantiator); |
1736 } | 1746 } |
1737 } | 1747 } |
1738 | 1748 |
1739 | 1749 |
1740 /* Support for mixin alias. | 1750 /* Support for mixin alias. |
1741 Consider the following example: | 1751 Consider the following example: |
1742 | 1752 |
1743 class I<T> { } | 1753 class I<T> { } |
1744 class J<T> { } | 1754 class J<T> { } |
1745 class S<T> { } | 1755 class S<T extends num> { } |
1746 class M<T> { } | 1756 class M<T extends Map> { } |
1747 class A<U, V> = Object with M<Map<U, V>> implements I<V>; | 1757 class A<U, V extends List> = Object with M<Map<U, V>> implements I<V>; |
1748 class C<T, K> = S<T> with A<T, List<K>> implements J<K>; | 1758 class C<T, K extends T> = S<T> with A<T, List<K>> implements J<K>; |
1749 | 1759 |
1750 Before the call to ApplyMixinAppAlias, the VM has already synthesized 2 mixin | 1760 Before the call to ApplyMixinAppAlias, the VM has already synthesized 2 mixin |
1751 application classes Object&M and S&A: | 1761 application classes Object&M and S&A: |
1752 | 1762 |
1753 Object&M<T> extends Object implements M<T> { ... members of M applied here ... } | 1763 Object&M<T extends Map> extends Object implements M<T> { |
1754 A<U, V> extends Object&M<Map<U, V>> implements I<V> { } | 1764 ... members of M applied here ... |
| 1765 } |
| 1766 A<U, V extends List> extends Object&M<Map<U, V>> implements I<V> { } |
1755 | 1767 |
1756 S&A<T`, U, V> extends S<T`> implements A<U, V> { } | 1768 S&A<T`, U, V extends List> extends S<T`> implements A<U, V> { |
1757 C<T, K> extends S&A<T, T, List<K>> implements J<K> { } | 1769 ... members of A applied here, but A has no members ... |
| 1770 } |
| 1771 C<T, K extends T> extends S&A<T, T, List<K>> implements J<K> { } |
1758 | 1772 |
1759 In theory, class A should be an alias of Object&M instead of extending it. | 1773 In theory, class A should be an alias of Object&M instead of extending it. |
1760 In practice, the additional class provides a hook for implemented interfaces | 1774 In practice, the additional class provides a hook for implemented interfaces |
1761 (e.g. I<V>) and for type argument substitution via the super type relation (e.g. | 1775 (e.g. I<V>) and for type argument substitution via the super type relation (e.g. |
1762 type parameter T of Object&M is substituted with Map<U, V>, U and V being the | 1776 type parameter T of Object&M is substituted with Map<U, V>, U and V being the |
1763 type parameters of the alias A). | 1777 type parameters of the alias A). |
1764 | 1778 |
1765 Similarly, class C should be an alias of S&A instead of extending it. | 1779 Similarly, class C should be an alias of S&A instead of extending it. |
1766 | 1780 |
1767 Since A is used as a mixin, it must extend Object. The fact that it extends | |
1768 Object&M must be hidden so that no error is wrongly reported. | |
1769 | |
1770 Now, A does not have any members to be mixed into S&A, because A is an alias. | 1781 Now, A does not have any members to be mixed into S&A, because A is an alias. |
1771 The members to be mixed in are actually those of M, and they should appear in a | 1782 The members to be mixed in are actually those of M, and they should appear in a |
1772 scope where the type parameter T is visible. The class S&A declares the type | 1783 scope where the type parameter T is visible. The class S&A declares the type |
1773 parameters of A, i.e. U and V, but not T. | 1784 parameters of A, i.e. U and V, but not T. |
1774 | 1785 |
1775 Therefore, the call to ApplyMixinAppAlias inserts another synthesized class S&A` | 1786 Therefore, the call to ApplyMixinAppAlias inserts another synthesized class S&A` |
1776 as the superclass of S&A. The class S&A` declares a type argument T: | 1787 as the superclass of S&A. The class S&A` declares a type argument T: |
1777 | 1788 |
1778 Instead of | 1789 Instead of |
1779 S&A<T`, U, V> extends S<T`> implements A<U, V> { } | 1790 S&A<T`, U, V extends List> extends S<T`> implements A<U, V> { } |
1780 | 1791 |
1781 We now have: | 1792 We now have: |
1782 S&A`<T`, T> extends S<T`> implements M<T> { ... members of M applied here ... } | 1793 S&A`<T`, T extends Map> extends S<T`> implements M<T> { |
1783 S&A<T`, U, V> extends S&A`<T`, Map<U, V>> implements A<U, V> { } | 1794 ... members of M applied here ... |
| 1795 } |
| 1796 S&A<T`, U, V extends List> extends S&A`<T`, Map<U, V>> implements A<U, V> { } |
1784 | 1797 |
1785 The main implementation difficulty resides in the fact that the type parameters | 1798 The main implementation difficulty resides in the fact that the type parameters |
1786 U and V in the super type S&A`<T`, Map<U, V>> of S&A must refer to the type | 1799 U and V in the super type S&A`<T`, Map<U, V>> of S&A must refer to the type |
1787 parameters U and V of S&A. However, Map<U, V> is copied from the super type | 1800 parameters U and V of S&A. However, Map<U, V> is copied from the super type |
1788 Object&M<Map<U, V>> of A and, therefore, U and V refer to A. An instantiation | 1801 Object&M<Map<U, V>> of A and, therefore, U and V refer to A. An instantiation |
1789 step with a properly crafted instantiator vector takes care of the required type | 1802 step with a properly crafted instantiator vector takes care of the required type |
1790 parameter substitution. | 1803 parameter substitution. |
1791 The instantiator vector must end with the type parameters U and V of S&A. | 1804 The instantiator vector must end with the type parameters U and V of S&A. |
1792 The offset of the first type parameter U of S&A must be at the finalized index | 1805 The offset in the instantiator of the type parameter U of S&A must be at the |
1793 of type parameter U of A. | 1806 finalized index of type parameter U of A. |
1794 | 1807 |
1795 The same instantiator vector is used to adjust the type parameter bounds on U | 1808 The same instantiator vector is used to adjust the type parameter bounds on U |
1796 and V, if any. This step was postponed from CloneMixinAppTypeParameters above. | 1809 and V, if any. This step is done in CloneMixinAppTypeParameters above, and the |
| 1810 already built instantiator is passed here. |
1797 | 1811 |
1798 Also, a possible bound on type parameter T of M (not shown in the example above) | 1812 Also, a possible bound on type parameter T of M must be applied to type |
1799 must be applied to type parameter T of S&A`. If the bound is uninstantiated, | 1813 parameter T of S&A`. If the bound is uninstantiated, i.e. if it refers to T or |
1800 i.e. if it refers to T or other type parameters of M, an instantiation step is | 1814 other type parameters of M, an instantiation step is required to substitute |
1801 required to substitute these type parameters of M with type parameters of S&A`. | 1815 these type parameters of M with type parameters of S&A`. |
1802 The instantiator vector consists of the cloned type parameters of M without | 1816 The instantiator vector consists of the cloned type parameters of M shifted by |
1803 offset, since class M must extend Object. This is done in the recursive call to | 1817 an offset corresponding to the finalized index of the first type parameter of M. |
1804 CloneMixinAppTypeParameters and does not require specific code in | 1818 This is done in the recursive call to CloneMixinAppTypeParameters and does not |
1805 ApplyMixinAppAlias. | 1819 require specific code in ApplyMixinAppAlias. |
1806 */ | 1820 */ |
1807 void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class, | 1821 void ClassFinalizer::ApplyMixinAppAlias(const Class& mixin_app_class, |
1808 bool has_uninstantiated_bounds) { | 1822 const TypeArguments& instantiator) { |
1809 // If this mixin alias is aliasing another mixin alias, another class | 1823 // If this mixin alias is aliasing another mixin alias, another class |
1810 // will be inserted via recursion. No need to check here. | 1824 // will be inserted via recursion. No need to check here. |
1811 // The mixin type may or may not be finalized yet. | 1825 // The mixin type may or may not be finalized yet. |
1812 Isolate* isolate = Isolate::Current(); | 1826 Isolate* isolate = Isolate::Current(); |
1813 AbstractType& super_type = AbstractType::Handle(isolate, | 1827 AbstractType& super_type = AbstractType::Handle(isolate, |
1814 mixin_app_class.super_type()); | 1828 mixin_app_class.super_type()); |
1815 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); | 1829 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); |
1816 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); | 1830 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); |
1817 ASSERT(mixin_class.is_mixin_app_alias()); | 1831 ASSERT(mixin_class.is_mixin_app_alias()); |
1818 const Class& aliased_mixin_app_class = Class::Handle(isolate, | 1832 const Class& aliased_mixin_app_class = Class::Handle(isolate, |
1819 mixin_class.SuperClass()); | 1833 mixin_class.SuperClass()); |
| 1834 // Note that the super class of aliased_mixin_app_class can itself be a |
| 1835 // mixin application class (this happens if the alias is mixing more than one |
| 1836 // type). Instead of trying to recursively insert yet another class as the |
| 1837 // super class of this inserted class, we apply the composition rules of the |
| 1838 // spec and only mixin the members of aliased_mixin_app_class, not those of |
| 1839 // its super class. In other words, we only mixin the last mixin of the alias. |
1820 const Type& aliased_mixin_type = Type::Handle(isolate, | 1840 const Type& aliased_mixin_type = Type::Handle(isolate, |
1821 aliased_mixin_app_class.mixin()); | 1841 aliased_mixin_app_class.mixin()); |
1822 // The name of the inserted mixin application class is the name of mixin | 1842 // The name of the inserted mixin application class is the name of mixin |
1823 // class name with a backtick added. | 1843 // class name with a backtick added. |
1824 String& inserted_class_name = String::Handle(isolate, mixin_app_class.Name()); | 1844 String& inserted_class_name = String::Handle(isolate, mixin_app_class.Name()); |
1825 inserted_class_name = String::Concat(inserted_class_name, | 1845 inserted_class_name = String::Concat(inserted_class_name, |
1826 Symbols::Backtick()); | 1846 Symbols::Backtick()); |
1827 const Library& library = Library::Handle(isolate, mixin_app_class.library()); | 1847 const Library& library = Library::Handle(isolate, mixin_app_class.library()); |
1828 Class& inserted_class = Class::Handle(isolate, | 1848 Class& inserted_class = Class::Handle(isolate, |
1829 library.LookupLocalClass(inserted_class_name)); | 1849 library.LookupLocalClass(inserted_class_name)); |
(...skipping 14 matching lines...) Expand all Loading... |
1844 // this mixin application class, except that it must refer to the type | 1864 // this mixin application class, except that it must refer to the type |
1845 // parameters of the inserted class rather than to those of the mixin | 1865 // parameters of the inserted class rather than to those of the mixin |
1846 // application class. | 1866 // application class. |
1847 // The type arguments of the super type will be set properly when calling | 1867 // The type arguments of the super type will be set properly when calling |
1848 // CloneMixinAppTypeParameters on the inserted class, as long as the super | 1868 // CloneMixinAppTypeParameters on the inserted class, as long as the super |
1849 // type class is set properly. | 1869 // type class is set properly. |
1850 inserted_class.set_super_type(super_type); // Super class only is used. | 1870 inserted_class.set_super_type(super_type); // Super class only is used. |
1851 | 1871 |
1852 // The mixin type and interface type must also be set before calling | 1872 // The mixin type and interface type must also be set before calling |
1853 // CloneMixinAppTypeParameters. | 1873 // CloneMixinAppTypeParameters. |
1854 // After FinalizeTypesInClass, they will refer to the type parameters of | 1874 // After FinalizeTypesInClass, if the mixin type and interface type are |
1855 // the mixin class typedef. | 1875 // generic, their type arguments will refer to the type parameters of |
1856 const Type& generic_mixin_type = Type::Handle(isolate, | 1876 // inserted_class. |
| 1877 const Type& inserted_class_mixin_type = Type::Handle(isolate, |
1857 Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()), | 1878 Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()), |
1858 Object::null_type_arguments(), | 1879 Object::null_type_arguments(), |
1859 aliased_mixin_type.token_pos())); | 1880 aliased_mixin_type.token_pos())); |
1860 inserted_class.set_mixin(generic_mixin_type); | 1881 inserted_class.set_mixin(inserted_class_mixin_type); |
1861 // Add the mixin type to the list of interfaces that the mixin application | 1882 // Add the mixin type to the list of interfaces that the mixin application |
1862 // class implements. This is necessary so that cycle check work at | 1883 // class implements. This is necessary so that cycle check work at |
1863 // compile time (type arguments are ignored by that check). | 1884 // compile time (type arguments are ignored by that check). |
1864 const Array& interfaces = Array::Handle(Array::New(1)); | 1885 const Array& interfaces = Array::Handle(Array::New(1)); |
1865 interfaces.SetAt(0, generic_mixin_type); | 1886 interfaces.SetAt(0, inserted_class_mixin_type); |
1866 ASSERT(inserted_class.interfaces() == Object::empty_array().raw()); | 1887 ASSERT(inserted_class.interfaces() == Object::empty_array().raw()); |
1867 inserted_class.set_interfaces(interfaces); | 1888 inserted_class.set_interfaces(interfaces); |
1868 // The type arguments of the interface, if any, will be set in | 1889 // The type arguments of the interface, if any, will be set in |
1869 // CloneMixinAppTypeParameters, which is called indirectly from | 1890 // CloneMixinAppTypeParameters, which is called indirectly from |
1870 // FinalizeTypesInClass below. | 1891 // FinalizeTypesInClass below. |
1871 } | 1892 } |
1872 | 1893 |
1873 // Finalize the types and call CloneMixinAppTypeParameters. | 1894 // Finalize the types and call CloneMixinAppTypeParameters. |
1874 FinalizeTypesInClass(inserted_class); | 1895 FinalizeTypesInClass(inserted_class); |
1875 | 1896 |
1876 // The super type of this mixin application class must point to the | 1897 // The super type of this mixin application class must point to the |
1877 // inserted class. The super type arguments are the concatenation of the | 1898 // inserted class. The super type arguments are the concatenation of the |
1878 // old super type arguments (propagating type arguments to the super class) | 1899 // old super type arguments (propagating type arguments to the super class) |
1879 // with new type arguments providing type arguments to the mixin. | 1900 // with new type arguments providing type arguments to the mixin. |
1880 // The appended type arguments are those of the super type of the mixin | 1901 // The appended type arguments are those of the super type of the mixin |
1881 // application alias that are forwarding to the aliased mixin type, except | 1902 // application alias that are forwarding to the aliased mixin type, except |
1882 // that they must refer to the type parameters of the mixin application | 1903 // that they must refer to the type parameters of the mixin application |
1883 // class rather than to those of the mixin application alias class. | 1904 // class rather than to those of the mixin application alias class. |
1884 // This type parameter substitution is performed by an instantiation step. | 1905 // This type parameter substitution is performed by an instantiation step. |
1885 // It is important that the type parameters of the mixin application class | 1906 // It is important that the type parameters of the mixin application class |
1886 // are not finalized yet, because new type parameters may have been added | 1907 // are not finalized yet, because new type parameters may have been added |
1887 // to the super class. | 1908 // to the super class. |
1888 Class& super_class = Class::Handle(isolate, super_type.type_class()); | 1909 const Class& super_class = Class::Handle(isolate, super_type.type_class()); |
1889 ASSERT(mixin_app_class.SuperClass() == super_class.raw()); | 1910 ASSERT(mixin_app_class.SuperClass() == super_class.raw()); // Will change. |
1890 while (super_class.IsMixinApplication()) { | |
1891 super_class = super_class.SuperClass(); | |
1892 } | |
1893 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 1911 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
1894 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); | |
1895 intptr_t offset = | |
1896 mixin_class.NumTypeArguments() - mixin_class.NumTypeParameters(); | |
1897 const TypeArguments& type_params = | |
1898 TypeArguments::Handle(isolate, mixin_app_class.type_parameters()); | |
1899 TypeArguments& instantiator = TypeArguments::Handle(isolate, | |
1900 TypeArguments::New(offset + num_mixin_type_params)); | |
1901 AbstractType& type = AbstractType::Handle(isolate); | 1912 AbstractType& type = AbstractType::Handle(isolate); |
1902 for (intptr_t i = 0; i < num_mixin_type_params; i++) { | 1913 // The instantiator is mapping finalized type parameters of mixin_class to |
1903 type = type_params.TypeAt(num_super_type_params + i); | 1914 // unfinalized type parameters of mixin_app_class. |
1904 instantiator.SetTypeAt(offset + i, type); | |
1905 } | |
1906 ASSERT(aliased_mixin_type.IsFinalized()); | 1915 ASSERT(aliased_mixin_type.IsFinalized()); |
1907 const Class& aliased_mixin_type_class = Class::Handle(isolate, | 1916 const Class& aliased_mixin_type_class = Class::Handle(isolate, |
1908 aliased_mixin_type.type_class()); | 1917 aliased_mixin_type.type_class()); |
1909 const intptr_t num_aliased_mixin_type_params = | 1918 const intptr_t num_aliased_mixin_type_params = |
1910 aliased_mixin_type_class.NumTypeParameters(); | 1919 aliased_mixin_type_class.NumTypeParameters(); |
1911 const intptr_t num_aliased_mixin_type_args = | |
1912 aliased_mixin_type_class.NumTypeArguments(); | |
1913 offset = num_aliased_mixin_type_args - num_aliased_mixin_type_params; | |
1914 ASSERT(inserted_class.NumTypeParameters() == | 1920 ASSERT(inserted_class.NumTypeParameters() == |
1915 (num_super_type_params + num_aliased_mixin_type_params)); | 1921 (num_super_type_params + num_aliased_mixin_type_params)); |
| 1922 const AbstractType& mixin_class_super_type = |
| 1923 AbstractType::Handle(isolate, mixin_class.super_type()); |
| 1924 ASSERT(mixin_class_super_type.IsFinalized()); |
1916 // The aliased_mixin_type may be raw. | 1925 // The aliased_mixin_type may be raw. |
1917 const TypeArguments& mixin_class_super_type_args = | 1926 const TypeArguments& mixin_class_super_type_args = |
1918 TypeArguments::Handle(isolate, | 1927 TypeArguments::Handle(isolate, mixin_class_super_type.arguments()); |
1919 AbstractType::Handle(isolate, mixin_class.super_type()).arguments()); | |
1920 TypeArguments& new_mixin_type_args = TypeArguments::Handle(isolate); | 1928 TypeArguments& new_mixin_type_args = TypeArguments::Handle(isolate); |
1921 if ((num_aliased_mixin_type_params > 0) && | 1929 if ((num_aliased_mixin_type_params > 0) && |
1922 !mixin_class_super_type_args.IsNull()) { | 1930 !mixin_class_super_type_args.IsNull()) { |
1923 new_mixin_type_args = TypeArguments::New(num_aliased_mixin_type_params); | 1931 new_mixin_type_args = TypeArguments::New(num_aliased_mixin_type_params); |
| 1932 AbstractType& bounded_type = AbstractType::Handle(isolate); |
| 1933 AbstractType& upper_bound = AbstractType::Handle(isolate); |
| 1934 TypeParameter& type_parameter = TypeParameter::Handle(isolate); |
| 1935 Error& bound_error = Error::Handle(isolate); |
| 1936 const intptr_t offset = |
| 1937 mixin_class_super_type_args.Length() - num_aliased_mixin_type_params; |
1924 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { | 1938 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { |
1925 type = mixin_class_super_type_args.TypeAt(offset + i); | 1939 type = mixin_class_super_type_args.TypeAt(offset + i); |
| 1940 if (!type.IsInstantiated()) { |
| 1941 // In the presence of bounds, the bounded type and the upper bound must |
| 1942 // be instantiated separately. Instantiating a BoundedType would wrap |
| 1943 // the BoundedType in another BoundedType. |
| 1944 if (type.IsBoundedType()) { |
| 1945 bounded_type = BoundedType::Cast(type).type(); |
| 1946 bounded_type = bounded_type.InstantiateFrom(instantiator, |
| 1947 &bound_error); |
| 1948 // The instantiator contains only TypeParameter objects and no |
| 1949 // BoundedType objects, so no bound error may occur. |
| 1950 ASSERT(bound_error.IsNull()); |
| 1951 upper_bound = BoundedType::Cast(type).bound(); |
| 1952 upper_bound = upper_bound.InstantiateFrom(instantiator, &bound_error); |
| 1953 ASSERT(bound_error.IsNull()); |
| 1954 type_parameter = BoundedType::Cast(type).type_parameter(); |
| 1955 // The type parameter that declared the bound does not change. |
| 1956 type = BoundedType::New(bounded_type, upper_bound, type_parameter); |
| 1957 } else { |
| 1958 type = type.InstantiateFrom(instantiator, &bound_error); |
| 1959 ASSERT(bound_error.IsNull()); |
| 1960 } |
| 1961 } |
1926 new_mixin_type_args.SetTypeAt(i, type); | 1962 new_mixin_type_args.SetTypeAt(i, type); |
1927 } | 1963 } |
1928 } | 1964 } |
1929 if (!new_mixin_type_args.IsNull() && | |
1930 !new_mixin_type_args.IsInstantiated()) { | |
1931 Error& bound_error = Error::Handle(isolate); | |
1932 new_mixin_type_args ^= | |
1933 new_mixin_type_args.InstantiateFrom(instantiator, &bound_error); | |
1934 // The instantiator contains only TypeParameter objects and no BoundedType | |
1935 // objects, so no bound error may occur. | |
1936 ASSERT(bound_error.IsNull()); | |
1937 } | |
1938 TypeArguments& new_super_type_args = TypeArguments::Handle(isolate); | 1965 TypeArguments& new_super_type_args = TypeArguments::Handle(isolate); |
1939 if ((num_super_type_params + num_aliased_mixin_type_params) > 0) { | 1966 if ((num_super_type_params + num_aliased_mixin_type_params) > 0) { |
1940 new_super_type_args = TypeArguments::New(num_super_type_params + | 1967 new_super_type_args = TypeArguments::New(num_super_type_params + |
1941 num_aliased_mixin_type_params); | 1968 num_aliased_mixin_type_params); |
| 1969 const TypeArguments& type_params = |
| 1970 TypeArguments::Handle(isolate, mixin_app_class.type_parameters()); |
1942 for (intptr_t i = 0; i < num_super_type_params; i++) { | 1971 for (intptr_t i = 0; i < num_super_type_params; i++) { |
1943 type = type_params.TypeAt(i); | 1972 type = type_params.TypeAt(i); |
1944 new_super_type_args.SetTypeAt(i, type); | 1973 new_super_type_args.SetTypeAt(i, type); |
1945 } | 1974 } |
1946 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { | 1975 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { |
1947 if (new_mixin_type_args.IsNull()) { | 1976 if (new_mixin_type_args.IsNull()) { |
1948 type = Type::DynamicType(); | 1977 type = Type::DynamicType(); |
1949 } else { | 1978 } else { |
1950 type = new_mixin_type_args.TypeAt(i); | 1979 type = new_mixin_type_args.TypeAt(i); |
1951 } | 1980 } |
1952 new_super_type_args.SetTypeAt(num_super_type_params + i, type); | 1981 new_super_type_args.SetTypeAt(num_super_type_params + i, type); |
1953 } | 1982 } |
1954 } | 1983 } |
1955 super_type = Type::New(inserted_class, | 1984 super_type = Type::New(inserted_class, |
1956 new_super_type_args, | 1985 new_super_type_args, |
1957 mixin_app_class.token_pos()); | 1986 mixin_app_class.token_pos()); |
1958 mixin_app_class.set_super_type(super_type); | 1987 mixin_app_class.set_super_type(super_type); |
1959 | 1988 |
1960 // Perform the bound adjustment posponed from CloneMixinAppTypeParameters. | |
1961 if (has_uninstantiated_bounds) { | |
1962 TypeParameter& param = TypeParameter::Handle(isolate); | |
1963 AbstractType& param_bound = AbstractType::Handle(isolate); | |
1964 Error& bound_error = Error::Handle(isolate); | |
1965 for (intptr_t i = 0; i < num_mixin_type_params; i++) { | |
1966 param ^= type_params.TypeAt(num_super_type_params + i); | |
1967 param_bound = param.bound(); | |
1968 if (!param_bound.IsInstantiated()) { | |
1969 param_bound = param_bound.InstantiateFrom(instantiator, &bound_error); | |
1970 // The instantiator contains only TypeParameter objects and no | |
1971 // BoundedType objects, so no bound error may occur. | |
1972 ASSERT(bound_error.IsNull()); | |
1973 ASSERT(!param_bound.IsInstantiated()); | |
1974 param.set_bound(param_bound); | |
1975 } | |
1976 } | |
1977 } | |
1978 | |
1979 // Mark this mixin application class as being an alias. | 1989 // Mark this mixin application class as being an alias. |
1980 mixin_app_class.set_is_mixin_app_alias(); | 1990 mixin_app_class.set_is_mixin_app_alias(); |
1981 ASSERT(!mixin_app_class.is_type_finalized()); | 1991 ASSERT(!mixin_app_class.is_type_finalized()); |
1982 ASSERT(!mixin_app_class.is_mixin_type_applied()); | 1992 ASSERT(!mixin_app_class.is_mixin_type_applied()); |
1983 if (FLAG_trace_class_finalization) { | 1993 if (FLAG_trace_class_finalization) { |
1984 OS::Print("Inserting class %s to mixin application alias %s " | 1994 OS::Print("Inserting class '%s' %s\n" |
1985 "with super type '%s'\n", | 1995 " as super type '%s' with %" Pd " type args: %s\n" |
1986 inserted_class.ToCString(), | 1996 " of mixin application alias '%s' %s\n", |
1987 mixin_app_class.ToCString(), | 1997 String::Handle(inserted_class.Name()).ToCString(), |
1988 String::Handle(isolate, super_type.Name()).ToCString()); | 1998 TypeArguments::Handle( |
| 1999 inserted_class.type_parameters()).ToCString(), |
| 2000 String::Handle(isolate, super_type.Name()).ToCString(), |
| 2001 num_super_type_params + num_aliased_mixin_type_params, |
| 2002 super_type.ToCString(), |
| 2003 String::Handle(mixin_app_class.Name()).ToCString(), |
| 2004 TypeArguments::Handle( |
| 2005 mixin_app_class.type_parameters()).ToCString()); |
1989 } | 2006 } |
1990 } | 2007 } |
1991 | 2008 |
1992 | 2009 |
1993 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class, | 2010 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class, |
1994 GrowableObjectArray* pending_types) { | 2011 GrowableObjectArray* pending_types) { |
1995 if (mixin_app_class.is_mixin_type_applied()) { | 2012 if (mixin_app_class.is_mixin_type_applied()) { |
1996 return; | 2013 return; |
1997 } | 2014 } |
1998 Type& mixin_type = Type::Handle(mixin_app_class.mixin()); | 2015 Type& mixin_type = Type::Handle(mixin_app_class.mixin()); |
1999 ASSERT(!mixin_type.IsNull()); | 2016 ASSERT(!mixin_type.IsNull()); |
2000 ASSERT(mixin_type.HasResolvedTypeClass()); | 2017 ASSERT(mixin_type.HasResolvedTypeClass()); |
2001 const Class& mixin_class = Class::Handle(mixin_type.type_class()); | 2018 const Class& mixin_class = Class::Handle(mixin_type.type_class()); |
2002 | 2019 |
2003 if (FLAG_trace_class_finalization) { | 2020 if (FLAG_trace_class_finalization) { |
2004 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n", | 2021 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n", |
2005 String::Handle(mixin_type.Name()).ToCString(), | 2022 String::Handle(mixin_type.Name()).ToCString(), |
2006 mixin_app_class.ToCString(), | 2023 mixin_app_class.ToCString(), |
2007 mixin_app_class.token_pos()); | 2024 mixin_app_class.token_pos()); |
2008 } | 2025 } |
2009 | 2026 |
2010 // Check for illegal self references. This has to be done before checking | 2027 // Check for illegal self references. |
2011 // that the super class of the mixin class is class Object. | |
2012 GrowableArray<intptr_t> visited_mixins; | 2028 GrowableArray<intptr_t> visited_mixins; |
2013 if (!IsMixinCycleFree(mixin_class, &visited_mixins)) { | 2029 if (!IsMixinCycleFree(mixin_class, &visited_mixins)) { |
2014 const String& class_name = String::Handle(mixin_class.Name()); | 2030 const String& class_name = String::Handle(mixin_class.Name()); |
2015 ReportError(mixin_class, mixin_class.token_pos(), | 2031 ReportError(mixin_class, mixin_class.token_pos(), |
2016 "mixin class '%s' illegally refers to itself", | 2032 "mixin class '%s' illegally refers to itself", |
2017 class_name.ToCString()); | 2033 class_name.ToCString()); |
2018 } | 2034 } |
2019 | 2035 |
2020 // Check that the super class of the mixin class is class Object. | 2036 if (!FLAG_supermixin) { |
2021 Class& mixin_super_class = Class::Handle(mixin_class.SuperClass()); | 2037 // Check that the super class of the mixin class is class Object. |
2022 // Skip over mixin application alias classes, which are implemented as | 2038 Class& mixin_super_class = Class::Handle(mixin_class.SuperClass()); |
2023 // subclasses of the mixin application classes they name. | 2039 // Skip over mixin application alias classes, which are implemented as |
2024 if (!mixin_super_class.IsNull() && mixin_class.is_mixin_app_alias()) { | 2040 // subclasses of the mixin application classes they name. |
2025 while (mixin_super_class.is_mixin_app_alias()) { | 2041 if (!mixin_super_class.IsNull() && mixin_class.is_mixin_app_alias()) { |
| 2042 while (mixin_super_class.is_mixin_app_alias()) { |
| 2043 mixin_super_class = mixin_super_class.SuperClass(); |
| 2044 } |
2026 mixin_super_class = mixin_super_class.SuperClass(); | 2045 mixin_super_class = mixin_super_class.SuperClass(); |
2027 } | 2046 } |
2028 mixin_super_class = mixin_super_class.SuperClass(); | 2047 if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) { |
2029 } | 2048 const String& class_name = String::Handle(mixin_class.Name()); |
2030 if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) { | 2049 ReportError(mixin_app_class, mixin_app_class.token_pos(), |
2031 const String& class_name = String::Handle(mixin_class.Name()); | 2050 "mixin class '%s' must extend class 'Object'", |
2032 ReportError(mixin_app_class, mixin_app_class.token_pos(), | 2051 class_name.ToCString()); |
2033 "mixin class '%s' must extend class 'Object'", | 2052 } |
2034 class_name.ToCString()); | |
2035 } | 2053 } |
2036 | 2054 |
2037 // Copy type parameters to mixin application class. | 2055 // Copy type parameters to mixin application class. |
2038 CloneMixinAppTypeParameters(mixin_app_class); | 2056 CloneMixinAppTypeParameters(mixin_app_class); |
2039 | 2057 |
2040 // Verify that no restricted class is used as a mixin by checking the | 2058 // Verify that no restricted class is used as a mixin by checking the |
2041 // interfaces of the mixin application class, which implements its mixin. | 2059 // interfaces of the mixin application class, which implements its mixin. |
2042 GrowableArray<intptr_t> visited_interfaces; | 2060 GrowableArray<intptr_t> visited_interfaces; |
2043 ResolveSuperTypeAndInterfaces(mixin_app_class, &visited_interfaces); | 2061 ResolveSuperTypeAndInterfaces(mixin_app_class, &visited_interfaces); |
2044 | 2062 |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 AbstractType& interface_type = AbstractType::Handle(); | 2308 AbstractType& interface_type = AbstractType::Handle(); |
2291 AbstractType& seen_interf = AbstractType::Handle(); | 2309 AbstractType& seen_interf = AbstractType::Handle(); |
2292 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 2310 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
2293 interface_type ^= interface_types.At(i); | 2311 interface_type ^= interface_types.At(i); |
2294 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 2312 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
2295 interface_types.SetAt(i, interface_type); | 2313 interface_types.SetAt(i, interface_type); |
2296 | 2314 |
2297 // Check whether the interface is duplicated. We need to wait with | 2315 // Check whether the interface is duplicated. We need to wait with |
2298 // this check until the super type and interface types are finalized, | 2316 // this check until the super type and interface types are finalized, |
2299 // so that we can use Type::Equals() for the test. | 2317 // so that we can use Type::Equals() for the test. |
| 2318 // TODO(regis): This restriction about duplicated interfaces may get lifted. |
2300 ASSERT(interface_type.IsFinalized()); | 2319 ASSERT(interface_type.IsFinalized()); |
2301 ASSERT(super_type.IsNull() || super_type.IsFinalized()); | 2320 ASSERT(super_type.IsNull() || super_type.IsFinalized()); |
2302 if (!super_type.IsNull() && interface_type.Equals(super_type)) { | 2321 if (!super_type.IsNull() && interface_type.Equals(super_type)) { |
2303 ReportError(cls, cls.token_pos(), | 2322 ReportError(cls, cls.token_pos(), |
2304 "super type '%s' may not be listed in " | 2323 "super type '%s' may not be listed in " |
2305 "implements clause of class '%s'", | 2324 "implements clause of class '%s'", |
2306 String::Handle(super_type.Name()).ToCString(), | 2325 String::Handle(super_type.Name()).ToCString(), |
2307 String::Handle(cls.Name()).ToCString()); | 2326 String::Handle(cls.Name()).ToCString()); |
2308 } | 2327 } |
2309 for (intptr_t j = 0; j < i; j++) { | 2328 for (intptr_t j = 0; j < i; j++) { |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2636 const GrowableObjectArray& type_args = | 2655 const GrowableObjectArray& type_args = |
2637 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); | 2656 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
2638 AbstractType& mixin_super_type = | 2657 AbstractType& mixin_super_type = |
2639 AbstractType::Handle(isolate, mixin_app_type.super_type()); | 2658 AbstractType::Handle(isolate, mixin_app_type.super_type()); |
2640 ResolveType(cls, mixin_super_type); | 2659 ResolveType(cls, mixin_super_type); |
2641 ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed. | 2660 ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed. |
2642 // The super type may have a BoundedType as type argument, but cannot be | 2661 // The super type may have a BoundedType as type argument, but cannot be |
2643 // a BoundedType itself. | 2662 // a BoundedType itself. |
2644 CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args); | 2663 CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args); |
2645 AbstractType& mixin_type = AbstractType::Handle(isolate); | 2664 AbstractType& mixin_type = AbstractType::Handle(isolate); |
2646 Type& generic_mixin_type = Type::Handle(isolate); | |
2647 Class& mixin_type_class = Class::Handle(isolate); | 2665 Class& mixin_type_class = Class::Handle(isolate); |
2648 Class& mixin_app_class = Class::Handle(isolate); | 2666 Class& mixin_app_class = Class::Handle(isolate); |
2649 String& mixin_app_class_name = String::Handle(isolate); | 2667 String& mixin_app_class_name = String::Handle(isolate); |
2650 String& mixin_type_class_name = String::Handle(isolate); | 2668 String& mixin_type_class_name = String::Handle(isolate); |
2651 AbstractType& super_type_arg = AbstractType::Handle(isolate); | 2669 AbstractType& super_type_arg = AbstractType::Handle(isolate); |
2652 AbstractType& mixin_type_arg = AbstractType::Handle(isolate); | 2670 AbstractType& mixin_type_arg = AbstractType::Handle(isolate); |
2653 const intptr_t depth = mixin_app_type.Depth(); | 2671 const intptr_t depth = mixin_app_type.Depth(); |
2654 for (intptr_t i = 0; i < depth; i++) { | 2672 for (intptr_t i = 0; i < depth; i++) { |
2655 mixin_type = mixin_app_type.MixinTypeAt(i); | 2673 mixin_type = mixin_app_type.MixinTypeAt(i); |
2656 ASSERT(!mixin_type.IsNull()); | 2674 ASSERT(!mixin_type.IsNull()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2697 mixin_app_class_name = String::Concat(mixin_app_class_name, | 2715 mixin_app_class_name = String::Concat(mixin_app_class_name, |
2698 mixin_type_class_name); | 2716 mixin_type_class_name); |
2699 mixin_app_class = library.LookupLocalClass(mixin_app_class_name); | 2717 mixin_app_class = library.LookupLocalClass(mixin_app_class_name); |
2700 if (mixin_app_class.IsNull()) { | 2718 if (mixin_app_class.IsNull()) { |
2701 mixin_app_class_name = Symbols::New(mixin_app_class_name); | 2719 mixin_app_class_name = Symbols::New(mixin_app_class_name); |
2702 mixin_app_class = Class::New(mixin_app_class_name, | 2720 mixin_app_class = Class::New(mixin_app_class_name, |
2703 script, | 2721 script, |
2704 mixin_type.token_pos()); | 2722 mixin_type.token_pos()); |
2705 mixin_app_class.set_super_type(mixin_super_type); | 2723 mixin_app_class.set_super_type(mixin_super_type); |
2706 mixin_type_class = mixin_type.type_class(); | 2724 mixin_type_class = mixin_type.type_class(); |
2707 generic_mixin_type = Type::New(mixin_type_class, | 2725 const Type& generic_mixin_type = Type::Handle(isolate, |
2708 Object::null_type_arguments(), | 2726 Type::New(mixin_type_class, |
2709 mixin_type.token_pos()); | 2727 Object::null_type_arguments(), |
| 2728 mixin_type.token_pos())); |
2710 mixin_app_class.set_mixin(generic_mixin_type); | 2729 mixin_app_class.set_mixin(generic_mixin_type); |
2711 // Add the mixin type to the list of interfaces that the mixin application | 2730 // Add the mixin type to the list of interfaces that the mixin application |
2712 // class implements. This is necessary so that cycle check work at | 2731 // class implements. This is necessary so that cycle check work at |
2713 // compile time (type arguments are ignored by that check). | 2732 // compile time (type arguments are ignored by that check). |
2714 const Array& interfaces = Array::Handle(isolate, Array::New(1)); | 2733 const Array& interfaces = Array::Handle(isolate, Array::New(1)); |
2715 interfaces.SetAt(0, generic_mixin_type); | 2734 interfaces.SetAt(0, generic_mixin_type); |
2716 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); | 2735 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); |
2717 mixin_app_class.set_interfaces(interfaces); | 2736 mixin_app_class.set_interfaces(interfaces); |
2718 mixin_app_class.set_is_synthesized_class(); | 2737 mixin_app_class.set_is_synthesized_class(); |
2719 library.AddClass(mixin_app_class); | 2738 library.AddClass(mixin_app_class); |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3200 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); | 3219 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); |
3201 field ^= fields_array.At(0); | 3220 field ^= fields_array.At(0); |
3202 ASSERT(field.Offset() == ByteBuffer::data_offset()); | 3221 ASSERT(field.Offset() == ByteBuffer::data_offset()); |
3203 name ^= field.name(); | 3222 name ^= field.name(); |
3204 expected_name ^= String::New("_data"); | 3223 expected_name ^= String::New("_data"); |
3205 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3224 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
3206 #endif | 3225 #endif |
3207 } | 3226 } |
3208 | 3227 |
3209 } // namespace dart | 3228 } // namespace dart |
OLD | NEW |