| 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..f560372ba4fbdf3755b3e2054bf8df42f8160304 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. Computes the type held in all own or "inherited" type variables.
|
| + /// 2. Evaluates all own or inherited field initializers.
|
| + /// 3. Creates the object and assigns its fields and runtime type.
|
| + /// 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,44 @@ 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 [type] and all of its super classes into
|
| + /// the environment. All type variables mentioned in [type] 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) {
|
| + irBuilder.declareTypeVariable(clazz.typeVariables[i],
|
| + type.typeArguments[i]);
|
| + }
|
| + 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;
|
|
|