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