mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
New AST optimization algorithm
This commit is contained in:
parent
d93883296e
commit
16d11909ea
|
@ -53,7 +53,7 @@
|
||||||
<phase>process-test-classes</phase>
|
<phase>process-test-classes</phase>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minifying>false</minifying>
|
<minifying>false</minifying>
|
||||||
<numThreads>0</numThreads>
|
<numThreads>1</numThreads>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* 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.javascript;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.javascript.ast.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BlockRefCountVisitor implements StatementVisitor {
|
||||||
|
Map<IdentifiedStatement, Integer> refs = new HashMap<>();
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
for (Statement stmt : statement.getConsequent()) {
|
||||||
|
stmt.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
for (Statement stmt : statement.getAlternative()) {
|
||||||
|
stmt.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(SwitchStatement statement) {
|
||||||
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
|
for (Statement part : clause.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Statement part : statement.getDefaultClause()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WhileStatement statement) {
|
||||||
|
refs.put(statement, 0);
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BlockStatement statement) {
|
||||||
|
refs.put(statement, 0);
|
||||||
|
for (Statement part : statement.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ForStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(BreakStatement statement) {
|
||||||
|
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ContinueStatement statement) {
|
||||||
|
refs.put(statement.getTarget(), refs.get(statement.getTarget()) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ReturnStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(ThrowStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(IncrementStatement statement) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InitClassStatement statement) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,225 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.List;
|
|
||||||
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 j = 1; j < stmt.getBody().size(); ++j) {
|
|
||||||
altBody.getSequence().add(stmt.getBody().get(j));
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
for (int i = 0; i < stmt.getBody().size(); ++i) {
|
|
||||||
if (stmt.getBody().isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(stmt.getBody().get(i) instanceof ConditionalStatement)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ConditionalStatement condStmt = (ConditionalStatement)stmt.getBody().get(i);
|
|
||||||
if (condStmt.getAlternative() != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(condStmt.getConsequent() instanceof BreakStatement)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
BreakStatement breakStmt = (BreakStatement)condStmt.getConsequent();
|
|
||||||
if (breakStmt.getTarget() != stmt) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
stmt.getBody().remove(i);
|
|
||||||
referencedStatements.put(stmt, referencedStatements.get(stmt) - 1);
|
|
||||||
ConditionalStatement newCond = new ConditionalStatement();
|
|
||||||
newCond.setCondition(ExprOptimizer.invert(condStmt.getCondition()));
|
|
||||||
List<Statement> remaining = stmt.getBody().subList(i, stmt.getBody().size());
|
|
||||||
if (remaining.size() == 1) {
|
|
||||||
newCond.setConsequent(remaining.get(0));
|
|
||||||
} else {
|
|
||||||
SequentialStatement newConsequent = new SequentialStatement();
|
|
||||||
newConsequent.getSequence().addAll(remaining);
|
|
||||||
newCond.setConsequent(newConsequent);
|
|
||||||
}
|
|
||||||
remaining.clear();
|
|
||||||
stmt.getBody().add(newCond);
|
|
||||||
if (referencedStatements.get(stmt) == 0) {
|
|
||||||
SequentialStatement flat = new SequentialStatement();
|
|
||||||
flat.getSequence().addAll(stmt.getBody());
|
|
||||||
return flat;
|
|
||||||
} else {
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,10 @@ public class Optimizer {
|
||||||
public void optimize(RegularMethodNode method, Program program) {
|
public void optimize(RegularMethodNode method, Program program) {
|
||||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||||
stats.analyze(program);
|
stats.analyze(program);
|
||||||
|
BlockRefCountVisitor refsCounter = new BlockRefCountVisitor();
|
||||||
|
method.getBody().acceptVisitor(refsCounter);
|
||||||
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
|
||||||
|
optimizer.referencedStatements = refsCounter.refs;
|
||||||
method.getBody().acceptVisitor(optimizer);
|
method.getBody().acceptVisitor(optimizer);
|
||||||
method.setBody(optimizer.resultStmt);
|
method.setBody(optimizer.resultStmt);
|
||||||
int paramCount = method.getReference().parameterCount();
|
int paramCount = method.getReference().parameterCount();
|
||||||
|
|
|
@ -26,15 +26,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
public Expr resultExpr;
|
public Expr resultExpr;
|
||||||
public Statement resultStmt;
|
public Statement resultStmt;
|
||||||
private ReadWriteStatsBuilder stats;
|
private ReadWriteStatsBuilder stats;
|
||||||
private Map<IdentifiedStatement, IdentifiedStatement> copies = new HashMap<>();
|
Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
|
||||||
private Map<IdentifiedStatement, Integer> referencedStatements = new HashMap<>();
|
|
||||||
private ConditionalOptimizer conditionalOptimizer = new ConditionalOptimizer();
|
|
||||||
private List<Statement> resultSequence;
|
private List<Statement> resultSequence;
|
||||||
|
|
||||||
public OptimizingVisitor(ReadWriteStatsBuilder stats) {
|
public OptimizingVisitor(ReadWriteStatsBuilder stats) {
|
||||||
this.stats = stats;
|
this.stats = stats;
|
||||||
conditionalOptimizer.referencedStatements = referencedStatements;
|
|
||||||
conditionalOptimizer.stats = stats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isZero(Expr expr) {
|
private static boolean isZero(Expr expr) {
|
||||||
|
@ -83,14 +79,17 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resultExpr = Expr.binary(expr.getOperation(), a, b);
|
expr.setFirstOperand(a);
|
||||||
|
expr.setSecondOperand(b);
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnaryExpr expr) {
|
public void visit(UnaryExpr expr) {
|
||||||
expr.getOperand().acceptVisitor(this);
|
expr.getOperand().acceptVisitor(this);
|
||||||
Expr operand = resultExpr;
|
Expr operand = resultExpr;
|
||||||
resultExpr = Expr.unary(expr.getOperation(), operand);
|
expr.setOperand(operand);
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -101,22 +100,21 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
Expr consequent = resultExpr;
|
Expr consequent = resultExpr;
|
||||||
expr.getAlternative().acceptVisitor(this);
|
expr.getAlternative().acceptVisitor(this);
|
||||||
Expr alternative = resultExpr;
|
Expr alternative = resultExpr;
|
||||||
ConditionalExpr result = new ConditionalExpr();
|
expr.setCondition(cond);
|
||||||
result.setCondition(cond);
|
expr.setConsequent(consequent);
|
||||||
result.setConsequent(consequent);
|
expr.setAlternative(alternative);
|
||||||
result.setAlternative(alternative);
|
resultExpr = expr;
|
||||||
resultExpr = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstantExpr expr) {
|
public void visit(ConstantExpr expr) {
|
||||||
resultExpr = Expr.constant(expr.getValue());
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(VariableExpr expr) {
|
public void visit(VariableExpr expr) {
|
||||||
int index = expr.getIndex();
|
int index = expr.getIndex();
|
||||||
resultExpr = Expr.var(index);
|
resultExpr = expr;
|
||||||
if (stats.reads[index] != 1 || stats.writes[index] != 1) {
|
if (stats.reads[index] != 1 || stats.writes[index] != 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,16 +142,17 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
Expr index = resultExpr;
|
Expr index = resultExpr;
|
||||||
expr.getArray().acceptVisitor(this);
|
expr.getArray().acceptVisitor(this);
|
||||||
Expr array = resultExpr;
|
Expr array = resultExpr;
|
||||||
resultExpr = Expr.subscript(array, index);
|
expr.setArray(array);
|
||||||
|
expr.setIndex(index);
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayExpr expr) {
|
public void visit(UnwrapArrayExpr expr) {
|
||||||
expr.getArray().acceptVisitor(this);
|
expr.getArray().acceptVisitor(this);
|
||||||
Expr arrayExpr = resultExpr;
|
Expr arrayExpr = resultExpr;
|
||||||
UnwrapArrayExpr result = new UnwrapArrayExpr(expr.getElementType());
|
expr.setArray(arrayExpr);
|
||||||
result.setArray(arrayExpr);
|
resultExpr = expr;
|
||||||
resultExpr = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,20 +162,10 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
args[i] = resultExpr;
|
args[i] = resultExpr;
|
||||||
}
|
}
|
||||||
switch (expr.getType()) {
|
for (int i = 0; i < args.length; ++i) {
|
||||||
case STATIC:
|
expr.getArguments().set(i, args[i]);
|
||||||
resultExpr = Expr.invokeStatic(expr.getMethod(), args);
|
|
||||||
break;
|
|
||||||
case DYNAMIC:
|
|
||||||
resultExpr = Expr.invoke(expr.getMethod(), args[0], Arrays.copyOfRange(args, 1, args.length));
|
|
||||||
break;
|
|
||||||
case SPECIAL:
|
|
||||||
resultExpr = Expr.invokeSpecial(expr.getMethod(), args[0], Arrays.copyOfRange(args, 1, args.length));
|
|
||||||
break;
|
|
||||||
case CONSTRUCTOR:
|
|
||||||
resultExpr = Expr.constructObject(expr.getMethod(), args);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean tryApplyConstructor(InvocationExpr expr) {
|
private boolean tryApplyConstructor(InvocationExpr expr) {
|
||||||
|
@ -220,42 +209,43 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
public void visit(QualificationExpr expr) {
|
public void visit(QualificationExpr expr) {
|
||||||
expr.getQualified().acceptVisitor(this);
|
expr.getQualified().acceptVisitor(this);
|
||||||
Expr qualified = resultExpr;
|
Expr qualified = resultExpr;
|
||||||
resultExpr = Expr.qualify(qualified, expr.getField());
|
expr.setQualified(qualified);
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewExpr expr) {
|
public void visit(NewExpr expr) {
|
||||||
resultExpr = Expr.createObject(expr.getConstructedClass());
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewArrayExpr expr) {
|
public void visit(NewArrayExpr expr) {
|
||||||
expr.getLength().acceptVisitor(this);
|
expr.getLength().acceptVisitor(this);
|
||||||
Expr length = resultExpr;
|
Expr length = resultExpr;
|
||||||
resultExpr = Expr.createArray(expr.getType(), length);
|
expr.setLength(length);
|
||||||
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewMultiArrayExpr expr) {
|
public void visit(NewMultiArrayExpr expr) {
|
||||||
NewMultiArrayExpr result = new NewMultiArrayExpr();
|
for (int i = 0; i < expr.getDimensions().size(); ++i) {
|
||||||
result.setType(expr.getType());
|
Expr dimension = expr.getDimensions().get(i);
|
||||||
for (Expr dimension : expr.getDimensions()) {
|
|
||||||
dimension.acceptVisitor(this);
|
dimension.acceptVisitor(this);
|
||||||
result.getDimensions().add(resultExpr);
|
expr.getDimensions().set(i, resultExpr);
|
||||||
}
|
}
|
||||||
resultExpr = result;
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InstanceOfExpr expr) {
|
public void visit(InstanceOfExpr expr) {
|
||||||
expr.getExpr().acceptVisitor(this);
|
expr.getExpr().acceptVisitor(this);
|
||||||
Expr value = resultExpr;
|
expr.setExpr(resultExpr);
|
||||||
resultExpr = Expr.instanceOf(value, expr.getType());
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StaticClassExpr expr) {
|
public void visit(StaticClassExpr expr) {
|
||||||
resultExpr = Expr.staticClass(expr.getType());
|
resultExpr = expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -266,7 +256,8 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
tryApplyConstructor((InvocationExpr)resultExpr)) {
|
tryApplyConstructor((InvocationExpr)resultExpr)) {
|
||||||
resultStmt = new SequentialStatement();
|
resultStmt = new SequentialStatement();
|
||||||
} else {
|
} else {
|
||||||
resultStmt = Statement.assign(null, resultExpr);
|
statement.setRightValue(resultExpr);
|
||||||
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
statement.getRightValue().acceptVisitor(this);
|
statement.getRightValue().acceptVisitor(this);
|
||||||
|
@ -276,7 +267,9 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
statement.getLeftValue().acceptVisitor(this);
|
statement.getLeftValue().acceptVisitor(this);
|
||||||
left = resultExpr;
|
left = resultExpr;
|
||||||
}
|
}
|
||||||
resultStmt = Statement.assign(left, right);
|
statement.setLeftValue(left);
|
||||||
|
statement.setRightValue(right);
|
||||||
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,14 +279,21 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
if (strict) {
|
if (strict) {
|
||||||
resultSequence = result;
|
resultSequence = result;
|
||||||
}
|
}
|
||||||
for (Statement part : statements) {
|
outer: for (int i = 0; i < statements.size(); ++i) {
|
||||||
|
Statement part = statements.get(i);
|
||||||
part.acceptVisitor(this);
|
part.acceptVisitor(this);
|
||||||
if (resultStmt != null) {
|
List<Statement> newStatements = new ArrayList<>();
|
||||||
|
if (resultStmt instanceof SequentialStatement) {
|
||||||
|
newStatements.addAll(((SequentialStatement)resultStmt).getSequence());
|
||||||
|
} else {
|
||||||
|
newStatements.add(resultStmt);
|
||||||
|
}
|
||||||
|
for (int j = 0; j < newStatements.size(); ++j) {
|
||||||
|
Statement newStatement = newStatements.get(j);
|
||||||
resultSequence = result;
|
resultSequence = result;
|
||||||
if (resultStmt instanceof SequentialStatement) {
|
result.add(newStatement);
|
||||||
result.addAll(((SequentialStatement)resultStmt).getSequence());
|
if (newStatement instanceof BreakStatement) {
|
||||||
} else {
|
break outer;
|
||||||
result.add(resultStmt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,118 +301,168 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void eliminateRedundantBreaks(List<Statement> statements, Set<IdentifiedStatement> currentExits,
|
||||||
|
Set<IdentifiedStatement> exits) {
|
||||||
|
if (statements.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Statement last = statements.get(statements.size() - 1);
|
||||||
|
if (last instanceof BreakStatement) {
|
||||||
|
IdentifiedStatement target = ((BreakStatement)last).getTarget();
|
||||||
|
if (exits.contains(target)) {
|
||||||
|
statements.remove(statements.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (statements.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<IdentifiedStatement> nestedExits = new HashSet<>();
|
||||||
|
nestedExits.addAll(currentExits);
|
||||||
|
for (int i = 0; i < statements.size(); ++i) {
|
||||||
|
if (i == statements.size() - 1) {
|
||||||
|
nestedExits.addAll(exits);
|
||||||
|
}
|
||||||
|
Statement stmt = statements.get(i);
|
||||||
|
if (stmt instanceof ConditionalStatement) {
|
||||||
|
ConditionalStatement cond = (ConditionalStatement)stmt;
|
||||||
|
last = cond.getConsequent().get(cond.getConsequent().size() - 1);
|
||||||
|
if (last instanceof BreakStatement) {
|
||||||
|
BreakStatement breakStmt = (BreakStatement)last;
|
||||||
|
if (currentExits.contains(breakStmt.getTarget()) || exits.contains(breakStmt.getTarget())) {
|
||||||
|
int refs = referencedStatements.get(breakStmt.getTarget());
|
||||||
|
referencedStatements.put(breakStmt.getTarget(), refs - 1);
|
||||||
|
cond.getConsequent().remove(cond.getConsequent().size() - 1);
|
||||||
|
List<Statement> remaining = statements.subList(i + 1, statements.size());
|
||||||
|
cond.getAlternative().addAll(remaining);
|
||||||
|
remaining.clear();
|
||||||
|
visit(cond);
|
||||||
|
if (resultStmt == cond) {
|
||||||
|
eliminateRedundantBreaks(cond.getConsequent(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||||
|
eliminateRedundantBreaks(cond.getAlternative(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||||
|
} else {
|
||||||
|
statements.set(i, resultStmt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = cond.getAlternative().isEmpty() ? null :
|
||||||
|
cond.getAlternative().get(cond.getAlternative().size() - 1);
|
||||||
|
if (last instanceof BreakStatement) {
|
||||||
|
BreakStatement breakStmt = (BreakStatement)last;
|
||||||
|
if (currentExits.contains(breakStmt.getTarget()) || exits.contains(breakStmt.getTarget())) {
|
||||||
|
int refs = referencedStatements.get(breakStmt.getTarget());
|
||||||
|
referencedStatements.put(breakStmt.getTarget(), refs - 1);
|
||||||
|
cond.getAlternative().remove(cond.getConsequent().size() - 1);
|
||||||
|
List<Statement> remaining = statements.subList(i + 1, statements.size());
|
||||||
|
cond.getConsequent().addAll(remaining);
|
||||||
|
remaining.clear();
|
||||||
|
visit(cond);
|
||||||
|
if (resultStmt == cond) {
|
||||||
|
eliminateRedundantBreaks(cond.getConsequent(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||||
|
eliminateRedundantBreaks(cond.getAlternative(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet(), nestedExits);
|
||||||
|
}
|
||||||
|
statements.set(i, resultStmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (stmt instanceof BlockStatement) {
|
||||||
|
BlockStatement nestedBlock = (BlockStatement)stmt;
|
||||||
|
eliminateRedundantBreaks(nestedBlock.getBody(),
|
||||||
|
Collections.<IdentifiedStatement>singleton(nestedBlock), nestedExits);
|
||||||
|
} else if (stmt instanceof WhileStatement) {
|
||||||
|
WhileStatement whileStmt = (WhileStatement)stmt;
|
||||||
|
eliminateRedundantBreaks(whileStmt.getBody(), Collections.<IdentifiedStatement>emptySet(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet());
|
||||||
|
} else if (stmt instanceof SwitchStatement) {
|
||||||
|
SwitchStatement switchStmt = (SwitchStatement)stmt;
|
||||||
|
for (SwitchClause clause : switchStmt.getClauses()) {
|
||||||
|
eliminateRedundantBreaks(clause.getBody(), Collections.<IdentifiedStatement>emptySet(),
|
||||||
|
Collections.<IdentifiedStatement>emptySet());
|
||||||
|
}
|
||||||
|
eliminateRedundantBreaks(switchStmt.getDefaultClause(), null,
|
||||||
|
Collections.<IdentifiedStatement>emptySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SequentialStatement statement) {
|
public void visit(SequentialStatement statement) {
|
||||||
List<Statement> statements = processSequence(statement.getSequence(), false);
|
List<Statement> statements = processSequence(statement.getSequence(), false);
|
||||||
if (statements.isEmpty()) {
|
|
||||||
resultStmt = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (statements.size() == 1) {
|
if (statements.size() == 1) {
|
||||||
resultStmt = statements.get(0);
|
resultStmt = statements.get(0);
|
||||||
} else {
|
} else {
|
||||||
SequentialStatement result = new SequentialStatement();
|
statement.getSequence().clear();
|
||||||
result.getSequence().addAll(statements);
|
statement.getSequence().addAll(statements);
|
||||||
resultStmt = result;
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
Expr predicate = resultExpr;
|
statement.setCondition(resultExpr);
|
||||||
List<Statement> sequenceBackup = resultSequence;
|
List<Statement> consequent = processSequence(statement.getConsequent(), true);
|
||||||
resultSequence = new ArrayList<>();
|
List<Statement> alternative = processSequence(statement.getAlternative(), true);
|
||||||
statement.getConsequent().acceptVisitor(this);
|
if (consequent.isEmpty()) {
|
||||||
Statement consequent = resultStmt;
|
consequent.addAll(alternative);
|
||||||
Statement alternative = null;
|
alternative.clear();
|
||||||
if (statement.getAlternative() != null) {
|
statement.setCondition(ExprOptimizer.invert(statement.getCondition()));
|
||||||
statement.getAlternative().acceptVisitor(this);
|
|
||||||
alternative = resultStmt;
|
|
||||||
}
|
}
|
||||||
if (consequent == null) {
|
if (consequent.isEmpty()) {
|
||||||
if (alternative != null) {
|
resultStmt = Statement.empty();
|
||||||
Statement tmp = alternative;
|
return;
|
||||||
alternative = consequent;
|
|
||||||
consequent = tmp;
|
|
||||||
predicate = ExprOptimizer.invert(predicate);
|
|
||||||
} else {
|
|
||||||
consequent = Statement.empty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
resultStmt = conditionalOptimizer.tryMakeInline(
|
statement.getConsequent().clear();
|
||||||
(ConditionalStatement)Statement.cond(predicate, consequent, alternative));
|
statement.getConsequent().addAll(consequent);
|
||||||
resultSequence = sequenceBackup;
|
statement.getAlternative().clear();
|
||||||
}
|
statement.getAlternative().addAll(alternative);
|
||||||
|
resultStmt = statement;
|
||||||
private void visitIdentified(IdentifiedStatement stmt, IdentifiedStatement copy) {
|
|
||||||
copies.put(stmt, copy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
SwitchStatement result = new SwitchStatement();
|
|
||||||
result.setId(statement.getId());
|
|
||||||
visitIdentified(statement, result);
|
|
||||||
statement.getValue().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
result.setValue(resultExpr);
|
statement.setValue(resultExpr);
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
clause.getStatement().acceptVisitor(this);
|
List<Statement> newBody = processSequence(clause.getBody(), true);
|
||||||
SwitchClause resultClause = new SwitchClause();
|
clause.getBody().clear();
|
||||||
resultClause.setConditions(clause.getConditions());
|
clause.getBody().addAll(newBody);
|
||||||
resultClause.setStatement(resultStmt != null ? resultStmt : Statement.empty());
|
|
||||||
result.getClauses().add(resultClause);
|
|
||||||
}
|
}
|
||||||
if (statement.getDefaultClause() != null) {
|
List<Statement> newDefault = processSequence(statement.getDefaultClause(), true);
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
statement.getDefaultClause().clear();
|
||||||
} else {
|
statement.getDefaultClause().addAll(newDefault);
|
||||||
resultStmt = null;
|
resultStmt = statement;
|
||||||
}
|
|
||||||
result.setDefaultClause(resultStmt != null ? resultStmt : Statement.empty());
|
|
||||||
resultStmt = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WhileStatement statement) {
|
public void visit(WhileStatement statement) {
|
||||||
WhileStatement result = new WhileStatement();
|
|
||||||
result.setId(statement.getId());
|
|
||||||
visitIdentified(statement, result);
|
|
||||||
List<Statement> statements = processSequence(statement.getBody(), true);
|
List<Statement> statements = processSequence(statement.getBody(), true);
|
||||||
|
statement.getBody().clear();
|
||||||
|
statement.getBody().addAll(statements);
|
||||||
if (statement.getCondition() != null) {
|
if (statement.getCondition() != null) {
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
result.setCondition(resultExpr);
|
statement.setCondition(resultExpr);
|
||||||
} else {
|
|
||||||
result.setCondition(null);
|
|
||||||
}
|
}
|
||||||
result.getBody().addAll(statements);
|
resultStmt = statement;
|
||||||
conditionalOptimizer.tryOptimize(result);
|
|
||||||
resultStmt = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BlockStatement statement) {
|
public void visit(BlockStatement statement) {
|
||||||
BlockStatement result = new BlockStatement();
|
|
||||||
result.setId(statement.getId());
|
|
||||||
visitIdentified(statement, result);
|
|
||||||
List<Statement> statements = processSequence(statement.getBody(), false);
|
List<Statement> statements = processSequence(statement.getBody(), false);
|
||||||
result.getBody().addAll(statements);
|
eliminateRedundantBreaks(statements, Collections.<IdentifiedStatement>singleton(statement),
|
||||||
if (referencedStatements.containsKey(result)) {
|
Collections.<IdentifiedStatement>emptySet());
|
||||||
resultStmt = conditionalOptimizer.tryOptimize(result);
|
if (referencedStatements.get(statement).equals(0)) {
|
||||||
|
SequentialStatement result = new SequentialStatement();
|
||||||
|
result.getSequence().addAll(statements);
|
||||||
|
resultStmt = result;
|
||||||
} else {
|
} else {
|
||||||
SequentialStatement altResult = new SequentialStatement();
|
statement.getBody().clear();
|
||||||
altResult.getSequence().addAll(result.getBody());
|
statement.getBody().addAll(statements);
|
||||||
resultStmt = altResult;
|
resultStmt = statement;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,48 +472,28 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BreakStatement statement) {
|
public void visit(BreakStatement statement) {
|
||||||
BreakStatement result = new BreakStatement();
|
resultStmt = statement;
|
||||||
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
|
@Override
|
||||||
public void visit(ContinueStatement statement) {
|
public void visit(ContinueStatement statement) {
|
||||||
ContinueStatement result = new ContinueStatement();
|
resultStmt = statement;
|
||||||
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
|
@Override
|
||||||
public void visit(ReturnStatement statement) {
|
public void visit(ReturnStatement statement) {
|
||||||
if (statement.getResult() == null) {
|
if (statement.getResult() != null) {
|
||||||
resultStmt = Statement.exitFunction(null);
|
|
||||||
} else {
|
|
||||||
statement.getResult().acceptVisitor(this);
|
statement.getResult().acceptVisitor(this);
|
||||||
resultStmt = Statement.exitFunction(resultExpr);
|
statement.setResult(resultExpr);
|
||||||
}
|
}
|
||||||
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ThrowStatement statement) {
|
public void visit(ThrowStatement statement) {
|
||||||
statement.getException().acceptVisitor(this);
|
statement.getException().acceptVisitor(this);
|
||||||
resultStmt = Statement.raiseException(resultExpr);
|
statement.setException(resultExpr);
|
||||||
|
resultStmt = statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -42,18 +42,24 @@ class ReferenceCountingVisitor implements StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
statement.getConsequent().acceptVisitor(this);
|
for (Statement part : statement.getConsequent()) {
|
||||||
if (statement.getAlternative() != null) {
|
part.acceptVisitor(this);
|
||||||
statement.getAlternative().acceptVisitor(this);
|
}
|
||||||
|
for (Statement part : statement.getAlternative()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
clause.getStatement().acceptVisitor(this);
|
for (Statement part : clause.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Statement part : statement.getDefaultClause()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -388,10 +388,14 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.append("if").ws().append("(");
|
writer.append("if").ws().append("(");
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
statement.getConsequent().acceptVisitor(this);
|
for (Statement part : statement.getConsequent()) {
|
||||||
if (statement.getAlternative() != null) {
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
if (!statement.getAlternative().isEmpty()) {
|
||||||
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
writer.outdent().append("}").ws().append("else").ws().append("{").indent().softNewLine();
|
||||||
statement.getAlternative().acceptVisitor(this);
|
for (Statement part : statement.getAlternative()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
writer.outdent().append("}").softNewLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -413,12 +417,16 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.append("case ").append(condition).append(":").softNewLine();
|
writer.append("case ").append(condition).append(":").softNewLine();
|
||||||
}
|
}
|
||||||
writer.indent();
|
writer.indent();
|
||||||
clause.getStatement().acceptVisitor(this);
|
for (Statement part : clause.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
writer.outdent();
|
writer.outdent();
|
||||||
}
|
}
|
||||||
if (statement.getDefaultClause() != null) {
|
if (statement.getDefaultClause() != null) {
|
||||||
writer.append("default:").softNewLine().indent();
|
writer.append("default:").softNewLine().indent();
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
for (Statement part : statement.getDefaultClause()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
writer.outdent();
|
writer.outdent();
|
||||||
}
|
}
|
||||||
writer.outdent().append("}").softNewLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
|
|
|
@ -413,10 +413,16 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
conditions[i] = conditionList.get(i);
|
conditions[i] = conditionList.get(i);
|
||||||
}
|
}
|
||||||
clause.setConditions(conditions);
|
clause.setConditions(conditions);
|
||||||
clause.setStatement(generateJumpStatement(stmt, target));
|
Statement jumpStmt = generateJumpStatement(stmt, target);
|
||||||
|
if (jumpStmt != null) {
|
||||||
|
clause.getBody().add(jumpStmt);
|
||||||
|
}
|
||||||
stmt.getClauses().add(clause);
|
stmt.getClauses().add(clause);
|
||||||
}
|
}
|
||||||
stmt.setDefaultClause(generateJumpStatement(insn.getDefaultTarget()));
|
Statement breakStmt = generateJumpStatement(insn.getDefaultTarget());
|
||||||
|
if (breakStmt != null) {
|
||||||
|
stmt.getDefaultClause().add(breakStmt);
|
||||||
|
}
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,13 +611,9 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) {
|
private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) {
|
||||||
Statement consequent = generateJumpStatement(consequentBlock);
|
Statement consequent = generateJumpStatement(consequentBlock);
|
||||||
Statement alternative = generateJumpStatement(alternativeBlock);
|
Statement alternative = generateJumpStatement(alternativeBlock);
|
||||||
if (consequent == null) {
|
statements.add(Statement.cond(condition,
|
||||||
consequent = Statement.empty();
|
consequent != null ? Arrays.asList(consequent) : Collections.<Statement>emptyList(),
|
||||||
}
|
alternative != null ? Arrays.asList(alternative) : Collections.<Statement>emptyList()));
|
||||||
if (alternative == null) {
|
|
||||||
alternative = Statement.empty();
|
|
||||||
}
|
|
||||||
statements.add(Statement.cond(condition, consequent, alternative));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expr compare(BinaryOperation op, Variable value) {
|
private Expr compare(BinaryOperation op, Variable value) {
|
||||||
|
|
|
@ -61,9 +61,11 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
statement.getConsequent().acceptVisitor(this);
|
for (Statement part : statement.getConsequent()) {
|
||||||
if (statement.getAlternative() != null) {
|
part.acceptVisitor(this);
|
||||||
statement.getAlternative().acceptVisitor(this);
|
}
|
||||||
|
for (Statement part : statement.getAlternative()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +73,13 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
statement.getValue().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
clause.getStatement().acceptVisitor(this);
|
for (Statement part : clause.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Statement part : statement.getDefaultClause()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Alexey Andreev.
|
* Copyright 2011 Alexey Andreev.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -15,14 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript.ast;
|
package org.teavm.javascript.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class ConditionalStatement extends Statement {
|
public class ConditionalStatement extends Statement {
|
||||||
private Expr condition;
|
private Expr condition;
|
||||||
private Statement consequent;
|
private List<Statement> consequent = new ArrayList<>();
|
||||||
private Statement alternative;
|
private List<Statement> alternative = new ArrayList<>();
|
||||||
|
|
||||||
public Expr getCondition() {
|
public Expr getCondition() {
|
||||||
return condition;
|
return condition;
|
||||||
|
@ -32,22 +35,14 @@ public class ConditionalStatement extends Statement {
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement getConsequent() {
|
public List<Statement> getConsequent() {
|
||||||
return consequent;
|
return consequent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConsequent(Statement consequent) {
|
public List<Statement> getAlternative() {
|
||||||
this.consequent = consequent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Statement getAlternative() {
|
|
||||||
return alternative;
|
return alternative;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlternative(Statement alternative) {
|
|
||||||
this.alternative = alternative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(StatementVisitor visitor) {
|
public void acceptVisitor(StatementVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -119,9 +119,11 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
statement.getConsequent().acceptVisitor(this);
|
for (Statement part : statement.getConsequent()) {
|
||||||
if (statement.getAlternative() != null) {
|
part.acceptVisitor(this);
|
||||||
statement.getAlternative().acceptVisitor(this);
|
}
|
||||||
|
for (Statement part : statement.getAlternative()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +131,12 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
statement.getValue().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
clause.getStatement().acceptVisitor(this);
|
for (Statement part : clause.getBody()) {
|
||||||
|
part.acceptVisitor(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (statement.getDefaultClause() != null) {
|
for (Statement part : statement.getDefaultClause()) {
|
||||||
statement.getDefaultClause().acceptVisitor(this);
|
part.acceptVisitor(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript.ast;
|
package org.teavm.javascript.ast;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
|
@ -52,16 +55,16 @@ public abstract class Statement {
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Statement cond(Expr predicate, Statement consequent, Statement alternative) {
|
public static Statement cond(Expr predicate, List<Statement> consequent, List<Statement> alternative) {
|
||||||
ConditionalStatement statement = new ConditionalStatement();
|
ConditionalStatement statement = new ConditionalStatement();
|
||||||
statement.setCondition(predicate);
|
statement.setCondition(predicate);
|
||||||
statement.setConsequent(consequent);
|
statement.getConsequent().addAll(consequent);
|
||||||
statement.setAlternative(alternative);
|
statement.getAlternative().addAll(alternative);
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Statement cond(Expr predicate, Statement consequent) {
|
public static Statement cond(Expr predicate, List<Statement> consequent) {
|
||||||
return cond(predicate, consequent, null);
|
return cond(predicate, consequent, Collections.<Statement>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Statement initClass(String className) {
|
public static Statement initClass(String className) {
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript.ast;
|
package org.teavm.javascript.ast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -23,7 +25,7 @@ import java.util.Arrays;
|
||||||
*/
|
*/
|
||||||
public class SwitchClause {
|
public class SwitchClause {
|
||||||
private int[] conditions;
|
private int[] conditions;
|
||||||
private Statement statement;
|
private List<Statement> body = new ArrayList<>();
|
||||||
|
|
||||||
public int[] getConditions() {
|
public int[] getConditions() {
|
||||||
return conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
return conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
||||||
|
@ -33,11 +35,7 @@ public class SwitchClause {
|
||||||
this.conditions = conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
this.conditions = conditions != null ? Arrays.copyOf(conditions, conditions.length) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement getStatement() {
|
public List<Statement> getBody() {
|
||||||
return statement;
|
return body;
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatement(Statement statement) {
|
|
||||||
this.statement = statement;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,20 +25,16 @@ import java.util.List;
|
||||||
public class SwitchStatement extends IdentifiedStatement {
|
public class SwitchStatement extends IdentifiedStatement {
|
||||||
private Expr value;
|
private Expr value;
|
||||||
private List<SwitchClause> clauses = new ArrayList<>();
|
private List<SwitchClause> clauses = new ArrayList<>();
|
||||||
private Statement defaultClause;
|
private List<Statement> defaultClause = new ArrayList<>();
|
||||||
|
|
||||||
public List<SwitchClause> getClauses() {
|
public List<SwitchClause> getClauses() {
|
||||||
return clauses;
|
return clauses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Statement getDefaultClause() {
|
public List<Statement> getDefaultClause() {
|
||||||
return defaultClause;
|
return defaultClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultClause(Statement defaultClause) {
|
|
||||||
this.defaultClause = defaultClause;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Expr getValue() {
|
public Expr getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user