updated allow dead instructions handling

Added labels collecting:
Allow dead instruction block can have several starters and
one stopper that knows all corresponding starters by labels
This commit is contained in:
Svetlana Isakova
2012-12-07 20:09:27 +04:00
parent 28f1d288cf
commit bb2e1c04ec
6 changed files with 104 additions and 48 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.*;
import java.util.Collection;
import java.util.List;
/**
@@ -37,8 +38,12 @@ public interface JetControlFlowBuilder {
Label createUnboundLabel(@NotNull String name);
void bindLabel(@NotNull Label label);
void allowDead();
void stopAllowDead();
@NotNull
Label createAllowDeadLabel(@NotNull Collection<Label> allowDeadLabels);
@NotNull
Label createAllowDeadLabel(@NotNull String name, @NotNull Collection<Label> allowDeadLabels);
void stopAllowDead(@NotNull Collection<Label> allowDeadLabels);
// Jumps
void jump(@NotNull Label label);
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.*;
import java.util.Collection;
import java.util.List;
/**
@@ -61,16 +62,24 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
builder.bindLabel(label);
}
@NotNull
@Override
public void allowDead() {
public Label createAllowDeadLabel(@NotNull Collection<Label> allowDeadLabels) {
assert builder != null;
builder.allowDead();
return builder.createAllowDeadLabel(allowDeadLabels);
}
@NotNull
@Override
public Label createAllowDeadLabel(@NotNull String name, @NotNull Collection<Label> allowDeadLabels) {
assert builder != null;
return builder.createAllowDeadLabel(name, allowDeadLabels);
}
@Override
public void stopAllowDead() {
public void stopAllowDead(@NotNull Collection<Label> allowDeadLabels) {
assert builder != null;
builder.stopAllowDead();
builder.stopAllowDead(allowDeadLabels);
}
@Override
@@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -378,8 +379,9 @@ public class JetControlFlowProcessor {
}
value(expression.getTryBlock(), inCondition);
Collection<Label> allowDeadLabels = Lists.newArrayList();
if (hasCatches) {
builder.allowDead();
builder.createAllowDeadLabel(allowDeadLabels);
Label afterCatches = builder.createUnboundLabel("afterCatches");
builder.jump(afterCatches);
@@ -407,14 +409,14 @@ public class JetControlFlowProcessor {
if (catchBody != null) {
value(catchBody, false);
}
builder.allowDead();
builder.createAllowDeadLabel(allowDeadLabels);
builder.jump(afterCatches);
}
builder.bindLabel(afterCatches);
}
else {
builder.allowDead();
builder.createAllowDeadLabel(allowDeadLabels);
}
if (finallyBlock != null) {
@@ -429,7 +431,7 @@ public class JetControlFlowProcessor {
value(finallyBlock.getFinalExpression(), inCondition);
}
builder.stopAllowDead();
builder.stopAllowDead(allowDeadLabels);
}
@Override
@@ -784,6 +786,7 @@ public class JetControlFlowProcessor {
Label doneLabel = builder.createUnboundLabel();
Label nextLabel = null;
Collection<Label> allowDeadLabels = Lists.newArrayList();
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
JetWhenEntry whenEntry = iterator.next();
@@ -818,7 +821,7 @@ public class JetControlFlowProcessor {
builder.bindLabel(bodyLabel);
value(whenEntry.getExpression(), inCondition);
builder.allowDead();
builder.createAllowDeadLabel(allowDeadLabels);
builder.jump(doneLabel);
if (!isIrrefutable) {
@@ -830,7 +833,7 @@ public class JetControlFlowProcessor {
if (!hasElseOrIrrefutableBranch && !isWhenExhaust) {
trace.report(NO_ELSE_IN_WHEN.on(expression));
}
builder.stopAllowDead();
builder.stopAllowDead(allowDeadLabels);
}
@Override
@@ -21,4 +21,5 @@ package org.jetbrains.jet.lang.cfg;
*/
public interface Label {
String getName();
boolean allowDead();
}
@@ -30,6 +30,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
private final Stack<BreakableBlockInfo> loopInfo = new Stack<BreakableBlockInfo>();
private final Map<JetElement, BreakableBlockInfo> elementToBlockInfo = new HashMap<JetElement, BreakableBlockInfo>();
private int labelCount = 0;
private int allowDeadLabelCount = 0;
private final Stack<JetControlFlowInstructionsGeneratorWorker> builders = new Stack<JetControlFlowInstructionsGeneratorWorker>();
@@ -272,18 +273,26 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
pseudocode.bindLabel(label);
}
@NotNull
@Override
public void allowDead() {
Label allowedDeadLabel = createUnboundLabel();
bindLabel(allowedDeadLabel);
pseudocode.allowDead(allowedDeadLabel);
public Label createAllowDeadLabel(@NotNull Collection<Label> allowDeadLabels) {
return createAllowDeadLabel("d" + allowDeadLabelCount++, allowDeadLabels);
}
@NotNull
@Override
public Label createAllowDeadLabel(@NotNull String name, @NotNull Collection<Label> allowDeadLabels) {
Label label = pseudocode.createAllowDeadLabel(name);
bindLabel(label);
allowDeadLabels.add(label);
return label;
}
@Override
public void stopAllowDead() {
Label allowedDeadLabel = createUnboundLabel();
public void stopAllowDead(@NotNull Collection<Label> allowDeadLabels) {
Label allowedDeadLabel = createUnboundLabel("stop " + allowDeadLabels);
bindLabel(allowedDeadLabel);
pseudocode.stopAllowDead(allowedDeadLabel);
pseudocode.stopAllowDead(allowedDeadLabel, allowDeadLabels);
}
@Override
@@ -36,11 +36,13 @@ public class PseudocodeImpl implements Pseudocode {
public class PseudocodeLabel implements Label {
private final String name;
private final boolean allowDead;
private Integer targetInstructionIndex;
private PseudocodeLabel(String name) {
private PseudocodeLabel(String name, boolean allowDead) {
this.name = name;
this.allowDead = allowDead;
}
@Override
@@ -48,6 +50,11 @@ public class PseudocodeImpl implements Pseudocode {
return name;
}
@Override
public boolean allowDead() {
return allowDead;
}
@Override
public String toString() {
return name;
@@ -85,8 +92,7 @@ public class PseudocodeImpl implements Pseudocode {
private final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> stopAllowDeadLabels = new ArrayList<PseudocodeLabel>();
private final Map<PseudocodeLabel, Collection<Label>> stopAllowDeadLabels = Maps.newHashMap();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
@@ -126,17 +132,21 @@ public class PseudocodeImpl implements Pseudocode {
}
/*package*/ PseudocodeLabel createLabel(String name) {
PseudocodeLabel label = new PseudocodeLabel(name);
return createLabel(name, false);
}
private PseudocodeLabel createLabel(String name, boolean allowDead) {
PseudocodeLabel label = new PseudocodeLabel(name, allowDead);
labels.add(label);
return label;
}
/*package*/ void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label);
/*package*/ Label createAllowDeadLabel(String name) {
return createLabel(name, true);
}
/*package*/ void stopAllowDead(Label label) {
stopAllowDeadLabels.add((PseudocodeLabel) label);
/*package*/ void stopAllowDead(Label label, Collection<Label> allowDeadLabels) {
stopAllowDeadLabels.put((PseudocodeLabel) label, allowDeadLabels);
}
@Override
@@ -373,24 +383,26 @@ public class PseudocodeImpl implements Pseudocode {
}
@NotNull
private Set<Instruction> prepareAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
allowedDeadStartInstructions.add(allowedDeadInstruction);
private Map<Instruction, Label> prepareAllowDeadStarters() {
Map<Instruction, Label> allowedDeadBeginners = Maps.newHashMap();
for (PseudocodeLabel label : labels) {
if (!label.allowDead()) continue;
Instruction allowDeadPossibleBeginner = getJumpTarget(label);
if (((InstructionImpl)allowDeadPossibleBeginner).isDead()) {
allowedDeadBeginners.put(allowDeadPossibleBeginner, label);
}
}
return allowedDeadStartInstructions;
return allowedDeadBeginners;
}
@NotNull
private Set<Instruction> prepareStopAllowedDeadInstructions() {
Set<Instruction> stopAllowedDeadInstructions = Sets.newHashSet();
for (PseudocodeLabel stopAllowedDeadLabel : stopAllowDeadLabels) {
private Map<Instruction, Collection<Label>> prepareAllowDeadStoppers() {
Map<Instruction, Collection<Label>> stopAllowedDeadInstructions = Maps.newHashMap();
for (Map.Entry<PseudocodeLabel, Collection<Label>> entry : stopAllowDeadLabels.entrySet()) {
PseudocodeLabel stopAllowedDeadLabel = entry.getKey();
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.add(stopAllowDeadInsruction);
stopAllowedDeadInstructions.put(stopAllowDeadInsruction, entry.getValue());
}
}
return stopAllowedDeadInstructions;
@@ -398,22 +410,39 @@ public class PseudocodeImpl implements Pseudocode {
@NotNull
private Collection<Instruction> collectAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
Set<Instruction> stopAllowDeadInstructions = prepareStopAllowedDeadInstructions();
// Allow dead instruction block can have several starters and
// one stopper that knows all corresponding starters by labels
Map<Instruction, Label> allowDeadStarters = prepareAllowDeadStarters();
Map<Instruction, Collection<Label>> allowDeadStoppers = prepareAllowDeadStoppers();
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions, stopAllowDeadInstructions);
for (Map.Entry<Instruction, Label> entry : allowDeadStarters.entrySet()) {
Instruction starter = entry.getKey();
Set<Instruction> allowedDeadFromThisInstruction = Sets.newHashSet();
Label starterLabel = entry.getValue();
collectAllowedDeadInstructions(starter, starterLabel, allowedDeadFromThisInstruction, allowDeadStoppers);
allowedDeadInstructions.addAll(allowedDeadFromThisInstruction);
}
return allowedDeadInstructions;
}
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet, Set<Instruction> stopAllowDeadInstructions) {
if (instructionSet.contains(allowedDeadInstruction) || stopAllowDeadInstructions.contains(allowedDeadInstruction)) return;
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
instructionSet.add(allowedDeadInstruction);
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, instructionSet, stopAllowDeadInstructions);
private static void collectAllowedDeadInstructions(
@NotNull Instruction current,
@NotNull Label starterLabel,
@NotNull Set<Instruction> collectedDeadInstructions,
@NotNull Map<Instruction, Collection<Label>> allowDeadStoppers
) {
if (collectedDeadInstructions.contains(current)) return;
Collection<Label> allowDeadLabels = allowDeadStoppers.get(current);
boolean isStopper = allowDeadLabels != null && allowDeadLabels.contains(starterLabel);
if (isStopper) return;
if (((InstructionImpl)current).isDead()) {
collectedDeadInstructions.add(current);
for (Instruction instruction : current.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, starterLabel, collectedDeadInstructions, allowDeadStoppers);
}
}
}