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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_emitter/nsm_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/nsm_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
index c298c5709861b6693c6e4c76b2c19688b2435630..0173cd9e4b7410884a397ec876e83fec9093f660 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/nsm_emitter.dart
@@ -63,10 +63,8 @@ class NsmEmitter extends CodeEmitterHelper {
jsAst.Expression generateMethod(String jsName, Selector selector) {
// Values match JSInvocationMirror in js-helper library.
int type = selector.invocationMirrorKind;
- List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
- for (int i = 0; i < selector.argumentCount; i++) {
- parameters.add(new jsAst.Parameter('\$$i'));
- }
+ List<String> parameterNames =
+ new List.generate(selector.argumentCount, (i) => '\$$i');
List<jsAst.Expression> argNames =
selector.getOrderedNamedArguments().map((String name) =>
@@ -83,20 +81,21 @@ class NsmEmitter extends CodeEmitterHelper {
}
assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
- jsAst.Expression expression = js('this.$noSuchMethodName')(
- [js('this'),
- namer.elementAccess(backend.getCreateInvocationMirror())([
- js.string(compiler.enableMinification ?
- internalName : methodName),
- js.string(internalName),
- type,
- new jsAst.ArrayInitializer.from(
- parameters.map((param) => js(param.name)).toList()),
- new jsAst.ArrayInitializer.from(argNames)])]);
- parameters = backend.isInterceptedName(selector.name)
- ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters))
- : parameters;
- return js.fun(parameters, js.return_(expression));
+ jsAst.Expression expression = js('this.#(this, #(#, #, #, #, #))', [
+ noSuchMethodName,
+ namer.elementAccess(backend.getCreateInvocationMirror()),
+ js.string(compiler.enableMinification ?
+ internalName : methodName),
+ js.string(internalName),
+ js.number(type),
+ new jsAst.ArrayInitializer.from(parameterNames.map(js)),
+ new jsAst.ArrayInitializer.from(argNames)]);
+
+ if (backend.isInterceptedName(selector.name)) {
+ return js(r'function($receiver, #) { return # }', [parameterNames, expression]);
floitsch 2014/04/22 16:11:18 long line.
sra1 2014/04/23 02:33:50 Done.
+ } else {
+ return js(r'function(#) { return # }', [parameterNames, expression]);
+ }
}
for (String jsName in addedJsNames.keys.toList()..sort()) {
@@ -176,8 +175,9 @@ class NsmEmitter extends CodeEmitterHelper {
* they are called with the receiver as the first argument). They need a
* slightly different noSuchMethod handler, so we handle these first.
*/
- void addTrivialNsmHandlers(List<jsAst.Node> statements) {
- if (trivialNsmHandlers.length == 0) return;
+ List<jsAst.Statement> buildTrivialNsmHandlers() {
+ List<jsAst.Statement> statements = <jsAst.Statement>[];
+ if (trivialNsmHandlers.length == 0) return statements;
// Sort by calling convention, JS name length and by JS name.
trivialNsmHandlers.sort((a, b) {
bool aIsIntercepted = backend.isInterceptedName(a.name);
@@ -268,106 +268,120 @@ class NsmEmitter extends CodeEmitterHelper {
// Startup code that loops over the method names and puts handlers on the
// Object class to catch noSuchMethod invocations.
ClassElement objectClass = compiler.objectClass;
- String createInvocationMirror = namer.isolateAccess(
+ jsAst.Expression createInvocationMirror = namer.elementAccess(
backend.getCreateInvocationMirror());
String noSuchMethodName = namer.publicInstanceMethodNameByArity(
Compiler.NO_SUCH_METHOD, Compiler.NO_SUCH_METHOD_ARG_COUNT);
var type = 0;
if (useDiffEncoding) {
- statements.addAll([
- js('var objectClassObject = '
- ' collectedClasses["${namer.getNameOfClass(objectClass)}"],'
- ' shortNames = "$diffEncoding".split(","),'
- ' nameNumber = 0,'
- ' diffEncodedString = shortNames[0],'
- ' calculatedShortNames = [0, 1]'), // 0, 1 are args for splice.
- // If we are loading a deferred library the object class will not be in
- // the collectedClasses so objectClassObject is undefined, and we skip
- // setting up the names.
- js.if_('objectClassObject', [
- js.if_('objectClassObject instanceof Array',
- js('objectClassObject = objectClassObject[1]')),
- js.for_('var i = 0', 'i < diffEncodedString.length', 'i++', [
- js('var codes = [],'
- ' diff = 0,'
- ' digit = diffEncodedString.charCodeAt(i)'),
- js.if_('digit == ${$PERIOD}', [
- js('nameNumber = 0'),
- js('digit = diffEncodedString.charCodeAt(++i)')
- ]),
- js.while_('digit <= ${$Z}', [
- js('diff *= 26'),
- js('diff += (digit - ${$A})'),
- js('digit = diffEncodedString.charCodeAt(++i)')
- ]),
- js('diff *= 26'),
- js('diff += (digit - ${$a})'),
- js('nameNumber += diff'),
- js.for_('var remaining = nameNumber',
- 'remaining > 0',
- 'remaining = (remaining / 88) | 0', [
- js('codes.unshift(${$HASH} + remaining % 88)')
- ]),
- js('calculatedShortNames.push('
- ' String.fromCharCode.apply(String, codes))')
- ]),
- js('shortNames.splice.apply(shortNames, calculatedShortNames)')])
- ]);
+ statements.add(js.statement('''{
+ var objectClassObject =
+ collectedClasses[#], // # is name of class Object.
+ shortNames = #.split(","), // # is diffEncoding.
+ nameNumber = 0,
+ diffEncodedString = shortNames[0],
+ calculatedShortNames = [0, 1]; // 0, 1 are args for splice.
+ // If we are loading a deferred library the object class will not be in
floitsch 2014/04/22 16:11:18 long line.
+ // the collectedClasses so objectClassObject is undefined, and we skip
+ // setting up the names.
+
+ if (objectClassObject) {
+ if (objectClassObject instanceof Array)
+ objectClassObject = objectClassObject[1];
+ for (var i = 0; i < diffEncodedString.length; i++) {
+ var codes = [],
+ diff = 0,
+ digit = diffEncodedString.charCodeAt(i);
+ if (digit == ${$PERIOD}) {
+ nameNumber = 0;
+ digit = diffEncodedString.charCodeAt(++i);
+ }
+ for (; digit <= ${$Z};) {
+ diff *= 26;
+ diff += (digit - ${$A});
+ digit = diffEncodedString.charCodeAt(++i);
+ }
+ diff *= 26;
+ diff += (digit - ${$a});
+ nameNumber += diff;
+ for (var remaining = nameNumber;
+ remaining > 0;
+ remaining = (remaining / 88) | 0) {
+ codes.unshift(${$HASH} + remaining % 88);
+ }
+ calculatedShortNames.push(
+ String.fromCharCode.apply(String, codes));
+ }
+ shortNames.splice.apply(shortNames, calculatedShortNames);
+ }
+ }''', [
+ js.string(namer.getNameOfClass(objectClass)),
+ js.string('$diffEncoding')]));
} else {
// No useDiffEncoding version.
Iterable<String> longs = trivialNsmHandlers.map((selector) =>
selector.invocationMirrorMemberName);
- String longNamesConstant = minify ? "" :
- ',longNames = "${longs.join(",")}".split(",")';
- statements.add(
- js('var objectClassObject = '
- ' collectedClasses["${namer.getNameOfClass(objectClass)}"],'
- ' shortNames = "$diffEncoding".split(",")'
- ' $longNamesConstant'));
- statements.add(
- js.if_('objectClassObject instanceof Array',
- js('objectClassObject = objectClassObject[1]')));
+ statements.add(js.statement(
+ 'var objectClassObject = collectedClasses[#],'
+ ' shortNames = #.split(",")', [
+ js.string(namer.getNameOfClass(objectClass)),
+ js.string('$diffEncoding')]));
+ if (!minify) {
+ statements.add(js.statement('var longNames = #.split(",")',
+ js.string(longs.join(','))));
+ }
+ statements.add(js.statement(
+ 'if (objectClassObject instanceof Array)'
+ ' objectClassObject = objectClassObject[1];'));
}
- String sliceOffset = ', (j < $firstNormalSelector) ? 1 : 0';
- if (firstNormalSelector == 0) sliceOffset = '';
- if (firstNormalSelector == shorts.length) sliceOffset = ', 1';
-
+ // TODO(9631): This is no longer valid for native methods.
String whatToPatch = task.nativeEmitter.handleNoSuchMethod ?
"Object.prototype" :
"objectClassObject";
- var params = ['name', 'short', 'type'];
- var sliceOffsetParam = '';
- var slice = 'Array.prototype.slice.call';
- if (!sliceOffset.isEmpty) {
- sliceOffsetParam = ', sliceOffset';
- params.add('sliceOffset');
- }
- statements.addAll([
+ List<jsAst.Expression> sliceOffsetArguments =
+ firstNormalSelector == 0
+ ? []
+ : (firstNormalSelector == shorts.length
+ ? [js.number(1)]
+ : [js('(j < #) ? 1 : 0', js.number(firstNormalSelector))]);
+
+ var sliceOffsetParams = sliceOffsetArguments.isEmpty ? [] : ['sliceOffset'];
+
+ statements.add(js.statement('''
// If we are loading a deferred library the object class will not be in
// the collectedClasses so objectClassObject is undefined, and we skip
// setting up the names.
- js.if_('objectClassObject', [
- js.for_('var j = 0', 'j < shortNames.length', 'j++', [
- js('var type = 0'),
- js('var short = shortNames[j]'),
- js.if_('short[0] == "${namer.getterPrefix[0]}"', js('type = 1')),
- js.if_('short[0] == "${namer.setterPrefix[0]}"', js('type = 2')),
+ if (objectClassObject) {
+ for (var j = 0; j < shortNames.length; j++) {
+ var type = 0;
+ var short = shortNames[j];
+ if (short[0] == "${namer.getterPrefix[0]}") type = 1;
+ if (short[0] == "${namer.setterPrefix[0]}") type = 2;
// Generate call to:
- // createInvocationMirror(String name, internalName, type, arguments,
- // argumentNames)
- js('$whatToPatch[short] = #(${minify ? "shortNames" : "longNames"}[j], '
- 'short, type$sliceOffset)',
- js.fun(params, [js.return_(js.fun([],
- [js.return_(js(
- 'this.$noSuchMethodName('
- 'this, '
- '$createInvocationMirror('
- 'name, short, type, '
- '$slice(arguments$sliceOffsetParam), []))'))]))]))
- ])
- ])
- ]);
+ //
+ // createInvocationMirror(String name, internalName, type,
+ // arguments, argumentNames)
+ //
+ $whatToPatch[short] = (function(name, short, type, #) {
+ return function() {
+ return this.#(this,
+ #(name, short, type,
+ Array.prototype.slice.call(arguments, #),
+ []));
+ }
+ })(#[j], short, type, #);
+ }
+ }''', [
+ sliceOffsetParams, // parameter
+ noSuchMethodName,
+ createInvocationMirror,
+ sliceOffsetParams, // argument to slice
+ minify ? 'shortNames' : 'longNames',
+ sliceOffsetArguments
+ ]));
+
+ return statements;
}
}

Powered by Google App Engine
This is Rietveld 408576698