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

Unified Diff: pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart

Issue 1198293002: dart2js: Use an abstract Name class for names in the generated JavaScript ast. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix new emitter. Created 5 years, 6 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/js_emitter/old_emitter/nsm_emitter.dart
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
index ca49a9eb57fd98d5b6645b82a458e1465bee919a..8a81f455788ef2108d6cfcb42f05867e51e6e10b 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
@@ -25,7 +25,7 @@ class NsmEmitter extends CodeEmitterHelper {
// Keep track of the JavaScript names we've already added so we
// do not introduce duplicates (bad for code size).
- Map<String, Selector> addedJsNames
+ Map<jsAst.Name, Selector> addedJsNames
= generator.computeSelectorsForNsmHandlers();
// Set flag used by generateMethod helper below. If we have very few
@@ -33,7 +33,8 @@ class NsmEmitter extends CodeEmitterHelper {
// them at runtime.
bool haveVeryFewNoSuchMemberHandlers =
(addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
- for (String jsName in addedJsNames.keys.toList()..sort()) {
+ List<jsAst.Name> names = addedJsNames.keys.toList()..sort();
floitsch 2015/06/22 17:43:45 sort on a different line?
herhut 2015/06/23 13:26:32 Done.
+ for (jsAst.Name jsName in names) {
Selector selector = addedJsNames[jsName];
String reflectionName = emitter.getReflectionName(selector, jsName);
@@ -57,7 +58,8 @@ class NsmEmitter extends CodeEmitterHelper {
bool accessible =
compiler.world.allFunctions.filter(selector, null).any(
(Element e) => backend.isAccessibleByReflection(e));
- addProperty('+$reflectionName', js(accessible ? '2' : '0'));
+ addProperty(namer.asName('+$reflectionName'),
+ js(accessible ? '2' : '0'));
}
}
}
@@ -66,23 +68,25 @@ class NsmEmitter extends CodeEmitterHelper {
// Identify the noSuchMethod handlers that are so simple that we can
// generate them programatically.
bool isTrivialNsmHandler(
- int type, List argNames, Selector selector, String internalName) {
+ int type, List argNames, Selector selector, jsAst.Name internalName) {
if (!generateTrivialNsmHandlers) return false;
// Check for interceptor calling convention.
if (backend.isInterceptedName(selector.name)) {
floitsch 2015/06/22 17:43:45 TBH I don't see why we do special casing for the i
herhut 2015/06/23 13:26:31 This is probably an artifact. I checked the decode
// We can handle the calling convention used by intercepted names in the
// diff encoding, but we don't use that for non-minified code.
if (!compiler.enableMinification) return false;
- String shortName = namer.invocationMirrorInternalName(selector);
- if (shortName.length > MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
- return false;
- }
+ // TODO(herhut): We can no longer answer the below with the late bound
+ // names. However, names longer than 4 are bad anyway.
+ // jsAst.Name shortName = namer.invocationMirrorInternalName(selector);
+ // if (shortName.length > MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
+ // return false;
+ // }
}
// Check for named arguments.
if (argNames.length != 0) return false;
// Check for unexpected name (this doesn't really happen).
- if (internalName.startsWith(namer.getterPrefix[0])) return type == 1;
- if (internalName.startsWith(namer.setterPrefix[0])) return type == 2;
+ if (internalName is GetterName) return type == 1;
+ if (internalName is SetterName) return type == 2;
return type == 0;
}
@@ -128,14 +132,13 @@ class NsmEmitter extends CodeEmitterHelper {
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.
+ // Sort by calling convention and by JS name.
trivialNsmHandlers.sort((a, b) {
bool aIsIntercepted = backend.isInterceptedName(a.name);
bool bIsIntercepted = backend.isInterceptedName(b.name);
if (aIsIntercepted != bIsIntercepted) return aIsIntercepted ? -1 : 1;
- String aName = namer.invocationMirrorInternalName(a);
- String bName = namer.invocationMirrorInternalName(b);
- if (aName.length != bName.length) return aName.length - bName.length;
+ jsAst.Name aName = namer.invocationMirrorInternalName(a);
+ jsAst.Name bName = namer.invocationMirrorInternalName(b);
return aName.compareTo(bName);
sra1 2015/06/23 04:47:54 How does this work? jsAst.Name does not implement
herhut 2015/06/23 13:26:32 Done.
});
@@ -150,68 +153,19 @@ class NsmEmitter extends CodeEmitterHelper {
}
// Get the short names (JS names, perhaps minified).
- Iterable<String> shorts = trivialNsmHandlers.map((selector) =>
- namer.invocationMirrorInternalName(selector));
- var diffEncoding = new StringBuffer();
-
- // Treat string as a number in base 88 with digits in ASCII order from # to
- // z. The short name sorting is based on length, and uses ASCII order for
- // equal length strings so this means that names are ascending. The hash
- // character, #, is never given as input, but we need it because it's the
- // implicit leading zero (otherwise we could not code names with leading
- // dollar signs).
- int fromBase88(String x) {
- int answer = 0;
- for (int i = 0; i < x.length; i++) {
- int c = x.codeUnitAt(i);
- // No support for Unicode minified identifiers in JS.
- assert(c >= $$ && c <= $z);
- answer *= 88;
- answer += c - $HASH;
- }
- return answer;
- }
-
- // Big endian encoding, A = 0, B = 1...
- // A lower case letter terminates the number.
- String toBase26(int x) {
- int c = x;
- var encodingChars = <int>[];
- encodingChars.add($a + (c % 26));
- while (true) {
- c ~/= 26;
- if (c == 0) break;
- encodingChars.add($A + (c % 26));
- }
- return new String.fromCharCodes(encodingChars.reversed.toList());
- }
+ Iterable<jsAst.Name> shorts = trivialNsmHandlers.map((selector) =>
+ namer.invocationMirrorInternalName(selector));
floitsch 2015/06/22 17:43:45 indentation.
herhut 2015/06/23 13:26:32 Done.
bool minify = compiler.enableMinification;
bool useDiffEncoding = minify && shorts.length > 30;
- int previous = 0;
- int nameCounter = 0;
- for (String short in shorts) {
- // Emit period that resets the diff base to zero when we switch to normal
- // calling convention (this avoids the need to code negative diffs).
- if (useDiffEncoding && nameCounter == firstNormalSelector) {
- diffEncoding.write(".");
- previous = 0;
- }
- if (short.length <= MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING &&
- useDiffEncoding) {
- int base63 = fromBase88(short);
- int diff = base63 - previous;
- previous = base63;
- String base26Diff = toBase26(diff);
- diffEncoding.write(base26Diff);
- } else {
- if (useDiffEncoding || diffEncoding.length != 0) {
- diffEncoding.write(",");
- }
- diffEncoding.write(short);
- }
- nameCounter++;
+ jsAst.Expression diffEncoding;
+ if (useDiffEncoding) {
+ diffEncoding = new _DiffEncodedListOfNames(shorts, firstNormalSelector);
+ } else {
+ diffEncoding = jsAst.concatenateStrings(
+ jsAst.joinLiterals(shorts, jsAst.stringPart(",")),
sra1 2015/06/23 04:47:54 This also needs to be deferred, since the sort ord
herhut 2015/06/23 13:26:31 Done.
+ addQuotes: true);
}
// Startup code that loops over the method names and puts handlers on the
@@ -259,8 +213,8 @@ class NsmEmitter extends CodeEmitterHelper {
}
shortNames.splice.apply(shortNames, calculatedShortNames);
}
- }''', {'objectClass': js.string(namer.className(objectClass)),
- 'diffEncoding': js.string('$diffEncoding')}));
+ }''', {'objectClass': js.quoteName(namer.className(objectClass)),
+ 'diffEncoding': diffEncoding}));
} else {
// No useDiffEncoding version.
Iterable<String> longs = trivialNsmHandlers.map((selector) =>
@@ -268,8 +222,8 @@ class NsmEmitter extends CodeEmitterHelper {
statements.add(js.statement(
'var objectClassObject = processedClasses.collected[#objectClass],'
' shortNames = #diffEncoding.split(",")',
- {'objectClass': js.string(namer.className(objectClass)),
- 'diffEncoding': js.string('$diffEncoding')}));
+ {'objectClass': js.quoteName(namer.className(objectClass)),
+ 'diffEncoding': diffEncoding}));
if (!minify) {
statements.add(js.statement('var longNames = #longs.split(",")',
{'longs': js.string(longs.join(','))}));
@@ -324,3 +278,89 @@ class NsmEmitter extends CodeEmitterHelper {
return statements;
}
}
+
+/// When pretty printed, this node computes a diff-encoded string for the list
+/// of given names.
floitsch 2015/06/22 17:43:45 Refer or copy the documentation from buildTrivialN
herhut 2015/06/23 13:26:32 Done.
+class _DiffEncodedListOfNames extends jsAst.DeferredString
+ implements AstContainer {
+ String _cachedValue;
+ jsAst.ArrayInitializer ast;
+ int firstNormalSelector;
+
+ _DiffEncodedListOfNames(Iterable<jsAst.Name> names,
+ this.firstNormalSelector) {
+ ast = new jsAst.ArrayInitializer(names.toList());
+ }
+
+ _computeDiffEncoding() {
+ var diffEncoding = new StringBuffer();
+
+ // Treat string as a number in base 88 with digits in ASCII order from # to
+ // z. The short name sorting is based on length, and uses ASCII order for
+ // equal length strings so this means that names are ascending. The hash
+ // character, #, is never given as input, but we need it because it's the
+ // implicit leading zero (otherwise we could not code names with leading
+ // dollar signs).
+ int fromBase88(String x) {
+ int answer = 0;
+ for (int i = 0; i < x.length; i++) {
+ int c = x.codeUnitAt(i);
+ // No support for Unicode minified identifiers in JS.
+ assert(c >= $$ && c <= $z);
+ answer *= 88;
+ answer += c - $HASH;
+ }
+ return answer;
+ }
+
+ // Big endian encoding, A = 0, B = 1...
+ // A lower case letter terminates the number.
+ String toBase26(int x) {
+ int c = x;
+ var encodingChars = <int>[];
+ encodingChars.add($a + (c % 26));
+ while (true) {
+ c ~/= 26;
+ if (c == 0) break;
+ encodingChars.add($A + (c % 26));
+ }
+ return new String.fromCharCodes(encodingChars.reversed.toList());
+ }
+
+ Iterable<String> shorts = ast.elements.map((jsAst.Name name) => name.name);
+
+ int previous = 0;
+ int nameCounter = 0;
+ for (String short in shorts) {
+ // Emit period that resets the diff base to zero when we switch to normal
+ // calling convention (this avoids the need to code negative diffs).
+ if (nameCounter == firstNormalSelector) {
+ diffEncoding.write('.');
+ previous = 0;
+ }
+ if (short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
+ int base63 = fromBase88(short);
+ int diff = base63 - previous;
+ previous = base63;
+ String base26Diff = toBase26(diff);
+ diffEncoding.write(base26Diff);
+ } else {
+ if (diffEncoding.length != 0) {
+ diffEncoding.write(',');
+ }
+ diffEncoding.write(short);
+ }
+ nameCounter++;
+ }
+
+ _cachedValue = diffEncoding.toString();
+ }
+
+ String get value {
+ if (_cachedValue == null) {
+ _cachedValue = _computeDiffEncoding();
+ }
+
+ return _cachedValue;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698