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/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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 if (!type.IsMalformed()) { | 282 if (!type.IsMalformed()) { |
283 const GrowableObjectArray& visited_factories = | 283 const GrowableObjectArray& visited_factories = |
284 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 284 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
285 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); | 285 ResolveRedirectingFactoryTarget(cls, factory, visited_factories); |
286 } | 286 } |
287 if (factory.is_const()) { | 287 if (factory.is_const()) { |
288 type = factory.RedirectionType(); | 288 type = factory.RedirectionType(); |
289 if (type.IsMalformed()) { | 289 if (type.IsMalformed()) { |
290 ReportError(Error::Handle(type.malformed_error())); | 290 ReportError(Error::Handle(type.malformed_error())); |
291 } | 291 } |
| 292 Error& error = Error::Handle(); |
| 293 if (type.IsMalboundedWithError(&error)) { |
| 294 ReportError(error); |
| 295 } |
292 } | 296 } |
293 } | 297 } |
294 } | 298 } |
295 | 299 |
296 | 300 |
297 void ClassFinalizer::ResolveRedirectingFactoryTarget( | 301 void ClassFinalizer::ResolveRedirectingFactoryTarget( |
298 const Class& cls, | 302 const Class& cls, |
299 const Function& factory, | 303 const Function& factory, |
300 const GrowableObjectArray& visited_factories) { | 304 const GrowableObjectArray& visited_factories) { |
301 ASSERT(factory.IsRedirectingFactory()); | 305 ASSERT(factory.IsRedirectingFactory()); |
302 | 306 |
303 // Check for redirection cycle. | 307 // Check for redirection cycle. |
304 for (intptr_t i = 0; i < visited_factories.Length(); i++) { | 308 for (intptr_t i = 0; i < visited_factories.Length(); i++) { |
305 if (visited_factories.At(i) == factory.raw()) { | 309 if (visited_factories.At(i) == factory.raw()) { |
306 // A redirection cycle is reported as a compile-time error. | 310 // A redirection cycle is reported as a compile-time error. |
307 const Script& script = Script::Handle(cls.script()); | 311 const Script& script = Script::Handle(cls.script()); |
308 ReportError(Error::Handle(), // No previous error. | 312 ReportError(Error::Handle(), // No previous error. |
309 script, factory.token_pos(), | 313 script, factory.token_pos(), |
310 "factory '%s' illegally redirects to itself", | 314 "factory '%s' illegally redirects to itself", |
311 String::Handle(factory.name()).ToCString()); | 315 String::Handle(factory.name()).ToCString()); |
312 } | 316 } |
313 } | 317 } |
314 visited_factories.Add(factory); | 318 visited_factories.Add(factory); |
315 | 319 |
316 // Check if target is already resolved. | 320 // Check if target is already resolved. |
317 Type& type = Type::Handle(factory.RedirectionType()); | 321 Type& type = Type::Handle(factory.RedirectionType()); |
318 Function& target = Function::Handle(factory.RedirectionTarget()); | 322 Function& target = Function::Handle(factory.RedirectionTarget()); |
319 if (type.IsMalformed()) { | 323 if (type.IsMalformed() || (type.IsResolved() && type.IsMalbounded())) { |
320 // Already resolved to a malformed type. Will throw on usage. | 324 // Already resolved to a malformed or malbounded type. Will throw on usage. |
321 ASSERT(target.IsNull()); | 325 ASSERT(target.IsNull()); |
322 return; | 326 return; |
323 } | 327 } |
324 if (!target.IsNull()) { | 328 if (!target.IsNull()) { |
325 // Already resolved. | 329 // Already resolved. |
326 return; | 330 return; |
327 } | 331 } |
328 | 332 |
329 // Target is not resolved yet. | 333 // Target is not resolved yet. |
330 if (FLAG_trace_class_finalization) { | 334 if (FLAG_trace_class_finalization) { |
331 OS::Print("Resolving redirecting factory: %s\n", | 335 OS::Print("Resolving redirecting factory: %s\n", |
332 String::Handle(factory.name()).ToCString()); | 336 String::Handle(factory.name()).ToCString()); |
333 } | 337 } |
334 ResolveType(cls, type, kCanonicalize); | 338 ResolveType(cls, type, kCanonicalize); |
335 type ^= FinalizeType(cls, type, kCanonicalize); | 339 type ^= FinalizeType(cls, type, kCanonicalize); |
336 factory.SetRedirectionType(type); | 340 factory.SetRedirectionType(type); |
337 if (type.IsMalformed()) { | 341 if (type.IsMalformed() || type.IsMalbounded()) { |
338 ASSERT(factory.RedirectionTarget() == Function::null()); | 342 ASSERT(factory.RedirectionTarget() == Function::null()); |
339 return; | 343 return; |
340 } | 344 } |
341 ASSERT(!type.IsTypeParameter()); // Resolved in parser. | 345 ASSERT(!type.IsTypeParameter()); // Resolved in parser. |
342 if (type.IsDynamicType()) { | 346 if (type.IsDynamicType()) { |
343 // Replace the type with a malformed type and compile a throw when called. | 347 // Replace the type with a malformed type and compile a throw when called. |
344 type = NewFinalizedMalformedType( | 348 type = NewFinalizedMalformedType( |
345 Error::Handle(), // No previous error. | 349 Error::Handle(), // No previous error. |
346 Script::Handle(cls.script()), | 350 Script::Handle(cls.script()), |
347 factory.token_pos(), | 351 factory.token_pos(), |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 Type& target_type = Type::Handle(target.RedirectionType()); | 427 Type& target_type = Type::Handle(target.RedirectionType()); |
424 Function& target_target = Function::Handle(target.RedirectionTarget()); | 428 Function& target_target = Function::Handle(target.RedirectionTarget()); |
425 if (target_target.IsNull()) { | 429 if (target_target.IsNull()) { |
426 ASSERT(target_type.IsMalformed()); | 430 ASSERT(target_type.IsMalformed()); |
427 } else { | 431 } else { |
428 // 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 |
429 // type arguments of the redirection type. | 433 // type arguments of the redirection type. |
430 if (!target_type.IsInstantiated()) { | 434 if (!target_type.IsInstantiated()) { |
431 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( | 435 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( |
432 type.arguments()); | 436 type.arguments()); |
433 Error& malformed_error = Error::Handle(); | 437 Error& bound_error = Error::Handle(); |
434 target_type ^= target_type.InstantiateFrom(type_args, &malformed_error); | 438 target_type ^= target_type.InstantiateFrom(type_args, &bound_error); |
435 if (malformed_error.IsNull()) { | 439 if (bound_error.IsNull()) { |
436 target_type ^= FinalizeType(cls, target_type, kCanonicalize); | 440 target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
437 } else { | 441 } else { |
| 442 ASSERT(target_type.IsInstantiated() && type_args.IsInstantiated()); |
438 const Script& script = Script::Handle(target_class.script()); | 443 const Script& script = Script::Handle(target_class.script()); |
439 FinalizeMalformedType(malformed_error, script, target_type, | 444 FinalizeMalformedType(bound_error, script, target_type, |
440 "cannot resolve redirecting factory"); | 445 "cannot resolve redirecting factory"); |
441 target_target = Function::null(); | 446 target_target = Function::null(); |
442 } | 447 } |
443 } | 448 } |
444 } | 449 } |
445 factory.SetRedirectionType(target_type); | 450 factory.SetRedirectionType(target_type); |
446 factory.SetRedirectionTarget(target_target); | 451 factory.SetRedirectionTarget(target_target); |
447 } | 452 } |
448 | 453 |
449 | 454 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 } | 594 } |
590 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 595 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
591 const intptr_t offset = super_class.NumTypeArguments(); | 596 const intptr_t offset = super_class.NumTypeArguments(); |
592 const intptr_t super_offset = offset - num_super_type_params; | 597 const intptr_t super_offset = offset - num_super_type_params; |
593 ASSERT(offset == (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); | 598 ASSERT(offset == (cls.NumTypeArguments() - cls.NumOwnTypeArguments())); |
594 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); | 599 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); |
595 for (intptr_t i = 0; super_offset + i < num_uninitialized_arguments; i++) { | 600 for (intptr_t i = 0; super_offset + i < num_uninitialized_arguments; i++) { |
596 if (!super_type_args.IsNull()) { | 601 if (!super_type_args.IsNull()) { |
597 super_type_arg = super_type_args.TypeAt(super_offset + i); | 602 super_type_arg = super_type_args.TypeAt(super_offset + i); |
598 if (!super_type_arg.IsInstantiated()) { | 603 if (!super_type_arg.IsInstantiated()) { |
599 Error& malformed_error = Error::Handle(); | 604 Error& error = Error::Handle(); |
600 super_type_arg = super_type_arg.InstantiateFrom(arguments, | 605 super_type_arg = super_type_arg.InstantiateFrom(arguments, &error); |
601 &malformed_error); | 606 if (!error.IsNull()) { |
602 if (!malformed_error.IsNull()) { | 607 // InstantiateFrom does not report an error if the type is still |
603 if (!super_type_arg.IsInstantiated()) { | 608 // uninstantiated. Instead, it will return a new BoundedType so that |
604 // CheckTypeArgumentBounds will insert a BoundedType. | 609 // the check is postponed to run time. |
605 } else if (bound_error->IsNull()) { | 610 ASSERT(super_type_arg.IsInstantiated()); |
606 *bound_error = malformed_error.raw(); | 611 // Keep only the first bound error. |
| 612 if (bound_error->IsNull()) { |
| 613 *bound_error = error.raw(); |
607 } | 614 } |
608 } | 615 } |
609 } | 616 } |
610 if (finalization >= kCanonicalize) { | 617 if (finalization >= kCanonicalize) { |
611 super_type_arg = super_type_arg.Canonicalize(); | 618 super_type_arg = super_type_arg.Canonicalize(); |
612 } | 619 } |
613 } | 620 } |
614 arguments.SetTypeAt(super_offset + i, super_type_arg); | 621 arguments.SetTypeAt(super_offset + i, super_type_arg); |
615 } | 622 } |
616 FinalizeTypeArguments(super_class, arguments, super_offset, | 623 FinalizeTypeArguments(super_class, arguments, super_offset, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 cls_type_param = cls_type_params.TypeAt(i); | 665 cls_type_param = cls_type_params.TypeAt(i); |
659 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); | 666 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); |
660 ASSERT(type_param.IsFinalized()); | 667 ASSERT(type_param.IsFinalized()); |
661 declared_bound = type_param.bound(); | 668 declared_bound = type_param.bound(); |
662 if (!declared_bound.IsObjectType() && !declared_bound.IsDynamicType()) { | 669 if (!declared_bound.IsObjectType() && !declared_bound.IsDynamicType()) { |
663 if (!declared_bound.IsFinalized() && !declared_bound.IsBeingFinalized()) { | 670 if (!declared_bound.IsFinalized() && !declared_bound.IsBeingFinalized()) { |
664 declared_bound = FinalizeType(cls, declared_bound, kCanonicalize); | 671 declared_bound = FinalizeType(cls, declared_bound, kCanonicalize); |
665 type_param.set_bound(declared_bound); | 672 type_param.set_bound(declared_bound); |
666 } | 673 } |
667 ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized()); | 674 ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized()); |
668 Error& malformed_error = Error::Handle(); | 675 Error& error = Error::Handle(); |
669 // Note that the bound may be malformed, in which case the bound check | 676 // Note that the bound may be malformed, in which case the bound check |
670 // will return an error and the bound check will be postponed to run time. | 677 // will return an error and the bound check will be postponed to run time. |
671 if (declared_bound.IsInstantiated()) { | 678 if (declared_bound.IsInstantiated()) { |
672 instantiated_bound = declared_bound.raw(); | 679 instantiated_bound = declared_bound.raw(); |
673 } else { | 680 } else { |
674 instantiated_bound = | 681 instantiated_bound = declared_bound.InstantiateFrom(arguments, &error); |
675 declared_bound.InstantiateFrom(arguments, &malformed_error); | |
676 } | 682 } |
677 if (!instantiated_bound.IsFinalized()) { | 683 if (!instantiated_bound.IsFinalized()) { |
678 // The bound refers to type parameters, creating a cycle; postpone | 684 // The bound refers to type parameters, creating a cycle; postpone |
679 // bound check to run time, when the bound will be finalized. | 685 // bound check to run time, when the bound will be finalized. |
680 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the | 686 // The bound may not necessarily be 'IsBeingFinalized' yet, as is the |
681 // case with a pair of type parameters of the same class referring to | 687 // case with a pair of type parameters of the same class referring to |
682 // each other via their bounds. | 688 // each other via their bounds. |
683 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); | 689 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); |
684 arguments.SetTypeAt(offset + i, type_arg); | 690 arguments.SetTypeAt(offset + i, type_arg); |
685 continue; | 691 continue; |
686 } | 692 } |
687 // TODO(regis): We could simplify this code if we could differentiate | |
688 // between a failed bound check and a bound check that is undecidable at | |
689 // compile time. | |
690 // Shortcut the special case where we check a type parameter against its | 693 // Shortcut the special case where we check a type parameter against its |
691 // declared upper bound. | 694 // declared upper bound. |
692 bool below_bound = true; | 695 if (error.IsNull() && |
693 if (malformed_error.IsNull() && | 696 !(type_arg.Equals(type_param) && |
694 (!type_arg.Equals(type_param) || | 697 instantiated_bound.Equals(declared_bound))) { |
695 !instantiated_bound.Equals(declared_bound))) { | 698 if (!type_param.CheckBound(type_arg, instantiated_bound, &error) && |
696 // Pass NULL to prevent expensive and unnecessary error formatting in | 699 error.IsNull()) { |
697 // the case the bound check is postponed to run time. | 700 // The bound cannot be checked at compile time; postpone to run time. |
698 below_bound = type_param.CheckBound(type_arg, instantiated_bound, NULL); | |
699 } | |
700 if (!malformed_error.IsNull() || !below_bound) { | |
701 if (!type_arg.IsInstantiated() || | |
702 !instantiated_bound.IsInstantiated()) { | |
703 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); | 701 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); |
704 arguments.SetTypeAt(offset + i, type_arg); | 702 arguments.SetTypeAt(offset + i, type_arg); |
705 } else if (bound_error->IsNull()) { | |
706 if (malformed_error.IsNull()) { | |
707 // Call CheckBound again to format error message. | |
708 type_param.CheckBound(type_arg, | |
709 instantiated_bound, | |
710 &malformed_error); | |
711 } | |
712 ASSERT(!malformed_error.IsNull()); | |
713 *bound_error = malformed_error.raw(); | |
714 } | 703 } |
715 } | 704 } |
| 705 if (!error.IsNull() && bound_error->IsNull()) { |
| 706 *bound_error = error.raw(); |
| 707 } |
716 } | 708 } |
717 } | 709 } |
718 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 710 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
719 if (!super_type.IsNull()) { | 711 if (!super_type.IsNull()) { |
720 const Class& super_class = Class::Handle(super_type.type_class()); | 712 const Class& super_class = Class::Handle(super_type.type_class()); |
721 CheckTypeArgumentBounds(super_class, arguments, bound_error); | 713 CheckTypeArgumentBounds(super_class, arguments, bound_error); |
722 } | 714 } |
723 } | 715 } |
724 | 716 |
725 | 717 |
(...skipping 2032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2758 expected_name ^= String::New("_offset"); | 2750 expected_name ^= String::New("_offset"); |
2759 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2751 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
2760 field ^= fields_array.At(2); | 2752 field ^= fields_array.At(2); |
2761 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2753 ASSERT(field.Offset() == TypedDataView::length_offset()); |
2762 name ^= field.name(); | 2754 name ^= field.name(); |
2763 ASSERT(name.Equals("length")); | 2755 ASSERT(name.Equals("length")); |
2764 #endif | 2756 #endif |
2765 } | 2757 } |
2766 | 2758 |
2767 } // namespace dart | 2759 } // namespace dart |
OLD | NEW |