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;
|
||||
|
||||
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<JetElement, PseudoValue> elementsToValues = new BidirectionalMap<JetElement, PseudoValue>();
|
||||
|
||||
private final NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>> valueUsages =
|
||||
new NotNullLazyValue<Map<PseudoValue, List<? extends Instruction>>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Map<PseudoValue, List<? extends Instruction>> compute() {
|
||||
return PseudocodePackage.collectValueUsages(PseudocodeImpl.this);
|
||||
}
|
||||
};
|
||||
private final Map<PseudoValue, List<Instruction>> valueUsages = Maps.newHashMap();
|
||||
private final Map<PseudoValue, Set<PseudoValue>> mergedValues = Maps.newHashMap();
|
||||
|
||||
private Pseudocode parent = null;
|
||||
private Set<LocalFunctionDeclarationInstruction> 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<? 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();
|
||||
}
|
||||
|
||||
@@ -283,6 +290,34 @@ public class PseudocodeImpl implements Pseudocode {
|
||||
/*package*/ void bindLabel(Label label) {
|
||||
((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() {
|
||||
if (postPrecessed) return;
|
||||
|
||||
@@ -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<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>
|
||||
2 <v1>: Unit NEW: r(2) -> <v1>
|
||||
1 <v0>: {<: Unit} NEW: r(1) -> <v0>
|
||||
2 <v1>: {<: Unit} NEW: r(2) -> <v1>
|
||||
=====================
|
||||
== t12 ==
|
||||
fun t12() : Int {
|
||||
|
||||
@@ -17,7 +17,7 @@ fun dowhile() {
|
||||
while(0 > 1)
|
||||
}
|
||||
---------------------
|
||||
0 <v0>: * NEW: r(0) -> <v0>
|
||||
1 <v1>: * NEW: r(1) -> <v1>
|
||||
0 > 1 <v2>: * NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
|
||||
0 <v0>: {<: Comparable<Int>} NEW: r(0) -> <v0>
|
||||
1 <v1>: Int NEW: r(1) -> <v1>
|
||||
0 > 1 <v2>: Boolean NEW: call(0 > 1, compareTo|<v0>, <v1>) -> <v2>
|
||||
=====================
|
||||
|
||||
Reference in New Issue
Block a user