Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(391)

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 12473002: Complete implementation of bounds checking in the vm, by introducing a vm object (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/flags.h" 7 #include "vm/flags.h"
8 #include "vm/heap.h" 8 #include "vm/heap.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 ASSERT(!function.IsNull()); 58 ASSERT(!function.IsNull());
59 if (function.HasOptimizedCode()) { 59 if (function.HasOptimizedCode()) {
60 function.SwitchToUnoptimizedCode(); 60 function.SwitchToUnoptimizedCode();
61 } 61 }
62 } 62 }
63 } 63 }
64 #endif 64 #endif
65 } 65 }
66 66
67 67
68 void AddSuperType(const Type& type, 68 void AddSuperType(const AbstractType& type,
69 GrowableArray<intptr_t>* finalized_super_classes) { 69 GrowableArray<intptr_t>* finalized_super_classes) {
70 ASSERT(type.HasResolvedTypeClass()); 70 ASSERT(type.HasResolvedTypeClass());
71 if (type.IsObjectType()) { 71 if (type.IsObjectType()) {
72 return; 72 return;
73 } 73 }
74 const Class& cls = Class::Handle(type.type_class()); 74 const Class& cls = Class::Handle(type.type_class());
75 ASSERT(cls.is_finalized()); 75 ASSERT(cls.is_finalized());
76 const intptr_t cid = cls.id(); 76 const intptr_t cid = cls.id();
77 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) { 77 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) {
78 if ((*finalized_super_classes)[i] == cid) { 78 if ((*finalized_super_classes)[i] == cid) {
79 // Already added. 79 // Already added.
80 return; 80 return;
81 } 81 }
82 } 82 }
83 finalized_super_classes->Add(cid); 83 finalized_super_classes->Add(cid);
84 const Type& super_type = Type::Handle(cls.super_type()); 84 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
85 AddSuperType(super_type, finalized_super_classes); 85 AddSuperType(super_type, finalized_super_classes);
86 } 86 }
87 87
88 88
89 // Use array instead of set since we expect very few subclassed classes 89 // Use array instead of set since we expect very few subclassed classes
90 // to occur. 90 // to occur.
91 static void CollectFinalizedSuperClasses( 91 static void CollectFinalizedSuperClasses(
92 const GrowableObjectArray& pending_classes, 92 const GrowableObjectArray& pending_classes,
93 GrowableArray<intptr_t>* finalized_super_classes) { 93 GrowableArray<intptr_t>* finalized_super_classes) {
94 Class& cls = Class::Handle(); 94 Class& cls = Class::Handle();
95 Type& super_type = Type::Handle(); 95 AbstractType& super_type = Type::Handle();
96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) {
97 cls ^= pending_classes.At(i); 97 cls ^= pending_classes.At(i);
98 ASSERT(!cls.is_finalized()); 98 ASSERT(!cls.is_finalized());
99 super_type ^= cls.super_type(); 99 super_type = cls.super_type();
100 if (!super_type.IsNull()) { 100 if (!super_type.IsNull()) {
101 if (!super_type.IsMalformed() && 101 if (!super_type.IsMalformed() &&
102 super_type.HasResolvedTypeClass() && 102 super_type.HasResolvedTypeClass() &&
103 Class::Handle(super_type.type_class()).is_finalized()) { 103 Class::Handle(super_type.type_class()).is_finalized()) {
104 AddSuperType(super_type, finalized_super_classes); 104 AddSuperType(super_type, finalized_super_classes);
105 } 105 }
106 } 106 }
107 } 107 }
108 } 108 }
109 109
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 Type& target_type = Type::Handle(target.RedirectionType()); 427 Type& target_type = Type::Handle(target.RedirectionType());
428 Function& target_target = Function::Handle(target.RedirectionTarget()); 428 Function& target_target = Function::Handle(target.RedirectionTarget());
429 if (target_target.IsNull()) { 429 if (target_target.IsNull()) {
430 ASSERT(target_type.IsMalformed()); 430 ASSERT(target_type.IsMalformed());
431 } else { 431 } else {
432 // If the target type refers to type parameters, substitute them with the 432 // If the target type refers to type parameters, substitute them with the
433 // type arguments of the redirection type. 433 // type arguments of the redirection type.
434 if (!target_type.IsInstantiated()) { 434 if (!target_type.IsInstantiated()) {
435 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( 435 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
436 type.arguments()); 436 type.arguments());
437 target_type ^= target_type.InstantiateFrom(type_args); 437 Error& malformed_error = Error::Handle();
438 // TODO(regis): Check bounds in checked mode. 438 target_type ^= target_type.InstantiateFrom(type_args, &malformed_error);
439 target_type ^= FinalizeType(cls, target_type, kCanonicalize); 439 if (malformed_error.IsNull()) {
440 if (target_type.IsMalformed()) { 440 target_type ^= FinalizeType(cls, target_type, kCanonicalize);
441 } else {
442 FinalizeMalformedType(malformed_error,
443 cls, target_type, kFinalize,
444 "cannot resolve redirecting factory");
441 target_target = Function::null(); 445 target_target = Function::null();
442 } 446 }
443 } 447 }
444 } 448 }
445 factory.SetRedirectionType(target_type); 449 factory.SetRedirectionType(target_type);
446 factory.SetRedirectionTarget(target_target); 450 factory.SetRedirectionTarget(target_target);
447 } 451 }
448 452
449 453
450 void ClassFinalizer::ResolveType(const Class& cls, 454 void ClassFinalizer::ResolveType(const Class& cls,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 AbstractType& type_argument = AbstractType::Handle(); 501 AbstractType& type_argument = AbstractType::Handle();
498 for (intptr_t i = 0; i < num_arguments; i++) { 502 for (intptr_t i = 0; i < num_arguments; i++) {
499 type_argument = arguments.TypeAt(i); 503 type_argument = arguments.TypeAt(i);
500 ResolveType(cls, type_argument, finalization); 504 ResolveType(cls, type_argument, finalization);
501 } 505 }
502 } 506 }
503 } 507 }
504 508
505 509
506 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { 510 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
511 // The type parameter bounds are not finalized here.
507 const TypeArguments& type_parameters = 512 const TypeArguments& type_parameters =
508 TypeArguments::Handle(cls.type_parameters()); 513 TypeArguments::Handle(cls.type_parameters());
509 if (!type_parameters.IsNull()) { 514 if (!type_parameters.IsNull()) {
510 TypeParameter& type_parameter = TypeParameter::Handle(); 515 TypeParameter& type_parameter = TypeParameter::Handle();
511 const intptr_t num_types = type_parameters.Length(); 516 const intptr_t num_types = type_parameters.Length();
512 for (intptr_t i = 0; i < num_types; i++) { 517 for (intptr_t i = 0; i < num_types; i++) {
513 type_parameter ^= type_parameters.TypeAt(i); 518 type_parameter ^= type_parameters.TypeAt(i);
514 type_parameter ^= FinalizeType(cls, 519 type_parameter ^= FinalizeType(cls,
515 type_parameter, 520 type_parameter,
516 kCanonicalizeWellFormed); 521 kCanonicalizeWellFormed);
(...skipping 13 matching lines...) Expand all
530 // Example: 535 // Example:
531 // Declared: class C<K, V> extends B<V> { ... } 536 // Declared: class C<K, V> extends B<V> { ... }
532 // class B<T> extends A<int> { ... } 537 // class B<T> extends A<int> { ... }
533 // Input: C<String, double> expressed as 538 // Input: C<String, double> expressed as
534 // cls = C, arguments = [null, null, String, double], 539 // cls = C, arguments = [null, null, String, double],
535 // i.e. cls_args = [String, double], offset = 2, length = 2. 540 // i.e. cls_args = [String, double], offset = 2, length = 2.
536 // Output: arguments = [int, double, String, double] 541 // Output: arguments = [int, double, String, double]
537 void ClassFinalizer::FinalizeTypeArguments( 542 void ClassFinalizer::FinalizeTypeArguments(
538 const Class& cls, 543 const Class& cls,
539 const AbstractTypeArguments& arguments, 544 const AbstractTypeArguments& arguments,
540 FinalizationKind finalization) { 545 FinalizationKind finalization,
546 Error* bound_error) {
541 ASSERT(arguments.Length() >= cls.NumTypeArguments()); 547 ASSERT(arguments.Length() >= cls.NumTypeArguments());
542 if (!cls.is_finalized()) { 548 if (!cls.is_finalized()) {
543 FinalizeTypeParameters(cls); 549 FinalizeTypeParameters(cls);
544 } 550 }
545 Type& super_type = Type::Handle(cls.super_type()); 551 AbstractType& super_type = AbstractType::Handle(cls.super_type());
546 if (!super_type.IsNull()) { 552 if (!super_type.IsNull()) {
547 const Class& super_class = Class::Handle(super_type.type_class()); 553 const Class& super_class = Class::Handle(super_type.type_class());
548 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); 554 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle();
549 if (super_type.IsBeingFinalized()) { 555 if (super_type.IsBeingFinalized()) {
550 // This type references itself via its type arguments. This is legal, but 556 // This type references itself via its type arguments. This is legal, but
551 // we must avoid endless recursion. We therefore map the innermost 557 // we must avoid endless recursion. We therefore map the innermost
552 // super type to dynamic. 558 // super type to dynamic.
553 // Note that a direct self-reference via the super class chain is illegal 559 // Note that a direct self-reference via the super class chain is illegal
554 // and reported as an error earlier. 560 // and reported as an error earlier.
555 // Such legal self-references occur with F-bounded quantification. 561 // Such legal self-references occur with F-bounded quantification.
(...skipping 13 matching lines...) Expand all
569 } 575 }
570 const intptr_t num_super_type_params = super_class.NumTypeParameters(); 576 const intptr_t num_super_type_params = super_class.NumTypeParameters();
571 const intptr_t offset = super_class.NumTypeArguments(); 577 const intptr_t offset = super_class.NumTypeArguments();
572 const intptr_t super_offset = offset - num_super_type_params; 578 const intptr_t super_offset = offset - num_super_type_params;
573 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters())); 579 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters()));
574 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); 580 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType());
575 for (intptr_t i = 0; i < num_super_type_params; i++) { 581 for (intptr_t i = 0; i < num_super_type_params; i++) {
576 if (!super_type_args.IsNull()) { 582 if (!super_type_args.IsNull()) {
577 super_type_arg = super_type_args.TypeAt(super_offset + i); 583 super_type_arg = super_type_args.TypeAt(super_offset + i);
578 if (!super_type_arg.IsInstantiated()) { 584 if (!super_type_arg.IsInstantiated()) {
579 super_type_arg = super_type_arg.InstantiateFrom(arguments); 585 Error& malformed_error = Error::Handle();
586 super_type_arg = super_type_arg.InstantiateFrom(arguments,
587 &malformed_error);
588 if (!malformed_error.IsNull()) {
589 if (!super_type_arg.IsInstantiated()) {
590 // CheckTypeArgumentBounds will insert a BoundedType.
591 } else if (bound_error->IsNull()) {
592 *bound_error = malformed_error.raw();
593 }
594 }
580 } 595 }
581 if (finalization >= kCanonicalize) { 596 if (finalization >= kCanonicalize) {
582 super_type_arg = super_type_arg.Canonicalize(); 597 super_type_arg = super_type_arg.Canonicalize();
583 } 598 }
584 } 599 }
585 arguments.SetTypeAt(super_offset + i, super_type_arg); 600 arguments.SetTypeAt(super_offset + i, super_type_arg);
586 } 601 }
587 FinalizeTypeArguments(super_class, arguments, finalization); 602 FinalizeTypeArguments(super_class, arguments, finalization, bound_error);
603 }
604 }
605
606
607 // Check the type argument vector 'arguments' against the corresponding bounds
608 // of the type parameters of class 'cls' and, recursively, of its superclasses.
609 // Replace a type argument that cannot be checked at compile time by a
610 // BoundedType, thereby postponing the bound check to run time.
611 // Return a bound error if a type argument is not within bound at compile time.
612 void ClassFinalizer::CheckTypeArgumentBounds(
613 const Class& cls,
614 const AbstractTypeArguments& arguments,
615 Error* bound_error) {
616 if (!cls.is_finalized()) {
617 ResolveAndFinalizeUpperBounds(cls);
618 }
619 // Note that when finalizing a type, we need to verify the bounds in both
620 // production mode and checked mode, because the finalized type may be written
621 // to a snapshot. It would be wrong to ignore bounds when generating the
622 // snapshot in production mode and then use the unchecked type in checked mode
623 // after reading it from the snapshot.
624 // However, we do not immediately report a bound error, which would be wrong
625 // in production mode, but simply postpone the bound checking to runtime.
626 const intptr_t num_type_params = cls.NumTypeParameters();
627 const intptr_t offset = cls.NumTypeArguments() - num_type_params;
628 AbstractType& type_arg = AbstractType::Handle();
629 AbstractType& cls_type_param = AbstractType::Handle();
630 AbstractType& bound = AbstractType::Handle();
631 const TypeArguments& cls_type_params =
632 TypeArguments::Handle(cls.type_parameters());
633 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) ||
634 (cls_type_params.Length() == num_type_params));
635 for (intptr_t i = 0; i < num_type_params; i++) {
636 type_arg = arguments.TypeAt(offset + i);
637 if (type_arg.IsDynamicType()) {
638 continue;
639 }
640 cls_type_param = cls_type_params.TypeAt(i);
641 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param);
642 ASSERT(type_param.IsFinalized());
643 bound = type_param.bound();
644 if (!bound.IsObjectType() && !bound.IsDynamicType()) {
645 Error& malformed_error = Error::Handle();
646 // Note that the bound may be malformed, in which case the bound check
647 // will return an error and the bound check will be postponed to run time.
648 // Note also that the bound may still be unfinalized.
649 if (!bound.IsFinalized()) {
650 ASSERT(bound.IsBeingFinalized());
651 // The bound refers to type parameters, creating a cycle; postpone
652 // bound check to run time, when the bound will be finalized.
653 // TODO(regis): Do we need to instantiate an uninstantiated bound here?
654 type_arg = BoundedType::New(type_arg, bound, type_param);
655 arguments.SetTypeAt(offset + i, type_arg);
656 continue;
657 }
658 if (!bound.IsInstantiated()) {
659 bound = bound.InstantiateFrom(arguments, &malformed_error);
660 }
661 // TODO(regis): We could simplify this code if we could differentiate
662 // between a failed bound check and a bound check that is undecidable at
663 // compile time.
664 if (malformed_error.IsNull()) {
665 type_param.CheckBound(type_arg, bound, &malformed_error);
666 }
667 if (!malformed_error.IsNull()) {
668 if (!type_arg.IsInstantiated() || !bound.IsInstantiated()) {
669 type_arg = BoundedType::New(type_arg, bound, type_param);
670 arguments.SetTypeAt(offset + i, type_arg);
671 } else if (bound_error->IsNull()) {
672 *bound_error = malformed_error.raw();
673 }
674 }
675 }
676 }
677 AbstractType& super_type = AbstractType::Handle(cls.super_type());
678 if (!super_type.IsNull()) {
679 const Class& super_class = Class::Handle(super_type.type_class());
680 CheckTypeArgumentBounds(super_class, arguments, bound_error);
588 } 681 }
589 } 682 }
590 683
591 684
592 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, 685 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
593 const AbstractType& type, 686 const AbstractType& type,
594 FinalizationKind finalization) { 687 FinalizationKind finalization) {
595 if (type.IsFinalized()) { 688 if (type.IsFinalized()) {
596 // Ensure type is canonical if canonicalization is requested, unless type is 689 // Ensure type is canonical if canonicalization is requested, unless type is
597 // malformed. 690 // malformed.
(...skipping 22 matching lines...) Expand all
620 ASSERT(!parameterized_class.IsNull()); 713 ASSERT(!parameterized_class.IsNull());
621 // The index must reflect the position of this type parameter in the type 714 // The index must reflect the position of this type parameter in the type
622 // arguments vector of its parameterized class. The offset to add is the 715 // arguments vector of its parameterized class. The offset to add is the
623 // number of type arguments in the super type, which is equal to the 716 // number of type arguments in the super type, which is equal to the
624 // difference in number of type arguments and type parameters of the 717 // difference in number of type arguments and type parameters of the
625 // parameterized class. 718 // parameterized class.
626 const intptr_t offset = parameterized_class.NumTypeArguments() - 719 const intptr_t offset = parameterized_class.NumTypeArguments() -
627 parameterized_class.NumTypeParameters(); 720 parameterized_class.NumTypeParameters();
628 type_parameter.set_index(type_parameter.index() + offset); 721 type_parameter.set_index(type_parameter.index() + offset);
629 type_parameter.set_is_finalized(); 722 type_parameter.set_is_finalized();
630 // TODO(regis): We are not able to finalize the bound here without getting
631 // into cycles. Revisit.
632 // We do not canonicalize type parameters. 723 // We do not canonicalize type parameters.
633 return type_parameter.raw(); 724 return type_parameter.raw();
634 } 725 }
635 726
636 // At this point, we can only have a parameterized_type. 727 // At this point, we can only have a parameterized_type.
637 const Type& parameterized_type = Type::Cast(type); 728 const Type& parameterized_type = Type::Cast(type);
638 729
639 if (parameterized_type.IsBeingFinalized()) { 730 if (parameterized_type.IsBeingFinalized()) {
640 // Self reference detected. The type is malformed. 731 // Self reference detected. The type is malformed.
641 FinalizeMalformedType( 732 FinalizeMalformedType(
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 Error::Handle(), // No previous error. 802 Error::Handle(), // No previous error.
712 cls, parameterized_type, finalization, 803 cls, parameterized_type, finalization,
713 "wrong number of type arguments in type '%s'", 804 "wrong number of type arguments in type '%s'",
714 String::Handle(parameterized_type.UserVisibleName()).ToCString()); 805 String::Handle(parameterized_type.UserVisibleName()).ToCString());
715 return parameterized_type.raw(); 806 return parameterized_type.raw();
716 } 807 }
717 // The full type argument vector consists of the type arguments of the 808 // The full type argument vector consists of the type arguments of the
718 // super types of type_class, which may be initialized from the parsed 809 // super types of type_class, which may be initialized from the parsed
719 // type arguments, followed by the parsed type arguments. 810 // type arguments, followed by the parsed type arguments.
720 TypeArguments& full_arguments = TypeArguments::Handle(); 811 TypeArguments& full_arguments = TypeArguments::Handle();
812 Error& bound_error = Error::Handle();
721 if (num_type_arguments > 0) { 813 if (num_type_arguments > 0) {
722 // If no type arguments were parsed and if the super types do not prepend 814 // If no type arguments were parsed and if the super types do not prepend
723 // type arguments to the vector, we can leave the vector as null. 815 // type arguments to the vector, we can leave the vector as null.
724 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { 816 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
725 full_arguments = TypeArguments::New(num_type_arguments); 817 full_arguments = TypeArguments::New(num_type_arguments);
726 // Copy the parsed type arguments at the correct offset in the full type 818 // Copy the parsed type arguments at the correct offset in the full type
727 // argument vector. 819 // argument vector.
728 const intptr_t offset = num_type_arguments - num_type_parameters; 820 const intptr_t offset = num_type_arguments - num_type_parameters;
729 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType()); 821 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType());
730 for (intptr_t i = 0; i < num_type_parameters; i++) { 822 for (intptr_t i = 0; i < num_type_parameters; i++) {
(...skipping 11 matching lines...) Expand all
742 // of its signature function and no super type is involved. 834 // of its signature function and no super type is involved.
743 // If the signature class is canonical (not an alias), the owner of its 835 // If the signature class is canonical (not an alias), the owner of its
744 // signature function may either be an alias or the enclosing class of a 836 // signature function may either be an alias or the enclosing class of a
745 // local function, in which case the super type of the enclosing class is 837 // local function, in which case the super type of the enclosing class is
746 // also considered when filling up the argument vector. 838 // also considered when filling up the argument vector.
747 if (type_class.IsSignatureClass()) { 839 if (type_class.IsSignatureClass()) {
748 const Function& signature_fun = 840 const Function& signature_fun =
749 Function::Handle(type_class.signature_function()); 841 Function::Handle(type_class.signature_function());
750 ASSERT(!signature_fun.is_static()); 842 ASSERT(!signature_fun.is_static());
751 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner()); 843 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner());
752 FinalizeTypeArguments(sig_fun_owner, full_arguments, finalization); 844 FinalizeTypeArguments(
845 sig_fun_owner, full_arguments, finalization, &bound_error);
846 CheckTypeArgumentBounds(sig_fun_owner, full_arguments, &bound_error);
753 } else { 847 } else {
754 FinalizeTypeArguments(type_class, full_arguments, finalization); 848 FinalizeTypeArguments(
849 type_class, full_arguments, finalization, &bound_error);
850 CheckTypeArgumentBounds(type_class, full_arguments, &bound_error);
755 } 851 }
756 if (full_arguments.IsRaw(num_type_arguments)) { 852 if (full_arguments.IsRaw(num_type_arguments)) {
757 // The parameterized_type is raw. Set its argument vector to null, which 853 // The parameterized_type is raw. Set its argument vector to null, which
758 // is more efficient in type tests. 854 // is more efficient in type tests.
759 full_arguments = TypeArguments::null(); 855 full_arguments = TypeArguments::null();
760 } else if (finalization >= kCanonicalize) { 856 } else if (finalization >= kCanonicalize) {
761 // FinalizeTypeArguments can modify 'full_arguments', 857 // FinalizeTypeArguments can modify 'full_arguments',
762 // canonicalize afterwards. 858 // canonicalize afterwards.
763 full_arguments ^= full_arguments.Canonicalize(); 859 full_arguments ^= full_arguments.Canonicalize();
764 } 860 }
765 parameterized_type.set_arguments(full_arguments); 861 parameterized_type.set_arguments(full_arguments);
766 } else { 862 } else {
767 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. 863 ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
768 } 864 }
769 } 865 }
770 866
771 // Self referencing types may get finalized indirectly. 867 // Self referencing types may get finalized indirectly.
772 if (!parameterized_type.IsFinalized()) { 868 if (!parameterized_type.IsFinalized()) {
773 // Mark the type as finalized. 869 // Mark the type as finalized.
774 parameterized_type.SetIsFinalized(); 870 parameterized_type.SetIsFinalized();
775 } 871 }
776 872
777 // Upper bounds of the finalized type arguments are only verified in checked
778 // mode, since bound errors are never reported by the vm in production mode.
779 if (FLAG_enable_type_checks &&
780 !full_arguments.IsNull() &&
781 full_arguments.IsInstantiated()) {
782 ResolveAndFinalizeUpperBounds(type_class);
783 Error& malformed_error = Error::Handle();
784 // Pass the full type argument vector as the bounds instantiator.
785 if (!full_arguments.IsWithinBoundsOf(type_class,
786 full_arguments,
787 &malformed_error)) {
788 ASSERT(!malformed_error.IsNull());
789 // The type argument vector of the type is not within bounds. The type
790 // is malformed. Prepend malformed_error to new malformed type error in
791 // order to report both locations.
792 // Note that malformed bounds never result in a compile time error, even
793 // in checked mode. Therefore, overwrite finalization with kFinalize
794 // when finalizing the malformed type.
795 FinalizeMalformedType(
796 malformed_error,
797 cls, parameterized_type, kFinalize,
798 "type arguments of type '%s' are not within bounds",
799 String::Handle(parameterized_type.UserVisibleName()).ToCString());
800 return parameterized_type.raw();
801 }
802 }
803
804 // If the type class is a signature class, we are currently finalizing a 873 // If the type class is a signature class, we are currently finalizing a
805 // signature type, i.e. finalizing the result type and parameter types of the 874 // signature type, i.e. finalizing the result type and parameter types of the
806 // signature function of this signature type. 875 // signature function of this signature type.
807 // We do this after marking this type as finalized in order to allow a 876 // We do this after marking this type as finalized in order to allow a
808 // function type to refer to itself via its parameter types and result type. 877 // function type to refer to itself via its parameter types and result type.
809 if (type_class.IsSignatureClass()) { 878 if (type_class.IsSignatureClass()) {
810 // The class may be created while parsing a function body, after all 879 // The class may be created while parsing a function body, after all
811 // pending classes have already been finalized. 880 // pending classes have already been finalized.
812 FinalizeClass(type_class); 881 FinalizeClass(type_class);
813 } 882 }
814 883
884 // If a bound error occurred, return a BoundedType with a malformed bound.
885 // The malformed bound will be ignored in production mode.
886 if (!bound_error.IsNull()) {
887 FinalizationKind bound_finalization = kTryResolve; // No compile error.
888 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
889 bound_finalization = finalization;
890 }
891 const String& parameterized_type_name = String::Handle(
892 parameterized_type.UserVisibleName());
893 const Type& malformed_bound = Type::Handle(
894 NewFinalizedMalformedType(bound_error,
895 cls,
896 parameterized_type.token_pos(),
897 bound_finalization,
898 "type '%s' has an out of bound type argument",
899 parameterized_type_name.ToCString()));
900 return BoundedType::New(parameterized_type,
901 malformed_bound,
902 TypeParameter::Handle());
903 }
904
815 if (finalization >= kCanonicalize) { 905 if (finalization >= kCanonicalize) {
816 return parameterized_type.Canonicalize(); 906 return parameterized_type.Canonicalize();
817 } else { 907 } else {
818 return parameterized_type.raw(); 908 return parameterized_type.raw();
819 } 909 }
820 } 910 }
821 911
822 912
823 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, 913 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls,
824 const Function& function) { 914 const Function& function) {
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); 1191 const Class& mixin_cls = Class::Handle(mixin_type.type_class());
1102 1192
1103 if (FLAG_trace_class_finalization) { 1193 if (FLAG_trace_class_finalization) {
1104 OS::Print("Applying mixin '%s' to '%s'\n", 1194 OS::Print("Applying mixin '%s' to '%s'\n",
1105 String::Handle(mixin_cls.Name()).ToCString(), 1195 String::Handle(mixin_cls.Name()).ToCString(),
1106 cls.ToCString()); 1196 cls.ToCString());
1107 } 1197 }
1108 1198
1109 // Check that the super class of the mixin class is extending 1199 // Check that the super class of the mixin class is extending
1110 // class Object. 1200 // class Object.
1111 const Type& mixin_super_type = Type::Handle(mixin_cls.super_type()); 1201 const AbstractType& mixin_super_type =
1202 AbstractType::Handle(mixin_cls.super_type());
1112 if (!mixin_super_type.IsObjectType()) { 1203 if (!mixin_super_type.IsObjectType()) {
1113 const Script& script = Script::Handle(cls.script()); 1204 const Script& script = Script::Handle(cls.script());
1114 const String& class_name = String::Handle(mixin_cls.Name()); 1205 const String& class_name = String::Handle(mixin_cls.Name());
1115 ReportError(script, cls.token_pos(), 1206 ReportError(script, cls.token_pos(),
1116 "mixin class %s must extend class Object", 1207 "mixin class %s must extend class Object",
1117 class_name.ToCString()); 1208 class_name.ToCString());
1118 } 1209 }
1119 1210
1120 // Copy the type parameters of the mixin class to the mixin 1211 // Copy the type parameters of the mixin class to the mixin
1121 // application class. 1212 // application class.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 } 1308 }
1218 if (cls.mixin() != Type::null()) { 1309 if (cls.mixin() != Type::null()) {
1219 // Copy instance methods and fields from the mixin class. 1310 // Copy instance methods and fields from the mixin class.
1220 // This has to happen before the check whether the methods of 1311 // This has to happen before the check whether the methods of
1221 // the class conflict with inherited methods. 1312 // the class conflict with inherited methods.
1222 ApplyMixin(cls); 1313 ApplyMixin(cls);
1223 } 1314 }
1224 // Finalize type parameters before finalizing the super type. 1315 // Finalize type parameters before finalizing the super type.
1225 FinalizeTypeParameters(cls); 1316 FinalizeTypeParameters(cls);
1226 // Finalize super type. 1317 // Finalize super type.
1227 Type& super_type = Type::Handle(cls.super_type()); 1318 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1228 if (!super_type.IsNull()) { 1319 if (!super_type.IsNull()) {
1229 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); 1320 // In case of a bound error in the super type in production mode, the
1321 // finalized super type will be a BoundedType with a malformed bound.
1322 // It should not be a problem if the class is written to a snapshot and
1323 // later executed in checked mode. Note that the finalized type argument
1324 // vector of any type of the base class will contain a BoundedType for the
1325 // out of bound type argument.
1326 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed);
1230 cls.set_super_type(super_type); 1327 cls.set_super_type(super_type);
1231 } 1328 }
1232 if (cls.IsSignatureClass()) { 1329 if (cls.IsSignatureClass()) {
1233 // Check for illegal self references. 1330 // Check for illegal self references.
1234 GrowableArray<intptr_t> visited_aliases; 1331 GrowableArray<intptr_t> visited_aliases;
1235 if (!IsAliasCycleFree(cls, &visited_aliases)) { 1332 if (!IsAliasCycleFree(cls, &visited_aliases)) {
1236 const String& name = String::Handle(cls.Name()); 1333 const String& name = String::Handle(cls.Name());
1237 const Script& script = Script::Handle(cls.script()); 1334 const Script& script = Script::Handle(cls.script());
1238 ReportError(script, cls.token_pos(), 1335 ReportError(script, cls.token_pos(),
1239 "typedef '%s' illegally refers to itself", 1336 "typedef '%s' illegally refers to itself",
1240 name.ToCString()); 1337 name.ToCString());
1241 } 1338 }
1242 cls.Finalize(); 1339 cls.Finalize();
1243 // Signature classes extend Object. No need to add this class to the direct 1340 // Signature classes extend Object. No need to add this class to the direct
1244 // subclasses of Object. 1341 // subclasses of Object.
1245 ASSERT(super_type.IsNull() || super_type.IsObjectType()); 1342 ASSERT(super_type.IsNull() || super_type.IsObjectType());
1246 1343
1344 // The type parameters of signature classes may have bounds.
1345 ResolveAndFinalizeUpperBounds(cls);
1346
1247 // Resolve and finalize the result and parameter types of the signature 1347 // Resolve and finalize the result and parameter types of the signature
1248 // function of this signature class. 1348 // function of this signature class.
1249 const Function& sig_function = Function::Handle(cls.signature_function()); 1349 const Function& sig_function = Function::Handle(cls.signature_function());
1250 ResolveAndFinalizeSignature(cls, sig_function); 1350 ResolveAndFinalizeSignature(cls, sig_function);
1251 1351
1252 // Resolve and finalize the signature type of this signature class. 1352 // Resolve and finalize the signature type of this signature class.
1253 const Type& sig_type = Type::Handle(cls.SignatureType()); 1353 const Type& sig_type = Type::Handle(cls.SignatureType());
1254 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); 1354 FinalizeType(cls, sig_type, kCanonicalizeWellFormed);
1255 return; 1355 return;
1256 } 1356 }
1257 // Finalize interface types (but not necessarily interface classes). 1357 // Finalize interface types (but not necessarily interface classes).
1258 Array& interface_types = Array::Handle(cls.interfaces()); 1358 Array& interface_types = Array::Handle(cls.interfaces());
1259 AbstractType& interface_type = AbstractType::Handle(); 1359 AbstractType& interface_type = AbstractType::Handle();
1260 for (intptr_t i = 0; i < interface_types.Length(); i++) { 1360 for (intptr_t i = 0; i < interface_types.Length(); i++) {
1261 interface_type ^= interface_types.At(i); 1361 interface_type ^= interface_types.At(i);
1262 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); 1362 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed);
1263 interface_types.SetAt(i, interface_type); 1363 interface_types.SetAt(i, interface_type);
1264 } 1364 }
1265 // Mark as finalized before resolving type parameter upper bounds and member 1365 // Mark as finalized before resolving type parameter upper bounds and member
1266 // types in order to break cycles. 1366 // types in order to break cycles.
1267 cls.Finalize(); 1367 cls.Finalize();
1368 // Finalize bounds even if running in production mode, so that a snapshot
1369 // contains them.
1268 ResolveAndFinalizeUpperBounds(cls); 1370 ResolveAndFinalizeUpperBounds(cls);
1269 ResolveAndFinalizeMemberTypes(cls); 1371 ResolveAndFinalizeMemberTypes(cls);
1270 // Run additional checks after all types are finalized. 1372 // Run additional checks after all types are finalized.
1271 if (cls.is_const()) { 1373 if (cls.is_const()) {
1272 CheckForLegalConstClass(cls); 1374 CheckForLegalConstClass(cls);
1273 } 1375 }
1274 // Add this class to the direct subclasses of the superclass, unless the 1376 // Add this class to the direct subclasses of the superclass, unless the
1275 // superclass is Object. 1377 // superclass is Object.
1276 if (!super_type.IsNull() && !super_type.IsObjectType()) { 1378 if (!super_type.IsNull() && !super_type.IsObjectType()) {
1277 ASSERT(!super_class.IsNull()); 1379 ASSERT(!super_class.IsNull());
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1366 const String& class_name = String::Handle(cls.Name()); 1468 const String& class_name = String::Handle(cls.Name());
1367 const Script& script = Script::Handle(cls.script()); 1469 const Script& script = Script::Handle(cls.script());
1368 ReportError(script, cls.token_pos(), 1470 ReportError(script, cls.token_pos(),
1369 "cyclic reference found for class '%s'", 1471 "cyclic reference found for class '%s'",
1370 class_name.ToCString()); 1472 class_name.ToCString());
1371 } 1473 }
1372 } 1474 }
1373 1475
1374 // If the class/interface has no explicit super class/interfaces 1476 // If the class/interface has no explicit super class/interfaces
1375 // and is not a mixin application, we are done. 1477 // and is not a mixin application, we are done.
1376 Type& super_type = Type::Handle(cls.super_type()); 1478 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1377 Type& mixin_type = Type::Handle(cls.mixin()); 1479 Type& mixin_type = Type::Handle(cls.mixin());
1378 Array& super_interfaces = Array::Handle(cls.interfaces()); 1480 Array& super_interfaces = Array::Handle(cls.interfaces());
1379 if ((super_type.IsNull() || super_type.IsObjectType()) && 1481 if ((super_type.IsNull() || super_type.IsObjectType()) &&
1380 (super_interfaces.Length() == 0) && 1482 (super_interfaces.Length() == 0) &&
1381 (mixin_type.IsNull())) { 1483 (mixin_type.IsNull())) {
1382 return; 1484 return;
1383 } 1485 }
1384 1486
1385 if (!mixin_type.IsNull()) { 1487 if (!mixin_type.IsNull()) {
1386 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); 1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed);
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 const String& class_name = String::Handle(cls.Name()); 1648 const String& class_name = String::Handle(cls.Name());
1547 OS::Print("class '%s'", class_name.ToCString()); 1649 OS::Print("class '%s'", class_name.ToCString());
1548 const Library& library = Library::Handle(cls.library()); 1650 const Library& library = Library::Handle(cls.library());
1549 if (!library.IsNull()) { 1651 if (!library.IsNull()) {
1550 OS::Print(" library '%s%s':\n", 1652 OS::Print(" library '%s%s':\n",
1551 String::Handle(library.url()).ToCString(), 1653 String::Handle(library.url()).ToCString(),
1552 String::Handle(library.private_key()).ToCString()); 1654 String::Handle(library.private_key()).ToCString());
1553 } else { 1655 } else {
1554 OS::Print(" (null library):\n"); 1656 OS::Print(" (null library):\n");
1555 } 1657 }
1556 const Type& super_type = Type::Handle(cls.super_type()); 1658 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
1557 if (super_type.IsNull()) { 1659 if (super_type.IsNull()) {
1558 OS::Print(" Super: NULL"); 1660 OS::Print(" Super: NULL");
1559 } else { 1661 } else {
1560 const String& super_name = String::Handle(super_type.Name()); 1662 const String& super_name = String::Handle(super_type.Name());
1561 OS::Print(" Super: %s", super_name.ToCString()); 1663 OS::Print(" Super: %s", super_name.ToCString());
1562 } 1664 }
1563 const Array& interfaces_array = Array::Handle(cls.interfaces()); 1665 const Array& interfaces_array = Array::Handle(cls.interfaces());
1564 if (interfaces_array.Length() > 0) { 1666 if (interfaces_array.Length() > 0) {
1565 OS::Print("; interfaces: "); 1667 OS::Print("; interfaces: ");
1566 AbstractType& interface = AbstractType::Handle(); 1668 AbstractType& interface = AbstractType::Handle();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 script, type.token_pos(), "Error", format, args); 1707 script, type.token_pos(), "Error", format, args);
1606 } else { 1708 } else {
1607 error ^= Parser::FormatErrorWithAppend( 1709 error ^= Parser::FormatErrorWithAppend(
1608 prev_error, script, type.token_pos(), "Error", format, args); 1710 prev_error, script, type.token_pos(), "Error", format, args);
1609 } 1711 }
1610 if ((finalization == kCanonicalizeWellFormed) || 1712 if ((finalization == kCanonicalizeWellFormed) ||
1611 FLAG_error_on_malformed_type) { 1713 FLAG_error_on_malformed_type) {
1612 ReportError(error); 1714 ReportError(error);
1613 } 1715 }
1614 } 1716 }
1717 // In checked mode, always mark the type as malformed.
1718 // In production mode, mark the type as malformed only if its type class is
1719 // not resolved.
1720 // In both mode, make the type raw, since it may not be possible to
1721 // properly finalize its type arguments.
1615 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { 1722 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) {
1616 // In check mode, always mark the type as malformed.
1617 // In production mode, mark the type as malformed only if its type class is
1618 // not resolved.
1619 type.set_malformed_error(error); 1723 type.set_malformed_error(error);
1620 if (!type.HasResolvedTypeClass()) {
1621 // We do not want an unresolved class to end up in a snapshot.
1622 type.set_type_class(Object::Handle(Object::null_class()));
1623 }
1624 } else {
1625 // In production mode, do not mark the type with a resolved type class as
1626 // malformed, but make it raw.
1627 type.set_arguments(AbstractTypeArguments::Handle());
1628 } 1724 }
1629 ASSERT(type.HasResolvedTypeClass()); 1725 type.set_arguments(AbstractTypeArguments::Handle());
1630 if (!type.IsFinalized()) { 1726 if (!type.IsFinalized()) {
1631 type.SetIsFinalized(); 1727 type.SetIsFinalized();
1632 // Do not canonicalize malformed types, since they may not be resolved. 1728 // Do not canonicalize malformed types, since they may not be resolved.
1633 } else { 1729 } else {
1634 // The only case where the malformed type was already finalized is when its 1730 // The only case where the malformed type was already finalized is when its
1635 // type arguments are not within bounds. In that case, we have a prev_error. 1731 // type arguments are not within bounds. In that case, we have a prev_error.
1636 ASSERT(!prev_error.IsNull()); 1732 ASSERT(!prev_error.IsNull());
1637 } 1733 }
1638 } 1734 }
1639 1735
1640 1736
1641 RawType* ClassFinalizer::NewFinalizedMalformedType( 1737 RawType* ClassFinalizer::NewFinalizedMalformedType(
1642 const Error& prev_error, 1738 const Error& prev_error,
1643 const Class& cls, 1739 const Class& cls,
1644 intptr_t type_pos, 1740 intptr_t type_pos,
1645 FinalizationKind finalization, 1741 FinalizationKind finalization,
1646 const char* format, ...) { 1742 const char* format, ...) {
1647 va_list args; 1743 va_list args;
1648 va_start(args, format); 1744 va_start(args, format);
1649 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( 1745 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle(
1650 UnresolvedClass::New(LibraryPrefix::Handle(), 1746 UnresolvedClass::New(LibraryPrefix::Handle(),
1651 Symbols::Empty(), 1747 Symbols::Empty(),
1652 type_pos)); 1748 type_pos));
1653 const Type& type = Type::Handle( 1749 const Type& type = Type::Handle(
1654 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); 1750 Type::New(unresolved_class, TypeArguments::Handle(), type_pos));
1655 ReportMalformedType(prev_error, cls, type, finalization, format, args); 1751 ReportMalformedType(prev_error, cls, type, finalization, format, args);
1656 va_end(args); 1752 va_end(args);
1657 ASSERT(type.IsMalformed()); 1753 ASSERT(type.IsMalformed());
1754 ASSERT(type.IsFinalized());
1658 return type.raw(); 1755 return type.raw();
1659 } 1756 }
1660 1757
1661 1758
1662 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, 1759 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error,
1663 const Class& cls, 1760 const Class& cls,
1664 const Type& type, 1761 const Type& type,
1665 FinalizationKind finalization, 1762 FinalizationKind finalization,
1666 const char* format, ...) { 1763 const char* format, ...) {
1667 va_list args; 1764 va_list args;
(...skipping 24 matching lines...) Expand all
1692 void ClassFinalizer::ReportError(const char* format, ...) { 1789 void ClassFinalizer::ReportError(const char* format, ...) {
1693 va_list args; 1790 va_list args;
1694 va_start(args, format); 1791 va_start(args, format);
1695 const Error& error = Error::Handle( 1792 const Error& error = Error::Handle(
1696 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1793 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1697 va_end(args); 1794 va_end(args);
1698 ReportError(error); 1795 ReportError(error);
1699 } 1796 }
1700 1797
1701 } // namespace dart 1798 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/code_generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698