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