| 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 13f4306d5b4951b1d675f368dc074f05beb5ac5d..aebd19dbd5fa85b098d1f1d28049b93dde0091cc 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
|
| @@ -2123,6 +2123,10 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| /// It is computed by the [ClosureTranslator].
|
| ClosureClassMap closureClassMap;
|
|
|
| + /// During construction of a constructor factory, [fieldValues] maps fields
|
| + /// to the primitive containing their initial value.
|
| + Map<FieldElement, ir.Primitive> fieldValues = <FieldElement, ir.Primitive>{};
|
| +
|
| JsIrBuilderVisitor(TreeElements elements,
|
| Compiler compiler,
|
| SourceInformationBuilder sourceInformationBuilder)
|
| @@ -2265,23 +2269,15 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| });
|
| }
|
|
|
| - /// Make a visitor suitable for translating ASTs taken from [context].
|
| - ///
|
| - /// Every visitor can only be applied to nodes in one context, because
|
| - /// the [elements] field is specific to that context.
|
| - JsIrBuilderVisitor makeVisitorForContext(AstElement context) {
|
| - return new JsIrBuilderVisitor(
|
| - context.resolvedAst.elements,
|
| - compiler,
|
| - sourceInformationBuilder.forContext(context));
|
| - }
|
| -
|
| /// Builds the IR for an [expression] taken from a different [context].
|
| ///
|
| /// Such expressions need to be compiled with a different [sourceFile] and
|
| /// [elements] mapping.
|
| ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
|
| - JsIrBuilderVisitor visitor = makeVisitorForContext(context);
|
| + JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
|
| + context.resolvedAst.elements,
|
| + compiler,
|
| + sourceInformationBuilder.forContext(context));
|
| return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
|
| }
|
|
|
| @@ -2290,7 +2286,10 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| /// Such constants need to be compiled with a different [sourceFile] and
|
| /// [elements] mapping.
|
| ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
|
| - JsIrBuilderVisitor visitor = makeVisitorForContext(context);
|
| + JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
|
| + context.resolvedAst.elements,
|
| + compiler,
|
| + sourceInformationBuilder.forContext(context));
|
| return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
|
| }
|
|
|
| @@ -2359,16 +2358,11 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| // get it out of the way here to avoid complications with mixins.
|
| loadTypeVariablesForSuperClasses(classElement);
|
|
|
| - /// Maps each field from this class or a superclass to its initial value.
|
| - Map<FieldElement, ir.Primitive> fieldValues =
|
| - <FieldElement, ir.Primitive>{};
|
| -
|
| // -- Evaluate field initializers ---
|
| // Evaluate field initializers in constructor and super constructors.
|
| irBuilder.enterInitializers();
|
| List<ConstructorElement> constructorList = <ConstructorElement>[];
|
| - evaluateConstructorFieldInitializers(
|
| - constructor, constructorList, fieldValues);
|
| + evaluateConstructorFieldInitializers(constructor, constructorList);
|
| irBuilder.leaveInitializers();
|
|
|
| // All parameters in all constructors are now bound in the environment.
|
| @@ -2424,12 +2418,8 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| /// the environment, but will be put there by this procedure.
|
| ///
|
| /// All constructors will be added to [supers], with superconstructors first.
|
| - void evaluateConstructorFieldInitializers(
|
| - ConstructorElement constructor,
|
| - List<ConstructorElement> supers,
|
| - Map<FieldElement, ir.Primitive> fieldValues) {
|
| - assert(constructor.isImplementation);
|
| - assert(constructor == elements.analyzedElement);
|
| + void evaluateConstructorFieldInitializers(ConstructorElement constructor,
|
| + List<ConstructorElement> supers) {
|
| ClassElement enclosingClass = constructor.enclosingClass.implementation;
|
| // Evaluate declaration-site field initializers, unless this constructor
|
| // redirects to another using a `this()` initializer. In that case, these
|
| @@ -2466,18 +2456,19 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| if (initializer is ast.SendSet) {
|
| // Field initializer.
|
| FieldElement field = elements[initializer];
|
| - fieldValues[field] = visit(initializer.arguments.head);
|
| + fieldValues[field] =
|
| + inlineExpression(constructor, initializer.arguments.head);
|
| } else if (initializer is ast.Send) {
|
| // Super or this initializer.
|
| ConstructorElement target = elements[initializer].implementation;
|
| Selector selector = elements.getSelector(initializer);
|
| - List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
|
| - evaluateConstructorCallFromInitializer(
|
| - target,
|
| - selector.callStructure,
|
| - arguments,
|
| - supers,
|
| - fieldValues);
|
| + ir.Primitive evaluateArgument(ast.Node arg) {
|
| + return inlineExpression(constructor, arg);
|
| + }
|
| + List<ir.Primitive> arguments =
|
| + initializer.arguments.mapToList(evaluateArgument);
|
| + loadArguments(target, selector, arguments);
|
| + evaluateConstructorFieldInitializers(target, supers);
|
| hasConstructorCall = true;
|
| } else {
|
| compiler.internalError(initializer,
|
| @@ -2492,35 +2483,12 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| if (target == null) {
|
| compiler.internalError(superClass, "No default constructor available.");
|
| }
|
| - target = target.implementation;
|
| - evaluateConstructorCallFromInitializer(
|
| - target,
|
| - CallStructure.NO_ARGS,
|
| - const [],
|
| - supers,
|
| - fieldValues);
|
| + evaluateConstructorFieldInitializers(target, supers);
|
| }
|
| // Add this constructor after the superconstructors.
|
| supers.add(constructor);
|
| }
|
|
|
| - /// Evaluates a call to the given constructor from an initializer list.
|
| - ///
|
| - /// Calls [loadArguments] and [evaluateConstructorFieldInitializers] in a
|
| - /// visitor that has the proper [TreeElements] mapping.
|
| - void evaluateConstructorCallFromInitializer(
|
| - ConstructorElement target,
|
| - CallStructure call,
|
| - List<ir.Primitive> arguments,
|
| - List<ConstructorElement> supers,
|
| - Map<FieldElement, ir.Primitive> fieldValues) {
|
| - JsIrBuilderVisitor visitor = makeVisitorForContext(target);
|
| - return visitor.withBuilder(irBuilder, () {
|
| - visitor.loadArguments(target, call, arguments);
|
| - visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
|
| - });
|
| - }
|
| -
|
| /// Loads the type variables for all super classes of [superClass] into the
|
| /// IR builder's environment with their corresponding values.
|
| ///
|
| @@ -2559,10 +2527,9 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| /// Defaults for optional arguments are evaluated in order to ensure
|
| /// all parameters are available in the environment.
|
| void loadArguments(ConstructorElement target,
|
| - CallStructure call,
|
| + Selector selector,
|
| List<ir.Primitive> arguments) {
|
| - assert(target.isImplementation);
|
| - assert(target == elements.analyzedElement);
|
| + target = target.implementation;
|
| FunctionSignature signature = target.functionSignature;
|
|
|
| // Establish a scope in case parameters are captured.
|
| @@ -2581,9 +2548,9 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| ir.Primitive value;
|
| // Load argument if provided.
|
| if (signature.optionalParametersAreNamed) {
|
| - int nameIndex = call.namedArguments.indexOf(param.name);
|
| + int nameIndex = selector.namedArguments.indexOf(param.name);
|
| if (nameIndex != -1) {
|
| - int translatedIndex = call.positionalArgumentCount + nameIndex;
|
| + int translatedIndex = selector.positionalArgumentCount + nameIndex;
|
| value = arguments[translatedIndex];
|
| }
|
| } else if (index < arguments.length) {
|
| @@ -2592,7 +2559,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| // Load default if argument was not provided.
|
| if (value == null) {
|
| if (param.initializer != null) {
|
| - value = visit(param.initializer);
|
| + value = inlineExpression(target, param.initializer);
|
| } else {
|
| value = irBuilder.buildNullConstant();
|
| }
|
| @@ -2614,8 +2581,9 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
|
| // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
|
| // Instead of forging ParameterElements to forge a FunctionSignature, we
|
| // need a way to create backend methods without creating more fake elements.
|
| +
|
| assert(constructor.isGenerativeConstructor);
|
| - assert(constructor.isImplementation);
|
| + assert(invariant(constructor, constructor.isImplementation));
|
| if (constructor.isSynthesized) return null;
|
| ast.FunctionExpression node = constructor.node;
|
| // If we know the body doesn't have any code, we don't generate it.
|
|
|