Chromium Code Reviews| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
| index deffab4a20dc0bd50fba6d30a424e75ed0fa6314..570e743cec0eef7d2e6e68cc826d0a3bbe49a137 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
| @@ -13,7 +13,8 @@ import '../io/source_information.dart'; |
| import '../tree/tree.dart' as ast; |
| import '../closure.dart' hide ClosureScope; |
| import 'cps_ir_nodes.dart' as ir; |
| -import 'cps_ir_builder_task.dart' show DartCapturedVariables; |
| +import 'cps_ir_builder_task.dart' show DartCapturedVariables, |
| + GlobalProgramInformation; |
| /// A mapping from variable elements to their compile-time values. |
| /// |
| @@ -308,7 +309,7 @@ abstract class IrBuilder { |
| /// Add the given function parameter to the IR, and bind it in the environment |
| /// or put it in its box, if necessary. |
| - void _createFunctionParameter(ParameterElement parameterElement); |
| + void _createFunctionParameter(Local parameterElement); |
| void _createThisParameter(); |
| /// Creates an access to the receiver from the current (or enclosing) method. |
| @@ -416,7 +417,7 @@ abstract class IrBuilder { |
| _enterScope(closureScope); |
| } |
| - List<ir.Primitive> buildFunctionHeader(Iterable<ParameterElement> parameters, |
| + List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters, |
| {ClosureScope closureScope, |
| ClosureEnvironment env}) { |
| _createThisParameter(); |
| @@ -828,12 +829,8 @@ abstract class IrBuilder { |
| /// argument values are defined by [arguments]. |
| ir.Primitive buildConstructorInvocation(FunctionElement element, |
| Selector selector, |
| - DartType type, |
| - List<ir.Primitive> arguments) { |
| - assert(isOpen); |
| - return _continueWithExpression( |
| - (k) => new ir.InvokeConstructor(type, element, selector, k, arguments)); |
| - } |
| + InterfaceType type, |
| + List<ir.Primitive> arguments); |
| /// Create a string concatenation of the [arguments]. |
| ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) { |
| @@ -2070,7 +2067,7 @@ class DartIrBuilder extends IrBuilder { |
| } |
| } |
| - void _createFunctionParameter(ParameterElement parameterElement) { |
| + void _createFunctionParameter(Local parameterElement) { |
| ir.Parameter parameter = new ir.Parameter(parameterElement); |
| _parameters.add(parameter); |
| if (isInMutableVariable(parameterElement)) { |
| @@ -2169,6 +2166,16 @@ class DartIrBuilder extends IrBuilder { |
| return _buildInvokeSuper(target, selector, arguments); |
| } |
| + @override |
| + ir.Primitive buildConstructorInvocation(FunctionElement element, |
| + Selector selector, |
| + InterfaceType type, |
| + List<ir.Primitive> arguments) { |
| + assert(isOpen); |
| + return _continueWithExpression( |
| + (k) => new ir.InvokeConstructor(type, element, selector, k, |
| + arguments)); |
| + } |
| } |
| /// State shared between JsIrBuilders within the same function. |
| @@ -2181,6 +2188,10 @@ class JsIrBuilderSharedState { |
| /// If non-null, this refers to the receiver (`this`) in the enclosing method. |
| ir.Primitive receiver; |
| + |
| + /// `true` when we are currently building expressions inside the initializer |
| + /// list of a constructor. |
| + bool inInitializers = false; |
| } |
| /// JS-specific subclass of [IrBuilder]. |
| @@ -2189,11 +2200,13 @@ class JsIrBuilderSharedState { |
| /// variables are boxed as necessary using [CreateBox], [GetField], [SetField]. |
| class JsIrBuilder extends IrBuilder { |
| final JsIrBuilderSharedState jsState; |
| + final GlobalProgramInformation program; |
| - IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState); |
| - JsIrBuilder._blank(this.jsState); |
| + IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState); |
| + JsIrBuilder._blank(this.program, this.jsState); |
| - JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement) |
| + JsIrBuilder(this.program, ConstantSystem constantSystem, |
| + ExecutableElement currentElement) |
| : jsState = new JsIrBuilderSharedState() { |
| _init(constantSystem, currentElement); |
| } |
| @@ -2204,6 +2217,16 @@ class JsIrBuilder extends IrBuilder { |
| void makeMutableVariable(Local local) {} |
| void removeMutableVariable(Local local) {} |
| + void enterInitializers() { |
| + assert(jsState.inInitializers == false); |
| + jsState.inInitializers = true; |
| + } |
| + |
| + void leaveInitializers() { |
| + assert(jsState.inInitializers == true); |
| + jsState.inInitializers = false; |
| + } |
| + |
| void _enterClosureEnvironment(ClosureEnvironment env) { |
| if (env == null) return; |
| @@ -2255,7 +2278,7 @@ class JsIrBuilder extends IrBuilder { |
| }); |
| } |
| - void _createFunctionParameter(ParameterElement parameterElement) { |
| + void _createFunctionParameter(Local parameterElement) { |
| ir.Parameter parameter = new ir.Parameter(parameterElement); |
| _parameters.add(parameter); |
| state.functionParameters.add(parameter); |
| @@ -2430,6 +2453,64 @@ class JsIrBuilder extends IrBuilder { |
| jsState.boxedVariables.addAll(closureScope.capturedVariables); |
| } |
| } |
| + |
| + @override |
| + ir.Primitive buildConstructorInvocation(FunctionElement element, |
| + Selector selector, |
| + InterfaceType type, |
| + List<ir.Primitive> arguments) { |
| + assert(isOpen); |
| + // TODO(karlklose): resolve effective target and type here or inline later? |
|
asgerf
2015/03/24 12:37:21
I don't understand this TODO. Please clarify or re
karlklose
2015/03/26 09:50:07
To implement redirecting factory constructors, we
|
| + ClassElement cls = element.enclosingClass; |
| + if (program.requiresRuntimeTypesFor(cls)) { |
| + Iterable<ir.Primitive> typeArguments = |
| + type.typeArguments.map((DartType argument) { |
| + return type.treatAsRaw |
| + ? buildNullLiteral() |
| + : buildTypeExpression(argument); |
| + }); |
| + arguments = new List<ir.Primitive>.from(arguments) |
| + ..addAll(typeArguments); |
| + } |
| + return _continueWithExpression( |
| + (k) => new ir.InvokeConstructor(type, element, selector, k, |
| + arguments)); |
| + } |
| + |
| + ir.Primitive buildTypeExpression(DartType type) { |
| + if (type is TypeVariableType) { |
| + return buildTypeVariableAccess(buildThis(), type); |
| + } else { |
| + assert(type is InterfaceType); |
| + // TODO(karlklose): optimization: share the type expression for variables. |
|
asgerf
2015/03/24 12:37:21
Doesn't seem worthwhile, considering how rarely it
karlklose
2015/03/26 09:50:07
Done.
|
| + List<ir.Primitive> arguments = <ir.Primitive>[]; |
| + type.forEachTypeVariable((TypeVariableType variable) { |
| + ir.Primitive value = buildTypeExpression(variable); |
|
asgerf
2015/03/24 12:37:21
It would be more clear to call buildTypeVariableAc
karlklose
2015/03/26 09:50:07
Done.
|
| + arguments.add(value); |
| + }); |
| + return addPrimitive(new ir.TypeExpression(type, arguments)); |
| + } |
| + } |
| + |
| + ir.Primitive buildTypeVariableAccess(ir.Primitive target, |
| + TypeVariableType variable) { |
| + ir.Parameter accessTypeArgumentParameter() { |
| + for (int i = 0; i < environment.length; i++) { |
| + Local local = environment.index2variable[i]; |
| + if (local is TypeInformationParameter && |
| + local.variable == variable.element) { |
| + return environment.index2value[i]; |
| + } |
| + } |
| + throw 'unable to find constructor parameter for type variable $variable.'; |
| + } |
|
asgerf
2015/03/24 12:37:21
IMO a better alternative is to implement == and ha
|
| + |
| + if (jsState.inInitializers) { |
| + return accessTypeArgumentParameter(); |
| + } else { |
| + return addPrimitive(new ir.ReadTypeVariable(variable, target)); |
| + } |
| + } |
| } |
| @@ -2501,3 +2582,12 @@ class CatchClauseInfo { |
| this.stackTraceVariable, |
| this.buildCatchBlock}); |
| } |
| + |
| +/// Synthetic parameter to a JavaScript factory method that takes the type |
| +/// argument given for the type variable [variable]. |
| +class TypeInformationParameter implements Local { |
| + final TypeVariableElement variable; |
| + final ExecutableElement executableContext; |
| + TypeInformationParameter(this.variable, this.executableContext); |
| + String get name => variable.name; |
| +} |