diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java index 7fd6e252c82..874f163e514 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -32,22 +32,22 @@ import java.util.*; public class JetControlFlowGraphTraverser { private final Pseudocode pseudocode; private final boolean lookInside; - private final boolean straightDirection; + private final boolean directOrder; private final Map> dataMap = Maps.newLinkedHashMap(); public static JetControlFlowGraphTraverser create(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { return new JetControlFlowGraphTraverser(pseudocode, lookInside, straightDirection); } - private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { + private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean directOrder) { this.pseudocode = pseudocode; this.lookInside = lookInside; - this.straightDirection = straightDirection; + this.directOrder = directOrder; } @NotNull private Instruction getStartInstruction(@NotNull Pseudocode pseudocode) { - return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); + return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } @NotNull @@ -84,42 +84,21 @@ public class JetControlFlowGraphTraverser { } } - private static List reverseInstructions(@NotNull Pseudocode pseudocode) { - LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); - Instruction sinkInstruction = pseudocode.getSinkInstruction(); - traverseInstructions(sinkInstruction, traversedInstructions); - return Lists.newArrayList(traversedInstructions); - } - - private static void traverseInstructions(@NotNull Instruction instruction, @NotNull LinkedHashSet instructions) { - if (((InstructionImpl)instruction).isDead()) return; - if (instructions.contains(instruction)) return; - instructions.add(instruction); - for (Instruction previousInstruction : instruction.getPreviousInstructions()) { - traverseInstructions(previousInstruction, instructions); - } - } - private void traverseSubGraph( @NotNull Pseudocode pseudocode, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @NotNull Collection previousSubGraphInstructions, boolean[] changed, boolean isLocal) { - List instructions = pseudocode.getInstructions(); + List instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); Instruction startInstruction = getStartInstruction(pseudocode); - if (!straightDirection) { - instructions = reverseInstructions(pseudocode); - } for (Instruction instruction : instructions) { - boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; + boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; if (!isLocal && isStart) continue; Collection allPreviousInstructions; - Collection previousInstructions = straightDirection - ? instruction.getPreviousInstructions() - : instruction.getNextInstructions(); + Collection previousInstructions = directOrder ? instruction.getPreviousInstructions() : instruction.getNextInstructions(); if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { allPreviousInstructions = Lists.newArrayList(previousInstructions); @@ -132,7 +111,7 @@ public class JetControlFlowGraphTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true); - Instruction lastInstruction = straightDirection ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); + Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); Pair previousValue = dataMap.get(instruction); Pair newValue = dataMap.get(lastInstruction); if (!previousValue.equals(newValue)) { @@ -168,7 +147,7 @@ public class JetControlFlowGraphTraverser { @NotNull Pseudocode pseudocode, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { List instructions = pseudocode.getInstructions(); - if (!straightDirection) { + if (!directOrder) { instructions = Lists.newArrayList(instructions); Collections.reverse(instructions); } 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 20837493531..fa4d265e80f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator; import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl; @@ -57,8 +58,8 @@ public class JetControlFlowProcessor { public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) { Pseudocode pseudocode = generate(subroutine); ((PseudocodeImpl)pseudocode).postProcess(); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - ((PseudocodeImpl)localPseudocode).postProcess(); + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + ((PseudocodeImpl)localDeclarationInstruction.getBody()).postProcess(); } return pseudocode; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 01558871026..c643fe1a65b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -140,7 +140,7 @@ public class JetFlowInformationProvider { } final boolean blockBody = function.hasBlockBody(); - final Set rootUnreachableElements = collectUnreachableCode(function.asElement()); + final Set rootUnreachableElements = collectUnreachableCode(); for (JetElement element : rootUnreachableElements) { trace.report(UNREACHABLE_CODE.on(element)); } @@ -168,7 +168,7 @@ public class JetFlowInformationProvider { } } - private Set collectUnreachableCode(@NotNull JetElement subroutine) { + private Set collectUnreachableCode() { Collection unreachableElements = Lists.newArrayList(); for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { if (deadInstruction instanceof JetElementInstruction && @@ -223,8 +223,8 @@ public class JetFlowInformationProvider { Pseudocode pseudocode = pseudocodeData.getPseudocode(); recordInitializedVariables(pseudocodeData.getDeclarationData(pseudocode), pseudocodeData.getResultInfo(pseudocode)); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - recordInitializedVariables(pseudocodeData.getDeclarationData(localPseudocode), pseudocodeData.getResultInfo(localPseudocode)); + for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) { + recordInitializedVariables(pseudocodeData.getDeclarationData(instruction.getBody()), pseudocodeData.getResultInfo(instruction.getBody())); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java index d78011e47a4..ccb6173d932 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/data/PseudocodeData.java @@ -119,8 +119,8 @@ public class PseudocodeData { DeclarationData declarationData = new DeclarationData(pseudocode.getCorrespondingElement(), this, collectDeclaredVariables(pseudocode), collectUsedVariables(pseudocode)); declarationDataMap.put(pseudocode, declarationData); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { - collectDeclarationData(localPseudocode); + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + collectDeclarationData(localDeclarationInstruction.getBody()); } } @@ -180,7 +180,9 @@ public class PseudocodeData { Map, Map>> result = traverser.getDataMap(); - for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) { + + for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) { + Pseudocode localPseudocode = localDeclarationInstruction.getBody(); Map, Map>> initializersForLocalDeclaration = collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java index 990c2142c9c..fd8639d94f9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/LocalDeclarationInstruction.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetElement; import java.util.ArrayList; import java.util.Collection; @@ -40,6 +41,12 @@ public class LocalDeclarationInstruction extends InstructionWithNext { return body; } + @NotNull + @Override + public JetDeclaration getElement() { + return (JetDeclaration) super.getElement(); + } + @NotNull @Override public Collection getNextInstructions() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java index 85d141b7e21..8394b6725ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java @@ -30,11 +30,14 @@ public interface Pseudocode { JetElement getCorrespondingElement(); @NotNull - Set getLocalDeclarations(); + Set getLocalDeclarations(); @NotNull List getInstructions(); + @NotNull + List getReversedInstructions(); + @NotNull List getDeadInstructions(); 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 c648dcadb03..8eb651cf4a0 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 @@ -76,10 +76,13 @@ public class PseudocodeImpl implements Pseudocode { private final List mutableInstructionList = new ArrayList(); private final List instructions = new ArrayList(); + private List reversedInstructions = null; private List deadInstructions; - final Map representativeInstructions = new HashMap(); - final Map loopInfo = Maps.newHashMap(); + private Set localDeclarations = null; + //todo getters + private final Map representativeInstructions = new HashMap(); + private final Map loopInfo = Maps.newHashMap(); private final List labels = new ArrayList(); private final List allowedDeadLabels = new ArrayList(); @@ -103,28 +106,30 @@ public class PseudocodeImpl implements Pseudocode { @NotNull @Override - public Set getLocalDeclarations() { - Set localDeclarations = Sets.newLinkedHashSet(); - //todo look recursively inside local declarations - for (Instruction instruction : instructions) { - if (instruction instanceof LocalDeclarationInstruction) { - localDeclarations.add(((LocalDeclarationInstruction) instruction).getBody()); + public Set getLocalDeclarations() { + if (localDeclarations == null) { + localDeclarations = Sets.newLinkedHashSet(); + //todo look recursively inside local declarations + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + localDeclarations.add((LocalDeclarationInstruction) instruction); + } } } return localDeclarations; } - public PseudocodeLabel createLabel(String name) { + /*package*/ PseudocodeLabel createLabel(String name) { PseudocodeLabel label = new PseudocodeLabel(name); labels.add(label); return label; } - public void allowDead(Label label) { + /*package*/ void allowDead(Label label) { allowedDeadLabels.add((PseudocodeLabel) label); } - public void stopAllowDead(Label label) { + /*package*/ void stopAllowDead(Label label) { stopAllowDeadLabels.add((PseudocodeLabel) label); } @@ -134,9 +139,30 @@ public class PseudocodeImpl implements Pseudocode { return instructions; } - @Deprecated //for tests only @NotNull - public List getMutableInstructionList() { + @Override + public List getReversedInstructions() { + if (reversedInstructions == null) { + LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); + traverseInstructionsInReverseOrder(sinkInstruction, traversedInstructions); + reversedInstructions = Lists.newArrayList(traversedInstructions); + } + return reversedInstructions; + } + + private static void traverseInstructionsInReverseOrder(@NotNull Instruction instruction, + @NotNull LinkedHashSet instructions) { + if (instructions.contains(instruction)) return; + instructions.add(instruction); + for (Instruction previousInstruction : instruction.getPreviousInstructions()) { + traverseInstructionsInReverseOrder(previousInstruction, instructions); + } + } + + + //for tests only + @NotNull + public List getAllInstructions() { return mutableInstructionList; } @@ -159,31 +185,31 @@ public class PseudocodeImpl implements Pseudocode { return deadInstructions; } - @Deprecated //for tests only + //for tests only @NotNull public List getLabels() { return labels; } - public void addExitInstruction(SubroutineExitInstruction exitInstruction) { + /*package*/ void addExitInstruction(SubroutineExitInstruction exitInstruction) { addInstruction(exitInstruction); assert this.exitInstruction == null; this.exitInstruction = exitInstruction; } - public void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) { + /*package*/ void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) { addInstruction(sinkInstruction); assert this.sinkInstruction == null; this.sinkInstruction = sinkInstruction; } - public void addErrorInstruction(SubroutineExitInstruction errorInstruction) { + /*package*/ void addErrorInstruction(SubroutineExitInstruction errorInstruction) { addInstruction(errorInstruction); assert this.errorInstruction == null; this.errorInstruction = errorInstruction; } - public void addInstruction(Instruction instruction) { + /*package*/ void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); @@ -193,7 +219,7 @@ public class PseudocodeImpl implements Pseudocode { } } - public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { + /*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { loopInfo.put(expression, blockInfo); } @@ -215,7 +241,7 @@ public class PseudocodeImpl implements Pseudocode { return (SubroutineEnterInstruction) mutableInstructionList.get(0); } - public void bindLabel(Label label) { + /*package*/ void bindLabel(Label label) { ((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size()); }