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

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

Issue 162163002: Make cycle checking of super interfaces linear instead of quadratic by marking (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 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.h » ('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/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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698