Pseudocode: Track merged values. Compute closure of value usages over merge instructions. Exclude merge instructions from usage lists
This commit is contained in:
@@ -17,13 +17,15 @@
|
|||||||
package org.jetbrains.jet.lang.cfg.pseudocode;
|
package org.jetbrains.jet.lang.cfg.pseudocode;
|
||||||
|
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.*;
|
||||||
import com.intellij.openapi.util.NotNullLazyValue;
|
|
||||||
import com.intellij.util.containers.BidirectionalMap;
|
import com.intellij.util.containers.BidirectionalMap;
|
||||||
|
import kotlin.Function0;
|
||||||
|
import kotlin.KotlinPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.cfg.Label;
|
import org.jetbrains.jet.lang.cfg.Label;
|
||||||
import org.jetbrains.jet.lang.cfg.LoopInfo;
|
import org.jetbrains.jet.lang.cfg.LoopInfo;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.*;
|
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.AbstractJumpInstruction;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.ConditionalJumpInstruction;
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.ConditionalJumpInstruction;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.NondeterministicJumpInstruction;
|
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.NondeterministicJumpInstruction;
|
||||||
@@ -91,14 +93,8 @@ public class PseudocodeImpl implements Pseudocode {
|
|||||||
|
|
||||||
private final BidirectionalMap<JetElement, PseudoValue> elementsToValues = new BidirectionalMap<JetElement, PseudoValue>();
|
private final BidirectionalMap<JetElement, PseudoValue> elementsToValues = new BidirectionalMap<JetElement, PseudoValue>();
|
||||||
|
|
||||||
private final NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>> valueUsages =
|
private final Map<PseudoValue, List<Instruction>> valueUsages = Maps.newHashMap();
|
||||||
new NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>>() {
|
private final Map<PseudoValue, Set<PseudoValue>> mergedValues = Maps.newHashMap();
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
protected Map<PseudoValue, List<? extends Instruction>> compute() {
|
|
||||||
return PseudocodePackage.collectValueUsages(PseudocodeImpl.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private Pseudocode parent = null;
|
private Pseudocode parent = null;
|
||||||
private Set<LocalFunctionDeclarationInstruction> localDeclarations = null;
|
private Set<LocalFunctionDeclarationInstruction> localDeclarations = null;
|
||||||
@@ -232,6 +228,17 @@ public class PseudocodeImpl implements Pseudocode {
|
|||||||
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
||||||
representativeInstructions.put(elementInstruction.getElement(), 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) {
|
/*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
|
||||||
@@ -272,7 +279,7 @@ public class PseudocodeImpl implements Pseudocode {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Instruction> getUsages(@Nullable PseudoValue value) {
|
public List<? extends Instruction> getUsages(@Nullable PseudoValue value) {
|
||||||
List<? extends Instruction> result = valueUsages.getValue().get(value);
|
List<? extends Instruction> result = valueUsages.get(value);
|
||||||
return result != null ? result : Collections.<Instruction>emptyList();
|
return result != null ? result : Collections.<Instruction>emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +290,34 @@ public class PseudocodeImpl implements Pseudocode {
|
|||||||
/*package*/ void bindLabel(Label label) {
|
/*package*/ void bindLabel(Label label) {
|
||||||
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
|
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<PseudoValue> getMergedValues(@NotNull PseudoValue value) {
|
||||||
|
Set<PseudoValue> result = mergedValues.get(value);
|
||||||
|
return result != null ? result : Collections.<PseudoValue>emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMergedValues(@NotNull MergeInstruction instruction) {
|
||||||
|
Set<PseudoValue> result = new LinkedHashSet<PseudoValue>();
|
||||||
|
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<List<Instruction>>() {
|
||||||
|
@Override
|
||||||
|
public List<Instruction> invoke() {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).add(usage);
|
||||||
|
}
|
||||||
|
|
||||||
public void postProcess() {
|
public void postProcess() {
|
||||||
if (postPrecessed) return;
|
if (postPrecessed) return;
|
||||||
|
|||||||
@@ -135,16 +135,4 @@ public fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: Bind
|
|||||||
is CallInstruction -> return resolvedCall.getResultingDescriptor()
|
is CallInstruction -> return resolvedCall.getResultingDescriptor()
|
||||||
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
|
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun Pseudocode.collectValueUsages(): Map<PseudoValue, List<Instruction>> {
|
|
||||||
val map = HashMap<PseudoValue, MutableList<Instruction>>()
|
|
||||||
traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) {
|
|
||||||
for (value in it.inputValues) {
|
|
||||||
map.getOrPut(value){ ArrayList() }.add(it)
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
return map
|
|
||||||
}
|
}
|
||||||
@@ -268,8 +268,8 @@ fun t11() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
1 <v0>: * NEW: r(1) -> <v0>
|
1 <v0>: {<: Unit} NEW: r(1) -> <v0>
|
||||||
2 <v1>: Unit NEW: r(2) -> <v1>
|
2 <v1>: {<: Unit} NEW: r(2) -> <v1>
|
||||||
=====================
|
=====================
|
||||||
== t12 ==
|
== t12 ==
|
||||||
fun t12() : Int {
|
fun t12() : Int {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ fun dowhile() {
|
|||||||
while(0 > 1)
|
while(0 > 1)
|
||||||
}
|
}
|
||||||
---------------------
|
---------------------
|
||||||
0 <v0>: * NEW: r(0) -> <v0>
|
0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0>
|
||||||
1 <v1>: * NEW: r(1) -> <v1>
|
1 <v1>: Int NEW: r(1) -> <v1>
|
||||||
0 > 1 <v2>: * NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
|
0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
Reference in New Issue
Block a user