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

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

Issue 10996002: Fix snapshot reading of canonicalized types. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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 | « no previous file | runtime/vm/object.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 402
403 void ClassFinalizer::ResolveRedirectingFactoryTarget( 403 void ClassFinalizer::ResolveRedirectingFactoryTarget(
404 const Class& cls, 404 const Class& cls,
405 const Function& factory, 405 const Function& factory,
406 const GrowableObjectArray& visited_factories) { 406 const GrowableObjectArray& visited_factories) {
407 ASSERT(factory.IsRedirectingFactory()); 407 ASSERT(factory.IsRedirectingFactory());
408 408
409 // Check for redirection cycle. 409 // Check for redirection cycle.
410 for (int i = 0; i < visited_factories.Length(); i++) { 410 for (int i = 0; i < visited_factories.Length(); i++) {
411 if (visited_factories.At(i) == factory.raw()) { 411 if (visited_factories.At(i) == factory.raw()) {
412 // TODO(regis): Throw or report error? 412 // A redirection cycle is reported as a compile-time error.
413 const Script& script = Script::Handle(cls.script()); 413 const Script& script = Script::Handle(cls.script());
414 ReportError(script, factory.token_pos(), 414 ReportError(script, factory.token_pos(),
415 "factory '%s' illegally redirects to itself", 415 "factory '%s' illegally redirects to itself",
416 String::Handle(factory.name()).ToCString()); 416 String::Handle(factory.name()).ToCString());
417 } 417 }
418 } 418 }
419 visited_factories.Add(factory); 419 visited_factories.Add(factory);
420 420
421 // Check if target is already resolved. 421 // Check if target is already resolved.
422 Type& type = Type::Handle(factory.RedirectionType()); 422 Type& type = Type::Handle(factory.RedirectionType());
(...skipping 10 matching lines...) Expand all
433 433
434 // Target is not resolved yet. 434 // Target is not resolved yet.
435 if (FLAG_trace_class_finalization) { 435 if (FLAG_trace_class_finalization) {
436 OS::Print("Resolving redirecting factory: %s\n", 436 OS::Print("Resolving redirecting factory: %s\n",
437 String::Handle(factory.name()).ToCString()); 437 String::Handle(factory.name()).ToCString());
438 } 438 }
439 ResolveType(cls, type, kCanonicalize); 439 ResolveType(cls, type, kCanonicalize);
440 type ^= FinalizeType(cls, type, kCanonicalize); 440 type ^= FinalizeType(cls, type, kCanonicalize);
441 factory.SetRedirectionType(type); 441 factory.SetRedirectionType(type);
442 if (type.IsMalformed()) { 442 if (type.IsMalformed()) {
443 ASSERT(target.IsNull()); 443 ASSERT(factory.RedirectionTarget() == Function::null());
444 factory.SetRedirectionTarget(target);
445 return; 444 return;
446 } 445 }
447 const Class& target_class = Class::Handle(type.type_class()); 446 const Class& target_class = Class::Handle(type.type_class());
448 String& target_class_name = String::Handle(target_class.Name()); 447 String& target_class_name = String::Handle(target_class.Name());
449 const String& period = String::Handle(Symbols::Dot()); 448 const String& period = String::Handle(Symbols::Dot());
450 String& target_name = String::Handle( 449 String& target_name = String::Handle(
451 String::Concat(target_class_name, period)); 450 String::Concat(target_class_name, period));
452 const String& identifier = String::Handle(factory.RedirectionIdentifier()); 451 const String& identifier = String::Handle(factory.RedirectionIdentifier());
453 if (!identifier.IsNull()) { 452 if (!identifier.IsNull()) {
454 target_name = String::Concat(target_name, identifier); 453 target_name = String::Concat(target_name, identifier);
455 } 454 }
456 455
457 // Verify that the target constructor of the redirection exists. 456 // Verify that the target constructor of the redirection exists.
458 target = target_class.LookupConstructor(target_name); 457 target = target_class.LookupConstructor(target_name);
459 if (target.IsNull()) { 458 if (target.IsNull()) {
460 target = target_class.LookupFactory(target_name); 459 target = target_class.LookupFactory(target_name);
461 } 460 }
462 if (target.IsNull()) { 461 if (target.IsNull()) {
463 const String& user_visible_target_name = 462 const String& user_visible_target_name =
464 identifier.IsNull() ? target_class_name : target_name; 463 identifier.IsNull() ? target_class_name : target_name;
465 const Script& script = Script::Handle(cls.script()); 464 // Replace the type with a malformed type and compile a throw when called.
466 // TODO(regis): Instead of reporting an error, should we replace the type 465 FinalizeMalformedType(Error::Handle(), // No previous error.
467 // with a malformed type and compile a throw? We should then also do it 466 cls, type, kCanonicalize,
468 // below for incompatible signatures. Wait for spec to stabilize. 467 "class '%s' has no constructor or factory named '%s'",
469 ReportError(script, factory.token_pos(), 468 target_class_name.ToCString(),
470 "class '%s' has no constructor or factory named '%s'", 469 user_visible_target_name.ToCString());
471 target_class_name.ToCString(), 470 factory.SetRedirectionType(type);
472 user_visible_target_name.ToCString()); 471 ASSERT(factory.RedirectionTarget() == Function::null());
472 return;
473 } 473 }
474 474
475 // Verify that the target is compatible with the redirecting factory. 475 // Verify that the target is compatible with the redirecting factory.
476 if (!target.HasCompatibleParametersWith(factory)) { 476 if (!target.HasCompatibleParametersWith(factory)) {
477 const Script& script = Script::Handle(cls.script()); 477 FinalizeMalformedType(Error::Handle(), // No previous error.
478 ReportError(script, factory.token_pos(), 478 cls, type, kCanonicalize,
479 "constructor '%s' has incompatible parameters with redirecting " 479 "constructor '%s' has incompatible parameters with "
480 "factory '%s'", 480 "redirecting factory '%s'",
481 String::Handle(target.name()).ToCString(), 481 String::Handle(target.name()).ToCString(),
482 String::Handle(factory.name()).ToCString()); 482 String::Handle(factory.name()).ToCString());
483 factory.SetRedirectionType(type);
484 ASSERT(factory.RedirectionTarget() == Function::null());
485 return;
483 } 486 }
484 487
485 // Verify that the target is const if the the redirecting factory is const. 488 // Verify that the target is const if the the redirecting factory is const.
486 if (factory.is_const() && !target.is_const()) { 489 if (factory.is_const() && !target.is_const()) {
487 const Script& script = Script::Handle(cls.script()); 490 const Script& script = Script::Handle(cls.script());
488 ReportError(script, factory.token_pos(), 491 ReportError(script, factory.token_pos(),
489 "constructor '%s' must be const as required by redirecting" 492 "constructor '%s' must be const as required by redirecting"
490 "const factory '%s'", 493 "const factory '%s'",
491 String::Handle(target.name()).ToCString(), 494 String::Handle(target.name()).ToCString(),
492 String::Handle(factory.name()).ToCString()); 495 String::Handle(factory.name()).ToCString());
493 } 496 }
494 497
495 // Update redirection data with resolved target. 498 // Update redirection data with resolved target.
496 factory.SetRedirectionTarget(target); 499 factory.SetRedirectionTarget(target);
497 factory.SetRedirectionIdentifier(String::Handle()); // Not needed anymore. 500 factory.SetRedirectionIdentifier(String::Handle()); // Not needed anymore.
498 if (!target.IsRedirectingFactory()) { 501 if (!target.IsRedirectingFactory()) {
499 return; 502 return;
500 } 503 }
501 504
502 // The target is itself a redirecting factory. Recursively resolve its own 505 // The target is itself a redirecting factory. Recursively resolve its own
503 // target and update the current redirection data to point to the end target 506 // target and update the current redirection data to point to the end target
504 // of the redirection chain. 507 // of the redirection chain.
505 ResolveRedirectingFactoryTarget(target_class, target, visited_factories); 508 ResolveRedirectingFactoryTarget(target_class, target, visited_factories);
506 Type& target_type = Type::Handle(target.RedirectionType()); 509 Type& target_type = Type::Handle(target.RedirectionType());
507 const Function& target_target = Function::Handle(target.RedirectionTarget()); 510 Function& target_target = Function::Handle(target.RedirectionTarget());
508 if (target_target.IsNull()) { 511 if (target_target.IsNull()) {
509 ASSERT(target_type.IsMalformed()); 512 ASSERT(target_type.IsMalformed());
510 } else { 513 } else {
514 // If the target type refers to type parameters, substitute them with the
515 // type arguments of the redirection type.
511 if (!target_type.IsInstantiated()) { 516 if (!target_type.IsInstantiated()) {
512 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( 517 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
513 type.arguments()); 518 type.arguments());
514 target_type ^= target_type.InstantiateFrom(type_args); 519 target_type ^= target_type.InstantiateFrom(type_args);
515 // TODO(regis): Do we need to check bounds? 520 // TODO(regis): Check bounds in checked mode.
516 target_type ^= FinalizeType(cls, target_type, kCanonicalize); 521 target_type ^= FinalizeType(cls, target_type, kCanonicalize);
522 if (target_type.IsMalformed()) {
523 target_target = Function::null();
524 }
517 } 525 }
518 } 526 }
519 factory.SetRedirectionType(target_type); 527 factory.SetRedirectionType(target_type);
520 factory.SetRedirectionTarget(target_target); 528 factory.SetRedirectionTarget(target_target);
521 } 529 }
522 530
523 531
524 void ClassFinalizer::ResolveType(const Class& cls, 532 void ClassFinalizer::ResolveType(const Class& cls,
525 const AbstractType& type, 533 const AbstractType& type,
526 FinalizationKind finalization) { 534 FinalizationKind finalization) {
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 void ClassFinalizer::ReportError(const char* format, ...) { 1540 void ClassFinalizer::ReportError(const char* format, ...) {
1533 va_list args; 1541 va_list args;
1534 va_start(args, format); 1542 va_start(args, format);
1535 const Error& error = Error::Handle( 1543 const Error& error = Error::Handle(
1536 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1544 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1537 va_end(args); 1545 va_end(args);
1538 ReportError(error); 1546 ReportError(error);
1539 } 1547 }
1540 1548
1541 } // namespace dart 1549 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698