Various code size optimizations

1. Generate 'a' for 'this' instead of '$t'
2. Fix frequency-based identifier optimization
3. Generate less code in <clinit> callers
4. Generate one-letter identifier in most of constructors
   (instead of $r)
5. Use $ and _ chars in identifiers
This commit is contained in:
Alexey Andreev 2018-10-04 16:29:05 +03:00
parent b66053f5ce
commit 4c4c589172
7 changed files with 26 additions and 17 deletions

View File

@ -318,6 +318,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
}
int start = sourceWriter.getOffset();
sourceWriter.append("\"use strict\";").newLine();
renderer.prepare(clsNodes);
renderer.renderRuntime();
renderer.render(clsNodes);
renderer.renderStringPool();

View File

@ -83,7 +83,7 @@ public class MinifyingAliasProvider implements AliasProvider {
public String getClassInitAlias(String className) {
String result;
do {
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
return result;
}

View File

@ -100,6 +100,11 @@ class NameFrequencyEstimator extends RecursiveVisitor implements MethodNodeVisit
consumer.consumeFunction("$rt_resuming");
consumer.consumeFunction("$rt_invalidPointer");
}
method.acceptVisitor(this);
}
if (clinit != null) {
consumer.consumeFunction("$rt_eraseClinit");
}
// Metadata

View File

@ -295,7 +295,7 @@ public class Renderer implements RenderingManager {
private void renderRuntimeAliases() throws IOException {
String[] names = { "$rt_throw", "$rt_compare", "$rt_nullCheck", "$rt_cls", "$rt_createArray",
"$rt_isInstance", "$rt_nativeThread", "$rt_suspending", "$rt_resuming", "$rt_invalidPointer",
"$rt_s" };
"$rt_s", "$rt_eraseClinit" };
boolean first = true;
for (String name : names) {
if (!first) {
@ -307,7 +307,7 @@ public class Renderer implements RenderingManager {
writer.newLine();
}
public void render(List<ClassNode> classes) throws RenderingException {
public void prepare(List<ClassNode> classes) {
if (minifying) {
NamingOrderer orderer = new NamingOrderer();
NameFrequencyEstimator estimator = new NameFrequencyEstimator(orderer, classSource, asyncMethods,
@ -317,7 +317,9 @@ public class Renderer implements RenderingManager {
}
orderer.apply(naming);
}
}
public void render(List<ClassNode> classes) throws RenderingException {
if (minifying) {
try {
renderRuntimeAliases();
@ -484,8 +486,8 @@ public class Renderer implements RenderingManager {
private void renderEraseClinit(ClassNode cls) throws IOException {
writer.append(naming.getNameForClassInit(cls.getName())).ws().append("=").ws()
.appendClass(cls.getName()).append(".$clinit").ws().append("=").ws()
.append("function(){};").newLine();
.appendFunction("$rt_eraseClinit").append("(")
.appendClass(cls.getName()).append(");").softNewLine();
}
private void renderClassMetadata(List<ClassNode> classes) {
@ -713,22 +715,24 @@ public class Renderer implements RenderingManager {
MethodReference ref = method.getReference();
debugEmitter.emitMethod(ref.getDescriptor());
writer.append("function ").append(naming.getNameForInit(ref)).append("(");
for (int i = 1; i <= ref.parameterCount(); ++i) {
if (i > 1) {
for (int i = 0; i < ref.parameterCount(); ++i) {
if (i > 0) {
writer.append(",").ws();
}
writer.append(variableNameForInitializer(i));
}
writer.append(")").ws().append("{").softNewLine().indent();
writer.append("var $r").ws().append("=").ws().append("new ").appendClass(
String instanceName = variableNameForInitializer(ref.parameterCount());
writer.append("var " + instanceName).ws().append("=").ws().append("new ").appendClass(
ref.getClassName()).append("();").softNewLine();
writer.append(naming.getFullNameFor(ref)).append("($r");
for (int i = 1; i <= ref.parameterCount(); ++i) {
writer.append(naming.getFullNameFor(ref)).append("(" + instanceName);
for (int i = 0; i < ref.parameterCount(); ++i) {
writer.append(",").ws();
writer.append(variableNameForInitializer(i));
}
writer.append(");").softNewLine();
writer.append("return $r;").softNewLine();
writer.append("return " + instanceName + ";").softNewLine();
writer.outdent().append("}").newLine();
debugEmitter.emitMethod(null);
}

View File

@ -27,7 +27,7 @@ public final class RenderingUtil {
"super", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with", "yield",
"NaN")));
public static final String VARIABLE_START_CHARS = "abcdefghijklmnopqrstuvwxyz";
public static final String VARIABLE_PART_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
public static final String VARIABLE_PART_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_";
private RenderingUtil() {
}

View File

@ -462,10 +462,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
}
private String generateVariableName(int index) {
if (index == 0 && minifying) {
return "$t";
}
if (!minifying) {
VariableNode variable = index < currentMethod.getVariables().size()
? currentMethod.getVariables().get(index)
@ -484,7 +480,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
return "var$" + index;
}
} else {
return RenderingUtil.indexToId(--index);
return RenderingUtil.indexToId(index);
}
}

View File

@ -520,6 +520,9 @@ function $rt_stringPool(strings) {
function $rt_s(index) {
return $rt_stringPool_instance[index];
}
function $rt_eraseClinit(target) {
return target.$clinit = function() {};
}
function TeaVMThread(runner) {
this.status = 3;
this.stack = [];