Fix error. Apply frequency-based alias generation for some $rt functions

This commit is contained in:
konsoletyper 2015-03-09 15:14:28 +03:00
parent 62118e2cfe
commit 93c7fb52b4
11 changed files with 129 additions and 13 deletions

View File

@ -31,4 +31,6 @@ public interface AliasProvider {
String getAlias(MethodDescriptor method); String getAlias(MethodDescriptor method);
String getAlias(String className); String getAlias(String className);
String getFunctionAlias(String name);
} }

View File

@ -76,4 +76,9 @@ public class DefaultAliasProvider implements AliasProvider {
public String getAlias(FieldReference field) { public String getAlias(FieldReference field) {
return field.getFieldName() + (lastSuffix++); return field.getFieldName() + (lastSuffix++);
} }
@Override
public String getFunctionAlias(String name) {
return name;
}
} }

View File

@ -30,6 +30,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
private Map<String, String> privateAliases = new HashMap<>(); private Map<String, String> privateAliases = new HashMap<>();
private Map<String, String> classAliases = new HashMap<>(); private Map<String, String> classAliases = new HashMap<>();
private Map<String, String> fieldAliases = new HashMap<>(); private Map<String, String> fieldAliases = new HashMap<>();
private Map<String, String> functionAliases = new HashMap<>();
private boolean minifying; private boolean minifying;
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) { public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
@ -126,6 +127,19 @@ public class DefaultNamingStrategy implements NamingStrategy {
} }
} }
@Override
public String getNameForFunction(String name) throws NamingException {
if (!minifying) {
return name;
}
String alias = functionAliases.get(name);
if (alias == null) {
alias = aliasProvider.getFunctionAlias(name);
functionAliases.put(name, alias);
}
return alias;
}
private MethodReference getRealMethod(MethodReference methodRef) { private MethodReference getRealMethod(MethodReference methodRef) {
String className = methodRef.getClassName(); String className = methodRef.getClassName();
while (className != null) { while (className != null) {

View File

@ -50,6 +50,11 @@ public class MinifyingAliasProvider implements AliasProvider {
return getNewAlias(lastSuffix++, startLetters); return getNewAlias(lastSuffix++, startLetters);
} }
@Override
public String getFunctionAlias(String className) {
return getNewAlias(lastSuffix++, startLetters);
}
private String getNewAlias(int index, String startLetters) { private String getNewAlias(int index, String startLetters) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(startLetters.charAt(index % startLetters.length())); sb.append(startLetters.charAt(index % startLetters.length()));

View File

@ -37,4 +37,6 @@ public interface NameFrequencyConsumer {
void consume(String className); void consume(String className);
void consume(FieldReference field); void consume(FieldReference field);
void consumeFunction(String name);
} }

View File

@ -139,6 +139,22 @@ public class NamingOrderer implements NameFrequencyConsumer {
entry.frequency++; entry.frequency++;
} }
@Override
public void consumeFunction(final String name) {
String key = "n:" + name;
Entry entry = entries.get(key);
if (entry == null) {
entry = new Entry();
entry.operation = new NamingOperation() {
@Override public void perform(NamingStrategy naming) {
naming.getNameForFunction(name);
}
};
entries.put(key, entry);
}
entry.frequency++;
}
public void apply(NamingStrategy naming) { public void apply(NamingStrategy naming) {
List<Entry> entryList = new ArrayList<>(entries.values()); List<Entry> entryList = new ArrayList<>(entries.values());
Collections.sort(entryList, new Comparator<Entry>() { Collections.sort(entryList, new Comparator<Entry>() {

View File

@ -37,4 +37,6 @@ public interface NamingStrategy {
String getFullNameForAsync(MethodReference method) throws NamingException; String getFullNameForAsync(MethodReference method) throws NamingException;
String getNameFor(FieldReference field) throws NamingException; String getNameFor(FieldReference field) throws NamingException;
String getNameForFunction(String name) throws NamingException;
} }

View File

@ -137,6 +137,10 @@ public class SourceWriter implements Appendable, LocationProvider {
return append(naming.getFullNameFor(new MethodReference(cls, name, params))); return append(naming.getFullNameFor(new MethodReference(cls, name, params)));
} }
public SourceWriter appendFunction(String name) throws NamingException, IOException {
return append(naming.getNameForFunction(name));
}
private void appendIndent() throws IOException { private void appendIndent() throws IOException {
if (minified) { if (minified) {
return; return;

View File

@ -70,6 +70,8 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
if (asyncFamilyMethods.contains(method.getReference())) { if (asyncFamilyMethods.contains(method.getReference())) {
consumer.consume(method.getReference()); consumer.consume(method.getReference());
consumer.consumeAsync(method.getReference()); consumer.consumeAsync(method.getReference());
consumer.consumeFunction("$rt_asyncError");
consumer.consumeFunction("$rt_asyncResult");
} }
} }
if (clinit != null && (method.getModifiers().contains(NodeModifier.STATIC) || if (clinit != null && (method.getModifiers().contains(NodeModifier.STATIC) ||
@ -118,6 +120,7 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
async = true; async = true;
for (AsyncMethodPart part : methodNode.getBody()) { for (AsyncMethodPart part : methodNode.getBody()) {
part.getStatement().acceptVisitor(this); part.getStatement().acceptVisitor(this);
consumer.consumeFunction("$rt_guardAsync");
} }
} }
@ -180,11 +183,15 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
if (statement.getResult() != null) { if (statement.getResult() != null) {
statement.getResult().acceptVisitor(this); statement.getResult().acceptVisitor(this);
} }
if (async) {
consumer.consumeFunction("$rt_asyncResult");
}
} }
@Override @Override
public void visit(ThrowStatement statement) { public void visit(ThrowStatement statement) {
statement.getException().acceptVisitor(this); statement.getException().acceptVisitor(this);
consumer.consumeFunction("$rt_throw");
} }
@Override @Override
@ -235,11 +242,25 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
public void visit(BinaryExpr expr) { public void visit(BinaryExpr expr) {
expr.getFirstOperand().acceptVisitor(this); expr.getFirstOperand().acceptVisitor(this);
expr.getSecondOperand().acceptVisitor(this); expr.getSecondOperand().acceptVisitor(this);
switch (expr.getOperation()) {
case COMPARE:
consumer.consumeFunction("$rt_compare");
break;
default:
break;
}
} }
@Override @Override
public void visit(UnaryExpr expr) { public void visit(UnaryExpr expr) {
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
switch (expr.getOperation()) {
case NULL_CHECK:
consumer.consumeFunction("$rt_nullCheck");
break;
default:
break;
}
} }
@Override @Override
@ -263,6 +284,7 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
if (type instanceof ValueType.Object) { if (type instanceof ValueType.Object) {
String clsName = ((ValueType.Object)type).getClassName(); String clsName = ((ValueType.Object)type).getClassName();
consumer.consume(clsName); consumer.consume(clsName);
consumer.consumeFunction("$rt_cls");
} }
} }
@ -307,6 +329,9 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
} }
break; break;
} }
if (asyncCall) {
consumer.consumeFunction("$rt_continue");
}
} }
@Override @Override
@ -324,6 +349,9 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
public void visit(NewArrayExpr expr) { public void visit(NewArrayExpr expr) {
visitType(expr.getType()); visitType(expr.getType());
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
if (!(expr.getType() instanceof ValueType.Primitive)) {
consumer.consumeFunction("$rt_createArray");
}
} }
@Override @Override
@ -338,6 +366,15 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
public void visit(InstanceOfExpr expr) { public void visit(InstanceOfExpr expr) {
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
visitType(expr.getType()); visitType(expr.getType());
if (expr.getType() instanceof ValueType.Object) {
String clsName = ((ValueType.Object)expr.getType()).getClassName();
ClassReader cls = classSource.get(clsName);
if (cls == null || cls.hasModifier(ElementModifier.INTERFACE)) {
consumer.consumeFunction("$rt_isInstance");
}
} else {
consumer.consumeFunction("$rt_isInstance");
}
} }
@Override @Override

