Move static fields from class scope to global scope

This commit is contained in:
Alexey Andreev 2016-04-17 13:26:29 +03:00
parent 2d79da7b1b
commit 894e39c59f
26 changed files with 291 additions and 665 deletions

View File

@ -17,8 +17,8 @@
<inspection_tool class="CloneCallsSuperClone" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="CloneCallsSuperClone" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="CloneDeclaresCloneNotSupported" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="CloneDeclaresCloneNotSupported" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="CodeBlock2Expr" enabled="true" level="WEAK WARNING" enabled_by_default="true" /> <inspection_tool class="CodeBlock2Expr" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="ConstantConditions" enabled="false" level="WARNING" enabled_by_default="false">
<scope name="classlib" level="WEAK WARNING" enabled="true"> <scope name="classlib" level="WEAK WARNING" enabled="false">
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" /> <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" /> <option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
</scope> </scope>

View File

@ -26,18 +26,14 @@ import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.model.instructions.ArrayElementType; import org.teavm.model.instructions.ArrayElementType;
/**
*
* @author Alexey Andreev
*/
public class AstIO { public class AstIO {
private static NodeModifier[] nodeModifiers = NodeModifier.values(); private static final NodeModifier[] nodeModifiers = NodeModifier.values();
private static BinaryOperation[] binaryOperations = BinaryOperation.values(); private static final BinaryOperation[] binaryOperations = BinaryOperation.values();
private static UnaryOperation[] unaryOperations = UnaryOperation.values(); private static final UnaryOperation[] unaryOperations = UnaryOperation.values();
private static ArrayElementType[] arrayElementTypes = ArrayElementType.values(); private static final ArrayElementType[] arrayElementTypes = ArrayElementType.values();
private SymbolTable symbolTable; private final SymbolTable symbolTable;
private SymbolTable fileTable; private final SymbolTable fileTable;
private Map<String, IdentifiedStatement> statementMap = new HashMap<>(); private final Map<String, IdentifiedStatement> statementMap = new HashMap<>();
public AstIO(SymbolTable symbolTable, SymbolTable fileTable) { public AstIO(SymbolTable symbolTable, SymbolTable fileTable) {
this.symbolTable = symbolTable; this.symbolTable = symbolTable;
@ -51,14 +47,7 @@ public class AstIO {
output.writeShort(var); output.writeShort(var);
} }
output.writeShort(method.getParameterDebugNames().size()); output.writeShort(method.getParameterDebugNames().size());
for (Set<String> debugNames : method.getParameterDebugNames()) { writeParameters(output, method);
output.writeShort(debugNames != null ? debugNames.size() : 0);
if (debugNames != null) {
for (String debugName : debugNames) {
output.writeUTF(debugName);
}
}
}
try { try {
method.getBody().acceptVisitor(new NodeWriter(output)); method.getBody().acceptVisitor(new NodeWriter(output));
} catch (IOExceptionWrapper e) { } catch (IOExceptionWrapper e) {
@ -73,15 +62,7 @@ public class AstIO {
for (int i = 0; i < varCount; ++i) { for (int i = 0; i < varCount; ++i) {
node.getVariables().add((int) input.readShort()); node.getVariables().add((int) input.readShort());
} }
int paramDebugNameCount = input.readShort(); readParameters(input, node);
for (int i = 0; i < paramDebugNameCount; ++i) {
int debugNameCount = input.readShort();
Set<String> debugNames = new HashSet<>();
for (int j = 0; j < debugNameCount; ++j) {
debugNames.add(input.readUTF());
}
node.getParameterDebugNames().add(debugNames);
}
node.setBody(readStatement(input)); node.setBody(readStatement(input));
return node; return node;
} }
@ -93,14 +74,7 @@ public class AstIO {
output.writeShort(var); output.writeShort(var);
} }
output.writeShort(method.getParameterDebugNames().size()); output.writeShort(method.getParameterDebugNames().size());
for (Set<String> debugNames : method.getParameterDebugNames()) { writeParameters(output, method);
output.writeShort(debugNames != null ? debugNames.size() : 0);
if (debugNames != null) {
for (String debugName : debugNames) {
output.writeUTF(debugName);
}
}
}
try { try {
output.writeShort(method.getBody().size()); output.writeShort(method.getBody().size());
for (int i = 0; i < method.getBody().size(); ++i) { for (int i = 0; i < method.getBody().size(); ++i) {
@ -111,6 +85,17 @@ public class AstIO {
} }
} }
private void writeParameters(DataOutput output, MethodNode method) throws IOException {
for (Set<String> debugNames : method.getParameterDebugNames()) {
output.writeShort(debugNames != null ? debugNames.size() : 0);
if (debugNames != null) {
for (String debugName : debugNames) {
output.writeUTF(debugName);
}
}
}
}
public AsyncMethodNode readAsync(DataInput input, MethodReference method) throws IOException { public AsyncMethodNode readAsync(DataInput input, MethodReference method) throws IOException {
AsyncMethodNode node = new AsyncMethodNode(method); AsyncMethodNode node = new AsyncMethodNode(method);
node.getModifiers().addAll(unpackModifiers(input.readInt())); node.getModifiers().addAll(unpackModifiers(input.readInt()));
@ -118,6 +103,17 @@ public class AstIO {
for (int i = 0; i < varCount; ++i) { for (int i = 0; i < varCount; ++i) {
node.getVariables().add((int) input.readShort()); node.getVariables().add((int) input.readShort());
} }
readParameters(input, node);
int partCount = input.readShort();
for (int i = 0; i < partCount; ++i) {
AsyncMethodPart part = new AsyncMethodPart();
part.setStatement(readStatement(input));
node.getBody().add(part);
}
return node;
}
private void readParameters(DataInput input, MethodNode node) throws IOException {
int paramDebugNameCount = input.readShort(); int paramDebugNameCount = input.readShort();
for (int i = 0; i < paramDebugNameCount; ++i) { for (int i = 0; i < paramDebugNameCount; ++i) {
int debugNameCount = input.readShort(); int debugNameCount = input.readShort();
@ -127,13 +123,6 @@ public class AstIO {
} }
node.getParameterDebugNames().add(debugNames); node.getParameterDebugNames().add(debugNames);
} }
int partCount = input.readShort();
for (int i = 0; i < partCount; ++i) {
AsyncMethodPart part = new AsyncMethodPart();
part.setStatement(readStatement(input));
node.getBody().add(part);
}
return node;
} }
private int packModifiers(Set<NodeModifier> modifiers) { private int packModifiers(Set<NodeModifier> modifiers) {
@ -154,15 +143,15 @@ public class AstIO {
return modifiers; return modifiers;
} }
class NodeWriter implements ExprVisitor, StatementVisitor { private class NodeWriter implements ExprVisitor, StatementVisitor {
private DataOutput output; private final DataOutput output;
public NodeWriter(DataOutput output) { NodeWriter(DataOutput output) {
super(); super();
this.output = output; this.output = output;
} }
public void writeExpr(Expr expr) throws IOException { void writeExpr(Expr expr) throws IOException {
writeLocation(expr.getLocation()); writeLocation(expr.getLocation());
expr.acceptVisitor(this); expr.acceptVisitor(this);
} }
@ -515,8 +504,10 @@ public class AstIO {
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
try { try {
output.writeByte(17); output.writeByte(expr.getQualified() != null ? 17 : 18);
if (expr.getQualified() != null) {
writeExpr(expr.getQualified()); writeExpr(expr.getQualified());
}
output.writeInt(symbolTable.lookup(expr.getField().getClassName())); output.writeInt(symbolTable.lookup(expr.getField().getClassName()));
output.writeInt(symbolTable.lookup(expr.getField().getFieldName())); output.writeInt(symbolTable.lookup(expr.getField().getFieldName()));
} catch (IOException e) { } catch (IOException e) {
@ -527,7 +518,7 @@ public class AstIO {
@Override @Override
public void visit(NewExpr expr) { public void visit(NewExpr expr) {
try { try {
output.writeByte(18); output.writeByte(19);
output.writeInt(symbolTable.lookup(expr.getConstructedClass())); output.writeInt(symbolTable.lookup(expr.getConstructedClass()));
} catch (IOException e) { } catch (IOException e) {
throw new IOExceptionWrapper(e); throw new IOExceptionWrapper(e);
@ -537,7 +528,7 @@ public class AstIO {
@Override @Override
public void visit(NewArrayExpr expr) { public void visit(NewArrayExpr expr) {
try { try {
output.writeByte(19); output.writeByte(20);
writeExpr(expr.getLength()); writeExpr(expr.getLength());
output.writeInt(symbolTable.lookup(expr.getType().toString())); output.writeInt(symbolTable.lookup(expr.getType().toString()));
} catch (IOException e) { } catch (IOException e) {
@ -548,7 +539,7 @@ public class AstIO {
@Override @Override
public void visit(NewMultiArrayExpr expr) { public void visit(NewMultiArrayExpr expr) {
try { try {
output.writeByte(20); output.writeByte(21);
output.writeByte(expr.getDimensions().size()); output.writeByte(expr.getDimensions().size());
for (Expr dimension : expr.getDimensions()) { for (Expr dimension : expr.getDimensions()) {
writeExpr(dimension); writeExpr(dimension);
@ -561,19 +552,9 @@ public class AstIO {
@Override @Override
public void visit(InstanceOfExpr expr) { public void visit(InstanceOfExpr expr) {
try {
output.writeByte(21);
writeExpr(expr.getExpr());
output.writeInt(symbolTable.lookup(expr.getType().toString()));
} catch (IOException e) {
throw new IOExceptionWrapper(e);
}
}
@Override
public void visit(StaticClassExpr expr) {
try { try {
output.writeByte(22); output.writeByte(22);
writeExpr(expr.getExpr());
output.writeInt(symbolTable.lookup(expr.getType().toString())); output.writeInt(symbolTable.lookup(expr.getType().toString()));
} catch (IOException e) { } catch (IOException e) {
throw new IOExceptionWrapper(e); throw new IOExceptionWrapper(e);
@ -856,24 +837,31 @@ public class AstIO {
return parseInvocationExpr(InvocationType.DYNAMIC, input); return parseInvocationExpr(InvocationType.DYNAMIC, input);
case 17: { case 17: {
QualificationExpr expr = new QualificationExpr(); QualificationExpr expr = new QualificationExpr();
expr.setQualified(readExpr(input));
String className = symbolTable.at(input.readInt()); String className = symbolTable.at(input.readInt());
String fieldName = symbolTable.at(input.readInt()); String fieldName = symbolTable.at(input.readInt());
expr.setField(new FieldReference(className, fieldName)); expr.setField(new FieldReference(className, fieldName));
return expr; return expr;
} }
case 18: { case 18: {
QualificationExpr expr = new QualificationExpr();
expr.setQualified(readExpr(input));
String className = symbolTable.at(input.readInt());
String fieldName = symbolTable.at(input.readInt());
expr.setField(new FieldReference(className, fieldName));
return expr;
}
case 19: {
NewExpr expr = new NewExpr(); NewExpr expr = new NewExpr();
expr.setConstructedClass(symbolTable.at(input.readInt())); expr.setConstructedClass(symbolTable.at(input.readInt()));
return expr; return expr;
} }
case 19: { case 20: {
NewArrayExpr expr = new NewArrayExpr(); NewArrayExpr expr = new NewArrayExpr();
expr.setLength(readExpr(input)); expr.setLength(readExpr(input));
expr.setType(ValueType.parse(symbolTable.at(input.readInt()))); expr.setType(ValueType.parse(symbolTable.at(input.readInt())));
return expr; return expr;
} }
case 20: { case 21: {
NewMultiArrayExpr expr = new NewMultiArrayExpr(); NewMultiArrayExpr expr = new NewMultiArrayExpr();
int dimensionCount = input.readByte(); int dimensionCount = input.readByte();
for (int i = 0; i < dimensionCount; ++i) { for (int i = 0; i < dimensionCount; ++i) {
@ -882,17 +870,12 @@ public class AstIO {
expr.setType(ValueType.parse(symbolTable.at(input.readInt()))); expr.setType(ValueType.parse(symbolTable.at(input.readInt())));
return expr; return expr;
} }
case 21: { case 22: {
InstanceOfExpr expr = new InstanceOfExpr(); InstanceOfExpr expr = new InstanceOfExpr();
expr.setExpr(readExpr(input)); expr.setExpr(readExpr(input));
expr.setType(ValueType.parse(symbolTable.at(input.readInt()))); expr.setType(ValueType.parse(symbolTable.at(input.readInt())));
return expr; return expr;
} }
case 22: {
StaticClassExpr expr = new StaticClassExpr();
expr.setType(ValueType.parse(symbolTable.at(input.readInt())));
return expr;
}
default: default:
throw new RuntimeException("Unknown expression type: " + type); throw new RuntimeException("Unknown expression type: " + type);
} }
@ -911,10 +894,10 @@ public class AstIO {
return expr; return expr;
} }
static class IOExceptionWrapper extends RuntimeException { private static class IOExceptionWrapper extends RuntimeException {
private static final long serialVersionUID = -7566355431593608333L; private static final long serialVersionUID = -7566355431593608333L;
public IOExceptionWrapper(Throwable cause) { IOExceptionWrapper(Throwable cause) {
super(cause); super(cause);
} }
} }

View File

@ -22,18 +22,14 @@ import org.teavm.javascript.ast.*;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.parsing.ClassDateProvider; import org.teavm.parsing.ClassDateProvider;
/**
*
* @author Alexey Andreev
*/
public class DiskRegularMethodNodeCache implements MethodNodeCache { public class DiskRegularMethodNodeCache implements MethodNodeCache {
private File directory; private final File directory;
private AstIO astIO; private final AstIO astIO;
private ClassDateProvider classDateProvider; private final ClassDateProvider classDateProvider;
private Map<MethodReference, Item> cache = new HashMap<>(); private final Map<MethodReference, Item> cache = new HashMap<>();
private Map<MethodReference, AsyncItem> asyncCache = new HashMap<>(); private final Map<MethodReference, AsyncItem> asyncCache = new HashMap<>();
private Set<MethodReference> newMethods = new HashSet<>(); private final Set<MethodReference> newMethods = new HashSet<>();
private Set<MethodReference> newAsyncMethods = new HashSet<>(); private final Set<MethodReference> newAsyncMethods = new HashSet<>();
public DiskRegularMethodNodeCache(File directory, SymbolTable symbolTable, SymbolTable fileTable, public DiskRegularMethodNodeCache(File directory, SymbolTable symbolTable, SymbolTable fileTable,
ClassDateProvider classDateProvider) { ClassDateProvider classDateProvider) {
@ -52,17 +48,7 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
if (file.exists()) { if (file.exists()) {
try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) { try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
DataInput input = new DataInputStream(stream); DataInput input = new DataInputStream(stream);
int depCount = input.readShort(); if (!checkIfDependenciesChanged(input, file)) {
boolean dependenciesChanged = false;
for (int i = 0; i < depCount; ++i) {
String depClass = input.readUTF();
Date depDate = classDateProvider.getModificationDate(depClass);
if (depDate == null || depDate.after(new Date(file.lastModified()))) {
dependenciesChanged = true;
break;
}
}
if (!dependenciesChanged) {
item.node = astIO.read(input, methodReference); item.node = astIO.read(input, methodReference);
} }
} catch (IOException e) { } catch (IOException e) {
@ -91,17 +77,7 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
if (file.exists()) { if (file.exists()) {
try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) { try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
DataInput input = new DataInputStream(stream); DataInput input = new DataInputStream(stream);
int depCount = input.readShort(); if (!checkIfDependenciesChanged(input, file)) {
boolean dependenciesChanged = false;
for (int i = 0; i < depCount; ++i) {
String depClass = input.readUTF();
Date depDate = classDateProvider.getModificationDate(depClass);
if (depDate == null || depDate.after(new Date(file.lastModified()))) {
dependenciesChanged = true;
break;
}
}
if (!dependenciesChanged) {
item.node = astIO.readAsync(input, methodReference); item.node = astIO.readAsync(input, methodReference);
} }
} catch (IOException e) { } catch (IOException e) {
@ -112,6 +88,18 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
return item.node; return item.node;
} }
private boolean checkIfDependenciesChanged(DataInput input, File file) throws IOException {
int depCount = input.readShort();
for (int i = 0; i < depCount; ++i) {
String depClass = input.readUTF();
Date depDate = classDateProvider.getModificationDate(depClass);
if (depDate == null || depDate.after(new Date(file.lastModified()))) {
return true;
}
}
return false;
}
@Override @Override
public void storeAsync(MethodReference methodReference, AsyncMethodNode node) { public void storeAsync(MethodReference methodReference, AsyncMethodNode node) {
AsyncItem item = new AsyncItem(); AsyncItem item = new AsyncItem();
@ -159,8 +147,8 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
+ (async ? "-async" : "")); + (async ? "-async" : ""));
} }
static class AstDependencyAnalyzer implements StatementVisitor, ExprVisitor { private static class AstDependencyAnalyzer implements StatementVisitor, ExprVisitor {
Set<String> dependencies = new HashSet<>(); final Set<String> dependencies = new HashSet<>();
private void visitSequence(List<Statement> statements) { private void visitSequence(List<Statement> statements) {
for (Statement stmt : statements) { for (Statement stmt : statements) {
@ -288,8 +276,10 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
dependencies.add(expr.getField().getClassName()); dependencies.add(expr.getField().getClassName());
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
} }
}
@Override @Override
public void visit(NewExpr expr) { public void visit(NewExpr expr) {
@ -312,10 +302,6 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
} }
@Override
public void visit(StaticClassExpr expr) {
}
@Override @Override
public void visit(GotoPartStatement statement) { public void visit(GotoPartStatement statement) {
} }
@ -330,11 +316,11 @@ public class DiskRegularMethodNodeCache implements MethodNodeCache {
} }
} }
static class Item { private static class Item {
RegularMethodNode node; RegularMethodNode node;
} }
static class AsyncItem { private static class AsyncItem {
AsyncMethodNode node; AsyncMethodNode node;
} }
} }

View File

@ -19,18 +19,16 @@ import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public interface AliasProvider { public interface AliasProvider {
String getAlias(FieldReference field); String getFieldAlias(FieldReference field);
String getAlias(MethodReference method); String getStaticFieldAlias(FieldReference field);
String getAlias(MethodDescriptor method); String getStaticMethodAlias(MethodReference method);
String getAlias(String className); String getMethodAlias(MethodDescriptor method);
String getClassAlias(String className);
String getFunctionAlias(String name); String getFunctionAlias(String name);
} }

View File

@ -15,23 +15,22 @@
*/ */
package org.teavm.codegen; package org.teavm.codegen;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.teavm.model.FieldReference; import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class DefaultAliasProvider implements AliasProvider { public class DefaultAliasProvider implements AliasProvider {
private int lastSuffix; private final Map<String, String> classAliases = new HashMap<>();
private int lastVirtualSuffix; private final Set<String> knownAliases = new HashSet<>();
private Set<String> usedAliases = new HashSet<>(); private final Set<String> knownVirtualAliases = new HashSet<>();
@Override @Override
public String getAlias(String cls) { public String getClassAlias(String cls) {
return classAliases.computeIfAbsent(cls, key -> {
StringBuilder alias = new StringBuilder(); StringBuilder alias = new StringBuilder();
int lastIndex = 0; int lastIndex = 0;
while (true) { while (true) {
@ -49,47 +48,55 @@ public class DefaultAliasProvider implements AliasProvider {
lastIndex = index + 1; lastIndex = index + 1;
} }
} }
alias.append(lastSuffix++);
return alias.toString(); return makeUnique(knownAliases, alias.toString());
});
} }
@Override @Override
public String getAlias(MethodDescriptor method) { public String getMethodAlias(MethodDescriptor method) {
String alias = method.getName(); String alias = method.getName();
if (alias.equals("<init>")) { if (alias.equals("<init>")) {
alias = "$init"; alias = "$init";
} else if (alias.equals("<clinit>")) { } else if (alias.equals("<clinit>")) {
alias = "$clinit"; alias = "$clinit";
} }
String result; return makeUnique(knownVirtualAliases, alias);
do {
result = alias + lastVirtualSuffix++;
} while (!usedAliases.add(result));
return result;
} }
@Override @Override
public String getAlias(MethodReference method) { public String getStaticMethodAlias(MethodReference method) {
String alias = method.getDescriptor().getName(); String alias = method.getDescriptor().getName();
if (alias.equals("<init>")) { if (alias.equals("<init>")) {
alias = "$init"; alias = "$init";
} else if (alias.equals("<clinit>")) { } else if (alias.equals("<clinit>")) {
alias = "$clinit"; alias = "$clinit";
} }
return alias + lastSuffix++;
return makeUnique(knownAliases, getClassAlias(method.getClassName()) + "_" + alias);
} }
@Override @Override
public String getAlias(FieldReference field) { public String getFieldAlias(FieldReference field) {
String result; return makeUnique(knownVirtualAliases, field.getFieldName());
do { }
result = field.getFieldName() + lastSuffix++;
} while (!usedAliases.add(result)); @Override
return result; public String getStaticFieldAlias(FieldReference field) {
return makeUnique(knownAliases, getClassAlias(field.getClassName()) + "_" + field.getFieldName());
} }
@Override @Override
public String getFunctionAlias(String name) { public String getFunctionAlias(String name) {
return name; return name;
} }
private String makeUnique(Set<String> knowAliases, String alias) {
String uniqueAlias = alias;
int index = 1;
while (!knowAliases.add(uniqueAlias)) {
uniqueAlias = alias + index++;
}
return uniqueAlias;
}
} }

View File

@ -19,41 +19,24 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.teavm.model.*; import org.teavm.model.*;
/**
*
* @author Alexey Andreev
*/
public class DefaultNamingStrategy implements NamingStrategy { public class DefaultNamingStrategy implements NamingStrategy {
private AliasProvider aliasProvider; private final AliasProvider aliasProvider;
private ClassReaderSource classSource; private final ClassReaderSource classSource;
private Map<String, String> aliases = new HashMap<>(); private final Map<String, String> aliases = new HashMap<>();
private Map<String, String> privateAliases = new HashMap<>(); private final Map<String, String> privateAliases = new HashMap<>();
private Map<String, String> classAliases = new HashMap<>(); private final Map<String, String> classAliases = new HashMap<>();
private Map<String, String> fieldAliases = new HashMap<>(); private final Map<String, String> fieldAliases = new HashMap<>();
private Map<String, String> functionAliases = new HashMap<>(); private final Map<String, String> staticFieldAliases = new HashMap<>();
private boolean minifying; private final Map<String, String> functionAliases = new HashMap<>();
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) { public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
this.aliasProvider = aliasProvider; this.aliasProvider = aliasProvider;
this.classSource = classSource; this.classSource = classSource;
} }
public boolean isMinifying() {
return minifying;
}
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
@Override @Override
public String getNameFor(String cls) { public String getNameFor(String cls) {
String name = classAliases.get(cls); return classAliases.computeIfAbsent(cls, key -> aliasProvider.getClassAlias(cls));
if (name == null) {
name = aliasProvider.getAlias(cls);
classAliases.put(cls, name);
}
return name;
} }
@Override @Override
@ -65,7 +48,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
String key = classifier + method.toString(); String key = classifier + method.toString();
String alias = aliases.get(key); String alias = aliases.get(key);
if (alias == null) { if (alias == null) {
alias = aliasProvider.getAlias(method); alias = aliasProvider.getMethodAlias(method);
aliases.put(key, alias); aliases.put(key, alias);
} }
return alias; return alias;
@ -87,16 +70,10 @@ public class DefaultNamingStrategy implements NamingStrategy {
if (method == null) { if (method == null) {
throw new NamingException("Can't provide name for method as it was not found: " + originalMethod); throw new NamingException("Can't provide name for method as it was not found: " + originalMethod);
} }
if (!minifying) {
return getNameFor(method.getClassName()) + "_" + getNameFor(method.getDescriptor(), classifier); MethodReference resolvedMethod = method;
} return privateAliases.computeIfAbsent(classifier + method.toString(),
String key = classifier + method.toString(); key -> aliasProvider.getStaticMethodAlias(resolvedMethod));
String alias = privateAliases.get(key);
if (alias == null) {
alias = aliasProvider.getAlias(method);
privateAliases.put(key, alias);
}
return alias;
} }
@Override @Override
@ -107,27 +84,26 @@ public class DefaultNamingStrategy implements NamingStrategy {
fieldAliases.put(field.getClassName() + "#" + field, alias); fieldAliases.put(field.getClassName() + "#" + field, alias);
return alias; return alias;
} else { } else {
String key = realCls + "#" + field; return fieldAliases.computeIfAbsent(realCls + "#" + field, key -> aliasProvider.getFieldAlias(field));
String alias = fieldAliases.get(key);
if (alias == null) {
alias = aliasProvider.getAlias(field);
fieldAliases.put(key, alias);
} }
}
@Override
public String getFullNameFor(FieldReference field) throws NamingException {
String realCls = getRealFieldOwner(field.getClassName(), field.getFieldName());
if (!realCls.equals(field.getClassName())) {
String alias = getNameFor(new FieldReference(realCls, field.getFieldName()));
staticFieldAliases.put(field.getClassName() + "#" + field, alias);
return alias; return alias;
} else {
return staticFieldAliases.computeIfAbsent(realCls + "#" + field,
key -> aliasProvider.getStaticFieldAlias(field));
} }
} }
@Override @Override
public String getNameForFunction(String name) throws NamingException { public String getNameForFunction(String name) throws NamingException {
if (!minifying) { return functionAliases.computeIfAbsent(name, key -> aliasProvider.getFunctionAlias(name));
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) {

View File

@ -22,22 +22,18 @@ import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class MinifyingAliasProvider implements AliasProvider { public class MinifyingAliasProvider implements AliasProvider {
private static Set<String> keywords = new HashSet<>(Arrays.asList("do", "if", "else", "for", "case", private static final Set<String> keywords = new HashSet<>(Arrays.asList("do", "if", "else", "for", "case",
"goto", "in", "let", "new", "this", "try", "var", "void", "with")); "goto", "in", "let", "new", "this", "try", "var", "void", "with"));
private static String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; private static final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int lastSuffix; private int lastSuffix;
private int lastVirtual; private int lastVirtual;
private Set<String> usedAliases = new HashSet<>(); private final Set<String> usedAliases = new HashSet<>();
@Override @Override
public String getAlias(FieldReference field) { public String getFieldAlias(FieldReference field) {
String result; String result;
do { do {
result = getNewAlias(lastVirtual++, startVirtualLetters); result = getNewAlias(lastVirtual++, startVirtualLetters);
@ -46,12 +42,21 @@ public class MinifyingAliasProvider implements AliasProvider {
} }
@Override @Override
public String getAlias(MethodReference method) { public String getStaticFieldAlias(FieldReference field) {
String result;
do {
result = getNewAlias(lastSuffix++, startLetters);
} while (!usedAliases.add(result) || keywords.contains(result));
return result;
}
@Override
public String getStaticMethodAlias(MethodReference method) {
return getNewAlias(lastSuffix++, startLetters); return getNewAlias(lastSuffix++, startLetters);
} }
@Override @Override
public String getAlias(MethodDescriptor method) { public String getMethodAlias(MethodDescriptor method) {
String result; String result;
do { do {
result = getNewAlias(lastVirtual++, startVirtualLetters); result = getNewAlias(lastVirtual++, startVirtualLetters);
@ -60,7 +65,7 @@ public class MinifyingAliasProvider implements AliasProvider {
} }
@Override @Override
public String getAlias(String className) { public String getClassAlias(String className) {
return getNewAlias(lastSuffix++, startLetters); return getNewAlias(lastSuffix++, startLetters);
} }

View File

@ -19,10 +19,6 @@ import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public interface NamingStrategy { public interface NamingStrategy {
String getNameFor(String cls) throws NamingException; String getNameFor(String cls) throws NamingException;
@ -34,5 +30,7 @@ public interface NamingStrategy {
String getNameFor(FieldReference field) throws NamingException; String getNameFor(FieldReference field) throws NamingException;
String getFullNameFor(FieldReference method) throws NamingException;
String getNameForFunction(String name) throws NamingException; String getNameForFunction(String name) throws NamingException;
} }

View File

@ -21,17 +21,13 @@ import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
public class SourceWriter implements Appendable, LocationProvider { public class SourceWriter implements Appendable, LocationProvider {
private Appendable innerWriter; private final Appendable innerWriter;
private int indentSize; private int indentSize;
private NamingStrategy naming; private final NamingStrategy naming;
private boolean lineStart; private boolean lineStart;
private boolean minified; private boolean minified;
private int lineWidth; private final int lineWidth;
private int column; private int column;
private int line; private int line;
@ -111,6 +107,10 @@ public class SourceWriter implements Appendable, LocationProvider {
return append(naming.getNameFor(field)); return append(naming.getNameFor(field));
} }
public SourceWriter appendStaticField(FieldReference field) throws NamingException, IOException {
return append(naming.getFullNameFor(field));
}
public SourceWriter appendMethod(MethodDescriptor method) throws NamingException, IOException { public SourceWriter appendMethod(MethodDescriptor method) throws NamingException, IOException {
return append(naming.getNameFor(method)); return append(naming.getNameFor(method));
} }

View File

@ -26,8 +26,8 @@ import org.teavm.model.MethodReference;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class AsyncCallsFinder implements StatementVisitor, ExprVisitor { class AsyncCallsFinder implements StatementVisitor, ExprVisitor {
Set<MethodReference> asyncCalls = new HashSet<>(); final Set<MethodReference> asyncCalls = new HashSet<>();
Set<MethodReference> allCalls = new HashSet<>(); final Set<MethodReference> allCalls = new HashSet<>();
private void visitList(List<Statement> statements) { private void visitList(List<Statement> statements) {
for (Statement stmt : statements) { for (Statement stmt : statements) {
@ -178,8 +178,10 @@ class AsyncCallsFinder implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
} }
}
@Override @Override
public void visit(NewExpr expr) { public void visit(NewExpr expr) {
@ -201,8 +203,4 @@ class AsyncCallsFinder implements StatementVisitor, ExprVisitor {
public void visit(InstanceOfExpr expr) { public void visit(InstanceOfExpr expr) {
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
} }
@Override
public void visit(StaticClassExpr expr) {
}
} }

View File

@ -21,18 +21,14 @@ import org.teavm.codegen.NameFrequencyConsumer;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
import org.teavm.model.*; import org.teavm.model.*;
/** class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, MethodNodeVisitor {
* private final NameFrequencyConsumer consumer;
* @author Alexey Andreev private final ClassReaderSource classSource;
*/
public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, MethodNodeVisitor {
private NameFrequencyConsumer consumer;
private ClassReaderSource classSource;
private boolean async; private boolean async;
private Set<MethodReference> injectedMethods; private final Set<MethodReference> injectedMethods;
private Set<MethodReference> asyncFamilyMethods; private final Set<MethodReference> asyncFamilyMethods;
public NameFrequencyEstimator(NameFrequencyConsumer consumer, ClassReaderSource classSource, NameFrequencyEstimator(NameFrequencyConsumer consumer, ClassReaderSource classSource,
Set<MethodReference> injectedMethods, Set<MethodReference> asyncFamilyMethods) { Set<MethodReference> injectedMethods, Set<MethodReference> asyncFamilyMethods) {
this.consumer = consumer; this.consumer = consumer;
this.classSource = classSource; this.classSource = classSource;
@ -309,7 +305,9 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
}
consumer.consume(expr.getField()); consumer.consume(expr.getField());
} }
@ -349,9 +347,4 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
consumer.consumeFunction("$rt_isInstance"); consumer.consumeFunction("$rt_isInstance");
} }
} }
@Override
public void visit(StaticClassExpr expr) {
visitType(expr.getType());
}
} }

View File

@ -30,10 +30,6 @@ import org.teavm.model.util.LivenessAnalyzer;
import org.teavm.model.util.ProgramUtils; import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.UsageExtractor; import org.teavm.model.util.UsageExtractor;
/**
*
* @author Alexey Andreev
*/
public class Optimizer { public class Optimizer {
public void optimize(RegularMethodNode method, Program program) { public void optimize(RegularMethodNode method, Program program) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());

View File

@ -16,20 +16,17 @@
package org.teavm.javascript; package org.teavm.javascript;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
/**
*
* @author Alexey Andreev
*/
class OptimizingVisitor implements StatementVisitor, ExprVisitor { class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public Expr resultExpr; private Expr resultExpr;
public Statement resultStmt; Statement resultStmt;
private boolean[] preservedVars; private final boolean[] preservedVars;
private int[] readFrequencies; private final int[] readFrequencies;
private List<Statement> resultSequence; private List<Statement> resultSequence;
public OptimizingVisitor(boolean[] preservedVars, int[] readFreqencies) { OptimizingVisitor(boolean[] preservedVars, int[] readFreqencies) {
this.preservedVars = preservedVars; this.preservedVars = preservedVars;
this.readFrequencies = readFreqencies; this.readFrequencies = readFreqencies;
} }
@ -261,9 +258,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
Expr qualified = resultExpr; Expr qualified = resultExpr;
expr.setQualified(qualified); expr.setQualified(qualified);
}
resultExpr = expr; resultExpr = expr;
} }
@ -297,11 +296,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
resultExpr = expr; resultExpr = expr;
} }
@Override
public void visit(StaticClassExpr expr) {
resultExpr = expr;
}
@Override @Override
public void visit(AssignmentStatement statement) { public void visit(AssignmentStatement statement) {
if (statement.getLeftValue() == null) { if (statement.getLeftValue() == null) {
@ -331,19 +325,13 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
resultSequence = new ArrayList<>(); resultSequence = new ArrayList<>();
processSequenceImpl(statements); processSequenceImpl(statements);
wieldTryCatch(resultSequence); wieldTryCatch(resultSequence);
List<Statement> result = new ArrayList<>(); List<Statement> result = resultSequence.stream().filter(part -> part != null).collect(Collectors.toList());
for (Statement part : resultSequence) {
if (part != null) {
result.add(part);
}
}
resultSequence = backup; resultSequence = backup;
return result; return result;
} }
private boolean processSequenceImpl(List<Statement> statements) { private boolean processSequenceImpl(List<Statement> statements) {
for (int i = 0; i < statements.size(); ++i) { for (Statement part : statements) {
Statement part = statements.get(i);
if (part instanceof SequentialStatement) { if (part instanceof SequentialStatement) {
if (!processSequenceImpl(((SequentialStatement) part).getSequence())) { if (!processSequenceImpl(((SequentialStatement) part).getSequence())) {
return false; return false;
@ -440,7 +428,6 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
List<Statement> remaining = statements.subList(i + 1, statements.size()); List<Statement> remaining = statements.subList(i + 1, statements.size());
cond.getConsequent().addAll(remaining); cond.getConsequent().addAll(remaining);
remaining.clear(); remaining.clear();
break check_conditional;
} }
} }
} }

View File

@ -73,7 +73,6 @@ import org.teavm.javascript.ast.ReturnStatement;
import org.teavm.javascript.ast.SequentialStatement; import org.teavm.javascript.ast.SequentialStatement;
import org.teavm.javascript.ast.Statement; import org.teavm.javascript.ast.Statement;
import org.teavm.javascript.ast.StatementVisitor; import org.teavm.javascript.ast.StatementVisitor;
import org.teavm.javascript.ast.StaticClassExpr;
import org.teavm.javascript.ast.SubscriptExpr; import org.teavm.javascript.ast.SubscriptExpr;
import org.teavm.javascript.ast.SwitchClause; import org.teavm.javascript.ast.SwitchClause;
import org.teavm.javascript.ast.SwitchStatement; import org.teavm.javascript.ast.SwitchStatement;
@ -100,50 +99,46 @@ import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext { public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext {
private static final String variableNames = "abcdefghijkmnopqrstuvwxyz"; private static final String variableNames = "abcdefghijkmnopqrstuvwxyz";
private static final String variablePartNames = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static final String variablePartNames = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private NamingStrategy naming; private final NamingStrategy naming;
private SourceWriter writer; private final SourceWriter writer;
private ListableClassHolderSource classSource; private final ListableClassHolderSource classSource;
private ClassLoader classLoader; private final ClassLoader classLoader;
private boolean minifying; private boolean minifying;
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>(); private final Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
private Map<String, Integer> stringPoolMap = new HashMap<>(); private final Map<String, Integer> stringPoolMap = new HashMap<>();
private List<String> stringPool = new ArrayList<>(); private final List<String> stringPool = new ArrayList<>();
private Properties properties = new Properties(); private final Properties properties = new Properties();
private ServiceRepository services; private final ServiceRepository services;
private DebugInformationEmitter debugEmitter = new DummyDebugInformationEmitter(); private DebugInformationEmitter debugEmitter = new DummyDebugInformationEmitter();
private Deque<LocationStackEntry> locationStack = new ArrayDeque<>(); private final Deque<LocationStackEntry> locationStack = new ArrayDeque<>();
private DeferredCallSite lastCallSite; private DeferredCallSite lastCallSite;
private DeferredCallSite prevCallSite; private DeferredCallSite prevCallSite;
private Set<MethodReference> asyncMethods; private final Set<MethodReference> asyncMethods;
private Set<MethodReference> asyncFamilyMethods; private final Set<MethodReference> asyncFamilyMethods;
private Diagnostics diagnostics; private final Diagnostics diagnostics;
private boolean async; private boolean async;
private Precedence precedence; private Precedence precedence;
private Map<String, String> blockIdMap = new HashMap<>(); private final Map<String, String> blockIdMap = new HashMap<>();
private List<Set<String>> debugNames = new ArrayList<>(); private final List<Set<String>> debugNames = new ArrayList<>();
private List<String> cachedVariableNames = new ArrayList<>(); private final List<String> cachedVariableNames = new ArrayList<>();
private boolean end; private boolean end;
private int currentPart; private int currentPart;
private static class InjectorHolder { private static class InjectorHolder {
public final Injector injector; public final Injector injector;
public InjectorHolder(Injector injector) { private InjectorHolder(Injector injector) {
this.injector = injector; this.injector = injector;
} }
} }
private static class LocationStackEntry { private static class LocationStackEntry {
NodeLocation location; final NodeLocation location;
public LocationStackEntry(NodeLocation location) { LocationStackEntry(NodeLocation location) {
this.location = location; this.location = location;
} }
} }
@ -403,7 +398,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
value = getDefaultValue(field.getType()); value = getDefaultValue(field.getType());
} }
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName()); FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
writer.appendClass(cls.getName()).append('.').appendField(fieldRef).ws().append("=").ws() writer.append("var ").appendStaticField(fieldRef).ws().append("=").ws()
.append(constantToString(value)).append(";").softNewLine(); .append(constantToString(value)).append(";").softNewLine();
} }
} catch (NamingException e) { } catch (NamingException e) {
@ -431,9 +426,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
if (needsClinit) { if (needsClinit) {
writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws() writer.append("function ").appendClass(cls.getName()).append("_$callClinit()").ws()
.append("{").softNewLine().indent(); .append("{").softNewLine().indent();
writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws() writer.appendClass(cls.getName()).append("_$callClinit").ws().append("=").ws()
.append("function(){};").newLine(); .append("function(){};").newLine();
for (MethodNode method : clinitMethods) { for (MethodNode method : clinitMethods) {
renderBody(method, true); renderBody(method, true);
@ -498,7 +493,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
MethodHolder clinit = classSource.get(cls.getName()).getMethod( MethodHolder clinit = classSource.get(cls.getName()).getMethod(
new MethodDescriptor("<clinit>", ValueType.VOID)); new MethodDescriptor("<clinit>", ValueType.VOID));
if (clinit != null) { if (clinit != null) {
writer.appendClass(cls.getName()).append("_$clinit"); writer.appendClass(cls.getName()).append("_$callClinit");
} else { } else {
writer.append('0'); writer.append('0');
} }
@ -624,13 +619,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
writer.appendMethodBody(ref).append("("); writer.appendMethodBody(ref).append("(");
writer.append("this"); writer.append("this");
for (int i = 0; i < args.size(); ++i) { for (String arg : args) {
writer.append(",").ws().append(args.get(i)); writer.append(",").ws().append(arg);
} }
writer.append(");").ws().append("}"); writer.append(");").ws().append("}");
} }
public void renderBody(MethodNode method, boolean inner) throws IOException { private void renderBody(MethodNode method, boolean inner) throws IOException {
debugNames.clear(); debugNames.clear();
cachedVariableNames.clear(); cachedVariableNames.clear();
debugNames.addAll(method.getParameterDebugNames()); debugNames.addAll(method.getParameterDebugNames());
@ -1211,7 +1206,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
if (statement.getLocation() != null) { if (statement.getLocation() != null) {
pushLocation(statement.getLocation()); pushLocation(statement.getLocation());
} }
writer.appendClass(statement.getClassName()).append("_$clinit();").softNewLine(); writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine();
if (statement.getLocation() != null) { if (statement.getLocation() != null) {
popLocation(); popLocation();
} }
@ -1220,7 +1215,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
} }
public String variableName(int index) { private String variableName(int index) {
while (index >= cachedVariableNames.size()) { while (index >= cachedVariableNames.size()) {
cachedVariableNames.add(null); cachedVariableNames.add(null);
} }
@ -1673,7 +1668,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
} }
public String constantToString(Object cst) { private String constantToString(Object cst) {
if (cst == null) { if (cst == null) {
return "null"; return "null";
} }
@ -1948,8 +1943,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
pushLocation(expr.getLocation()); pushLocation(expr.getLocation());
} }
precedence = Precedence.MEMBER_ACCESS; precedence = Precedence.MEMBER_ACCESS;
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
writer.append('.').appendField(expr.getField()); writer.append('.').appendField(expr.getField());
} else {
writer.appendStaticField(expr.getField());
}
if (expr.getLocation() != null) { if (expr.getLocation() != null) {
popLocation(); popLocation();
} }
@ -2140,21 +2141,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
} }
@Override
public void visit(StaticClassExpr expr) {
try {
if (expr.getLocation() != null) {
pushLocation(expr.getLocation());
}
writer.append(typeToClsString(naming, expr.getType()));
if (expr.getLocation() != null) {
popLocation();
}
} catch (IOException e) {
throw new RenderingException("IO error occured", e);
}
}
private void visitStatements(List<Statement> statements) { private void visitStatements(List<Statement> statements) {
if (statements.isEmpty()) { if (statements.isEmpty()) {
return; return;
@ -2313,10 +2299,10 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
private class InjectorContextImpl implements InjectorContext { private class InjectorContextImpl implements InjectorContext {
private List<Expr> arguments; private final List<Expr> arguments;
private Precedence precedence = Renderer.this.precedence; private final Precedence precedence = Renderer.this.precedence;
public InjectorContextImpl(List<Expr> arguments) { InjectorContextImpl(List<Expr> arguments) {
this.arguments = arguments; this.arguments = arguments;
} }

View File

@ -23,13 +23,9 @@ import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
/**
*
* @author Alexey Andreev
*/
class StatementGenerator implements InstructionVisitor { class StatementGenerator implements InstructionVisitor {
private int lastSwitchId; private int lastSwitchId;
List<Statement> statements = new ArrayList<>(); final List<Statement> statements = new ArrayList<>();
GraphIndexer indexer; GraphIndexer indexer;
BasicBlock nextBlock; BasicBlock nextBlock;
BasicBlock currentBlock; BasicBlock currentBlock;
@ -39,7 +35,7 @@ class StatementGenerator implements InstructionVisitor {
private NodeLocation currentLocation; private NodeLocation currentLocation;
boolean async; boolean async;
public void setCurrentLocation(NodeLocation currentLocation) { void setCurrentLocation(NodeLocation currentLocation) {
this.currentLocation = currentLocation; this.currentLocation = currentLocation;
} }
@ -478,8 +474,7 @@ class StatementGenerator implements InstructionVisitor {
stmt.setLocation(currentLocation); stmt.setLocation(currentLocation);
statements.add(stmt); statements.add(stmt);
} else { } else {
Expr fieldExpr = Expr.qualify(Expr.staticClass(ValueType.object(insn.getField().getClassName())), Expr fieldExpr = Expr.qualify(null, insn.getField());
insn.getField());
AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), fieldExpr); AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), fieldExpr);
stmt.setLocation(currentLocation); stmt.setLocation(currentLocation);
statements.add(stmt); statements.add(stmt);
@ -493,7 +488,7 @@ class StatementGenerator implements InstructionVisitor {
if (insn.getInstance() != null) { if (insn.getInstance() != null) {
left = Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField()); left = Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField());
} else { } else {
left = Expr.qualify(Expr.staticClass(ValueType.object(insn.getField().getClassName())), insn.getField()); left = Expr.qualify(null, insn.getField());
} }
AssignmentStatement stmt = Statement.assign(left, right); AssignmentStatement stmt = Statement.assign(left, right);
stmt.setLocation(currentLocation); stmt.setLocation(currentLocation);

View File

@ -19,16 +19,12 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import org.teavm.javascript.ast.*; import org.teavm.javascript.ast.*;
/**
*
* @author Alexey Andreev
*/
class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
int[] variables; private final int[] variables;
int[] indexes; private final int[] indexes;
int lastIndex; int lastIndex;
public UnusedVariableEliminator(int parameterCount, List<Integer> variables) { UnusedVariableEliminator(int parameterCount, List<Integer> variables) {
this.variables = new int[variables.size()]; this.variables = new int[variables.size()];
int variableCount = 0; int variableCount = 0;
for (int i = 0; i < variables.size(); ++i) { for (int i = 0; i < variables.size(); ++i) {
@ -176,8 +172,10 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
@Override @Override
public void visit(QualificationExpr expr) { public void visit(QualificationExpr expr) {
if (expr.getQualified() != null) {
expr.getQualified().acceptVisitor(this); expr.getQualified().acceptVisitor(this);
} }
}
@Override @Override
public void visit(NewExpr expr) { public void visit(NewExpr expr) {
@ -200,10 +198,6 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
expr.getExpr().acceptVisitor(this); expr.getExpr().acceptVisitor(this);
} }
@Override
public void visit(StaticClassExpr expr) {
}
@Override @Override
public void visit(InitClassStatement statement) { public void visit(InitClassStatement statement) {
} }

View File

@ -20,10 +20,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.teavm.model.*; import org.teavm.model.*;
/**
*
* @author Alexey Andreev
*/
public abstract class Expr implements Cloneable { public abstract class Expr implements Cloneable {
private NodeLocation location; private NodeLocation location;
@ -152,12 +148,6 @@ public abstract class Expr implements Cloneable {
return expr; return expr;
} }
public static Expr staticClass(ValueType type) {
StaticClassExpr expr = new StaticClassExpr();
expr.setType(type);
return expr;
}
public NodeLocation getLocation() { public NodeLocation getLocation() {
return location; return location;
} }

View File

@ -15,10 +15,6 @@
*/ */
package org.teavm.javascript.ast; package org.teavm.javascript.ast;
/**
*
* @author Alexey Andreev
*/
public interface ExprVisitor { public interface ExprVisitor {
void visit(BinaryExpr expr); void visit(BinaryExpr expr);
@ -45,6 +41,4 @@ public interface ExprVisitor {
void visit(NewMultiArrayExpr expr); void visit(NewMultiArrayExpr expr);
void visit(InstanceOfExpr expr); void visit(InstanceOfExpr expr);
void visit(StaticClassExpr expr);
} }

View File

@ -1,206 +0,0 @@
/*
* Copyright 2013 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.javascript.ast;
/**
*
* @author Alexey Andreev
*/
public class RenamingVisitor implements StatementVisitor, ExprVisitor {
private int[] varNames;
public RenamingVisitor(int[] varNames) {
this.varNames = varNames;
}
@Override
public void visit(BinaryExpr expr) {
expr.getFirstOperand().acceptVisitor(this);
expr.getSecondOperand().acceptVisitor(this);
}
@Override
public void visit(UnaryExpr expr) {
expr.getOperand().acceptVisitor(this);
}
@Override
public void visit(ConditionalExpr expr) {
expr.getCondition().acceptVisitor(this);
expr.getConsequent().acceptVisitor(this);
expr.getAlternative().acceptVisitor(this);
}
@Override
public void visit(ConstantExpr expr) {
}
@Override
public void visit(VariableExpr expr) {
expr.setIndex(varNames[expr.getIndex()]);
}
@Override
public void visit(SubscriptExpr expr) {
expr.getArray().acceptVisitor(this);
expr.getIndex().acceptVisitor(this);
}
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
}
@Override
public void visit(InvocationExpr expr) {
for (Expr arg : expr.getArguments()) {
arg.acceptVisitor(this);
}
}
@Override
public void visit(QualificationExpr expr) {
expr.getQualified().acceptVisitor(this);
}
@Override
public void visit(NewExpr expr) {
}
@Override
public void visit(NewArrayExpr expr) {
expr.getLength().acceptVisitor(this);
}
@Override
public void visit(NewMultiArrayExpr expr) {
for (Expr dim : expr.getDimensions()) {
dim.acceptVisitor(this);
}
}
@Override
public void visit(InstanceOfExpr expr) {
expr.getExpr().acceptVisitor(this);
}
@Override
public void visit(StaticClassExpr expr) {
}
@Override
public void visit(AssignmentStatement statement) {
if (statement.getLeftValue() != null) {
statement.getLeftValue().acceptVisitor(this);
}
statement.getRightValue().acceptVisitor(this);
}
@Override
public void visit(SequentialStatement statement) {
for (Statement part : statement.getSequence()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(ConditionalStatement statement) {
statement.getCondition().acceptVisitor(this);
for (Statement part : statement.getConsequent()) {
part.acceptVisitor(this);
}
for (Statement part : statement.getAlternative()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(SwitchStatement statement) {
statement.getValue().acceptVisitor(this);
for (SwitchClause clause : statement.getClauses()) {
for (Statement part : clause.getBody()) {
part.acceptVisitor(this);
}
}
for (Statement part : statement.getDefaultClause()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(WhileStatement statement) {
if (statement.getCondition() != null) {
statement.getCondition().acceptVisitor(this);
}
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(BlockStatement statement) {
for (Statement part : statement.getBody()) {
part.acceptVisitor(this);
}
}
@Override
public void visit(BreakStatement statement) {
}
@Override
public void visit(ContinueStatement statement) {
}
@Override
public void visit(ReturnStatement statement) {
if (statement.getResult() != null) {
statement.getResult().acceptVisitor(this);
}
}
@Override
public void visit(ThrowStatement statement) {
statement.getException().acceptVisitor(this);
}
@Override
public void visit(InitClassStatement statement) {
}
@Override
public void visit(TryCatchStatement statement) {
for (Statement part : statement.getProtectedBody()) {
part.acceptVisitor(this);
}
for (Statement part : statement.getHandler()) {
part.acceptVisitor(this);
}
statement.setExceptionVariable(varNames[statement.getExceptionVariable()]);
}
@Override
public void visit(GotoPartStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -1,52 +0,0 @@
/*
* Copyright 2012 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.javascript.ast;
import java.util.Map;
import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
public class StaticClassExpr extends Expr {
private ValueType type;
public ValueType getType() {
return type;
}
public void setType(ValueType type) {
this.type = type;
}
@Override
public void acceptVisitor(ExprVisitor visitor) {
visitor.visit(this);
}
@Override
protected Expr clone(Map<Expr, Expr> cache) {
Expr known = cache.get(this);
if (known != null) {
return known;
}
StaticClassExpr copy = new StaticClassExpr();
cache.put(this, copy);
copy.setType(type);
return copy;
}
}

View File

@ -69,20 +69,20 @@ import org.teavm.vm.spi.TeaVMPlugin;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TeaVM implements TeaVMHost, ServiceRepository { public class TeaVM implements TeaVMHost, ServiceRepository {
private ClassReaderSource classSource; private final ClassReaderSource classSource;
private DependencyChecker dependencyChecker; private final DependencyChecker dependencyChecker;
private AccumulationDiagnostics diagnostics = new AccumulationDiagnostics(); private final AccumulationDiagnostics diagnostics = new AccumulationDiagnostics();
private ClassLoader classLoader; private final ClassLoader classLoader;
private boolean minifying = true; private boolean minifying = true;
private boolean bytecodeLogging; private boolean bytecodeLogging;
private OutputStream logStream = System.out; private final OutputStream logStream = System.out;
private Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>(); private final Map<String, TeaVMEntryPoint> entryPoints = new HashMap<>();
private Map<String, String> exportedClasses = new HashMap<>(); private final Map<String, String> exportedClasses = new HashMap<>();
private Map<MethodReference, Generator> methodGenerators = new HashMap<>(); private final Map<MethodReference, Generator> methodGenerators = new HashMap<>();
private Map<MethodReference, Injector> methodInjectors = new HashMap<>(); private final Map<MethodReference, Injector> methodInjectors = new HashMap<>();
private List<RendererListener> rendererListeners = new ArrayList<>(); private final List<RendererListener> rendererListeners = new ArrayList<>();
private Map<Class<?>, Object> services = new HashMap<>(); private final Map<Class<?>, Object> services = new HashMap<>();
private Properties properties = new Properties(); private final Properties properties = new Properties();
private DebugInformationEmitter debugEmitter; private DebugInformationEmitter debugEmitter;
private ProgramCache programCache; private ProgramCache programCache;
private MethodNodeCache astCache = new EmptyRegularMethodNodeCache(); private MethodNodeCache astCache = new EmptyRegularMethodNodeCache();
@ -90,8 +90,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
private TeaVMProgressListener progressListener; private TeaVMProgressListener progressListener;
private boolean cancelled; private boolean cancelled;
private ListableClassHolderSource writtenClasses; private ListableClassHolderSource writtenClasses;
private Set<MethodReference> asyncMethods = new HashSet<>(); private final Set<MethodReference> asyncMethods = new HashSet<>();
private Set<MethodReference> asyncFamilyMethods = new HashSet<>(); private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) { TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
this.classSource = classSource; this.classSource = classSource;
@ -288,10 +288,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
exportedClasses.put(name, className); exportedClasses.put(name, className);
} }
public void linkType(String className) {
dependencyChecker.linkClass(className, null).initClass(null);
}
/** /**
* Gets a {@link ClassReaderSource} which is used by this TeaVM instance. It is exactly what was * Gets a {@link ClassReaderSource} which is used by this TeaVM instance. It is exactly what was
* passed to {@link TeaVMBuilder#setClassSource(ClassHolderSource)}. * passed to {@link TeaVMBuilder#setClassSource(ClassHolderSource)}.
@ -420,7 +416,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return; return;
} }
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource()); DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource());
naming.setMinifying(minifying);
SourceWriterBuilder builder = new SourceWriterBuilder(naming); SourceWriterBuilder builder = new SourceWriterBuilder(naming);
builder.setMinified(minifying); builder.setMinified(minifying);
SourceWriter sourceWriter = builder.build(writer); SourceWriter sourceWriter = builder.build(writer);

View File

@ -7,6 +7,7 @@
<property key="Bundle-Description" value="Implementation of metaprogramming API" /> <property key="Bundle-Description" value="Implementation of metaprogramming API" />
<property key="Export-Package" value="org.teavm.metaprogramming.*" /> <property key="Export-Package" value="org.teavm.metaprogramming.*" />
<property key="Bundle-Name" value="TeaVM metaprogramming API implementation" /> <property key="Bundle-Name" value="TeaVM metaprogramming API implementation" />
<property key="Include-Resource" value="META-INF/services/org.teavm.vm.spi.TeaVMPlugin=$MODULE_DIR$/src/main/resources/META-INF/services/org.teavm.vm.spi.TeaVMPlugin" />
</additionalProperties> </additionalProperties>
<additionalJARContents /> <additionalJARContents />
</configuration> </configuration>

View File

@ -24,6 +24,8 @@
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2" level="project" /> <orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-runtime:1.0.1-2" level="project" /> <orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-runtime:1.0.1-2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains.kotlin:kotlin-runtime:1.0.1-2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" /> <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" /> <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="module" module-name="teavm-classlib" scope="PROVIDED" /> <orderEntry type="module" module-name="teavm-classlib" scope="PROVIDED" />

View File

@ -9,7 +9,7 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="jdk" jdkName="IntelliJ IDEA IU-144.3600.7" jdkType="IDEA JDK" /> <orderEntry type="jdk" jdkName="IntelliJ IDEA" jdkType="IDEA JDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.ow2.asm:asm-debug-all:5.0.4" level="project" /> <orderEntry type="library" name="Maven: org.ow2.asm:asm-debug-all:5.0.4" level="project" />
<orderEntry type="library" name="teavm-all" level="project" /> <orderEntry type="library" name="teavm-all" level="project" />

View File

@ -10,7 +10,7 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="jdk" jdkName="IntelliJ IDEA IU-144.3600.7" jdkType="IDEA JDK" /> <orderEntry type="jdk" jdkName="IntelliJ IDEA" jdkType="IDEA JDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="teavm-jps-plugin" /> <orderEntry type="module" module-name="teavm-jps-plugin" />
<orderEntry type="library" name="teavm-all" level="project" /> <orderEntry type="library" name="teavm-all" level="project" />

View File

@ -76,7 +76,7 @@ class HtmlUnitRunStrategy implements TestRunStrategy {
private void init() { private void init() {
webClient.set(new WebClient(BrowserVersion.CHROME)); webClient.set(new WebClient(BrowserVersion.CHROME));
try { try {
page.set(webClient.get().getPage("about:blank")); page.set(webClient.get().<HtmlPage>getPage("about:blank"));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }