| 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/code_generator.h" | 7 #include "vm/code_generator.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 1389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 mixin_app_class.super_type()); | 1400 mixin_app_class.super_type()); |
| 1401 ASSERT(super_type.IsResolved()); | 1401 ASSERT(super_type.IsResolved()); |
| 1402 const Class& super_class = Class::Handle(isolate, super_type.type_class()); | 1402 const Class& super_class = Class::Handle(isolate, super_type.type_class()); |
| 1403 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 1403 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
| 1404 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); | 1404 const Type& mixin_type = Type::Handle(isolate, mixin_app_class.mixin()); |
| 1405 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); | 1405 const Class& mixin_class = Class::Handle(isolate, mixin_type.type_class()); |
| 1406 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); | 1406 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); |
| 1407 // The mixin class cannot be Object and this was checked earlier. | 1407 // The mixin class cannot be Object and this was checked earlier. |
| 1408 ASSERT(!mixin_class.IsObjectClass()); | 1408 ASSERT(!mixin_class.IsObjectClass()); |
| 1409 | 1409 |
| 1410 // Add the mixin type to the interfaces that the mixin application | 1410 // The mixin type (in raw form) should have been added to the interfaces |
| 1411 // class implements. This is necessary so that type tests work. | 1411 // implemented by the mixin application class. This is necessary so that cycle |
| 1412 const Array& interfaces = Array::Handle(isolate, Array::New(1)); | 1412 // check works at compile time (type arguments are ignored) and so that |
| 1413 interfaces.SetAt(0, mixin_type); | 1413 // type tests work at runtime (by then, type arguments will have been set, see |
| 1414 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); | 1414 // below). |
| 1415 mixin_app_class.set_interfaces(interfaces); | 1415 ASSERT(mixin_app_class.interfaces() != Object::empty_array().raw()); |
| 1416 | 1416 |
| 1417 // If both the super type and the mixin type are non generic, the mixin | 1417 // If both the super type and the mixin type are non generic, the mixin |
| 1418 // application class is non generic as well and we can skip type parameter | 1418 // application class is non generic as well and we can skip type parameter |
| 1419 // cloning. | 1419 // cloning. |
| 1420 bool has_uninstantiated_bounds = false; | 1420 bool has_uninstantiated_bounds = false; |
| 1421 if ((num_super_type_params + num_mixin_type_params) > 0) { | 1421 if ((num_super_type_params + num_mixin_type_params) > 0) { |
| 1422 // If the last ampersand in the name of the mixin application class is | 1422 // If the last ampersand in the name of the mixin application class is |
| 1423 // doubled, the same type parameters can propagate the type arguments to | 1423 // doubled, the same type parameters can propagate the type arguments to |
| 1424 // the super type and to the mixin type. | 1424 // the super type and to the mixin type. |
| 1425 bool share_type_params = false; | 1425 bool share_type_params = false; |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1668 | 1668 |
| 1669 // The mixin type and interface type must also be set before calling | 1669 // The mixin type and interface type must also be set before calling |
| 1670 // CloneMixinAppTypeParameters. | 1670 // CloneMixinAppTypeParameters. |
| 1671 // After FinalizeTypesInClass, they will refer to the type parameters of | 1671 // After FinalizeTypesInClass, they will refer to the type parameters of |
| 1672 // the mixin class typedef. | 1672 // the mixin class typedef. |
| 1673 const Type& generic_mixin_type = Type::Handle(isolate, | 1673 const Type& generic_mixin_type = Type::Handle(isolate, |
| 1674 Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()), | 1674 Type::New(Class::Handle(isolate, aliased_mixin_type.type_class()), |
| 1675 Object::null_type_arguments(), | 1675 Object::null_type_arguments(), |
| 1676 aliased_mixin_type.token_pos())); | 1676 aliased_mixin_type.token_pos())); |
| 1677 inserted_class.set_mixin(generic_mixin_type); | 1677 inserted_class.set_mixin(generic_mixin_type); |
| 1678 // The interface will be set in CloneMixinAppTypeParameters. | 1678 // Add the mixin type to the list of interfaces that the mixin application |
| 1679 // class implements. This is necessary so that cycle check work at |
| 1680 // compile time (type arguments are ignored by that check). |
| 1681 const Array& interfaces = Array::Handle(Array::New(1)); |
| 1682 interfaces.SetAt(0, generic_mixin_type); |
| 1683 ASSERT(inserted_class.interfaces() == Object::empty_array().raw()); |
| 1684 inserted_class.set_interfaces(interfaces); |
| 1685 // The type arguments of the interface, if any, will be set in |
| 1686 // CloneMixinAppTypeParameters, which is called indirectly from |
| 1687 // FinalizeTypesInClass below. |
| 1679 } | 1688 } |
| 1680 | 1689 |
| 1681 // Finalize the types and call CloneMixinAppTypeParameters. | 1690 // Finalize the types and call CloneMixinAppTypeParameters. |
| 1682 FinalizeTypesInClass(inserted_class); | 1691 FinalizeTypesInClass(inserted_class); |
| 1683 | 1692 |
| 1684 // The super type of this mixin application class must point to the | 1693 // The super type of this mixin application class must point to the |
| 1685 // inserted class. The super type arguments are the concatenation of the | 1694 // inserted class. The super type arguments are the concatenation of the |
| 1686 // old super type arguments (propagating type arguments to the super class) | 1695 // old super type arguments (propagating type arguments to the super class) |
| 1687 // with new type arguments providing type arguments to the mixin. | 1696 // with new type arguments providing type arguments to the mixin. |
| 1688 // The appended type arguments are those of the super type of the mixin | 1697 // The appended type arguments are those of the super type of the mixin |
| (...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2446 mixin_app_class_name = Symbols::New(mixin_app_class_name); | 2455 mixin_app_class_name = Symbols::New(mixin_app_class_name); |
| 2447 mixin_app_class = Class::New(mixin_app_class_name, | 2456 mixin_app_class = Class::New(mixin_app_class_name, |
| 2448 script, | 2457 script, |
| 2449 mixin_type.token_pos()); | 2458 mixin_type.token_pos()); |
| 2450 mixin_app_class.set_super_type(mixin_super_type); | 2459 mixin_app_class.set_super_type(mixin_super_type); |
| 2451 mixin_type_class = mixin_type.type_class(); | 2460 mixin_type_class = mixin_type.type_class(); |
| 2452 generic_mixin_type = Type::New(mixin_type_class, | 2461 generic_mixin_type = Type::New(mixin_type_class, |
| 2453 Object::null_type_arguments(), | 2462 Object::null_type_arguments(), |
| 2454 mixin_type.token_pos()); | 2463 mixin_type.token_pos()); |
| 2455 mixin_app_class.set_mixin(generic_mixin_type); | 2464 mixin_app_class.set_mixin(generic_mixin_type); |
| 2465 // Add the mixin type to the list of interfaces that the mixin application |
| 2466 // class implements. This is necessary so that cycle check work at |
| 2467 // compile time (type arguments are ignored by that check). |
| 2468 const Array& interfaces = Array::Handle(Array::New(1)); |
| 2469 interfaces.SetAt(0, generic_mixin_type); |
| 2470 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); |
| 2471 mixin_app_class.set_interfaces(interfaces); |
| 2456 mixin_app_class.set_is_synthesized_class(); | 2472 mixin_app_class.set_is_synthesized_class(); |
| 2457 library.AddClass(mixin_app_class); | 2473 library.AddClass(mixin_app_class); |
| 2458 | 2474 |
| 2459 // No need to add the new class to pending_classes, since it will be | 2475 // No need to add the new class to pending_classes, since it will be |
| 2460 // processed via the super_type chain of a pending class. | 2476 // processed via the super_type chain of a pending class. |
| 2461 | 2477 |
| 2462 if (FLAG_trace_class_finalization) { | 2478 if (FLAG_trace_class_finalization) { |
| 2463 OS::Print("Creating mixin application %s\n", | 2479 OS::Print("Creating mixin application %s\n", |
| 2464 mixin_app_class.ToCString()); | 2480 mixin_app_class.ToCString()); |
| 2465 } | 2481 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2494 | 2510 |
| 2495 // Recursively walks the graph of explicitly declared super type and | 2511 // Recursively walks the graph of explicitly declared super type and |
| 2496 // interfaces, resolving unresolved super types and interfaces. | 2512 // interfaces, resolving unresolved super types and interfaces. |
| 2497 // Reports an error if there is an interface reference that cannot be | 2513 // Reports an error if there is an interface reference that cannot be |
| 2498 // resolved, or if there is a cycle in the graph. We detect cycles by | 2514 // resolved, or if there is a cycle in the graph. We detect cycles by |
| 2499 // remembering interfaces we've visited in each path through the | 2515 // remembering interfaces we've visited in each path through the |
| 2500 // graph. If we visit an interface a second time on a given path, | 2516 // graph. If we visit an interface a second time on a given path, |
| 2501 // we found a loop. | 2517 // we found a loop. |
| 2502 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 2518 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
| 2503 const Class& cls, GrowableArray<intptr_t>* visited) { | 2519 const Class& cls, GrowableArray<intptr_t>* visited) { |
| 2520 if (cls.is_cycle_free()) { |
| 2521 return; |
| 2522 } |
| 2504 ASSERT(visited != NULL); | 2523 ASSERT(visited != NULL); |
| 2505 if (FLAG_trace_class_finalization) { | 2524 if (FLAG_trace_class_finalization) { |
| 2506 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); | 2525 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); |
| 2507 } | 2526 } |
| 2508 const intptr_t cls_index = cls.id(); | 2527 const intptr_t cls_index = cls.id(); |
| 2509 for (intptr_t i = 0; i < visited->length(); i++) { | 2528 for (intptr_t i = 0; i < visited->length(); i++) { |
| 2510 if ((*visited)[i] == cls_index) { | 2529 if ((*visited)[i] == cls_index) { |
| 2511 // We have already visited class 'cls'. We found a cycle. | 2530 // We have already visited class 'cls'. We found a cycle. |
| 2512 const String& class_name = String::Handle(cls.Name()); | 2531 const String& class_name = String::Handle(cls.Name()); |
| 2513 const Script& script = Script::Handle(cls.script()); | 2532 const Script& script = Script::Handle(cls.script()); |
| 2514 ReportError(Error::Handle(), // No previous error. | 2533 ReportError(Error::Handle(), // No previous error. |
| 2515 script, cls.token_pos(), | 2534 script, cls.token_pos(), |
| 2516 "cyclic reference found for class '%s'", | 2535 "cyclic reference found for class '%s'", |
| 2517 class_name.ToCString()); | 2536 class_name.ToCString()); |
| 2518 } | 2537 } |
| 2519 } | 2538 } |
| 2520 | 2539 |
| 2521 // If the class/interface has no explicit super class/interfaces | 2540 // If the class/interface has no explicit super class/interfaces |
| 2522 // and is not a mixin application, we are done. | 2541 // and is not a mixin application, we are done. |
| 2523 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 2542 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 2524 Array& super_interfaces = Array::Handle(cls.interfaces()); | 2543 Array& super_interfaces = Array::Handle(cls.interfaces()); |
| 2525 if ((super_type.IsNull() || super_type.IsObjectType()) && | 2544 if ((super_type.IsNull() || super_type.IsObjectType()) && |
| 2526 (super_interfaces.Length() == 0)) { | 2545 (super_interfaces.Length() == 0)) { |
| 2546 cls.set_is_cycle_free(); |
| 2527 return; | 2547 return; |
| 2528 } | 2548 } |
| 2529 | 2549 |
| 2530 if (super_type.IsMixinAppType()) { | 2550 if (super_type.IsMixinAppType()) { |
| 2551 // For the cycle check below to work, ResolveMixinAppType needs to set |
| 2552 // the mixin interfaces in the super classes, even if only in raw form. |
| 2553 // It is indeed too early to set the correct type arguments, which is not |
| 2554 // a problem since they are ignored in the cycle check. |
| 2531 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type); | 2555 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type); |
| 2532 super_type = ResolveMixinAppType(cls, mixin_app_type); | 2556 super_type = ResolveMixinAppType(cls, mixin_app_type); |
| 2533 cls.set_super_type(super_type); | 2557 cls.set_super_type(super_type); |
| 2534 } | 2558 } |
| 2535 | 2559 |
| 2536 // If cls belongs to core lib, restrictions about allowed interfaces | 2560 // If cls belongs to core lib, restrictions about allowed interfaces |
| 2537 // are lifted. | 2561 // are lifted. |
| 2538 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); | 2562 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
| 2539 | 2563 |
| 2540 // Resolve and check the super type and interfaces of cls. | 2564 // Resolve and check the super type and interfaces of cls. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2664 String::Handle(cls.Name()).ToCString(), | 2688 String::Handle(cls.Name()).ToCString(), |
| 2665 interface_name.ToCString()); | 2689 interface_name.ToCString()); |
| 2666 } | 2690 } |
| 2667 } | 2691 } |
| 2668 } | 2692 } |
| 2669 interface_class.set_is_implemented(); | 2693 interface_class.set_is_implemented(); |
| 2670 // Now resolve the super interfaces. | 2694 // Now resolve the super interfaces. |
| 2671 ResolveSuperTypeAndInterfaces(interface_class, visited); | 2695 ResolveSuperTypeAndInterfaces(interface_class, visited); |
| 2672 } | 2696 } |
| 2673 visited->RemoveLast(); | 2697 visited->RemoveLast(); |
| 2698 cls.set_is_cycle_free(); |
| 2674 } | 2699 } |
| 2675 | 2700 |
| 2676 | 2701 |
| 2677 // A class is marked as constant if it has one constant constructor. | 2702 // A class is marked as constant if it has one constant constructor. |
| 2678 // A constant class can only have final instance fields. | 2703 // A constant class can only have final instance fields. |
| 2679 // Note: we must check for cycles before checking for const properties. | 2704 // Note: we must check for cycles before checking for const properties. |
| 2680 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { | 2705 void ClassFinalizer::CheckForLegalConstClass(const Class& cls) { |
| 2681 ASSERT(cls.is_const()); | 2706 ASSERT(cls.is_const()); |
| 2682 const Array& fields_array = Array::Handle(cls.fields()); | 2707 const Array& fields_array = Array::Handle(cls.fields()); |
| 2683 intptr_t len = fields_array.Length(); | 2708 intptr_t len = fields_array.Length(); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 expected_name ^= String::New("_offset"); | 2927 expected_name ^= String::New("_offset"); |
| 2903 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2928 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2904 field ^= fields_array.At(2); | 2929 field ^= fields_array.At(2); |
| 2905 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2930 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2906 name ^= field.name(); | 2931 name ^= field.name(); |
| 2907 ASSERT(name.Equals("length")); | 2932 ASSERT(name.Equals("length")); |
| 2908 #endif | 2933 #endif |
| 2909 } | 2934 } |
| 2910 | 2935 |
| 2911 } // namespace dart | 2936 } // namespace dart |
| OLD | NEW |