| 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 77806c00c334282149e35f446964ba6b83a99a65..c9886775cb8ac9f8777a31b4380c3246b5df65fc 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| @@ -20,7 +20,7 @@ import 'cps_ir_builder_task.dart' show DartCapturedVariables,
|
| GlobalProgramInformation;
|
|
|
| import '../common.dart' as types show TypeMask;
|
| -import '../js/js.dart' as js show Template;
|
| +import '../js/js.dart' as js show Template, js, LiteralStatement;
|
| import '../native/native.dart' show NativeBehavior;
|
|
|
| /// A mapping from variable elements to their compile-time values.
|
| @@ -2025,6 +2025,80 @@ class IrBuilder {
|
| }
|
| }
|
|
|
| + /// Build a call to the closure conversion helper for the [Function] typed
|
| + /// value in [value].
|
| + ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) {
|
| + ir.Constant arity = buildIntegerConstant(type.computeArity());
|
| + return buildStaticFunctionInvocation(
|
| + program.closureConverter,
|
| + CallStructure.TWO_ARGS,
|
| + <ir.Primitive>[value, arity]);
|
| + }
|
| +
|
| + /// Generate the body for a native function [function] that is annotated with
|
| + /// an implementation in JavaScript (provided as string in [javaScriptCode]).
|
| + void buildNativeFunctionBody(FunctionElement function,
|
| + String javaScriptCode) {
|
| + NativeBehavior behavior = new NativeBehavior();
|
| + behavior.sideEffects.setAllSideEffects();
|
| + // Generate a [ForeignCode] statement from the given native code.
|
| + buildForeignCode(
|
| + js.js.statementTemplateYielding(
|
| + new js.LiteralStatement(javaScriptCode)),
|
| + <ir.Primitive>[],
|
| + behavior);
|
| + }
|
| +
|
| + /// Generate the body for a native function that redirects to a native
|
| + /// JavaScript function, getter, or setter.
|
| + ///
|
| + /// Generates a call to the real target, which is given by [functions]'s
|
| + /// `fixedBackendName`, passing all parameters as arguments. The target can
|
| + /// be the JavaScript implementation of a function, getter, or setter.
|
| + void buildRedirectingNativeFunctionBody(FunctionElement function,
|
| + SourceInformation source) {
|
| + String name = function.fixedBackendName;
|
| + List<ir.Primitive> arguments = <ir.Primitive>[];
|
| + NativeBehavior behavior = new NativeBehavior();
|
| + behavior.sideEffects.setAllSideEffects();
|
| + program.addNativeMethod(function);
|
| + // Construct the access of the target element.
|
| + String code = function.isInstanceMember ? '#.$name' : name;
|
| + if (function.isInstanceMember) {
|
| + arguments.add(state.thisParameter);
|
| + }
|
| + // Collect all parameters of the function and templates for them to be
|
| + // inserted into the JavaScript code.
|
| + List<String> argumentTemplates = <String>[];
|
| + function.functionSignature.forEachParameter((ParameterElement parameter) {
|
| + ir.Primitive input = environment.lookup(parameter);
|
| + DartType type = program.unaliasType(parameter.type);
|
| + if (type is FunctionType) {
|
| + // The parameter type is a function type either directly or through
|
| + // typedef(s).
|
| + input = _convertDartClosure(input, type);
|
| + }
|
| + arguments.add(input);
|
| + argumentTemplates.add('#');
|
| + });
|
| + // Construct the application of parameters for functions and setters.
|
| + if (function.kind == ElementKind.FUNCTION) {
|
| + code = "$code(${argumentTemplates.join(', ')})";
|
| + } else if (function.kind == ElementKind.SETTER) {
|
| + code = "$code = ${argumentTemplates.single}";
|
| + } else {
|
| + assert(argumentTemplates.isEmpty);
|
| + assert(function.kind == ElementKind.GETTER);
|
| + }
|
| + // Generate the [ForeignCode] expression and a return statement to return
|
| + // its value.
|
| + ir.Primitive value = buildForeignCode(
|
| + js.js.uncachedExpressionTemplate(code),
|
| + arguments,
|
| + behavior);
|
| + buildReturn(value: value, sourceInformation: source);
|
| + }
|
| +
|
| /// Create a blocks of [statements] by applying [build] to all reachable
|
| /// statements. The first statement is assumed to be reachable.
|
| // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
|
| @@ -2599,6 +2673,7 @@ class IrBuilder {
|
| List<ir.Primitive> arguments,
|
| NativeBehavior behavior,
|
| {Element dependency}) {
|
| + assert(behavior != null);
|
| types.TypeMask type = program.getTypeMaskForForeign(behavior);
|
| ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode(
|
| codeTemplate,
|
| @@ -2608,7 +2683,7 @@ class IrBuilder {
|
| k,
|
| dependency: dependency));
|
| if (!codeTemplate.isExpression) {
|
| - // Close the term if this is a "throw" expression.
|
| + // Close the term if this is a "throw" expression or native body.
|
| add(new ir.Unreachable());
|
| _current = null;
|
| }
|
|
|