mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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 fileTable;
|
||||
|
||||
public AstIO(SymbolTable symbolTable, SymbolTable fileTable) {
|
||||
this.symbolTable = symbolTable;
|
||||
this.fileTable = fileTable;
|
||||
}
|
||||
|
||||
public void write(DataOutput output, RegularMethodNode method) throws IOException {
|
||||
output.writeInt(packModifiers(method.getModifiers()));
|
||||
output.writeShort(method.getVariables().size());
|
||||
|
|
|
@ -80,7 +80,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource {
|
|||
if (item.cls != null) {
|
||||
File classFile = new File(directory, className.replace('.', '/') + ".teavm-cls");
|
||||
classFile.getParentFile().mkdirs();
|
||||
try (OutputStream output = new FileOutputStream(classFile)) {
|
||||
try (OutputStream output = new BufferedOutputStream(new FileOutputStream(classFile))) {
|
||||
writeClass(output, item.cls);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public class DiskProgramCache implements ProgramCache {
|
|||
}
|
||||
}
|
||||
file.getParentFile().mkdirs();
|
||||
try (OutputStream stream = new FileOutputStream(file)) {
|
||||
try (OutputStream stream = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||
DataOutput output = new DataOutputStream(stream);
|
||||
output.writeShort(analyzer.dependencies.size());
|
||||
for (String dep : analyzer.dependencies) {
|
||||
|
@ -104,57 +104,7 @@ public class DiskProgramCache implements ProgramCache {
|
|||
|
||||
private File getMethodFile(MethodReference method) {
|
||||
File dir = new File(directory, method.getClassName().replace('.', '/'));
|
||||
String desc = method.getDescriptor().toString();
|
||||
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");
|
||||
return new File(dir, FileNameEncoder.encodeFileName(method.getDescriptor().toString()) + ".teavm-opt");
|
||||
}
|
||||
|
||||
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()) {
|
||||
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()) {
|
||||
String symbol = symbols.get(firstUnstoredIndex);
|
||||
output.writeByte((symbol.length() >> 8) & 0xFF);
|
||||
|
|
Loading…
Reference in New Issue
Block a user