mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Eliminate exception joint in favour of phi functions with multiple inputs per source basic block
This commit is contained in:
parent
9532f9a32b
commit
ff059919a7
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.ast.optimization;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import org.teavm.ast.AsyncMethodNode;
|
||||
import org.teavm.ast.AsyncMethodPart;
|
||||
import org.teavm.ast.RegularMethodNode;
|
||||
|
|
|
@ -78,14 +78,6 @@ class ReadWriteStatsBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
writes[joint.getReceiver().getIndex()] += joint.getSourceVariables().size();
|
||||
for (Variable var : joint.getSourceVariables()) {
|
||||
reads[var.getIndex()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int succ : dom.outgoingEdges(node)) {
|
||||
stack.push(succ);
|
||||
|
|
|
@ -63,14 +63,6 @@ public class ProgramIO {
|
|||
data.writeInt(tryCatch.getExceptionType() != null ? symbolTable.lookup(
|
||||
tryCatch.getExceptionType()) : -1);
|
||||
data.writeShort(tryCatch.getHandler().getIndex());
|
||||
data.writeShort(tryCatch.getJoints().size());
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
data.writeShort(joint.getReceiver().getIndex());
|
||||
data.writeShort(joint.getSourceVariables().size());
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
data.writeShort(sourceVar.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
TextLocation location = null;
|
||||
InstructionWriter insnWriter = new InstructionWriter(data);
|
||||
|
@ -141,17 +133,6 @@ public class ProgramIO {
|
|||
}
|
||||
tryCatch.setHandler(program.basicBlockAt(data.readShort()));
|
||||
|
||||
int jointCount = data.readShort();
|
||||
for (int k = 0; k < jointCount; ++k) {
|
||||
TryCatchJoint joint = new TryCatchJoint();
|
||||
joint.setReceiver(program.variableAt(data.readShort()));
|
||||
int jointSourceCount = data.readShort();
|
||||
for (int m = 0; m < jointSourceCount; ++m) {
|
||||
joint.getSourceVariables().add(program.variableAt(data.readShort()));
|
||||
}
|
||||
tryCatch.getJoints().add(joint);
|
||||
}
|
||||
|
||||
block.getTryCatchBlocks().add(tryCatch);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,13 +64,6 @@ public class DataFlowGraphBuilder extends AbstractInstructionReader {
|
|||
builder.addEdge(from, to);
|
||||
}
|
||||
}
|
||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
for (VariableReader sourceVar : joint.readSourceVariables()) {
|
||||
builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
block.readAllInstructions(this);
|
||||
}
|
||||
Graph graph = builder.build();
|
||||
|
@ -221,13 +214,6 @@ public class DataFlowGraphBuilder extends AbstractInstructionReader {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDynamic(VariableReader receiver, VariableReader instance, MethodDescriptor method,
|
||||
List<? extends VariableReader> arguments, MethodHandle bootstrapMethod,
|
||||
List<RuntimeConstant> bootstrapArguments) {
|
||||
// Should be eliminated by bootstrap method substitutor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||
connect(value.getIndex(), receiver.getIndex());
|
||||
|
|
|
@ -44,7 +44,6 @@ import org.teavm.model.Program;
|
|||
import org.teavm.model.RuntimeConstant;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlockReader;
|
||||
import org.teavm.model.TryCatchJointReader;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.VariableReader;
|
||||
import org.teavm.model.emit.ProgramEmitter;
|
||||
|
@ -142,19 +141,6 @@ class DependencyGraphBuilder {
|
|||
if (tryCatch.getExceptionType() != null) {
|
||||
dependencyChecker.linkClass(tryCatch.getExceptionType(), new CallLocation(caller.getMethod()));
|
||||
}
|
||||
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
DependencyNode receiverNode = nodes[joint.getReceiver().getIndex()];
|
||||
if (receiverNode == null) {
|
||||
continue;
|
||||
}
|
||||
for (VariableReader source : joint.readSourceVariables()) {
|
||||
DependencyNode sourceNode = nodes[source.getIndex()];
|
||||
if (sourceNode != null) {
|
||||
sourceNode.connect(receiverNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,10 +20,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class Phi implements PhiReader {
|
||||
private BasicBlock basicBlock;
|
||||
private Variable receiver;
|
||||
|
|
|
@ -65,6 +65,35 @@ public class Program implements ProgramReader {
|
|||
return basicBlocks;
|
||||
}
|
||||
|
||||
public void rearrangeBasicBlocks(List<BasicBlock> basicBlocks) {
|
||||
if (!isPacked()) {
|
||||
throw new IllegalStateException("This operation is not supported on unpacked programs");
|
||||
}
|
||||
|
||||
if (basicBlocks.size() != this.basicBlocks.size()) {
|
||||
throw new IllegalArgumentException("New list of basic blocks has wrong size ("
|
||||
+ basicBlocks.size() + ", expected " + basicBlockCount() + ")");
|
||||
}
|
||||
|
||||
boolean[] indexes = new boolean[basicBlocks.size()];
|
||||
for (BasicBlock block : basicBlocks) {
|
||||
if (block.getProgram() != this) {
|
||||
throw new IllegalArgumentException("The list of basic blocks contains a basic block from "
|
||||
+ "another program");
|
||||
}
|
||||
if (indexes[block.getIndex()]) {
|
||||
throw new IllegalArgumentException("The list of basic blocks contains same basic block twice");
|
||||
}
|
||||
indexes[block.getIndex()] = true;
|
||||
}
|
||||
|
||||
this.basicBlocks.clear();
|
||||
this.basicBlocks.addAll(basicBlocks);
|
||||
for (int i = 0; i < this.basicBlocks.size(); ++i) {
|
||||
this.basicBlocks.get(i).setIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteVariable(int index) {
|
||||
Variable variable = variables.get(index);
|
||||
if (variable == null) {
|
||||
|
|
|
@ -15,64 +15,10 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TryCatchBlock implements TryCatchBlockReader {
|
||||
BasicBlock protectedBlock;
|
||||
private BasicBlock handler;
|
||||
private String exceptionType;
|
||||
private List<TryCatchJoint> joints = new ArrayList<>();
|
||||
private List<TryCatchJointReader> immutableJoints;
|
||||
|
||||
private List<TryCatchJoint> safeJoints = new AbstractList<TryCatchJoint>() {
|
||||
@Override
|
||||
public TryCatchJoint get(int index) {
|
||||
return joints.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return joints.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, TryCatchJoint e) {
|
||||
if (e.getBlock() != null) {
|
||||
throw new IllegalArgumentException("This joint is already in some basic block");
|
||||
}
|
||||
e.block = TryCatchBlock.this;
|
||||
joints.add(index, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TryCatchJoint set(int index, TryCatchJoint element) {
|
||||
if (element.block != null) {
|
||||
throw new IllegalArgumentException("This phi is already in some basic block");
|
||||
}
|
||||
TryCatchJoint oldJoint = joints.get(index);
|
||||
oldJoint.block = null;
|
||||
element.block = TryCatchBlock.this;
|
||||
return joints.set(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TryCatchJoint remove(int index) {
|
||||
TryCatchJoint joint = joints.remove(index);
|
||||
joint.block = null;
|
||||
return joint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
for (TryCatchJoint joint : joints) {
|
||||
joint.block = null;
|
||||
}
|
||||
joints.clear();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public BasicBlock getHandler() {
|
||||
|
@ -96,16 +42,4 @@ public class TryCatchBlock implements TryCatchBlockReader {
|
|||
public BasicBlock getProtectedBlock() {
|
||||
return protectedBlock;
|
||||
}
|
||||
|
||||
public List<TryCatchJoint> getJoints() {
|
||||
return safeJoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TryCatchJointReader> readJoints() {
|
||||
if (immutableJoints == null) {
|
||||
immutableJoints = Collections.unmodifiableList(safeJoints);
|
||||
}
|
||||
return immutableJoints;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,10 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TryCatchBlockReader {
|
||||
BasicBlockReader getProtectedBlock();
|
||||
|
||||
BasicBlockReader getHandler();
|
||||
|
||||
String getExceptionType();
|
||||
|
||||
List<TryCatchJointReader> readJoints();
|
||||
}
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TryCatchJoint implements TryCatchJointReader {
|
||||
private List<Variable> sourceVariables = new ArrayList<>();
|
||||
private List<VariableReader> readonlySourceVariables;
|
||||
private Variable receiver;
|
||||
TryCatchBlock block;
|
||||
|
||||
@Override
|
||||
public List<VariableReader> readSourceVariables() {
|
||||
if (readonlySourceVariables == null) {
|
||||
readonlySourceVariables = Collections.unmodifiableList(sourceVariables);
|
||||
}
|
||||
return readonlySourceVariables;
|
||||
}
|
||||
|
||||
public List<Variable> getSourceVariables() {
|
||||
return sourceVariables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public void setReceiver(Variable receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public TryCatchBlock getBlock() {
|
||||
return block;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TryCatchJointReader {
|
||||
List<VariableReader> readSourceVariables();
|
||||
|
||||
VariableReader getReceiver();
|
||||
|
||||
TryCatchBlockReader getBlock();
|
||||
}
|
|
@ -24,8 +24,6 @@ import org.teavm.model.Instruction;
|
|||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.util.DefinitionExtractor;
|
||||
import org.teavm.model.util.InstructionVariableMapper;
|
||||
|
@ -57,7 +55,6 @@ public class NullnessInformation {
|
|||
|
||||
public void dispose() {
|
||||
Set<Phi> phisToRemove = new HashSet<>(phiUpdater.getSynthesizedPhis());
|
||||
Set<TryCatchJoint> jointsToRemove = new HashSet<>(phiUpdater.getSynthesizedJoints());
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
InstructionVariableMapper variableMapper = new InstructionVariableMapper(var -> {
|
||||
int source = phiUpdater.getSourceVariable(var.getIndex());
|
||||
|
@ -65,9 +62,6 @@ public class NullnessInformation {
|
|||
});
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
block.getPhis().removeIf(phisToRemove::contains);
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
tryCatch.getJoints().removeIf(jointsToRemove::contains);
|
||||
}
|
||||
for (Instruction insn : block) {
|
||||
insn.acceptVisitor(defExtractor);
|
||||
if (Arrays.stream(defExtractor.getDefinedVariables())
|
||||
|
@ -78,8 +72,18 @@ public class NullnessInformation {
|
|||
}
|
||||
}
|
||||
variableMapper.applyToPhis(block);
|
||||
variableMapper.applyToTryCatchBlocks(block);
|
||||
if (block.getExceptionVariable() != null) {
|
||||
block.setExceptionVariable(variableMapper.map(block.getExceptionVariable()));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
int sourceVar = phiUpdater.getSourceVariable(i);
|
||||
if (sourceVar >= 0 && sourceVar != i) {
|
||||
program.deleteVariable(i);
|
||||
}
|
||||
}
|
||||
program.pack();
|
||||
}
|
||||
|
||||
public static NullnessInformation build(Program program, MethodDescriptor methodDescriptor) {
|
||||
|
|
|
@ -33,8 +33,6 @@ import org.teavm.model.Instruction;
|
|||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
|
@ -126,13 +124,6 @@ class NullnessInformationBuilder {
|
|||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Instruction instruction : block) {
|
||||
if (instruction instanceof AssignInstruction) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.model.lowlevel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.interop.StaticInit;
|
||||
import org.teavm.interop.Structure;
|
||||
|
@ -26,7 +25,6 @@ import org.teavm.model.ClassReaderSource;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
|
||||
public class ClassInitializerEliminator {
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.model.lowlevel;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.common.DominatorTree;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphUtils;
|
||||
|
@ -29,7 +30,6 @@ import org.teavm.model.Phi;
|
|||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||
|
@ -64,7 +64,6 @@ public class ExceptionHandlingShadowStackContributor {
|
|||
private Program program;
|
||||
private DominatorTree dom;
|
||||
private BasicBlock[] variableDefinitionPlaces;
|
||||
private Phi[] jointPhis;
|
||||
private boolean hasExceptionHandlers;
|
||||
|
||||
public ExceptionHandlingShadowStackContributor(ManagedMethodRepository managedMethodRepository,
|
||||
|
@ -77,7 +76,6 @@ public class ExceptionHandlingShadowStackContributor {
|
|||
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||
dom = GraphUtils.buildDominatorTree(cfg);
|
||||
variableDefinitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program);
|
||||
jointPhis = new Phi[program.variableCount()];
|
||||
}
|
||||
|
||||
public boolean contribute() {
|
||||
|
@ -126,17 +124,26 @@ public class ExceptionHandlingShadowStackContributor {
|
|||
int[] currentJointSources = new int[program.variableCount()];
|
||||
int[] jointReceiverMap = new int[program.variableCount()];
|
||||
Arrays.fill(currentJointSources, -1);
|
||||
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
for (Phi phi : tryCatch.getHandler().getPhis()) {
|
||||
List<Variable> sourceVariables = phi.getIncomings().stream()
|
||||
.filter(incoming -> incoming.getSource() == tryCatch.getProtectedBlock())
|
||||
.map(incoming -> incoming.getValue())
|
||||
.collect(Collectors.toList());
|
||||
if (sourceVariables.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Variable sourceVar : sourceVariables) {
|
||||
BasicBlock sourceVarDefinedAt = variableDefinitionPlaces[sourceVar.getIndex()];
|
||||
if (dom.dominates(sourceVarDefinedAt.getIndex(), block.getIndex())) {
|
||||
currentJointSources[joint.getReceiver().getIndex()] = sourceVar.getIndex();
|
||||
currentJointSources[phi.getReceiver().getIndex()] = sourceVar.getIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
jointReceiverMap[sourceVar.getIndex()] = joint.getReceiver().getIndex();
|
||||
for (Variable sourceVar : sourceVariables) {
|
||||
jointReceiverMap[sourceVar.getIndex()] = phi.getReceiver().getIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,13 +288,17 @@ public class ExceptionHandlingShadowStackContributor {
|
|||
switchInsn.getEntries().add(catchEntry);
|
||||
}
|
||||
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
Phi phi = getJointPhi(joint);
|
||||
Incoming incoming = new Incoming();
|
||||
incoming.setSource(block);
|
||||
int value = currentJointSources[joint.getReceiver().getIndex()];
|
||||
incoming.setValue(program.variableAt(value));
|
||||
phi.getIncomings().add(incoming);
|
||||
for (Phi phi : tryCatch.getHandler().getPhis()) {
|
||||
int value = currentJointSources[phi.getReceiver().getIndex()];
|
||||
if (value < 0) {
|
||||
continue;
|
||||
}
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
if (incoming.getValue().getIndex() == value) {
|
||||
incoming.setSource(block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,18 +338,6 @@ public class ExceptionHandlingShadowStackContributor {
|
|||
return defaultExceptionHandler;
|
||||
}
|
||||
|
||||
private Phi getJointPhi(TryCatchJoint joint) {
|
||||
Phi phi = jointPhis[joint.getReceiver().getIndex()];
|
||||
if (phi == null) {
|
||||
phi = new Phi();
|
||||
phi.setReceiver(joint.getReceiver());
|
||||
BasicBlock handler = program.basicBlockAt(joint.getBlock().getHandler().getIndex());
|
||||
handler.getPhis().add(phi);
|
||||
jointPhis[joint.getReceiver().getIndex()] = phi;
|
||||
}
|
||||
return phi;
|
||||
}
|
||||
|
||||
private Variable createReturnValueInstructions(BasicBlock block) {
|
||||
ValueType returnType = method.getReturnType();
|
||||
if (returnType == ValueType.VOID) {
|
||||
|
|
|
@ -28,8 +28,6 @@ import org.teavm.model.Incoming;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.InvokeDynamicInstruction;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
|
@ -164,14 +162,6 @@ public class GlobalValueNumbering implements MethodOptimization {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
||||
int sourceVar = map[joint.getSourceVariables().get(i).getIndex()];
|
||||
joint.getSourceVariables().set(i, program.variableAt(sourceVar));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Incoming incoming : outgoings.get(v)) {
|
||||
int value = map[incoming.getValue().getIndex()];
|
||||
incoming.setValue(program.variableAt(value));
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.analysis.NullnessInformation;
|
||||
import org.teavm.model.util.BasicBlockMapper;
|
||||
|
@ -345,13 +344,6 @@ class LoopInversionImpl {
|
|||
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||
tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler)));
|
||||
targetBlock.getTryCatchBlocks().add(tryCatchCopy);
|
||||
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
TryCatchJoint jointCopy = new TryCatchJoint();
|
||||
jointCopy.setReceiver(joint.getReceiver());
|
||||
jointCopy.getSourceVariables().addAll(joint.getSourceVariables());
|
||||
tryCatchCopy.getJoints().add(jointCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ import org.teavm.model.InvokeDynamicInstruction;
|
|||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
|
@ -105,15 +103,6 @@ public class UnusedVariableElimination implements MethodOptimization {
|
|||
}
|
||||
}
|
||||
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (int j = 0; j < tryCatch.getJoints().size(); ++j) {
|
||||
TryCatchJoint joint = tryCatch.getJoints().get(j);
|
||||
if (!used[joint.getReceiver().getIndex()]) {
|
||||
tryCatch.getJoints().remove(j--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < block.getPhis().size(); ++j) {
|
||||
Phi phi = block.getPhis().get(j);
|
||||
if (!used[phi.getReceiver().getIndex()]) {
|
||||
|
|
|
@ -17,8 +17,28 @@ package org.teavm.model.optimization;
|
|||
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphBuilder;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.*;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
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.BinaryInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.CastIntegerInstruction;
|
||||
import org.teavm.model.instructions.CastNumberInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.GetElementInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
import org.teavm.model.instructions.NegateInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||
|
||||
public final class VariableUsageGraphBuilder {
|
||||
private VariableUsageGraphBuilder() {
|
||||
|
@ -37,18 +57,11 @@ public final class VariableUsageGraphBuilder {
|
|||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static class InstructionAnalyzer implements InstructionVisitor {
|
||||
private static class InstructionAnalyzer extends AbstractInstructionVisitor {
|
||||
private GraphBuilder builder;
|
||||
|
||||
public InstructionAnalyzer(GraphBuilder builder) {
|
||||
|
@ -61,38 +74,6 @@ public final class VariableUsageGraphBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IntegerConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LongConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FloatConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DoubleConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getFirstOperand(), insn.getSecondOperand());
|
||||
|
@ -123,39 +104,11 @@ public final class VariableUsageGraphBuilder {
|
|||
use(insn.getReceiver(), insn.getValue());
|
||||
}
|
||||
|
||||
@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) {
|
||||
use(insn.getReceiver(), insn.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructMultiArrayInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getDimensions().toArray(new Variable[0]));
|
||||
|
@ -168,10 +121,6 @@ public final class VariableUsageGraphBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutFieldInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ArrayLengthInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getArray());
|
||||
|
@ -192,40 +141,14 @@ public final class VariableUsageGraphBuilder {
|
|||
use(insn.getReceiver(), insn.getArray(), insn.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeDynamicInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IsInstanceInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
use(insn.getReceiver(), insn.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorEnterInstruction insn) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,14 @@ package org.teavm.model.text;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.BasicBlockReader;
|
||||
import org.teavm.model.IncomingReader;
|
||||
import org.teavm.model.InstructionIterator;
|
||||
import org.teavm.model.PhiReader;
|
||||
import org.teavm.model.ProgramReader;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlockReader;
|
||||
import org.teavm.model.VariableReader;
|
||||
|
||||
public class ListingBuilder {
|
||||
public String buildListing(ProgramReader program, String prefix) {
|
||||
|
@ -87,14 +93,6 @@ public class ListingBuilder {
|
|||
}
|
||||
sb.append(" goto $").append(tryCatch.getHandler().getIndex());
|
||||
sb.append("\n");
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
sb.append(" @").append(stringifier.getVariableLabel(joint.getReceiver().getIndex()))
|
||||
.append(" := ephi ");
|
||||
sb.append(joint.readSourceVariables().stream()
|
||||
.map(sourceVar -> "@" + stringifier.getVariableLabel(sourceVar.getIndex()))
|
||||
.collect(Collectors.joining(", ")));
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.teavm.model.Phi;
|
|||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ArrayElementType;
|
||||
|
@ -89,9 +88,9 @@ public class ListingParser {
|
|||
private Map<String, BasicBlock> blockMap;
|
||||
private Map<String, Integer> blockFirstOccurrence;
|
||||
private Set<String> declaredBlocks = new HashSet<>();
|
||||
private List<BasicBlock> orderedBlocks = new ArrayList<>();
|
||||
private TextLocation currentLocation;
|
||||
private BasicBlock currentBlock;
|
||||
private TryCatchBlock currentTryCatch;
|
||||
|
||||
public Program parse(Reader reader) throws IOException, ListingParseException {
|
||||
try {
|
||||
|
@ -114,6 +113,9 @@ public class ListingParser {
|
|||
throw new ListingParseException("Block not defined: " + blockName, blockIndex);
|
||||
}
|
||||
|
||||
program.pack();
|
||||
program.rearrangeBasicBlocks(orderedBlocks);
|
||||
|
||||
return program;
|
||||
} finally {
|
||||
program = null;
|
||||
|
@ -177,7 +179,7 @@ public class ListingParser {
|
|||
b.setLabel(k);
|
||||
return b;
|
||||
});
|
||||
currentTryCatch = null;
|
||||
orderedBlocks.add(currentBlock);
|
||||
|
||||
currentLocation = null;
|
||||
do {
|
||||
|
@ -361,10 +363,6 @@ public class ListingParser {
|
|||
lexer.nextToken();
|
||||
parsePhi(receiver);
|
||||
break;
|
||||
case "ephi":
|
||||
lexer.nextToken();
|
||||
parseExceptionPhi(receiver);
|
||||
break;
|
||||
case "classOf":
|
||||
lexer.nextToken();
|
||||
parseClassLiteral(receiver);
|
||||
|
@ -593,24 +591,6 @@ public class ListingParser {
|
|||
currentBlock.getPhis().add(phi);
|
||||
}
|
||||
|
||||
private void parseExceptionPhi(Variable receiver) throws IOException, ListingParseException {
|
||||
int phiStart = lexer.getIndex();
|
||||
|
||||
TryCatchJoint joint = new TryCatchJoint();
|
||||
joint.setReceiver(receiver);
|
||||
joint.getSourceVariables().add(expectVariable());
|
||||
while (lexer.getToken() == ListingToken.COMMA) {
|
||||
lexer.nextToken();
|
||||
joint.getSourceVariables().add(expectVariable());
|
||||
}
|
||||
|
||||
if (currentTryCatch == null) {
|
||||
throw new ListingParseException("Exception phi must appear right after catch block", phiStart);
|
||||
}
|
||||
|
||||
currentTryCatch.getJoints().add(joint);
|
||||
}
|
||||
|
||||
private void parseClassLiteral(Variable receiver) throws IOException, ListingParseException {
|
||||
ValueType type = expectValueType();
|
||||
ClassConstantInstruction insn = new ClassConstantInstruction();
|
||||
|
@ -792,7 +772,6 @@ public class ListingParser {
|
|||
}
|
||||
expectKeyword("goto");
|
||||
tryCatch.setHandler(expectBlock());
|
||||
currentTryCatch = tryCatch;
|
||||
currentBlock.getTryCatchBlocks().add(tryCatch);
|
||||
}
|
||||
|
||||
|
@ -1170,7 +1149,6 @@ public class ListingParser {
|
|||
}
|
||||
|
||||
private void addInstruction(Instruction instruction) throws ListingParseException {
|
||||
currentTryCatch = null;
|
||||
instruction.setLocation(currentLocation);
|
||||
currentBlock.add(instruction);
|
||||
}
|
||||
|
|
|
@ -21,12 +21,43 @@ import org.teavm.model.Incoming;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.InvokeDynamicInstruction;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.*;
|
||||
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.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.ExitInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.GetElementInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
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.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 InstructionVariableMapper implements InstructionVisitor {
|
||||
public class InstructionVariableMapper extends AbstractInstructionVisitor {
|
||||
private final Function<Variable, Variable> f;
|
||||
|
||||
public InstructionVariableMapper(Function<Variable, Variable> f) {
|
||||
|
@ -40,7 +71,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
|||
|
||||
applyToInstructions(block);
|
||||
applyToPhis(block);
|
||||
applyToTryCatchBlocks(block);
|
||||
}
|
||||
|
||||
public void applyToInstructions(BasicBlock block) {
|
||||
|
@ -58,26 +88,10 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
public void applyToTryCatchBlocks(BasicBlock block) {
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
joint.setReceiver(map(joint.getReceiver()));
|
||||
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
||||
Variable var = joint.getSourceVariables().get(i);
|
||||
joint.getSourceVariables().set(i, map(var));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Variable map(Variable var) {
|
||||
public Variable map(Variable var) {
|
||||
return f.apply(var);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
insn.setReceiver(map(insn.getReceiver()));
|
||||
|
@ -161,10 +175,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
|||
insn.setSecondOperand(map(insn.getSecondOperand()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(JumpInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchInstruction insn) {
|
||||
insn.setCondition(map(insn.getCondition()));
|
||||
|
@ -281,10 +291,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
|||
insn.setValue(map(insn.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
insn.setReceiver(map(insn.getReceiver()));
|
||||
|
|
|
@ -52,15 +52,6 @@ class InterferenceGraphBuilder {
|
|||
live.add(nodes.get(outgoing.getValue().getIndex()));
|
||||
}
|
||||
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
live.add(nodes.get(sourceVar.getIndex()));
|
||||
}
|
||||
live.remove(nodes.get(joint.getReceiver().getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
for (Instruction insn = block.getLastInstruction(); insn != null; insn = insn.getPrevious()) {
|
||||
insn.acceptVisitor(useExtractor);
|
||||
insn.acceptVisitor(defExtractor);
|
||||
|
|
|
@ -21,7 +21,12 @@ import java.util.ArrayDeque;
|
|||
import java.util.BitSet;
|
||||
import java.util.Deque;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
|
||||
public class LivenessAnalyzer {
|
||||
private BitSet[] liveVars;
|
||||
|
@ -70,18 +75,6 @@ public class LivenessAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
definitions[joint.getReceiver().getIndex()] = i;
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
Task task = new Task();
|
||||
task.block = i;
|
||||
task.var = sourceVar.getIndex();
|
||||
stack.push(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Phi phi : block.getPhis()) {
|
||||
definitions[phi.getReceiver().getIndex()] = i;
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
|
|
|
@ -27,12 +27,7 @@ import java.util.Arrays;
|
|||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.teavm.common.DominatorTree;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphUtils;
|
||||
|
@ -44,7 +39,6 @@ import org.teavm.model.InvokeDynamicInstruction;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
|
@ -92,21 +86,17 @@ public class PhiUpdater {
|
|||
private int[][] domFrontiers;
|
||||
private Variable[] variableMap;
|
||||
private boolean[] variableDefined;
|
||||
private List<List<Variable>> definedVersions = new ArrayList<>();
|
||||
private BasicBlock currentBlock;
|
||||
private TryCatchBlock currentTryCatch;
|
||||
private Phi[][] phiMap;
|
||||
private int[][] phiIndexMap;
|
||||
private Map<TryCatchBlock, Map<Variable, TryCatchJoint>> jointMap = new HashMap<>();
|
||||
private List<List<Phi>> synthesizedPhisByBlock = new ArrayList<>();
|
||||
private IntObjectMap<Phi> phisByReceiver = new IntObjectOpenHashMap<>();
|
||||
private IntObjectMap<TryCatchJoint> jointsByReceiver = new IntObjectOpenHashMap<>();
|
||||
private BitSet usedPhis = new BitSet();
|
||||
private List<List<List<TryCatchJoint>>> synthesizedJointsByBlock = new ArrayList<>();
|
||||
private Variable[] originalExceptionVariables;
|
||||
private boolean[] usedDefinitions;
|
||||
private IntegerArray variableToSourceMap = new IntegerArray(10);
|
||||
private List<Phi> synthesizedPhis = new ArrayList<>();
|
||||
private List<TryCatchJoint> synthesizedJoints = new ArrayList<>();
|
||||
|
||||
public int getSourceVariable(int var) {
|
||||
if (var >= variableToSourceMap.size()) {
|
||||
|
@ -119,17 +109,12 @@ public class PhiUpdater {
|
|||
return synthesizedPhis;
|
||||
}
|
||||
|
||||
public List<TryCatchJoint> getSynthesizedJoints() {
|
||||
return synthesizedJoints;
|
||||
}
|
||||
|
||||
public void updatePhis(Program program, Variable[] arguments) {
|
||||
if (program.basicBlockCount() == 0) {
|
||||
return;
|
||||
}
|
||||
this.program = program;
|
||||
phisByReceiver.clear();
|
||||
jointsByReceiver.clear();
|
||||
cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||
domFrontiers = new int[cfg.size()][];
|
||||
|
@ -141,12 +126,14 @@ public class PhiUpdater {
|
|||
variableMap[i] = arguments[i];
|
||||
usedDefinitions[i] = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
variableToSourceMap.add(-1);
|
||||
}
|
||||
definedVersions.addAll(Collections.nCopies(program.variableCount(), null));
|
||||
|
||||
phiMap = new Phi[program.basicBlockCount()][];
|
||||
phiIndexMap = new int[program.basicBlockCount()][];
|
||||
jointMap.clear();
|
||||
for (int i = 0; i < phiMap.length; ++i) {
|
||||
phiMap[i] = new Phi[program.variableCount()];
|
||||
phiIndexMap[i] = new int[program.variableCount()];
|
||||
|
@ -154,15 +141,9 @@ public class PhiUpdater {
|
|||
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
|
||||
|
||||
synthesizedPhisByBlock.clear();
|
||||
synthesizedJointsByBlock.clear();
|
||||
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
synthesizedPhisByBlock.add(new ArrayList<>());
|
||||
synthesizedJointsByBlock.add(new ArrayList<>());
|
||||
int catchCount = program.basicBlockAt(i).getTryCatchBlocks().size();
|
||||
for (int j = 0; j < catchCount; ++j) {
|
||||
synthesizedJointsByBlock.get(i).add(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
originalExceptionVariables = new Variable[program.basicBlockCount()];
|
||||
|
@ -176,7 +157,6 @@ public class PhiUpdater {
|
|||
|
||||
private void estimatePhis() {
|
||||
DefinitionExtractor definitionExtractor = new DefinitionExtractor();
|
||||
List<List<TryCatchJoint>> inputJoints = getInputJoints(program);
|
||||
variableDefined = new boolean[program.variableCount()];
|
||||
|
||||
IntDeque stack = new IntArrayDeque();
|
||||
|
@ -189,10 +169,6 @@ public class PhiUpdater {
|
|||
markAssignment(currentBlock.getExceptionVariable());
|
||||
}
|
||||
|
||||
for (TryCatchJoint joint : inputJoints.get(currentBlock.getIndex())) {
|
||||
markAssignment(joint.getReceiver());
|
||||
}
|
||||
|
||||
for (Phi phi : currentBlock.getPhis()) {
|
||||
markAssignment(phi.getReceiver());
|
||||
}
|
||||
|
@ -200,20 +176,8 @@ public class PhiUpdater {
|
|||
for (Instruction insn : currentBlock) {
|
||||
currentBlock = program.basicBlockAt(i);
|
||||
insn.acceptVisitor(definitionExtractor);
|
||||
Set<Variable> definedVariables = new HashSet<>();
|
||||
for (Variable var : definitionExtractor.getDefinedVariables()) {
|
||||
markAssignment(var);
|
||||
definedVariables.add(var);
|
||||
}
|
||||
|
||||
Set<BasicBlock> handlers = currentBlock.getTryCatchBlocks().stream()
|
||||
.map(tryCatch -> tryCatch.getHandler())
|
||||
.collect(Collectors.toSet());
|
||||
for (BasicBlock handler : handlers) {
|
||||
currentBlock = handler;
|
||||
for (Variable var : definedVariables) {
|
||||
markAssignment(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,8 +190,6 @@ public class PhiUpdater {
|
|||
private static class Task {
|
||||
Variable[] variables;
|
||||
BasicBlock block;
|
||||
TryCatchBlock tryCatch;
|
||||
int tryCatchIndex;
|
||||
}
|
||||
|
||||
private void renameVariables() {
|
||||
|
@ -244,69 +206,35 @@ public class PhiUpdater {
|
|||
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
Collections.fill(definedVersions, null);
|
||||
Task task = stack.pop();
|
||||
|
||||
currentBlock = task.block;
|
||||
currentTryCatch = task.tryCatch;
|
||||
int index = currentBlock.getIndex();
|
||||
variableMap = task.variables.clone();
|
||||
|
||||
if (currentTryCatch == null) {
|
||||
if (currentBlock.getExceptionVariable() != null) {
|
||||
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
||||
}
|
||||
|
||||
for (Phi phi : synthesizedPhisByBlock.get(index)) {
|
||||
Variable var = program.createVariable();
|
||||
var.setDebugName(phi.getReceiver().getDebugName());
|
||||
var.setLabel(phi.getReceiver().getLabel());
|
||||
mapVariable(phi.getReceiver().getIndex(), var);
|
||||
phisByReceiver.put(var.getIndex(), phi);
|
||||
phi.setReceiver(var);
|
||||
}
|
||||
for (Phi phi : currentBlock.getPhis()) {
|
||||
phi.setReceiver(define(phi.getReceiver()));
|
||||
}
|
||||
|
||||
for (Instruction insn : currentBlock) {
|
||||
insn.acceptVisitor(consumer);
|
||||
}
|
||||
} else {
|
||||
for (TryCatchJoint joint : currentTryCatch.getJoints()) {
|
||||
joint.setReceiver(define(joint.getReceiver()));
|
||||
}
|
||||
if (currentBlock.getExceptionVariable() != null) {
|
||||
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
||||
}
|
||||
|
||||
boolean tryCatchIsSuccessor = currentTryCatch != null
|
||||
&& domTree.immediateDominatorOf(currentTryCatch.getHandler().getIndex()) == index;
|
||||
if (currentTryCatch != null) {
|
||||
for (TryCatchJoint joint : synthesizedJointsByBlock.get(index).get(task.tryCatchIndex)) {
|
||||
Variable var = program.createVariable();
|
||||
var.setDebugName(joint.getReceiver().getDebugName());
|
||||
var.setLabel(joint.getReceiver().getLabel());
|
||||
mapVariable(joint.getReceiver().getIndex(), var);
|
||||
joint.setReceiver(var);
|
||||
jointsByReceiver.put(var.getIndex(), joint);
|
||||
}
|
||||
for (Phi phi : synthesizedPhisByBlock.get(index)) {
|
||||
Variable var = program.createVariable();
|
||||
var.setDebugName(phi.getReceiver().getDebugName());
|
||||
var.setLabel(phi.getReceiver().getLabel());
|
||||
mapVariable(phi.getReceiver().getIndex(), var);
|
||||
phisByReceiver.put(var.getIndex(), phi);
|
||||
phi.setReceiver(var);
|
||||
}
|
||||
for (Phi phi : currentBlock.getPhis()) {
|
||||
phi.setReceiver(define(phi.getReceiver()));
|
||||
}
|
||||
|
||||
int[] successors;
|
||||
List<TryCatchBlock> tryCatchBlockSuccessors = new ArrayList<>();
|
||||
IntSet tryCatchSuccessors = new IntOpenHashSet();
|
||||
if (currentTryCatch != null) {
|
||||
successors = tryCatchIsSuccessor ? new int[] { currentTryCatch.getHandler().getIndex() } : new int[0];
|
||||
} else {
|
||||
List<TryCatchBlock> tryCatchBlocks = currentBlock.getTryCatchBlocks();
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||
TryCatchBlock tryCatch = tryCatchBlocks.get(i);
|
||||
tryCatchSuccessors.add(tryCatch.getHandler().getIndex());
|
||||
tryCatchBlockSuccessors.add(tryCatch);
|
||||
}
|
||||
successors = Arrays.stream(domGraph.outgoingEdges(index))
|
||||
.filter(successor -> !tryCatchSuccessors.contains(successor))
|
||||
.toArray();
|
||||
for (Instruction insn : currentBlock) {
|
||||
insn.acceptVisitor(consumer);
|
||||
}
|
||||
|
||||
int[] successors = domGraph.outgoingEdges(index);
|
||||
|
||||
IntSet successorSet = IntOpenHashSet.from(successors);
|
||||
for (Incoming output : phiOutputs.get(index)) {
|
||||
if (successorSet.contains(output.getPhi().getBasicBlock().getIndex())) {
|
||||
|
@ -314,13 +242,6 @@ public class PhiUpdater {
|
|||
output.setValue(use(var));
|
||||
}
|
||||
}
|
||||
if (tryCatchIsSuccessor) {
|
||||
for (TryCatchJoint joint : currentTryCatch.getJoints()) {
|
||||
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
||||
joint.getSourceVariables().set(i, use(joint.getSourceVariables().get(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = successors.length - 1; j >= 0; --j) {
|
||||
int successor = successors[j];
|
||||
|
@ -330,24 +251,13 @@ public class PhiUpdater {
|
|||
stack.push(next);
|
||||
}
|
||||
|
||||
for (int j = tryCatchBlockSuccessors.size() - 1; j >= 0; --j) {
|
||||
TryCatchBlock tryCatch = tryCatchBlockSuccessors.get(j);
|
||||
Task next = new Task();
|
||||
next.variables = variableMap.clone();
|
||||
next.block = currentBlock;
|
||||
next.tryCatch = tryCatch;
|
||||
next.tryCatchIndex = j;
|
||||
stack.push(next);
|
||||
IntSet exceptionHandlingSuccessors = new IntOpenHashSet();
|
||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||
exceptionHandlingSuccessors.add(tryCatch.getHandler().getIndex());
|
||||
}
|
||||
|
||||
if (currentTryCatch == null) {
|
||||
for (int successor : cfg.outgoingEdges(index)) {
|
||||
if (!tryCatchSuccessors.contains(successor)) {
|
||||
renameOutgoingPhis(successor);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
renameOutgoingPhis(currentTryCatch.getHandler().getIndex());
|
||||
for (int successor : cfg.outgoingEdges(index)) {
|
||||
renameOutgoingPhis(successor, exceptionHandlingSuccessors.contains(successor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,21 +273,6 @@ public class PhiUpdater {
|
|||
synthesizedPhis.add(phi);
|
||||
}
|
||||
}
|
||||
|
||||
List<List<TryCatchJoint>> joints = synthesizedJointsByBlock.get(i);
|
||||
for (int j = 0; j < joints.size(); ++j) {
|
||||
List<TryCatchJoint> jointList = joints.get(j);
|
||||
TryCatchBlock targetTryCatch = program.basicBlockAt(i).getTryCatchBlocks().get(j);
|
||||
for (TryCatchJoint joint : jointList) {
|
||||
if (!usedPhis.get(joint.getReceiver().getIndex())) {
|
||||
continue;
|
||||
}
|
||||
if (!joint.getSourceVariables().isEmpty()) {
|
||||
targetTryCatch.getJoints().add(joint);
|
||||
synthesizedJoints.add(joint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,11 +283,6 @@ public class PhiUpdater {
|
|||
worklist.addLast(receiverIndex);
|
||||
}
|
||||
}
|
||||
for (int receiverIndex : jointsByReceiver.keys().toArray()) {
|
||||
if (usedPhis.get(receiverIndex)) {
|
||||
worklist.addLast(receiverIndex);
|
||||
}
|
||||
}
|
||||
|
||||
IntSet visited = new IntOpenHashSet();
|
||||
while (!worklist.isEmpty()) {
|
||||
|
@ -410,19 +300,10 @@ public class PhiUpdater {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TryCatchJoint joint = jointsByReceiver.get(varIndex);
|
||||
if (joint != null) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
if (!visited.contains(sourceVar.getIndex())) {
|
||||
worklist.addLast(sourceVar.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renameOutgoingPhis(int successor) {
|
||||
private void renameOutgoingPhis(int successor, boolean allVersions) {
|
||||
int[] phiIndexes = phiIndexMap[successor];
|
||||
List<Phi> phis = synthesizedPhisByBlock.get(successor);
|
||||
|
||||
|
@ -430,6 +311,16 @@ public class PhiUpdater {
|
|||
Phi phi = phis.get(j);
|
||||
Variable var = variableMap[phiIndexes[j]];
|
||||
if (var != null) {
|
||||
List<Variable> versions = definedVersions.get(phiIndexes[j]);
|
||||
if (versions != null && allVersions) {
|
||||
for (Variable version : versions) {
|
||||
Incoming incoming = new Incoming();
|
||||
incoming.setSource(currentBlock);
|
||||
incoming.setValue(version);
|
||||
phi.getIncomings().add(incoming);
|
||||
}
|
||||
}
|
||||
|
||||
Incoming incoming = new Incoming();
|
||||
incoming.setSource(currentBlock);
|
||||
incoming.setValue(var);
|
||||
|
@ -440,91 +331,66 @@ public class PhiUpdater {
|
|||
}
|
||||
|
||||
private void markAssignment(Variable var) {
|
||||
BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4];
|
||||
int head = 0;
|
||||
worklist[head++] = currentBlock;
|
||||
Deque<BasicBlock> worklist = new ArrayDeque<>();
|
||||
worklist.push(currentBlock);
|
||||
|
||||
if (variableDefined[var.getIndex()]) {
|
||||
BasicBlock startBlock = currentBlock;
|
||||
List<TryCatchBlock> tryCatchBlocks = startBlock.getTryCatchBlocks();
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||
TryCatchBlock tryCatch = tryCatchBlocks.get(i);
|
||||
TryCatchJoint joint = jointMap.computeIfAbsent(tryCatch, k -> new HashMap<>()).get(var);
|
||||
if (joint == null) {
|
||||
joint = new TryCatchJoint();
|
||||
joint.setReceiver(var);
|
||||
synthesizedJointsByBlock.get(startBlock.getIndex()).get(i).add(joint);
|
||||
jointMap.get(tryCatch).put(var, joint);
|
||||
worklist[head++] = tryCatch.getHandler();
|
||||
}
|
||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||
placePhi(tryCatch.getHandler().getIndex(), var, currentBlock, worklist);
|
||||
}
|
||||
} else {
|
||||
variableDefined[var.getIndex()] = true;
|
||||
}
|
||||
|
||||
while (head > 0) {
|
||||
BasicBlock block = worklist[--head];
|
||||
while (!worklist.isEmpty()) {
|
||||
BasicBlock block = worklist.pop();
|
||||
int[] frontiers = domFrontiers[block.getIndex()];
|
||||
|
||||
if (frontiers != null) {
|
||||
for (int frontier : frontiers) {
|
||||
BasicBlock frontierBlock = program.basicBlockAt(frontier);
|
||||
if (frontierBlock.getExceptionVariable() == var) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean exists = frontierBlock.getPhis().stream()
|
||||
.flatMap(phi -> phi.getIncomings().stream())
|
||||
.anyMatch(incoming -> incoming.getSource() == block && incoming.getValue() == var);
|
||||
if (exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Phi phi = phiMap[frontier][var.getIndex()];
|
||||
if (phi == null) {
|
||||
phi = new Phi();
|
||||
phi.setReceiver(var);
|
||||
phiIndexMap[frontier][synthesizedPhisByBlock.get(frontier).size()] = var.getIndex();
|
||||
synthesizedPhisByBlock.get(frontier).add(phi);
|
||||
phiMap[frontier][var.getIndex()] = phi;
|
||||
worklist[head++] = frontierBlock;
|
||||
}
|
||||
placePhi(frontier, var, block, worklist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Variable define(Variable var) {
|
||||
Variable old = variableMap[var.getIndex()];
|
||||
Variable original = var;
|
||||
var = introduce(var);
|
||||
propagateToTryCatch(original, var, old);
|
||||
mapVariable(original.getIndex(), var);
|
||||
return var;
|
||||
private void placePhi(int frontier, Variable var, BasicBlock block, Deque<BasicBlock> worklist) {
|
||||
BasicBlock frontierBlock = program.basicBlockAt(frontier);
|
||||
if (frontierBlock.getExceptionVariable() == var) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean exists = frontierBlock.getPhis().stream()
|
||||
.flatMap(phi -> phi.getIncomings().stream())
|
||||
.anyMatch(incoming -> incoming.getSource() == block && incoming.getValue() == var);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
Phi phi = phiMap[frontier][var.getIndex()];
|
||||
if (phi == null) {
|
||||
phi = new Phi();
|
||||
phi.setReceiver(var);
|
||||
phiIndexMap[frontier][synthesizedPhisByBlock.get(frontier).size()] = var.getIndex();
|
||||
synthesizedPhisByBlock.get(frontier).add(phi);
|
||||
phiMap[frontier][var.getIndex()] = phi;
|
||||
worklist.push(frontierBlock);
|
||||
}
|
||||
}
|
||||
|
||||
private void propagateToTryCatch(Variable original, Variable var, Variable old) {
|
||||
for (int i = 0; i < currentBlock.getTryCatchBlocks().size(); ++i) {
|
||||
TryCatchBlock tryCatch = currentBlock.getTryCatchBlocks().get(i);
|
||||
if (originalExceptionVariables[tryCatch.getHandler().getIndex()] == original) {
|
||||
continue;
|
||||
private Variable define(Variable var) {
|
||||
Variable old = variableMap[var.getIndex()];
|
||||
if (old != null) {
|
||||
if (definedVersions.get(var.getIndex()) == null) {
|
||||
definedVersions.set(var.getIndex(), new ArrayList<>());
|
||||
}
|
||||
|
||||
Map<Variable, TryCatchJoint> joints = jointMap.get(tryCatch);
|
||||
if (joints == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TryCatchJoint joint = joints.get(original);
|
||||
if (joint == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (joint.getSourceVariables().isEmpty() && old != null) {
|
||||
joint.getSourceVariables().add(old);
|
||||
}
|
||||
joint.getSourceVariables().add(var);
|
||||
definedVersions.get(var.getIndex()).add(old);
|
||||
}
|
||||
|
||||
Variable original = var;
|
||||
var = introduce(var);
|
||||
mapVariable(original.getIndex(), var);
|
||||
return var;
|
||||
}
|
||||
|
||||
private void mapVariable(int index, Variable var) {
|
||||
|
@ -551,25 +417,13 @@ public class PhiUpdater {
|
|||
private Variable use(Variable var) {
|
||||
Variable mappedVar = variableMap[var.getIndex()];
|
||||
if (mappedVar == null) {
|
||||
throw new AssertionError("Variable used before definition: " + var.getDisplayLabel());
|
||||
throw new AssertionError("Variable used before definition: @" + var.getDisplayLabel()
|
||||
+ " at $" + currentBlock.getIndex());
|
||||
}
|
||||
usedPhis.set(mappedVar.getIndex());
|
||||
return mappedVar;
|
||||
}
|
||||
|
||||
private static List<List<TryCatchJoint>> getInputJoints(Program program) {
|
||||
List<List<TryCatchJoint>> inputJoints = new ArrayList<>(Collections.nCopies(program.basicBlockCount(), null));
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
inputJoints.set(i, new ArrayList<>());
|
||||
}
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
inputJoints.get(tryCatch.getHandler().getIndex()).addAll(tryCatch.getJoints());
|
||||
}
|
||||
}
|
||||
return inputJoints;
|
||||
}
|
||||
|
||||
private InstructionVisitor consumer = new InstructionVisitor() {
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
|
|
|
@ -36,10 +36,7 @@ import org.teavm.model.ProgramReader;
|
|||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchBlockReader;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.TryCatchJointReader;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.VariableReader;
|
||||
|
||||
public final class ProgramUtils {
|
||||
private ProgramUtils() {
|
||||
|
@ -110,6 +107,7 @@ public final class ProgramUtils {
|
|||
InstructionReadVisitor visitor = new InstructionReadVisitor(copyReader);
|
||||
while (from != to) {
|
||||
from.acceptVisitor(visitor);
|
||||
copyReader.getCopy().setLocation(from.getLocation());
|
||||
result.add(copyReader.getCopy());
|
||||
from = from.getNext();
|
||||
}
|
||||
|
@ -138,25 +136,11 @@ public final class ProgramUtils {
|
|||
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
||||
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||
tryCatchCopy.setHandler(target.basicBlockAt(tryCatch.getHandler().getIndex()));
|
||||
tryCatchCopy.getJoints().addAll(copyTryCatchJoints(tryCatch, target));
|
||||
result.add(tryCatchCopy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<TryCatchJoint> copyTryCatchJoints(TryCatchBlockReader block, Program target) {
|
||||
List<TryCatchJoint> result = new ArrayList<>();
|
||||
for (TryCatchJointReader joint : block.readJoints()) {
|
||||
TryCatchJoint jointCopy = new TryCatchJoint();
|
||||
jointCopy.setReceiver(target.variableAt(joint.getReceiver().getIndex()));
|
||||
for (VariableReader sourceVar : joint.readSourceVariables()) {
|
||||
jointCopy.getSourceVariables().add(target.variableAt(sourceVar.getIndex()));
|
||||
}
|
||||
result.add(jointCopy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<List<Incoming>> getPhiOutputs(Program program) {
|
||||
List<List<Incoming>> outputs = new ArrayList<>(program.basicBlockCount());
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
|
@ -175,23 +159,6 @@ public final class ProgramUtils {
|
|||
return outputs;
|
||||
}
|
||||
|
||||
public static List<List<Incoming>> getPhiOutputsByVariable(Program program) {
|
||||
List<List<Incoming>> outputs = new ArrayList<>(program.variableCount());
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
outputs.add(new ArrayList<>());
|
||||
}
|
||||
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Phi phi : block.getPhis()) {
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
outputs.get(incoming.getValue().getIndex()).add(incoming);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public static BasicBlock[] getVariableDefinitionPlaces(Program program) {
|
||||
BasicBlock[] places = new BasicBlock[program.variableCount()];
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
|
@ -213,12 +180,6 @@ public final class ProgramUtils {
|
|||
places[var.getIndex()] = block;
|
||||
}
|
||||
}
|
||||
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
places[joint.getReceiver().getIndex()] = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return places;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,8 @@ package org.teavm.model.util;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.common.DisjointSet;
|
||||
import org.teavm.common.MutableGraphEdge;
|
||||
import org.teavm.common.MutableGraphNode;
|
||||
|
@ -33,15 +31,12 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ProgramReader;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.JumpInstruction;
|
||||
|
||||
public class RegisterAllocator {
|
||||
public void allocateRegisters(MethodReader method, Program program) {
|
||||
insertJointArgumentsCopies(program);
|
||||
insertPhiArgumentsCopies(program);
|
||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
|
@ -91,9 +86,6 @@ public class RegisterAllocator {
|
|||
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
program.basicBlockAt(i).getPhis().clear();
|
||||
for (TryCatchBlock tryCatch : program.basicBlockAt(i).getTryCatchBlocks()) {
|
||||
tryCatch.getJoints().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,42 +129,6 @@ public class RegisterAllocator {
|
|||
}
|
||||
}
|
||||
|
||||
private void insertJointArgumentsCopies(Program program) {
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
tryCatch.getJoints().forEach(this::insertCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void insertCopy(TryCatchJoint joint) {
|
||||
Set<Variable> variableSet = new HashSet<>(joint.getSourceVariables());
|
||||
|
||||
BasicBlock block = joint.getBlock().getProtectedBlock();
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
Instruction nextInsn;
|
||||
for (Instruction insn = block.getFirstInstruction(); insn != null; insn = nextInsn) {
|
||||
nextInsn = insn.getNext();
|
||||
insn.acceptVisitor(defExtractor);
|
||||
for (Variable definedVar : defExtractor.getDefinedVariables()) {
|
||||
if (variableSet.remove(definedVar)) {
|
||||
AssignInstruction copyInsn = new AssignInstruction();
|
||||
copyInsn.setReceiver(joint.getReceiver());
|
||||
copyInsn.setAssignee(definedVar);
|
||||
insn.insertNext(copyInsn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Variable enteringVar : variableSet) {
|
||||
AssignInstruction copyInsn = new AssignInstruction();
|
||||
copyInsn.setReceiver(joint.getReceiver());
|
||||
copyInsn.setAssignee(enteringVar);
|
||||
block.addFirst(copyInsn);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertPhiArgumentsCopies(Program program) {
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
Map<BasicBlock, BasicBlock> blockMap = new HashMap<>();
|
||||
|
@ -321,13 +277,6 @@ public class RegisterAllocator {
|
|||
classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
classes.union(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
|
|
@ -52,14 +52,6 @@ public class TypeInferer {
|
|||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
for (VariableReader sourceVar : joint.readSourceVariables()) {
|
||||
builder.addEdge(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IntegerStack stack = new IntegerStack(sz);
|
||||
|
|
|
@ -8,9 +8,9 @@ $if0
|
|||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
@bar_1 := nullCheck @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
@bar_2 := ephi @bar, @bar_1
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
$if0Handler
|
||||
@bar_2 := phi @bar from $if0, @bar_1 from $if0
|
||||
goto $join
|
||||
$else
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
|
@ -19,7 +19,7 @@ $else
|
|||
$else1
|
||||
invokeVirtual `Bar.baz2()LBar;` @bar_3
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
$elseHandler
|
||||
goto $join
|
||||
$join
|
||||
|
|
|
@ -7,7 +7,7 @@ $start
|
|||
$if0
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
$if0Handler
|
||||
goto $join
|
||||
$else
|
||||
|
@ -16,7 +16,7 @@ $else
|
|||
$else1
|
||||
invokeVirtual `Bar.baz2()LBar;` @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
$elseHandler
|
||||
goto $join
|
||||
$join
|
||||
|
|
|
@ -5,9 +5,9 @@ $start
|
|||
invokeStatic `foo.Bar.baz()I`
|
||||
@a_3 := 2
|
||||
return @a_3
|
||||
catch java.lang.Exception goto $handler
|
||||
@a_h := ephi @a_1, @a_2, @a_3
|
||||
catch java.lang.Exception goto $handler
|
||||
$handler
|
||||
@a_h := phi @a_1 from $start, @a_2 from $start, @a_3 from $start
|
||||
@e := exception
|
||||
@out := field `java.lang.String.out` as `Ljava/io/PrintStream;`
|
||||
invokeVirtual `java.io.PrintStream.println(Ljava/lang/Object;)V` @out, @e
|
||||
|
|
|
@ -3,8 +3,8 @@ $start
|
|||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$catch
|
||||
@a_2 := phi @a from $start, @a_1 from $start
|
||||
@b := 1
|
||||
@a_3 := @a_2 + @b as int
|
||||
goto $end
|
||||
|
|
|
@ -3,17 +3,15 @@ $start
|
|||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_5 := invokeStatic `Foo.boo()I`
|
||||
@a_2 := invokeStatic `Foo.boo()I`
|
||||
goto $end
|
||||
catch java.lang.RuntimeException goto $catch
|
||||
@a_6 := ephi @a_1, @a_5
|
||||
$catch
|
||||
@a_3 := phi @a_2 from $start, @a_6 from $second
|
||||
@a_3 := phi @a from $start, @a_1 from $start, @a_1 from $second, @a_2 from $second
|
||||
@b := 1
|
||||
@a_4 := @a_3 + @b as int
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_4 from $catch, @a_5 from $second
|
||||
return @a_7
|
||||
@a_5 := phi @a_2 from $second, @a_4 from $catch
|
||||
return @a_5
|
|
@ -3,16 +3,14 @@ $start
|
|||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_3 := invokeStatic `Foo.bar2()I`
|
||||
@a_4 := invokeStatic `Foo.baz2()I`
|
||||
@a_2 := invokeStatic `Foo.bar2()I`
|
||||
@a_3 := invokeStatic `Foo.baz2()I`
|
||||
goto $end
|
||||
catch goto $catch
|
||||
@a_5 := ephi @a_1, @a_3, @a_4
|
||||
$catch
|
||||
@a_6 := phi @a_2 from $start, @a_5 from $second
|
||||
@a_4 := phi @a from $start, @a_1 from $start, @a_2 from $second, @a_3 from $second
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
||||
return @a_7
|
||||
@a_5 := phi @a_3 from $second, @a_4 from $catch
|
||||
return @a_5
|
||||
|
|
|
@ -3,16 +3,14 @@ $start
|
|||
@a_1 := invokeStatic `Foo.baz()I`
|
||||
goto $second
|
||||
catch goto $catch
|
||||
@a_2 := ephi @a, @a_1
|
||||
$second
|
||||
@a_3 := invokeStatic `Foo.bar2()I`
|
||||
@a_4 := invokeStatic `Foo.baz2()I`
|
||||
@a_2 := invokeStatic `Foo.bar2()I`
|
||||
@a_3 := invokeStatic `Foo.baz2()I`
|
||||
goto $end
|
||||
catch goto $catch
|
||||
@a_5 := ephi @a_1, @a_3, @a_4
|
||||
$catch
|
||||
@a_6 := phi @a_2 from $start, @a_5 from $second
|
||||
@a_4 := phi @a from $start, @a_1 from $start, @a_2 from $second, @a_3 from $second
|
||||
goto $end
|
||||
$end
|
||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
||||
return @a_7
|
||||
@a_5 := phi @a_3 from $second, @a_4 from $catch
|
||||
return @a_5
|
||||
|
|
|
@ -22,8 +22,6 @@ import org.teavm.common.DisjointSet;
|
|||
import org.teavm.model.BasicBlockReader;
|
||||
import org.teavm.model.PhiReader;
|
||||
import org.teavm.model.ProgramReader;
|
||||
import org.teavm.model.TryCatchBlockReader;
|
||||
import org.teavm.model.TryCatchJointReader;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.VariableReader;
|
||||
import org.teavm.model.instructions.AbstractInstructionReader;
|
||||
|
@ -51,16 +49,6 @@ class AliasFinder {
|
|||
set.union(inputs.iterator().next(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
|
||||
for (TryCatchJointReader joint : tryCatch.readJoints()) {
|
||||
Set<Integer> inputs = joint.readSourceVariables().stream()
|
||||
.map(sourceVar -> sourceVar.getIndex())
|
||||
.collect(Collectors.toSet());
|
||||
if (inputs.size() == 1) {
|
||||
set.union(inputs.iterator().next(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] map = new int[set.size()];
|
||||
|
|
|
@ -29,8 +29,6 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.PrimitiveType;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.TryCatchJoint;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
|
@ -112,13 +110,6 @@ public class BoxingElimination {
|
|||
union(phi.getReceiver().getIndex(), incoming.getValue().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
union(sourceVar.getIndex(), joint.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user