From 7db6752e202a393b6380df26f6254c1807495b59 Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 28 Oct 2011 13:33:38 +0400 Subject: [PATCH] Control flow graph traversing refactoring --- .../cfg/JetControlFlowGraphTraverser.java | 116 ++++++++++++++++++ .../jetbrains/jet/cfg/JetControlFlowTest.java | 1 - 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java new file mode 100644 index 00000000000..4ac299453dd --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -0,0 +1,116 @@ +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.jet.lang.cfg.pseudocode.Instruction; +import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction; +import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; +import org.jetbrains.jet.lang.cfg.pseudocode.SubroutineEnterInstruction; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author svtk + */ +public class JetControlFlowGraphTraverser { + public static Map traverseInstructionGraphUntilFactsStabilization( + Pseudocode pseudocode, + InstructionsMergeStrategy instructionsMergeStrategy, + D initialDataValue, + D initialDataValueForEnterInstruction, + boolean straightDirection) { + Map dataMap = Maps.newHashMap(); + initializeDataMap(dataMap, pseudocode, initialDataValue); + dataMap.put(pseudocode.getEnterInstruction(), initialDataValueForEnterInstruction); + + boolean[] changed = new boolean[1]; + changed[0] = true; + while (changed[0]) { + changed[0] = false; + traverseSubGraph(pseudocode, instructionsMergeStrategy, Collections.emptyList(), straightDirection, dataMap, changed, false); + } + return dataMap; + } + + private static void initializeDataMap( + Map dataMap, + Pseudocode pseudocode, + D initialDataValue) { + List instructions = pseudocode.getInstructions(); + for (Instruction instruction : instructions) { + dataMap.put(instruction, initialDataValue); + if (instruction instanceof LocalDeclarationInstruction) { + initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue); + } + } + } + + private static void traverseSubGraph( + Pseudocode pseudocode, + InstructionsMergeStrategy instructionsMergeStrategy, + Collection previousSubGraphInstructions, + boolean straightDirection, + Map dataMap, + boolean[] changed, + boolean isLocal) { + List instructions = pseudocode.getInstructions(); + SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); + for (Instruction instruction : instructions) { + if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue; + + Collection allPreviousInstructions; + Collection previousInstructions = straightDirection + ? instruction.getPreviousInstructions() + : instruction.getNextInstructions(); + + if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) { + allPreviousInstructions = Lists.newArrayList(previousInstructions); + allPreviousInstructions.addAll(previousSubGraphInstructions); + } + else { + allPreviousInstructions = previousInstructions; + } + + if (instruction instanceof LocalDeclarationInstruction) { + Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); + traverseSubGraph(subroutinePseudocode, instructionsMergeStrategy, previousInstructions, straightDirection, dataMap, changed, true); + } + D previousDataValue = dataMap.get(instruction); + + Collection incomingEdgesData = Sets.newHashSet(); + + for (Instruction previousInstruction : allPreviousInstructions) { + incomingEdgesData.add(dataMap.get(previousInstruction)); + } + D mergedData = instructionsMergeStrategy.execute(instruction, incomingEdgesData); + if (!mergedData.equals(previousDataValue)) { + changed[0] = true; + dataMap.put(instruction, mergedData); + } + } + } + + public static void traverseAndAnalyzeInstructionGraph( + Pseudocode pseudocode, + InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + List instructions = pseudocode.getInstructions(); + for (Instruction instruction : instructions) { + if (instruction instanceof LocalDeclarationInstruction) { + traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); + } + instructionDataAnalyzeStrategy.execute(instruction); + } + } + + interface InstructionsMergeStrategy { + D execute(Instruction instruction, Collection incomingEdgesData); + } + + interface InstructionDataAnalyzeStrategy { + void execute(Instruction instruction); + } +} diff --git a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index b9efa562bcf..b56e4930a24 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java @@ -270,7 +270,6 @@ public class JetControlFlowTest extends JetTestCaseBase { @Override public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { //todo print edges - visitInstruction(instruction); printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); }