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

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

Issue 66033006: Check type bounds of redirecting factories (issue 14699). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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/ast.h ('k') | runtime/vm/dart_api_impl.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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698