| 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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 factory.SetRedirectionType(type); | 330 factory.SetRedirectionType(type); |
| 331 if (type.IsMalformed()) { | 331 if (type.IsMalformed()) { |
| 332 ASSERT(factory.RedirectionTarget() == Function::null()); | 332 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 333 return; | 333 return; |
| 334 } | 334 } |
| 335 ASSERT(!type.IsTypeParameter()); // Resolved in parser. | 335 ASSERT(!type.IsTypeParameter()); // Resolved in parser. |
| 336 if (type.IsDynamicType()) { | 336 if (type.IsDynamicType()) { |
| 337 // Replace the type with a malformed type and compile a throw when called. | 337 // Replace the type with a malformed type and compile a throw when called. |
| 338 type = NewFinalizedMalformedType( | 338 type = NewFinalizedMalformedType( |
| 339 Error::Handle(), // No previous error. | 339 Error::Handle(), // No previous error. |
| 340 cls, | 340 Script::Handle(cls.script()), |
| 341 factory.token_pos(), | 341 factory.token_pos(), |
| 342 "factory may not redirect to 'dynamic'"); | 342 "factory may not redirect to 'dynamic'"); |
| 343 factory.SetRedirectionType(type); | 343 factory.SetRedirectionType(type); |
| 344 ASSERT(factory.RedirectionTarget() == Function::null()); | 344 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 345 return; | 345 return; |
| 346 } | 346 } |
| 347 const Class& target_class = Class::Handle(type.type_class()); | 347 const Class& target_class = Class::Handle(type.type_class()); |
| 348 String& target_class_name = String::Handle(target_class.Name()); | 348 String& target_class_name = String::Handle(target_class.Name()); |
| 349 String& target_name = String::Handle( | 349 String& target_name = String::Handle( |
| 350 String::Concat(target_class_name, Symbols::Dot())); | 350 String::Concat(target_class_name, Symbols::Dot())); |
| 351 const String& identifier = String::Handle(factory.RedirectionIdentifier()); | 351 const String& identifier = String::Handle(factory.RedirectionIdentifier()); |
| 352 if (!identifier.IsNull()) { | 352 if (!identifier.IsNull()) { |
| 353 target_name = String::Concat(target_name, identifier); | 353 target_name = String::Concat(target_name, identifier); |
| 354 } | 354 } |
| 355 | 355 |
| 356 // Verify that the target constructor of the redirection exists. | 356 // Verify that the target constructor of the redirection exists. |
| 357 target = target_class.LookupConstructor(target_name); | 357 target = target_class.LookupConstructor(target_name); |
| 358 if (target.IsNull()) { | 358 if (target.IsNull()) { |
| 359 target = target_class.LookupFactory(target_name); | 359 target = target_class.LookupFactory(target_name); |
| 360 } | 360 } |
| 361 if (target.IsNull()) { | 361 if (target.IsNull()) { |
| 362 const String& user_visible_target_name = | 362 const String& user_visible_target_name = |
| 363 identifier.IsNull() ? target_class_name : target_name; | 363 identifier.IsNull() ? target_class_name : target_name; |
| 364 // Replace the type with a malformed type and compile a throw when called. | 364 // Replace the type with a malformed type and compile a throw when called. |
| 365 type = NewFinalizedMalformedType( | 365 type = NewFinalizedMalformedType( |
| 366 Error::Handle(), // No previous error. | 366 Error::Handle(), // No previous error. |
| 367 cls, | 367 Script::Handle(target_class.script()), |
| 368 factory.token_pos(), | 368 factory.token_pos(), |
| 369 "class '%s' has no constructor or factory named '%s'", | 369 "class '%s' has no constructor or factory named '%s'", |
| 370 target_class_name.ToCString(), | 370 target_class_name.ToCString(), |
| 371 user_visible_target_name.ToCString()); | 371 user_visible_target_name.ToCString()); |
| 372 factory.SetRedirectionType(type); | 372 factory.SetRedirectionType(type); |
| 373 ASSERT(factory.RedirectionTarget() == Function::null()); | 373 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 374 return; | 374 return; |
| 375 } | 375 } |
| 376 | 376 |
| 377 if (FLAG_error_on_bad_override) { | 377 if (FLAG_error_on_bad_override) { |
| 378 // Verify that the target is compatible with the redirecting factory. | 378 // Verify that the target is compatible with the redirecting factory. |
| 379 Error& error = Error::Handle(); | 379 Error& error = Error::Handle(); |
| 380 if (!target.HasCompatibleParametersWith(factory, &error)) { | 380 if (!target.HasCompatibleParametersWith(factory, &error)) { |
| 381 const Script& script = Script::Handle(target_class.script()); |
| 381 type = NewFinalizedMalformedType( | 382 type = NewFinalizedMalformedType( |
| 382 error, target_class, target.token_pos(), | 383 error, script, target.token_pos(), |
| 383 "constructor '%s' has incompatible parameters with " | 384 "constructor '%s' has incompatible parameters with " |
| 384 "redirecting factory '%s'", | 385 "redirecting factory '%s'", |
| 385 String::Handle(target.name()).ToCString(), | 386 String::Handle(target.name()).ToCString(), |
| 386 String::Handle(factory.name()).ToCString()); | 387 String::Handle(factory.name()).ToCString()); |
| 387 factory.SetRedirectionType(type); | 388 factory.SetRedirectionType(type); |
| 388 ASSERT(factory.RedirectionTarget() == Function::null()); | 389 ASSERT(factory.RedirectionTarget() == Function::null()); |
| 389 return; | 390 return; |
| 390 } | 391 } |
| 391 } | 392 } |
| 392 | 393 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 421 // If the target type refers to type parameters, substitute them with the | 422 // If the target type refers to type parameters, substitute them with the |
| 422 // type arguments of the redirection type. | 423 // type arguments of the redirection type. |
| 423 if (!target_type.IsInstantiated()) { | 424 if (!target_type.IsInstantiated()) { |
| 424 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( | 425 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( |
| 425 type.arguments()); | 426 type.arguments()); |
| 426 Error& malformed_error = Error::Handle(); | 427 Error& malformed_error = Error::Handle(); |
| 427 target_type ^= target_type.InstantiateFrom(type_args, &malformed_error); | 428 target_type ^= target_type.InstantiateFrom(type_args, &malformed_error); |
| 428 if (malformed_error.IsNull()) { | 429 if (malformed_error.IsNull()) { |
| 429 target_type ^= FinalizeType(cls, target_type, kCanonicalize); | 430 target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
| 430 } else { | 431 } else { |
| 431 FinalizeMalformedType(malformed_error, cls, target_type, | 432 const Script& script = Script::Handle(target_class.script()); |
| 433 FinalizeMalformedType(malformed_error, script, target_type, |
| 432 "cannot resolve redirecting factory"); | 434 "cannot resolve redirecting factory"); |
| 433 target_target = Function::null(); | 435 target_target = Function::null(); |
| 434 } | 436 } |
| 435 } | 437 } |
| 436 } | 438 } |
| 437 factory.SetRedirectionType(target_type); | 439 factory.SetRedirectionType(target_type); |
| 438 factory.SetRedirectionTarget(target_target); | 440 factory.SetRedirectionTarget(target_target); |
| 439 } | 441 } |
| 440 | 442 |
| 441 | 443 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 464 Class::Handle(ResolveClass(cls, unresolved_class)); | 466 Class::Handle(ResolveClass(cls, unresolved_class)); |
| 465 | 467 |
| 466 // Replace unresolved class with resolved type class. | 468 // Replace unresolved class with resolved type class. |
| 467 const Type& parameterized_type = Type::Cast(type); | 469 const Type& parameterized_type = Type::Cast(type); |
| 468 if (type_class.IsNull()) { | 470 if (type_class.IsNull()) { |
| 469 if ((finalization == kCanonicalizeWellFormed) || | 471 if ((finalization == kCanonicalizeWellFormed) || |
| 470 FLAG_error_on_bad_type) { | 472 FLAG_error_on_bad_type) { |
| 471 // The type class could not be resolved. The type is malformed. | 473 // The type class could not be resolved. The type is malformed. |
| 472 FinalizeMalformedType( | 474 FinalizeMalformedType( |
| 473 Error::Handle(), // No previous error. | 475 Error::Handle(), // No previous error. |
| 474 cls, | 476 Script::Handle(cls.script()), |
| 475 parameterized_type, | 477 parameterized_type, |
| 476 "cannot resolve class '%s' from '%s'", | 478 "cannot resolve class '%s' from '%s'", |
| 477 String::Handle(unresolved_class.Name()).ToCString(), | 479 String::Handle(unresolved_class.Name()).ToCString(), |
| 478 String::Handle(cls.Name()).ToCString()); | 480 String::Handle(cls.Name()).ToCString()); |
| 479 } else { | 481 } else { |
| 480 // Map the malformed type to dynamic and ignore type arguments. | 482 // Map the malformed type to dynamic and ignore type arguments. |
| 481 parameterized_type.set_type_class(Class::Handle( | 483 parameterized_type.set_type_class(Class::Handle( |
| 482 Object::dynamic_class())); | 484 Object::dynamic_class())); |
| 483 parameterized_type.set_arguments( | 485 parameterized_type.set_arguments( |
| 484 Object::null_abstract_type_arguments()); | 486 Object::null_abstract_type_arguments()); |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 } | 901 } |
| 900 | 902 |
| 901 // If a bound error occurred, return a BoundedType with a malformed bound. | 903 // If a bound error occurred, return a BoundedType with a malformed bound. |
| 902 // The malformed bound will be ignored in production mode. | 904 // The malformed bound will be ignored in production mode. |
| 903 if (!bound_error.IsNull()) { | 905 if (!bound_error.IsNull()) { |
| 904 // No compile-time error during finalization. | 906 // No compile-time error during finalization. |
| 905 const String& parameterized_type_name = String::Handle( | 907 const String& parameterized_type_name = String::Handle( |
| 906 parameterized_type.UserVisibleName()); | 908 parameterized_type.UserVisibleName()); |
| 907 const Type& malformed_bound = Type::Handle( | 909 const Type& malformed_bound = Type::Handle( |
| 908 NewFinalizedMalformedType(bound_error, | 910 NewFinalizedMalformedType(bound_error, |
| 909 cls, | 911 Script::Handle(cls.script()), |
| 910 parameterized_type.token_pos(), | 912 parameterized_type.token_pos(), |
| 911 "type '%s' has an out of bound type argument", | 913 "type '%s' has an out of bound type argument", |
| 912 parameterized_type_name.ToCString())); | 914 parameterized_type_name.ToCString())); |
| 913 return BoundedType::New(parameterized_type, | 915 return BoundedType::New(parameterized_type, |
| 914 malformed_bound, | 916 malformed_bound, |
| 915 TypeParameter::Handle()); | 917 TypeParameter::Handle()); |
| 916 } | 918 } |
| 917 | 919 |
| 918 if (finalization >= kCanonicalize) { | 920 if (finalization >= kCanonicalize) { |
| 919 return parameterized_type.Canonicalize(); | 921 return parameterized_type.Canonicalize(); |
| (...skipping 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 Field& field = Field::Handle(); | 2441 Field& field = Field::Handle(); |
| 2440 len = fields_array.Length(); | 2442 len = fields_array.Length(); |
| 2441 for (intptr_t i = 0; i < len; i++) { | 2443 for (intptr_t i = 0; i < len; i++) { |
| 2442 field ^= fields_array.At(i); | 2444 field ^= fields_array.At(i); |
| 2443 OS::Print(" %s\n", field.ToCString()); | 2445 OS::Print(" %s\n", field.ToCString()); |
| 2444 } | 2446 } |
| 2445 } | 2447 } |
| 2446 | 2448 |
| 2447 // Either report an error or mark the type as malformed. | 2449 // Either report an error or mark the type as malformed. |
| 2448 void ClassFinalizer::ReportMalformedType(const Error& prev_error, | 2450 void ClassFinalizer::ReportMalformedType(const Error& prev_error, |
| 2449 const Class& cls, | 2451 const Script& script, |
| 2450 const Type& type, | 2452 const Type& type, |
| 2451 const char* format, | 2453 const char* format, |
| 2452 va_list args) { | 2454 va_list args) { |
| 2453 LanguageError& error = LanguageError::Handle(); | 2455 LanguageError& error = LanguageError::Handle(); |
| 2454 const Script& script = Script::Handle(cls.script()); | |
| 2455 if (prev_error.IsNull()) { | 2456 if (prev_error.IsNull()) { |
| 2456 error ^= Parser::FormatError( | 2457 error ^= Parser::FormatError( |
| 2457 script, type.token_pos(), "Error", format, args); | 2458 script, type.token_pos(), "Error", format, args); |
| 2458 } else { | 2459 } else { |
| 2459 error ^= Parser::FormatErrorWithAppend( | 2460 error ^= Parser::FormatErrorWithAppend( |
| 2460 prev_error, script, type.token_pos(), "Error", format, args); | 2461 prev_error, script, type.token_pos(), "Error", format, args); |
| 2461 } | 2462 } |
| 2462 if (FLAG_error_on_bad_type) { | 2463 if (FLAG_error_on_bad_type) { |
| 2463 ReportError(error); | 2464 ReportError(error); |
| 2464 } | 2465 } |
| 2465 type.set_malformed_error(error); | 2466 type.set_malformed_error(error); |
| 2466 // Make the type raw, since it may not be possible to | 2467 // Make the type raw, since it may not be possible to |
| 2467 // properly finalize its type arguments. | 2468 // properly finalize its type arguments. |
| 2468 type.set_type_class(Class::Handle(Object::dynamic_class())); | 2469 type.set_type_class(Class::Handle(Object::dynamic_class())); |
| 2469 type.set_arguments(Object::null_abstract_type_arguments()); | 2470 type.set_arguments(Object::null_abstract_type_arguments()); |
| 2470 if (!type.IsFinalized()) { | 2471 if (!type.IsFinalized()) { |
| 2471 type.SetIsFinalized(); | 2472 type.SetIsFinalized(); |
| 2472 // Do not canonicalize malformed types, since they may not be resolved. | 2473 // Do not canonicalize malformed types, since they may not be resolved. |
| 2473 } else { | 2474 } else { |
| 2474 // The only case where the malformed type was already finalized is when its | 2475 // The only case where the malformed type was already finalized is when its |
| 2475 // type arguments are not within bounds. In that case, we have a prev_error. | 2476 // type arguments are not within bounds. In that case, we have a prev_error. |
| 2476 ASSERT(!prev_error.IsNull()); | 2477 ASSERT(!prev_error.IsNull()); |
| 2477 } | 2478 } |
| 2478 } | 2479 } |
| 2479 | 2480 |
| 2480 | 2481 |
| 2481 RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error, | 2482 RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error, |
| 2482 const Class& cls, | 2483 const Script& script, |
| 2483 intptr_t type_pos, | 2484 intptr_t type_pos, |
| 2484 const char* format, ...) { | 2485 const char* format, ...) { |
| 2485 va_list args; | 2486 va_list args; |
| 2486 va_start(args, format); | 2487 va_start(args, format); |
| 2487 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( | 2488 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( |
| 2488 UnresolvedClass::New(LibraryPrefix::Handle(), | 2489 UnresolvedClass::New(LibraryPrefix::Handle(), |
| 2489 Symbols::Empty(), | 2490 Symbols::Empty(), |
| 2490 type_pos)); | 2491 type_pos)); |
| 2491 const Type& type = Type::Handle( | 2492 const Type& type = Type::Handle( |
| 2492 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); | 2493 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); |
| 2493 ReportMalformedType(prev_error, cls, type, format, args); | 2494 ReportMalformedType(prev_error, script, type, format, args); |
| 2494 va_end(args); | 2495 va_end(args); |
| 2495 ASSERT(type.IsMalformed()); | 2496 ASSERT(type.IsMalformed()); |
| 2496 ASSERT(type.IsFinalized()); | 2497 ASSERT(type.IsFinalized()); |
| 2497 return type.raw(); | 2498 return type.raw(); |
| 2498 } | 2499 } |
| 2499 | 2500 |
| 2500 | 2501 |
| 2501 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 2502 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
| 2502 const Class& cls, | 2503 const Script& script, |
| 2503 const Type& type, | 2504 const Type& type, |
| 2504 const char* format, ...) { | 2505 const char* format, ...) { |
| 2505 va_list args; | 2506 va_list args; |
| 2506 va_start(args, format); | 2507 va_start(args, format); |
| 2507 ReportMalformedType(prev_error, cls, type, format, args); | 2508 ReportMalformedType(prev_error, script, type, format, args); |
| 2508 va_end(args); | 2509 va_end(args); |
| 2509 } | 2510 } |
| 2510 | 2511 |
| 2511 | 2512 |
| 2512 void ClassFinalizer::ReportError(const Error& error) { | 2513 void ClassFinalizer::ReportError(const Error& error) { |
| 2513 Isolate::Current()->long_jump_base()->Jump(1, error); | 2514 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2514 UNREACHABLE(); | 2515 UNREACHABLE(); |
| 2515 } | 2516 } |
| 2516 | 2517 |
| 2517 | 2518 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2596 expected_name ^= String::New("_offset"); | 2597 expected_name ^= String::New("_offset"); |
| 2597 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2598 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2598 field ^= fields_array.At(2); | 2599 field ^= fields_array.At(2); |
| 2599 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2600 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2600 name ^= field.name(); | 2601 name ^= field.name(); |
| 2601 ASSERT(name.Equals("length")); | 2602 ASSERT(name.Equals("length")); |
| 2602 #endif | 2603 #endif |
| 2603 } | 2604 } |
| 2604 | 2605 |
| 2605 } // namespace dart | 2606 } // namespace dart |
| OLD | NEW |