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

Unified Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ptal Created 5 years, 3 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
Index: pkg/compiler/lib/src/ssa/builder.dart
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index f9d87f94304cfb42add3c17338ba54c19881a5c1..76625f1c8fa53cbbb8e99d862bc72971d41273f7 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1297,6 +1297,11 @@ class SsaBuilder extends ast.Visitor
// enqueued.
backend.registerStaticUse(element, compiler.enqueuer.codegen);
+ if (element.isJsInterop && !element.isFactoryConstructor) {
+ // We only inline factory JavaScript interop constructors.
+ return false;
+ }
+
// Ensure that [element] is an implementation element.
element = element.implementation;
@@ -1327,6 +1332,8 @@ class SsaBuilder extends ast.Visitor
}
}
+ if (element.isJsInterop) return false;
+
// Don't inline operator== methods if the parameter can be null.
if (element.name == '==') {
if (element.enclosingClass != compiler.objectClass
@@ -1502,6 +1509,13 @@ class SsaBuilder extends ast.Visitor
});
}
+ /**
+ * Return null so it is simple to remove the optional parameters completely
+ * interop methods to match JavaScript semantics for ommitted arguments.
Siggi Cherem (dart-lang) 2015/09/18 20:34:10 completely interop => completely from interop?
Jacob 2015/10/01 00:47:33 Done.
+ */
+ HInstruction handleConstantForOptionalParameterJsInterop(Element parameter) =>
+ null;
+
HInstruction handleConstantForOptionalParameter(Element parameter) {
ConstantValue constantValue =
backend.constants.getConstantValueForVariable(parameter);
@@ -1596,10 +1610,19 @@ class SsaBuilder extends ast.Visitor
graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
ast.FunctionExpression function = functionElement.node;
assert(function != null);
- assert(!function.modifiers.isExternal);
assert(elements.getFunctionDefinition(function) != null);
openFunction(functionElement, function);
String name = functionElement.name;
+ if (functionElement.isJsInterop) {
+ push(invokeJsInteropFunction(functionElement, parameters.values.toList(), sourceInformationBuilder.buildGeneric(function)));
Siggi Cherem (dart-lang) 2015/09/18 20:34:10 long lines (here and below)
Jacob 2015/10/01 00:47:33 Done.
+ var value = pop();
+ closeAndGotoExit(new HReturn(value,
+ sourceInformationBuilder.buildReturn(functionElement.node)));
Siggi Cherem (dart-lang) 2015/09/18 20:34:10 indent
Jacob 2015/10/01 00:47:33 Done.
+ return closeFunction();
+ } else {
+ assert(!function.modifiers.isExternal);
+ }
+
// If [functionElement] is `operator==` we explicitely add a null check at
// the beginning of the method. This is to avoid having call sites do the
// null check.
@@ -1781,6 +1804,7 @@ class SsaBuilder extends ast.Visitor
*/
void visitInlinedFunction(FunctionElement function) {
potentiallyCheckInlinedParameterTypes(function);
+
if (function.isGenerativeConstructor) {
buildFactory(function);
} else {
@@ -2084,7 +2108,8 @@ class SsaBuilder extends ast.Visitor
ClassElement classElement =
functionElement.enclosingClass.implementation;
bool isNativeUpgradeFactory =
- Elements.isNativeOrExtendsNative(classElement);
+ Elements.isNativeOrExtendsNative(classElement)
+ && !classElement.isJsInterop;
ast.FunctionExpression function = functionElement.node;
// Note that constructors (like any other static function) do not need
// to deal with optional arguments. It is the callers job to provide all
@@ -3863,7 +3888,10 @@ class SsaBuilder extends ast.Visitor
arguments,
element,
compileArgument,
- handleConstantForOptionalParameter);
+ element.isJsInterop ?
+ handleConstantForOptionalParameterJsInterop :
+ handleConstantForOptionalParameter
+ );
}
void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> list) {
@@ -4998,7 +5026,8 @@ class SsaBuilder extends ast.Visitor
var inputs = <HInstruction>[];
if (constructor.isGenerativeConstructor &&
- Elements.isNativeOrExtendsNative(constructor.enclosingClass)) {
+ Elements.isNativeOrExtendsNative(constructor.enclosingClass) &&
+ !constructor.isJsInterop) {
// Native class generative constructors take a pre-constructed object.
inputs.add(graph.addConstantNull(compiler));
}
@@ -5726,6 +5755,96 @@ class SsaBuilder extends ast.Visitor
}
}
+ HForeignCode invokeJsInteropFunction(Element element,
+ List<HInstruction> arguments,
+ SourceInformation sourceInformation) {
+ assert(element.isJsInterop);
+ nativeEmitter.nativeMethods.add(element);
+ var templateString;
sra1 2015/10/01 17:34:30 The rest of this file uses local types. We have fo
Jacob 2015/10/02 20:08:15 Done. Tried to match the general style of builder.
+
+ if (element.isFactoryConstructor) {
+ // Treat factory constructors as syntactic sugar for creating object
+ // literals.
+ var templateParts = [];
+ var parameterValues = [];
+
+ FunctionSignature params = (element as ConstructorElement).functionSignature;
sra1 2015/10/01 17:34:30 The dart2js way is to use a local declaration: C
Jacob 2015/10/02 20:08:15 Done.
+ int i = 0;
+ int positions = 0;
+ var filteredArguments = <HInstruction>[];
+ var parameterNameMap = new Map<String, js.Expression>();
+ params.orderedForEachParameter((ParameterElement parameter) {
+ // TODO(jacobr): throw if parameter names do not match names of property
+ // names in the class.
+ assert (parameter.isNamed);
+ if (!parameter.isNamed) {
+ compiler.reportError(
+ parameter, MessageKind.GENERIC,
+ {'text': 'Error: all arguments to external constructors of'
+ 'JavaScript interop classes must be named as these'
+ 'constructors are syntactic sugar for object literals'});
+ }
+ var argument = arguments[i];
+ if (argument != null) {
+ filteredArguments.add(argument);
+ parameterNameMap[parameter.name] =
+ new js.InterpolatedExpression(positions++);
+ }
+ i++;
+ });
+ var codeTemplate = new js.Template(null,
+ js.objectLiteral(parameterNameMap));
+
+ var nativeBehavior = new native.NativeBehavior()
+ ..codeTemplate = codeTemplate;
+ return new HForeignCode(
+ codeTemplate,
+ backend.dynamicType, filteredArguments,
+ nativeBehavior: nativeBehavior)
+ ..sourceInformation = sourceInformation;
+ }
+ var target = new HForeignCode(js.js.parseForeignJS(
+ element.isInstanceMember ?
+ "this.${element.fixedBackendName}" : element.fixedBackendName),
+ backend.dynamicType,
+ <HInstruction>[]);
+ add(target);
+ // Strip off trailing arguments that were not specified.
+ // we could assert that the trailing arguments are all null.
+ // TODO(jacobr): rewrite named arguments to an object literal matching
+ // the factory constructor case.
+ arguments = arguments.where((arg) => arg != null).toList();
+ var inputs = [target]..addAll(arguments);
+
+ var codeTemplate;
+ if (element.isGetter) {
+ codeTemplate = js.js.parseForeignJS("#");
+ } else if (element.isSetter) {
+ codeTemplate = js.js.parseForeignJS("# = #");
+ } else {
+ var argsStub = [];
+ for (int i = 0; i < arguments.length; i++) {
+ argsStub.add('#');
+ }
+ if (element.isConstructor) {
+ codeTemplate = js.js.parseForeignJS("new #(${argsStub.join(",")})");
+ } else {
+ codeTemplate = js.js.parseForeignJS("#(${argsStub.join(",")})");
+ }
+ }
+
+ var nativeBehavior = new native.NativeBehavior()
+ ..codeTemplate = codeTemplate
+ ..typesReturned.add(backend.jsPlainJavaScriptObjectClass.computeType(compiler))
+ ..typesInstantiated.add(backend.jsPlainJavaScriptObjectClass.computeType(compiler))
+ ..sideEffects.setAllSideEffects();
+ return new HForeignCode(
+ codeTemplate,
+ backend.dynamicType, inputs,
+ nativeBehavior: nativeBehavior)
+ ..sourceInformation = sourceInformation;
+ }
+
void pushInvokeStatic(ast.Node location,
Element element,
List<HInstruction> arguments,
@@ -5744,16 +5863,21 @@ class SsaBuilder extends ast.Visitor
}
bool targetCanThrow = !compiler.world.getCannotThrow(element);
// TODO(5346): Try to avoid the need for calling [declaration] before
- // creating an [HInvokeStatic].
- HInvokeStatic instruction = new HInvokeStatic(
- element.declaration, arguments, typeMask,
- targetCanThrow: targetCanThrow)
- ..sourceInformation = sourceInformation;
- if (!currentInlinedInstantiations.isEmpty) {
- instruction.instantiatedTypes = new List<DartType>.from(
- currentInlinedInstantiations);
+ var instruction;
+ if (element.isJsInterop) {
+ instruction = invokeJsInteropFunction(element, arguments, sourceInformation);
+ } else {
+ // creating an [HInvokeStatic].
+ instruction = new HInvokeStatic(
+ element.declaration, arguments, typeMask,
+ targetCanThrow: targetCanThrow)
+ ..sourceInformation = sourceInformation;
+ if (!currentInlinedInstantiations.isEmpty) {
+ instruction.instantiatedTypes = new List<DartType>.from(
+ currentInlinedInstantiations);
+ }
+ instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
}
- instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
if (location == null) {
push(instruction);
} else {

Powered by Google App Engine
This is Rietveld 408576698