From bd31f36836040deb6b507a84a49bc1c43fae1adb Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 11 Dec 2012 18:29:15 +0400 Subject: [PATCH] added repeat pseudocode method repeat from startLabel to finishLabel (logic is inside PseudocodeImpl) --- .../jet/lang/cfg/JetControlFlowBuilder.java | 2 + .../cfg/JetControlFlowBuilderAdapter.java | 6 ++ .../jet/lang/cfg/JetControlFlowProcessor.java | 33 +++++++- .../JetControlFlowInstructionsGenerator.java | 5 ++ .../lang/cfg/pseudocode/PseudocodeImpl.java | 78 +++++++++++++++++-- 5 files changed, 115 insertions(+), 9 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java index 2cf2df1f776..a1f1e69dbac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -88,4 +88,6 @@ public interface JetControlFlowBuilder { // Other void unsupported(JetElement element); + + void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java index 3e58dc15762..dcc16c88dc6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -222,4 +222,10 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { assert builder != null; builder.declare(property); } + + @Override + public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) { + assert builder != null; + builder.repeatPseudocode(startLabel, finishLabel); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index ad61ae1fe3e..2d9dde278e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -345,11 +345,38 @@ public class JetControlFlowProcessor { } builder.bindLabel(resultLabel); } + + private class FinallyBlockGenerator { + private final JetFinallySection finallyBlock; + private Label startFinally = null; + private Label finishFinally = null; + + private FinallyBlockGenerator(JetFinallySection block) { + finallyBlock = block; + } + + public void generate() { + JetBlockExpression finalExpression = finallyBlock.getFinalExpression(); + if (finalExpression == null) return; + if (startFinally != null) { + assert finishFinally != null; + builder.repeatPseudocode(startFinally, finishFinally); + return; + } + startFinally = builder.createUnboundLabel("start finally"); + builder.bindLabel(startFinally); + value(finalExpression, inCondition); + finishFinally = builder.createUnboundLabel("finish finally"); + builder.bindLabel(finishFinally); + } + } + @Override public void visitTryExpression(JetTryExpression expression) { builder.read(expression); final JetFinallySection finallyBlock = expression.getFinallyBlock(); + final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock); if (finallyBlock != null) { builder.enterTryFinally(new GenerationTrigger() { private boolean working = false; @@ -359,7 +386,7 @@ public class JetControlFlowProcessor { // This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}' if (working) return; working = true; - value(finallyBlock.getFinalExpression(), inCondition); + finallyBlockGenerator.generate(); working = false; } }); @@ -425,11 +452,11 @@ public class JetControlFlowProcessor { Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock"); builder.jump(skipFinallyToErrorBlock); builder.bindLabel(onExceptionToFinallyBlock); - value(finallyBlock.getFinalExpression(), inCondition); + finallyBlockGenerator.generate(); builder.jumpToError(); builder.bindLabel(skipFinallyToErrorBlock); - value(finallyBlock.getFinalExpression(), inCondition); + finallyBlockGenerator.generate(); } builder.stopAllowDead(allowDeadLabels); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java index 11821754e77..42ce80f3e2a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java @@ -328,6 +328,11 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd public void unsupported(JetElement element) { add(new UnsupportedElementInstruction(element)); } + + @Override + public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) { + pseudocode.repeatPart(startLabel, finishLabel); + } } public static class TryFinallyBlockInfo extends BlockInfo { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index c23e8eb6f20..ca13f276ac4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -16,9 +16,8 @@ package org.jetbrains.jet.lang.cfg.pseudocode; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import com.google.common.collect.*; +import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.Label; @@ -79,6 +78,9 @@ public class PseudocodeImpl implements Pseudocode { return mutableInstructionList.get(targetInstructionIndex); } + public Label copy() { + return new PseudocodeLabel("copy " + name, allowDead); + } } private final List mutableInstructionList = new ArrayList(); @@ -92,7 +94,7 @@ public class PseudocodeImpl implements Pseudocode { private final Map loopInfo = Maps.newHashMap(); private final List labels = new ArrayList(); - private final Map> stopAllowDeadLabels = Maps.newHashMap(); + private final Map> stopAllowDeadLabels = Maps.newHashMap(); private final JetElement correspondingElement; private SubroutineExitInstruction exitInstruction; @@ -398,8 +400,8 @@ public class PseudocodeImpl implements Pseudocode { @NotNull private Map> prepareAllowDeadStoppers() { Map> stopAllowedDeadInstructions = Maps.newHashMap(); - for (Map.Entry> entry : stopAllowDeadLabels.entrySet()) { - PseudocodeLabel stopAllowedDeadLabel = entry.getKey(); + for (Map.Entry> entry : stopAllowDeadLabels.entrySet()) { + Label stopAllowedDeadLabel = entry.getKey(); Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel); if (((InstructionImpl)stopAllowDeadInsruction).isDead()) { stopAllowedDeadInstructions.put(stopAllowDeadInsruction, entry.getValue()); @@ -458,4 +460,68 @@ public class PseudocodeImpl implements Pseudocode { assert targetPosition < mutableInstructionList.size() : currentPosition; return mutableInstructionList.get(targetPosition); } + + public void repeatPart(@NotNull Label startLabel, @NotNull Label finishLabel) { + Integer startIndex = ((PseudocodeLabel) startLabel).getTargetInstructionIndex(); + assert startIndex != null; + Integer finishIndex = ((PseudocodeLabel) finishLabel).getTargetInstructionIndex(); + assert finishIndex != null; + + Map originalToCopy = Maps.newHashMap(); + Multimap originalLabelsForInstruction = HashMultimap.create(); + for (PseudocodeLabel label : labels) { + Integer index = label.getTargetInstructionIndex(); + if (index == null) continue; //label is not bounded yet + if (label == startLabel || label == finishLabel) continue; + + if (startIndex <= index && index <= finishIndex) { + originalToCopy.put(label, label.copy()); + originalLabelsForInstruction.put(getJumpTarget(label), label); + } + } + for (int index = startIndex; index < finishIndex; index++) { + Instruction oldInstruction = mutableInstructionList.get(index); + Instruction newInstruction = copyInstruction(oldInstruction, originalToCopy); + if (originalLabelsForInstruction.containsKey(oldInstruction)) { + Collection