From ffd4af872c4da39c7b9dfc0aa03a4a34c8fbab16 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 17 Jul 2014 16:29:42 +0400 Subject: [PATCH] Pseudocode: Track merged values. Compute closure of value usages over merge instructions. Exclude merge instructions from usage lists --- .../lang/cfg/pseudocode/PseudocodeImpl.java | 55 +++++++++++++++---- .../jet/lang/cfg/pseudocode/pseudocodeUtil.kt | 12 ---- .../cfg/controlStructures/Finally.values | 4 +- .../OnlyWhileInFunctionBody.values | 6 +- 4 files changed, 50 insertions(+), 27 deletions(-) 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 7c7caf967ea..f755edbc7d8 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 @@ -17,13 +17,15 @@ package org.jetbrains.jet.lang.cfg.pseudocode; import com.google.common.collect.*; -import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.util.containers.BidirectionalMap; +import kotlin.Function0; +import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.Label; import org.jetbrains.jet.lang.cfg.LoopInfo; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.*; +import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.MergeInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.AbstractJumpInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.ConditionalJumpInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.NondeterministicJumpInstruction; @@ -91,14 +93,8 @@ public class PseudocodeImpl implements Pseudocode { private final BidirectionalMap elementsToValues = new BidirectionalMap(); - private final NotNullLazyValue>> valueUsages = - new NotNullLazyValue>>() { - @NotNull - @Override - protected Map> compute() { - return PseudocodePackage.collectValueUsages(PseudocodeImpl.this); - } - }; + private final Map> valueUsages = Maps.newHashMap(); + private final Map> mergedValues = Maps.newHashMap(); private Pseudocode parent = null; private Set localDeclarations = null; @@ -232,6 +228,17 @@ public class PseudocodeImpl implements Pseudocode { JetElementInstruction elementInstruction = (JetElementInstruction) instruction; representativeInstructions.put(elementInstruction.getElement(), instruction); } + + if (instruction instanceof MergeInstruction) { + addMergedValues((MergeInstruction) instruction); + } + + for (PseudoValue inputValue : instruction.getInputValues()) { + addValueUsage(inputValue, instruction); + for (PseudoValue mergedValue : getMergedValues(inputValue)) { + addValueUsage(mergedValue, instruction); + } + } } /*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) { @@ -272,7 +279,7 @@ public class PseudocodeImpl implements Pseudocode { @NotNull @Override public List getUsages(@Nullable PseudoValue value) { - List result = valueUsages.getValue().get(value); + List result = valueUsages.get(value); return result != null ? result : Collections.emptyList(); } @@ -283,6 +290,34 @@ public class PseudocodeImpl implements Pseudocode { /*package*/ void bindLabel(Label label) { ((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size()); } + + private Set getMergedValues(@NotNull PseudoValue value) { + Set result = mergedValues.get(value); + return result != null ? result : Collections.emptySet(); + } + + private void addMergedValues(@NotNull MergeInstruction instruction) { + Set result = new LinkedHashSet(); + for (PseudoValue value : instruction.getInputValues()) { + result.addAll(getMergedValues(value)); + result.add(value); + } + mergedValues.put(instruction.getOutputValue(), result); + } + + private void addValueUsage(PseudoValue value, Instruction usage) { + if (usage instanceof MergeInstruction) return; + KotlinPackage.getOrPut( + valueUsages, + value, + new Function0>() { + @Override + public List invoke() { + return Lists.newArrayList(); + } + } + ).add(usage); + } public void postProcess() { if (postPrecessed) return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt index 39e56828bdc..3c66a32a983 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt @@ -135,16 +135,4 @@ public fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: Bind is CallInstruction -> return resolvedCall.getResultingDescriptor() else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext) } -} - -private fun Pseudocode.collectValueUsages(): Map> { - val map = HashMap>() - traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) { - for (value in it.inputValues) { - map.getOrPut(value){ ArrayList() }.add(it) - } - true - } - - return map } \ No newline at end of file diff --git a/compiler/testData/cfg/controlStructures/Finally.values b/compiler/testData/cfg/controlStructures/Finally.values index 0287b18c72b..88328671165 100644 --- a/compiler/testData/cfg/controlStructures/Finally.values +++ b/compiler/testData/cfg/controlStructures/Finally.values @@ -268,8 +268,8 @@ fun t11() { } } --------------------- -1 : * NEW: r(1) -> -2 : Unit NEW: r(2) -> +1 : {<: Unit} NEW: r(1) -> +2 : {<: Unit} NEW: r(2) -> ===================== == t12 == fun t12() : Int { diff --git a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values index e27c2bd5512..27bf2cc3078 100644 --- a/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values +++ b/compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.values @@ -17,7 +17,7 @@ fun dowhile() { while(0 > 1) } --------------------- -0 : * NEW: r(0) -> -1 : * NEW: r(1) -> -0 > 1 : * NEW: call(0 > 1, compareTo|, ) -> +0 : {<: Comparable} NEW: r(0) -> +1 : Int NEW: r(1) -> +0 > 1 : Boolean NEW: call(0 > 1, compareTo|, ) -> =====================