Chromium Code Reviews| 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" |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 for (intptr_t i = 0; i < num_types; i++) { | 505 for (intptr_t i = 0; i < num_types; i++) { |
| 506 type_parameter ^= type_parameters.TypeAt(i); | 506 type_parameter ^= type_parameters.TypeAt(i); |
| 507 type_parameter ^= FinalizeType( | 507 type_parameter ^= FinalizeType( |
| 508 cls, type_parameter, kFinalize, pending_types); | 508 cls, type_parameter, kFinalize, pending_types); |
| 509 type_parameters.SetTypeAt(i, type_parameter); | 509 type_parameters.SetTypeAt(i, type_parameter); |
| 510 } | 510 } |
| 511 } | 511 } |
| 512 } | 512 } |
| 513 | 513 |
| 514 | 514 |
| 515 // This function reports a compilation error if the recursive 'type' being | |
| 516 // finalized is a non-contractive type. This can be detected by looking at the | |
|
srdjan
2014/03/26 18:02:12
non-contractive types is not a commonly known term
regis
2014/03/26 18:41:29
I expanded the comment and added a reference to th
| |
| 517 // queue of types pending finalization that may be mutually recursive with the | |
| 518 // checked type. | |
| 519 void ClassFinalizer::CheckRecursiveType(const Class& cls, | |
| 520 const Type& type, | |
| 521 GrowableObjectArray* pending_types) { | |
| 522 Isolate* isolate = Isolate::Current(); | |
| 523 if (FLAG_trace_type_finalization) { | |
| 524 OS::Print("Checking recursive type '%s' for class '%s'\n", | |
| 525 String::Handle(type.Name()).ToCString(), | |
| 526 cls.ToCString()); | |
| 527 } | |
| 528 const Class& type_cls = Class::Handle(isolate, type.type_class()); | |
| 529 const TypeArguments& arguments = | |
| 530 TypeArguments::Handle(isolate, type.arguments()); | |
| 531 // A type can only be recursive via its type arguments. | |
| 532 ASSERT(!arguments.IsNull()); | |
| 533 const intptr_t num_type_args = arguments.Length(); | |
| 534 ASSERT(num_type_args > 0); | |
| 535 ASSERT(num_type_args == type_cls.NumTypeArguments()); | |
| 536 const intptr_t num_type_params = type_cls.NumTypeParameters(); | |
| 537 const intptr_t first_type_param = num_type_args - num_type_params; | |
| 538 // If the type parameters are instantiated (or null), no divergence can occur. | |
| 539 if ((num_type_params == 0) || | |
| 540 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) { | |
| 541 return; | |
| 542 } | |
| 543 // The type parameters are not instantiated. Verify that there is no other | |
| 544 // type pending finalization with the same type class, but different | |
| 545 // uninstantiated type parameters. | |
| 546 Type& pending_type = Type::Handle(isolate); | |
| 547 TypeArguments& pending_arguments = TypeArguments::Handle(isolate); | |
| 548 const intptr_t num_pending_types = pending_types->Length(); | |
| 549 for (intptr_t i = num_pending_types - 1; i >= 0; i--) { | |
| 550 pending_type ^= pending_types->At(i); | |
| 551 if (FLAG_trace_type_finalization) { | |
| 552 OS::Print(" Comparing with pending type '%s'\n", | |
| 553 String::Handle(pending_type.Name()).ToCString()); | |
| 554 } | |
| 555 if ((pending_type.raw() != type.raw()) && | |
| 556 (pending_type.type_class() == type_cls.raw())) { | |
| 557 pending_arguments = pending_type.arguments(); | |
| 558 if (!pending_arguments.IsSubvectorEquivalent(arguments, | |
| 559 first_type_param, | |
| 560 num_type_params) && | |
| 561 !pending_arguments.IsSubvectorInstantiated(first_type_param, | |
| 562 num_type_params)) { | |
| 563 // Reject the non-contractive recursive type. | |
| 564 const Script& script = Script::Handle(isolate, cls.script()); | |
| 565 const String& type_name = String::Handle(isolate, type.Name()); | |
| 566 ReportError(Error::Handle(isolate), // No previous error. | |
| 567 script, type.token_pos(), | |
| 568 "illegal recursive type '%s'", | |
| 569 type_name.ToCString()); | |
| 570 } | |
| 571 } | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 | |
| 515 // Finalize the type argument vector 'arguments' of the type defined by the | 576 // Finalize the type argument vector 'arguments' of the type defined by the |
| 516 // class 'cls' parameterized with the type arguments 'cls_args'. | 577 // class 'cls' parameterized with the type arguments 'cls_args'. |
| 517 // The vector 'cls_args' is already initialized as a subvector at the correct | 578 // The vector 'cls_args' is already initialized as a subvector at the correct |
| 518 // position in the passed in 'arguments' vector. | 579 // position in the passed in 'arguments' vector. |
| 519 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at | 580 // The subvector 'cls_args' has length cls.NumTypeParameters() and starts at |
| 520 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments' | 581 // offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments' |
| 521 // vector. | 582 // vector. |
| 522 // The type argument vector of cls may overlap the type argument vector of its | 583 // The type argument vector of cls may overlap the type argument vector of its |
| 523 // super class. In case of an overlap, the overlapped type arguments of the | 584 // super class. In case of an overlap, the overlapped type arguments of the |
| 524 // super class are already initialized. The still uninitialized ones have an | 585 // super class are already initialized. The still uninitialized ones have an |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 535 // Declared: class C<K, V> extends B<K> { ... } | 596 // Declared: class C<K, V> extends B<K> { ... } |
| 536 // class B<T> extends A<int> { ... } | 597 // class B<T> extends A<int> { ... } |
| 537 // Input: C<String, double> expressed as | 598 // Input: C<String, double> expressed as |
| 538 // cls = C, arguments = [dynamic, String, double], | 599 // cls = C, arguments = [dynamic, String, double], |
| 539 // num_uninitialized_arguments = 1, | 600 // num_uninitialized_arguments = 1, |
| 540 // i.e. cls_args = [String, double], offset = 1, length = 2. | 601 // i.e. cls_args = [String, double], offset = 1, length = 2. |
| 541 // Output: arguments = [int, String, double] | 602 // Output: arguments = [int, String, double] |
| 542 // | 603 // |
| 543 // It is too early to canonicalize the type arguments of the vector, because | 604 // It is too early to canonicalize the type arguments of the vector, because |
| 544 // several type argument vectors may be mutually recursive and finalized at the | 605 // several type argument vectors may be mutually recursive and finalized at the |
| 545 // same time. Canonicalization happens when pending types are processed. | 606 // same time. Canonicalization happens when pending types are processed. |
|
srdjan
2014/03/26 18:02:12
Maybe document 'trail' in comment.
regis
2014/03/26 18:41:29
Added comment about trail.
| |
| 546 void ClassFinalizer::FinalizeTypeArguments( | 607 void ClassFinalizer::FinalizeTypeArguments( |
| 547 const Class& cls, | 608 const Class& cls, |
| 548 const TypeArguments& arguments, | 609 const TypeArguments& arguments, |
| 549 intptr_t num_uninitialized_arguments, | 610 intptr_t num_uninitialized_arguments, |
| 550 Error* bound_error, | 611 Error* bound_error, |
| 551 GrowableObjectArray* pending_types) { | 612 GrowableObjectArray* pending_types, |
| 613 GrowableObjectArray* trail) { | |
| 552 ASSERT(arguments.Length() >= cls.NumTypeArguments()); | 614 ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
| 553 if (!cls.is_type_finalized()) { | 615 if (!cls.is_type_finalized()) { |
| 554 FinalizeTypeParameters(cls, pending_types); | 616 FinalizeTypeParameters(cls, pending_types); |
| 555 ResolveUpperBounds(cls); | 617 ResolveUpperBounds(cls); |
| 556 } | 618 } |
| 557 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 619 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 558 if (!super_type.IsNull()) { | 620 if (!super_type.IsNull()) { |
| 559 const Class& super_class = Class::Handle(super_type.type_class()); | 621 const Class& super_class = Class::Handle(super_type.type_class()); |
| 560 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 622 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
| 561 const intptr_t num_super_type_args = super_class.NumTypeArguments(); | 623 const intptr_t num_super_type_args = super_class.NumTypeArguments(); |
| 562 ASSERT(num_super_type_args == | 624 ASSERT(num_super_type_args == |
| 563 (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); | 625 (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); |
| 564 if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) { | 626 if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) { |
| 565 super_type ^= FinalizeType( | 627 super_type ^= FinalizeType( |
| 566 cls, super_type, kFinalize, pending_types); | 628 cls, super_type, kFinalize, pending_types); |
| 567 cls.set_super_type(super_type); | 629 cls.set_super_type(super_type); |
| 568 } | 630 } |
| 569 TypeArguments& super_type_args = TypeArguments::Handle( | 631 TypeArguments& super_type_args = TypeArguments::Handle( |
| 570 super_type.arguments()); | 632 super_type.arguments()); |
| 571 // Offset of super type's type parameters in cls' type argument vector. | 633 // Offset of super type's type parameters in cls' type argument vector. |
| 572 const intptr_t super_offset = num_super_type_args - num_super_type_params; | 634 const intptr_t super_offset = num_super_type_args - num_super_type_params; |
| 573 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); | 635 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); |
| 574 for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) { | 636 for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) { |
| 575 if (!super_type_args.IsNull()) { | 637 if (!super_type_args.IsNull()) { |
| 576 super_type_arg = super_type_args.TypeAt(i); | 638 super_type_arg = super_type_args.TypeAt(i); |
| 577 if (!super_type_arg.IsFinalized()) { | 639 if (!super_type_arg.IsTypeRef()) { |
| 578 super_type_arg ^= FinalizeType( | 640 if (super_type_arg.IsBeingFinalized()) { |
| 579 cls, super_type_arg, kFinalize, pending_types); | 641 ASSERT(super_type_arg.IsType()); |
| 580 super_type_args.SetTypeAt(i, super_type_arg); | 642 CheckRecursiveType(cls, Type::Cast(super_type_arg), pending_types); |
| 643 if (FLAG_trace_type_finalization) { | |
| 644 OS::Print("Creating TypeRef '%s' for class '%s'\n", | |
| 645 String::Handle(super_type_arg.Name()).ToCString(), | |
| 646 cls.ToCString()); | |
| 647 } | |
| 648 super_type_arg = TypeRef::New(super_type_arg); | |
| 649 super_type_args.SetTypeAt(i, super_type_arg); | |
| 650 } else { | |
| 651 if (!super_type_arg.IsFinalized()) { | |
| 652 super_type_arg ^= FinalizeType( | |
| 653 cls, super_type_arg, kFinalize, pending_types); | |
| 654 super_type_args.SetTypeAt(i, super_type_arg); | |
| 655 // Note that super_type_arg may still not be finalized here, in | |
| 656 // which case it is a TypeRef to a legal recursive type. | |
| 657 // Therefore, it does not need to be instantiated below. | |
| 658 // See tests/language/regress_16640_test.dart for an example. | |
| 659 } | |
| 660 } | |
| 581 } | 661 } |
| 582 if (!super_type_arg.IsBeingFinalized() && | 662 if (!super_type_arg.IsBeingFinalized() && |
| 583 !super_type_arg.IsInstantiated()) { | 663 !super_type_arg.IsInstantiated()) { |
| 584 Error& error = Error::Handle(); | 664 Error& error = Error::Handle(); |
| 585 super_type_arg = super_type_arg.InstantiateFrom(arguments, &error); | 665 super_type_arg = |
| 666 super_type_arg.InstantiateFrom(arguments, &error, trail); | |
| 586 if (!error.IsNull()) { | 667 if (!error.IsNull()) { |
| 587 // InstantiateFrom does not report an error if the type is still | 668 // InstantiateFrom does not report an error if the type is still |
| 588 // uninstantiated. Instead, it will return a new BoundedType so that | 669 // uninstantiated. Instead, it will return a new BoundedType so |
| 589 // the check is postponed to run time. | 670 // that the check is postponed to run time. |
| 590 ASSERT(super_type_arg.IsInstantiated()); | 671 ASSERT(super_type_arg.IsInstantiated()); |
| 591 // Keep only the first bound error. | 672 // Keep only the first bound error. |
| 592 if (bound_error->IsNull()) { | 673 if (bound_error->IsNull()) { |
| 593 *bound_error = error.raw(); | 674 *bound_error = error.raw(); |
| 594 } | 675 } |
| 595 } | 676 } |
| 596 } | 677 } |
| 597 } | 678 } |
| 598 arguments.SetTypeAt(i, super_type_arg); | 679 arguments.SetTypeAt(i, super_type_arg); |
| 599 } | 680 } |
| 600 FinalizeTypeArguments(super_class, arguments, super_offset, | 681 FinalizeTypeArguments(super_class, arguments, super_offset, |
| 601 bound_error, pending_types); | 682 bound_error, pending_types, trail); |
| 602 } | 683 } |
| 603 } | 684 } |
| 604 | 685 |
| 605 | 686 |
| 606 // Check the type argument vector 'arguments' against the corresponding bounds | 687 // Check the type argument vector 'arguments' against the corresponding bounds |
| 607 // of the type parameters of class 'cls' and, recursively, of its superclasses. | 688 // of the type parameters of class 'cls' and, recursively, of its superclasses. |
| 608 // Replace a type argument that cannot be checked at compile time by a | 689 // Replace a type argument that cannot be checked at compile time by a |
| 609 // BoundedType, thereby postponing the bound check to run time. | 690 // BoundedType, thereby postponing the bound check to run time. |
| 610 // Return a bound error if a type argument is not within bound at compile time. | 691 // Return a bound error if a type argument is not within bound at compile time. |
| 611 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, | 692 void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 756 return type.raw(); | 837 return type.raw(); |
| 757 } | 838 } |
| 758 ASSERT(finalization >= kFinalize); | 839 ASSERT(finalization >= kFinalize); |
| 759 | 840 |
| 760 if (type.IsTypeRef()) { | 841 if (type.IsTypeRef()) { |
| 761 // The referenced type will be finalized later by the code that set the | 842 // The referenced type will be finalized later by the code that set the |
| 762 // is_being_finalized mark bit. | 843 // is_being_finalized mark bit. |
| 763 return type.raw(); | 844 return type.raw(); |
| 764 } | 845 } |
| 765 | 846 |
| 766 if (type.IsBeingFinalized()) { | 847 // Recursive types must be processed in FinalizeTypeArguments() and cannot be |
| 767 if (FLAG_trace_type_finalization) { | 848 // encountered here. |
| 768 OS::Print("Creating TypeRef '%s' for class '%s'\n", | 849 ASSERT(!type.IsBeingFinalized()); |
| 769 String::Handle(type.Name()).ToCString(), | 850 |
| 770 cls.ToCString()); | 851 // A malformed type gets mapped to a finalized type. |
| 771 } | 852 ResolveType(cls, type); |
| 772 return TypeRef::New(type); | 853 if (type.IsMalformed()) { |
| 854 ASSERT(type.IsFinalized()); | |
| 855 return type.raw(); | |
| 773 } | 856 } |
| 774 | 857 |
| 775 ResolveType(cls, type); | 858 Isolate* isolate = Isolate::Current(); |
| 776 if (FLAG_trace_type_finalization) { | 859 if (FLAG_trace_type_finalization) { |
| 777 OS::Print("Finalizing type '%s' for class '%s'\n", | 860 OS::Print("Finalizing type '%s' for class '%s'\n", |
| 778 String::Handle(type.Name()).ToCString(), | 861 String::Handle(isolate, type.Name()).ToCString(), |
| 779 cls.ToCString()); | 862 cls.ToCString()); |
| 780 } | 863 } |
| 781 | 864 |
| 782 if (type.IsTypeParameter()) { | 865 if (type.IsTypeParameter()) { |
| 783 const TypeParameter& type_parameter = TypeParameter::Cast(type); | 866 const TypeParameter& type_parameter = TypeParameter::Cast(type); |
| 784 const Class& parameterized_class = | 867 const Class& parameterized_class = |
| 785 Class::Handle(type_parameter.parameterized_class()); | 868 Class::Handle(isolate, type_parameter.parameterized_class()); |
| 786 ASSERT(!parameterized_class.IsNull()); | 869 ASSERT(!parameterized_class.IsNull()); |
| 787 // The index must reflect the position of this type parameter in the type | 870 // The index must reflect the position of this type parameter in the type |
| 788 // arguments vector of its parameterized class. The offset to add is the | 871 // arguments vector of its parameterized class. The offset to add is the |
| 789 // number of type arguments in the super type, which is equal to the | 872 // number of type arguments in the super type, which is equal to the |
| 790 // difference in number of type arguments and type parameters of the | 873 // difference in number of type arguments and type parameters of the |
| 791 // parameterized class. | 874 // parameterized class. |
| 792 const intptr_t offset = parameterized_class.NumTypeArguments() - | 875 const intptr_t offset = parameterized_class.NumTypeArguments() - |
| 793 parameterized_class.NumTypeParameters(); | 876 parameterized_class.NumTypeParameters(); |
| 794 // Calling NumTypeParameters() may finalize this type parameter if it | 877 // Calling NumTypeParameters() may finalize this type parameter if it |
| 795 // belongs to a mixin application class. | 878 // belongs to a mixin application class. |
| 796 if (!type_parameter.IsFinalized()) { | 879 if (!type_parameter.IsFinalized()) { |
| 797 type_parameter.set_index(type_parameter.index() + offset); | 880 type_parameter.set_index(type_parameter.index() + offset); |
| 798 type_parameter.set_is_finalized(); | 881 type_parameter.set_is_finalized(); |
| 799 } else { | 882 } else { |
| 800 ASSERT(cls.IsMixinApplication()); | 883 ASSERT(cls.IsMixinApplication()); |
| 801 } | 884 } |
| 802 | 885 |
| 803 if (FLAG_trace_type_finalization) { | 886 if (FLAG_trace_type_finalization) { |
| 804 OS::Print("Done finalizing type parameter '%s' with index %" Pd "\n", | 887 OS::Print("Done finalizing type parameter '%s' with index %" Pd "\n", |
| 805 String::Handle(type_parameter.name()).ToCString(), | 888 String::Handle(isolate, type_parameter.name()).ToCString(), |
| 806 type_parameter.index()); | 889 type_parameter.index()); |
| 807 } | 890 } |
| 808 | 891 |
| 809 // We do not canonicalize type parameters. | 892 // We do not canonicalize type parameters. |
| 810 return type_parameter.raw(); | 893 return type_parameter.raw(); |
| 811 } | 894 } |
| 812 | 895 |
| 813 // At this point, we can only have a parameterized_type. | 896 // At this point, we can only have a parameterized_type. |
| 814 const Type& parameterized_type = Type::Cast(type); | 897 const Type& parameterized_type = Type::Cast(type); |
| 815 | 898 |
| 816 Isolate* isolate = Isolate::Current(); | |
| 817 // This type is the root type of the type graph if no pending types queue is | 899 // This type is the root type of the type graph if no pending types queue is |
| 818 // allocated yet. | 900 // allocated yet. |
| 819 const bool is_root_type = (pending_types == NULL); | 901 const bool is_root_type = (pending_types == NULL); |
| 820 GrowableObjectArray& types = GrowableObjectArray::Handle(isolate); | 902 GrowableObjectArray& types = GrowableObjectArray::Handle(isolate); |
| 821 if (is_root_type) { | 903 if (is_root_type) { |
| 822 types = GrowableObjectArray::New(); | 904 types = GrowableObjectArray::New(); |
| 823 pending_types = &types; | 905 pending_types = &types; |
| 824 } | 906 } |
| 825 | 907 |
| 826 // The type class does not need to be finalized in order to finalize the type, | 908 // The type class does not need to be finalized in order to finalize the type, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 855 script, parameterized_type.token_pos(), | 937 script, parameterized_type.token_pos(), |
| 856 "wrong number of type arguments for class '%s'", | 938 "wrong number of type arguments for class '%s'", |
| 857 type_class_name.ToCString()); | 939 type_class_name.ToCString()); |
| 858 } | 940 } |
| 859 // Make the type raw and continue without reporting any error. | 941 // Make the type raw and continue without reporting any error. |
| 860 // A static warning should have been reported. | 942 // A static warning should have been reported. |
| 861 arguments = TypeArguments::null(); | 943 arguments = TypeArguments::null(); |
| 862 parameterized_type.set_arguments(arguments); | 944 parameterized_type.set_arguments(arguments); |
| 863 } | 945 } |
| 864 | 946 |
| 947 // Mark the type as being finalized in order to detect self reference and | |
| 948 // postpone bound checking until after all types in the graph of | |
| 949 // mutually recursive types are finalized. | |
| 950 parameterized_type.set_is_being_finalized(); | |
| 951 pending_types->Add(parameterized_type); | |
| 952 | |
| 865 // The full type argument vector consists of the type arguments of the | 953 // The full type argument vector consists of the type arguments of the |
| 866 // super types of type_class, which are initialized from the parsed | 954 // super types of type_class, which are initialized from the parsed |
| 867 // type arguments, followed by the parsed type arguments. | 955 // type arguments, followed by the parsed type arguments. |
| 868 TypeArguments& full_arguments = TypeArguments::Handle(isolate); | 956 TypeArguments& full_arguments = TypeArguments::Handle(isolate); |
| 869 Error& bound_error = Error::Handle(isolate); | 957 Error& bound_error = Error::Handle(isolate); |
| 870 if (num_type_arguments > 0) { | 958 if (num_type_arguments > 0) { |
| 871 // If no type arguments were parsed and if the super types do not prepend | 959 // If no type arguments were parsed and if the super types do not prepend |
| 872 // type arguments to the vector, we can leave the vector as null. | 960 // type arguments to the vector, we can leave the vector as null. |
| 873 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { | 961 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { |
| 874 full_arguments = TypeArguments::New(num_type_arguments); | 962 full_arguments = TypeArguments::New(num_type_arguments); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 887 } | 975 } |
| 888 full_arguments.SetTypeAt(offset + i, type_arg); | 976 full_arguments.SetTypeAt(offset + i, type_arg); |
| 889 } | 977 } |
| 890 // Replace the compile-time argument vector (of length zero or | 978 // Replace the compile-time argument vector (of length zero or |
| 891 // num_type_parameters) of this type being finalized with the still | 979 // num_type_parameters) of this type being finalized with the still |
| 892 // unfinalized run-time argument vector (of length num_type_arguments). | 980 // unfinalized run-time argument vector (of length num_type_arguments). |
| 893 // This type being finalized may be recursively reached via bounds | 981 // This type being finalized may be recursively reached via bounds |
| 894 // checking, in which case type arguments of super classes will be seen | 982 // checking, in which case type arguments of super classes will be seen |
| 895 // as dynamic. | 983 // as dynamic. |
| 896 parameterized_type.set_arguments(full_arguments); | 984 parameterized_type.set_arguments(full_arguments); |
| 897 // Mark type as being finalized in order to detect self reference. | |
| 898 parameterized_type.set_is_being_finalized(); | |
| 899 // Finalize the current type arguments of the type, which are still the | 985 // Finalize the current type arguments of the type, which are still the |
| 900 // parsed type arguments. | 986 // parsed type arguments. |
| 901 if (!arguments.IsNull()) { | 987 if (!arguments.IsNull()) { |
| 902 for (intptr_t i = 0; i < num_type_parameters; i++) { | 988 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 903 type_arg = full_arguments.TypeAt(offset + i); | 989 type_arg = full_arguments.TypeAt(offset + i); |
| 904 ASSERT(!type_arg.IsBeingFinalized()); | 990 ASSERT(!type_arg.IsBeingFinalized()); |
| 905 type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types); | 991 type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types); |
| 906 if (type_arg.IsMalformed()) { | 992 if (type_arg.IsMalformed()) { |
| 907 // Malformed type arguments are mapped to dynamic. | 993 // Malformed type arguments are mapped to dynamic. |
| 908 type_arg = Type::DynamicType(); | 994 type_arg = Type::DynamicType(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 921 Class& owner_class = Class::Handle(isolate); | 1007 Class& owner_class = Class::Handle(isolate); |
| 922 if (type_class.IsSignatureClass()) { | 1008 if (type_class.IsSignatureClass()) { |
| 923 const Function& signature_fun = | 1009 const Function& signature_fun = |
| 924 Function::Handle(isolate, type_class.signature_function()); | 1010 Function::Handle(isolate, type_class.signature_function()); |
| 925 ASSERT(!signature_fun.is_static()); | 1011 ASSERT(!signature_fun.is_static()); |
| 926 owner_class = signature_fun.Owner(); | 1012 owner_class = signature_fun.Owner(); |
| 927 } else { | 1013 } else { |
| 928 owner_class = type_class.raw(); | 1014 owner_class = type_class.raw(); |
| 929 } | 1015 } |
| 930 if (offset > 0) { | 1016 if (offset > 0) { |
| 1017 GrowableObjectArray& trail = | |
| 1018 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); | |
| 931 FinalizeTypeArguments(owner_class, full_arguments, offset, | 1019 FinalizeTypeArguments(owner_class, full_arguments, offset, |
| 932 &bound_error, pending_types); | 1020 &bound_error, pending_types, &trail); |
| 933 } | 1021 } |
| 934 if (full_arguments.IsRaw(0, num_type_arguments)) { | 1022 if (full_arguments.IsRaw(0, num_type_arguments)) { |
| 935 // The parameterized_type is raw. Set its argument vector to null, which | 1023 // The parameterized_type is raw. Set its argument vector to null, which |
| 936 // is more efficient in type tests. | 1024 // is more efficient in type tests. |
| 937 full_arguments = TypeArguments::null(); | 1025 full_arguments = TypeArguments::null(); |
| 938 } else { | |
| 939 // Postpone bound checking until after all types in the graph of | |
| 940 // mutually recursive types are finalized. | |
| 941 pending_types->Add(parameterized_type); | |
| 942 } | 1026 } |
| 943 parameterized_type.set_arguments(full_arguments); | 1027 parameterized_type.set_arguments(full_arguments); |
| 944 } else { | 1028 } else { |
| 945 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. | 1029 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. |
| 946 } | 1030 } |
| 947 } | 1031 } |
| 948 | 1032 |
| 949 // Self referencing types may get finalized indirectly. | 1033 // Self referencing types may get finalized indirectly. |
| 950 if (!parameterized_type.IsFinalized()) { | 1034 if (!parameterized_type.IsFinalized()) { |
| 951 ASSERT(full_arguments.IsNull() || | 1035 ASSERT(full_arguments.IsNull() || |
| 952 !full_arguments.IsRaw(0, num_type_arguments)); | 1036 !full_arguments.IsRaw(0, num_type_arguments)); |
| 953 // Mark the type as finalized. | 1037 // Mark the type as finalized. |
| 954 parameterized_type.SetIsFinalized(); | 1038 parameterized_type.SetIsFinalized(); |
| 1039 // Do not yet remove the type from the pending_types array. | |
| 955 } | 1040 } |
| 956 | 1041 |
| 957 // If we are done finalizing a graph of mutually recursive types, check their | 1042 // If we are done finalizing a graph of mutually recursive types, check their |
| 958 // bounds. | 1043 // bounds. |
| 959 if (is_root_type) { | 1044 if (is_root_type) { |
| 960 Type& type = Type::Handle(isolate); | 1045 Type& type = Type::Handle(isolate); |
| 961 for (intptr_t i = 0; i < types.Length(); i++) { | 1046 for (intptr_t i = 0; i < types.Length(); i++) { |
| 962 type ^= types.At(i); | 1047 type ^= types.At(i); |
| 963 CheckTypeBounds(cls, type); | 1048 CheckTypeBounds(cls, type); |
| 964 } | 1049 } |
| (...skipping 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2484 mixin_app_class.ToCString()); | 2569 mixin_app_class.ToCString()); |
| 2485 } | 2570 } |
| 2486 } | 2571 } |
| 2487 // This mixin application class becomes the type class of the super type of | 2572 // This mixin application class becomes the type class of the super type of |
| 2488 // the next mixin application class. It is however too early to provide the | 2573 // the next mixin application class. It is however too early to provide the |
| 2489 // correct super type arguments. We use the raw type for now. | 2574 // correct super type arguments. We use the raw type for now. |
| 2490 mixin_super_type = Type::New(mixin_app_class, | 2575 mixin_super_type = Type::New(mixin_app_class, |
| 2491 Object::null_type_arguments(), | 2576 Object::null_type_arguments(), |
| 2492 mixin_type.token_pos()); | 2577 mixin_type.token_pos()); |
| 2493 } | 2578 } |
| 2494 AbstractType& type_arg = AbstractType::Handle(); | 2579 TypeArguments& mixin_app_args = TypeArguments::Handle(); |
| 2495 const TypeArguments& mixin_app_args = | 2580 if (type_args.Length() > 0) { |
| 2496 TypeArguments::Handle(TypeArguments::New(type_args.Length())); | 2581 mixin_app_args = TypeArguments::New(type_args.Length()); |
| 2497 for (intptr_t i = 0; i < type_args.Length(); i++) { | 2582 AbstractType& type_arg = AbstractType::Handle(); |
| 2498 type_arg ^= type_args.At(i); | 2583 for (intptr_t i = 0; i < type_args.Length(); i++) { |
| 2499 mixin_app_args.SetTypeAt(i, type_arg); | 2584 type_arg ^= type_args.At(i); |
| 2585 mixin_app_args.SetTypeAt(i, type_arg); | |
| 2586 } | |
| 2500 } | 2587 } |
| 2501 if (FLAG_trace_class_finalization) { | 2588 if (FLAG_trace_class_finalization) { |
| 2502 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", | 2589 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", |
| 2503 mixin_app_args.ToCString()); | 2590 mixin_app_args.ToCString()); |
| 2504 } | 2591 } |
| 2505 // The mixin application class at depth k is a subclass of mixin application | 2592 // The mixin application class at depth k is a subclass of mixin application |
| 2506 // class at depth k - 1. Build a new super type with the class at the highest | 2593 // class at depth k - 1. Build a new super type with the class at the highest |
| 2507 // depth (the last one processed by the loop above) as the type class and the | 2594 // depth (the last one processed by the loop above) as the type class and the |
| 2508 // collected type arguments from the super type and all mixin types. | 2595 // collected type arguments from the super type and all mixin types. |
| 2509 // This super type replaces the MixinAppType object in the class that extends | 2596 // This super type replaces the MixinAppType object in the class that extends |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2931 expected_name ^= String::New("_offset"); | 3018 expected_name ^= String::New("_offset"); |
| 2932 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 3019 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2933 field ^= fields_array.At(2); | 3020 field ^= fields_array.At(2); |
| 2934 ASSERT(field.Offset() == TypedDataView::length_offset()); | 3021 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2935 name ^= field.name(); | 3022 name ^= field.name(); |
| 2936 ASSERT(name.Equals("length")); | 3023 ASSERT(name.Equals("length")); |
| 2937 #endif | 3024 #endif |
| 2938 } | 3025 } |
| 2939 | 3026 |
| 2940 } // namespace dart | 3027 } // namespace dart |
| OLD | NEW |