Control flow graph traversing refactoring
This commit is contained in:
+40
-20
@@ -4,6 +4,8 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -14,28 +16,35 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public class JetControlFlowGraphTraverser {
|
public class JetControlFlowGraphTraverser<D> {
|
||||||
public static <D> Map<Instruction, Pair<D, D>> traverseInstructionGraphUntilFactsStabilization(
|
private final Pseudocode pseudocode;
|
||||||
Pseudocode pseudocode,
|
private final Map<Instruction, Pair<D, D>> dataMap = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
|
public static <D> JetControlFlowGraphTraverser<D> create(Pseudocode pseudocode) {
|
||||||
|
return new JetControlFlowGraphTraverser<D>(pseudocode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JetControlFlowGraphTraverser(Pseudocode pseudocode) {
|
||||||
|
this.pseudocode = pseudocode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collectInformationFromInstructionGraph(
|
||||||
InstructionsMergeStrategy<D> instructionsMergeStrategy,
|
InstructionsMergeStrategy<D> instructionsMergeStrategy,
|
||||||
D initialDataValue,
|
D initialDataValue,
|
||||||
D initialDataValueForEnterInstruction,
|
D initialDataValueForEnterInstruction,
|
||||||
boolean straightDirection) {
|
boolean straightDirection) {
|
||||||
Map<Instruction, Pair<D, D>> dataMap = Maps.newLinkedHashMap();
|
initializeDataMap(pseudocode, initialDataValue);
|
||||||
initializeDataMap(dataMap, pseudocode, initialDataValue);
|
|
||||||
dataMap.put(pseudocode.getEnterInstruction(), Pair.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
dataMap.put(pseudocode.getEnterInstruction(), Pair.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
||||||
|
|
||||||
boolean[] changed = new boolean[1];
|
boolean[] changed = new boolean[1];
|
||||||
changed[0] = true;
|
changed[0] = true;
|
||||||
while (changed[0]) {
|
while (changed[0]) {
|
||||||
changed[0] = false;
|
changed[0] = false;
|
||||||
traverseSubGraph(pseudocode, instructionsMergeStrategy, Collections.<Instruction>emptyList(), straightDirection, dataMap, changed, false);
|
traverseSubGraph(pseudocode, instructionsMergeStrategy, Collections.<Instruction>emptyList(), straightDirection, changed, false);
|
||||||
}
|
}
|
||||||
return dataMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D> void initializeDataMap(
|
private void initializeDataMap(
|
||||||
Map<Instruction, Pair<D, D>> dataMap,
|
|
||||||
Pseudocode pseudocode,
|
Pseudocode pseudocode,
|
||||||
D initialDataValue) {
|
D initialDataValue) {
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
List<Instruction> instructions = pseudocode.getInstructions();
|
||||||
@@ -43,17 +52,16 @@ public class JetControlFlowGraphTraverser {
|
|||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
dataMap.put(instruction, initialPair);
|
dataMap.put(instruction, initialPair);
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
if (instruction instanceof LocalDeclarationInstruction) {
|
||||||
initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
|
initializeDataMap(((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D> void traverseSubGraph(
|
private void traverseSubGraph(
|
||||||
Pseudocode pseudocode,
|
Pseudocode pseudocode,
|
||||||
InstructionsMergeStrategy<D> instructionsMergeStrategy,
|
InstructionsMergeStrategy<D> instructionsMergeStrategy,
|
||||||
Collection<Instruction> previousSubGraphInstructions,
|
Collection<Instruction> previousSubGraphInstructions,
|
||||||
boolean straightDirection,
|
boolean straightDirection,
|
||||||
Map<Instruction, Pair<D, D>> dataMap,
|
|
||||||
boolean[] changed,
|
boolean[] changed,
|
||||||
boolean isLocal) {
|
boolean isLocal) {
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
List<Instruction> instructions = pseudocode.getInstructions();
|
||||||
@@ -76,7 +84,7 @@ public class JetControlFlowGraphTraverser {
|
|||||||
|
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
if (instruction instanceof LocalDeclarationInstruction) {
|
||||||
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
||||||
traverseSubGraph(subroutinePseudocode, instructionsMergeStrategy, previousInstructions, straightDirection, dataMap, changed, true);
|
traverseSubGraph(subroutinePseudocode, instructionsMergeStrategy, previousInstructions, straightDirection, changed, true);
|
||||||
}
|
}
|
||||||
Pair<D, D> previousDataValue = dataMap.get(instruction);
|
Pair<D, D> previousDataValue = dataMap.get(instruction);
|
||||||
|
|
||||||
@@ -93,24 +101,36 @@ public class JetControlFlowGraphTraverser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void traverseAndAnalyzeInstructionGraph(
|
public void traverseAndAnalyzeInstructionGraph(
|
||||||
|
InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
||||||
|
traverseAndAnalyzeInstructionGraph(pseudocode, instructionDataAnalyzeStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void traverseAndAnalyzeInstructionGraph(
|
||||||
Pseudocode pseudocode,
|
Pseudocode pseudocode,
|
||||||
InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) {
|
InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
List<Instruction> instructions = pseudocode.getInstructions();
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
if (((InstructionImpl)instruction).isDead()) continue;
|
if (((InstructionImpl)instruction).isDead()) continue;
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
if (instruction instanceof LocalDeclarationInstruction) {
|
||||||
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy);
|
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy);
|
||||||
}
|
}
|
||||||
instructionDataAnalyzeStrategy.execute(instruction);
|
Pair<D, D> pair = dataMap.get(instruction);
|
||||||
|
instructionDataAnalyzeStrategy.execute(instruction,
|
||||||
|
pair != null ? pair.getFirst() : null,
|
||||||
|
pair != null ? pair.getSecond() : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InstructionsMergeStrategy<D> {
|
public D getResultInfo() {
|
||||||
Pair<D, D> execute(Instruction instruction, Collection<D> incomingEdgesData);
|
return dataMap.get(pseudocode.getExitInstruction()).getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InstructionDataAnalyzeStrategy {
|
interface InstructionsMergeStrategy<D> {
|
||||||
void execute(Instruction instruction);
|
Pair<D, D> execute(Instruction instruction, @NotNull Collection<D> incomingEdgesData);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InstructionDataAnalyzeStrategy<D> {
|
||||||
|
void execute(Instruction instruction, @Nullable D enterData, @Nullable D exitData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,14 +65,6 @@ public class JetFlowInformationProvider {
|
|||||||
wrappedTrace.close();
|
wrappedTrace.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
|
||||||
// Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
|
||||||
// assert pseudocode != null;
|
|
||||||
//
|
|
||||||
// SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
|
||||||
// processPreviousInstructions(exitInstruction, new HashSet<Instruction>(), returnedExpressions, elementsReturningUnit);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetExpression> returnedExpressions) {
|
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetExpression> returnedExpressions) {
|
||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
@@ -128,149 +120,20 @@ public class JetFlowInformationProvider {
|
|||||||
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
|
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
|
|
||||||
// Set<Instruction> visited = new HashSet<Instruction>();
|
|
||||||
// collectReachable(enterInstruction, visited, null);
|
|
||||||
//
|
|
||||||
// for (Instruction instruction : pseudocode.getInstructions()) {
|
|
||||||
// if (!visited.contains(instruction) &&
|
|
||||||
// instruction instanceof JetElementInstruction &&
|
|
||||||
// // TODO : do {return} while (1 > a)
|
|
||||||
// !(instruction instanceof ReadUnitValueInstruction)) {
|
|
||||||
// unreachableElements.add(((JetElementInstruction) instruction).getElement());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
|
||||||
// Instruction dominatorInstruction = representativeInstructions.get(dominator);
|
|
||||||
// if (dominatorInstruction == null) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
|
|
||||||
//
|
|
||||||
// Set<Instruction> reachable = new HashSet<Instruction>();
|
|
||||||
// collectReachable(enterInstruction, reachable, null);
|
|
||||||
//
|
|
||||||
// Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
|
|
||||||
// reachableWithDominatorProhibited.add(dominatorInstruction);
|
|
||||||
// collectReachable(enterInstruction, reachableWithDominatorProhibited, null);
|
|
||||||
//
|
|
||||||
// for (Instruction instruction : reachable) {
|
|
||||||
// if (instruction instanceof JetElementInstruction
|
|
||||||
// && reachable.contains(instruction)
|
|
||||||
// && !reachableWithDominatorProhibited.contains(instruction)) {
|
|
||||||
// JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
|
||||||
// dominated.add(elementInstruction.getElement());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public boolean isBreakable(JetLoopExpression loop) {
|
|
||||||
// LoopInfo info = loopInfo.get(loop);
|
|
||||||
// Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint();
|
|
||||||
// Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint();
|
|
||||||
// HashSet<Instruction> visited = Sets.newHashSet();
|
|
||||||
// Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint();
|
|
||||||
// visited.add(conditionEntryPoint.resolveToInstruction());
|
|
||||||
// return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public boolean isReachable(JetExpression from, JetExpression to) {
|
|
||||||
// Instruction fromInstr = representativeInstructions.get(from);
|
|
||||||
// assert fromInstr != null : "No representative instruction for " + from.getText();
|
|
||||||
// Instruction toInstr = representativeInstructions.get(to);
|
|
||||||
// assert toInstr != null : "No representative instruction for " + to.getText();
|
|
||||||
//
|
|
||||||
// return collectReachable(fromInstr, Sets.<Instruction>newHashSet(), toInstr);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private boolean collectReachable(Instruction current, Set<Instruction> visited, @Nullable Instruction lookFor) {
|
public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean inAnonymousInitializers) {
|
||||||
// if (!visited.add(current)) return false;
|
|
||||||
// if (current == lookFor) return true;
|
|
||||||
//
|
|
||||||
// for (Instruction nextInstruction : current.getNextInstructions()) {
|
|
||||||
// if (collectReachable(nextInstruction, visited, lookFor)) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
|
|
||||||
// if (!visited.add(previousFor)) return;
|
|
||||||
//
|
|
||||||
// Collection<Instruction> previousInstructions = previousFor.getPreviousInstructions();
|
|
||||||
// InstructionVisitor visitor = new InstructionVisitor() {
|
|
||||||
// @Override
|
|
||||||
// public void visitReadValue(ReadValueInstruction instruction) {
|
|
||||||
// returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitReturnValue(ReturnValueInstruction instruction) {
|
|
||||||
// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
|
||||||
// elementsReturningUnit.add(instruction.getElement());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitSubroutineEnter(SubroutineEnterInstruction instruction) {
|
|
||||||
// elementsReturningUnit.add(instruction.getSubroutine());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
|
|
||||||
// context.getTrace().report(UNSUPPORTED.on(instruction.getElement(), "Control-flow builder"));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
|
|
||||||
// elementsReturningUnit.add(writeValueInstruction.getElement());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitJump(AbstractJumpInstruction instruction) {
|
|
||||||
// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitReadUnitValue(ReadUnitValueInstruction instruction) {
|
|
||||||
// returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void visitInstruction(Instruction instruction) {
|
|
||||||
// if (instruction instanceof JetElementInstructionImpl) {
|
|
||||||
// JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction;
|
|
||||||
// context.getTrace().report(UNSUPPORTED.on(elementInstruction.getElement(), "Control-flow builder"));
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// throw new UnsupportedOperationException(instruction.toString());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// for (Instruction previousInstruction : previousInstructions) {
|
|
||||||
// previousInstruction.accept(visitor);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void markUninitializedVariables(
|
|
||||||
@NotNull JetElement subroutine,
|
|
||||||
final boolean inAnonymousInitializers) {
|
|
||||||
final Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
final Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
|
|
||||||
|
JetControlFlowGraphTraverser<Map<VariableDescriptor, InitializationPoints>> traverser = JetControlFlowGraphTraverser.create(pseudocode);
|
||||||
|
|
||||||
JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>> instructionsMergeStrategy =
|
JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>> instructionsMergeStrategy =
|
||||||
new JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>>() {
|
new JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>>() {
|
||||||
@Override
|
@Override
|
||||||
public Pair<Map<VariableDescriptor, InitializationPoints>, Map<VariableDescriptor, InitializationPoints>> execute(
|
public Pair<Map<VariableDescriptor, InitializationPoints>, Map<VariableDescriptor, InitializationPoints>> execute(
|
||||||
Instruction instruction,
|
Instruction instruction,
|
||||||
Collection<Map<VariableDescriptor, InitializationPoints>> incomingEdgesData) {
|
@NotNull Collection<Map<VariableDescriptor, InitializationPoints>> incomingEdgesData) {
|
||||||
|
|
||||||
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
|
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
|
||||||
for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
||||||
@@ -300,34 +163,17 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Collection<VariableDescriptor> usedVariables = collectUsedVariables(pseudocode);
|
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = prepareInitialMapForStartInstruction(subroutine, pseudocode);
|
||||||
Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
|
|
||||||
|
|
||||||
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap();
|
traverser.collectInformationFromInstructionGraph(instructionsMergeStrategy,
|
||||||
InitializationPoints initialPointsForDeclaredVariable = new InitializationPoints(false);
|
Collections.<VariableDescriptor, InitializationPoints>emptyMap(),
|
||||||
InitializationPoints initialPointsForExternalVariable = new InitializationPoints(true);
|
initialMapForStartInstruction,
|
||||||
|
true);
|
||||||
|
|
||||||
for (VariableDescriptor variable : usedVariables) {
|
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Map<VariableDescriptor, InitializationPoints>>() {
|
||||||
if (declaredVariables.contains(variable)) {
|
|
||||||
initialMapForStartInstruction.put(variable, initialPointsForDeclaredVariable);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
initialMapForStartInstruction.put(variable, initialPointsForExternalVariable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Map<Instruction, Pair<Map<VariableDescriptor, InitializationPoints>, Map<VariableDescriptor, InitializationPoints>>> dataMap =
|
|
||||||
JetControlFlowGraphTraverser.traverseInstructionGraphUntilFactsStabilization(pseudocode,
|
|
||||||
instructionsMergeStrategy,
|
|
||||||
Collections.<VariableDescriptor, InitializationPoints>emptyMap(),
|
|
||||||
initialMapForStartInstruction,
|
|
||||||
true);
|
|
||||||
|
|
||||||
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Instruction instruction) {
|
public void execute(Instruction instruction, @Nullable Map<VariableDescriptor, InitializationPoints> enterData, @Nullable Map<VariableDescriptor, InitializationPoints> exitData) {
|
||||||
Pair<Map<VariableDescriptor, InitializationPoints>, Map<VariableDescriptor, InitializationPoints>> variablesData = dataMap.get(instruction);
|
assert enterData != null && exitData != null;
|
||||||
Map<VariableDescriptor, InitializationPoints> enterData = variablesData.getFirst();
|
|
||||||
Map<VariableDescriptor, InitializationPoints> exitData = variablesData.getSecond();
|
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
@@ -380,7 +226,7 @@ public class JetFlowInformationProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (inAnonymousInitializers) {
|
if (inAnonymousInitializers) {
|
||||||
Map<VariableDescriptor, InitializationPoints> lastInfo = dataMap.get(pseudocode.getExitInstruction()).getFirst();
|
Map<VariableDescriptor, InitializationPoints> lastInfo = traverser.getResultInfo();
|
||||||
for (Map.Entry<VariableDescriptor, InitializationPoints> entry : lastInfo.entrySet()) {
|
for (Map.Entry<VariableDescriptor, InitializationPoints> entry : lastInfo.entrySet()) {
|
||||||
VariableDescriptor variable = entry.getKey();
|
VariableDescriptor variable = entry.getKey();
|
||||||
if (variable instanceof PropertyDescriptor) {
|
if (variable instanceof PropertyDescriptor) {
|
||||||
@@ -391,6 +237,25 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<VariableDescriptor, InitializationPoints> prepareInitialMapForStartInstruction(JetElement subroutine, Pseudocode pseudocode) {
|
||||||
|
Collection<VariableDescriptor> usedVariables = collectUsedVariables(pseudocode);
|
||||||
|
Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
|
||||||
|
|
||||||
|
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap();
|
||||||
|
InitializationPoints initialPointsForDeclaredVariable = new InitializationPoints(false);
|
||||||
|
InitializationPoints initialPointsForExternalVariable = new InitializationPoints(true);
|
||||||
|
|
||||||
|
for (VariableDescriptor variable : usedVariables) {
|
||||||
|
if (declaredVariables.contains(variable)) {
|
||||||
|
initialMapForStartInstruction.put(variable, initialPointsForDeclaredVariable);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initialMapForStartInstruction.put(variable, initialPointsForExternalVariable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return initialMapForStartInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> variables) {
|
public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> variables) {
|
||||||
final List<VariableDescriptor> functionVariables = Lists.newArrayList();
|
final List<VariableDescriptor> functionVariables = Lists.newArrayList();
|
||||||
for (VariableDescriptor variable : variables) {
|
for (VariableDescriptor variable : variables) {
|
||||||
@@ -402,16 +267,16 @@ public class JetFlowInformationProvider {
|
|||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
|
|
||||||
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
JetControlFlowGraphTraverser.<Void>create(pseudocode).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(Instruction instruction) {
|
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
|
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
|
||||||
//check that we only invoke this variable
|
//check that we only invoke this variable
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) {
|
if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) {
|
||||||
trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression)element, variableDescriptor));
|
trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,9 +314,9 @@ public class JetFlowInformationProvider {
|
|||||||
|
|
||||||
private Collection<VariableDescriptor> collectUsedVariables(Pseudocode pseudocode) {
|
private Collection<VariableDescriptor> collectUsedVariables(Pseudocode pseudocode) {
|
||||||
final Set<VariableDescriptor> usedVariables = Sets.newHashSet();
|
final Set<VariableDescriptor> usedVariables = Sets.newHashSet();
|
||||||
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
JetControlFlowGraphTraverser.<Void>create(pseudocode).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(Instruction instruction) {
|
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
usedVariables.add(variableDescriptor);
|
usedVariables.add(variableDescriptor);
|
||||||
@@ -462,13 +327,13 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<VariableDescriptor> collectDeclaredVariables(JetElement element) {
|
private Collection<VariableDescriptor> collectDeclaredVariables(JetElement element) {
|
||||||
final Set<VariableDescriptor> concernedVariables = Sets.newHashSet();
|
final Set<VariableDescriptor> declaredVariables = Sets.newHashSet();
|
||||||
element.accept(new JetTreeVisitor<Void>() {
|
element.accept(new JetTreeVisitor<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void visitProperty(JetProperty property, Void data) {
|
public Void visitProperty(JetProperty property, Void data) {
|
||||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
|
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
|
||||||
assert descriptor instanceof VariableDescriptor;
|
assert descriptor instanceof VariableDescriptor;
|
||||||
concernedVariables.add((VariableDescriptor) descriptor);
|
declaredVariables.add((VariableDescriptor) descriptor);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,12 +343,12 @@ public class JetFlowInformationProvider {
|
|||||||
if (loopParameter != null) {
|
if (loopParameter != null) {
|
||||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, loopParameter);
|
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, loopParameter);
|
||||||
assert descriptor instanceof VariableDescriptor;
|
assert descriptor instanceof VariableDescriptor;
|
||||||
concernedVariables.add((VariableDescriptor) descriptor);
|
declaredVariables.add((VariableDescriptor) descriptor);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
return concernedVariables;
|
return declaredVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class InitializationPoints {
|
private static class InitializationPoints {
|
||||||
|
|||||||
Reference in New Issue
Block a user