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 b4581a9200a..31bfcec6ce7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java @@ -19,6 +19,7 @@ public interface JetControlFlowBuilder { void bindLabel(@NotNull Label label); void allowDead(); + void stopAllowDead(); // Jumps void jump(@NotNull Label label); 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 d42a0cbd726..0c6ea512103 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java @@ -43,6 +43,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder { builder.allowDead(); } + @Override + public void stopAllowDead() { + assert builder != null; + builder.stopAllowDead(); + } + @Override public void jump(@NotNull Label label) { assert builder != null; 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 7befd95b142..9b35e30ec89 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -8,10 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.pseudocode.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author svtk @@ -140,7 +137,6 @@ public class JetControlFlowGraphTraverser { Collections.reverse(instructions); } for (Instruction instruction : instructions) { - if (instruction.isDead()) continue; if (lookInside && instruction instanceof LocalDeclarationInstruction) { traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); } 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 c3dab813a27..3c32dfc6c2d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -408,6 +408,7 @@ public class JetControlFlowProcessor { builder.exitTryFinally(); value(finallyBlock.getFinalExpression(), inCondition); } + builder.stopAllowDead(); } @Override 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 37c96d9dce7..c0284d377b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -252,7 +252,10 @@ public class JetFlowInformationProvider { analyzeLocalDeclarations(processLocalDeclaration, pseudocode); } - private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, @NotNull JetElement element, @NotNull VariableInitializers variableInitializers, @NotNull Collection varWithUninitializedErrorGenerated) { + private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetElement element, + @NotNull VariableInitializers variableInitializers, + @NotNull Collection varWithUninitializedErrorGenerated) { if (!(element instanceof JetSimpleNameExpression)) return; boolean isInitialized = variableInitializers.isInitialized(); @@ -272,7 +275,10 @@ public class JetFlowInformationProvider { } } - private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull Collection varWithValReassignErrorGenerated) { + private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, + @NotNull JetExpression expression, + @NotNull VariableInitializers enterInitializers, + @NotNull Collection varWithValReassignErrorGenerated) { boolean isInitializedNotHere = enterInitializers.isInitialized(); Set possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); if (possibleLocalInitializers.size() == 1) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java index 63f759c81d1..4a2cf3832e6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Instruction.java @@ -20,6 +20,4 @@ public interface Instruction { Collection getNextInstructions(); void accept(InstructionVisitor visitor); - - boolean isDead(); } 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 0d6ac71d32c..71d5ffc290e 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 @@ -190,7 +190,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd bindLabel(getExitPoint(subroutine)); pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "")); bindLabel(error); - add(new SubroutineExitInstruction(subroutine, "")); + pseudocode.addErrorInstruction(new SubroutineExitInstruction(subroutine, "")); bindLabel(sink); pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "")); elementToBlockInfo.remove(subroutine); @@ -266,6 +266,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd pseudocode.allowDead(allowedDeadLabel); } + @Override + public void stopAllowDead() { + Label allowedDeadLabel = createUnboundLabel(); + bindLabel(allowedDeadLabel); + pseudocode.stopAllowDead(allowedDeadLabel); + } + @Override public void nondeterministicJump(Label label) { handleJumpInsideTryFinally(label); 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 520b52437a8..f9e1ea2ded1 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 @@ -56,12 +56,16 @@ public class Pseudocode { private final List mutableInstructionList = new ArrayList(); private final List instructions = new ArrayList(); + private List deadInstructions; + private final List labels = new ArrayList(); private final List allowedDeadLabels = new ArrayList(); + private final List stopAllowDeadLabels = new ArrayList(); private final JetElement correspondingElement; private SubroutineExitInstruction exitInstruction; private SubroutineSinkInstruction sinkInstruction; + private SubroutineExitInstruction errorInstruction; private boolean postPrecessed = false; public Pseudocode(JetElement correspondingElement) { @@ -81,6 +85,10 @@ public class Pseudocode { public void allowDead(Label label) { allowedDeadLabels.add((PseudocodeLabel) label); } + + public void stopAllowDead(Label label) { + stopAllowDeadLabels.add((PseudocodeLabel) label); + } @NotNull public List getInstructions() { @@ -95,10 +103,17 @@ public class Pseudocode { @NotNull public List getDeadInstructions() { - List deadInstructions = Lists.newArrayList(); - for (Instruction instruction : instructions) { - if (instruction.isDead()) { - deadInstructions.add(instruction); + if (deadInstructions != null) { + return deadInstructions; + } + deadInstructions = Lists.newArrayList(); + Collection allowedDeadInstructions = collectAllowedDeadInstructions(); + + for (Instruction instruction : mutableInstructionList) { + if (((InstructionImpl)instruction).isDead()) { + if (!allowedDeadInstructions.contains(instruction)) { + deadInstructions.add(instruction); + } } } return deadInstructions; @@ -122,6 +137,12 @@ public class Pseudocode { this.sinkInstruction = sinkInstruction; } + public void addErrorInstruction(SubroutineExitInstruction errorInstruction) { + addInstruction(errorInstruction); + assert this.errorInstruction == null; + this.errorInstruction = errorInstruction; + } + public void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); @@ -151,88 +172,107 @@ public class Pseudocode { if (postPrecessed) return; postPrecessed = true; for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) { - Instruction instruction = mutableInstructionList.get(i); - final int currentPosition = i; - instruction.accept(new InstructionVisitor() { - @Override - public void visitInstructionWithNext(InstructionWithNext instruction) { - instruction.setNext(getNextPosition(currentPosition)); - } - - @Override - public void visitJump(AbstractJumpInstruction instruction) { - instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel())); - } - - @Override - public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { - instruction.setNext(getNextPosition(currentPosition)); - List