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 80f8d5b1b0f..88dd8b70018 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -118,18 +118,26 @@ public class JetFlowInformationProvider { Pseudocode pseudocode = pseudocodeMap.get(subroutine); assert pseudocode != null; - SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); - Set visited = new HashSet(); - collectReachable(enterInstruction, visited, null); - - for (Instruction instruction : pseudocode.getInstructions()) { - if (!visited.contains(instruction) && - instruction instanceof JetElementInstruction && + for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { + if (deadInstruction instanceof JetElementInstruction && // TODO : do {return} while (1 > a) - !(instruction instanceof ReadUnitValueInstruction)) { - unreachableElements.add(((JetElementInstruction) instruction).getElement()); + !(deadInstruction instanceof ReadUnitValueInstruction)) { + unreachableElements.add(((JetElementInstruction) deadInstruction).getElement()); } } + +// SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); +// Set visited = new HashSet(); +// collectReachable(enterInstruction, visited, null); +// +// for (Instruction instruction : pseudocode.getInstructions()) { +// if (!visited.contains(instruction) && +// instruction instanceof JetElementInstruction && +// // TODO : do {return} while (1 > a) +// !(instruction instanceof ReadUnitValueInstruction)) { +// unreachableElements.add(((JetElementInstruction) instruction).getElement()); +// } +// } } // public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection dominated) { // Instruction dominatorInstruction = representativeInstructions.get(dominator); @@ -248,7 +256,11 @@ public class JetFlowInformationProvider { // } // } - private Map traverseInstructionGraphUntilFactsStabilization(Pseudocode pseudocode, InstructionsMergeHandler instructionsMergeHandler, D initialDataValue, boolean straightDirection) { + private Map traverseInstructionGraphUntilFactsStabilization( + Pseudocode pseudocode, + InstructionsMergeHandler instructionsMergeHandler, + D initialDataValue, + boolean straightDirection) { Map dataMap = Maps.newHashMap(); initializeDataMap(dataMap, pseudocode, initialDataValue); @@ -261,7 +273,10 @@ public class JetFlowInformationProvider { return dataMap; } - private void initializeDataMap(Map dataMap, Pseudocode pseudocode, D initialDataValue) { + private void initializeDataMap( + Map dataMap, + Pseudocode pseudocode, + D initialDataValue) { List instructions = pseudocode.getInstructions(); for (Instruction instruction : instructions) { dataMap.put(instruction, initialDataValue); @@ -271,7 +286,13 @@ public class JetFlowInformationProvider { } } - private void traverseSubGraph(Pseudocode pseudocode, InstructionsMergeHandler instructionsMergeHandler, Collection previousSubGraphInstructions, boolean straightDirection, Map dataMap, boolean[] changed) { + private void traverseSubGraph( + Pseudocode pseudocode, + InstructionsMergeHandler instructionsMergeHandler, + Collection previousSubGraphInstructions, + boolean straightDirection, + Map dataMap, + boolean[] changed) { List instructions = pseudocode.getInstructions(); SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); for (Instruction instruction : instructions) { @@ -317,22 +338,28 @@ public class JetFlowInformationProvider { public Set merge(Instruction instruction, Set previousDataValue, Collection> incomingEdgesData) { Set initializedVariables = Sets.newHashSet(); initializedVariables.addAll(previousDataValue); - for (Set edgeDataValue : incomingEdgesData) { - initializedVariables.addAll(edgeDataValue); + Set edgesDataIntersection = Sets.newHashSet(); + boolean isFirst = true; + for (Set edgeData : incomingEdgesData) { + if (isFirst) { + edgesDataIntersection.addAll(edgeData); + } + else { + edgesDataIntersection = Sets.intersection(edgesDataIntersection, edgeData).immutableCopy(); + } + isFirst = false; } + initializedVariables.addAll(edgesDataIntersection); if (instruction instanceof WriteValueInstruction) { DeclarationDescriptor descriptor = null; JetElement lValue = ((WriteValueInstruction) instruction).getlValue(); - if (lValue instanceof JetProperty) { + if (lValue instanceof JetProperty || lValue instanceof JetParameter) { descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, lValue); } else if (lValue instanceof JetSimpleNameExpression) { descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue); } - else if (lValue instanceof JetParameter) { - descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, lValue); - } if (descriptor instanceof LocalVariableDescriptor) { initializedVariables.add((LocalVariableDescriptor) descriptor); } @@ -357,16 +384,16 @@ public class JetFlowInformationProvider { } } else if (instruction instanceof WriteValueInstruction) { - JetElement element = ((WriteValueInstruction) instruction).getElement(); + JetElement element = ((WriteValueInstruction) instruction).getlValue(); if (element instanceof JetSimpleNameExpression) { DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element); if (descriptor instanceof LocalVariableDescriptor) { - if (initializedVariables.contains(descriptor) && ((LocalVariableDescriptor) descriptor).isVar()) { + if (initializedVariables.contains(descriptor) && !((LocalVariableDescriptor) descriptor).isVar()) { trace.report(Errors.VAL_REASSIGNMENT.on((JetSimpleNameExpression) element, descriptor)); } } } - } + } } }; traverseInstructionGraphAndReportErrors(instructions, dataMap, instructionDataAnalyzer); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java index 65fadb3b5a3..07179794241 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/InstructionImpl.java @@ -12,6 +12,7 @@ import java.util.LinkedHashSet; public abstract class InstructionImpl implements Instruction { private Pseudocode owner; private final Collection previousInstructions = new LinkedHashSet(); + protected boolean isDead = false; protected InstructionImpl() { } @@ -42,4 +43,11 @@ public abstract class InstructionImpl implements Instruction { return target; } + public void die() { + isDead = true; + } + + public boolean isDead() { + return isDead; + } } 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 9a7f0087050..630199c91e8 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 @@ -1,5 +1,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.Label; @@ -77,6 +79,17 @@ public class Pseudocode { public List getInstructions() { return instructions; } + + @NotNull + public List getDeadInstructions() { + List deadInstructions = Lists.newArrayList(); + for (Instruction instruction : instructions) { + if (((InstructionImpl)instruction).isDead()) { + deadInstructions.add(instruction); + } + } + return deadInstructions; + } @Deprecated //for tests only public List getLabels() { @@ -166,6 +179,26 @@ public class Pseudocode { } }); } + removeDeadInstructions(); + } + + private void removeDeadInstructions() { + boolean hasRemovedInstruction = true; + Collection processedInstructions = Sets.newHashSet(); + while (hasRemovedInstruction) { + hasRemovedInstruction = false; + for (Instruction instruction : instructions) { + if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction) && + instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) { + hasRemovedInstruction = true; + for (Instruction nextInstruction : instruction.getNextInstructions()) { + nextInstruction.getPreviousInstructions().remove(instruction); + } + ((InstructionImpl)instruction).die(); + processedInstructions.add(instruction); + } + } + } } @NotNull