View File

@ -259,6 +259,20 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
writer.outdent().append("}").newLine(); writer.outdent().append("}").newLine();
} }
private void renderRuntimeAliases() throws IOException {
String[] names = { "$rt_asyncResult", "$rt_asyncError", "$rt_continue", "$rt_guardAsync", "$rt_throw",
"$rt_compare", "$rt_nullCheck", "$rt_cls", "$rt_createArray", "$rt_isInstance" };
boolean first = true;
for (String name : names) {
if (!first) {
writer.softNewLine();
}
first = false;
writer.append("var ").appendFunction(name).ws().append('=').ws().append(name).append(";").softNewLine();
}
writer.newLine();
}
public void render(List<ClassNode> classes) throws RenderingException { public void render(List<ClassNode> classes) throws RenderingException {
if (minifying) { if (minifying) {
NamingOrderer orderer = new NamingOrderer(); NamingOrderer orderer = new NamingOrderer();
@ -269,6 +283,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
orderer.apply(naming); orderer.apply(naming);
} }
if (minifying) {
try {
renderRuntimeAliases();
} catch (IOException e) {
throw new RenderingException(e);
}
}
for (ClassNode cls : classes) { for (ClassNode cls : classes) {
renderDeclaration(cls); renderDeclaration(cls);
} }
@ -638,9 +660,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
writer.append(");").softNewLine(); writer.append(");").softNewLine();
writer.outdent().append("}").ws().append("catch").ws().append("($e)").ws() writer.outdent().append("}").ws().append("catch").ws().append("($e)").ws()
.append("{").indent().softNewLine(); .append("{").indent().softNewLine();
writer.append("return ").append(getReturnVariable()).append("($rt_asyncError($e));").softNewLine(); writer.append("return ").append(getReturnVariable()).append("(").appendFunction("$rt_asyncError")
.append("($e));").softNewLine();
writer.outdent().append("}"); writer.outdent().append("}");
writer.append(getReturnVariable()).append("($rt_asyncResult($x));").softNewLine(); writer.append(getReturnVariable()).append("(").appendFunction("$rt_asyncResult").append("($x));")
.softNewLine();
writer.outdent().append("}"); writer.outdent().append("}");
if (inner) { if (inner) {
writer.append(';'); writer.append(';');
@ -744,7 +768,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
for (int i = 0; i < methodNode.getBody().size(); ++i) { for (int i = 0; i < methodNode.getBody().size(); ++i) {
writer.append("var ").append(getPartVariable(i)).ws().append("=").ws() writer.append("var ").append(getPartVariable(i)).ws().append("=").ws()
.append("$rt_guardAsync(function("); .appendFunction("$rt_guardAsync").append("(function(");
if (i > 0) { if (i > 0) {
writer.append("$restore"); writer.append("$restore");
} }
@ -1074,7 +1098,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
writer.append("return"); writer.append("return");
if (async) { if (async) {
writer.append(' ').append(getReturnVariable()).append("($rt_asyncResult("); writer.append(' ').append(getReturnVariable()).append("(").appendFunction("$rt_asyncResult")
.append("(");
} }
if (statement.getResult() != null) { if (statement.getResult() != null) {
if (!async) { if (!async) {
@ -1105,7 +1130,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
if (statement.getLocation() != null) { if (statement.getLocation() != null) {
pushLocation(statement.getLocation()); pushLocation(statement.getLocation());
} }
writer.append("$rt_throw("); writer.appendFunction("$rt_throw").append("(");
prevCallSite = debugEmitter.emitCallSite(); prevCallSite = debugEmitter.emitCallSite();
priority = Priority.COMMA; priority = Priority.COMMA;
associativity = Associativity.NONE; associativity = Associativity.NONE;
@ -1282,7 +1307,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
visitBinary(expr, "!==", Priority.COMPARISON, Associativity.LEFT); visitBinary(expr, "!==", Priority.COMPARISON, Associativity.LEFT);
break; break;
case COMPARE: case COMPARE:
visitBinaryFunction(expr, "$rt_compare"); visitBinaryFunction(expr, naming.getNameForFunction("$rt_compare"));
break; break;
case COMPARE_LONG: case COMPARE_LONG:
visitBinaryFunction(expr, "Long_compare"); visitBinaryFunction(expr, "Long_compare");
@ -1420,7 +1445,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
break; break;
case NULL_CHECK: case NULL_CHECK:
enterPriority(Priority.COMMA, Associativity.NONE, false); enterPriority(Priority.COMMA, Associativity.NONE, false);
writer.append("$rt_nullCheck("); writer.appendFunction("$rt_nullCheck").append("(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.append(')'); writer.append(')');
exitPriority(); exitPriority();
@ -1483,7 +1508,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
if (cst instanceof ValueType) { if (cst instanceof ValueType) {
ValueType type = (ValueType)cst; ValueType type = (ValueType)cst;
return "$rt_cls(" + typeToClsString(naming, type) + ")"; return naming.getNameForFunction("$rt_cls") + "(" + typeToClsString(naming, type) + ")";
} else if (cst instanceof String) { } else if (cst instanceof String) {
String string = (String)cst; String string = (String)cst;
Integer index = stringPoolMap.get(string); Integer index = stringPoolMap.get(string);
@ -1738,7 +1763,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
if (hasParams) { if (hasParams) {
writer.append(',').ws(); writer.append(',').ws();
} }
writer.append("$rt_continue(").append(getPartVariable(expr.getAsyncTarget())).append(')'); writer.appendFunction("$rt_continue").append("(").append(getPartVariable(expr.getAsyncTarget()))
.append(')');
} }
writer.append(')'); writer.append(')');
exitPriority(); exitPriority();
@ -1849,7 +1875,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
break; break;
} }
} else { } else {
writer.append("$rt_createArray(").append(typeToClsString(naming, expr.getType())).append(",").ws(); writer.appendFunction("$rt_createArray").append("(").append(typeToClsString(naming, expr.getType()))
.append(",").ws();
expr.getLength().acceptVisitor(this); expr.getLength().acceptVisitor(this);
writer.append(")"); writer.append(")");
} }
@ -1946,7 +1973,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
} }
enterPriority(Priority.COMMA, Associativity.NONE, false); enterPriority(Priority.COMMA, Associativity.NONE, false);
writer.append("$rt_isInstance("); writer.appendFunction("$rt_isInstance").append("(");
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
writer.append(",").ws().append(typeToClsString(naming, expr.getType())).append(")"); writer.append(",").ws().append(typeToClsString(naming, expr.getType())).append(")");
exitPriority(); exitPriority();
@ -2037,7 +2064,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
writer.append("return ").append(naming.getFullNameForAsync(monitorEnterRef)).append("("); writer.append("return ").append(naming.getFullNameForAsync(monitorEnterRef)).append("(");
statement.getObjectRef().acceptVisitor(this); statement.getObjectRef().acceptVisitor(this);
writer.append(",").ws(); writer.append(",").ws();
writer.append("$rt_continue(").append(getPartVariable(statement.getAsyncTarget())).append(')'); writer.appendFunction("$rt_continue").append("(").append(getPartVariable(statement.getAsyncTarget()))
.append(')');
writer.append(");").softNewLine(); writer.append(");").softNewLine();
} else { } else {
MethodReference monitorEnterRef = new MethodReference( MethodReference monitorEnterRef = new MethodReference(

View File

@ -549,11 +549,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
for (MethodReference injectedMethod : methodInjectors.keySet()) { for (MethodReference injectedMethod : methodInjectors.keySet()) {
decompiler.addMethodToPass(injectedMethod); decompiler.addMethodToPass(injectedMethod);
} }
List<String> classOrder = decompiler.getClassOrdering(classes.getClassNames());
List<ClassNode> classNodes = new ArrayList<>(); List<ClassNode> classNodes = new ArrayList<>();
int index = 0; int index = 0;
try (PrintWriter bytecodeLogger = bytecodeLogging ? try (PrintWriter bytecodeLogger = bytecodeLogging ?
new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")) : null) { new PrintWriter(new OutputStreamWriter(logStream, "UTF-8")) : null) {
for (String className : classes.getClassNames()) { for (String className : classOrder) {
ClassHolder cls = classes.get(className); ClassHolder cls = classes.get(className);
for (MethodHolder method : cls.getMethods()) { for (MethodHolder method : cls.getMethods()) {
processMethod(method); processMethod(method);