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

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

Issue 1220333003: dart2js: Rename emitters. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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
deleted file mode 100644
index 5d7df35210e3da68bf1c1c7cc827ea5f54809393..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
+++ /dev/null
@@ -1,391 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js.js_emitter;
-
-class NsmEmitter extends CodeEmitterHelper {
- final List<Selector> trivialNsmHandlers = <Selector>[];
-
- /// If this is true then we can generate the noSuchMethod handlers at startup
- /// time, instead of them being emitted as part of the Object class.
- bool get generateTrivialNsmHandlers => true;
-
- // If we need fewer than this many noSuchMethod handlers we can save space by
- // just emitting them in JS, rather than emitting the JS needed to generate
- // them at run time.
- static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;
-
- static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
-
- void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
-
- ClassStubGenerator generator =
- new ClassStubGenerator(compiler, namer, backend);
-
- // Keep track of the JavaScript names we've already added so we
- // do not introduce duplicates (bad for code size).
- Map<jsAst.Name, Selector> addedJsNames
- = generator.computeSelectorsForNsmHandlers();
-
- // Set flag used by generateMethod helper below. If we have very few
- // handlers we use addProperty for them all, rather than try to generate
- // them at runtime.
- bool haveVeryFewNoSuchMemberHandlers =
- (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
- List<jsAst.Name> names = addedJsNames.keys.toList()
- ..sort();
- for (jsAst.Name jsName in names) {
- Selector selector = addedJsNames[jsName];
- String reflectionName = emitter.getReflectionName(selector, jsName);
-
- if (reflectionName != null) {
- emitter.mangledFieldNames[jsName] = reflectionName;
- }
-
- List<jsAst.Expression> argNames =
- selector.callStructure.getOrderedNamedArguments().map((String name) =>
- js.string(name)).toList();
- int type = selector.invocationMirrorKind;
- if (!haveVeryFewNoSuchMemberHandlers &&
- isTrivialNsmHandler(type, argNames, selector, jsName) &&
- reflectionName == null) {
- trivialNsmHandlers.add(selector);
- } else {
- StubMethod method =
- generator.generateStubForNoSuchMethod(jsName, selector);
- addProperty(method.name, method.code);
- if (reflectionName != null) {
- bool accessible =
- compiler.world.allFunctions.filter(selector, null).any(
- (Element e) => backend.isAccessibleByReflection(e));
- addProperty(namer.asName('+$reflectionName'),
- js(accessible ? '2' : '0'));
- }
- }
- }
- }
-
- // Identify the noSuchMethod handlers that are so simple that we can
- // generate them programatically.
- bool isTrivialNsmHandler(
- int type, List argNames, Selector selector, jsAst.Name internalName) {
- if (!generateTrivialNsmHandlers) return false;
- // Check for named arguments.
- if (argNames.length != 0) return false;
- // Check for unexpected name (this doesn't really happen).
- if (internalName is GetterName) return type == 1;
- if (internalName is SetterName) return type == 2;
- return type == 0;
- }
-
- /**
- * Adds (at runtime) the handlers to the Object class which catch calls to
- * methods that the object does not have. The handlers create an invocation
- * mirror object.
- *
- * The current version only gives you the minified name when minifying (when
- * not minifying this method is not called).
- *
- * In order to generate the noSuchMethod handlers we only need the minified
- * name of the method. We test the first character of the minified name to
- * determine if it is a getter or a setter, and we use the arguments array at
- * runtime to get the number of arguments and their values. If the method
- * involves named arguments etc. then we don't handle it here, but emit the
- * handler method directly on the Object class.
- *
- * The minified names are mostly 1-4 character names, which we emit in sorted
- * order (primary key is length, secondary ordering is lexicographic). This
- * gives an order like ... dD dI dX da ...
- *
- * Gzip is good with repeated text, but it can't diff-encode, so we do that
- * for it. We encode the minified names in a comma-separated string, but all
- * the 1-4 character names are encoded before the first comma as a series of
- * base 26 numbers. The last digit of each number is lower case, the others
- * are upper case, so 1 is "b" and 26 is "Ba".
- *
- * We think of the minified names as base 88 numbers using the ASCII
- * characters from # to z. The base 26 numbers each encode the delta from
- * the previous minified name to the next. So if there is a minified name
- * called Df and the next is Dh, then they are 2971 and 2973 when thought of
- * as base 88 numbers. The difference is 2, which is "c" in lower-case-
- * terminated base 26.
- *
- * The reason we don't encode long minified names with this method is that
- * decoding the base 88 numbers would overflow JavaScript's puny integers.
- *
- * There are some selectors that have a special calling convention (because
- * they are called with the receiver as the first argument). They need a
- * slightly different noSuchMethod handler, so we handle these first.
- */
- List<jsAst.Statement> buildTrivialNsmHandlers() {
- List<jsAst.Statement> statements = <jsAst.Statement>[];
- if (trivialNsmHandlers.length == 0) return statements;
-
- bool minify = compiler.enableMinification;
- bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
-
- // Find out how many selectors there are with the special calling
- // convention.
- Iterable<Selector> interceptedSelectors = trivialNsmHandlers.where(
- (Selector s) => backend.isInterceptedName(s.name));
- Iterable<Selector> ordinarySelectors = trivialNsmHandlers.where(
- (Selector s) => !backend.isInterceptedName(s.name));
-
- // Get the short names (JS names, perhaps minified).
- Iterable<jsAst.Name> interceptedShorts =
- interceptedSelectors.map(namer.invocationMirrorInternalName);
- Iterable<jsAst.Name> ordinaryShorts =
- ordinarySelectors.map(namer.invocationMirrorInternalName);
-
- jsAst.Expression sortedShorts;
- Iterable<String> sortedLongs;
- if (useDiffEncoding) {
- assert(minify);
- sortedShorts = new _DiffEncodedListOfNames(
- [interceptedShorts, ordinaryShorts]);
- } else {
- Iterable<Selector> sorted =
- [interceptedSelectors, ordinarySelectors].expand((e) => (e));
- sortedShorts = js.concatenateStrings(
- js.joinLiterals(
- sorted.map(namer.invocationMirrorInternalName),
- js.stringPart(",")),
- addQuotes: true);
-
- if (!minify) {
- sortedLongs = sorted.map((selector) =>
- selector.invocationMirrorMemberName);
- }
- }
- // Startup code that loops over the method names and puts handlers on the
- // Object class to catch noSuchMethod invocations.
- ClassElement objectClass = compiler.objectClass;
- jsAst.Expression createInvocationMirror = backend.emitter
- .staticFunctionAccess(backend.getCreateInvocationMirror());
- if (useDiffEncoding) {
- statements.add(js.statement('''{
- var objectClassObject = processedClasses.collected[#objectClass],
- nameSequences = #diffEncoding.split("."),
- shortNames = [];
- if (objectClassObject instanceof Array)
- objectClassObject = objectClassObject[1];
- for (var j = 0; j < nameSequences.length; ++j) {
- var sequence = nameSequences[j].split(","),
- nameNumber = 0;
- // 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.
- if (!objectClassObject) break;
- // Likewise, if the current sequence is empty, we don't process it.
- if (sequence.length == 0) continue;
- var diffEncodedString = sequence[0];
- for (var i = 0; i < diffEncodedString.length; i++) {
- var codes = [],
- diff = 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);
- }
- shortNames.push(
- String.fromCharCode.apply(String, codes));
- }
- if (sequence.length > 1) {
- Array.prototype.push.apply(shortNames, sequence.shift());
- }
- }
- }''', {'objectClass': js.quoteName(namer.className(objectClass)),
- 'diffEncoding': sortedShorts}));
- } else {
- // No useDiffEncoding version.
- statements.add(js.statement(
- 'var objectClassObject = processedClasses.collected[#objectClass],'
- ' shortNames = #diffEncoding.split(",")',
- {'objectClass': js.quoteName(namer.className(objectClass)),
- 'diffEncoding': sortedShorts}));
- if (!minify) {
- statements.add(js.statement('var longNames = #longs.split(",")',
- {'longs': js.string(sortedLongs.join(','))}));
- }
- statements.add(js.statement(
- 'if (objectClassObject instanceof Array)'
- ' objectClassObject = objectClassObject[1];'));
- }
-
- dynamic isIntercepted = // jsAst.Expression or bool.
- interceptedSelectors.isEmpty
- ? false
- : ordinarySelectors.isEmpty
- ? true
- : js('j < #', js.number(interceptedSelectors.length));
-
- 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.
- if (objectClassObject) {
- for (var j = 0; j < shortNames.length; j++) {
- var type = 0;
- var shortName = shortNames[j];
- if (shortName[0] == "${namer.getterPrefix[0]}") type = 1;
- if (shortName[0] == "${namer.setterPrefix[0]}") type = 2;
- // Generate call to:
- //
- // createInvocationMirror(String name, internalName, type,
- // arguments, argumentNames)
- //
-
- // This 'if' is either a static choice or dynamic choice depending on
- // [isIntercepted].
- if (#isIntercepted) {
- objectClassObject[shortName] =
- (function(name, shortName, type) {
- return function(receiver) {
- return this.#noSuchMethodName(
- receiver,
- #createInvocationMirror(name, shortName, type,
- // Create proper Array with all arguments except first
- // (receiver).
- Array.prototype.slice.call(arguments, 1),
- []));
- }
- })(#names[j], shortName, type);
- } else {
- objectClassObject[shortName] =
- (function(name, shortName, type) {
- return function() {
- return this.#noSuchMethodName(
- // Object.noSuchMethodName ignores the explicit receiver
- // argument. We could pass anything in place of [this].
- this,
- #createInvocationMirror(name, shortName, type,
- // Create proper Array with all arguments.
- Array.prototype.slice.call(arguments, 0),
- []));
- }
- })(#names[j], shortName, type);
- }
- }
- }''', {
- 'noSuchMethodName': namer.noSuchMethodName,
- 'createInvocationMirror': createInvocationMirror,
- 'names': minify ? 'shortNames' : 'longNames',
- 'isIntercepted': isIntercepted}));
-
- return statements;
- }
-}
-
-/// When pretty printed, this node computes a diff-encoded string for the list
-/// of given names.
-///
-/// See [buildTrivialNsmHandlers].
-class _DiffEncodedListOfNames extends jsAst.DeferredString
- implements jsAst.AstContainer {
- String _cachedValue;
- List<jsAst.ArrayInitializer> ast;
-
- Iterable<jsAst.Node> get containedNodes => ast;
-
- _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
- // Store the names in ArrayInitializer nodes to make them discoverable
- // by traversals of the ast.
- ast = names.map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
- .toList();
- }
-
- void _computeDiffEncodingForList(Iterable<jsAst.Name> names,
- StringBuffer diffEncoding) {
- // 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());
- }
-
- // Sort by length, then lexicographic.
- int compare(String a, String b) {
- if (a.length != b.length) return a.length - b.length;
- return a.compareTo(b);
- }
-
- List<String> shorts =
- names.map((jsAst.Name name) => name.name)
- .toList()
- ..sort(compare);
-
- int previous = 0;
- for (String short in shorts) {
- 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);
- }
- }
- }
-
- String _computeDiffEncoding() {
- StringBuffer buffer = new StringBuffer();
- for (jsAst.ArrayInitializer list in ast) {
- if (buffer.isNotEmpty) {
- // Emit period that resets the diff base to zero when we switch to
- // normal calling convention (this avoids the need to code negative
- // diffs).
- buffer.write(".");
- }
- List<jsAst.Name> names = list.elements;
- _computeDiffEncodingForList(names, buffer);
- }
- return '"${buffer.toString()}"';
- }
-
- String get value {
- if (_cachedValue == null) {
- _cachedValue = _computeDiffEncoding();
- }
-
- return _cachedValue;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698