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

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

Issue 23452055: Address comments of committed change https://codereview.chromium.org/24397002/ (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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.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/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 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 // If the mixin class is a mixin application typedef class, we insert a new 1429 // If the mixin class is a mixin application typedef class, we insert a new
1430 // synthesized mixin application class in the super chain of this mixin 1430 // synthesized mixin application class in the super chain of this mixin
1431 // application class. The new class will have the aliased mixin as actual 1431 // application class. The new class will have the aliased mixin as actual
1432 // mixin. 1432 // mixin.
1433 if (mixin_class.is_mixin_typedef()) { 1433 if (mixin_class.is_mixin_typedef()) {
1434 ApplyMixinTypedef(mixin_app_class); 1434 ApplyMixinTypedef(mixin_app_class);
1435 } 1435 }
1436 } 1436 }
1437 1437
1438 1438
1439 /* Support for mixin typedef.
1440 Consider the following example:
1441
1442 class I<T> { }
1443 class J<T> { }
1444 class S<T> { }
1445 class M<T> { }
1446 typedef A<U, V> = Object with M<Map<U, V>> implements I<V>;
1447 typedef C<T, K> = S<T> with A<T, List<K>> implements J<K>;
1448
1449 Before the call to ApplyMixinTypedef, the VM has already synthesized 2 mixin
1450 application classes Object&M and S&A:
1451
1452 Object&M<T> extends Object implements M<T> { ... members of M applied here ... }
1453 A<U, V> extends Object&M<Map<U, V>> implements I<V> { }
1454
1455 S&A<T`, U, V> extends S<T`> implements A<U, V> { }
1456 C<T, K> extends S&A<T, T, List<K>> implements J<K> { }
1457
1458 In theory, class A should be an alias of Object&M instead of extending it.
1459 In practice, the additional class provides a hook for implemented interfaces
1460 (e.g. I<V>) and for type argument substitution via the super type relation (e.g.
1461 type parameter T of Object&M is substituted with Map<U, V>, U and V being the
1462 type parameters of the typedef A).
1463
1464 Similarly, class C should be an alias of S&A instead of extending it.
1465
1466 Since A is used as a mixin, it must extend Object. The fact that it extends
1467 Object&M must be hidden so that no error is wrongly reported.
1468
1469 Now, A does not have any members to be mixed into S&A, because A is a typedef.
1470 The members to be mixed in are actually those of M, and they should appear in a
1471 scope where the type parameter T is visible. The class S&A declares the type
1472 parameters of A, i.e. U and V, but not T.
1473
1474 Therefore, the call to ApplyMixinTypedef inserts another synthesized class S&A`
1475 as the superclass of S&A. The class S&A` declares a type argument T:
1476
1477 Instead of
1478 S&A<T`, U, V> extends S<T`> implements A<U, V> { }
1479
1480 We now have:
1481 S&A`<T`, T> extends S<T`> implements M<T> { ... members of M applied here ... }
1482 S&A<T`, U, V> extends S&A`<T`, Map<U, V>> implements A<U, V> { }
1483
1484 The main implementation difficulty resides in the fact that the type parameters
1485 U and V in the super type S&A`<T`, Map<U, V>> of S&A refer to the type
1486 parameters U and V of S&A, not to U and V of A. An instantiation step with
1487 a properly crafted instantiator vector takes care of the required type parameter
1488 substitution.
1489 */
1439 void ClassFinalizer::ApplyMixinTypedef(const Class& mixin_app_class) { 1490 void ClassFinalizer::ApplyMixinTypedef(const Class& mixin_app_class) {
1440 // If this mixin typedef is aliasing another mixin typedef, another class 1491 // If this mixin typedef is aliasing another mixin typedef, another class
1441 // will be inserted via recursion. No need to check here. 1492 // will be inserted via recursion. No need to check here.
1442 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); 1493 const Type& mixin_type = Type::Handle(mixin_app_class.mixin());
1443 const Class& mixin_class = Class::Handle(mixin_type.type_class()); 1494 const Class& mixin_class = Class::Handle(mixin_type.type_class());
1444 ASSERT(mixin_class.is_mixin_typedef()); 1495 ASSERT(mixin_class.is_mixin_typedef());
1445 const Class& aliased_mixin_app_class = Class::Handle( 1496 const Class& aliased_mixin_app_class = Class::Handle(
1446 mixin_class.SuperClass()); 1497 mixin_class.SuperClass());
1447 const Type& aliased_mixin_type = Type::Handle( 1498 const Type& aliased_mixin_type = Type::Handle(
1448 aliased_mixin_app_class.mixin()); 1499 aliased_mixin_app_class.mixin());
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 1620
1570 1621
1571 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class) { 1622 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class) {
1572 if (mixin_app_class.is_mixin_type_applied()) { 1623 if (mixin_app_class.is_mixin_type_applied()) {
1573 return; 1624 return;
1574 } 1625 }
1575 Type& mixin_type = Type::Handle(mixin_app_class.mixin()); 1626 Type& mixin_type = Type::Handle(mixin_app_class.mixin());
1576 ASSERT(!mixin_type.IsNull()); 1627 ASSERT(!mixin_type.IsNull());
1577 ASSERT(mixin_type.HasResolvedTypeClass()); 1628 ASSERT(mixin_type.HasResolvedTypeClass());
1578 const Class& mixin_class = Class::Handle(mixin_type.type_class()); 1629 const Class& mixin_class = Class::Handle(mixin_type.type_class());
1579 if (mixin_class.IsNullClass()) { 1630
1580 const Script& script = Script::Handle(mixin_app_class.script()); 1631 if (FLAG_trace_class_finalization) {
1581 ReportError(Error::Handle(), // No previous error. 1632 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n",
1582 script, mixin_app_class.token_pos(), 1633 String::Handle(mixin_type.Name()).ToCString(),
1583 "illegal mixin of 'Null'"); 1634 mixin_app_class.ToCString(),
1635 mixin_app_class.token_pos());
1584 } 1636 }
1585 // Check for illegal self references. 1637
1638 // Check for illegal self references. This has to be done before checking
1639 // that the super class of the mixin class is class Object.
1586 GrowableArray<intptr_t> visited_mixins; 1640 GrowableArray<intptr_t> visited_mixins;
1587 if (!IsMixinCycleFree(mixin_class, &visited_mixins)) { 1641 if (!IsMixinCycleFree(mixin_class, &visited_mixins)) {
1588 const Script& script = Script::Handle(mixin_class.script()); 1642 const Script& script = Script::Handle(mixin_class.script());
1589 const String& class_name = String::Handle(mixin_class.Name()); 1643 const String& class_name = String::Handle(mixin_class.Name());
1590 ReportError(Error::Handle(), // No previous error. 1644 ReportError(Error::Handle(), // No previous error.
1591 script, mixin_class.token_pos(), 1645 script, mixin_class.token_pos(),
1592 "mixin class '%s' illegally refers to itself", 1646 "mixin class '%s' illegally refers to itself",
1593 class_name.ToCString()); 1647 class_name.ToCString());
1594 } 1648 }
1595 1649
1596 if (FLAG_trace_class_finalization) {
1597 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n",
1598 String::Handle(mixin_type.Name()).ToCString(),
1599 mixin_app_class.ToCString(),
1600 mixin_app_class.token_pos());
1601 }
1602
1603 // Check that the super class of the mixin class is class Object. 1650 // Check that the super class of the mixin class is class Object.
1604 Class& mixin_super_class = Class::Handle(mixin_class.SuperClass()); 1651 Class& mixin_super_class = Class::Handle(mixin_class.SuperClass());
1605 // Skip over mixin application typedef classes, which are aliases (but are 1652 // Skip over mixin application typedef classes, which are aliases (but are
1606 // implemented as subclasses) of the mixin application classes they name. 1653 // implemented as subclasses) of the mixin application classes they name.
1607 if (!mixin_super_class.IsNull() && mixin_class.is_mixin_typedef()) { 1654 if (!mixin_super_class.IsNull() && mixin_class.is_mixin_typedef()) {
1608 while (mixin_super_class.is_mixin_typedef()) { 1655 while (mixin_super_class.is_mixin_typedef()) {
1609 mixin_super_class = mixin_super_class.SuperClass(); 1656 mixin_super_class = mixin_super_class.SuperClass();
1610 } 1657 }
1611 mixin_super_class = mixin_super_class.SuperClass(); 1658 mixin_super_class = mixin_super_class.SuperClass();
1612 } 1659 }
1613 if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) { 1660 if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) {
1614 const Script& script = Script::Handle(mixin_app_class.script()); 1661 const Script& script = Script::Handle(mixin_app_class.script());
1615 const String& class_name = String::Handle(mixin_class.Name()); 1662 const String& class_name = String::Handle(mixin_class.Name());
1616 ReportError(Error::Handle(), // No previous error. 1663 ReportError(Error::Handle(), // No previous error.
1617 script, mixin_app_class.token_pos(), 1664 script, mixin_app_class.token_pos(),
1618 "mixin class '%s' must extend class 'Object'", 1665 "mixin class '%s' must extend class 'Object'",
1619 class_name.ToCString()); 1666 class_name.ToCString());
1620 } 1667 }
1621 1668
1622 // Copy type parameters to mixin application class. 1669 // Copy type parameters to mixin application class.
1623 CloneMixinAppTypeParameters(mixin_app_class); 1670 CloneMixinAppTypeParameters(mixin_app_class);
1624 1671
1672 // Verify that no restricted class is used as a mixin by checking the
1673 // interfaces of the mixin application class, which implements its mixin.
1674 GrowableArray<intptr_t> visited_interfaces;
1675 ResolveSuperTypeAndInterfaces(mixin_app_class, &visited_interfaces);
1676
1625 if (FLAG_trace_class_finalization) { 1677 if (FLAG_trace_class_finalization) {
1626 OS::Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n", 1678 OS::Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n",
1627 String::Handle(mixin_type.Name()).ToCString(), 1679 String::Handle(mixin_type.Name()).ToCString(),
1628 String::Handle(mixin_app_class.Name()).ToCString(), 1680 String::Handle(mixin_app_class.Name()).ToCString(),
1629 TypeArguments::Handle( 1681 TypeArguments::Handle(
1630 mixin_app_class.type_parameters()).ToCString(), 1682 mixin_app_class.type_parameters()).ToCString(),
1631 AbstractType::Handle(mixin_app_class.super_type()).ToCString()); 1683 AbstractType::Handle(mixin_app_class.super_type()).ToCString());
1632 } 1684 }
1633 mixin_app_class.set_is_mixin_type_applied(); 1685 mixin_app_class.set_is_mixin_type_applied();
1634 } 1686 }
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
2273 "'dynamic' may not be used as interface"); 2325 "'dynamic' may not be used as interface");
2274 } 2326 }
2275 interface_class = interface.type_class(); 2327 interface_class = interface.type_class();
2276 if (interface_class.IsSignatureClass()) { 2328 if (interface_class.IsSignatureClass()) {
2277 const Script& script = Script::Handle(cls.script()); 2329 const Script& script = Script::Handle(cls.script());
2278 ReportError(Error::Handle(), // No previous error. 2330 ReportError(Error::Handle(), // No previous error.
2279 script, cls.token_pos(), 2331 script, cls.token_pos(),
2280 "function type alias '%s' may not be used as interface", 2332 "function type alias '%s' may not be used as interface",
2281 String::Handle(interface_class.Name()).ToCString()); 2333 String::Handle(interface_class.Name()).ToCString());
2282 } 2334 }
2283 // Verify that unless cls belongs to core lib, it cannot extend or implement 2335 // Verify that unless cls belongs to core lib, it cannot extend, implement,
2284 // any of Null, bool, num, int, double, String, Function, dynamic. 2336 // or mixin any of Null, bool, num, int, double, String, dynamic.
2285 // The exception is signature classes, which are compiler generated and
2286 // represent a function type, therefore implementing the Function interface.
2287 if (!cls_belongs_to_core_lib) { 2337 if (!cls_belongs_to_core_lib) {
2288 if (interface.IsBoolType() || 2338 if (interface.IsBoolType() ||
2289 interface.IsNullType() || 2339 interface.IsNullType() ||
2290 interface.IsNumberType() || 2340 interface.IsNumberType() ||
2291 interface.IsIntType() || 2341 interface.IsIntType() ||
2292 interface.IsDoubleType() || 2342 interface.IsDoubleType() ||
2293 interface.IsStringType() || 2343 interface.IsStringType() ||
2294 interface.IsDynamicType()) { 2344 interface.IsDynamicType()) {
2295 const Script& script = Script::Handle(cls.script()); 2345 const Script& script = Script::Handle(cls.script());
2296 ReportError(Error::Handle(), // No previous error. 2346 const String& interface_name = String::Handle(interface_class.Name());
2297 script, cls.token_pos(), 2347 if (cls.IsMixinApplication()) {
2298 "'%s' is not allowed to extend or implement '%s'", 2348 ReportError(Error::Handle(), // No previous error.
2299 String::Handle(cls.Name()).ToCString(), 2349 script, cls.token_pos(),
2300 String::Handle(interface_class.Name()).ToCString()); 2350 "illegal mixin of '%s'",
2351 interface_name.ToCString());
2352 } else {
2353 ReportError(Error::Handle(), // No previous error.
2354 script, cls.token_pos(),
2355 "'%s' is not allowed to extend or implement '%s'",
2356 String::Handle(cls.Name()).ToCString(),
2357 interface_name.ToCString());
2358 }
2301 } 2359 }
2302 } 2360 }
2303 interface_class.set_is_implemented(); 2361 interface_class.set_is_implemented();
2304 // Now resolve the super interfaces. 2362 // Now resolve the super interfaces.
2305 ResolveSuperTypeAndInterfaces(interface_class, visited); 2363 ResolveSuperTypeAndInterfaces(interface_class, visited);
2306 } 2364 }
2307 visited->RemoveLast(); 2365 visited->RemoveLast();
2308 } 2366 }
2309 2367
2310 2368
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
2529 expected_name ^= String::New("_offset"); 2587 expected_name ^= String::New("_offset");
2530 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 2588 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
2531 field ^= fields_array.At(2); 2589 field ^= fields_array.At(2);
2532 ASSERT(field.Offset() == TypedDataView::length_offset()); 2590 ASSERT(field.Offset() == TypedDataView::length_offset());
2533 name ^= field.name(); 2591 name ^= field.name();
2534 ASSERT(name.Equals("length")); 2592 ASSERT(name.Equals("length"));
2535 #endif 2593 #endif
2536 } 2594 }
2537 2595
2538 } // namespace dart 2596 } // 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