diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index c67d560ec73..0e848c6268e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -36,26 +36,26 @@ public class PseudocodeTraverser { } @NotNull - private static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { + /*package*/ static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { return traversalOrder == FORWARD ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } @NotNull - private static Instruction getLastInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { + /*package*/ static Instruction getLastInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { return traversalOrder == FORWARD ? pseudocode.getSinkInstruction() : pseudocode.getEnterInstruction(); } @NotNull - private static List getInstructions(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { + /*package*/ static List getInstructions(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { return traversalOrder == FORWARD ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); } @NotNull - private static Collection getPreviousInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) { + /*packge*/ static Collection getPreviousInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) { return traversalOrder == FORWARD ? instruction.getPreviousInstructions() : instruction.getNextInstructions(); } - private static boolean isStartInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) { + /*package*/ static boolean isStartInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) { return traversalOrder == FORWARD ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; } @@ -65,105 +65,10 @@ public class PseudocodeTraverser { SKIP_LOCAL_DECLARATIONS } - private static boolean shouldLookInside(Instruction instruction, LookInsideStrategy lookInside) { + protected static boolean shouldLookInside(Instruction instruction, LookInsideStrategy lookInside) { return lookInside == LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS && instruction instanceof LocalFunctionDeclarationInstruction; } - public static Map> collectData( - @NotNull Pseudocode pseudocode, - @NotNull TraversalOrder traversalOrder, - @NotNull LookInsideStrategy lookInside, - @NotNull D initialDataValue, - @NotNull D initialDataValueForEnterInstruction, - @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy - ) { - - Map> edgesMap = Maps.newLinkedHashMap(); - initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue); - edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); - - boolean[] changed = new boolean[1]; - changed[0] = true; - while (changed[0]) { - changed[0] = false; - collectDataFromSubgraph(pseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, - Collections.emptyList(), changed, false); - } - return edgesMap; - } - - private static void initializeEdgesMap( - @NotNull Pseudocode pseudocode, LookInsideStrategy lookInside, - @NotNull Map> edgesMap, - @NotNull D initialDataValue) { - List instructions = pseudocode.getInstructions(); - Edges initialEdge = Edges.create(initialDataValue, initialDataValue); - for (Instruction instruction : instructions) { - edgesMap.put(instruction, initialEdge); - if (shouldLookInside(instruction, lookInside)) { - initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue); - } - } - } - - private static void collectDataFromSubgraph( - @NotNull Pseudocode pseudocode, - @NotNull TraversalOrder traversalOrder, - @NotNull LookInsideStrategy lookInside, - @NotNull Map> edgesMap, - @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, - @NotNull Collection previousSubGraphInstructions, - boolean[] changed, - boolean isLocal - ) { - List instructions = getInstructions(pseudocode, traversalOrder); - Instruction startInstruction = getStartInstruction(pseudocode, traversalOrder); - - for (Instruction instruction : instructions) { - boolean isStart = isStartInstruction(instruction, traversalOrder); - if (!isLocal && isStart) continue; - - Collection allPreviousInstructions; - Collection previousInstructions = getPreviousInstruction(instruction, traversalOrder); - - if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { - allPreviousInstructions = Lists.newArrayList(previousInstructions); - allPreviousInstructions.addAll(previousSubGraphInstructions); - } - else { - allPreviousInstructions = previousInstructions; - } - - if (shouldLookInside(instruction, lookInside)) { - Pseudocode subroutinePseudocode = ((LocalFunctionDeclarationInstruction) instruction).getBody(); - collectDataFromSubgraph(subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, - previousInstructions, changed, true); - Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder); - Edges previousValue = edgesMap.get(instruction); - Edges newValue = edgesMap.get(lastInstruction); - if (!previousValue.equals(newValue)) { - changed[0] = true; - edgesMap.put(instruction, newValue); - } - continue; - } - Edges previousDataValue = edgesMap.get(instruction); - - Collection incomingEdgesData = Sets.newHashSet(); - - for (Instruction previousInstruction : allPreviousInstructions) { - Edges previousData = edgesMap.get(previousInstruction); - if (previousData != null) { - incomingEdgesData.add(previousData.out); - } - } - Edges mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); - if (!mergedData.equals(previousDataValue)) { - changed[0] = true; - edgesMap.put(instruction, mergedData); - } - } - } public static void traverse( @NotNull Pseudocode pseudocode, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.java new file mode 100644 index 00000000000..4748353c033 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.java @@ -0,0 +1,137 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.cfg; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; +import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; +import org.jetbrains.jet.lang.resolve.BindingContext; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class PseudocodeVariableDataCollector extends PseudocodeTraverser { + private final BindingContext bindingContext; + + public PseudocodeVariableDataCollector(@NotNull BindingContext context) { + bindingContext = context; + } + + public Map> collectData( + @NotNull Pseudocode pseudocode, + @NotNull TraversalOrder traversalOrder, + @NotNull LookInsideStrategy lookInside, + @NotNull D initialDataValue, + @NotNull D initialDataValueForEnterInstruction, + @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy + ) { + + Map> edgesMap = Maps.newLinkedHashMap(); + initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue); + edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); + + boolean[] changed = new boolean[1]; + changed[0] = true; + while (changed[0]) { + changed[0] = false; + collectDataFromSubgraph(pseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, + Collections.emptyList(), changed, false); + } + return edgesMap; + } + + private void initializeEdgesMap( + @NotNull Pseudocode pseudocode, LookInsideStrategy lookInside, + @NotNull Map> edgesMap, + @NotNull D initialDataValue) { + List instructions = pseudocode.getInstructions(); + Edges initialEdge = Edges.create(initialDataValue, initialDataValue); + for (Instruction instruction : instructions) { + edgesMap.put(instruction, initialEdge); + if (shouldLookInside(instruction, lookInside)) { + initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue); + } + } + } + + private void collectDataFromSubgraph( + @NotNull Pseudocode pseudocode, + @NotNull TraversalOrder traversalOrder, + @NotNull LookInsideStrategy lookInside, + @NotNull Map> edgesMap, + @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, + @NotNull Collection previousSubGraphInstructions, + boolean[] changed, + boolean isLocal + ) { + List instructions = getInstructions(pseudocode, traversalOrder); + Instruction startInstruction = getStartInstruction(pseudocode, traversalOrder); + + for (Instruction instruction : instructions) { + boolean isStart = isStartInstruction(instruction, traversalOrder); + if (!isLocal && isStart) continue; + + Collection allPreviousInstructions; + Collection previousInstructions = getPreviousInstruction(instruction, traversalOrder); + + if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { + allPreviousInstructions = Lists.newArrayList(previousInstructions); + allPreviousInstructions.addAll(previousSubGraphInstructions); + } + else { + allPreviousInstructions = previousInstructions; + } + + if (shouldLookInside(instruction, lookInside)) { + LocalFunctionDeclarationInstruction functionInstruction = (LocalFunctionDeclarationInstruction) instruction; + Pseudocode subroutinePseudocode = functionInstruction.getBody(); + collectDataFromSubgraph(subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, + previousInstructions, + changed, true); + Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder); + Edges previousValue = edgesMap.get(instruction); + Edges newValue = edgesMap.get(lastInstruction); + if (!previousValue.equals(newValue)) { + changed[0] = true; + edgesMap.put(instruction, newValue); + } + continue; + } + Edges previousDataValue = edgesMap.get(instruction); + + Collection incomingEdgesData = Sets.newHashSet(); + + for (Instruction previousInstruction : allPreviousInstructions) { + Edges previousData = edgesMap.get(previousInstruction); + if (previousData != null) { + incomingEdgesData.add(previousData.out); + } + } + Edges mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); + if (!mergedData.equals(previousDataValue)) { + changed[0] = true; + edgesMap.put(instruction, mergedData); + } + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index f9e533c1ff4..19c564fba43 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -147,7 +147,7 @@ public class PseudocodeVariablesData { } }; - return PseudocodeTraverser.collectData( + return new PseudocodeVariableDataCollector(bindingContext).collectData( pseudocode, FORWARD, ANALYSE_LOCAL_DECLARATIONS, initialMap, initialMap, instructionDataMergeStrategy); } @@ -273,7 +273,7 @@ public class PseudocodeVariablesData { return Edges.create(enterResult, exitResult); } }; - return PseudocodeTraverser.collectData( + return new PseudocodeVariableDataCollector(bindingContext).collectData( pseudocode, BACKWARD, ANALYSE_LOCAL_DECLARATIONS, Collections.emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy); }