Chromium Code Reviews| 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 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1416 const Array& interfaces = Array::Handle(isolate, Array::New(1)); | 1416 const Array& interfaces = Array::Handle(isolate, Array::New(1)); |
| 1417 interfaces.SetAt(0, mixin_type); | 1417 interfaces.SetAt(0, mixin_type); |
| 1418 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); | 1418 ASSERT(mixin_app_class.interfaces() == Object::empty_array().raw()); |
| 1419 mixin_app_class.set_interfaces(interfaces); | 1419 mixin_app_class.set_interfaces(interfaces); |
| 1420 | 1420 |
| 1421 // If both the super type and the mixin type are non generic, the mixin | 1421 // If both the super type and the mixin type are non generic, the mixin |
| 1422 // application class is non generic as well and we can skip type parameter | 1422 // application class is non generic as well and we can skip type parameter |
| 1423 // cloning. | 1423 // cloning. |
| 1424 bool has_uninstantiated_bounds = false; | 1424 bool has_uninstantiated_bounds = false; |
| 1425 if ((num_super_type_params + num_mixin_type_params) > 0) { | 1425 if ((num_super_type_params + num_mixin_type_params) > 0) { |
| 1426 // First, clone the super class type parameters. Rename them so that | 1426 // If the last ampersand in the name of the mixin application class is |
| 1427 // there can be no name conflict between the parameters of the super | 1427 // doubled, the same type parameters can propagate the type arguments to |
| 1428 // class and the mixin class. | 1428 // the super type and to the mixin type. |
| 1429 bool share_type_params = false; | |
| 1430 if (num_super_type_params == num_mixin_type_params) { | |
| 1431 const String& name = String::Handle(isolate, mixin_app_class.Name()); | |
| 1432 for (intptr_t i = name.Length(); --i > 0; ) { | |
|
srdjan
2014/01/29 20:33:27
Why that form? Wouldn't this be simpler to read:
f
regis
2014/01/29 21:10:34
Done.
| |
| 1433 if (name.CharAt(i) == '&') { | |
| 1434 if (name.CharAt(i - 1) == '&') { | |
| 1435 share_type_params = true; | |
| 1436 } | |
| 1437 break; | |
| 1438 } | |
| 1439 } | |
| 1440 } | |
| 1441 | |
| 1429 const TypeArguments& cloned_type_params = TypeArguments::Handle(isolate, | 1442 const TypeArguments& cloned_type_params = TypeArguments::Handle(isolate, |
| 1430 TypeArguments::New(num_super_type_params + num_mixin_type_params)); | 1443 TypeArguments::New((share_type_params ? 0 : num_super_type_params) + |
| 1444 num_mixin_type_params)); | |
| 1431 TypeParameter& param = TypeParameter::Handle(isolate); | 1445 TypeParameter& param = TypeParameter::Handle(isolate); |
| 1432 TypeParameter& cloned_param = TypeParameter::Handle(isolate); | 1446 TypeParameter& cloned_param = TypeParameter::Handle(isolate); |
| 1433 String& param_name = String::Handle(isolate); | 1447 String& param_name = String::Handle(isolate); |
| 1434 AbstractType& param_bound = AbstractType::Handle(isolate); | 1448 AbstractType& param_bound = AbstractType::Handle(isolate); |
| 1435 intptr_t cloned_index = 0; | 1449 intptr_t cloned_index = 0; |
| 1436 if (num_super_type_params > 0) { | 1450 |
| 1451 // First, clone the super class type parameters. Rename them so that | |
| 1452 // there can be no name conflict between the parameters of the super | |
| 1453 // class and the mixin class. | |
| 1454 if (!share_type_params && (num_super_type_params > 0)) { | |
| 1437 const TypeArguments& super_type_params = | 1455 const TypeArguments& super_type_params = |
| 1438 TypeArguments::Handle(isolate, super_class.type_parameters()); | 1456 TypeArguments::Handle(isolate, super_class.type_parameters()); |
| 1439 const TypeArguments& super_type_args = TypeArguments::Handle(isolate, | 1457 const TypeArguments& super_type_args = TypeArguments::Handle(isolate, |
| 1440 TypeArguments::New(num_super_type_params)); | 1458 TypeArguments::New(num_super_type_params)); |
| 1441 // The cloned super class type parameters do not need to repeat their | 1459 // The cloned super class type parameters do not need to repeat their |
| 1442 // bounds, since the bound checks will be performed at the super class | 1460 // bounds, since the bound checks will be performed at the super class |
| 1443 // level. | 1461 // level. |
| 1444 param_bound = isolate->object_store()->object_type(); | 1462 param_bound = isolate->object_store()->object_type(); |
| 1445 for (intptr_t i = 0; i < num_super_type_params; i++) { | 1463 for (intptr_t i = 0; i < num_super_type_params; i++) { |
| 1446 param ^= super_type_params.TypeAt(i); | 1464 param ^= super_type_params.TypeAt(i); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1516 ASSERT(!param_bound.IsInstantiated()); | 1534 ASSERT(!param_bound.IsInstantiated()); |
| 1517 param.set_bound(param_bound); | 1535 param.set_bound(param_bound); |
| 1518 } | 1536 } |
| 1519 } | 1537 } |
| 1520 } | 1538 } |
| 1521 | 1539 |
| 1522 // Lastly, set the type arguments of the mixin type, which is also the | 1540 // Lastly, set the type arguments of the mixin type, which is also the |
| 1523 // single interface type. | 1541 // single interface type. |
| 1524 ASSERT(!mixin_type.IsFinalized()); | 1542 ASSERT(!mixin_type.IsFinalized()); |
| 1525 mixin_type.set_arguments(mixin_type_args); | 1543 mixin_type.set_arguments(mixin_type_args); |
| 1544 if (share_type_params) { | |
| 1545 Type::Cast(super_type).set_arguments(mixin_type_args); | |
| 1546 ASSERT(!super_type.IsFinalized()); | |
| 1547 } | |
| 1526 } | 1548 } |
| 1527 mixin_app_class.set_type_parameters(cloned_type_params); | 1549 mixin_app_class.set_type_parameters(cloned_type_params); |
| 1528 } | 1550 } |
| 1529 // If the mixin class is a mixin application alias class, we insert a new | 1551 // If the mixin class is a mixin application alias class, we insert a new |
| 1530 // synthesized mixin application class in the super chain of this mixin | 1552 // synthesized mixin application class in the super chain of this mixin |
| 1531 // application class. The new class will have the aliased mixin as actual | 1553 // application class. The new class will have the aliased mixin as actual |
| 1532 // mixin. | 1554 // mixin. |
| 1533 if (mixin_class.is_mixin_app_alias()) { | 1555 if (mixin_class.is_mixin_app_alias()) { |
| 1534 ApplyMixinAppAlias(mixin_app_class, has_uninstantiated_bounds); | 1556 ApplyMixinAppAlias(mixin_app_class, has_uninstantiated_bounds); |
| 1535 } | 1557 } |
| (...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2370 ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed. | 2392 ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed. |
| 2371 // The super type may have a BoundedType as type argument, but cannot be | 2393 // The super type may have a BoundedType as type argument, but cannot be |
| 2372 // a BoundedType itself. | 2394 // a BoundedType itself. |
| 2373 CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args); | 2395 CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args); |
| 2374 AbstractType& mixin_type = AbstractType::Handle(); | 2396 AbstractType& mixin_type = AbstractType::Handle(); |
| 2375 Type& generic_mixin_type = Type::Handle(); | 2397 Type& generic_mixin_type = Type::Handle(); |
| 2376 Class& mixin_type_class = Class::Handle(); | 2398 Class& mixin_type_class = Class::Handle(); |
| 2377 Class& mixin_app_class = Class::Handle(); | 2399 Class& mixin_app_class = Class::Handle(); |
| 2378 String& mixin_app_class_name = String::Handle(); | 2400 String& mixin_app_class_name = String::Handle(); |
| 2379 String& mixin_type_class_name = String::Handle(); | 2401 String& mixin_type_class_name = String::Handle(); |
| 2402 AbstractType& super_type_arg = AbstractType::Handle(); | |
| 2403 AbstractType& mixin_type_arg = AbstractType::Handle(); | |
| 2380 const intptr_t depth = mixin_app_type.Depth(); | 2404 const intptr_t depth = mixin_app_type.Depth(); |
| 2381 for (intptr_t i = 0; i < depth; i++) { | 2405 for (intptr_t i = 0; i < depth; i++) { |
| 2382 mixin_type = mixin_app_type.MixinTypeAt(i); | 2406 mixin_type = mixin_app_type.MixinTypeAt(i); |
| 2383 ASSERT(!mixin_type.IsNull()); | 2407 ASSERT(!mixin_type.IsNull()); |
| 2384 ResolveType(cls, mixin_type); | 2408 ResolveType(cls, mixin_type); |
| 2385 ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed. | 2409 ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed. |
| 2386 ASSERT(mixin_type.IsType()); | 2410 ASSERT(mixin_type.IsType()); |
| 2411 const intptr_t num_super_type_args = type_args.Length(); | |
| 2387 CollectTypeArguments(cls, Type::Cast(mixin_type), type_args); | 2412 CollectTypeArguments(cls, Type::Cast(mixin_type), type_args); |
| 2388 | 2413 |
| 2414 // If the mixin type has identical type arguments as the super type, they | |
| 2415 // can share the same type parameters of the mixin application class, | |
| 2416 // thereby allowing for further optimizations, such as instantiator vector | |
| 2417 // reuse or sharing of type arguments with the super class. | |
| 2418 bool share_type_params = (num_super_type_args > 0) && | |
| 2419 (type_args.Length() == 2*num_super_type_args); | |
| 2420 if (share_type_params) { | |
| 2421 for (intptr_t i = 0; i < num_super_type_args; i++) { | |
| 2422 super_type_arg ^= type_args.At(i); | |
| 2423 mixin_type_arg ^= type_args.At(num_super_type_args + i); | |
| 2424 if (!super_type_arg.Equals(mixin_type_arg)) { | |
| 2425 share_type_params = false; | |
| 2426 break; | |
| 2427 } | |
| 2428 } | |
| 2429 if (share_type_params) { | |
| 2430 // Cut the type argument vector in half. | |
| 2431 type_args.SetLength(num_super_type_args); | |
| 2432 } | |
| 2433 } | |
| 2434 | |
| 2389 // The name of the mixin application class is a combination of | 2435 // The name of the mixin application class is a combination of |
| 2390 // the super class name and mixin class name. | 2436 // the super class name and mixin class name. |
| 2391 mixin_app_class_name = mixin_super_type.ClassName(); | 2437 mixin_app_class_name = mixin_super_type.ClassName(); |
| 2392 mixin_app_class_name = String::Concat(mixin_app_class_name, | 2438 mixin_app_class_name = String::Concat(mixin_app_class_name, |
| 2393 Symbols::Ampersand()); | 2439 Symbols::Ampersand()); |
| 2440 // If the type parameters are shared between the super type and the mixin | |
| 2441 // type, use two ampersand symbols, so that the class has a different name | |
| 2442 // and is not reused in a context where this optimization is not possible. | |
| 2443 if (share_type_params) { | |
| 2444 mixin_app_class_name = String::Concat(mixin_app_class_name, | |
| 2445 Symbols::Ampersand()); | |
| 2446 } | |
| 2394 mixin_type_class_name = mixin_type.ClassName(); | 2447 mixin_type_class_name = mixin_type.ClassName(); |
| 2395 mixin_app_class_name = String::Concat(mixin_app_class_name, | 2448 mixin_app_class_name = String::Concat(mixin_app_class_name, |
| 2396 mixin_type_class_name); | 2449 mixin_type_class_name); |
| 2397 mixin_app_class = library.LookupLocalClass(mixin_app_class_name); | 2450 mixin_app_class = library.LookupLocalClass(mixin_app_class_name); |
| 2398 if (mixin_app_class.IsNull()) { | 2451 if (mixin_app_class.IsNull()) { |
| 2399 mixin_app_class_name = Symbols::New(mixin_app_class_name); | 2452 mixin_app_class_name = Symbols::New(mixin_app_class_name); |
| 2400 mixin_app_class = Class::New(mixin_app_class_name, | 2453 mixin_app_class = Class::New(mixin_app_class_name, |
| 2401 script, | 2454 script, |
| 2402 mixin_type.token_pos()); | 2455 mixin_type.token_pos()); |
| 2403 mixin_app_class.set_super_type(mixin_super_type); | 2456 mixin_app_class.set_super_type(mixin_super_type); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2855 expected_name ^= String::New("_offset"); | 2908 expected_name ^= String::New("_offset"); |
| 2856 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2909 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2857 field ^= fields_array.At(2); | 2910 field ^= fields_array.At(2); |
| 2858 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2911 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2859 name ^= field.name(); | 2912 name ^= field.name(); |
| 2860 ASSERT(name.Equals("length")); | 2913 ASSERT(name.Equals("length")); |
| 2861 #endif | 2914 #endif |
| 2862 } | 2915 } |
| 2863 | 2916 |
| 2864 } // namespace dart | 2917 } // namespace dart |
| OLD | NEW |