mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-12-09 02:00:25 +08:00
When removing empty if statements, extract expressions with side effects from its condition
This commit is contained in:
parent
19625034c4
commit
ea9605e518
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2016 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 org.teavm.javascript.ast.BinaryExpr;
|
||||
import org.teavm.javascript.ast.ConditionalExpr;
|
||||
import org.teavm.javascript.ast.ConditionalStatement;
|
||||
import org.teavm.javascript.ast.ConstantExpr;
|
||||
import org.teavm.javascript.ast.Expr;
|
||||
import org.teavm.javascript.ast.ExprVisitor;
|
||||
import org.teavm.javascript.ast.InstanceOfExpr;
|
||||
import org.teavm.javascript.ast.InvocationExpr;
|
||||
import org.teavm.javascript.ast.NewArrayExpr;
|
||||
import org.teavm.javascript.ast.NewExpr;
|
||||
import org.teavm.javascript.ast.NewMultiArrayExpr;
|
||||
import org.teavm.javascript.ast.QualificationExpr;
|
||||
import org.teavm.javascript.ast.Statement;
|
||||
import org.teavm.javascript.ast.SubscriptExpr;
|
||||
import org.teavm.javascript.ast.UnaryExpr;
|
||||
import org.teavm.javascript.ast.UnwrapArrayExpr;
|
||||
import org.teavm.javascript.ast.VariableExpr;
|
||||
|
||||
public class ExpressionSideEffectDecomposer implements ExprVisitor {
|
||||
private List<Statement> target;
|
||||
|
||||
public ExpressionSideEffectDecomposer(List<Statement> target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@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) {
|
||||
ConditionalStatement statement = new ConditionalStatement();
|
||||
statement.setCondition(expr.getCondition());
|
||||
expr.getCondition().acceptVisitor(new ExpressionSideEffectDecomposer(statement.getConsequent()));
|
||||
expr.getAlternative().acceptVisitor(new ExpressionSideEffectDecomposer(statement.getAlternative()));
|
||||
target.add(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstantExpr expr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(VariableExpr expr) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SubscriptExpr expr) {
|
||||
expr.getArray().acceptVisitor(this);
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayExpr expr) {
|
||||
expr.getArray().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvocationExpr expr) {
|
||||
target.add(Statement.assign(null, expr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(QualificationExpr expr) {
|
||||
if (expr.getQualified() != null) {
|
||||
expr.getQualified().acceptVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewExpr expr) {
|
||||
target.add(Statement.assign(null, 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);
|
||||
}
|
||||
}
|
@ -505,7 +505,10 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||
statement.setCondition(ExprOptimizer.invert(statement.getCondition()));
|
||||
}
|
||||
if (consequent.isEmpty()) {
|
||||
resultStmt = Statement.empty();
|
||||
SequentialStatement sequentialStatement = new SequentialStatement();
|
||||
resultStmt = sequentialStatement;
|
||||
statement.getCondition().acceptVisitor(new ExpressionSideEffectDecomposer(
|
||||
sequentialStatement.getSequence()));
|
||||
return;
|
||||
}
|
||||
statement.getConsequent().clear();
|
||||
|
@ -84,15 +84,15 @@ public class Inlining {
|
||||
splitBlock.getInstructions().addAll(instructionsToMove);
|
||||
copyTryCatchBlocks(block, splitBlock);
|
||||
|
||||
JumpInstruction jumpToInlinedProgram = new JumpInstruction();
|
||||
jumpToInlinedProgram.setTarget(firstInlineBlock);
|
||||
block.getInstructions().set(planEntry.targetInstruction, jumpToInlinedProgram);
|
||||
|
||||
block.getInstructions().remove(block.getInstructions().size() - 1);
|
||||
if (invoke.getInstance() == null || invoke.getMethod().getName().equals("<init>")) {
|
||||
InitClassInstruction clinit = new InitClassInstruction();
|
||||
clinit.setClassName(invoke.getMethod().getClassName());
|
||||
firstInlineBlock.getInstructions().add(clinit);
|
||||
block.getInstructions().add(clinit);
|
||||
}
|
||||
JumpInstruction jumpToInlinedProgram = new JumpInstruction();
|
||||
jumpToInlinedProgram.setTarget(firstInlineBlock);
|
||||
block.getInstructions().add(jumpToInlinedProgram);
|
||||
|
||||
for (int i = 0; i < inlineProgram.basicBlockCount(); ++i) {
|
||||
BasicBlock blockToInline = inlineProgram.basicBlockAt(i);
|
||||
@ -214,12 +214,13 @@ public class Inlining {
|
||||
tryCatchCopy.setExceptionVariable(source.getProgram().createVariable());
|
||||
List<Incoming> handlerIncomings = tryCatch.getHandler().getPhis().stream()
|
||||
.flatMap(phi -> phi.getIncomings().stream())
|
||||
.filter(incoming -> incoming.getValue() == tryCatch.getExceptionVariable())
|
||||
.filter(incoming -> incoming.getValue() == tryCatch.getExceptionVariable()
|
||||
&& incoming.getSource() == source)
|
||||
.collect(Collectors.toList());
|
||||
for (Incoming incoming : handlerIncomings) {
|
||||
Incoming incomingCopy = new Incoming();
|
||||
incomingCopy.setValue(tryCatchCopy.getExceptionVariable());
|
||||
incomingCopy.setSource(incoming.getSource());
|
||||
incomingCopy.setSource(target);
|
||||
incoming.getPhi().getIncomings().add(incomingCopy);
|
||||
}
|
||||
copiedTryCatches.add(tryCatchCopy);
|
||||
@ -236,6 +237,9 @@ public class Inlining {
|
||||
|
||||
for (int i = program.basicBlockCount() - 1; i >= 0; --i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
if (!block.getTryCatchBlocks().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
List<Instruction> instructions = block.getInstructions();
|
||||
for (int j = instructions.size() - 1; j >= 0; --j) {
|
||||
Instruction insn = instructions.get(j);
|
||||
|
@ -21,6 +21,6 @@ import org.teavm.model.Program;
|
||||
public class LoopInversion implements MethodOptimization {
|
||||
@Override
|
||||
public boolean optimize(MethodReader method, Program program) {
|
||||
return new LoopInversionImpl(program, method.parameterCount() + 1).apply();
|
||||
return new LoopInversionImpl(method, program, method.parameterCount() + 1).apply();
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import org.teavm.common.LoopGraph;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
@ -78,6 +79,7 @@ import org.teavm.model.util.UsageExtractor;
|
||||
* all remaining nodes are *condition*.
|
||||
*/
|
||||
class LoopInversionImpl {
|
||||
private final MethodReader method;
|
||||
private final Program program;
|
||||
private final int parameterCount;
|
||||
private Graph cfg;
|
||||
@ -87,7 +89,8 @@ class LoopInversionImpl {
|
||||
private BasicBlock[] definitionPlaces;
|
||||
private boolean affected;
|
||||
|
||||
LoopInversionImpl(Program program, int parameterCount) {
|
||||
LoopInversionImpl(MethodReader method, Program program, int parameterCount) {
|
||||
this.method = method;
|
||||
this.program = program;
|
||||
this.parameterCount = parameterCount;
|
||||
definitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program);
|
||||
@ -112,6 +115,7 @@ class LoopInversionImpl {
|
||||
inputs[i] = program.variableAt(i);
|
||||
}
|
||||
new PhiUpdater().updatePhis(program, inputs);
|
||||
new UnusedVariableElimination().optimize(method, program);
|
||||
}
|
||||
}
|
||||
} while (postponed);
|
||||
|
Loading…
Reference in New Issue
Block a user