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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart

Issue 237583014: JS templates (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: cleanup Created 6 years, 8 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: sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
index c57a42c00c01723b33e586d8bbed216864cbc131..b879750bd3c63836a4ae7bd136c88a4549b6a187 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/interceptor_emitter.dart
@@ -29,13 +29,13 @@ class InterceptorEmitter extends CodeEmitterHelper {
void emitGetInterceptorMethod(CodeBuffer buffer,
String key,
Set<ClassElement> classes) {
- jsAst.Statement buildReturnInterceptor(ClassElement cls) {
- return js.return_(js(namer.isolateAccess(cls))['prototype']);
+ jsAst.Expression interceptorFor(ClassElement cls) {
+ return js('#.prototype', namer.elementAccess(cls));
}
/**
* Build a JavaScrit AST node for doing a type check on
- * [cls]. [cls] must be an interceptor class.
+ * [cls]. [cls] must be a non-native interceptor class.
*/
jsAst.Statement buildInterceptorCheck(ClassElement cls) {
jsAst.Expression condition;
@@ -58,7 +58,7 @@ class InterceptorEmitter extends CodeEmitterHelper {
} else {
throw 'internal error';
}
- return js.if_(condition, buildReturnInterceptor(cls));
+ return js.statement('if (#) return #', [condition, interceptorFor(cls)]);
}
bool hasArray = false;
@@ -108,7 +108,7 @@ class InterceptorEmitter extends CodeEmitterHelper {
hasNative = anyNativeClasses;
}
- jsAst.Block block = new jsAst.Block.empty();
+ List<Statement> statements = <Statement>[];
if (hasNumber) {
jsAst.Statement whenNumber;
@@ -117,75 +117,67 @@ class InterceptorEmitter extends CodeEmitterHelper {
/// and JavaScript's Number (typeof receiver == 'number'). This
/// is the fallback used when we have determined that receiver
/// is a JavaScript Number.
- jsAst.Return returnNumberClass = buildReturnInterceptor(
+ jsAst.Expression interceptorForNumber = interceptorFor(
hasDouble ? backend.jsDoubleClass : backend.jsNumberClass);
if (hasInt) {
- jsAst.Expression isInt = js('Math.floor(receiver) == receiver');
- whenNumber = js.block([
- js.if_(isInt, buildReturnInterceptor(backend.jsIntClass)),
- returnNumberClass]);
+ whenNumber = js.statement('''{
+ if (Math.floor(receiver) == receiver) return #;
+ return #;
+ }''', [interceptorFor(backend.jsIntClass), interceptorForNumber]);
} else {
- whenNumber = returnNumberClass;
+ whenNumber = js.statement('return #', interceptorForNumber);
}
- block.statements.add(
- js.if_('(typeof receiver) == "number"',
- whenNumber));
+ statements.add(
+ js.statement('if (typeof receiver == "number") #;', whenNumber));
}
if (hasString) {
- block.statements.add(buildInterceptorCheck(backend.jsStringClass));
+ statements.add(buildInterceptorCheck(backend.jsStringClass));
}
if (hasNull) {
- block.statements.add(buildInterceptorCheck(backend.jsNullClass));
+ statements.add(buildInterceptorCheck(backend.jsNullClass));
} else {
// Returning "undefined" or "null" here will provoke a JavaScript
// TypeError which is later identified as a null-error by
// [unwrapException] in js_helper.dart.
- block.statements.add(js.if_('receiver == null',
- js.return_(js('receiver'))));
+ statements.add(
+ js.statement('if (receiver == null) return receiver'));
}
if (hasBool) {
- block.statements.add(buildInterceptorCheck(backend.jsBoolClass));
+ statements.add(buildInterceptorCheck(backend.jsBoolClass));
}
// TODO(ahe): It might be faster to check for Array before
// function and bool.
if (hasArray) {
- block.statements.add(buildInterceptorCheck(backend.jsArrayClass));
+ statements.add(buildInterceptorCheck(backend.jsArrayClass));
}
if (hasNative) {
- block.statements.add(
- js.if_(
- js('(typeof receiver) != "object"'),
- js.return_(js('receiver'))));
-
- // if (receiver instanceof $.Object) return receiver;
- // return $.getNativeInterceptor(receiver);
- block.statements.add(
- js.if_(js('receiver instanceof #',
- js(namer.isolateAccess(compiler.objectClass))),
- js.return_(js('receiver'))));
- block.statements.add(
- js.return_(
- js(namer.isolateAccess(backend.getNativeInterceptorMethod))(
- ['receiver'])));
+ statements.add(js.statement(r'''{
+ if (typeof receiver != "object") return receiver;
+ if (receiver instanceof #) return receiver;
+ return #(receiver);
+ }''', [
+ namer.elementAccess(compiler.objectClass),
+ namer.elementAccess(backend.getNativeInterceptorMethod)]));
} else {
ClassElement jsUnknown = backend.jsUnknownJavaScriptObjectClass;
if (compiler.codegenWorld.instantiatedClasses.contains(jsUnknown)) {
- block.statements.add(
- js.if_(js('!(receiver instanceof #)',
- js(namer.isolateAccess(compiler.objectClass))),
- buildReturnInterceptor(jsUnknown)));
+ statements.add(
+ js.statement('if (!(receiver instanceof #)) return #;',
+ [namer.elementAccess(compiler.objectClass),
+ interceptorFor(jsUnknown)]));
}
- block.statements.add(js.return_(js('receiver')));
+ statements.add(js.statement('return receiver'));
}
buffer.write(jsAst.prettyPrint(
- js('${namer.globalObjectFor(compiler.interceptorsLibrary)}.$key = #',
- js.fun(['receiver'], block)),
+ js('''${namer.globalObjectFor(compiler.interceptorsLibrary)}.# =
+ function(receiver) { #; }''',
+ [key, statements]),
compiler));
buffer.write(N);
}
@@ -208,37 +200,15 @@ class InterceptorEmitter extends CodeEmitterHelper {
// fast path.
jsAst.Statement fastPathForOneShotInterceptor(Selector selector,
Set<ClassElement> classes) {
- jsAst.Expression isNumber(String variable) {
- return js('typeof $variable == "number"');
- }
-
- jsAst.Expression isNotObject(String variable) {
- return js('typeof $variable != "object"');
- }
-
- jsAst.Expression isInt(String variable) {
- return isNumber(variable).binary('&&',
- js('Math.floor($variable) == $variable'));
- }
-
- jsAst.Expression tripleShiftZero(jsAst.Expression receiver) {
- return receiver.binary('>>>', js('0'));
- }
if (selector.isOperator()) {
String name = selector.name;
if (name == '==') {
- // Unfolds to:
- // if (receiver == null) return a0 == null;
- // if (typeof receiver != 'object') {
- // return a0 != null && receiver === a0;
- // }
- List<jsAst.Statement> body = <jsAst.Statement>[];
- body.add(js.if_('receiver == null', js.return_(js('a0 == null'))));
- body.add(js.if_(
- isNotObject('receiver'),
- js.return_(js('a0 != null && receiver === a0'))));
- return new jsAst.Block(body);
+ return js.statement('''{
+ if (receiver == null) return a0 == null;
+ if (typeof receiver != "object")
+ return a0 != null && receiver === a0;
+ }''');
}
if (!classes.contains(backend.jsIntClass)
&& !classes.contains(backend.jsNumberClass)
@@ -246,29 +216,27 @@ class InterceptorEmitter extends CodeEmitterHelper {
return null;
}
if (selector.argumentCount == 1) {
- // The following operators do not map to a JavaScript
- // operator.
+ // The following operators do not map to a JavaScript operator.
if (name == '~/' || name == '<<' || name == '%' || name == '>>') {
return null;
}
- jsAst.Expression result = js('receiver').binary(name, js('a0'));
+ jsAst.Expression result = js('receiver $name a0');
if (name == '&' || name == '|' || name == '^') {
- result = tripleShiftZero(result);
+ result = js('# >>> 0', result);
}
- // Unfolds to:
- // if (typeof receiver == "number" && typeof a0 == "number")
- // return receiver op a0;
- return js.if_(
- isNumber('receiver').binary('&&', isNumber('a0')),
- js.return_(result));
+ return js.statement(
+ 'if (typeof receiver == "number" && typeof a0 == "number")'
+ ' return #;',
+ result);
} else if (name == 'unary-') {
- // [: if (typeof receiver == "number") return -receiver :].
- return js.if_(isNumber('receiver'),
- js.return_(js('-receiver')));
+ return js.statement(
+ 'if (typeof receiver == "number") return -receiver');
} else {
assert(name == '~');
- return js.if_(isInt('receiver'),
- js.return_(js('~receiver >>> 0')));
+ return js.statement('''
+ if (typeof receiver == "number" && Math.floor(receiver) == receiver)
+ return (~receiver) >>> 0;
+ ''');
}
} else if (selector.isIndex() || selector.isIndexSet()) {
// For an index operation, this code generates:
@@ -302,34 +270,33 @@ class InterceptorEmitter extends CodeEmitterHelper {
if (!containsArray && !containsString) {
return null;
}
- jsAst.Expression isIntAndAboveZero = js('a0 >>> 0 === a0');
- jsAst.Expression belowLength = js('a0 < receiver.length');
jsAst.Expression arrayCheck = js('receiver.constructor == Array');
jsAst.Expression indexableCheck =
backend.generateIsJsIndexableCall(js('receiver'), js('receiver'));
jsAst.Expression orExp(left, right) {
- return left == null ? right : left.binary('||', right);
+ return left == null ? right : js('# || #', [left, right]);
}
if (selector.isIndex()) {
- jsAst.Expression stringCheck = js('typeof receiver == "string"');
jsAst.Expression typeCheck;
if (containsArray) {
typeCheck = arrayCheck;
}
if (containsString) {
- typeCheck = orExp(typeCheck, stringCheck);
+ typeCheck = orExp(typeCheck, js('typeof receiver == "string"'));
}
if (containsJsIndexable) {
typeCheck = orExp(typeCheck, indexableCheck);
}
- return js.if_(typeCheck,
- js.if_(isIntAndAboveZero.binary('&&', belowLength),
- js.return_(js('receiver[a0]'))));
+ return js.statement('''
+ if (#)
+ if ((a0 >>> 0) === a0 && a0 < receiver.length)
+ return receiver[a0];
+ ''', typeCheck);
} else {
jsAst.Expression typeCheck;
if (containsArray) {
@@ -340,11 +307,11 @@ class InterceptorEmitter extends CodeEmitterHelper {
typeCheck = orExp(typeCheck, indexableCheck);
}
- jsAst.Expression isImmutableArray = typeCheck.binary(
- '&&', js(r'!receiver.immutable$list'));
- return js.if_(isImmutableArray.binary(
- '&&', isIntAndAboveZero.binary('&&', belowLength)),
- js.return_(js('receiver[a0] = a1')));
+ return js.statement(r'''
+ if (# && !receiver.immutable$list &&
+ (a0 >>> 0) === a0 && a0 < receiver.length)
+ return receiver[a0] = a1;
+ ''', typeCheck);
}
}
return null;
@@ -360,37 +327,30 @@ class InterceptorEmitter extends CodeEmitterHelper {
String getInterceptorName =
namer.getInterceptorName(backend.getInterceptorMethod, classes);
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- List<jsAst.Expression> arguments = <jsAst.Expression>[];
- parameters.add(new jsAst.Parameter('receiver'));
- arguments.add(js('receiver'));
+ List<String> parameterNames = <String>[];
+ parameterNames.add('receiver');
if (selector.isSetter()) {
- parameters.add(new jsAst.Parameter('value'));
- arguments.add(js('value'));
+ parameterNames.add('value');
} else {
for (int i = 0; i < selector.argumentCount; i++) {
- String argName = 'a$i';
- parameters.add(new jsAst.Parameter(argName));
- arguments.add(js(argName));
+ parameterNames.add('a$i');
}
}
- List<jsAst.Statement> body = <jsAst.Statement>[];
- jsAst.Statement optimizedPath =
- fastPathForOneShotInterceptor(selector, classes);
- if (optimizedPath != null) {
- body.add(optimizedPath);
- }
-
String invocationName = backend.namer.invocationName(selector);
String globalObject = namer.globalObjectFor(compiler.interceptorsLibrary);
- body.add(js.return_(
- js(globalObject)[getInterceptorName]('receiver')[invocationName](
- arguments)));
- jsAst.Expression assignment =
- js('${globalObject}.$name = #', js.fun(parameters, body));
+ jsAst.Statement optimizedPath =
+ fastPathForOneShotInterceptor(selector, classes);
+ if (optimizedPath == null) optimizedPath = js.statement(';');
+
+ jsAst.Expression assignment = js('${globalObject}.# = function(#) {'
+ ' #;'
+ ' return #.#(receiver).#(#) }',
+ [name, parameterNames,
+ optimizedPath,
+ globalObject, getInterceptorName, invocationName, parameterNames]);
buffer.write(jsAst.prettyPrint(assignment, compiler));
buffer.write(N);
@@ -425,7 +385,7 @@ class InterceptorEmitter extends CodeEmitterHelper {
new jsAst.ArrayInitializer(invocationNames.length, elements);
jsAst.Expression assignment =
- js('${task.isolateProperties}.$name = #', array);
+ js('${task.isolateProperties}.# = #', [name, array]);
buffer.write(jsAst.prettyPrint(assignment, compiler));
buffer.write(N);
@@ -490,7 +450,7 @@ class InterceptorEmitter extends CodeEmitterHelper {
String name =
backend.namer.getNameOfGlobalField(backend.mapTypeToInterceptor);
jsAst.Expression assignment =
- js('${task.isolateProperties}.$name = #', array);
+ js('${task.isolateProperties}.# = #', [name, array]);
buffer.write(jsAst.prettyPrint(assignment, compiler));
buffer.write(N);

Powered by Google App Engine
This is Rietveld 408576698