mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds JavaScript AST optimizer.
This commit is contained in:
parent
3445910866
commit
4e4d0cfe9e
|
@ -16,6 +16,10 @@ public class SourceWriter {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
public SourceWriter append(String value) {
|
public SourceWriter append(String value) {
|
||||||
appendIndent();
|
appendIndent();
|
||||||
sb.append(value);
|
sb.append(value);
|
||||||
|
@ -34,6 +38,12 @@ public class SourceWriter {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SourceWriter append(char value) {
|
||||||
|
appendIndent();
|
||||||
|
sb.append(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) {
|
public SourceWriter appendClass(String cls) {
|
||||||
appendIndent();
|
appendIndent();
|
||||||
sb.append(naming.getNameFor(cls));
|
sb.append(naming.getNameFor(cls));
|
||||||
|
@ -69,7 +79,6 @@ public class SourceWriter {
|
||||||
|
|
||||||
public SourceWriter indent() {
|
public SourceWriter indent() {
|
||||||
++indentSize;
|
++indentSize;
|
||||||
newLine();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,19 +12,23 @@ import java.util.List;
|
||||||
public class GraphBuilder {
|
public class GraphBuilder {
|
||||||
private GraphImpl builtGraph;
|
private GraphImpl builtGraph;
|
||||||
private List<IntegerArray> addedEdges = new ArrayList<>();
|
private List<IntegerArray> addedEdges = new ArrayList<>();
|
||||||
|
private int sz = 0;
|
||||||
|
|
||||||
public GraphBuilder() {
|
public GraphBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphBuilder(int sz) {
|
public GraphBuilder(int sz) {
|
||||||
addedEdges.addAll(Collections.<IntegerArray>nCopies(sz, null));
|
addedEdges.addAll(Collections.<IntegerArray>nCopies(sz, null));
|
||||||
|
this.sz = sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
addedEdges.clear();
|
addedEdges.clear();
|
||||||
|
sz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEdge(int from, int to) {
|
public void addEdge(int from, int to) {
|
||||||
|
sz = Math.max(sz, Math.max(from, to) + 1);
|
||||||
builtGraph = null;
|
builtGraph = null;
|
||||||
if (addedEdges.size() == from) {
|
if (addedEdges.size() == from) {
|
||||||
addedEdges.add(IntegerArray.of(to));
|
addedEdges.add(IntegerArray.of(to));
|
||||||
|
@ -43,11 +47,11 @@ public class GraphBuilder {
|
||||||
|
|
||||||
public Graph build() {
|
public Graph build() {
|
||||||
if (builtGraph == null) {
|
if (builtGraph == null) {
|
||||||
IntegerArray[] incomingEdges = new IntegerArray[addedEdges.size()];
|
IntegerArray[] incomingEdges = new IntegerArray[sz];
|
||||||
for (int i = 0; i < addedEdges.size(); ++i) {
|
for (int i = 0; i < sz; ++i) {
|
||||||
incomingEdges[i] = new IntegerArray(1);
|
incomingEdges[i] = new IntegerArray(1);
|
||||||
}
|
}
|
||||||
int[][] outgoingEdgeList = new int[addedEdges.size()][];
|
int[][] outgoingEdgeList = new int[sz][];
|
||||||
for (int i = 0; i < addedEdges.size(); ++i) {
|
for (int i = 0; i < addedEdges.size(); ++i) {
|
||||||
IntegerArray edgeList = addedEdges.get(i);
|
IntegerArray edgeList = addedEdges.get(i);
|
||||||
outgoingEdgeList[i] = edgeList != null ? edgeList.getAll() : new int[0];
|
outgoingEdgeList[i] = edgeList != null ? edgeList.getAll() : new int[0];
|
||||||
|
@ -55,8 +59,11 @@ public class GraphBuilder {
|
||||||
incomingEdges[j].add(i);
|
incomingEdges[j].add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int[][] incomingEdgeList = new int[addedEdges.size()][];
|
for (int i = addedEdges.size(); i < sz; ++i) {
|
||||||
for (int i = 0; i < addedEdges.size(); ++i) {
|
outgoingEdgeList[i] = new int[0];
|
||||||
|
}
|
||||||
|
int[][] incomingEdgeList = new int[sz][];
|
||||||
|
for (int i = 0; i < sz; ++i) {
|
||||||
incomingEdgeList[i] = incomingEdges[i].getAll();
|
incomingEdgeList[i] = incomingEdges[i].getAll();
|
||||||
}
|
}
|
||||||
builtGraph = new GraphImpl(incomingEdgeList, outgoingEdgeList);
|
builtGraph = new GraphImpl(incomingEdgeList, outgoingEdgeList);
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ConditionalOptimizer {
|
||||||
|
public Map<IdentifiedStatement, Integer> referencedStatements;
|
||||||
|
public ReadWriteStatsBuilder stats;
|
||||||
|
|
||||||
|
public Statement tryOptimizeElse(BlockStatement stmt) {
|
||||||
|
if (stmt.getBody().isEmpty()) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
if (!(stmt.getBody().get(0) instanceof ConditionalStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(0);
|
||||||
|
if (condStmt.getAlternative() != null) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
if (!(condStmt.getConsequent() instanceof SequentialStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
SequentialStatement condBody = (SequentialStatement)condStmt.getConsequent();
|
||||||
|
if (condBody.getSequence().isEmpty()) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
Statement lastStmt = condBody.getSequence().get(condBody.getSequence().size() - 1);
|
||||||
|
if (!(lastStmt instanceof BreakStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
BreakStatement breakStmt = (BreakStatement)lastStmt;
|
||||||
|
if (breakStmt.getTarget() != stmt) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
SequentialStatement altBody = new SequentialStatement();
|
||||||
|
for (int i = 1; i < stmt.getBody().size(); ++i) {
|
||||||
|
altBody.getSequence().add(stmt.getBody().get(i));
|
||||||
|
}
|
||||||
|
if (!altBody.getSequence().isEmpty()) {
|
||||||
|
condStmt.setAlternative(altBody.getSequence().size() != 1 ?
|
||||||
|
altBody : altBody.getSequence().get(0));
|
||||||
|
}
|
||||||
|
condBody.getSequence().remove(condBody.getSequence().size() - 1);
|
||||||
|
if (condBody.getSequence().size() == 1) {
|
||||||
|
condStmt.setConsequent(condBody.getSequence().get(0));
|
||||||
|
}
|
||||||
|
stmt.getBody().clear();
|
||||||
|
stmt.getBody().add(condStmt);
|
||||||
|
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||||
|
if (referencedStatements.get(stmt) > 0) {
|
||||||
|
return stmt;
|
||||||
|
} else {
|
||||||
|
return tryMakeInline(condStmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Statement tryOptimize(BlockStatement stmt) {
|
||||||
|
Expr condition = null;
|
||||||
|
while (true) {
|
||||||
|
if (stmt.getBody().isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(stmt.getBody().get(0) instanceof ConditionalStatement)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(0);
|
||||||
|
if (condStmt.getAlternative() != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(condStmt.getConsequent() instanceof BreakStatement)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BreakStatement breakStmt = (BreakStatement)condStmt.getConsequent();
|
||||||
|
if (breakStmt.getTarget() != stmt) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stmt.getBody().remove(0);
|
||||||
|
if (condition == null) {
|
||||||
|
condition = ExprOptimizer.invert(condStmt.getCondition());
|
||||||
|
} else {
|
||||||
|
condition = Expr.binary(BinaryOperation.AND, condition,
|
||||||
|
ExprOptimizer.invert(condStmt.getCondition()));
|
||||||
|
}
|
||||||
|
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||||
|
}
|
||||||
|
if (condition == null) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
ConditionalStatement newCond = new ConditionalStatement();
|
||||||
|
newCond.setCondition(condition);
|
||||||
|
if (referencedStatements.get(stmt) > 0) {
|
||||||
|
newCond.setConsequent(stmt);
|
||||||
|
} else {
|
||||||
|
if (stmt.getBody().size() == 1) {
|
||||||
|
newCond.setConsequent(stmt.getBody().get(0));
|
||||||
|
} else {
|
||||||
|
SequentialStatement consequent = new SequentialStatement();
|
||||||
|
consequent.getSequence().addAll(stmt.getBody());
|
||||||
|
newCond.setConsequent(consequent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newCond;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryOptimize(WhileStatement stmt) {
|
||||||
|
if (stmt.getBody().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(stmt.getBody().get(0) instanceof ConditionalStatement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stmt.getCondition() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(0);
|
||||||
|
if (condStmt.getAlternative() != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(condStmt.getConsequent() instanceof BreakStatement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BreakStatement breakStmt = (BreakStatement)condStmt.getConsequent();
|
||||||
|
if (breakStmt.getTarget() != stmt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stmt.getBody().remove(0);
|
||||||
|
stmt.setCondition(ExprOptimizer.invert(condStmt.getCondition()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Statement tryMakeInline(ConditionalStatement stmt) {
|
||||||
|
if (!(stmt.getConsequent() instanceof AssignmentStatement) ||
|
||||||
|
!(stmt.getAlternative() instanceof AssignmentStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
AssignmentStatement consequent = (AssignmentStatement)stmt.getConsequent();
|
||||||
|
AssignmentStatement alternative = (AssignmentStatement)stmt.getAlternative();
|
||||||
|
if (!(consequent.getLeftValue() instanceof VariableExpr) ||
|
||||||
|
!(alternative.getLeftValue() instanceof VariableExpr)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
VariableExpr consequentLeft = (VariableExpr)consequent.getLeftValue();
|
||||||
|
VariableExpr alternativeLeft = (VariableExpr)alternative.getLeftValue();
|
||||||
|
if (consequentLeft.getIndex() != alternativeLeft.getIndex()) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
AssignmentStatement result = new AssignmentStatement();
|
||||||
|
result.setLeftValue(consequentLeft);
|
||||||
|
ConditionalExpr rightValue = new ConditionalExpr();
|
||||||
|
rightValue.setCondition(stmt.getCondition());
|
||||||
|
rightValue.setConsequent(consequent.getRightValue());
|
||||||
|
rightValue.setAlternative(alternative.getRightValue());
|
||||||
|
result.setRightValue(rightValue);
|
||||||
|
stats.writes[consequentLeft.getIndex()]--;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Statement tryOptimizeSwitch(BlockStatement stmt) {
|
||||||
|
if (stmt.getBody().size() < 2) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
if (!(stmt.getBody().get(0) instanceof SwitchStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
SwitchStatement switchStmt = (SwitchStatement)stmt.getBody().get(0);
|
||||||
|
Statement last = stmt.getBody().get(stmt.getBody().size() - 1);
|
||||||
|
if (!(last instanceof BreakStatement) && !(last instanceof ContinueStatement) &&
|
||||||
|
!(last instanceof ReturnStatement) && !(last instanceof ThrowStatement)) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
SequentialStatement seqStmt = new SequentialStatement();
|
||||||
|
for (int i = 1; i < stmt.getBody().size(); ++i) {
|
||||||
|
seqStmt.getSequence().add(stmt.getBody().get(i));
|
||||||
|
}
|
||||||
|
int count = referencedStatements.get(stmt);
|
||||||
|
ReferenceCountingVisitor refCounter = new ReferenceCountingVisitor(stmt);
|
||||||
|
switchStmt.acceptVisitor(refCounter);
|
||||||
|
if (count > refCounter.count) {
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
referencedStatements.put(stmt, 0);
|
||||||
|
for (SwitchClause clause : switchStmt.getClauses()) {
|
||||||
|
if (!(clause.getStatement() instanceof BreakStatement)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BreakStatement breakStmt = (BreakStatement)clause.getStatement();
|
||||||
|
if (breakStmt.getTarget() == stmt) {
|
||||||
|
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||||
|
Integer switchRefs = referencedStatements.get(switchStmt);
|
||||||
|
referencedStatements.put(switchStmt, (switchRefs != null ? switchRefs : 0) + 1);
|
||||||
|
breakStmt.setTarget(switchStmt);
|
||||||
|
} else if (breakStmt.getTarget() == switchStmt) {
|
||||||
|
clause.setStatement(seqStmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (switchStmt.getDefaultClause() instanceof BreakStatement) {
|
||||||
|
BreakStatement breakStmt = (BreakStatement)switchStmt.getDefaultClause();
|
||||||
|
if (breakStmt.getTarget() == stmt) {
|
||||||
|
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
||||||
|
Integer switchRefs = referencedStatements.get(switchStmt);
|
||||||
|
referencedStatements.put(switchStmt, (switchRefs != null ? switchRefs : 0) + 1);
|
||||||
|
breakStmt.setTarget(switchStmt);
|
||||||
|
} else if (breakStmt.getTarget() == switchStmt) {
|
||||||
|
switchStmt.setDefaultClause(seqStmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return switchStmt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ExprOptimizer {
|
||||||
|
public static Expr invert(Expr expr) {
|
||||||
|
if (expr instanceof UnaryExpr) {
|
||||||
|
UnaryExpr unary = (UnaryExpr)expr;
|
||||||
|
if (unary.getOperation() == UnaryOperation.NOT) {
|
||||||
|
return unary.getOperand();
|
||||||
|
}
|
||||||
|
} else if (expr instanceof BinaryExpr) {
|
||||||
|
BinaryExpr binary = (BinaryExpr)expr;
|
||||||
|
Expr a = binary.getFirstOperand();
|
||||||
|
Expr b = binary.getSecondOperand();
|
||||||
|
switch (binary.getOperation()) {
|
||||||
|
case EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.NOT_EQUALS, a, b);
|
||||||
|
case NOT_EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.EQUALS, a, b);
|
||||||
|
case LESS:
|
||||||
|
return Expr.binary(BinaryOperation.GREATER_OR_EQUALS, a, b);
|
||||||
|
case LESS_OR_EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.GREATER, a, b);
|
||||||
|
case GREATER:
|
||||||
|
return Expr.binary(BinaryOperation.LESS_OR_EQUALS, a, b);
|
||||||
|
case GREATER_OR_EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.LESS, a, b);
|
||||||
|
case STRICT_EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.STRICT_NOT_EQUALS, a, b);
|
||||||
|
case STRICT_NOT_EQUALS:
|
||||||
|
return Expr.binary(BinaryOperation.STRICT_EQUALS, a, b);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Expr.invert(expr);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript;
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.teavm.codegen.DefaultAliasProvider;
|
||||||
|
import org.teavm.codegen.DefaultNamingStrategy;
|
||||||
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.common.*;
|
import org.teavm.common.*;
|
||||||
import org.teavm.javascript.ast.*;
|
import org.teavm.javascript.ast.*;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
@ -201,9 +210,50 @@ public class MethodDecompiler {
|
||||||
this.loops = loops;
|
this.loops = loops;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) throws IOException {
|
||||||
ClassHolderSource source = new ClassHolderSource();
|
ClassHolderSource source = new ClassHolderSource();
|
||||||
Parser parser = new Parser();
|
ClassHolder arrayListCls = Parser.parseClass(readClass(ArrayList.class.getName()));
|
||||||
parser.parseClass(null);
|
source.putClassHolder(arrayListCls);
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(AbstractList.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(StringBuilder.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(IllegalArgumentException.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(IndexOutOfBoundsException.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Exception.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(RuntimeException.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Throwable.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(System.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Object.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Arrays.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ArrayList.class.getName() + "$ListItr")));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ArrayList.class.getName() + "$Itr")));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ArrayList.class.getName() + "$SubList")));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Collection.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ObjectOutputStream.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ObjectInputStream.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(ConcurrentModificationException.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(Math.class.getName())));
|
||||||
|
source.putClassHolder(Parser.parseClass(readClass(OutOfMemoryError.class.getName())));
|
||||||
|
MethodDecompiler decompiler = new MethodDecompiler(source);
|
||||||
|
DefaultAliasProvider aliasProvider = new DefaultAliasProvider();
|
||||||
|
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, source);
|
||||||
|
SourceWriter writer = new SourceWriter(naming);
|
||||||
|
Renderer renderer = new Renderer(writer, source);
|
||||||
|
Optimizer optimizer = new Optimizer();
|
||||||
|
for (MethodHolder method : arrayListCls.getMethods()) {
|
||||||
|
RenderableMethod renderableMethod = decompiler.decompile(method);
|
||||||
|
optimizer.optimize(renderableMethod);
|
||||||
|
renderer.render(renderableMethod);
|
||||||
|
}
|
||||||
|
System.out.println(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassNode readClass(String className) throws IOException {
|
||||||
|
ClassLoader classLoader = MethodDecompiler.class.getClassLoader();
|
||||||
|
try (InputStream input = classLoader.getResourceAsStream(className.replace('.', '/') + ".class")) {
|
||||||
|
ClassReader reader = new ClassReader(input);
|
||||||
|
ClassNode node = new ClassNode();
|
||||||
|
reader.accept(node, 0);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
teavm-core/src/main/java/org/teavm/javascript/Optimizer.java
Normal file
47
teavm-core/src/main/java/org/teavm/javascript/Optimizer.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.javascript.ast.RenderableMethod;
|
||||||
|
import org.teavm.javascript.ast.Statement;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class Optimizer {
|
||||||
|
public Statement optimize(MethodHolder method, Statement statement) {
|
||||||
|
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getProgram().variableCount());
|
||||||
|
statement.acceptVisitor(stats);
|
||||||
|
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
||||||
|
statement.acceptVisitor(optimizer);
|
||||||
|
return optimizer.resultStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void optimize(RenderableMethod method) {
|
||||||
|
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariableCount());
|
||||||
|
method.getBody().acceptVisitor(stats);
|
||||||
|
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
||||||
|
method.getBody().acceptVisitor(optimizer);
|
||||||
|
method.setBody(optimizer.resultStmt);
|
||||||
|
int paramCount = method.getMetadata().parameterCount();
|
||||||
|
UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariableCount());
|
||||||
|
method.getBody().acceptVisitor(unusedEliminator);
|
||||||
|
method.setVariableCount(unusedEliminator.lastIndex);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,474 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
public Expr resultExpr;
|
||||||
|
public Statement resultStmt;
|
||||||
|
private ReadWriteStatsBuilder stats;
|
||||||
|
private Map<IdentifiedStatement, IdentifiedStatement> copies = new HashMap<>();
|
||||||
|
private Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
|
||||||
|
private ConditionalOptimizer conditionalOptimizer = new ConditionalOptimizer();
|
||||||
|
private List<Statement> resultSequence;
|
||||||
|
|
||||||
|
public OptimizingVisitor(ReadWriteStatsBuilder stats) {
|
||||||
|
this.stats = stats;
|
||||||
|
conditionalOptimizer.referencedStatements = referencedStatements;
|
||||||
|
conditionalOptimizer.stats = stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isZero(Expr expr) {
|
||||||
|
return expr instanceof ConstantExpr &&
|
||||||
|
Integer.valueOf(0).equals(((ConstantExpr)expr).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isComparison(Expr expr) {
|
||||||
|
return expr instanceof BinaryExpr &&
|
||||||
|
((BinaryExpr)expr).getOperation() == BinaryOperation.COMPARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr expr) {
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
Expr b = resultExpr;
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
Expr a = resultExpr;
|
||||||
|
Expr p = a;
|
||||||
|
Expr q = b;
|
||||||
|
boolean invert = false;
|
||||||
|
if (isZero(p)) {
|
||||||
|
Expr tmp = p;
|
||||||
|
p = q;
|
||||||
|
q = tmp;
|
||||||
|
invert = true;
|
||||||
|
}
|
||||||
|
if (isComparison(p) && isZero(q)) {
|
||||||
|
switch (expr.getOperation()) {
|
||||||
|
case EQUALS:
|
||||||
|
case NOT_EQUALS:
|
||||||
|
case LESS:
|
||||||
|
case LESS_OR_EQUALS:
|
||||||
|
case GREATER:
|
||||||
|
case GREATER_OR_EQUALS: {
|
||||||
|
BinaryExpr comparison = (BinaryExpr)p;
|
||||||
|
Expr result = BinaryExpr.binary(expr.getOperation(),
|
||||||
|
comparison.getFirstOperand(), comparison.getSecondOperand());
|
||||||
|
if (invert) {
|
||||||
|
result = ExprOptimizer.invert(result);
|
||||||
|
}
|
||||||
|
resultExpr = result;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultExpr = Expr.binary(expr.getOperation(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr expr) {
|
||||||
|
expr.getOperand().acceptVisitor(this);
|
||||||
|
Expr operand = resultExpr;
|
||||||
|
resultExpr = Expr.unary(expr.getOperation(), operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalExpr expr) {
|
||||||
|
expr.getCondition().acceptVisitor(this);
|
||||||
|
Expr cond = resultExpr;
|
||||||
|
expr.getConsequent().acceptVisitor(this);
|
||||||
|
Expr consequent = resultExpr;
|
||||||
|
expr.getAlternative().acceptVisitor(this);
|
||||||
|
Expr alternative = resultExpr;
|
||||||
|
ConditionalExpr result = new ConditionalExpr();
|
||||||
|
result.setCondition(cond);
|
||||||
|
result.setConsequent(consequent);
|
||||||
|
result.setAlternative(alternative);
|
||||||
|
resultExpr = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstantExpr expr) {
|
||||||
|
resultExpr = Expr.constant(expr.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(VariableExpr expr) {
|
||||||
|
int index = expr.getIndex();
|
||||||
|
resultExpr = Expr.var(index);
|
||||||
|
if (stats.reads[index] != 1 || stats.writes[index] != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resultSequence.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Statement last = resultSequence.get(resultSequence.size() - 1);
|
||||||
|
if (!(last instanceof AssignmentStatement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AssignmentStatement assignment = (AssignmentStatement)last;
|
||||||
|
if (!(assignment.getLeftValue() instanceof VariableExpr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VariableExpr var = (VariableExpr)assignment.getLeftValue();
|
||||||
|
if (var.getIndex() == index) {
|
||||||
|
resultSequence.remove(resultSequence.size() - 1);
|
||||||
|
assignment.getRightValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SubscriptExpr expr) {
|
||||||
|
expr.getIndex().acceptVisitor(this);
|
||||||
|
Expr index = resultExpr;
|
||||||
|
expr.getArray().acceptVisitor(this);
|
||||||
|
Expr array = resultExpr;
|
||||||
|
resultExpr = Expr.subscript(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvocationExpr expr) {
|
||||||
|
Expr[] args = new Expr[expr.getArguments().size()];
|
||||||
|
for (int i = expr.getArguments().size() - 1; i >= 0; --i) {
|
||||||
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
|
args[i] = resultExpr;
|
||||||
|
}
|
||||||
|
switch (expr.getType()) {
|
||||||
|
case STATIC:
|
||||||
|
resultExpr = Expr.invokeStatic(expr.getClassName(), expr.getMethod(), args);
|
||||||
|
break;
|
||||||
|
case DYNAMIC:
|
||||||
|
resultExpr = Expr.invoke(expr.getClassName(), expr.getMethod(), args[0], Arrays.copyOfRange(
|
||||||
|
args, 1, args.length));
|
||||||
|
break;
|
||||||
|
case SPECIAL:
|
||||||
|
resultExpr = Expr.invokeSpecial(expr.getClassName(), expr.getMethod(), args[0], Arrays.copyOfRange(
|
||||||
|
args, 1, args.length));
|
||||||
|
break;
|
||||||
|
case CONSTRUCTOR:
|
||||||
|
resultExpr = Expr.constructObject(expr.getClassName(), expr.getMethod(), args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tryApplyConstructor(InvocationExpr expr) {
|
||||||
|
if (!expr.getMethod().getName().equals("<init>")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resultSequence == null || resultSequence.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Statement last = resultSequence.get(resultSequence.size() - 1);
|
||||||
|
if (!(last instanceof AssignmentStatement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AssignmentStatement assignment = (AssignmentStatement)last;
|
||||||
|
if (!(assignment.getLeftValue() instanceof VariableExpr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VariableExpr var = (VariableExpr)assignment.getLeftValue();
|
||||||
|
if (!(expr.getArguments().get(0) instanceof VariableExpr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VariableExpr target = (VariableExpr)expr.getArguments().get(0);
|
||||||
|
if (target.getIndex() != var.getIndex()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(assignment.getRightValue() instanceof NewExpr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NewExpr constructed = (NewExpr)assignment.getRightValue();
|
||||||
|
if (!constructed.getConstructedClass().equals(expr.getClassName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Expr[] args = expr.getArguments().toArray(new Expr[0]);
|
||||||
|
args = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
assignment.setRightValue(Expr.constructObject(expr.getClassName(), expr.getMethod(), args));
|
||||||
|
stats.reads[var.getIndex()]--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(QualificationExpr expr) {
|
||||||
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
Expr qualified = resultExpr;
|
||||||
|
resultExpr = Expr.qualify(qualified, expr.getClassName(), expr.getField());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewExpr expr) {
|
||||||
|
resultExpr = Expr.createObject(expr.getConstructedClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArrayExpr expr) {
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
Expr length = resultExpr;
|
||||||
|
resultExpr = Expr.createArray(expr.getType(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
|
NewMultiArrayExpr result = new NewMultiArrayExpr();
|
||||||
|
result.setType(expr.getType());
|
||||||
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
|
dimension.acceptVisitor(this);
|
||||||
|
result.getDimensions().add(resultExpr);
|
||||||
|
}
|
||||||
|
resultExpr = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
Expr value = resultExpr;
|
||||||
|
resultExpr = Expr.instanceOf(value, expr.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassExpr expr) {
|
||||||
|
resultExpr = Expr.staticClass(expr.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignmentStatement statement) {
|
||||||
|
if (statement.getLeftValue() == null) {
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
if (resultExpr instanceof InvocationExpr &&
|
||||||
|
tryApplyConstructor((InvocationExpr)resultExpr)) {
|
||||||
|
resultStmt = new SequentialStatement();
|
||||||
|
} else {
|
||||||
|
resultStmt = Statement.assign(null, resultExpr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
Expr right = resultExpr;
|
||||||
|
Expr left;
|
||||||
|
if (statement.getLeftValue() instanceof VariableExpr) {
|
||||||
|
VariableExpr leftVar = (VariableExpr)statement.getLeftValue();
|
||||||
|
left = statement.getLeftValue();
|
||||||
|
if (stats.reads[leftVar.getIndex()] == 0) {
|
||||||
|
left = null;
|
||||||
|
} else {
|
||||||
|
left = statement.getLeftValue();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
|
left = resultExpr;
|
||||||
|
}
|
||||||
|
resultStmt = Statement.assign(left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Statement> processSequence(List<Statement> statements, boolean strict) {
|
||||||
|
List<Statement> backup = resultSequence;
|
||||||
|
List<Statement> result = new ArrayList<>();
|
||||||
|
if (strict) {
|
||||||
|
resultSequence = result;
|
||||||
|
}
|
||||||
|
for (Statement part : statements) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
if (resultStmt != null) {
|
||||||
|
resultSequence = result;
|
||||||
|
if (resultStmt instanceof SequentialStatement) {
|
||||||
|
result.addAll(((SequentialStatement)resultStmt).getSequence());
|
||||||
|
} else {
|
||||||
|
result.add(resultStmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultSequence = backup;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SequentialStatement statement) {
|
||||||
|
List<Statement> statements = processSequence(statement.getSequence(), false);
|
||||||
|
if (statements.isEmpty()) {
|
||||||
|
resultStmt = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (statements.size() == 1) {
|
||||||
|
resultStmt = statements.get(0);
|
||||||
|
} else {
|
||||||
|
SequentialStatement result = new SequentialStatement();
|
||||||
|
result.getSequence().addAll(statements);
|
||||||
|
resultStmt = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalStatement statement) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
Expr predicate = resultExpr;
|
||||||
|
List<Statement> sequenceBackup = resultSequence;
|
||||||
|
resultSequence = new ArrayList<>();
|
||||||
|
statement.getConsequent().acceptVisitor(this);
|
||||||
|
Statement consequent = resultStmt;
|
||||||
|
Statement alternative = null;
|
||||||
|
if (statement.getAlternative() != null) {
|
||||||
|
statement.getAlternative().acceptVisitor(this);
|
||||||
|
alternative = resultStmt;
|
||||||
|
}
|
||||||
|
if (consequent == null) {
|
||||||
|
if (alternative != null) {
|
||||||
|
Statement tmp = alternative;
|
||||||
|
alternative = consequent;
|
||||||
|
consequent = tmp;
|
||||||
|
predicate = ExprOptimizer.invert(predicate);
|
||||||
|
} else {
|
||||||
|
consequent = Statement.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultStmt = conditionalOptimizer.tryMakeInline(
|
||||||
|
(ConditionalStatement)Statement.cond(predicate, consequent, alternative));
|
||||||
|
resultSequence = sequenceBackup;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitIdentified(IdentifiedStatement stmt, IdentifiedStatement copy) {
|
||||||
|
copies.put(stmt, copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
SwitchStatement result = new SwitchStatement();
|
||||||
|
result.setId(statement.getId());
|
||||||
|
visitIdentified(statement, result);
|
||||||
|
statement.getValue().acceptVisitor(this);
|
||||||
|
result.setValue(resultExpr);
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
clause.getStatement().acceptVisitor(this);
|
||||||
|
SwitchClause resultClause = new SwitchClause();
|
||||||
|
resultClause.setConditions(clause.getConditions());
|
||||||
|
resultClause.setStatement(resultStmt != null ? resultStmt : Statement.empty());
|
||||||
|
result.getClauses().add(resultClause);
|
||||||
|
}
|
||||||
|
if (statement.getDefaultClause() != null) {
|
||||||
|
statement.getDefaultClause().acceptVisitor(this);
|
||||||
|
} else {
|
||||||
|
resultStmt = null;
|
||||||
|
}
|
||||||
|
result.setDefaultClause(resultStmt != null ? resultStmt : Statement.empty());
|
||||||
|
resultStmt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
WhileStatement result = new WhileStatement();
|
||||||
|
result.setId(statement.getId());
|
||||||
|
visitIdentified(statement, result);
|
||||||
|
List<Statement> statements = processSequence(statement.getBody(), false);
|
||||||
|
if (statement.getCondition() != null) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
result.setCondition(resultExpr);
|
||||||
|
} else {
|
||||||
|
result.setCondition(null);
|
||||||
|
}
|
||||||
|
result.getBody().addAll(statements);
|
||||||
|
conditionalOptimizer.tryOptimize(result);
|
||||||
|
resultStmt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
BlockStatement result = new BlockStatement();
|
||||||
|
result.setId(statement.getId());
|
||||||
|
visitIdentified(statement, result);
|
||||||
|
List<Statement> statements = processSequence(statement.getBody(), false);
|
||||||
|
result.getBody().addAll(statements);
|
||||||
|
if (referencedStatements.containsKey(result)) {
|
||||||
|
resultStmt = conditionalOptimizer.tryOptimize(result);
|
||||||
|
} else {
|
||||||
|
SequentialStatement altResult = new SequentialStatement();
|
||||||
|
altResult.getSequence().addAll(result.getBody());
|
||||||
|
resultStmt = altResult;
|
||||||
|
}
|
||||||
|
if (resultStmt instanceof BlockStatement) {
|
||||||
|
resultStmt = conditionalOptimizer.tryOptimizeElse((BlockStatement)resultStmt);
|
||||||
|
}
|
||||||
|
if (resultStmt instanceof BlockStatement) {
|
||||||
|
resultStmt = conditionalOptimizer.tryOptimizeSwitch((BlockStatement)resultStmt);
|
||||||
|
}
|
||||||
|
if (resultStmt instanceof ConditionalStatement) {
|
||||||
|
ConditionalStatement conditional = (ConditionalStatement)resultStmt;
|
||||||
|
conditional.getCondition().acceptVisitor(this);
|
||||||
|
conditional.setCondition(resultExpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BreakStatement statement) {
|
||||||
|
BreakStatement result = new BreakStatement();
|
||||||
|
if (statement.getTarget() != null) {
|
||||||
|
IdentifiedStatement targetCopy = copies.get(statement.getTarget());
|
||||||
|
result.setTarget(targetCopy);
|
||||||
|
Integer refCount = referencedStatements.get(targetCopy);
|
||||||
|
if (refCount == null) {
|
||||||
|
refCount = 0;
|
||||||
|
}
|
||||||
|
referencedStatements.put(targetCopy, refCount + 1);
|
||||||
|
}
|
||||||
|
resultStmt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ContinueStatement statement) {
|
||||||
|
ContinueStatement result = new ContinueStatement();
|
||||||
|
if (statement.getTarget() != null) {
|
||||||
|
IdentifiedStatement targetCopy = copies.get(statement.getTarget());
|
||||||
|
result.setTarget(targetCopy);
|
||||||
|
Integer refCount = referencedStatements.get(targetCopy);
|
||||||
|
if (refCount == null) {
|
||||||
|
refCount = 0;
|
||||||
|
}
|
||||||
|
referencedStatements.put(targetCopy, refCount + 1);
|
||||||
|
}
|
||||||
|
resultStmt = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnStatement statement) {
|
||||||
|
if (statement.getResult() == null) {
|
||||||
|
resultStmt = Statement.exitFunction(null);
|
||||||
|
} else {
|
||||||
|
statement.getResult().acceptVisitor(this);
|
||||||
|
resultStmt = Statement.exitFunction(resultExpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ThrowStatement statement) {
|
||||||
|
statement.getException().acceptVisitor(this);
|
||||||
|
resultStmt = Statement.raiseException(resultExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IncrementStatement statement) {
|
||||||
|
resultStmt = Statement.increment(statement.getVar(), statement.getAmount());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
|
||||||
|
public int[] reads;
|
||||||
|
public int[] writes;
|
||||||
|
|
||||||
|
public ReadWriteStatsBuilder(int variableCount) {
|
||||||
|
reads = new int[variableCount];
|
||||||
|
writes = new int[variableCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
reads[expr.getIndex()]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SubscriptExpr expr) {
|
||||||
|
expr.getArray().acceptVisitor(this);
|
||||||
|
expr.getIndex().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvocationExpr expr) {
|
||||||
|
for (Expr arg : expr.getArguments()) {
|
||||||
|
arg.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(QualificationExpr expr) {
|
||||||
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArrayExpr expr) {
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
|
dimension.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignmentStatement statement) {
|
||||||
|
if (statement.getLeftValue() != null) {
|
||||||
|
if (statement.getLeftValue() instanceof VariableExpr) {
|
||||||
|
VariableExpr leftVar = (VariableExpr)statement.getLeftValue();
|
||||||
|
writes[leftVar.getIndex()]++;
|
||||||
|
} else {
|
||||||
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SequentialStatement statement) {
|
||||||
|
for (Statement part : statement.getSequence()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalStatement statement) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
statement.getConsequent().acceptVisitor(this);
|
||||||
|
if (statement.getAlternative() != null) {
|
||||||
|
statement.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
statement.getValue().acceptVisitor(this);
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
clause.getStatement().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
if (statement.getDefaultClause() != null) {
|
||||||
|
statement.getDefaultClause().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
if (statement.getCondition() != null) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(IncrementStatement statement) {
|
||||||
|
reads[statement.getVar()]++;
|
||||||
|
writes[statement.getVar()]++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class ReferenceCountingVisitor implements StatementVisitor {
|
||||||
|
private IdentifiedStatement target;
|
||||||
|
public int count;
|
||||||
|
|
||||||
|
public ReferenceCountingVisitor(IdentifiedStatement target) {
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignmentStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SequentialStatement statement) {
|
||||||
|
for (Statement part : statement.getSequence()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalStatement statement) {
|
||||||
|
statement.getConsequent().acceptVisitor(this);
|
||||||
|
if (statement.getAlternative() != null) {
|
||||||
|
statement.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
clause.getStatement().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
statement.getDefaultClause().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BreakStatement statement) {
|
||||||
|
if (statement.getTarget() == target) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ContinueStatement statement) {
|
||||||
|
if (statement.getTarget() == target) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ThrowStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IncrementStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -210,7 +210,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
first = false;
|
first = false;
|
||||||
writer.append(variableName(i));
|
writer.append(variableName(i));
|
||||||
}
|
}
|
||||||
writer.append(";\n");
|
writer.append(";").newLine();
|
||||||
}
|
}
|
||||||
method.getBody().acceptVisitor(this);
|
method.getBody().acceptVisitor(this);
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
|
@ -240,7 +240,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.append(") {").newLine().indent();
|
writer.append(") {").newLine().indent();
|
||||||
statement.getConsequent().acceptVisitor(this);
|
statement.getConsequent().acceptVisitor(this);
|
||||||
if (statement.getAlternative() != null) {
|
if (statement.getAlternative() != null) {
|
||||||
writer.outdent().append("} else {\n").indent().newLine();
|
writer.outdent().append("} else {").indent().newLine();
|
||||||
statement.getAlternative().acceptVisitor(this);
|
statement.getAlternative().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
|
@ -354,9 +354,9 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
--index;
|
--index;
|
||||||
if (index < variableNames.length()) {
|
if (index < variableNames.length()) {
|
||||||
return String.valueOf(variableNames.charAt(index));
|
return Character.toString(variableNames.charAt(index));
|
||||||
} else {
|
} else {
|
||||||
return String.valueOf(variableNames.charAt(index % variableNames.length())) +
|
return Character.toString(variableNames.charAt(index % variableNames.length())) +
|
||||||
index / variableNames.length();
|
index / variableNames.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
||||||
|
int[] indexes;
|
||||||
|
int lastIndex;
|
||||||
|
|
||||||
|
public UnusedVariableEliminator(int parameterCount, int variableCount) {
|
||||||
|
indexes = new int[variableCount];
|
||||||
|
Arrays.fill(indexes, -1);
|
||||||
|
for (int i = 0; i <= parameterCount; ++i) {
|
||||||
|
indexes[i] = lastIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(AssignmentStatement statement) {
|
||||||
|
if (statement.getLeftValue() != null) {
|
||||||
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SequentialStatement statement) {
|
||||||
|
for (Statement part : statement.getSequence()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalStatement statement) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
statement.getConsequent().acceptVisitor(this);
|
||||||
|
if (statement.getAlternative() != null) {
|
||||||
|
statement.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
statement.getValue().acceptVisitor(this);
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
clause.getStatement().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
statement.getDefaultClause().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
if (statement.getCondition() != null) {
|
||||||
|
statement.getCondition().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int renumber(int var) {
|
||||||
|
int index = indexes[var];
|
||||||
|
if (index == -1) {
|
||||||
|
index = lastIndex++;
|
||||||
|
indexes[var] = index;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IncrementStatement statement) {
|
||||||
|
statement.setVar(renumber(statement.getVar()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BinaryExpr expr) {
|
||||||
|
expr.getFirstOperand().acceptVisitor(this);
|
||||||
|
expr.getSecondOperand().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(UnaryExpr expr) {
|
||||||
|
expr.getOperand().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConditionalExpr expr) {
|
||||||
|
expr.getCondition().acceptVisitor(this);
|
||||||
|
expr.getConsequent().acceptVisitor(this);
|
||||||
|
expr.getAlternative().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ConstantExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(VariableExpr expr) {
|
||||||
|
expr.setIndex(renumber(expr.getIndex()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SubscriptExpr expr) {
|
||||||
|
expr.getArray().acceptVisitor(this);
|
||||||
|
expr.getIndex().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InvocationExpr expr) {
|
||||||
|
for (Expr arg : expr.getArguments()) {
|
||||||
|
arg.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(QualificationExpr expr) {
|
||||||
|
expr.getQualified().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewExpr expr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewArrayExpr expr) {
|
||||||
|
expr.getLength().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
|
for (Expr dimension : expr.getDimensions()) {
|
||||||
|
dimension.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(StaticClassExpr expr) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,6 +67,7 @@ public class Program {
|
||||||
for (int i = 0; i < basicBlocks.size(); ++i) {
|
for (int i = 0; i < basicBlocks.size(); ++i) {
|
||||||
BasicBlock block = basicBlocks.get(i);
|
BasicBlock block = basicBlocks.get(i);
|
||||||
if (block != null) {
|
if (block != null) {
|
||||||
|
block.setIndex(sz);
|
||||||
basicBlocks.set(sz++, block);
|
basicBlocks.set(sz++, block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,7 +300,7 @@ public class ProgramParser {
|
||||||
insn.setCondition(getVariable(--currentDepth));
|
insn.setCondition(getVariable(--currentDepth));
|
||||||
insn.getEntries().addAll(Arrays.asList(table));
|
insn.getEntries().addAll(Arrays.asList(table));
|
||||||
builder.add(insn);
|
builder.add(insn);
|
||||||
int defaultIndex = labelIndexes.get(insn);
|
int defaultIndex = labelIndexes.get(dflt);
|
||||||
insn.setDefaultTarget(getBasicBlock(defaultIndex));
|
insn.setDefaultTarget(getBasicBlock(defaultIndex));
|
||||||
nextIndexes[labels.length] = defaultIndex;
|
nextIndexes[labels.length] = defaultIndex;
|
||||||
}
|
}
|
||||||
|
|
0
teavm-core/src/main/resources/.gitignore
vendored
Normal file
0
teavm-core/src/main/resources/.gitignore
vendored
Normal file
0
teavm-core/src/test/java/.gitignore
vendored
Normal file
0
teavm-core/src/test/java/.gitignore
vendored
Normal file
0
teavm-core/src/test/resources/.gitignore
vendored
Normal file
0
teavm-core/src/test/resources/.gitignore
vendored
Normal file
Loading…
Reference in New Issue
Block a user