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(String className);
String getFunctionAlias(String name);
}

View File

@ -76,4 +76,9 @@ public class DefaultAliasProvider implements AliasProvider {
public String getAlias(FieldReference field) {
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> classAliases = new HashMap<>();
private Map<String, String> fieldAliases = new HashMap<>();
private Map<String, String> functionAliases = new HashMap<>();
private boolean minifying;
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) {
String className = methodRef.getClassName();
while (className != null) {

View File

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

View File

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

View File

@ -139,6 +139,22 @@ public class NamingOrderer implements NameFrequencyConsumer {
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) {
List<Entry> entryList = new ArrayList<>(entries.values());
Collections.sort(entryList, new Comparator<Entry>() {

View File

@ -37,4 +37,6 @@ public interface NamingStrategy {
String getFullNameForAsync(MethodReference method) 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)));
}
public SourceWriter appendFunction(String name) throws NamingException, IOException {
return append(naming.getNameForFunction(name));
}
private void appendIndent() throws IOException {
if (minified) {
return;

View File

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

View File

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

View File

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