mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Decrease memory consumption during compilation
This commit is contained in:
parent
2a1aca98da
commit
88dca1bd02
|
@ -17,13 +17,23 @@ package org.teavm.backend.javascript.codegen;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.AccessLevel;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
public class DefaultNamingStrategy implements NamingStrategy {
|
||||
private static final byte NO_CLASSIFIER = 0;
|
||||
private static final byte INIT_CLASSIFIER = 1;
|
||||
|
||||
private final AliasProvider aliasProvider;
|
||||
private final ClassReaderSource classSource;
|
||||
private final Map<String, String> aliases = new HashMap<>();
|
||||
private final Map<String, ScopedName> privateAliases = new HashMap<>();
|
||||
private final Map<MethodDescriptor, String> aliases = new HashMap<>();
|
||||
private final Map<Key, ScopedName> privateAliases = new HashMap<>();
|
||||
private final Map<String, ScopedName> classAliases = new HashMap<>();
|
||||
private final Map<FieldReference, String> fieldAliases = new HashMap<>();
|
||||
private final Map<FieldReference, ScopedName> staticFieldAliases = new HashMap<>();
|
||||
|
@ -43,35 +53,33 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
|
||||
@Override
|
||||
public String getNameFor(MethodDescriptor method) {
|
||||
String key = method.toString();
|
||||
String alias = aliases.get(key);
|
||||
String alias = aliases.get(method);
|
||||
if (alias == null) {
|
||||
alias = aliasProvider.getMethodAlias(method);
|
||||
aliases.put(key, alias);
|
||||
aliases.put(method, alias);
|
||||
}
|
||||
return alias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScopedName getFullNameFor(MethodReference method) {
|
||||
return getFullNameFor(method, 'M');
|
||||
return getFullNameFor(method, NO_CLASSIFIER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScopedName getNameForInit(MethodReference method) {
|
||||
return getFullNameFor(method, 'I');
|
||||
return getFullNameFor(method, INIT_CLASSIFIER);
|
||||
}
|
||||
|
||||
private ScopedName getFullNameFor(MethodReference method, char classifier) {
|
||||
private ScopedName getFullNameFor(MethodReference method, byte classifier) {
|
||||
MethodReference originalMethod = method;
|
||||
method = getRealMethod(method);
|
||||
if (method == null) {
|
||||
method = originalMethod;
|
||||
}
|
||||
|
||||
MethodReference resolvedMethod = method;
|
||||
return privateAliases.computeIfAbsent(classifier + method.toString(),
|
||||
key -> aliasProvider.getStaticMethodAlias(resolvedMethod));
|
||||
return privateAliases.computeIfAbsent(new Key(classifier, method),
|
||||
key -> aliasProvider.getStaticMethodAlias(key.data));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -155,4 +163,38 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
}
|
||||
return fieldRef;
|
||||
}
|
||||
|
||||
private final class Key {
|
||||
final MethodReference data;
|
||||
int hash;
|
||||
final byte classifier;
|
||||
|
||||
Key(byte classifier, MethodReference data) {
|
||||
this.classifier = classifier;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Key)) {
|
||||
return false;
|
||||
}
|
||||
Key key = (Key) o;
|
||||
return classifier == key.classifier && data.equals(key.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = (classifier * 31 + data.hashCode()) * 17;
|
||||
if (hash == 0) {
|
||||
hash++;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
154
core/src/main/java/org/teavm/cache/AstIO.java
vendored
154
core/src/main/java/org/teavm/cache/AstIO.java
vendored
|
@ -20,6 +20,7 @@ import java.util.EnumSet;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.ArrayType;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
|
@ -82,16 +83,22 @@ public class AstIO {
|
|||
private static final UnaryOperation[] unaryOperations = UnaryOperation.values();
|
||||
private final SymbolTable symbolTable;
|
||||
private final SymbolTable fileTable;
|
||||
private final SymbolTable variableTable;
|
||||
private final Map<String, IdentifiedStatement> statementMap = new HashMap<>();
|
||||
private ReferenceCache referenceCache;
|
||||
private TextLocation lastWrittenLocation;
|
||||
private TextLocation lastReadLocation;
|
||||
|
||||
public AstIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable) {
|
||||
public AstIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable,
|
||||
SymbolTable variableTable) {
|
||||
this.referenceCache = referenceCache;
|
||||
this.symbolTable = symbolTable;
|
||||
this.fileTable = fileTable;
|
||||
this.variableTable = variableTable;
|
||||
}
|
||||
|
||||
public void write(VarDataOutput output, ControlFlowEntry[] cfg) throws IOException {
|
||||
lastWrittenLocation = null;
|
||||
output.writeUnsigned(cfg.length);
|
||||
for (ControlFlowEntry entry : cfg) {
|
||||
writeLocation(output, entry.from);
|
||||
|
@ -118,10 +125,11 @@ public class AstIO {
|
|||
private void write(VarDataOutput output, VariableNode variable) throws IOException {
|
||||
output.writeUnsigned(variable.getIndex());
|
||||
output.writeUnsigned(variable.getType().ordinal());
|
||||
output.write(variable.getName());
|
||||
output.writeUnsigned(variable.getName() != null ? variableTable.lookup(variable.getName()) + 1 : 0);
|
||||
}
|
||||
|
||||
public ControlFlowEntry[] readControlFlow(VarDataInput input) throws IOException {
|
||||
lastReadLocation = null;
|
||||
int size = input.readUnsigned();
|
||||
ControlFlowEntry[] result = new ControlFlowEntry[size];
|
||||
for (int i = 0; i < size; ++i) {
|
||||
|
@ -143,6 +151,7 @@ public class AstIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
node.getVariables().add(readVariable(input));
|
||||
}
|
||||
lastReadLocation = null;
|
||||
node.setBody(readStatement(input));
|
||||
return node;
|
||||
}
|
||||
|
@ -151,7 +160,8 @@ public class AstIO {
|
|||
int index = input.readUnsigned();
|
||||
VariableType type = VariableType.values()[input.readUnsigned()];
|
||||
VariableNode variable = new VariableNode(index, type);
|
||||
variable.setName(input.read());
|
||||
int nameIndex = input.readUnsigned();
|
||||
variable.setName(nameIndex != 0 ? variableTable.at(nameIndex - 1) : null);
|
||||
return variable;
|
||||
}
|
||||
|
||||
|
@ -162,10 +172,11 @@ public class AstIO {
|
|||
write(output, var);
|
||||
}
|
||||
try {
|
||||
output.writeUnsigned(method.getBody().size());
|
||||
for (int i = 0; i < method.getBody().size(); ++i) {
|
||||
method.getBody().get(i).getStatement().acceptVisitor(new NodeWriter(output));
|
||||
}
|
||||
output.writeUnsigned(method.getBody().size());
|
||||
NodeWriter writer = new NodeWriter(output);
|
||||
for (int i = 0; i < method.getBody().size(); ++i) {
|
||||
method.getBody().get(i).getStatement().acceptVisitor(writer);
|
||||
}
|
||||
} catch (IOExceptionWrapper e) {
|
||||
throw new IOException("Error writing method body", e.getCause());
|
||||
}
|
||||
|
@ -179,6 +190,7 @@ public class AstIO {
|
|||
node.getVariables().add(readVariable(input));
|
||||
}
|
||||
int partCount = input.readUnsigned();
|
||||
lastReadLocation = null;
|
||||
for (int i = 0; i < partCount; ++i) {
|
||||
AsyncMethodPart part = new AsyncMethodPart();
|
||||
part.setStatement(readStatement(input));
|
||||
|
@ -200,14 +212,21 @@ public class AstIO {
|
|||
private void writeLocation(VarDataOutput output, TextLocation location) throws IOException {
|
||||
if (location == null || location.getFileName() == null) {
|
||||
output.writeUnsigned(0);
|
||||
lastWrittenLocation = null;
|
||||
} else if (lastWrittenLocation != null && lastWrittenLocation.getFileName().equals(location.getFileName())) {
|
||||
output.writeUnsigned(1);
|
||||
output.writeSigned(location.getLine() - lastWrittenLocation.getLine());
|
||||
lastWrittenLocation = location;
|
||||
} else {
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()) + 1);
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()) + 2);
|
||||
output.writeUnsigned(location.getLine());
|
||||
lastWrittenLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
private class NodeWriter implements ExprVisitor, StatementVisitor {
|
||||
private final VarDataOutput output;
|
||||
private TextLocation lastLocation;
|
||||
|
||||
NodeWriter(VarDataOutput output) {
|
||||
super();
|
||||
|
@ -220,7 +239,22 @@ public class AstIO {
|
|||
}
|
||||
|
||||
private void writeLocation(TextLocation location) throws IOException {
|
||||
AstIO.this.writeLocation(output, location);
|
||||
if (Objects.equals(location, lastLocation)) {
|
||||
return;
|
||||
}
|
||||
if (location == null || location.getFileName() == null) {
|
||||
output.writeUnsigned(127);
|
||||
lastLocation = null;
|
||||
} else if (lastLocation != null && lastLocation.getFileName().equals(location.getFileName())) {
|
||||
output.writeUnsigned(126);
|
||||
output.writeSigned(location.getLine() - lastLocation.getLine());
|
||||
lastLocation = location;
|
||||
} else {
|
||||
output.writeUnsigned(125);
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()));
|
||||
output.writeUnsigned(location.getLine());
|
||||
lastLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeSequence(List<Statement> sequence) throws IOException {
|
||||
|
@ -233,8 +267,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(AssignmentStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(statement.getLeftValue() != null ? 0 : 1);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(statement.getLeftValue() != null ? 0 : 1);
|
||||
if (statement.getLeftValue() != null) {
|
||||
writeExpr(statement.getLeftValue());
|
||||
}
|
||||
|
@ -316,8 +350,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(BreakStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(statement.getTarget() != null && statement.getTarget().getId() != null ? 8 : 9);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(statement.getTarget() != null && statement.getTarget().getId() != null ? 8 : 9);
|
||||
if (statement.getTarget() != null && statement.getTarget().getId() != null) {
|
||||
output.write(statement.getTarget().getId());
|
||||
}
|
||||
|
@ -329,8 +363,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(ContinueStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(statement.getTarget() != null && statement.getTarget().getId() != null ? 10 : 11);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(statement.getTarget() != null && statement.getTarget().getId() != null ? 10 : 11);
|
||||
if (statement.getTarget() != null && statement.getTarget().getId() != null) {
|
||||
output.write(statement.getTarget().getId());
|
||||
}
|
||||
|
@ -342,8 +376,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(ReturnStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(statement.getResult() != null ? 12 : 13);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(statement.getResult() != null ? 12 : 13);
|
||||
if (statement.getResult() != null) {
|
||||
writeExpr(statement.getResult());
|
||||
}
|
||||
|
@ -355,8 +389,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(ThrowStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(14);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(14);
|
||||
writeExpr(statement.getException());
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
|
@ -366,8 +400,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(InitClassStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(15);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(15);
|
||||
output.writeUnsigned(symbolTable.lookup(statement.getClassName()));
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
|
@ -402,8 +436,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(MonitorEnterStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(18);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(18);
|
||||
writeExpr(statement.getObjectRef());
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
|
@ -413,8 +447,8 @@ public class AstIO {
|
|||
@Override
|
||||
public void visit(MonitorExitStatement statement) {
|
||||
try {
|
||||
output.writeUnsigned(19);
|
||||
writeLocation(statement.getLocation());
|
||||
output.writeUnsigned(19);
|
||||
writeExpr(statement.getObjectRef());
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
|
@ -636,18 +670,41 @@ public class AstIO {
|
|||
private TextLocation readLocation(VarDataInput input) throws IOException {
|
||||
int fileIndex = input.readUnsigned();
|
||||
if (fileIndex == 0) {
|
||||
return null;
|
||||
lastReadLocation = null;
|
||||
} else if (fileIndex == 1) {
|
||||
lastReadLocation = new TextLocation(lastReadLocation.getFileName(),
|
||||
lastReadLocation.getLine() + input.readSigned());
|
||||
} else {
|
||||
return new TextLocation(fileTable.at(fileIndex - 1), input.readUnsigned());
|
||||
lastReadLocation = new TextLocation(fileTable.at(fileIndex - 2), input.readUnsigned());
|
||||
return lastReadLocation;
|
||||
}
|
||||
return lastReadLocation;
|
||||
}
|
||||
|
||||
private int readNodeLocation(int type, VarDataInput input) throws IOException {
|
||||
switch (type) {
|
||||
case 127:
|
||||
lastReadLocation = null;
|
||||
break;
|
||||
case 126:
|
||||
lastReadLocation = new TextLocation(lastReadLocation.getFileName(),
|
||||
lastReadLocation.getLine() + input.readSigned());
|
||||
break;
|
||||
case 125:
|
||||
lastReadLocation = new TextLocation(fileTable.at(input.readUnsigned()), input.readUnsigned());
|
||||
break;
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
return input.readUnsigned();
|
||||
}
|
||||
|
||||
private Statement readStatement(VarDataInput input) throws IOException {
|
||||
int type = input.readUnsigned();
|
||||
int type = readNodeLocation(input.readUnsigned(), input);
|
||||
switch (type) {
|
||||
case 0: {
|
||||
AssignmentStatement stmt = new AssignmentStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setLeftValue(readExpr(input));
|
||||
stmt.setRightValue(readExpr(input));
|
||||
stmt.setAsync(input.readUnsigned() != 0);
|
||||
|
@ -655,7 +712,7 @@ public class AstIO {
|
|||
}
|
||||
case 1: {
|
||||
AssignmentStatement stmt = new AssignmentStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setRightValue(readExpr(input));
|
||||
stmt.setAsync(input.readUnsigned() != 0);
|
||||
return stmt;
|
||||
|
@ -721,46 +778,46 @@ public class AstIO {
|
|||
}
|
||||
case 8: {
|
||||
BreakStatement stmt = new BreakStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setTarget(statementMap.get(input.read()));
|
||||
return stmt;
|
||||
}
|
||||
case 9: {
|
||||
BreakStatement stmt = new BreakStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
return stmt;
|
||||
}
|
||||
case 10: {
|
||||
ContinueStatement stmt = new ContinueStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setTarget(statementMap.get(input.read()));
|
||||
return stmt;
|
||||
}
|
||||
case 11: {
|
||||
ContinueStatement stmt = new ContinueStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
return stmt;
|
||||
}
|
||||
case 12: {
|
||||
ReturnStatement stmt = new ReturnStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setResult(readExpr(input));
|
||||
return stmt;
|
||||
}
|
||||
case 13: {
|
||||
ReturnStatement stmt = new ReturnStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
return stmt;
|
||||
}
|
||||
case 14: {
|
||||
ThrowStatement stmt = new ThrowStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setException(readExpr(input));
|
||||
return stmt;
|
||||
}
|
||||
case 15: {
|
||||
InitClassStatement stmt = new InitClassStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setClassName(symbolTable.at(input.readUnsigned()));
|
||||
return stmt;
|
||||
}
|
||||
|
@ -785,13 +842,13 @@ public class AstIO {
|
|||
}
|
||||
case 18: {
|
||||
MonitorEnterStatement stmt = new MonitorEnterStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setObjectRef(readExpr(input));
|
||||
return stmt;
|
||||
}
|
||||
case 19: {
|
||||
MonitorExitStatement stmt = new MonitorExitStatement();
|
||||
stmt.setLocation(readLocation(input));
|
||||
stmt.setLocation(lastReadLocation);
|
||||
stmt.setObjectRef(readExpr(input));
|
||||
return stmt;
|
||||
}
|
||||
|
@ -808,17 +865,11 @@ public class AstIO {
|
|||
}
|
||||
|
||||
private Expr readExpr(VarDataInput input) throws IOException {
|
||||
TextLocation location = readLocation(input);
|
||||
Expr expr = readExprWithoutLocation(input);
|
||||
expr.setLocation(location);
|
||||
return expr;
|
||||
}
|
||||
|
||||
private Expr readExprWithoutLocation(VarDataInput input) throws IOException {
|
||||
int type = input.readUnsigned();
|
||||
int type = readNodeLocation(input.readUnsigned(), input);
|
||||
switch (type) {
|
||||
case 0: {
|
||||
BinaryExpr expr = new BinaryExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setOperation(binaryOperations[input.readUnsigned()]);
|
||||
int valueType = input.readUnsigned();
|
||||
expr.setType(valueType > 0 ? OperationType.values()[valueType - 1] : null);
|
||||
|
@ -828,6 +879,7 @@ public class AstIO {
|
|||
}
|
||||
case 1: {
|
||||
UnaryExpr expr = new UnaryExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setOperation(unaryOperations[input.readUnsigned()]);
|
||||
int valueType = input.readUnsigned();
|
||||
expr.setType(valueType > 0 ? OperationType.values()[valueType - 1] : null);
|
||||
|
@ -836,16 +888,20 @@ public class AstIO {
|
|||
}
|
||||
case 2: {
|
||||
ConditionalExpr expr = new ConditionalExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setCondition(readExpr(input));
|
||||
expr.setConsequent(readExpr(input));
|
||||
expr.setAlternative(readExpr(input));
|
||||
return expr;
|
||||
}
|
||||
case 3: {
|
||||
return new ConstantExpr();
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
return expr;
|
||||
}
|
||||
case 4: {
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setValue(input.readSigned());
|
||||
return expr;
|
||||
}
|
||||
|
@ -856,31 +912,37 @@ public class AstIO {
|
|||
}
|
||||
case 6: {
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setValue(input.readFloat());
|
||||
return expr;
|
||||
}
|
||||
case 7: {
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setValue(input.readDouble());
|
||||
return expr;
|
||||
}
|
||||
case 8: {
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setValue(input.read());
|
||||
return expr;
|
||||
}
|
||||
case 9: {
|
||||
ConstantExpr expr = new ConstantExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setValue(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||
return expr;
|
||||
}
|
||||
case 10: {
|
||||
VariableExpr expr = new VariableExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setIndex(input.readUnsigned());
|
||||
return expr;
|
||||
}
|
||||
case 11: {
|
||||
SubscriptExpr expr = new SubscriptExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setArray(readExpr(input));
|
||||
expr.setIndex(readExpr(input));
|
||||
expr.setType(ArrayType.values()[input.readUnsigned()]);
|
||||
|
@ -888,6 +950,7 @@ public class AstIO {
|
|||
}
|
||||
case 12: {
|
||||
UnwrapArrayExpr expr = new UnwrapArrayExpr(ArrayType.values()[input.readUnsigned()]);
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setArray(readExpr(input));
|
||||
return expr;
|
||||
}
|
||||
|
@ -901,6 +964,7 @@ public class AstIO {
|
|||
return parseInvocationExpr(InvocationType.DYNAMIC, input);
|
||||
case 17: {
|
||||
QualificationExpr expr = new QualificationExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
String className = symbolTable.at(input.readUnsigned());
|
||||
String fieldName = symbolTable.at(input.readUnsigned());
|
||||
expr.setField(new FieldReference(className, fieldName));
|
||||
|
@ -908,6 +972,7 @@ public class AstIO {
|
|||
}
|
||||
case 18: {
|
||||
QualificationExpr expr = new QualificationExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setQualified(readExpr(input));
|
||||
String className = symbolTable.at(input.readUnsigned());
|
||||
String fieldName = symbolTable.at(input.readUnsigned());
|
||||
|
@ -916,17 +981,20 @@ public class AstIO {
|
|||
}
|
||||
case 19: {
|
||||
NewExpr expr = new NewExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setConstructedClass(symbolTable.at(input.readUnsigned()));
|
||||
return expr;
|
||||
}
|
||||
case 20: {
|
||||
NewArrayExpr expr = new NewArrayExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setLength(readExpr(input));
|
||||
expr.setType(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||
return expr;
|
||||
}
|
||||
case 21: {
|
||||
NewMultiArrayExpr expr = new NewMultiArrayExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
int dimensionCount = input.readUnsigned();
|
||||
for (int i = 0; i < dimensionCount; ++i) {
|
||||
expr.getDimensions().add(readExpr(input));
|
||||
|
@ -936,18 +1004,21 @@ public class AstIO {
|
|||
}
|
||||
case 22: {
|
||||
InstanceOfExpr expr = new InstanceOfExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setExpr(readExpr(input));
|
||||
expr.setType(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||
return expr;
|
||||
}
|
||||
case 23: {
|
||||
CastExpr expr = new CastExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setTarget(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||
expr.setValue(readExpr(input));
|
||||
return expr;
|
||||
}
|
||||
case 24: {
|
||||
PrimitiveCastExpr expr = new PrimitiveCastExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setSource(OperationType.values()[input.readUnsigned()]);
|
||||
expr.setTarget(OperationType.values()[input.readUnsigned()]);
|
||||
expr.setValue(readExpr(input));
|
||||
|
@ -960,6 +1031,7 @@ public class AstIO {
|
|||
|
||||
private InvocationExpr parseInvocationExpr(InvocationType invocationType, VarDataInput input) throws IOException {
|
||||
InvocationExpr expr = new InvocationExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setType(invocationType);
|
||||
String className = symbolTable.at(input.readUnsigned());
|
||||
String signature = symbolTable.at(input.readUnsigned());
|
||||
|
|
|
@ -64,12 +64,13 @@ public class DiskCachedClassHolderSource implements ClassHolderSource, CacheStat
|
|||
private ProgramIO programIO;
|
||||
|
||||
public DiskCachedClassHolderSource(File directory, ReferenceCache referenceCache, SymbolTable symbolTable,
|
||||
SymbolTable fileTable, ClassHolderSource innerSource, ClassDateProvider classDateProvider) {
|
||||
SymbolTable fileTable, SymbolTable variableTable, ClassHolderSource innerSource,
|
||||
ClassDateProvider classDateProvider) {
|
||||
this.directory = directory;
|
||||
this.symbolTable = symbolTable;
|
||||
this.innerSource = innerSource;
|
||||
this.classDateProvider = classDateProvider;
|
||||
programIO = new ProgramIO(referenceCache, symbolTable, fileTable);
|
||||
programIO = new ProgramIO(referenceCache, symbolTable, fileTable, variableTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,9 +42,9 @@ public class DiskMethodNodeCache implements MethodNodeCache {
|
|||
private final Set<MethodReference> newAsyncMethods = new HashSet<>();
|
||||
|
||||
public DiskMethodNodeCache(File directory, ReferenceCache referenceCache, SymbolTable symbolTable,
|
||||
SymbolTable fileTable) {
|
||||
SymbolTable fileTable, SymbolTable variableTable) {
|
||||
this.directory = directory;
|
||||
astIO = new AstIO(referenceCache, symbolTable, fileTable);
|
||||
astIO = new AstIO(referenceCache, symbolTable, fileTable, variableTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,13 +27,11 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ProgramCache;
|
||||
|
@ -46,9 +44,9 @@ public class DiskProgramCache implements ProgramCache {
|
|||
private Set<MethodReference> newMethods = new HashSet<>();
|
||||
|
||||
public DiskProgramCache(File directory, ReferenceCache referenceCache, SymbolTable symbolTable,
|
||||
SymbolTable fileTable) {
|
||||
SymbolTable fileTable, SymbolTable variableTable) {
|
||||
this.directory = directory;
|
||||
programIO = new ProgramIO(referenceCache, symbolTable, fileTable);
|
||||
programIO = new ProgramIO(referenceCache, symbolTable, fileTable, variableTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -90,8 +88,7 @@ public class DiskProgramCache implements ProgramCache {
|
|||
newMethods.add(method);
|
||||
}
|
||||
|
||||
public void flush(ClassReaderSource classSource) throws IOException {
|
||||
Date currentTime = new Date();
|
||||
public void flush() throws IOException {
|
||||
for (MethodReference method : newMethods) {
|
||||
Item item = cache.get(method);
|
||||
File file = getMethodFile(method);
|
||||
|
|
|
@ -36,8 +36,8 @@ public class InMemoryMethodNodeCache implements MethodNodeCache {
|
|||
private AstIO io;
|
||||
|
||||
public InMemoryMethodNodeCache(ReferenceCache referenceCache, InMemorySymbolTable symbolTable,
|
||||
InMemorySymbolTable fileSymbolTable) {
|
||||
io = new AstIO(referenceCache, symbolTable, fileSymbolTable);
|
||||
InMemorySymbolTable fileSymbolTable, InMemorySymbolTable variableSymbolTable) {
|
||||
io = new AstIO(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,8 +33,8 @@ public class InMemoryProgramCache implements ProgramCache {
|
|||
private ProgramIO io;
|
||||
|
||||
public InMemoryProgramCache(ReferenceCache referenceCache, InMemorySymbolTable symbolTable,
|
||||
InMemorySymbolTable fileSymbolTable) {
|
||||
io = new ProgramIO(referenceCache, symbolTable, fileSymbolTable);
|
||||
InMemorySymbolTable fileSymbolTable, InMemorySymbolTable variableSymbolTable) {
|
||||
io = new ProgramIO(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,6 +85,7 @@ import org.teavm.model.instructions.UnwrapArrayInstruction;
|
|||
public class ProgramIO {
|
||||
private SymbolTable symbolTable;
|
||||
private SymbolTable fileTable;
|
||||
private SymbolTable variableTable;
|
||||
private ReferenceCache referenceCache;
|
||||
private static BinaryOperation[] binaryOperations = BinaryOperation.values();
|
||||
private static NumericOperandType[] numericOperandTypes = NumericOperandType.values();
|
||||
|
@ -94,10 +95,12 @@ public class ProgramIO {
|
|||
private static BinaryBranchingCondition[] binaryBranchingConditions = BinaryBranchingCondition.values();
|
||||
private static ArrayElementType[] arrayElementTypes = ArrayElementType.values();
|
||||
|
||||
public ProgramIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable) {
|
||||
public ProgramIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable,
|
||||
SymbolTable variableTable) {
|
||||
this.referenceCache = referenceCache;
|
||||
this.symbolTable = symbolTable;
|
||||
this.fileTable = fileTable;
|
||||
this.variableTable = variableTable;
|
||||
}
|
||||
|
||||
public void write(Program program, OutputStream output) throws IOException {
|
||||
|
@ -107,7 +110,7 @@ public class ProgramIO {
|
|||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
Variable var = program.variableAt(i);
|
||||
data.writeUnsigned(var.getRegister());
|
||||
data.write(var.getDebugName());
|
||||
data.writeUnsigned(var.getDebugName() != null ? variableTable.lookup(var.getDebugName()) + 1 : 0);
|
||||
}
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock basicBlock = program.basicBlockAt(i);
|
||||
|
@ -133,13 +136,20 @@ public class ProgramIO {
|
|||
for (Instruction insn : basicBlock) {
|
||||
try {
|
||||
if (!Objects.equals(location, insn.getLocation())) {
|
||||
location = insn.getLocation();
|
||||
if (location == null || location.getFileName() == null || location.getLine() < 0) {
|
||||
TextLocation newLocation = insn.getLocation();
|
||||
if (newLocation == null || newLocation.getFileName() == null || newLocation.getLine() < 0) {
|
||||
data.writeUnsigned(1);
|
||||
location = null;
|
||||
} else {
|
||||
data.writeUnsigned(2);
|
||||
data.writeUnsigned(fileTable.lookup(location.getFileName()));
|
||||
data.writeUnsigned(location.getLine());
|
||||
if (location != null && location.getFileName().equals(newLocation.getFileName())) {
|
||||
data.writeUnsigned(127);
|
||||
data.writeSigned(newLocation.getLine() - location.getLine());
|
||||
} else {
|
||||
data.writeUnsigned(2);
|
||||
data.writeUnsigned(fileTable.lookup(newLocation.getFileName()));
|
||||
data.writeUnsigned(newLocation.getLine());
|
||||
}
|
||||
location = newLocation;
|
||||
}
|
||||
}
|
||||
insn.acceptVisitor(insnWriter);
|
||||
|
@ -159,7 +169,8 @@ public class ProgramIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
Variable var = program.createVariable();
|
||||
var.setRegister(data.readUnsigned());
|
||||
var.setDebugName(referenceCache.getCached(data.read()));
|
||||
int nameIndex = data.readUnsigned();
|
||||
var.setDebugName(nameIndex != 0 ? referenceCache.getCached(variableTable.at(nameIndex - 1)) : null);
|
||||
}
|
||||
for (int i = 0; i < basicBlockCount; ++i) {
|
||||
program.createBasicBlock();
|
||||
|
@ -212,6 +223,11 @@ public class ProgramIO {
|
|||
location = new TextLocation(file, line);
|
||||
break;
|
||||
}
|
||||
case 127: {
|
||||
int line = location.getLine() + data.readSigned();
|
||||
location = new TextLocation(location.getFileName(), line);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Instruction insn = readInstruction(insnType, program, data);
|
||||
insn.setLocation(location);
|
||||
|
|
|
@ -69,7 +69,15 @@ public class VarDataInput {
|
|||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
int exponent = readSigned() + 127;
|
||||
int exponent = readUnsigned();
|
||||
if (exponent == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
exponent--;
|
||||
exponent = (exponent & 1) == 0 ? exponent >>> 1 : -(exponent >>> 1);
|
||||
exponent += 127;
|
||||
|
||||
int mantissa = Integer.reverse(readUnsigned()) >>> 8;
|
||||
boolean sign = (mantissa & (1 << 23)) != 0;
|
||||
|
||||
|
@ -83,7 +91,15 @@ public class VarDataInput {
|
|||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
int exponent = readSigned() + 1023;
|
||||
int exponent = readUnsigned();
|
||||
if (exponent == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
exponent--;
|
||||
exponent = (exponent & 1) == 0 ? exponent >>> 1 : -(exponent >>> 1);
|
||||
exponent += 1023;
|
||||
|
||||
long mantissa = Long.reverse(readUnsignedLong()) >>> 11;
|
||||
boolean sign = (mantissa & (1L << 52)) != 0;
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ public class VarDataOutput implements Closeable {
|
|||
}
|
||||
|
||||
public void writeFloat(float value) throws IOException {
|
||||
if (value == 0) {
|
||||
writeUnsigned(0);
|
||||
return;
|
||||
}
|
||||
int bits = Float.floatToRawIntBits(value);
|
||||
boolean sign = (bits & (1 << 31)) != 0;
|
||||
int exponent = (bits >> 23) & ((1 << 8) - 1);
|
||||
|
@ -60,11 +64,16 @@ public class VarDataOutput implements Closeable {
|
|||
if (sign) {
|
||||
mantissa |= 1 << 23;
|
||||
}
|
||||
writeSigned(exponent - 127);
|
||||
exponent -= 127;
|
||||
writeUnsigned(1 + (exponent > 0 ? exponent << 1 : 1 | (-exponent << 1)));
|
||||
writeUnsigned(Integer.reverse(mantissa << 8));
|
||||
}
|
||||
|
||||
public void writeDouble(double value) throws IOException {
|
||||
if (value == 0) {
|
||||
writeUnsigned(0);
|
||||
return;
|
||||
}
|
||||
long bits = Double.doubleToRawLongBits(value);
|
||||
boolean sign = (bits & (1L << 63)) != 0;
|
||||
int exponent = (int) (bits >> 52) & ((1 << 11) - 1);
|
||||
|
@ -72,7 +81,8 @@ public class VarDataOutput implements Closeable {
|
|||
if (sign) {
|
||||
mantissa |= 1L << 52;
|
||||
}
|
||||
writeSigned(exponent - 1023);
|
||||
exponent -= 1023;
|
||||
writeUnsigned(1 + (exponent > 0 ? exponent << 1 : 1 | (-exponent << 1)));
|
||||
writeUnsigned(Long.reverse(mantissa << 11));
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ public class DebugInformation {
|
|||
MethodTree methodTree;
|
||||
ReferenceCache referenceCache;
|
||||
|
||||
public DebugInformation() {
|
||||
this(new ReferenceCache());
|
||||
}
|
||||
|
||||
public DebugInformation(ReferenceCache referenceCache) {
|
||||
this.referenceCache = referenceCache;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -37,7 +36,6 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import org.teavm.cache.IncrementalDependencyProvider;
|
||||
import org.teavm.cache.IncrementalDependencyRegistration;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.callgraph.CallGraphNode;
|
||||
import org.teavm.callgraph.DefaultCallGraph;
|
||||
import org.teavm.common.CachedMapper;
|
||||
import org.teavm.common.Mapper;
|
||||
|
@ -429,8 +427,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
|
||||
private ClassDependency createClassDependency(String className) {
|
||||
ClassReader cls = classSource.get(className);
|
||||
ClassDependency dependency = new ClassDependency(this, className, cls);
|
||||
return dependency;
|
||||
return new ClassDependency(this, className, cls);
|
||||
}
|
||||
|
||||
public MethodDependency linkMethod(String className, MethodDescriptor descriptor) {
|
||||
|
@ -527,8 +524,6 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
return classCache.getCachedPreimages();
|
||||
}
|
||||
|
||||
private Set<FieldReference> fieldsAddedByRoot = new HashSet<>();
|
||||
|
||||
public FieldDependency linkField(FieldReference fieldRef) {
|
||||
FieldDependency dep = fieldCache.map(fieldRef);
|
||||
if (!dep.activated) {
|
||||
|
@ -746,9 +741,25 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
}
|
||||
}
|
||||
|
||||
for (Map<?, MethodDependency> map : methodCache.values()) {
|
||||
for (MethodDependency methodDependency : map.values()) {
|
||||
methodDependency.locationListeners = null;
|
||||
methodDependency.locations = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (FieldReference fieldRef : fieldCache.getCachedPreimages()) {
|
||||
FieldDependency field = fieldCache.getKnown(fieldRef);
|
||||
if (field != null) {
|
||||
field.locationListeners = null;
|
||||
field.locations = null;
|
||||
}
|
||||
}
|
||||
|
||||
allNodes.clear();
|
||||
classSource.cleanup();
|
||||
agent.cleanup();
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
public void cleanupTypes() {
|
||||
|
@ -857,10 +868,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
return;
|
||||
}
|
||||
|
||||
CallGraphNode caller = callGraph.getNode(methodDep.getReference());
|
||||
|
||||
ProgramEmitter pe = ProgramEmitter.create(program, classHierarchy);
|
||||
boolean hasIndy = false;
|
||||
BasicBlockSplitter splitter = new BasicBlockSplitter(program);
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
|
@ -885,7 +893,6 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
continue;
|
||||
}
|
||||
|
||||
hasIndy = true;
|
||||
BasicBlock splitBlock = splitter.split(block, insn);
|
||||
|
||||
pe.enter(block);
|
||||
|
@ -910,7 +917,6 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
|||
pe.addInstruction(assign);
|
||||
}
|
||||
pe.jump(splitBlock);
|
||||
block = splitBlock;
|
||||
}
|
||||
}
|
||||
splitter.fixProgram();
|
||||
|
|
|
@ -189,4 +189,11 @@ public class FastDependencyAnalyzer extends DependencyAnalyzer {
|
|||
boolean domainOptimizationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
virtualCallConsumers.clear();
|
||||
subtypeNodes.clear();
|
||||
super.cleanup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ public class FieldDependency implements FieldDependencyInfo {
|
|||
DependencyNode value;
|
||||
private FieldReader field;
|
||||
private FieldReference reference;
|
||||
private List<LocationListener> locationListeners;
|
||||
private Set<CallLocation> locations;
|
||||
List<LocationListener> locationListeners;
|
||||
Set<CallLocation> locations;
|
||||
boolean activated;
|
||||
|
||||
FieldDependency(DependencyNode value, FieldReader field, FieldReference reference) {
|
||||
|
|
|
@ -38,8 +38,8 @@ public class MethodDependency implements MethodDependencyInfo {
|
|||
boolean external;
|
||||
DependencyPlugin dependencyPlugin;
|
||||
boolean dependencyPluginAttached;
|
||||
private List<LocationListener> locationListeners;
|
||||
private Set<CallLocation> locations;
|
||||
List<LocationListener> locationListeners;
|
||||
Set<CallLocation> locations;
|
||||
boolean activated;
|
||||
|
||||
MethodDependency(DependencyAnalyzer dependencyAnalyzer, DependencyNode[] variableNodes, int parameterCount,
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.Arrays;
|
|||
public class MethodDescriptor {
|
||||
private String name;
|
||||
private ValueType[] signature;
|
||||
private volatile String reprCache;
|
||||
private int hash;
|
||||
|
||||
public MethodDescriptor(String name, ValueType... signature) {
|
||||
if (signature.length < 1) {
|
||||
|
@ -70,10 +70,7 @@ public class MethodDescriptor {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = name + signatureToString();
|
||||
}
|
||||
return reprCache;
|
||||
return name + signatureToString();
|
||||
}
|
||||
|
||||
public String signatureToString() {
|
||||
|
@ -140,17 +137,43 @@ public class MethodDescriptor {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
if (hash == 0) {
|
||||
hash = name.hashCode();
|
||||
for (ValueType param : signature) {
|
||||
hash = 31 * hash + param.hashCode();
|
||||
}
|
||||
if (hash == 0) {
|
||||
hash++;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof MethodDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
return toString().equals(obj.toString());
|
||||
}
|
||||
if (!(obj instanceof MethodDescriptor)) {
|
||||
return false;
|
||||
}
|
||||
MethodDescriptor that = (MethodDescriptor) obj;
|
||||
|
||||
if (signature.length != that.signature.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name.equals(that.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < signature.length; ++i) {
|
||||
if (!signature[i].equals(that.signature[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,16 +35,12 @@ import java.util.stream.Stream;
|
|||
*/
|
||||
public class MethodReference implements Serializable {
|
||||
private String className;
|
||||
private String name;
|
||||
private ValueType[] signature;
|
||||
private transient MethodDescriptor descriptor;
|
||||
private transient String reprCache;
|
||||
private int hash;
|
||||
|
||||
public MethodReference(String className, MethodDescriptor descriptor) {
|
||||
this.className = className;
|
||||
this.descriptor = descriptor;
|
||||
this.name = descriptor.getName();
|
||||
this.signature = descriptor.getSignature();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,9 +60,7 @@ public class MethodReference implements Serializable {
|
|||
* a type of a returning value, and all the remaining elements are types of arguments.
|
||||
*/
|
||||
public MethodReference(String className, String name, ValueType... signature) {
|
||||
this.className = className;
|
||||
this.name = name;
|
||||
this.signature = Arrays.copyOf(signature, signature.length);
|
||||
this(className, new MethodDescriptor(name, signature));
|
||||
}
|
||||
|
||||
public MethodReference(Class<?> cls, String name, Class<?>... signature) {
|
||||
|
@ -86,42 +80,42 @@ public class MethodReference implements Serializable {
|
|||
}
|
||||
|
||||
public MethodDescriptor getDescriptor() {
|
||||
if (descriptor == null) {
|
||||
descriptor = new MethodDescriptor(name, signature);
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public int parameterCount() {
|
||||
return signature.length - 1;
|
||||
return descriptor.parameterCount();
|
||||
}
|
||||
|
||||
public ValueType parameterType(int index) {
|
||||
if (index >= signature.length + 1) {
|
||||
throw new IndexOutOfBoundsException("Index " + index + " is greater than size " + (signature.length - 1));
|
||||
}
|
||||
return signature[index];
|
||||
return descriptor.parameterType(index);
|
||||
}
|
||||
|
||||
public ValueType[] getParameterTypes() {
|
||||
return Arrays.copyOf(signature, signature.length - 1);
|
||||
return descriptor.getParameterTypes();
|
||||
}
|
||||
|
||||
public ValueType[] getSignature() {
|
||||
return Arrays.copyOf(signature, signature.length);
|
||||
return descriptor.getSignature();
|
||||
}
|
||||
|
||||
public ValueType getReturnType() {
|
||||
return signature[signature.length - 1];
|
||||
return descriptor.getResultType();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
return descriptor.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
if (hash == 0) {
|
||||
hash = (className.hashCode() * 31 + descriptor.hashCode()) * 17;
|
||||
if (hash == 0) {
|
||||
hash++;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,17 +126,15 @@ public class MethodReference implements Serializable {
|
|||
if (!(obj instanceof MethodReference)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodReference other = (MethodReference) obj;
|
||||
return toString().equals(other.toString());
|
||||
return className.equals(other.className) && descriptor.equals(other.descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonValue
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = className + "." + getDescriptor().toString();
|
||||
}
|
||||
return reprCache;
|
||||
return className + "." + getDescriptor().toString();
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class ValueType implements Serializable {
|
||||
volatile String reprCache;
|
||||
private static final Map<Class<?>, ValueType> primitiveMap = new HashMap<>();
|
||||
|
||||
private ValueType() {
|
||||
|
@ -28,6 +27,7 @@ public abstract class ValueType implements Serializable {
|
|||
|
||||
public static class Object extends ValueType {
|
||||
private String className;
|
||||
private int hash;
|
||||
|
||||
public Object(String className) {
|
||||
this.className = className;
|
||||
|
@ -39,23 +39,45 @@ public abstract class ValueType implements Serializable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = "L" + className.replace('.', '/') + ";";
|
||||
}
|
||||
return reprCache;
|
||||
return "L" + className.replace('.', '/') + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject(String className) {
|
||||
return this.className.equals(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(java.lang.Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof Object)) {
|
||||
return false;
|
||||
}
|
||||
Object that = (Object) obj;
|
||||
return that.className.equals(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = 85396296 ^ (className.hashCode() * 167);
|
||||
if (hash == 0) {
|
||||
++hash;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Primitive extends ValueType {
|
||||
private PrimitiveType kind;
|
||||
private int hash;
|
||||
|
||||
Primitive(PrimitiveType kind) {
|
||||
private Primitive(PrimitiveType kind) {
|
||||
this.kind = kind;
|
||||
hash = 17988782 ^ (kind.ordinal() * 31);
|
||||
}
|
||||
|
||||
public PrimitiveType getKind() {
|
||||
|
@ -64,13 +86,6 @@ public abstract class ValueType implements Serializable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = createString();
|
||||
}
|
||||
return reprCache;
|
||||
}
|
||||
|
||||
private String createString() {
|
||||
switch (kind) {
|
||||
case BOOLEAN:
|
||||
return "Z";
|
||||
|
@ -97,10 +112,21 @@ public abstract class ValueType implements Serializable {
|
|||
public boolean isObject(String cls) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(java.lang.Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Array extends ValueType {
|
||||
private ValueType itemType;
|
||||
private int hash;
|
||||
|
||||
public Array(ValueType itemType) {
|
||||
this.itemType = itemType;
|
||||
|
@ -112,19 +138,43 @@ public abstract class ValueType implements Serializable {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = "[" + itemType.toString();
|
||||
}
|
||||
return reprCache;
|
||||
return "[" + itemType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject(String cls) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(java.lang.Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof Array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Array that = (Array) obj;
|
||||
return itemType.equals(that.itemType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (hash == 0) {
|
||||
hash = 27039876 ^ (itemType.hashCode() * 193);
|
||||
if (hash == 0) {
|
||||
++hash;
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Void extends ValueType {
|
||||
private Void() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "V";
|
||||
|
@ -134,12 +184,15 @@ public abstract class ValueType implements Serializable {
|
|||
public boolean isObject(String cls) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Null extends ValueType {
|
||||
@Override
|
||||
public boolean isObject(String cls) {
|
||||
return false;
|
||||
public boolean equals(java.lang.Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 53604390;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,9 +214,6 @@ public abstract class ValueType implements Serializable {
|
|||
|
||||
public static final Primitive CHARACTER = new Primitive(PrimitiveType.CHARACTER);
|
||||
|
||||
public static final Null NULL = new Null();
|
||||
|
||||
|
||||
static {
|
||||
primitiveMap.put(boolean.class, BOOLEAN);
|
||||
primitiveMap.put(char.class, CHARACTER);
|
||||
|
@ -227,7 +277,7 @@ public abstract class ValueType implements Serializable {
|
|||
types.add(type);
|
||||
index = nextIndex;
|
||||
}
|
||||
return types.toArray(new ValueType[types.size()]);
|
||||
return types.toArray(new ValueType[0]);
|
||||
}
|
||||
|
||||
private static int cut(String text, int index) {
|
||||
|
@ -344,20 +394,4 @@ public abstract class ValueType implements Serializable {
|
|||
return ValueType.object(cls.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(java.lang.Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof ValueType)) {
|
||||
return false;
|
||||
}
|
||||
return toString().equals(obj.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,7 +158,8 @@ public class ProgramIOTest {
|
|||
private Program inputOutput(Program program) {
|
||||
InMemorySymbolTable symbolTable = new InMemorySymbolTable();
|
||||
InMemorySymbolTable fileTable = new InMemorySymbolTable();
|
||||
ProgramIO programIO = new ProgramIO(new ReferenceCache(), symbolTable, fileTable);
|
||||
InMemorySymbolTable variableTable = new InMemorySymbolTable();
|
||||
ProgramIO programIO = new ProgramIO(new ReferenceCache(), symbolTable, fileTable, variableTable);
|
||||
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
programIO.write(program, output);
|
||||
try (ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray())) {
|
||||
|
|
|
@ -239,7 +239,8 @@ public class IncrementalTest {
|
|||
boolean capturing;
|
||||
|
||||
CapturingMethodNodeCache() {
|
||||
super(new ReferenceCache(), new InMemorySymbolTable(), new InMemorySymbolTable());
|
||||
super(new ReferenceCache(), new InMemorySymbolTable(), new InMemorySymbolTable(),
|
||||
new InMemorySymbolTable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -264,7 +265,8 @@ public class IncrementalTest {
|
|||
boolean capturing;
|
||||
|
||||
CapturingProgramCache() {
|
||||
super(new ReferenceCache(), new InMemorySymbolTable(), new InMemorySymbolTable());
|
||||
super(new ReferenceCache(), new InMemorySymbolTable(), new InMemorySymbolTable(),
|
||||
new InMemorySymbolTable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -88,6 +88,7 @@ public class TeaVMTool {
|
|||
private DiskMethodNodeCache astCache;
|
||||
private FileSymbolTable symbolTable;
|
||||
private FileSymbolTable fileTable;
|
||||
private FileSymbolTable variableTable;
|
||||
private boolean cancelled;
|
||||
private TeaVMProgressListener progressListener;
|
||||
private TeaVM vm;
|
||||
|
@ -327,27 +328,31 @@ public class TeaVMTool {
|
|||
try {
|
||||
cancelled = false;
|
||||
log.info("Running TeaVM");
|
||||
referenceCache = new ReferenceCache();
|
||||
TeaVMBuilder vmBuilder = new TeaVMBuilder(prepareTarget());
|
||||
CacheStatus cacheStatus;
|
||||
referenceCache = new ReferenceCache();
|
||||
vmBuilder.setReferenceCache(referenceCache);
|
||||
if (incremental) {
|
||||
cacheDirectory.mkdirs();
|
||||
symbolTable = new FileSymbolTable(new File(cacheDirectory, "symbols"));
|
||||
fileTable = new FileSymbolTable(new File(cacheDirectory, "files"));
|
||||
variableTable = new FileSymbolTable(new File(cacheDirectory, "variables"));
|
||||
ClasspathClassHolderSource innerClassSource = new ClasspathClassHolderSource(classLoader,
|
||||
referenceCache);
|
||||
ClassHolderSource classSource = new PreOptimizingClassHolderSource(innerClassSource);
|
||||
cachedClassSource = new DiskCachedClassHolderSource(cacheDirectory, referenceCache, symbolTable,
|
||||
fileTable, classSource, innerClassSource);
|
||||
programCache = new DiskProgramCache(cacheDirectory, referenceCache, symbolTable, fileTable);
|
||||
fileTable, variableTable, classSource, innerClassSource);
|
||||
programCache = new DiskProgramCache(cacheDirectory, referenceCache, symbolTable, fileTable,
|
||||
variableTable);
|
||||
if (incremental && targetType == TeaVMTargetType.JAVASCRIPT) {
|
||||
astCache = new DiskMethodNodeCache(cacheDirectory, referenceCache, symbolTable, fileTable);
|
||||
astCache = new DiskMethodNodeCache(cacheDirectory, referenceCache, symbolTable, fileTable,
|
||||
variableTable);
|
||||
javaScriptTarget.setAstCache(astCache);
|
||||
}
|
||||
try {
|
||||
symbolTable.update();
|
||||
fileTable.update();
|
||||
variableTable.update();
|
||||
} catch (IOException e) {
|
||||
log.info("Cache is missing");
|
||||
}
|
||||
|
@ -420,13 +425,14 @@ public class TeaVMTool {
|
|||
}
|
||||
|
||||
if (incremental) {
|
||||
programCache.flush(vm.getDependencyClassSource());
|
||||
programCache.flush();
|
||||
if (astCache != null) {
|
||||
astCache.flush();
|
||||
}
|
||||
cachedClassSource.flush();
|
||||
symbolTable.flush();
|
||||
fileTable.flush();
|
||||
variableTable.flush();
|
||||
log.info("Cache updated");
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,7 @@ public class CodeServlet extends HttpServlet {
|
|||
private WebSocketClient wsClient = new WebSocketClient();
|
||||
private InMemorySymbolTable symbolTable = new InMemorySymbolTable();
|
||||
private InMemorySymbolTable fileSymbolTable = new InMemorySymbolTable();
|
||||
private InMemorySymbolTable variableSymbolTable = new InMemorySymbolTable();
|
||||
private ReferenceCache referenceCache = new ReferenceCache();
|
||||
|
||||
public CodeServlet(String mainClass, String[] classPath) {
|
||||
|
@ -709,8 +710,8 @@ public class CodeServlet extends HttpServlet {
|
|||
watcher = new FileSystemWatcher(classPath);
|
||||
|
||||
classSource = new MemoryCachedClassReaderSource();
|
||||
astCache = new InMemoryMethodNodeCache(referenceCache, symbolTable, fileSymbolTable);
|
||||
programCache = new InMemoryProgramCache(referenceCache, symbolTable, fileSymbolTable);
|
||||
astCache = new InMemoryMethodNodeCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||
programCache = new InMemoryProgramCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||
}
|
||||
|
||||
private void shutdownBuilder() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user