mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Add incomplete implementation of AST disk cache
This commit is contained in:
parent
a7d3f26447
commit
0d1a59c03b
|
@ -32,6 +32,11 @@ public class AstIO {
|
||||||
private SymbolTable symbolTable;
|
private SymbolTable symbolTable;
|
||||||
private SymbolTable fileTable;
|
private SymbolTable fileTable;
|
||||||
|
|
||||||
|
public AstIO(SymbolTable symbolTable, SymbolTable fileTable) {
|
||||||
|
this.symbolTable = symbolTable;
|
||||||
|
this.fileTable = fileTable;
|
||||||
|
}
|
||||||
|
|
||||||
public void write(DataOutput output, RegularMethodNode method) throws IOException {
|
public void write(DataOutput output, RegularMethodNode method) throws IOException {
|
||||||
output.writeInt(packModifiers(method.getModifiers()));
|
output.writeInt(packModifiers(method.getModifiers()));
|
||||||
output.writeShort(method.getVariables().size());
|
output.writeShort(method.getVariables().size());
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource {
|
||||||
if (item.cls != null) {
|
if (item.cls != null) {
|
||||||
File classFile = new File(directory, className.replace('.', '/') + ".teavm-cls");
|
File classFile = new File(directory, className.replace('.', '/') + ".teavm-cls");
|
||||||
classFile.getParentFile().mkdirs();
|
classFile.getParentFile().mkdirs();
|
||||||
try (OutputStream output = new FileOutputStream(classFile)) {
|
try (OutputStream output = new BufferedOutputStream(new FileOutputStream(classFile))) {
|
||||||
writeClass(output, item.cls);
|
writeClass(output, item.cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class DiskProgramCache implements ProgramCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
try (OutputStream stream = new FileOutputStream(file)) {
|
try (OutputStream stream = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||||
DataOutput output = new DataOutputStream(stream);
|
DataOutput output = new DataOutputStream(stream);
|
||||||
output.writeShort(analyzer.dependencies.size());
|
output.writeShort(analyzer.dependencies.size());
|
||||||
for (String dep : analyzer.dependencies) {
|
for (String dep : analyzer.dependencies) {
|
||||||
|
@ -104,57 +104,7 @@ public class DiskProgramCache implements ProgramCache {
|
||||||
|
|
||||||
private File getMethodFile(MethodReference method) {
|
private File getMethodFile(MethodReference method) {
|
||||||
File dir = new File(directory, method.getClassName().replace('.', '/'));
|
File dir = new File(directory, method.getClassName().replace('.', '/'));
|
||||||
String desc = method.getDescriptor().toString();
|
return new File(dir, FileNameEncoder.encodeFileName(method.getDescriptor().toString()) + ".teavm-opt");
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < desc.length(); ++i) {
|
|
||||||
char c = desc.charAt(i);
|
|
||||||
switch (c) {
|
|
||||||
case '/':
|
|
||||||
sb.append("$s");
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
sb.append("$b");
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
sb.append("$q");
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
sb.append("$p");
|
|
||||||
break;
|
|
||||||
case '*':
|
|
||||||
sb.append("$a");
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
sb.append("$c");
|
|
||||||
break;
|
|
||||||
case '|':
|
|
||||||
sb.append("$v");
|
|
||||||
break;
|
|
||||||
case '$':
|
|
||||||
sb.append("$$");
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
sb.append("$Q");
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
sb.append("$l");
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
sb.append("$g");
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
sb.append("$d");
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
sb.append("$w");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sb.append(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return new File(dir, sb + ".teavm-opt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Item {
|
static class Item {
|
||||||
|
|
244
teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java
vendored
Normal file
244
teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java
vendored
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.cache;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import org.teavm.javascript.RegularMethodNodeCache;
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.parsing.ClassDateProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class DiskRegularMethodNodeCache implements RegularMethodNodeCache {
|
||||||
|
private File directory;
|
||||||
|
private AstIO astIO;
|
||||||
|
private ClassDateProvider classDateProvider;
|
||||||
|
private Map<MethodReference, Item> cache = new HashMap<>();
|
||||||
|
private Set<MethodReference> newMethods = new HashSet<>();
|
||||||
|
|
||||||
|
public DiskRegularMethodNodeCache(File directory, SymbolTable symbolTable, SymbolTable fileTable,
|
||||||
|
ClassDateProvider classDateProvider) {
|
||||||
|
this.directory = directory;
|
||||||
|
astIO = new AstIO(symbolTable, fileTable);
|
||||||
|
this.classDateProvider = classDateProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegularMethodNode get(MethodReference methodReference) {
|
||||||
|
Item item = cache.get(methodReference);
|
||||||
|
if (item == null) {
|
||||||
|
item = new Item();
|
||||||
|
cache.put(methodReference, item);
|
||||||
|
}
|
||||||
|
return item.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(MethodReference methodReference, RegularMethodNode node) {
|
||||||
|
Item item = new Item();
|
||||||
|
item.node = node;
|
||||||
|
cache.put(methodReference, item);
|
||||||
|
newMethods.add(methodReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
for (MethodReference method : newMethods) {
|
||||||
|
File file = getMethodFile(method);
|
||||||
|
AstDependencyAnalyzer analyzer = new AstDependencyAnalyzer();
|
||||||
|
RegularMethodNode node = cache.get(method).node;
|
||||||
|
node.getBody().acceptVisitor(analyzer);
|
||||||
|
analyzer.dependencies.add(method.getClassName());
|
||||||
|
try (DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
|
||||||
|
output.writeShort(analyzer.dependencies.size());
|
||||||
|
for (String dependency : analyzer.dependencies) {
|
||||||
|
output.writeUTF(dependency);
|
||||||
|
}
|
||||||
|
astIO.write(output, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getMethodFile(MethodReference method) {
|
||||||
|
File dir = new File(directory, method.getClassName().replace('.', '/'));
|
||||||
|
return new File(dir, FileNameEncoder.encodeFileName(method.getDescriptor().toString()) + ".teavm-ast");
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AstDependencyAnalyzer implements StatementVisitor, ExprVisitor {
|
||||||
|
Set<String> dependencies = new HashSet<>();
|
||||||
|
|
||||||
|
private void visitSequence(List<Statement> statements) {
|
||||||
|
for (Statement stmt : statements) {
|
||||||
|
stmt.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignmentStatement statement) {
|
||||||
|
if (statement.getLeftValue() != null) {
|
||||||
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SequentialStatement statement) {
|
||||||
|
visitSequence(statement.getSequence());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalStatement statement) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
visitSequence(statement.getConsequent());
|
||||||
|
visitSequence(statement.getAlternative());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
statement.getValue().acceptVisitor(this);
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
visitSequence(clause.getBody());
|
||||||
|
}
|
||||||
|
visitSequence(statement.getDefaultClause());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
if (statement.getCondition() != null) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
visitSequence(statement.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
visitSequence(statement.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BreakStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ContinueStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnStatement statement) {
|
||||||
|
if (statement.getResult() != null) {
|
||||||
|
statement.getResult().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ThrowStatement statement) {
|
||||||
|
statement.getException().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InitClassStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(TryCatchStatement statement) {
|
||||||
|
visitSequence(statement.getProtectedBody());
|
||||||
|
visitSequence(statement.getHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr expr) {
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr expr) {
|
||||||
|
expr.getOperand().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalExpr expr) {
|
||||||
|
expr.getCondition().acceptVisitor(this);
|
||||||
|
expr.getConsequent().acceptVisitor(this);
|
||||||
|
expr.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstantExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(VariableExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SubscriptExpr expr) {
|
||||||
|
expr.getArray().acceptVisitor(this);
|
||||||
|
expr.getIndex().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnwrapArrayExpr expr) {
|
||||||
|
expr.getArray().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvocationExpr expr) {
|
||||||
|
dependencies.add(expr.getMethod().getClassName());
|
||||||
|
for (Expr argument : expr.getArguments()) {
|
||||||
|
argument.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(QualificationExpr expr) {
|
||||||
|
dependencies.add(expr.getField().getClassName());
|
||||||
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArrayExpr expr) {
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
|
dimension.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassExpr expr) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Item {
|
||||||
|
RegularMethodNode node;
|
||||||
|
}
|
||||||
|
}
|
78
teavm-core/src/main/java/org/teavm/cache/FileNameEncoder.java
vendored
Normal file
78
teavm-core/src/main/java/org/teavm/cache/FileNameEncoder.java
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public final class FileNameEncoder {
|
||||||
|
private FileNameEncoder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeFileName(String name) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < name.length(); ++i) {
|
||||||
|
char c = name.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '/':
|
||||||
|
sb.append("$s");
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
sb.append("$b");
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
sb.append("$q");
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
sb.append("$p");
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
sb.append("$a");
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
sb.append("$c");
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
sb.append("$v");
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
sb.append("$$");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
sb.append("$Q");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
sb.append("$l");
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
sb.append("$g");
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
sb.append("$d");
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
sb.append("$w");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sb.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,7 +62,8 @@ public class FileSymbolTable implements SymbolTable {
|
||||||
if (firstUnstoredIndex >= symbols.size()) {
|
if (firstUnstoredIndex >= symbols.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try (DataOutputStream output = new DataOutputStream(new FileOutputStream(file, true))) {
|
try (DataOutputStream output = new DataOutputStream(new BufferedOutputStream(
|
||||||
|
new FileOutputStream(file, true)))) {
|
||||||
while (firstUnstoredIndex < symbols.size()) {
|
while (firstUnstoredIndex < symbols.size()) {
|
||||||
String symbol = symbols.get(firstUnstoredIndex);
|
String symbol = symbols.get(firstUnstoredIndex);
|
||||||
output.writeByte((symbol.length() >> 8) & 0xFF);
|
output.writeByte((symbol.length() >> 8) & 0xFF);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user