rollback: moved 'collectData' to PseudocodeTraverser
This commit is contained in:
@@ -74,6 +74,117 @@ fun <D> Pseudocode.traverse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun <D> Pseudocode.collectData(
|
||||||
|
traversalOrder: TraversalOrder,
|
||||||
|
mergeDataWithLocalDeclarations: Boolean,
|
||||||
|
mergeEdges: (Instruction, Collection<D>) -> Edges<D>,
|
||||||
|
updateEdge: (Instruction, Instruction, D) -> D,
|
||||||
|
initialDataValue: D
|
||||||
|
): Map<Instruction, Edges<D>> {
|
||||||
|
val edgesMap = LinkedHashMap<Instruction, Edges<D>>()
|
||||||
|
initializeEdgesMap(edgesMap, initialDataValue)
|
||||||
|
edgesMap.put(getStartInstruction(traversalOrder), Edges(initialDataValue, initialDataValue))
|
||||||
|
|
||||||
|
val changed = BooleanArray(1)
|
||||||
|
changed[0] = true
|
||||||
|
while (changed[0]) {
|
||||||
|
changed[0] = false
|
||||||
|
collectDataFromSubgraph(
|
||||||
|
traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
|
||||||
|
mergeEdges, updateEdge, Collections.emptyList<Instruction>(), changed, false)
|
||||||
|
}
|
||||||
|
return edgesMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D> Pseudocode.initializeEdgesMap(
|
||||||
|
edgesMap: MutableMap<Instruction, Edges<D>>,
|
||||||
|
initialDataValue: D
|
||||||
|
) {
|
||||||
|
val instructions = getInstructions()
|
||||||
|
val initialEdge = Edges(initialDataValue, initialDataValue)
|
||||||
|
for (instruction in instructions) {
|
||||||
|
edgesMap.put(instruction, initialEdge)
|
||||||
|
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||||
|
instruction.getBody().initializeEdgesMap(edgesMap, initialDataValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D> Pseudocode.collectDataFromSubgraph(
|
||||||
|
traversalOrder: TraversalOrder,
|
||||||
|
mergeDataWithLocalDeclarations: Boolean,
|
||||||
|
edgesMap: MutableMap<Instruction, Edges<D>>,
|
||||||
|
mergeEdges: (Instruction, Collection<D>) -> Edges<D>,
|
||||||
|
updateEdge: (Instruction, Instruction, D) -> D,
|
||||||
|
previousSubGraphInstructions: Collection<Instruction>,
|
||||||
|
changed: BooleanArray,
|
||||||
|
isLocal: Boolean
|
||||||
|
) {
|
||||||
|
val instructions = getInstructions(traversalOrder)
|
||||||
|
val startInstruction = getStartInstruction(traversalOrder)
|
||||||
|
|
||||||
|
for (instruction in instructions) {
|
||||||
|
val isStart = instruction.isStartInstruction(traversalOrder)
|
||||||
|
if (!isLocal && isStart)
|
||||||
|
continue
|
||||||
|
|
||||||
|
fun getPreviousIncludingSubGraphInstructions(): Collection<Instruction> {
|
||||||
|
val previous = instruction.getPreviousInstructions(traversalOrder)
|
||||||
|
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
||||||
|
return previous
|
||||||
|
}
|
||||||
|
val result = ArrayList(previous)
|
||||||
|
result.addAll(previousSubGraphInstructions)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
val previousInstructions = getPreviousIncludingSubGraphInstructions()
|
||||||
|
|
||||||
|
fun updateEdgeDataForInstruction(
|
||||||
|
previousValue: Edges<D>?,
|
||||||
|
newValue: Edges<D>?
|
||||||
|
) {
|
||||||
|
if (previousValue != newValue && newValue != null) {
|
||||||
|
changed[0] = true
|
||||||
|
edgesMap.put(instruction, newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||||
|
val subroutinePseudocode = instruction.getBody()
|
||||||
|
val previous = if (mergeDataWithLocalDeclarations) previousInstructions else Collections.emptyList()
|
||||||
|
subroutinePseudocode.collectDataFromSubgraph(
|
||||||
|
traversalOrder, mergeDataWithLocalDeclarations,
|
||||||
|
edgesMap, mergeEdges, updateEdge, previous, changed, true)
|
||||||
|
if (mergeDataWithLocalDeclarations) {
|
||||||
|
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
|
||||||
|
val previousValue = edgesMap.get(instruction)
|
||||||
|
val newValue = edgesMap.get(lastInstruction)
|
||||||
|
val updatedValue =
|
||||||
|
if (newValue == null)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
Edges(updateEdge(lastInstruction, instruction, newValue.`in`),
|
||||||
|
updateEdge(lastInstruction, instruction, newValue.out))
|
||||||
|
updateEdgeDataForInstruction(previousValue, updatedValue)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val previousDataValue = edgesMap.get(instruction)
|
||||||
|
|
||||||
|
val incomingEdgesData = HashSet<D>()
|
||||||
|
|
||||||
|
for (previousInstruction in previousInstructions) {
|
||||||
|
val previousData = edgesMap.get(previousInstruction)
|
||||||
|
if (previousData != null) {
|
||||||
|
incomingEdgesData.add(updateEdge(
|
||||||
|
previousInstruction, instruction, previousData.out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val mergedData = mergeEdges(instruction, incomingEdgesData)
|
||||||
|
updateEdgeDataForInstruction(previousDataValue, mergedData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trait InstructionDataMergeStrategy<D> : (Instruction, Collection<D>) -> Edges<D>
|
trait InstructionDataMergeStrategy<D> : (Instruction, Collection<D>) -> Edges<D>
|
||||||
trait InstructionDataAnalyzeStrategy<D> : (Instruction, D, D) -> Unit
|
trait InstructionDataAnalyzeStrategy<D> : (Instruction, D, D) -> Unit
|
||||||
|
|
||||||
@@ -87,7 +198,7 @@ fun traverseFollowingInstructions(
|
|||||||
visited: MutableSet<Instruction>,
|
visited: MutableSet<Instruction>,
|
||||||
order: TraversalOrder,
|
order: TraversalOrder,
|
||||||
// true to continue traversal
|
// true to continue traversal
|
||||||
handler: ((Instruction)->Boolean)?
|
handler: ((Instruction) -> Boolean)?
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val stack = ArrayDeque<Instruction>()
|
val stack = ArrayDeque<Instruction>()
|
||||||
stack.push(rootInstruction)
|
stack.push(rootInstruction)
|
||||||
|
|||||||
+7
-113
@@ -38,124 +38,18 @@ public class PseudocodeVariableDataCollector(
|
|||||||
val lexicalScopeVariableInfo = computeLexicalScopeVariableInfo(pseudocode)
|
val lexicalScopeVariableInfo = computeLexicalScopeVariableInfo(pseudocode)
|
||||||
|
|
||||||
suppress("UNCHECKED_CAST")
|
suppress("UNCHECKED_CAST")
|
||||||
public fun <D> collectDataJ(
|
public fun <D> collectData(
|
||||||
traversalOrder: TraversalOrder,
|
traversalOrder: TraversalOrder,
|
||||||
mergeDataWithLocalDeclarations: Boolean,
|
mergeDataWithLocalDeclarations: Boolean,
|
||||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
|
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
|
||||||
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
|
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
|
||||||
//see KT-4605
|
val result = pseudocode.collectData(
|
||||||
return collectData(
|
|
||||||
traversalOrder, mergeDataWithLocalDeclarations,
|
traversalOrder, mergeDataWithLocalDeclarations,
|
||||||
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
|
||||||
) as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
|
{ (from, to, data) -> filterOutVariablesOutOfScope(from, to, data)},
|
||||||
}
|
Collections.emptyMap<VariableDescriptor, D>())
|
||||||
|
//see KT-4605
|
||||||
public fun <D> collectData(
|
return result as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
|
||||||
traversalOrder: TraversalOrder,
|
|
||||||
mergeDataWithLocalDeclarations: Boolean,
|
|
||||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
|
||||||
): Map<Instruction, Edges<Map<VariableDescriptor, D>>> {
|
|
||||||
val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
|
|
||||||
val edgesMap = LinkedHashMap<Instruction, Edges<Map<VariableDescriptor, D>>>()
|
|
||||||
initializeEdgesMap(pseudocode, edgesMap, initialDataValue)
|
|
||||||
edgesMap.put(pseudocode.getStartInstruction(traversalOrder), Edges(initialDataValue, initialDataValue))
|
|
||||||
|
|
||||||
val changed = BooleanArray(1)
|
|
||||||
changed[0] = true
|
|
||||||
while (changed[0]) {
|
|
||||||
changed[0] = false
|
|
||||||
collectDataFromSubgraph(
|
|
||||||
pseudocode, traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
|
|
||||||
instructionDataMergeStrategy, Collections.emptyList<Instruction>(), changed, false)
|
|
||||||
}
|
|
||||||
return edgesMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <M> initializeEdgesMap(
|
|
||||||
pseudocode: Pseudocode,
|
|
||||||
edgesMap: MutableMap<Instruction, Edges<M>>,
|
|
||||||
initialDataValue: M
|
|
||||||
) {
|
|
||||||
val instructions = pseudocode.getInstructions()
|
|
||||||
val initialEdge = Edges(initialDataValue, initialDataValue)
|
|
||||||
for (instruction in instructions) {
|
|
||||||
edgesMap.put(instruction, initialEdge)
|
|
||||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
|
||||||
initializeEdgesMap(instruction.getBody(), edgesMap, initialDataValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <D> collectDataFromSubgraph(
|
|
||||||
pseudocode: Pseudocode,
|
|
||||||
traversalOrder: TraversalOrder,
|
|
||||||
mergeDataWithLocalDeclarations: Boolean,
|
|
||||||
edgesMap: MutableMap<Instruction, Edges<Map<VariableDescriptor, D>>>,
|
|
||||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
|
|
||||||
previousSubGraphInstructions: Collection<Instruction>,
|
|
||||||
changed: BooleanArray,
|
|
||||||
isLocal: Boolean
|
|
||||||
) {
|
|
||||||
val instructions = pseudocode.getInstructions(traversalOrder)
|
|
||||||
val startInstruction = pseudocode.getStartInstruction(traversalOrder)
|
|
||||||
|
|
||||||
for (instruction in instructions) {
|
|
||||||
val isStart = instruction.isStartInstruction(traversalOrder)
|
|
||||||
if (!isLocal && isStart)
|
|
||||||
continue
|
|
||||||
|
|
||||||
fun getPreviousIncludingSubGraphInstructions(): Collection<Instruction> {
|
|
||||||
val previous = instruction.getPreviousInstructions(traversalOrder)
|
|
||||||
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
|
||||||
return previous
|
|
||||||
}
|
|
||||||
val result = ArrayList(previous)
|
|
||||||
result.addAll(previousSubGraphInstructions)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
val previousInstructions = getPreviousIncludingSubGraphInstructions()
|
|
||||||
|
|
||||||
fun updateEdgeDataForInstruction(
|
|
||||||
previousValue: Edges<Map<VariableDescriptor, D>>?,
|
|
||||||
newValue: Edges<Map<VariableDescriptor, D>>?
|
|
||||||
) {
|
|
||||||
if (previousValue != newValue && newValue != null) {
|
|
||||||
changed[0] = true
|
|
||||||
edgesMap.put(instruction, newValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
|
||||||
val subroutinePseudocode = instruction.getBody()
|
|
||||||
val previous = if (mergeDataWithLocalDeclarations) previousInstructions else Collections.emptyList()
|
|
||||||
collectDataFromSubgraph(
|
|
||||||
subroutinePseudocode, traversalOrder, mergeDataWithLocalDeclarations,
|
|
||||||
edgesMap, instructionDataMergeStrategy, previous, changed, true)
|
|
||||||
if (mergeDataWithLocalDeclarations) {
|
|
||||||
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
|
|
||||||
val previousValue = edgesMap.get(instruction)
|
|
||||||
val newValue = edgesMap.get(lastInstruction)
|
|
||||||
val updatedValue = if (newValue == null) null else
|
|
||||||
Edges(filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
|
|
||||||
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
|
|
||||||
updateEdgeDataForInstruction(previousValue, updatedValue)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val previousDataValue = edgesMap.get(instruction)
|
|
||||||
|
|
||||||
val incomingEdgesData = HashSet<Map<VariableDescriptor, D>>()
|
|
||||||
|
|
||||||
for (previousInstruction in previousInstructions) {
|
|
||||||
val previousData = edgesMap.get(previousInstruction)
|
|
||||||
if (previousData != null) {
|
|
||||||
incomingEdgesData.add(filterOutVariablesOutOfScope(
|
|
||||||
previousInstruction, instruction, previousData.out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val mergedData = instructionDataMergeStrategy(instruction, incomingEdgesData)
|
|
||||||
updateEdgeDataForInstruction(previousDataValue, mergedData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <D> filterOutVariablesOutOfScope(
|
private fun <D> filterOutVariablesOutOfScope(
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public class PseudocodeVariablesData {
|
|||||||
|
|
||||||
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
|
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
|
||||||
|
|
||||||
return pseudocodeVariableDataCollector.collectDataJ(
|
return pseudocodeVariableDataCollector.collectData(
|
||||||
FORWARD, /*mergeDataWithLocalDeclarations=*/ false,
|
FORWARD, /*mergeDataWithLocalDeclarations=*/ false,
|
||||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -159,7 +159,7 @@ public class PseudocodeVariablesData {
|
|||||||
Map<VariableDescriptor, VariableInitState> enterInstructionData =
|
Map<VariableDescriptor, VariableInitState> enterInstructionData =
|
||||||
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
||||||
Map<VariableDescriptor, VariableInitState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
|
Map<VariableDescriptor, VariableInitState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
|
||||||
instruction, enterInstructionData, lexicalScopeVariableInfo);
|
instruction, enterInstructionData, lexicalScopeVariableInfo);
|
||||||
return createEdges(enterInstructionData, exitInstructionData);
|
return createEdges(enterInstructionData, exitInstructionData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ public class PseudocodeVariablesData {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
|
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
|
||||||
return pseudocodeVariableDataCollector.collectDataJ(
|
return pseudocodeVariableDataCollector.collectData(
|
||||||
BACKWARD, /*mergeDataWithLocalDeclarations=*/ true,
|
BACKWARD, /*mergeDataWithLocalDeclarations=*/ true,
|
||||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
|
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user