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