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 |