mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-21 01:00:54 +08:00
Add instruction to perform array bound check
This commit is contained in:
parent
80fb6c1f81
commit
a1d7153cab
67
core/src/main/java/org/teavm/ast/BoundCheckExpr.java
Normal file
67
core/src/main/java/org/teavm/ast/BoundCheckExpr.java
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2019 konsoletyper.
|
||||
*
|
||||
* 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.ast;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BoundCheckExpr extends Expr {
|
||||
private Expr index;
|
||||
private Expr array;
|
||||
private boolean lower;
|
||||
|
||||
public Expr getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Expr index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Expr getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(Expr array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public boolean isLower() {
|
||||
return lower;
|
||||
}
|
||||
|
||||
public void setLower(boolean lower) {
|
||||
this.lower = lower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(ExprVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Expr clone(Map<Expr, Expr> cache) {
|
||||
Expr known = cache.get(this);
|
||||
if (known != null) {
|
||||
return known;
|
||||
}
|
||||
BoundCheckExpr copy = new BoundCheckExpr();
|
||||
cache.put(this, copy);
|
||||
copy.setIndex(index.clone(cache));
|
||||
copy.setArray(array != null ? array.clone(cache) : null);
|
||||
copy.setLower(lower);
|
||||
return copy;
|
||||
}
|
||||
}
|
@ -45,4 +45,6 @@ public interface ExprVisitor {
|
||||
void visit(CastExpr expr);
|
||||
|
||||
void visit(PrimitiveCastExpr expr);
|
||||
|
||||
void visit(BoundCheckExpr expr);
|
||||
}
|
||||
|
@ -227,4 +227,14 @@ public class RecursiveVisitor implements ExprVisitor, StatementVisitor {
|
||||
public void visit(MonitorExitStatement statement) {
|
||||
statement.getObjectRef().acceptVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
beforeVisit(expr);
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
if (expr.getArray() != null) {
|
||||
expr.getArray().acceptVisitor(this);
|
||||
}
|
||||
afterVisit(expr);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
import org.teavm.ast.ConditionalStatement;
|
||||
@ -64,8 +65,8 @@ public final class LocationGraphBuilder {
|
||||
for (int terminal : visitor.nodes) {
|
||||
visitor.terminalNodes.set(terminal);
|
||||
}
|
||||
TextLocation[][] locations = propagate(visitor.locations.toArray(new TextLocation[0]), graph,
|
||||
visitor.terminalNodes);
|
||||
TextLocation[][] locations = propagate(visitor.locations.toArray(new TextLocation[0]), graph
|
||||
);
|
||||
|
||||
Map<TextLocation, Set<TextLocation>> builder = new LinkedHashMap<>();
|
||||
for (int i = 0; i < graph.size(); ++i) {
|
||||
@ -91,7 +92,7 @@ public final class LocationGraphBuilder {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static TextLocation[][] propagate(TextLocation[] locations, Graph graph, BitSet terminal) {
|
||||
private static TextLocation[][] propagate(TextLocation[] locations, Graph graph) {
|
||||
List<Set<TextLocation>> result = new ArrayList<>();
|
||||
boolean[] stop = new boolean[graph.size()];
|
||||
IntDeque queue = new IntArrayDeque();
|
||||
@ -338,6 +339,12 @@ public final class LocationGraphBuilder {
|
||||
nodes = distinct(exit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
super.visit(expr);
|
||||
setLocation(expr.getLocation());
|
||||
}
|
||||
|
||||
private void setNode(int node) {
|
||||
for (int prevNode : nodes) {
|
||||
builder.addEdge(prevNode, node);
|
||||
|
@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import org.teavm.ast.ArrayType;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BinaryOperation;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.ContinueStatement;
|
||||
import org.teavm.ast.Expr;
|
||||
@ -54,6 +55,7 @@ import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
@ -631,4 +633,16 @@ class StatementGenerator implements InstructionVisitor {
|
||||
stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex()));
|
||||
statements.add(stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
BoundCheckExpr expr = new BoundCheckExpr();
|
||||
expr.setLower(insn.isLower());
|
||||
expr.setIndex(Expr.var(insn.getIndex().getIndex()));
|
||||
if (insn.getArray() != null) {
|
||||
expr.setArray(Expr.var(insn.getArray().getIndex()));
|
||||
}
|
||||
expr.setLocation(insn.getLocation());
|
||||
assign(expr, insn.getReceiver());
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.BinaryOperation;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
@ -1036,6 +1037,28 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
pushLocation(expr.getLocation());
|
||||
try {
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
Expr index = resultExpr;
|
||||
|
||||
Expr array = null;
|
||||
if (expr.getArray() != null) {
|
||||
expr.getArray().acceptVisitor(this);
|
||||
array = resultExpr;
|
||||
}
|
||||
|
||||
expr.setIndex(index);
|
||||
expr.setArray(array);
|
||||
|
||||
resultExpr = expr;
|
||||
} finally {
|
||||
popLocation();
|
||||
}
|
||||
}
|
||||
|
||||
private Statement addBarrier() {
|
||||
SequentialStatement barrier = new SequentialStatement();
|
||||
resultSequence.add(barrier);
|
||||
|
@ -100,7 +100,7 @@ class ReadWriteStatsBuilder {
|
||||
static class ConstantExtractor extends AbstractInstructionVisitor {
|
||||
private Object[] constants;
|
||||
|
||||
public ConstantExtractor(Object[] constants) {
|
||||
ConstantExtractor(Object[] constants) {
|
||||
this.constants = constants;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,6 @@ public class VolatileDefinitionFinder {
|
||||
|
||||
private RecursiveVisitor handlerAnalyzer = new RecursiveVisitor() {
|
||||
StackElement surroundingTryCatches;
|
||||
StackElement handlingTryCatches;
|
||||
|
||||
@Override
|
||||
public void visit(TryCatchStatement statement) {
|
||||
|
@ -41,6 +41,7 @@ import org.teavm.ast.ArrayType;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
@ -1420,6 +1421,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||
popLocation(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
}
|
||||
|
||||
private IntrinsicContext intrinsicContext = new IntrinsicContext() {
|
||||
@Override
|
||||
public CodeWriter writer() {
|
||||
|
@ -30,6 +30,7 @@ import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.BinaryOperation;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
@ -1561,6 +1562,11 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
}
|
||||
|
||||
private class InjectorContextImpl implements InjectorContext {
|
||||
private final List<Expr> arguments;
|
||||
private final Precedence precedence = StatementRenderer.this.precedence;
|
||||
|
@ -28,6 +28,7 @@ import java.util.Set;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
@ -1365,6 +1366,11 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||
result = emptyStatement(statement.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
expr.getIndex().acceptVisitor(this);
|
||||
}
|
||||
|
||||
private WasmExpression negate(WasmExpression expr) {
|
||||
if (expr instanceof WasmIntBinary) {
|
||||
WasmIntBinary binary = (WasmIntBinary) expr;
|
||||
|
30
core/src/main/java/org/teavm/cache/AstIO.java
vendored
30
core/src/main/java/org/teavm/cache/AstIO.java
vendored
@ -29,6 +29,7 @@ import org.teavm.ast.AsyncMethodPart;
|
||||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.BinaryOperation;
|
||||
import org.teavm.ast.BlockStatement;
|
||||
import org.teavm.ast.BoundCheckExpr;
|
||||
import org.teavm.ast.BreakStatement;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
@ -665,6 +666,19 @@ public class AstIO {
|
||||
throw new IOExceptionWrapper(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckExpr expr) {
|
||||
try {
|
||||
output.writeUnsigned(expr.getArray() == null ? 27 : !expr.isLower() ? 26 : 25);
|
||||
writeExpr(expr.getIndex());
|
||||
if (expr.getArray() != null) {
|
||||
writeExpr(expr.getArray());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextLocation readLocation(VarDataInput input) throws IOException {
|
||||
@ -1024,6 +1038,22 @@ public class AstIO {
|
||||
expr.setValue(readExpr(input));
|
||||
return expr;
|
||||
}
|
||||
case 25:
|
||||
case 26: {
|
||||
BoundCheckExpr expr = new BoundCheckExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setIndex(readExpr(input));
|
||||
expr.setArray(readExpr(input));
|
||||
expr.setLower(type == 25);
|
||||
return expr;
|
||||
}
|
||||
case 27: {
|
||||
BoundCheckExpr expr = new BoundCheckExpr();
|
||||
expr.setLocation(lastReadLocation);
|
||||
expr.setIndex(readExpr(input));
|
||||
expr.setLower(true);
|
||||
return expr;
|
||||
}
|
||||
default:
|
||||
throw new RuntimeException("Unknown expression type: " + type);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class ProgramDependencyExtractor extends AbstractInstructionVisitor {
|
||||
return result;
|
||||
}
|
||||
|
||||
class AnalyzingVisitor extends AbstractInstructionVisitor {
|
||||
static class AnalyzingVisitor extends AbstractInstructionVisitor {
|
||||
Set<String> dependencies = new LinkedHashSet<>();
|
||||
@Override public void visit(GetFieldInstruction insn) {
|
||||
dependencies.add(insn.getField().getClassName());
|
||||
|
@ -48,6 +48,7 @@ import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingCondition;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
@ -738,6 +739,20 @@ public class ProgramIO {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
try {
|
||||
output.writeUnsigned(array == null ? 89 : !lower ? 88 : 87);
|
||||
output.writeUnsigned(receiver.getIndex());
|
||||
output.writeUnsigned(index.getIndex());
|
||||
if (array != null) {
|
||||
output.writeUnsigned(array.getIndex());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void write(MethodHandle handle) throws IOException {
|
||||
switch (handle.getKind()) {
|
||||
case GET_FIELD:
|
||||
@ -1205,6 +1220,18 @@ public class ProgramIO {
|
||||
}
|
||||
return insn;
|
||||
}
|
||||
case 87:
|
||||
case 88:
|
||||
case 89: {
|
||||
BoundCheckInstruction insn = new BoundCheckInstruction();
|
||||
insn.setReceiver(program.variableAt(input.readUnsigned()));
|
||||
insn.setIndex(program.variableAt(input.readUnsigned()));
|
||||
if (insnType != 89) {
|
||||
insn.setArray(program.variableAt(input.readUnsigned()));
|
||||
}
|
||||
insn.setLower(insnType != 88);
|
||||
return insn;
|
||||
}
|
||||
default:
|
||||
throw new RuntimeException("Unknown instruction type: " + insnType);
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ abstract class AbstractInstructionAnalyzer extends AbstractInstructionReader {
|
||||
static final MethodReference CLONE_METHOD = new MethodReference(Object.class, "clone", Object.class);
|
||||
private static final MethodReference NPE_INIT_METHOD = new MethodReference(NullPointerException.class,
|
||||
"<init>", void.class);
|
||||
private static final MethodReference AIOOB_INIT_METHOD = new MethodReference(ArrayIndexOutOfBoundsException.class,
|
||||
"<init>", void.class);
|
||||
static final MethodReference MONITOR_ENTER_METHOD = new MethodReference(Object.class,
|
||||
"monitorEnter", Object.class, void.class);
|
||||
static final MethodReference MONITOR_ENTER_SYNC_METHOD = new MethodReference(Object.class,
|
||||
@ -272,6 +274,14 @@ abstract class AbstractInstructionAnalyzer extends AbstractInstructionReader {
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
MethodDependency methodDep = getAnalyzer().linkMethod(AIOOB_INIT_METHOD);
|
||||
methodDep.addLocation(getCallLocation());
|
||||
methodDep.getVariable(0).propagate(getAnalyzer().getType(ArrayIndexOutOfBoundsException.class.getName()));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
protected abstract DependencyNode getNode(VariableReader variable);
|
||||
|
||||
protected abstract DependencyAnalyzer getAnalyzer();
|
||||
|
@ -213,4 +213,9 @@ public class InstructionReadVisitor implements InstructionVisitor {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
reader.monitorExit(insn.getObjectRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
reader.boundCheck(insn.getReceiver(), insn.getIndex(), insn.getArray(), insn.isLower());
|
||||
}
|
||||
}
|
||||
|
@ -791,6 +791,11 @@ public class Interpreter {
|
||||
public void monitorExit(VariableReader objectRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
variables[receiver.getIndex()] = variables[index.getIndex()];
|
||||
}
|
||||
|
||||
private Class<?> asJvmClass(ValueType type) {
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
|
@ -304,7 +304,6 @@ public class ClassInitializerAnalysis implements ClassInitializerInfo {
|
||||
static class MethodInfo {
|
||||
MethodReference method;
|
||||
boolean complete;
|
||||
Set<MethodInfo> recursiveCallers;
|
||||
Set<String> classesWithModifiedFields;
|
||||
boolean anyFieldModified;
|
||||
|
||||
|
@ -38,6 +38,7 @@ import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
@ -426,6 +427,13 @@ class NullnessInformationBuilder {
|
||||
markAsNotNull(insn.getReceiver());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
if (insn.getArray() != null) {
|
||||
markAsNotNull(insn.getArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void insertNotNullInstruction(Instruction currentInstruction, Variable var) {
|
||||
if (notNullVariables.get(var.getIndex())) {
|
||||
return;
|
||||
|
@ -189,4 +189,8 @@ public class AbstractInstructionReader implements InstructionReader {
|
||||
@Override
|
||||
public void monitorExit(VariableReader objectRef) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
}
|
||||
}
|
||||
|
@ -165,4 +165,8 @@ public abstract class AbstractInstructionVisitor implements InstructionVisitor {
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019 konsoletyper.
|
||||
*
|
||||
* 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.model.instructions;
|
||||
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Variable;
|
||||
|
||||
public class BoundCheckInstruction extends Instruction {
|
||||
private Variable receiver;
|
||||
private Variable index;
|
||||
private Variable array;
|
||||
private boolean lower;
|
||||
|
||||
public Variable getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public void setReceiver(Variable receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public Variable getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Variable index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Variable getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(Variable array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public boolean isLower() {
|
||||
return lower;
|
||||
}
|
||||
|
||||
public void setLower(boolean lower) {
|
||||
this.lower = lower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVisitor(InstructionVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
@ -103,4 +103,6 @@ public interface InstructionReader {
|
||||
void monitorEnter(VariableReader objectRef);
|
||||
|
||||
void monitorExit(VariableReader objectRef);
|
||||
|
||||
void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower);
|
||||
}
|
||||
|
@ -91,4 +91,6 @@ public interface InstructionVisitor {
|
||||
void visit(MonitorEnterInstruction insn);
|
||||
|
||||
void visit(MonitorExitInstruction insn);
|
||||
|
||||
void visit(BoundCheckInstruction insn);
|
||||
}
|
||||
|
@ -280,7 +280,6 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||
insn.setFirstOperand(program.variableAt(p));
|
||||
insn.setSecondOperand(program.variableAt(q));
|
||||
boolean commutative = false;
|
||||
boolean noReplace = false;
|
||||
String value;
|
||||
switch (insn.getOperation()) {
|
||||
case ADD:
|
||||
@ -302,7 +301,6 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||
break;
|
||||
case COMPARE:
|
||||
value = "$";
|
||||
noReplace = true;
|
||||
break;
|
||||
case AND:
|
||||
value = "&";
|
||||
|
@ -15,49 +15,29 @@
|
||||
*/
|
||||
package org.teavm.model.optimization;
|
||||
|
||||
import org.teavm.model.InvokeDynamicInstruction;
|
||||
import org.teavm.model.analysis.NullnessInformation;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.GetElementInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
import org.teavm.model.instructions.InstructionVisitor;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
import org.teavm.model.instructions.JumpInstruction;
|
||||
import org.teavm.model.instructions.LongConstantInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
import org.teavm.model.instructions.MonitorExitInstruction;
|
||||
import org.teavm.model.instructions.NegateInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.NullConstantInstruction;
|
||||
import org.teavm.model.instructions.NumericOperandType;
|
||||
import org.teavm.model.instructions.PutElementInstruction;
|
||||
import org.teavm.model.instructions.PutFieldInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.instructions.SwitchInstruction;
|
||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||
|
||||
public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
public class LoopInvariantAnalyzer extends AbstractInstructionVisitor {
|
||||
private NullnessInformation nullness;
|
||||
public boolean canMove;
|
||||
public boolean constant;
|
||||
@ -73,10 +53,6 @@ public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
sideEffect = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
constant = true;
|
||||
@ -146,50 +122,6 @@ public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryBranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(JumpInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExitInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaiseInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructMultiArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetFieldInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutFieldInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ArrayLengthInstruction insn) {
|
||||
canMove = true;
|
||||
@ -198,10 +130,6 @@ public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CloneArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayInstruction insn) {
|
||||
canMove = true;
|
||||
@ -210,31 +138,11 @@ public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeDynamicInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IsInstanceInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
canMove = true;
|
||||
@ -242,12 +150,4 @@ public class LoopInvariantAnalyzer implements InstructionVisitor {
|
||||
sideEffect = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorEnterInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ public class ScalarReplacement implements MethodOptimization {
|
||||
private EscapeAnalysis escapeAnalysis;
|
||||
private List<Map<FieldReference, Variable>> fieldMappings;
|
||||
|
||||
public ScalarReplacementVisitor(EscapeAnalysis escapeAnalysis,
|
||||
ScalarReplacementVisitor(EscapeAnalysis escapeAnalysis,
|
||||
List<Map<FieldReference, Variable>> fieldMappings) {
|
||||
this.escapeAnalysis = escapeAnalysis;
|
||||
this.fieldMappings = fieldMappings;
|
||||
|
@ -27,6 +27,7 @@ import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
@ -260,5 +261,10 @@ public class UnusedVariableElimination implements MethodOptimization {
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
requestUsage(insn.getReceiver());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
requestUsage(insn.getReceiver());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
@ -61,10 +62,10 @@ public final class VariableUsageGraphBuilder {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static class InstructionAnalyzer extends AbstractInstructionVisitor {
|
||||
static class InstructionAnalyzer extends AbstractInstructionVisitor {
|
||||
private GraphBuilder builder;
|
||||
|
||||
public InstructionAnalyzer(GraphBuilder builder) {
|
||||
InstructionAnalyzer(GraphBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@ -150,5 +151,14 @@ public final class VariableUsageGraphBuilder {
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
if (insn.getArray() != null) {
|
||||
use(insn.getReceiver(), insn.getIndex(), insn.getArray());
|
||||
} else {
|
||||
use(insn.getReceiver(), insn.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -544,4 +544,15 @@ class InstructionStringifier implements InstructionReader {
|
||||
public void monitorExit(VariableReader objectRef) {
|
||||
append("monitorExit ").appendLocalVar(objectRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
appendLocalVar(receiver).append(" = boundCheck ").appendLocalVar(index);
|
||||
if (array != null) {
|
||||
append(" upper ").appendLocalVar(array);
|
||||
}
|
||||
if (lower) {
|
||||
append(" lower");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class ListingLexer {
|
||||
private int index = -1;
|
||||
private int tokenStart;
|
||||
|
||||
public ListingLexer(Reader reader) {
|
||||
ListingLexer(Reader reader) {
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
@ -34,6 +34,14 @@ class ListingLexer {
|
||||
return token;
|
||||
}
|
||||
|
||||
public boolean tryConsumeIdentifier(String value) throws IOException, ListingParseException {
|
||||
if (token == ListingToken.IDENTIFIER && value.equals(tokenValue)) {
|
||||
nextToken();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getTokenValue() {
|
||||
return tokenValue;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingCondition;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
@ -431,6 +432,19 @@ public class ListingParser {
|
||||
currentBlock.setExceptionVariable(receiver);
|
||||
break;
|
||||
}
|
||||
case "boundCheck": {
|
||||
lexer.nextToken();
|
||||
BoundCheckInstruction insn = new BoundCheckInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
insn.setIndex(expectVariable());
|
||||
if (lexer.tryConsumeIdentifier("upper")) {
|
||||
insn.setArray(expectVariable());
|
||||
}
|
||||
if (lexer.tryConsumeIdentifier("lower")) {
|
||||
insn.setLower(true);
|
||||
}
|
||||
addInstruction(insn);
|
||||
}
|
||||
default:
|
||||
unexpected();
|
||||
break;
|
||||
|
@ -218,4 +218,9 @@ public class DefinitionExtractor implements InstructionVisitor {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
definedVariables = new Variable[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
definedVariables = new Variable[] { insn.getReceiver() };
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingCondition;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
@ -479,4 +480,17 @@ public class InstructionCopyReader implements InstructionReader {
|
||||
copy = insnCopy;
|
||||
copy.setLocation(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
BoundCheckInstruction insnCopy = new BoundCheckInstruction();
|
||||
insnCopy.setReceiver(copyVar(receiver));
|
||||
insnCopy.setIndex(copyVar(index));
|
||||
if (array != null) {
|
||||
insnCopy.setArray(copyVar(array));
|
||||
}
|
||||
insnCopy.setLower(lower);
|
||||
copy = insnCopy;
|
||||
copy.setLocation(location);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
@ -304,4 +305,13 @@ public class InstructionVariableMapper extends AbstractInstructionVisitor {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
insn.setObjectRef(map(insn.getObjectRef()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
insn.setReceiver(map(insn.getReceiver()));
|
||||
insn.setIndex(map(insn.getIndex()));
|
||||
if (insn.getArray() != null) {
|
||||
insn.setArray(map(insn.getArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +42,12 @@ import org.teavm.model.Program;
|
||||
import org.teavm.model.Sigma;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
@ -580,11 +582,7 @@ public class PhiUpdater {
|
||||
return mappedVar;
|
||||
}
|
||||
|
||||
private InstructionVisitor consumer = new InstructionVisitor() {
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
private InstructionVisitor consumer = new AbstractInstructionVisitor() {
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
insn.setReceiver(define(insn.getReceiver()));
|
||||
@ -649,11 +647,6 @@ public class PhiUpdater {
|
||||
insn.setFirstOperand(use(insn.getFirstOperand()));
|
||||
insn.setSecondOperand(use(insn.getSecondOperand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(JumpInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchInstruction insn) {
|
||||
insn.setCondition(use(insn.getCondition()));
|
||||
@ -788,10 +781,6 @@ public class PhiUpdater {
|
||||
insn.setReceiver(define(insn.getReceiver()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
insn.setValue(use(insn.getValue()));
|
||||
@ -807,6 +796,15 @@ public class PhiUpdater {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
insn.setObjectRef(use(insn.getObjectRef()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
insn.setIndex(use(insn.getIndex()));
|
||||
if (insn.getArray() != null) {
|
||||
insn.setArray(use(insn.getArray()));
|
||||
}
|
||||
insn.setReceiver(define(insn.getReceiver()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -216,4 +216,9 @@ public class TransitionExtractor implements InstructionVisitor {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
targets = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
targets = null;
|
||||
}
|
||||
}
|
||||
|
@ -322,6 +322,11 @@ public class TypeInferer {
|
||||
public void arrayLength(VariableReader receiver, VariableReader array) {
|
||||
types[receiver.getIndex()] = new InferenceType(InferenceKind.INT, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
types[receiver.getIndex()] = new InferenceType(InferenceKind.INT, 0);
|
||||
}
|
||||
};
|
||||
|
||||
enum InferenceKind {
|
||||
|
@ -225,4 +225,13 @@ public class UsageExtractor implements InstructionVisitor {
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
usedVariables = new Variable[] {insn.getObjectRef() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BoundCheckInstruction insn) {
|
||||
if (insn.getArray() != null) {
|
||||
usedVariables = new Variable[] { insn.getArray(), insn.getIndex() };
|
||||
} else {
|
||||
usedVariables = new Variable[] { insn.getIndex() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.BoundCheckInstruction;
|
||||
import org.teavm.model.instructions.BranchingCondition;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
@ -1169,5 +1170,17 @@ public class CompositeMethodGenerator {
|
||||
insn.setObjectRef(var(objectRef));
|
||||
add(insn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boundCheck(VariableReader receiver, VariableReader index, VariableReader array, boolean lower) {
|
||||
BoundCheckInstruction instruction = new BoundCheckInstruction();
|
||||
instruction.setReceiver(var(receiver));
|
||||
instruction.setIndex(var(index));
|
||||
if (array != null) {
|
||||
instruction.setArray(var(array));
|
||||
}
|
||||
instruction.setLower(lower);
|
||||
add(instruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user