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

Unified Diff: lib/compiler/implementation/js_backend/namer.dart

Issue 11265020: Minifying renamer for classes, methods and instance variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 2 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: lib/compiler/implementation/js_backend/namer.dart
diff --git a/lib/compiler/implementation/js_backend/namer.dart b/lib/compiler/implementation/js_backend/namer.dart
index 69e35ea19237e672d79e8e072c83f38fab797b91..a29f8aa2c9c32fa3efdf12e368b1adacd77a438d 100644
--- a/lib/compiler/implementation/js_backend/namer.dart
+++ b/lib/compiler/implementation/js_backend/namer.dart
@@ -6,8 +6,6 @@
* Assigns JavaScript identifiers to Dart variables, class-names and members.
*/
class Namer {
- final Compiler compiler;
-
static Set<String> _jsReserved = null;
Set<String> get jsReserved {
if (_jsReserved == null) {
@@ -18,32 +16,44 @@ class Namer {
return _jsReserved;
}
+ final String CURRENT_ISOLATE = r'$';
+
/**
* Map from top-level or static elements to their unique identifiers provided
* by [getName].
*
* Invariant: Keys must be declaration elements.
*/
+ final Compiler compiler;
final Map<Element, String> globals;
- final Map<String, int> usedGlobals;
final Map<String, LibraryElement> shortPrivateNameOwners;
+ final Set<String> usedGlobalNames;
+ final Set<String> usedInstanceNames;
+ final Map<String, String> instanceNameMap;
+ final Map<String, String> globalNameMap;
+ final Map<String, int> popularNameCounters;
final Map<Constant, String> constantNames;
Namer(this.compiler)
: globals = new Map<Element, String>(),
- usedGlobals = new Map<String, int>(),
shortPrivateNameOwners = new Map<String, LibraryElement>(),
- constantNames = new Map<Constant, String>();
+ usedGlobalNames = new Set<String>(),
+ usedInstanceNames = new Set<String>(),
+ instanceNameMap = new Map<String, String>(),
+ globalNameMap = new Map<String, String>(),
+ constantNames = new Map<Constant, String>(),
+ popularNameCounters = new Map<String, int>() {
+ usedGlobalNames.add('p'); // ISOLATE_PROPERTIES.
floitsch 2012/10/25 12:58:38 The ISOLATE_PROPERTIES for the non-minifying namer
erikcorry 2012/12/06 09:38:07 Removed this line.
+ }
- final String CURRENT_ISOLATE = r'$';
- final String ISOLATE = 'Isolate';
- final String ISOLATE_PROPERTIES = r"$isolateProperties";
+ String get ISOLATE => 'Isolate';
+ String get ISOLATE_PROPERTIES => r'$isolateProperties';
/** Some closures must contain their name. The name is stored in
* [STATIC_CLOSURE_NAME_NAME]. */
- final String STATIC_CLOSURE_NAME_NAME = r'$name';
- static const SourceString CLOSURE_INVOCATION_NAME =
- Compiler.CALL_OPERATOR_NAME;
+ String get STATIC_CLOSURE_NAME_NAME => r'$name';
+ SourceString get CLOSURE_INVOCATION_NAME => Compiler.CALL_OPERATOR_NAME;
+ bool get minify => false;
String constantName(Constant constant) {
// In the current implementation it doesn't make sense to give names to
@@ -52,16 +62,26 @@ class Namer {
assert(!constant.isFunction());
String result = constantNames[constant];
if (result == null) {
- result = getFreshGlobalName("CTC");
+ String longName;
+ if (minify) {
+ if (constant.isString()) {
+ StringConstant stringConstant = constant;
+ longName = stringConstant.value.slowToString();
floitsch 2012/10/25 12:58:38 Are you sure this can happen? Strings are normally
erikcorry 2012/12/06 09:38:07 This can happen.
+ } else {
+ longName = "C";
floitsch 2012/10/25 12:58:38 not for this CL, but this basically means that we
erikcorry 2012/12/06 09:38:07 Yes, after the first 30 non-string constants we st
+ }
+ } else {
+ longName = "CTC";
+ }
+ result = getFreshName(longName, usedGlobalNames);
constantNames[constant] = result;
}
return result;
}
String closureInvocationName(Selector selector) {
- // TODO(floitsch): mangle, while not conflicting with instance names.
- return instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME,
- selector);
+ return
floitsch 2012/10/25 12:58:38 one line?
erikcorry 2012/12/06 09:38:07 nope.
+ instanceMethodInvocationName(null, CLOSURE_INVOCATION_NAME, selector);
}
String breakLabelName(LabelElement label) {
@@ -87,6 +107,7 @@ class Namer {
* mangles the [name] so that each library has a unique name.
*/
String privateName(LibraryElement lib, SourceString name) {
+ String private;
floitsch 2012/10/25 12:58:38 s/private/result
erikcorry 2012/12/06 09:38:07 Done.
if (name.isPrivate()) {
String nameString = name.slowToString();
// The first library asking for a short private name wins.
@@ -95,17 +116,22 @@ class Namer {
// If a private name could clash with a mangled private name we don't
// use the short name. For example a private name "_lib3_foo" would
// clash with "_foo" from "lib3".
- if (identical(owner, lib) && !nameString.startsWith('_$LIBRARY_PREFIX')) {
- return nameString;
+ if (identical(owner, lib) &&
floitsch 2012/10/25 12:58:38 owner == lib
erikcorry 2012/12/06 09:38:07 Done.
+ !nameString.startsWith('_$LIBRARY_PREFIX') &&
+ !minify) {
+ private = nameString;
+ } else {
+ String libName = getName(lib);
+ // If a library name does not start with the [LIBRARY_PREFIX] then our
+ // assumptions about clashing with mangled private members do not hold.
+ assert(minify || libName.startsWith(LIBRARY_PREFIX));
+ // TODO(erikcorry): Fix this with other manglings to avoid clashes.
+ private = '_lib$libName\$$nameString';
}
- String libName = getName(lib);
- // If a library name does not start with the [LIBRARY_PREFIX] then our
- // assumptions about clashing with mangled private members do not hold.
- assert(libName.startsWith(LIBRARY_PREFIX));
- return '_$libName$nameString';
} else {
- return name.slowToString();
+ private = name.slowToString();
}
+ return private;
}
String instanceMethodName(FunctionElement element) {
@@ -118,20 +144,21 @@ class Namer {
FunctionSignature signature = element.computeSignature(compiler);
String methodName =
'${privateName(lib, name)}\$${signature.parameterCount}';
- if (!signature.optionalParametersAreNamed) {
- return methodName;
- } else if (!signature.optionalParameters.isEmpty) {
+ if (signature.optionalParametersAreNamed &&
+ !signature.optionalParameters.isEmpty) {
StringBuffer buffer = new StringBuffer();
signature.orderedOptionalParameters.forEach((Element element) {
buffer.add('\$${JsNames.getValid(element.name.slowToString())}');
});
- return '$methodName$buffer';
+ methodName = '$methodName$buffer';
}
+ return getMappedInstanceName(methodName);
}
String publicInstanceMethodNameByArity(SourceString name, int arity) {
assert(!name.isPrivate());
- return '${name.slowToString()}\$$arity';
+ var proposedName = '${name.slowToString()}\$$arity';
+ return getMappedInstanceName(proposedName);
}
String instanceMethodInvocationName(LibraryElement lib, SourceString name,
@@ -143,12 +170,13 @@ class Namer {
buffer.add(r'$');
argumentName.printOn(buffer);
}
- return '${privateName(lib, name)}\$${selector.argumentCount}$buffer';
+ return getMappedInstanceName(
+ '${privateName(lib, name)}\$${selector.argumentCount}$buffer');
}
String instanceFieldName(LibraryElement libraryElement, SourceString name) {
String proposedName = privateName(libraryElement, name);
- return safeName(proposedName);
+ return getMappedInstanceName(proposedName);
}
String shadowedFieldName(Element fieldElement) {
@@ -157,45 +185,64 @@ class Namer {
String libName = getName(libraryElement);
String clsName = getName(cls);
String instanceName = instanceFieldName(libraryElement, fieldElement.name);
- return safeName('$libName\$$clsName\$$instanceName');
+ return getMappedInstanceName('$libName\$$clsName\$$instanceName');
}
String setterName(LibraryElement lib, SourceString name) {
// We dynamically create setters from the field-name. The setter name must
// therefore be derived from the instance field-name.
- String fieldName = safeName(privateName(lib, name));
+ String fieldName = getMappedInstanceName(privateName(lib, name));
return 'set\$$fieldName';
}
String publicGetterName(SourceString name) {
// We dynamically create getters from the field-name. The getter name must
// therefore be derived from the instance field-name.
- String fieldName = safeName(name.slowToString());
+ String fieldName = getMappedInstanceName(name.slowToString());
return 'get\$$fieldName';
}
String getterName(LibraryElement lib, SourceString name) {
// We dynamically create getters from the field-name. The getter name must
// therefore be derived from the instance field-name.
- String fieldName = safeName(privateName(lib, name));
+ String fieldName = getMappedInstanceName(privateName(lib, name));
return 'get\$$fieldName';
}
- String getFreshGlobalName(String proposedName) {
- String name = proposedName;
- int count = usedGlobals[name];
- if (count != null) {
- // Not the first time we see this name. Append a number to make it unique.
- do {
- name = '$proposedName${count++}';
- } while (usedGlobals[name] != null);
- // Record the count in case we see this name later. We
- // frequently see names multiple times, as all our closures use
- // the same name for their class.
- usedGlobals[proposedName] = count;
+ String getMappedGlobalName(String proposedName) {
+ var newName = globalNameMap[proposedName];
+ if (newName == null) {
+ newName = getFreshName(proposedName, usedGlobalNames);
+ globalNameMap[proposedName] = newName;
}
- usedGlobals[name] = 0;
- return name;
+ return newName;
+ }
+
+ String getMappedInstanceName(String proposedName) {
+ var newName = instanceNameMap[proposedName];
+ if (newName == null) {
+ newName = getFreshName(proposedName, usedInstanceNames);
+ instanceNameMap[proposedName] = newName;
+ }
+ return newName;
+ }
+
+ String getFreshName(String proposedName, Set<String> usedNames) {
+ var candidate;
+ proposedName = safeName(proposedName);
+ if (!usedNames.contains(proposedName)) {
+ candidate = proposedName;
+ } else {
+ var counter = popularNameCounters[proposedName];
+ var i = counter == null ? 0 : counter;
+ while (usedNames.contains("$proposedName$i")) {
+ i++;
+ }
+ popularNameCounters[proposedName] = i + 1;
+ candidate = "$proposedName$i";
+ }
+ usedNames.add(candidate);
+ return candidate;
}
static const String LIBRARY_PREFIX = "lib";
@@ -223,17 +270,23 @@ class Namer {
} else {
name = element.name.slowToString();
}
- } else if (identical(element.kind, ElementKind.LIBRARY)) {
+ } else if (element.kind === ElementKind.LIBRARY) {
floitsch 2012/10/25 08:42:40 element.isLibrary()
erikcorry 2012/10/25 09:09:28 Done.
name = LIBRARY_PREFIX;
} else {
name = element.name.slowToString();
}
// Prefix the name with '$' if it is reserved.
- return safeName(name);
+ return name;
}
String getBailoutName(Element element) {
- return '${getName(element)}\$bailout';
+ bool global = !element.isInstanceMember();
+ var unminifiedName = '${getName(element)}\$bailout';
+ if (global) {
+ return getMappedGlobalName(unminifiedName);
+ } else {
+ return getMappedInstanceName(unminifiedName);
+ }
}
/**
@@ -272,17 +325,25 @@ class Namer {
if (identical(kind, ElementKind.VARIABLE) ||
identical(kind, ElementKind.PARAMETER)) {
// The name is not guaranteed to be unique.
- return guess;
+ return safeName(guess);
}
- if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
- identical(kind, ElementKind.FUNCTION) ||
- identical(kind, ElementKind.CLASS) ||
- identical(kind, ElementKind.FIELD) ||
- identical(kind, ElementKind.GETTER) ||
- identical(kind, ElementKind.SETTER) ||
- identical(kind, ElementKind.TYPEDEF) ||
- identical(kind, ElementKind.LIBRARY)) {
- String result = getFreshGlobalName(guess);
+ if (kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
+ kind == ElementKind.FUNCTION ||
+ kind == ElementKind.CLASS ||
+ kind == ElementKind.FIELD ||
+ kind == ElementKind.GETTER ||
+ kind == ElementKind.SETTER ||
+ kind == ElementKind.TYPEDEF ||
+ kind == ElementKind.LIBRARY) {
+ bool isNative = false;
+ if (identical(kind, ElementKind.CLASS)) {
+ ClassElement class_elt = element;
+ isNative = class_elt.isNative();
+ }
+ if (Elements.isInstanceField(element)) {
+ isNative = element.isNative();
+ }
+ String result = isNative ? guess : getFreshName(guess, usedGlobalNames);
globals[element] = result;
return result;
}
@@ -292,9 +353,8 @@ class Namer {
}
String getLazyInitializerName(Element element) {
- // TODO(floitsch): mangle while not conflicting with other statics.
assert(Elements.isStaticOrTopLevelField(element));
- return "get\$${getName(element)}";
+ return getMappedGlobalName("get\$${getName(element)}");
}
String isolatePropertiesAccess(Element element) {
@@ -310,7 +370,8 @@ class Namer {
}
String isolateBailoutAccess(Element element) {
- return '${isolateAccess(element)}\$bailout';
+ String newName = getMappedGlobalName('${getName(element)}\$bailout');
+ return '$CURRENT_ISOLATE.$newName';
}
String isolateLazyInitializerAccess(Element element) {
@@ -318,6 +379,7 @@ class Namer {
}
String operatorIs(Element element) {
+ // TODO(erikcorry): Reduce from is$x to ix when we are minifying.
return 'is\$${getName(element)}';
}

Powered by Google App Engine
This is Rietveld 408576698