Eliminate exception joint in favour of phi functions with multiple inputs per source basic block

This commit is contained in:
Alexey Andreev 2017-01-08 22:04:24 +03:00
parent 9532f9a32b
commit ff059919a7
37 changed files with 246 additions and 844 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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());

View File

@ -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);
}
}
}
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -15,14 +15,10 @@
*/
package org.teavm.model;
import java.util.List;
public interface TryCatchBlockReader {
BasicBlockReader getProtectedBlock();
BasicBlockReader getHandler();
String getExceptionType();
List<TryCatchJointReader> readJoints();
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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 {

View File

@ -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) {

View File

@ -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));

View File

@ -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);
}
}
}

View File

@ -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()]) {

View File

@ -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) {
}
}
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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()));

View File

@ -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);

View File

@ -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()) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()];

View File

@ -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());
}
}
}
}
}