Chromium Code Reviews| Index: runtime/vm/class_finalizer.cc |
| =================================================================== |
| --- runtime/vm/class_finalizer.cc (revision 32126) |
| +++ runtime/vm/class_finalizer.cc (working copy) |
| @@ -1423,17 +1423,35 @@ |
| // cloning. |
| bool has_uninstantiated_bounds = false; |
| if ((num_super_type_params + num_mixin_type_params) > 0) { |
| - // First, clone the super class type parameters. Rename them so that |
| - // there can be no name conflict between the parameters of the super |
| - // class and the mixin class. |
| + // If the last ampersand in the name of the mixin application class is |
| + // doubled, the same type parameters can propagate the type arguments to |
| + // the super type and to the mixin type. |
| + bool share_type_params = false; |
| + if (num_super_type_params == num_mixin_type_params) { |
| + const String& name = String::Handle(isolate, mixin_app_class.Name()); |
| + 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.
|
| + if (name.CharAt(i) == '&') { |
| + if (name.CharAt(i - 1) == '&') { |
| + share_type_params = true; |
| + } |
| + break; |
| + } |
| + } |
| + } |
| + |
| const TypeArguments& cloned_type_params = TypeArguments::Handle(isolate, |
| - TypeArguments::New(num_super_type_params + num_mixin_type_params)); |
| + TypeArguments::New((share_type_params ? 0 : num_super_type_params) + |
| + num_mixin_type_params)); |
| TypeParameter& param = TypeParameter::Handle(isolate); |
| TypeParameter& cloned_param = TypeParameter::Handle(isolate); |
| String& param_name = String::Handle(isolate); |
| AbstractType& param_bound = AbstractType::Handle(isolate); |
| intptr_t cloned_index = 0; |
| - if (num_super_type_params > 0) { |
| + |
| + // First, clone the super class type parameters. Rename them so that |
| + // there can be no name conflict between the parameters of the super |
| + // class and the mixin class. |
| + if (!share_type_params && (num_super_type_params > 0)) { |
| const TypeArguments& super_type_params = |
| TypeArguments::Handle(isolate, super_class.type_parameters()); |
| const TypeArguments& super_type_args = TypeArguments::Handle(isolate, |
| @@ -1523,6 +1541,10 @@ |
| // single interface type. |
| ASSERT(!mixin_type.IsFinalized()); |
| mixin_type.set_arguments(mixin_type_args); |
| + if (share_type_params) { |
| + Type::Cast(super_type).set_arguments(mixin_type_args); |
| + ASSERT(!super_type.IsFinalized()); |
| + } |
| } |
| mixin_app_class.set_type_parameters(cloned_type_params); |
| } |
| @@ -2377,6 +2399,8 @@ |
| Class& mixin_app_class = Class::Handle(); |
| String& mixin_app_class_name = String::Handle(); |
| String& mixin_type_class_name = String::Handle(); |
| + AbstractType& super_type_arg = AbstractType::Handle(); |
| + AbstractType& mixin_type_arg = AbstractType::Handle(); |
| const intptr_t depth = mixin_app_type.Depth(); |
| for (intptr_t i = 0; i < depth; i++) { |
| mixin_type = mixin_app_type.MixinTypeAt(i); |
| @@ -2384,13 +2408,42 @@ |
| ResolveType(cls, mixin_type); |
| ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed. |
| ASSERT(mixin_type.IsType()); |
| + const intptr_t num_super_type_args = type_args.Length(); |
| CollectTypeArguments(cls, Type::Cast(mixin_type), type_args); |
| + // If the mixin type has identical type arguments as the super type, they |
| + // can share the same type parameters of the mixin application class, |
| + // thereby allowing for further optimizations, such as instantiator vector |
| + // reuse or sharing of type arguments with the super class. |
| + bool share_type_params = (num_super_type_args > 0) && |
| + (type_args.Length() == 2*num_super_type_args); |
| + if (share_type_params) { |
| + for (intptr_t i = 0; i < num_super_type_args; i++) { |
| + super_type_arg ^= type_args.At(i); |
| + mixin_type_arg ^= type_args.At(num_super_type_args + i); |
| + if (!super_type_arg.Equals(mixin_type_arg)) { |
| + share_type_params = false; |
| + break; |
| + } |
| + } |
| + if (share_type_params) { |
| + // Cut the type argument vector in half. |
| + type_args.SetLength(num_super_type_args); |
| + } |
| + } |
| + |
| // The name of the mixin application class is a combination of |
| // the super class name and mixin class name. |
| mixin_app_class_name = mixin_super_type.ClassName(); |
| mixin_app_class_name = String::Concat(mixin_app_class_name, |
| Symbols::Ampersand()); |
| + // If the type parameters are shared between the super type and the mixin |
| + // type, use two ampersand symbols, so that the class has a different name |
| + // and is not reused in a context where this optimization is not possible. |
| + if (share_type_params) { |
| + mixin_app_class_name = String::Concat(mixin_app_class_name, |
| + Symbols::Ampersand()); |
| + } |
| mixin_type_class_name = mixin_type.ClassName(); |
| mixin_app_class_name = String::Concat(mixin_app_class_name, |
| mixin_type_class_name); |