mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -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;
|
package org.teavm.ast.optimization;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.List;
|
|
||||||
import org.teavm.ast.AsyncMethodNode;
|
import org.teavm.ast.AsyncMethodNode;
|
||||||
import org.teavm.ast.AsyncMethodPart;
|
import org.teavm.ast.AsyncMethodPart;
|
||||||
import org.teavm.ast.RegularMethodNode;
|
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)) {
|
for (int succ : dom.outgoingEdges(node)) {
|
||||||
stack.push(succ);
|
stack.push(succ);
|
||||||
|
|
|
@ -63,14 +63,6 @@ public class ProgramIO {
|
||||||
data.writeInt(tryCatch.getExceptionType() != null ? symbolTable.lookup(
|
data.writeInt(tryCatch.getExceptionType() != null ? symbolTable.lookup(
|
||||||
tryCatch.getExceptionType()) : -1);
|
tryCatch.getExceptionType()) : -1);
|
||||||
data.writeShort(tryCatch.getHandler().getIndex());
|
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;
|
TextLocation location = null;
|
||||||
InstructionWriter insnWriter = new InstructionWriter(data);
|
InstructionWriter insnWriter = new InstructionWriter(data);
|
||||||
|
@ -141,17 +133,6 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
tryCatch.setHandler(program.basicBlockAt(data.readShort()));
|
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);
|
block.getTryCatchBlocks().add(tryCatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,13 +64,6 @@ public class DataFlowGraphBuilder extends AbstractInstructionReader {
|
||||||
builder.addEdge(from, to);
|
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);
|
block.readAllInstructions(this);
|
||||||
}
|
}
|
||||||
Graph graph = builder.build();
|
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
|
@Override
|
||||||
public void nullCheck(VariableReader receiver, VariableReader value) {
|
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||||
connect(value.getIndex(), receiver.getIndex());
|
connect(value.getIndex(), receiver.getIndex());
|
||||||
|
|
|
@ -44,7 +44,6 @@ import org.teavm.model.Program;
|
||||||
import org.teavm.model.RuntimeConstant;
|
import org.teavm.model.RuntimeConstant;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.TryCatchBlockReader;
|
import org.teavm.model.TryCatchBlockReader;
|
||||||
import org.teavm.model.TryCatchJointReader;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.VariableReader;
|
import org.teavm.model.VariableReader;
|
||||||
import org.teavm.model.emit.ProgramEmitter;
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
|
@ -142,19 +141,6 @@ class DependencyGraphBuilder {
|
||||||
if (tryCatch.getExceptionType() != null) {
|
if (tryCatch.getExceptionType() != null) {
|
||||||
dependencyChecker.linkClass(tryCatch.getExceptionType(), new CallLocation(caller.getMethod()));
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class Phi implements PhiReader {
|
public class Phi implements PhiReader {
|
||||||
private BasicBlock basicBlock;
|
private BasicBlock basicBlock;
|
||||||
private Variable receiver;
|
private Variable receiver;
|
||||||
|
|
|
@ -65,6 +65,35 @@ public class Program implements ProgramReader {
|
||||||
return basicBlocks;
|
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) {
|
public void deleteVariable(int index) {
|
||||||
Variable variable = variables.get(index);
|
Variable variable = variables.get(index);
|
||||||
if (variable == null) {
|
if (variable == null) {
|
||||||
|
|
|
@ -15,64 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
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 {
|
public class TryCatchBlock implements TryCatchBlockReader {
|
||||||
BasicBlock protectedBlock;
|
BasicBlock protectedBlock;
|
||||||
private BasicBlock handler;
|
private BasicBlock handler;
|
||||||
private String exceptionType;
|
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
|
@Override
|
||||||
public BasicBlock getHandler() {
|
public BasicBlock getHandler() {
|
||||||
|
@ -96,16 +42,4 @@ public class TryCatchBlock implements TryCatchBlockReader {
|
||||||
public BasicBlock getProtectedBlock() {
|
public BasicBlock getProtectedBlock() {
|
||||||
return protectedBlock;
|
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;
|
package org.teavm.model;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface TryCatchBlockReader {
|
public interface TryCatchBlockReader {
|
||||||
BasicBlockReader getProtectedBlock();
|
BasicBlockReader getProtectedBlock();
|
||||||
|
|
||||||
BasicBlockReader getHandler();
|
BasicBlockReader getHandler();
|
||||||
|
|
||||||
String getExceptionType();
|
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.MethodDescriptor;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.util.DefinitionExtractor;
|
import org.teavm.model.util.DefinitionExtractor;
|
||||||
import org.teavm.model.util.InstructionVariableMapper;
|
import org.teavm.model.util.InstructionVariableMapper;
|
||||||
|
@ -57,7 +55,6 @@ public class NullnessInformation {
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
Set<Phi> phisToRemove = new HashSet<>(phiUpdater.getSynthesizedPhis());
|
Set<Phi> phisToRemove = new HashSet<>(phiUpdater.getSynthesizedPhis());
|
||||||
Set<TryCatchJoint> jointsToRemove = new HashSet<>(phiUpdater.getSynthesizedJoints());
|
|
||||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
InstructionVariableMapper variableMapper = new InstructionVariableMapper(var -> {
|
InstructionVariableMapper variableMapper = new InstructionVariableMapper(var -> {
|
||||||
int source = phiUpdater.getSourceVariable(var.getIndex());
|
int source = phiUpdater.getSourceVariable(var.getIndex());
|
||||||
|
@ -65,9 +62,6 @@ public class NullnessInformation {
|
||||||
});
|
});
|
||||||
for (BasicBlock block : program.getBasicBlocks()) {
|
for (BasicBlock block : program.getBasicBlocks()) {
|
||||||
block.getPhis().removeIf(phisToRemove::contains);
|
block.getPhis().removeIf(phisToRemove::contains);
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
|
||||||
tryCatch.getJoints().removeIf(jointsToRemove::contains);
|
|
||||||
}
|
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
insn.acceptVisitor(defExtractor);
|
insn.acceptVisitor(defExtractor);
|
||||||
if (Arrays.stream(defExtractor.getDefinedVariables())
|
if (Arrays.stream(defExtractor.getDefinedVariables())
|
||||||
|
@ -78,8 +72,18 @@ public class NullnessInformation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variableMapper.applyToPhis(block);
|
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) {
|
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.MethodDescriptor;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||||
|
@ -126,13 +124,6 @@ class NullnessInformationBuilder {
|
||||||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
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) {
|
for (Instruction instruction : block) {
|
||||||
if (instruction instanceof AssignInstruction) {
|
if (instruction instanceof AssignInstruction) {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package org.teavm.model.lowlevel;
|
package org.teavm.model.lowlevel;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.interop.StaticInit;
|
import org.teavm.interop.StaticInit;
|
||||||
import org.teavm.interop.Structure;
|
import org.teavm.interop.Structure;
|
||||||
|
@ -26,7 +25,6 @@ import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.instructions.EmptyInstruction;
|
|
||||||
import org.teavm.model.instructions.InitClassInstruction;
|
import org.teavm.model.instructions.InitClassInstruction;
|
||||||
|
|
||||||
public class ClassInitializerEliminator {
|
public class ClassInitializerEliminator {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.model.lowlevel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.teavm.common.DominatorTree;
|
import org.teavm.common.DominatorTree;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphUtils;
|
import org.teavm.common.GraphUtils;
|
||||||
|
@ -29,7 +30,6 @@ import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.BinaryBranchingCondition;
|
import org.teavm.model.instructions.BinaryBranchingCondition;
|
||||||
|
@ -64,7 +64,6 @@ public class ExceptionHandlingShadowStackContributor {
|
||||||
private Program program;
|
private Program program;
|
||||||
private DominatorTree dom;
|
private DominatorTree dom;
|
||||||
private BasicBlock[] variableDefinitionPlaces;
|
private BasicBlock[] variableDefinitionPlaces;
|
||||||
private Phi[] jointPhis;
|
|
||||||
private boolean hasExceptionHandlers;
|
private boolean hasExceptionHandlers;
|
||||||
|
|
||||||
public ExceptionHandlingShadowStackContributor(ManagedMethodRepository managedMethodRepository,
|
public ExceptionHandlingShadowStackContributor(ManagedMethodRepository managedMethodRepository,
|
||||||
|
@ -77,7 +76,6 @@ public class ExceptionHandlingShadowStackContributor {
|
||||||
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||||
dom = GraphUtils.buildDominatorTree(cfg);
|
dom = GraphUtils.buildDominatorTree(cfg);
|
||||||
variableDefinitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program);
|
variableDefinitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program);
|
||||||
jointPhis = new Phi[program.variableCount()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contribute() {
|
public boolean contribute() {
|
||||||
|
@ -126,17 +124,26 @@ public class ExceptionHandlingShadowStackContributor {
|
||||||
int[] currentJointSources = new int[program.variableCount()];
|
int[] currentJointSources = new int[program.variableCount()];
|
||||||
int[] jointReceiverMap = new int[program.variableCount()];
|
int[] jointReceiverMap = new int[program.variableCount()];
|
||||||
Arrays.fill(currentJointSources, -1);
|
Arrays.fill(currentJointSources, -1);
|
||||||
|
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
for (Phi phi : tryCatch.getHandler().getPhis()) {
|
||||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
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()];
|
BasicBlock sourceVarDefinedAt = variableDefinitionPlaces[sourceVar.getIndex()];
|
||||||
if (dom.dominates(sourceVarDefinedAt.getIndex(), block.getIndex())) {
|
if (dom.dominates(sourceVarDefinedAt.getIndex(), block.getIndex())) {
|
||||||
currentJointSources[joint.getReceiver().getIndex()] = sourceVar.getIndex();
|
currentJointSources[phi.getReceiver().getIndex()] = sourceVar.getIndex();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
for (Variable sourceVar : sourceVariables) {
|
||||||
jointReceiverMap[sourceVar.getIndex()] = joint.getReceiver().getIndex();
|
jointReceiverMap[sourceVar.getIndex()] = phi.getReceiver().getIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,13 +288,17 @@ public class ExceptionHandlingShadowStackContributor {
|
||||||
switchInsn.getEntries().add(catchEntry);
|
switchInsn.getEntries().add(catchEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
for (Phi phi : tryCatch.getHandler().getPhis()) {
|
||||||
Phi phi = getJointPhi(joint);
|
int value = currentJointSources[phi.getReceiver().getIndex()];
|
||||||
Incoming incoming = new Incoming();
|
if (value < 0) {
|
||||||
incoming.setSource(block);
|
continue;
|
||||||
int value = currentJointSources[joint.getReceiver().getIndex()];
|
}
|
||||||
incoming.setValue(program.variableAt(value));
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
phi.getIncomings().add(incoming);
|
if (incoming.getValue().getIndex() == value) {
|
||||||
|
incoming.setSource(block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,18 +338,6 @@ public class ExceptionHandlingShadowStackContributor {
|
||||||
return defaultExceptionHandler;
|
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) {
|
private Variable createReturnValueInstructions(BasicBlock block) {
|
||||||
ValueType returnType = method.getReturnType();
|
ValueType returnType = method.getReturnType();
|
||||||
if (returnType == ValueType.VOID) {
|
if (returnType == ValueType.VOID) {
|
||||||
|
|
|
@ -28,8 +28,6 @@ import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InvokeDynamicInstruction;
|
import org.teavm.model.InvokeDynamicInstruction;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
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)) {
|
for (Incoming incoming : outgoings.get(v)) {
|
||||||
int value = map[incoming.getValue().getIndex()];
|
int value = map[incoming.getValue().getIndex()];
|
||||||
incoming.setValue(program.variableAt(value));
|
incoming.setValue(program.variableAt(value));
|
||||||
|
|
|
@ -39,7 +39,6 @@ import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.analysis.NullnessInformation;
|
import org.teavm.model.analysis.NullnessInformation;
|
||||||
import org.teavm.model.util.BasicBlockMapper;
|
import org.teavm.model.util.BasicBlockMapper;
|
||||||
|
@ -345,13 +344,6 @@ class LoopInversionImpl {
|
||||||
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||||
tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler)));
|
tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler)));
|
||||||
targetBlock.getTryCatchBlocks().add(tryCatchCopy);
|
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.MethodReader;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
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) {
|
for (int j = 0; j < block.getPhis().size(); ++j) {
|
||||||
Phi phi = block.getPhis().get(j);
|
Phi phi = block.getPhis().get(j);
|
||||||
if (!used[phi.getReceiver().getIndex()]) {
|
if (!used[phi.getReceiver().getIndex()]) {
|
||||||
|
|
|
@ -17,8 +17,28 @@ package org.teavm.model.optimization;
|
||||||
|
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphBuilder;
|
import org.teavm.common.GraphBuilder;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.instructions.*;
|
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 {
|
public final class VariableUsageGraphBuilder {
|
||||||
private VariableUsageGraphBuilder() {
|
private VariableUsageGraphBuilder() {
|
||||||
|
@ -37,18 +57,11 @@ public final class VariableUsageGraphBuilder {
|
||||||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
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();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class InstructionAnalyzer implements InstructionVisitor {
|
private static class InstructionAnalyzer extends AbstractInstructionVisitor {
|
||||||
private GraphBuilder builder;
|
private GraphBuilder builder;
|
||||||
|
|
||||||
public InstructionAnalyzer(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
|
@Override
|
||||||
public void visit(BinaryInstruction insn) {
|
public void visit(BinaryInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getFirstOperand(), insn.getSecondOperand());
|
use(insn.getReceiver(), insn.getFirstOperand(), insn.getSecondOperand());
|
||||||
|
@ -123,39 +104,11 @@ public final class VariableUsageGraphBuilder {
|
||||||
use(insn.getReceiver(), insn.getValue());
|
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
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getSize());
|
use(insn.getReceiver(), insn.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ConstructInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructMultiArrayInstruction insn) {
|
public void visit(ConstructMultiArrayInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getDimensions().toArray(new Variable[0]));
|
use(insn.getReceiver(), insn.getDimensions().toArray(new Variable[0]));
|
||||||
|
@ -168,10 +121,6 @@ public final class VariableUsageGraphBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(PutFieldInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getArray());
|
use(insn.getReceiver(), insn.getArray());
|
||||||
|
@ -192,40 +141,14 @@ public final class VariableUsageGraphBuilder {
|
||||||
use(insn.getReceiver(), insn.getArray(), insn.getIndex());
|
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
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void visit(IsInstanceInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getValue());
|
use(insn.getReceiver(), insn.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(InitClassInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void visit(NullCheckInstruction insn) {
|
||||||
use(insn.getReceiver(), insn.getValue());
|
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.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import org.teavm.model.BasicBlockReader;
|
||||||
import org.teavm.model.*;
|
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 class ListingBuilder {
|
||||||
public String buildListing(ProgramReader program, String prefix) {
|
public String buildListing(ProgramReader program, String prefix) {
|
||||||
|
@ -87,14 +93,6 @@ public class ListingBuilder {
|
||||||
}
|
}
|
||||||
sb.append(" goto $").append(tryCatch.getHandler().getIndex());
|
sb.append(" goto $").append(tryCatch.getHandler().getIndex());
|
||||||
sb.append("\n");
|
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();
|
return sb.toString();
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.ArrayElementType;
|
import org.teavm.model.instructions.ArrayElementType;
|
||||||
|
@ -89,9 +88,9 @@ public class ListingParser {
|
||||||
private Map<String, BasicBlock> blockMap;
|
private Map<String, BasicBlock> blockMap;
|
||||||
private Map<String, Integer> blockFirstOccurrence;
|
private Map<String, Integer> blockFirstOccurrence;
|
||||||
private Set<String> declaredBlocks = new HashSet<>();
|
private Set<String> declaredBlocks = new HashSet<>();
|
||||||
|
private List<BasicBlock> orderedBlocks = new ArrayList<>();
|
||||||
private TextLocation currentLocation;
|
private TextLocation currentLocation;
|
||||||
private BasicBlock currentBlock;
|
private BasicBlock currentBlock;
|
||||||
private TryCatchBlock currentTryCatch;
|
|
||||||
|
|
||||||
public Program parse(Reader reader) throws IOException, ListingParseException {
|
public Program parse(Reader reader) throws IOException, ListingParseException {
|
||||||
try {
|
try {
|
||||||
|
@ -114,6 +113,9 @@ public class ListingParser {
|
||||||
throw new ListingParseException("Block not defined: " + blockName, blockIndex);
|
throw new ListingParseException("Block not defined: " + blockName, blockIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program.pack();
|
||||||
|
program.rearrangeBasicBlocks(orderedBlocks);
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
} finally {
|
} finally {
|
||||||
program = null;
|
program = null;
|
||||||
|
@ -177,7 +179,7 @@ public class ListingParser {
|
||||||
b.setLabel(k);
|
b.setLabel(k);
|
||||||
return b;
|
return b;
|
||||||
});
|
});
|
||||||
currentTryCatch = null;
|
orderedBlocks.add(currentBlock);
|
||||||
|
|
||||||
currentLocation = null;
|
currentLocation = null;
|
||||||
do {
|
do {
|
||||||
|
@ -361,10 +363,6 @@ public class ListingParser {
|
||||||
lexer.nextToken();
|
lexer.nextToken();
|
||||||
parsePhi(receiver);
|
parsePhi(receiver);
|
||||||
break;
|
break;
|
||||||
case "ephi":
|
|
||||||
lexer.nextToken();
|
|
||||||
parseExceptionPhi(receiver);
|
|
||||||
break;
|
|
||||||
case "classOf":
|
case "classOf":
|
||||||
lexer.nextToken();
|
lexer.nextToken();
|
||||||
parseClassLiteral(receiver);
|
parseClassLiteral(receiver);
|
||||||
|
@ -593,24 +591,6 @@ public class ListingParser {
|
||||||
currentBlock.getPhis().add(phi);
|
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 {
|
private void parseClassLiteral(Variable receiver) throws IOException, ListingParseException {
|
||||||
ValueType type = expectValueType();
|
ValueType type = expectValueType();
|
||||||
ClassConstantInstruction insn = new ClassConstantInstruction();
|
ClassConstantInstruction insn = new ClassConstantInstruction();
|
||||||
|
@ -792,7 +772,6 @@ public class ListingParser {
|
||||||
}
|
}
|
||||||
expectKeyword("goto");
|
expectKeyword("goto");
|
||||||
tryCatch.setHandler(expectBlock());
|
tryCatch.setHandler(expectBlock());
|
||||||
currentTryCatch = tryCatch;
|
|
||||||
currentBlock.getTryCatchBlocks().add(tryCatch);
|
currentBlock.getTryCatchBlocks().add(tryCatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1170,7 +1149,6 @@ public class ListingParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addInstruction(Instruction instruction) throws ListingParseException {
|
private void addInstruction(Instruction instruction) throws ListingParseException {
|
||||||
currentTryCatch = null;
|
|
||||||
instruction.setLocation(currentLocation);
|
instruction.setLocation(currentLocation);
|
||||||
currentBlock.add(instruction);
|
currentBlock.add(instruction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,43 @@ import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InvokeDynamicInstruction;
|
import org.teavm.model.InvokeDynamicInstruction;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
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;
|
private final Function<Variable, Variable> f;
|
||||||
|
|
||||||
public InstructionVariableMapper(Function<Variable, Variable> f) {
|
public InstructionVariableMapper(Function<Variable, Variable> f) {
|
||||||
|
@ -40,7 +71,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
||||||
|
|
||||||
applyToInstructions(block);
|
applyToInstructions(block);
|
||||||
applyToPhis(block);
|
applyToPhis(block);
|
||||||
applyToTryCatchBlocks(block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyToInstructions(BasicBlock block) {
|
public void applyToInstructions(BasicBlock block) {
|
||||||
|
@ -58,26 +88,10 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyToTryCatchBlocks(BasicBlock block) {
|
public Variable map(Variable var) {
|
||||||
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) {
|
|
||||||
return f.apply(var);
|
return f.apply(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(EmptyInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void visit(ClassConstantInstruction insn) {
|
||||||
insn.setReceiver(map(insn.getReceiver()));
|
insn.setReceiver(map(insn.getReceiver()));
|
||||||
|
@ -161,10 +175,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
||||||
insn.setSecondOperand(map(insn.getSecondOperand()));
|
insn.setSecondOperand(map(insn.getSecondOperand()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(JumpInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchInstruction insn) {
|
public void visit(SwitchInstruction insn) {
|
||||||
insn.setCondition(map(insn.getCondition()));
|
insn.setCondition(map(insn.getCondition()));
|
||||||
|
@ -281,10 +291,6 @@ public class InstructionVariableMapper implements InstructionVisitor {
|
||||||
insn.setValue(map(insn.getValue()));
|
insn.setValue(map(insn.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(InitClassInstruction insn) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void visit(NullCheckInstruction insn) {
|
||||||
insn.setReceiver(map(insn.getReceiver()));
|
insn.setReceiver(map(insn.getReceiver()));
|
||||||
|
|
|
@ -52,15 +52,6 @@ class InterferenceGraphBuilder {
|
||||||
live.add(nodes.get(outgoing.getValue().getIndex()));
|
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()) {
|
for (Instruction insn = block.getLastInstruction(); insn != null; insn = insn.getPrevious()) {
|
||||||
insn.acceptVisitor(useExtractor);
|
insn.acceptVisitor(useExtractor);
|
||||||
insn.acceptVisitor(defExtractor);
|
insn.acceptVisitor(defExtractor);
|
||||||
|
|
|
@ -21,7 +21,12 @@ import java.util.ArrayDeque;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import org.teavm.common.Graph;
|
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 {
|
public class LivenessAnalyzer {
|
||||||
private BitSet[] liveVars;
|
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()) {
|
for (Phi phi : block.getPhis()) {
|
||||||
definitions[phi.getReceiver().getIndex()] = i;
|
definitions[phi.getReceiver().getIndex()] = i;
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
|
|
|
@ -27,12 +27,7 @@ import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
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.DominatorTree;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphUtils;
|
import org.teavm.common.GraphUtils;
|
||||||
|
@ -44,7 +39,6 @@ import org.teavm.model.InvokeDynamicInstruction;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
@ -92,21 +86,17 @@ public class PhiUpdater {
|
||||||
private int[][] domFrontiers;
|
private int[][] domFrontiers;
|
||||||
private Variable[] variableMap;
|
private Variable[] variableMap;
|
||||||
private boolean[] variableDefined;
|
private boolean[] variableDefined;
|
||||||
|
private List<List<Variable>> definedVersions = new ArrayList<>();
|
||||||
private BasicBlock currentBlock;
|
private BasicBlock currentBlock;
|
||||||
private TryCatchBlock currentTryCatch;
|
|
||||||
private Phi[][] phiMap;
|
private Phi[][] phiMap;
|
||||||
private int[][] phiIndexMap;
|
private int[][] phiIndexMap;
|
||||||
private Map<TryCatchBlock, Map<Variable, TryCatchJoint>> jointMap = new HashMap<>();
|
|
||||||
private List<List<Phi>> synthesizedPhisByBlock = new ArrayList<>();
|
private List<List<Phi>> synthesizedPhisByBlock = new ArrayList<>();
|
||||||
private IntObjectMap<Phi> phisByReceiver = new IntObjectOpenHashMap<>();
|
private IntObjectMap<Phi> phisByReceiver = new IntObjectOpenHashMap<>();
|
||||||
private IntObjectMap<TryCatchJoint> jointsByReceiver = new IntObjectOpenHashMap<>();
|
|
||||||
private BitSet usedPhis = new BitSet();
|
private BitSet usedPhis = new BitSet();
|
||||||
private List<List<List<TryCatchJoint>>> synthesizedJointsByBlock = new ArrayList<>();
|
|
||||||
private Variable[] originalExceptionVariables;
|
private Variable[] originalExceptionVariables;
|
||||||
private boolean[] usedDefinitions;
|
private boolean[] usedDefinitions;
|
||||||
private IntegerArray variableToSourceMap = new IntegerArray(10);
|
private IntegerArray variableToSourceMap = new IntegerArray(10);
|
||||||
private List<Phi> synthesizedPhis = new ArrayList<>();
|
private List<Phi> synthesizedPhis = new ArrayList<>();
|
||||||
private List<TryCatchJoint> synthesizedJoints = new ArrayList<>();
|
|
||||||
|
|
||||||
public int getSourceVariable(int var) {
|
public int getSourceVariable(int var) {
|
||||||
if (var >= variableToSourceMap.size()) {
|
if (var >= variableToSourceMap.size()) {
|
||||||
|
@ -119,17 +109,12 @@ public class PhiUpdater {
|
||||||
return synthesizedPhis;
|
return synthesizedPhis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TryCatchJoint> getSynthesizedJoints() {
|
|
||||||
return synthesizedJoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePhis(Program program, Variable[] arguments) {
|
public void updatePhis(Program program, Variable[] arguments) {
|
||||||
if (program.basicBlockCount() == 0) {
|
if (program.basicBlockCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.program = program;
|
this.program = program;
|
||||||
phisByReceiver.clear();
|
phisByReceiver.clear();
|
||||||
jointsByReceiver.clear();
|
|
||||||
cfg = ProgramUtils.buildControlFlowGraph(program);
|
cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||||
domTree = GraphUtils.buildDominatorTree(cfg);
|
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
domFrontiers = new int[cfg.size()][];
|
domFrontiers = new int[cfg.size()][];
|
||||||
|
@ -141,12 +126,14 @@ public class PhiUpdater {
|
||||||
variableMap[i] = arguments[i];
|
variableMap[i] = arguments[i];
|
||||||
usedDefinitions[i] = true;
|
usedDefinitions[i] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
variableToSourceMap.add(-1);
|
variableToSourceMap.add(-1);
|
||||||
}
|
}
|
||||||
|
definedVersions.addAll(Collections.nCopies(program.variableCount(), null));
|
||||||
|
|
||||||
phiMap = new Phi[program.basicBlockCount()][];
|
phiMap = new Phi[program.basicBlockCount()][];
|
||||||
phiIndexMap = new int[program.basicBlockCount()][];
|
phiIndexMap = new int[program.basicBlockCount()][];
|
||||||
jointMap.clear();
|
|
||||||
for (int i = 0; i < phiMap.length; ++i) {
|
for (int i = 0; i < phiMap.length; ++i) {
|
||||||
phiMap[i] = new Phi[program.variableCount()];
|
phiMap[i] = new Phi[program.variableCount()];
|
||||||
phiIndexMap[i] = new int[program.variableCount()];
|
phiIndexMap[i] = new int[program.variableCount()];
|
||||||
|
@ -154,15 +141,9 @@ public class PhiUpdater {
|
||||||
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
|
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
|
||||||
|
|
||||||
synthesizedPhisByBlock.clear();
|
synthesizedPhisByBlock.clear();
|
||||||
synthesizedJointsByBlock.clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
synthesizedPhisByBlock.add(new ArrayList<>());
|
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()];
|
originalExceptionVariables = new Variable[program.basicBlockCount()];
|
||||||
|
@ -176,7 +157,6 @@ public class PhiUpdater {
|
||||||
|
|
||||||
private void estimatePhis() {
|
private void estimatePhis() {
|
||||||
DefinitionExtractor definitionExtractor = new DefinitionExtractor();
|
DefinitionExtractor definitionExtractor = new DefinitionExtractor();
|
||||||
List<List<TryCatchJoint>> inputJoints = getInputJoints(program);
|
|
||||||
variableDefined = new boolean[program.variableCount()];
|
variableDefined = new boolean[program.variableCount()];
|
||||||
|
|
||||||
IntDeque stack = new IntArrayDeque();
|
IntDeque stack = new IntArrayDeque();
|
||||||
|
@ -189,10 +169,6 @@ public class PhiUpdater {
|
||||||
markAssignment(currentBlock.getExceptionVariable());
|
markAssignment(currentBlock.getExceptionVariable());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TryCatchJoint joint : inputJoints.get(currentBlock.getIndex())) {
|
|
||||||
markAssignment(joint.getReceiver());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Phi phi : currentBlock.getPhis()) {
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
markAssignment(phi.getReceiver());
|
markAssignment(phi.getReceiver());
|
||||||
}
|
}
|
||||||
|
@ -200,20 +176,8 @@ public class PhiUpdater {
|
||||||
for (Instruction insn : currentBlock) {
|
for (Instruction insn : currentBlock) {
|
||||||
currentBlock = program.basicBlockAt(i);
|
currentBlock = program.basicBlockAt(i);
|
||||||
insn.acceptVisitor(definitionExtractor);
|
insn.acceptVisitor(definitionExtractor);
|
||||||
Set<Variable> definedVariables = new HashSet<>();
|
|
||||||
for (Variable var : definitionExtractor.getDefinedVariables()) {
|
for (Variable var : definitionExtractor.getDefinedVariables()) {
|
||||||
markAssignment(var);
|
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 {
|
private static class Task {
|
||||||
Variable[] variables;
|
Variable[] variables;
|
||||||
BasicBlock block;
|
BasicBlock block;
|
||||||
TryCatchBlock tryCatch;
|
|
||||||
int tryCatchIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renameVariables() {
|
private void renameVariables() {
|
||||||
|
@ -244,69 +206,35 @@ public class PhiUpdater {
|
||||||
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
|
Collections.fill(definedVersions, null);
|
||||||
Task task = stack.pop();
|
Task task = stack.pop();
|
||||||
|
|
||||||
currentBlock = task.block;
|
currentBlock = task.block;
|
||||||
currentTryCatch = task.tryCatch;
|
|
||||||
int index = currentBlock.getIndex();
|
int index = currentBlock.getIndex();
|
||||||
variableMap = task.variables.clone();
|
variableMap = task.variables.clone();
|
||||||
|
|
||||||
if (currentTryCatch == null) {
|
if (currentBlock.getExceptionVariable() != null) {
|
||||||
if (currentBlock.getExceptionVariable() != null) {
|
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean tryCatchIsSuccessor = currentTryCatch != null
|
for (Phi phi : synthesizedPhisByBlock.get(index)) {
|
||||||
&& domTree.immediateDominatorOf(currentTryCatch.getHandler().getIndex()) == index;
|
Variable var = program.createVariable();
|
||||||
if (currentTryCatch != null) {
|
var.setDebugName(phi.getReceiver().getDebugName());
|
||||||
for (TryCatchJoint joint : synthesizedJointsByBlock.get(index).get(task.tryCatchIndex)) {
|
var.setLabel(phi.getReceiver().getLabel());
|
||||||
Variable var = program.createVariable();
|
mapVariable(phi.getReceiver().getIndex(), var);
|
||||||
var.setDebugName(joint.getReceiver().getDebugName());
|
phisByReceiver.put(var.getIndex(), phi);
|
||||||
var.setLabel(joint.getReceiver().getLabel());
|
phi.setReceiver(var);
|
||||||
mapVariable(joint.getReceiver().getIndex(), var);
|
}
|
||||||
joint.setReceiver(var);
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
jointsByReceiver.put(var.getIndex(), joint);
|
phi.setReceiver(define(phi.getReceiver()));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int[] successors;
|
for (Instruction insn : currentBlock) {
|
||||||
List<TryCatchBlock> tryCatchBlockSuccessors = new ArrayList<>();
|
insn.acceptVisitor(consumer);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int[] successors = domGraph.outgoingEdges(index);
|
||||||
|
|
||||||
IntSet successorSet = IntOpenHashSet.from(successors);
|
IntSet successorSet = IntOpenHashSet.from(successors);
|
||||||
for (Incoming output : phiOutputs.get(index)) {
|
for (Incoming output : phiOutputs.get(index)) {
|
||||||
if (successorSet.contains(output.getPhi().getBasicBlock().getIndex())) {
|
if (successorSet.contains(output.getPhi().getBasicBlock().getIndex())) {
|
||||||
|
@ -314,13 +242,6 @@ public class PhiUpdater {
|
||||||
output.setValue(use(var));
|
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) {
|
for (int j = successors.length - 1; j >= 0; --j) {
|
||||||
int successor = successors[j];
|
int successor = successors[j];
|
||||||
|
@ -330,24 +251,13 @@ public class PhiUpdater {
|
||||||
stack.push(next);
|
stack.push(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = tryCatchBlockSuccessors.size() - 1; j >= 0; --j) {
|
IntSet exceptionHandlingSuccessors = new IntOpenHashSet();
|
||||||
TryCatchBlock tryCatch = tryCatchBlockSuccessors.get(j);
|
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||||
Task next = new Task();
|
exceptionHandlingSuccessors.add(tryCatch.getHandler().getIndex());
|
||||||
next.variables = variableMap.clone();
|
|
||||||
next.block = currentBlock;
|
|
||||||
next.tryCatch = tryCatch;
|
|
||||||
next.tryCatchIndex = j;
|
|
||||||
stack.push(next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTryCatch == null) {
|
for (int successor : cfg.outgoingEdges(index)) {
|
||||||
for (int successor : cfg.outgoingEdges(index)) {
|
renameOutgoingPhis(successor, exceptionHandlingSuccessors.contains(successor));
|
||||||
if (!tryCatchSuccessors.contains(successor)) {
|
|
||||||
renameOutgoingPhis(successor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
renameOutgoingPhis(currentTryCatch.getHandler().getIndex());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,21 +273,6 @@ public class PhiUpdater {
|
||||||
synthesizedPhis.add(phi);
|
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);
|
worklist.addLast(receiverIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int receiverIndex : jointsByReceiver.keys().toArray()) {
|
|
||||||
if (usedPhis.get(receiverIndex)) {
|
|
||||||
worklist.addLast(receiverIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IntSet visited = new IntOpenHashSet();
|
IntSet visited = new IntOpenHashSet();
|
||||||
while (!worklist.isEmpty()) {
|
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];
|
int[] phiIndexes = phiIndexMap[successor];
|
||||||
List<Phi> phis = synthesizedPhisByBlock.get(successor);
|
List<Phi> phis = synthesizedPhisByBlock.get(successor);
|
||||||
|
|
||||||
|
@ -430,6 +311,16 @@ public class PhiUpdater {
|
||||||
Phi phi = phis.get(j);
|
Phi phi = phis.get(j);
|
||||||
Variable var = variableMap[phiIndexes[j]];
|
Variable var = variableMap[phiIndexes[j]];
|
||||||
if (var != null) {
|
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 incoming = new Incoming();
|
||||||
incoming.setSource(currentBlock);
|
incoming.setSource(currentBlock);
|
||||||
incoming.setValue(var);
|
incoming.setValue(var);
|
||||||
|
@ -440,91 +331,66 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markAssignment(Variable var) {
|
private void markAssignment(Variable var) {
|
||||||
BasicBlock[] worklist = new BasicBlock[program.basicBlockCount() * 4];
|
Deque<BasicBlock> worklist = new ArrayDeque<>();
|
||||||
int head = 0;
|
worklist.push(currentBlock);
|
||||||
worklist[head++] = currentBlock;
|
|
||||||
|
|
||||||
if (variableDefined[var.getIndex()]) {
|
if (variableDefined[var.getIndex()]) {
|
||||||
BasicBlock startBlock = currentBlock;
|
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||||
List<TryCatchBlock> tryCatchBlocks = startBlock.getTryCatchBlocks();
|
placePhi(tryCatch.getHandler().getIndex(), var, currentBlock, worklist);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
variableDefined[var.getIndex()] = true;
|
variableDefined[var.getIndex()] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (head > 0) {
|
while (!worklist.isEmpty()) {
|
||||||
BasicBlock block = worklist[--head];
|
BasicBlock block = worklist.pop();
|
||||||
int[] frontiers = domFrontiers[block.getIndex()];
|
int[] frontiers = domFrontiers[block.getIndex()];
|
||||||
|
|
||||||
if (frontiers != null) {
|
if (frontiers != null) {
|
||||||
for (int frontier : frontiers) {
|
for (int frontier : frontiers) {
|
||||||
BasicBlock frontierBlock = program.basicBlockAt(frontier);
|
placePhi(frontier, var, block, worklist);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable define(Variable var) {
|
private void placePhi(int frontier, Variable var, BasicBlock block, Deque<BasicBlock> worklist) {
|
||||||
Variable old = variableMap[var.getIndex()];
|
BasicBlock frontierBlock = program.basicBlockAt(frontier);
|
||||||
Variable original = var;
|
if (frontierBlock.getExceptionVariable() == var) {
|
||||||
var = introduce(var);
|
return;
|
||||||
propagateToTryCatch(original, var, old);
|
}
|
||||||
mapVariable(original.getIndex(), var);
|
|
||||||
return var;
|
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) {
|
private Variable define(Variable var) {
|
||||||
for (int i = 0; i < currentBlock.getTryCatchBlocks().size(); ++i) {
|
Variable old = variableMap[var.getIndex()];
|
||||||
TryCatchBlock tryCatch = currentBlock.getTryCatchBlocks().get(i);
|
if (old != null) {
|
||||||
if (originalExceptionVariables[tryCatch.getHandler().getIndex()] == original) {
|
if (definedVersions.get(var.getIndex()) == null) {
|
||||||
continue;
|
definedVersions.set(var.getIndex(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
definedVersions.get(var.getIndex()).add(old);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variable original = var;
|
||||||
|
var = introduce(var);
|
||||||
|
mapVariable(original.getIndex(), var);
|
||||||
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mapVariable(int index, Variable var) {
|
private void mapVariable(int index, Variable var) {
|
||||||
|
@ -551,25 +417,13 @@ public class PhiUpdater {
|
||||||
private Variable use(Variable var) {
|
private Variable use(Variable var) {
|
||||||
Variable mappedVar = variableMap[var.getIndex()];
|
Variable mappedVar = variableMap[var.getIndex()];
|
||||||
if (mappedVar == null) {
|
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());
|
usedPhis.set(mappedVar.getIndex());
|
||||||
return mappedVar;
|
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() {
|
private InstructionVisitor consumer = new InstructionVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visit(EmptyInstruction insn) {
|
public void visit(EmptyInstruction insn) {
|
||||||
|
|
|
@ -36,10 +36,7 @@ import org.teavm.model.ProgramReader;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
import org.teavm.model.TryCatchBlockReader;
|
import org.teavm.model.TryCatchBlockReader;
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.TryCatchJointReader;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.VariableReader;
|
|
||||||
|
|
||||||
public final class ProgramUtils {
|
public final class ProgramUtils {
|
||||||
private ProgramUtils() {
|
private ProgramUtils() {
|
||||||
|
@ -110,6 +107,7 @@ public final class ProgramUtils {
|
||||||
InstructionReadVisitor visitor = new InstructionReadVisitor(copyReader);
|
InstructionReadVisitor visitor = new InstructionReadVisitor(copyReader);
|
||||||
while (from != to) {
|
while (from != to) {
|
||||||
from.acceptVisitor(visitor);
|
from.acceptVisitor(visitor);
|
||||||
|
copyReader.getCopy().setLocation(from.getLocation());
|
||||||
result.add(copyReader.getCopy());
|
result.add(copyReader.getCopy());
|
||||||
from = from.getNext();
|
from = from.getNext();
|
||||||
}
|
}
|
||||||
|
@ -138,25 +136,11 @@ public final class ProgramUtils {
|
||||||
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
TryCatchBlock tryCatchCopy = new TryCatchBlock();
|
||||||
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
tryCatchCopy.setExceptionType(tryCatch.getExceptionType());
|
||||||
tryCatchCopy.setHandler(target.basicBlockAt(tryCatch.getHandler().getIndex()));
|
tryCatchCopy.setHandler(target.basicBlockAt(tryCatch.getHandler().getIndex()));
|
||||||
tryCatchCopy.getJoints().addAll(copyTryCatchJoints(tryCatch, target));
|
|
||||||
result.add(tryCatchCopy);
|
result.add(tryCatchCopy);
|
||||||
}
|
}
|
||||||
return result;
|
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) {
|
public static List<List<Incoming>> getPhiOutputs(Program program) {
|
||||||
List<List<Incoming>> outputs = new ArrayList<>(program.basicBlockCount());
|
List<List<Incoming>> outputs = new ArrayList<>(program.basicBlockCount());
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
@ -175,23 +159,6 @@ public final class ProgramUtils {
|
||||||
return outputs;
|
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) {
|
public static BasicBlock[] getVariableDefinitionPlaces(Program program) {
|
||||||
BasicBlock[] places = new BasicBlock[program.variableCount()];
|
BasicBlock[] places = new BasicBlock[program.variableCount()];
|
||||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
|
@ -213,12 +180,6 @@ public final class ProgramUtils {
|
||||||
places[var.getIndex()] = block;
|
places[var.getIndex()] = block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
|
||||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
|
||||||
places[joint.getReceiver().getIndex()] = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return places;
|
return places;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,8 @@ package org.teavm.model.util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import org.teavm.common.DisjointSet;
|
import org.teavm.common.DisjointSet;
|
||||||
import org.teavm.common.MutableGraphEdge;
|
import org.teavm.common.MutableGraphEdge;
|
||||||
import org.teavm.common.MutableGraphNode;
|
import org.teavm.common.MutableGraphNode;
|
||||||
|
@ -33,15 +31,12 @@ import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ProgramReader;
|
import org.teavm.model.ProgramReader;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
|
||||||
public class RegisterAllocator {
|
public class RegisterAllocator {
|
||||||
public void allocateRegisters(MethodReader method, Program program) {
|
public void allocateRegisters(MethodReader method, Program program) {
|
||||||
insertJointArgumentsCopies(program);
|
|
||||||
insertPhiArgumentsCopies(program);
|
insertPhiArgumentsCopies(program);
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
|
@ -91,9 +86,6 @@ public class RegisterAllocator {
|
||||||
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
program.basicBlockAt(i).getPhis().clear();
|
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) {
|
private void insertPhiArgumentsCopies(Program program) {
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
Map<BasicBlock, BasicBlock> blockMap = new HashMap<>();
|
Map<BasicBlock, BasicBlock> blockMap = new HashMap<>();
|
||||||
|
@ -321,13 +277,6 @@ public class RegisterAllocator {
|
||||||
classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex());
|
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;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,14 +52,6 @@ public class TypeInferer {
|
||||||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
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);
|
IntegerStack stack = new IntegerStack(sz);
|
||||||
|
|
|
@ -8,9 +8,9 @@ $if0
|
||||||
invokeVirtual `Bar.baz()LBar;` @bar
|
invokeVirtual `Bar.baz()LBar;` @bar
|
||||||
@bar_1 := nullCheck @bar
|
@bar_1 := nullCheck @bar
|
||||||
goto $join
|
goto $join
|
||||||
catch java.lang.RuntimeException goto $if0Handler
|
catch java.lang.RuntimeException goto $if0Handler
|
||||||
@bar_2 := ephi @bar, @bar_1
|
|
||||||
$if0Handler
|
$if0Handler
|
||||||
|
@bar_2 := phi @bar from $if0, @bar_1 from $if0
|
||||||
goto $join
|
goto $join
|
||||||
$else
|
$else
|
||||||
invokeVirtual `Bar.baz()LBar;` @bar
|
invokeVirtual `Bar.baz()LBar;` @bar
|
||||||
|
@ -19,7 +19,7 @@ $else
|
||||||
$else1
|
$else1
|
||||||
invokeVirtual `Bar.baz2()LBar;` @bar_3
|
invokeVirtual `Bar.baz2()LBar;` @bar_3
|
||||||
goto $join
|
goto $join
|
||||||
catch java.lang.RuntimeException goto $elseHandler
|
catch java.lang.RuntimeException goto $elseHandler
|
||||||
$elseHandler
|
$elseHandler
|
||||||
goto $join
|
goto $join
|
||||||
$join
|
$join
|
||||||
|
|
|
@ -7,7 +7,7 @@ $start
|
||||||
$if0
|
$if0
|
||||||
invokeVirtual `Bar.baz()LBar;` @bar
|
invokeVirtual `Bar.baz()LBar;` @bar
|
||||||
goto $join
|
goto $join
|
||||||
catch java.lang.RuntimeException goto $if0Handler
|
catch java.lang.RuntimeException goto $if0Handler
|
||||||
$if0Handler
|
$if0Handler
|
||||||
goto $join
|
goto $join
|
||||||
$else
|
$else
|
||||||
|
@ -16,7 +16,7 @@ $else
|
||||||
$else1
|
$else1
|
||||||
invokeVirtual `Bar.baz2()LBar;` @bar
|
invokeVirtual `Bar.baz2()LBar;` @bar
|
||||||
goto $join
|
goto $join
|
||||||
catch java.lang.RuntimeException goto $elseHandler
|
catch java.lang.RuntimeException goto $elseHandler
|
||||||
$elseHandler
|
$elseHandler
|
||||||
goto $join
|
goto $join
|
||||||
$join
|
$join
|
||||||
|
|
|
@ -5,9 +5,9 @@ $start
|
||||||
invokeStatic `foo.Bar.baz()I`
|
invokeStatic `foo.Bar.baz()I`
|
||||||
@a_3 := 2
|
@a_3 := 2
|
||||||
return @a_3
|
return @a_3
|
||||||
catch java.lang.Exception goto $handler
|
catch java.lang.Exception goto $handler
|
||||||
@a_h := ephi @a_1, @a_2, @a_3
|
|
||||||
$handler
|
$handler
|
||||||
|
@a_h := phi @a_1 from $start, @a_2 from $start, @a_3 from $start
|
||||||
@e := exception
|
@e := exception
|
||||||
@out := field `java.lang.String.out` as `Ljava/io/PrintStream;`
|
@out := field `java.lang.String.out` as `Ljava/io/PrintStream;`
|
||||||
invokeVirtual `java.io.PrintStream.println(Ljava/lang/Object;)V` @out, @e
|
invokeVirtual `java.io.PrintStream.println(Ljava/lang/Object;)V` @out, @e
|
||||||
|
|
|
@ -3,8 +3,8 @@ $start
|
||||||
@a_1 := invokeStatic `Foo.baz()I`
|
@a_1 := invokeStatic `Foo.baz()I`
|
||||||
goto $end
|
goto $end
|
||||||
catch java.lang.RuntimeException goto $catch
|
catch java.lang.RuntimeException goto $catch
|
||||||
@a_2 := ephi @a, @a_1
|
|
||||||
$catch
|
$catch
|
||||||
|
@a_2 := phi @a from $start, @a_1 from $start
|
||||||
@b := 1
|
@b := 1
|
||||||
@a_3 := @a_2 + @b as int
|
@a_3 := @a_2 + @b as int
|
||||||
goto $end
|
goto $end
|
||||||
|
|
|
@ -3,17 +3,15 @@ $start
|
||||||
@a_1 := invokeStatic `Foo.baz()I`
|
@a_1 := invokeStatic `Foo.baz()I`
|
||||||
goto $second
|
goto $second
|
||||||
catch java.lang.RuntimeException goto $catch
|
catch java.lang.RuntimeException goto $catch
|
||||||
@a_2 := ephi @a, @a_1
|
|
||||||
$second
|
$second
|
||||||
@a_5 := invokeStatic `Foo.boo()I`
|
@a_2 := invokeStatic `Foo.boo()I`
|
||||||
goto $end
|
goto $end
|
||||||
catch java.lang.RuntimeException goto $catch
|
catch java.lang.RuntimeException goto $catch
|
||||||
@a_6 := ephi @a_1, @a_5
|
|
||||||
$catch
|
$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
|
@b := 1
|
||||||
@a_4 := @a_3 + @b as int
|
@a_4 := @a_3 + @b as int
|
||||||
goto $end
|
goto $end
|
||||||
$end
|
$end
|
||||||
@a_7 := phi @a_4 from $catch, @a_5 from $second
|
@a_5 := phi @a_2 from $second, @a_4 from $catch
|
||||||
return @a_7
|
return @a_5
|
|
@ -3,16 +3,14 @@ $start
|
||||||
@a_1 := invokeStatic `Foo.baz()I`
|
@a_1 := invokeStatic `Foo.baz()I`
|
||||||
goto $second
|
goto $second
|
||||||
catch goto $catch
|
catch goto $catch
|
||||||
@a_2 := ephi @a, @a_1
|
|
||||||
$second
|
$second
|
||||||
@a_3 := invokeStatic `Foo.bar2()I`
|
@a_2 := invokeStatic `Foo.bar2()I`
|
||||||
@a_4 := invokeStatic `Foo.baz2()I`
|
@a_3 := invokeStatic `Foo.baz2()I`
|
||||||
goto $end
|
goto $end
|
||||||
catch goto $catch
|
catch goto $catch
|
||||||
@a_5 := ephi @a_1, @a_3, @a_4
|
|
||||||
$catch
|
$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
|
goto $end
|
||||||
$end
|
$end
|
||||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
@a_5 := phi @a_3 from $second, @a_4 from $catch
|
||||||
return @a_7
|
return @a_5
|
||||||
|
|
|
@ -3,16 +3,14 @@ $start
|
||||||
@a_1 := invokeStatic `Foo.baz()I`
|
@a_1 := invokeStatic `Foo.baz()I`
|
||||||
goto $second
|
goto $second
|
||||||
catch goto $catch
|
catch goto $catch
|
||||||
@a_2 := ephi @a, @a_1
|
|
||||||
$second
|
$second
|
||||||
@a_3 := invokeStatic `Foo.bar2()I`
|
@a_2 := invokeStatic `Foo.bar2()I`
|
||||||
@a_4 := invokeStatic `Foo.baz2()I`
|
@a_3 := invokeStatic `Foo.baz2()I`
|
||||||
goto $end
|
goto $end
|
||||||
catch goto $catch
|
catch goto $catch
|
||||||
@a_5 := ephi @a_1, @a_3, @a_4
|
|
||||||
$catch
|
$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
|
goto $end
|
||||||
$end
|
$end
|
||||||
@a_7 := phi @a_4 from $second, @a_6 from $catch
|
@a_5 := phi @a_3 from $second, @a_4 from $catch
|
||||||
return @a_7
|
return @a_5
|
||||||
|
|
|
@ -22,8 +22,6 @@ import org.teavm.common.DisjointSet;
|
||||||
import org.teavm.model.BasicBlockReader;
|
import org.teavm.model.BasicBlockReader;
|
||||||
import org.teavm.model.PhiReader;
|
import org.teavm.model.PhiReader;
|
||||||
import org.teavm.model.ProgramReader;
|
import org.teavm.model.ProgramReader;
|
||||||
import org.teavm.model.TryCatchBlockReader;
|
|
||||||
import org.teavm.model.TryCatchJointReader;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.VariableReader;
|
import org.teavm.model.VariableReader;
|
||||||
import org.teavm.model.instructions.AbstractInstructionReader;
|
import org.teavm.model.instructions.AbstractInstructionReader;
|
||||||
|
@ -51,16 +49,6 @@ class AliasFinder {
|
||||||
set.union(inputs.iterator().next(), phi.getReceiver().getIndex());
|
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()];
|
int[] map = new int[set.size()];
|
||||||
|
|
|
@ -29,8 +29,6 @@ import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.PrimitiveType;
|
import org.teavm.model.PrimitiveType;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.TryCatchBlock;
|
|
||||||
import org.teavm.model.TryCatchJoint;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
@ -112,13 +110,6 @@ public class BoxingElimination {
|
||||||
union(phi.getReceiver().getIndex(), incoming.getValue().getIndex());
|
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