Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| index c6033373ed6de7655de0ad1f4bcd30fbfa25b834..4c6680d4737c91f28e7b6e6872dcf08f315062df 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart |
| @@ -2497,10 +2497,11 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| /// Builds the IR for a given constructor. |
| /// |
| - /// 1. Evaluates all own or inherited field initializers. |
| - /// 2. Creates the object and assigns its fields. |
| - /// 3. Calls constructor body and super constructor bodies. |
| - /// 4. Returns the created object. |
| + /// 1. Builds all types held in own or "inherited" type variables. |
|
karlklose
2015/05/28 08:12:19
Not sure what 'builds' means here. Further down we
asgerf
2015/05/28 09:34:21
I've tried to clarify a bit.
|
| + /// 2. Evaluates all own or inherited field initializers. |
| + /// 3. Creates the object and assigns its fields. |
| + /// 4. Calls constructor body and super constructor bodies. |
| + /// 5. Returns the created object. |
| ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { |
| // TODO(asgerf): Optimization: If constructor is redirecting, then just |
| // evaluate arguments and call the target constructor. |
| @@ -2525,8 +2526,11 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| if (requiresTypeInformation) { |
| firstTypeArgumentParameterIndex = parameters.length; |
| classElement.typeVariables.forEach((TypeVariableType variable) { |
| - parameters.add( |
| - new TypeInformationParameter(variable.element, constructor)); |
| + parameters.add(new TypeVariableLocal(variable, constructor)); |
| + }); |
| + } else { |
| + classElement.typeVariables.forEach((TypeVariableType variable) { |
| + irBuilder.declareTypeVariable(variable, const DynamicType()); |
| }); |
| } |
| @@ -2542,7 +2546,14 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| typeInformation = const <ir.Primitive>[]; |
| } |
| - // -- Step 1: evaluate field initializers --- |
| + // -- Load values for type variables declared on super classes -- |
| + // Field initializers for super classes can reference these, so they |
| + // must be available before evaluating field initializers. |
| + // This could be interleaved with field initialization, but we choose do |
| + // get it out of the way here to avoid complications with mixins. |
| + loadTypeVariablesForSuperClasses(classElement); |
| + |
| + // -- Evaluate field initializers --- |
| // Evaluate field initializers in constructor and super constructors. |
| irBuilder.enterInitializers(); |
| List<ConstructorElement> constructorList = <ConstructorElement>[]; |
| @@ -2553,7 +2564,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| // BoxLocals for captured parameters are also in the environment. |
| // The initial value of all fields are now bound in [fieldValues]. |
| - // --- Step 2: create the object --- |
| + // --- Create the object --- |
| // Get the initial field values in the canonical order. |
| List<ir.Primitive> instanceArguments = <ir.Primitive>[]; |
| classElement.forEachInstanceField((ClassElement c, FieldElement field) { |
| @@ -2571,7 +2582,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| typeInformation); |
| irBuilder.add(new ir.LetPrim(instance)); |
| - // --- Step 3: call constructor bodies --- |
| + // --- Call constructor bodies --- |
| for (ConstructorElement target in constructorList) { |
| ConstructorBodyElement bodyElement = getConstructorBody(target); |
| if (bodyElement == null) continue; // Skip if constructor has no body. |
| @@ -2673,12 +2684,45 @@ class JsIrBuilderVisitor extends IrBuilderVisitor { |
| supers.add(constructor); |
| } |
| + /// Loads the type variables for all super classes of [superClass] into the |
| + /// IR builder's environment with their corresponding values. |
| + /// |
| + /// The type variables for [currentClass] must already be in the IR builder's |
| + /// environment. |
| + /// |
| + /// Type variables are stored as [TypeVariableLocal] in the environment. |
| + /// |
| + /// This ensures that access to type variables mentioned inside the |
| + /// constructors and initializers will happen through the local environment |
| + /// instead of using 'this'. |
| + void loadTypeVariablesForSuperClasses(ClassElement currentClass) { |
| + if (currentClass.isObject) return; |
| + loadTypeVariablesForType(currentClass.supertype); |
| + if (currentClass is MixinApplicationElement) { |
| + loadTypeVariablesForType(currentClass.mixinType); |
| + } |
| + } |
| + |
| + /// Loads all type variables for [superType] and all of its super classes into |
| + /// the environment. All type variables mentioned in [superType] must already |
| + /// be in the environment. |
| + void loadTypeVariablesForType(InterfaceType type) { |
| + ClassElement clazz = type.element; |
| + assert(clazz.typeVariables.length == type.typeArguments.length); |
| + for (int i = 0; i < clazz.typeVariables.length; ++i) { |
| + TypeVariableType typeParameter = clazz.typeVariables[i]; |
|
karlklose
2015/05/28 08:12:19
Maybe inline typeParameter and typeArgument.
asgerf
2015/05/28 09:34:21
Done.
|
| + DartType typeArgument = type.typeArguments[i]; |
| + irBuilder.declareTypeVariable(typeParameter, typeArgument); |
| + } |
| + loadTypeVariablesForSuperClasses(clazz); |
| + } |
| + |
| /// In preparation of inlining (part of) [target], the [arguments] are moved |
| /// into the environment bindings for the corresponding parameters. |
| /// |
| /// Defaults for optional arguments are evaluated in order to ensure |
| /// all parameters are available in the environment. |
| - void loadArguments(FunctionElement target, |
| + void loadArguments(ConstructorElement target, |
| Selector selector, |
| List<ir.Primitive> arguments) { |
| target = target.implementation; |