Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(326)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1288013002: dart2js cps: Handle native functions, getters, and setters. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..d1461fc838d07c113de8da951b130f782369820d 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,88 @@ 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]);
+ }
+
+ final RegExp nativeRedirectionRegExp =
+ new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');
asgerf 2015/08/12 13:15:02 Make this static?
+
+ /// Generate the body for a native function.
+ ///
+ /// If [nativeBody] is non-null, generate a [ForeignCode] statement for the
+ /// body defined in JavaScript. Otherwise, generate a call to the real
+ /// target, which is given by the [FunctionElement]'s `fixedBackendName`.
+ /// The target can be a function, getter, or setter.
+ void buildNativeFunctionBody(ast.Node nativeBody,
+ SourceInformation source) {
+ FunctionElement function = state.currentElement;
+ assert(function.isNative);
+ String name = function.fixedBackendName;
+ List<ir.Primitive> arguments = <ir.Primitive>[];
+ NativeBehavior behavior = new NativeBehavior();
+ behavior.sideEffects.setAllSideEffects();
+
+ if (nativeBody != null) {
asgerf 2015/08/12 13:15:02 I think it would make more sense to have this spli
+ ast.LiteralString jsCode = nativeBody.asLiteralString();
+ String code = jsCode.dartString.slowToString();
+ assert(invariant(nativeBody, !nativeRedirectionRegExp.hasMatch(code),
+ message: "Deprecated syntax, use @JSName('name') instead."));
+ assert(invariant(nativeBody,
+ function.functionSignature.parameterCount == 0,
+ message: 'native "..." syntax is restricted to '
+ 'functions with zero parameters.'));
+ // Generate a [ForeignCode] statement from the given native code.
+ buildForeignCode(
+ js.js.statementTemplateYielding(new js.LiteralStatement(code)),
+ <ir.Primitive>[],
+ behavior);
+ } else {
+ 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 +2681,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 +2691,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;
}
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698