From 93c7fb52b48793896a08c1d8e7126d459933f7ac Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Mon, 9 Mar 2015 15:14:28 +0300 Subject: [PATCH] Fix error. Apply frequency-based alias generation for some $rt functions --- .../java/org/teavm/codegen/AliasProvider.java | 2 + .../teavm/codegen/DefaultAliasProvider.java | 5 ++ .../teavm/codegen/DefaultNamingStrategy.java | 14 +++++ .../teavm/codegen/MinifyingAliasProvider.java | 5 ++ .../teavm/codegen/NameFrequencyConsumer.java | 2 + .../java/org/teavm/codegen/NamingOrderer.java | 16 ++++++ .../org/teavm/codegen/NamingStrategy.java | 2 + .../java/org/teavm/codegen/SourceWriter.java | 4 ++ .../javascript/NameFrequencyEstimator.java | 37 +++++++++++++ .../java/org/teavm/javascript/Renderer.java | 52 ++++++++++++++----- .../src/main/java/org/teavm/vm/TeaVM.java | 3 +- 11 files changed, 129 insertions(+), 13 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/codegen/AliasProvider.java b/teavm-core/src/main/java/org/teavm/codegen/AliasProvider.java index 28a615277..cdc0a89a3 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/AliasProvider.java +++ b/teavm-core/src/main/java/org/teavm/codegen/AliasProvider.java @@ -31,4 +31,6 @@ public interface AliasProvider { String getAlias(MethodDescriptor method); String getAlias(String className); + + String getFunctionAlias(String name); } diff --git a/teavm-core/src/main/java/org/teavm/codegen/DefaultAliasProvider.java b/teavm-core/src/main/java/org/teavm/codegen/DefaultAliasProvider.java index 9b66e6cca..0cc90a5d5 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/DefaultAliasProvider.java +++ b/teavm-core/src/main/java/org/teavm/codegen/DefaultAliasProvider.java @@ -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; + } } diff --git a/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java b/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java index f977b3a33..0a28824b0 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java +++ b/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java @@ -30,6 +30,7 @@ public class DefaultNamingStrategy implements NamingStrategy { private Map privateAliases = new HashMap<>(); private Map classAliases = new HashMap<>(); private Map fieldAliases = new HashMap<>(); + private Map 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) { diff --git a/teavm-core/src/main/java/org/teavm/codegen/MinifyingAliasProvider.java b/teavm-core/src/main/java/org/teavm/codegen/MinifyingAliasProvider.java index 1410f3991..a51ce9a3a 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/MinifyingAliasProvider.java +++ b/teavm-core/src/main/java/org/teavm/codegen/MinifyingAliasProvider.java @@ -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())); diff --git a/teavm-core/src/main/java/org/teavm/codegen/NameFrequencyConsumer.java b/teavm-core/src/main/java/org/teavm/codegen/NameFrequencyConsumer.java index bfa6cfaab..20aec0331 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/NameFrequencyConsumer.java +++ b/teavm-core/src/main/java/org/teavm/codegen/NameFrequencyConsumer.java @@ -37,4 +37,6 @@ public interface NameFrequencyConsumer { void consume(String className); void consume(FieldReference field); + + void consumeFunction(String name); } diff --git a/teavm-core/src/main/java/org/teavm/codegen/NamingOrderer.java b/teavm-core/src/main/java/org/teavm/codegen/NamingOrderer.java index 1ab640f3e..8cfc4399d 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/NamingOrderer.java +++ b/teavm-core/src/main/java/org/teavm/codegen/NamingOrderer.java @@ -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 entryList = new ArrayList<>(entries.values()); Collections.sort(entryList, new Comparator() { diff --git a/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java b/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java index bbdd476e7..0902b5093 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java +++ b/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java @@ -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; } diff --git a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java index 4be2811cb..d10815dfb 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java +++ b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java @@ -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; diff --git a/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java b/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java index c68a4b9e8..61d639cde 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java @@ -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 diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index c205a34f8..d158d1dd3 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -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 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( diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index 6d6912b45..f459e4a46 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -549,11 +549,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository { for (MethodReference injectedMethod : methodInjectors.keySet()) { decompiler.addMethodToPass(injectedMethod); } + List classOrder = decompiler.getClassOrdering(classes.getClassNames()); List 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);