Refactoring: VariableInitState --> VariableControlFlowState

This commit is contained in:
Mikhail Glukhikh
2015-09-02 11:29:39 +03:00
parent 285d5d06c7
commit 726cbe3755
3 changed files with 62 additions and 61 deletions
@@ -28,7 +28,7 @@ import kotlin.jvm.functions.Function3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableInitState;
import org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableControlFlowState;
import org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableUseState;
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue;
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode;
@@ -302,7 +302,7 @@ public class JetFlowInformationProvider {
final boolean processClassOrObject = subroutine instanceof JetClassOrObject;
PseudocodeVariablesData pseudocodeVariablesData = getPseudocodeVariablesData();
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> initializers =
Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> initializers =
pseudocodeVariablesData.getVariableInitializers();
final Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, true);
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariablesData.getLexicalScopeVariableInfo();
@@ -311,12 +311,12 @@ public class JetFlowInformationProvider {
PseudocodeTraverserPackage.traverse(
pseudocode, FORWARD, initializers,
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableInitState>>() {
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableControlFlowState>>() {
@Override
public void execute(
@NotNull Instruction instruction,
@Nullable Map<VariableDescriptor, VariableInitState> in,
@Nullable Map<VariableDescriptor, VariableInitState> out
@Nullable Map<VariableDescriptor, VariableControlFlowState> in,
@Nullable Map<VariableDescriptor, VariableControlFlowState> out
) {
assert in != null && out != null;
VariableInitContext ctxt =
@@ -356,7 +356,7 @@ public class JetFlowInformationProvider {
public void recordInitializedVariables() {
PseudocodeVariablesData pseudocodeVariablesData = getPseudocodeVariablesData();
Pseudocode pseudocode = pseudocodeVariablesData.getPseudocode();
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> initializers =
Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> initializers =
pseudocodeVariablesData.getVariableInitializers();
recordInitializedVariables(pseudocode, initializers);
for (LocalFunctionDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
@@ -584,14 +584,14 @@ public class JetFlowInformationProvider {
private void recordInitializedVariables(
@NotNull Pseudocode pseudocode,
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>> initializersMap
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> initializersMap
) {
Edges<Map<VariableDescriptor, VariableInitState>> initializers = initializersMap.get(pseudocode.getExitInstruction());
Edges<Map<VariableDescriptor, VariableControlFlowState>> initializers = initializersMap.get(pseudocode.getExitInstruction());
Set<VariableDescriptor> declaredVariables = getPseudocodeVariablesData().getDeclaredVariables(pseudocode, false);
for (VariableDescriptor variable : declaredVariables) {
if (variable instanceof PropertyDescriptor) {
PseudocodeVariablesData.VariableInitState variableInitState = initializers.getIncoming().get(variable);
if (variableInitState != null && variableInitState.definitelyInitialized()) continue;
VariableControlFlowState variableControlFlowState = initializers.getIncoming().get(variable);
if (variableControlFlowState != null && variableControlFlowState.definitelyInitialized()) continue;
trace.record(BindingContext.IS_UNINITIALIZED, (PropertyDescriptor) variable);
}
}
@@ -977,14 +977,14 @@ public class JetFlowInformationProvider {
}
private class VariableInitContext extends VariableContext {
final VariableInitState enterInitState;
final VariableInitState exitInitState;
final VariableControlFlowState enterInitState;
final VariableControlFlowState exitInitState;
private VariableInitContext(
@NotNull Instruction instruction,
@NotNull Map<Instruction, DiagnosticFactory<?>> map,
@NotNull Map<VariableDescriptor, VariableInitState> in,
@NotNull Map<VariableDescriptor, VariableInitState> out,
@NotNull Map<VariableDescriptor, VariableControlFlowState> in,
@NotNull Map<VariableDescriptor, VariableControlFlowState> out,
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
) {
super(instruction, map);
@@ -992,13 +992,13 @@ public class JetFlowInformationProvider {
exitInitState = initialize(variableDescriptor, lexicalScopeVariableInfo, out);
}
private VariableInitState initialize(
private VariableControlFlowState initialize(
VariableDescriptor variableDescriptor,
LexicalScopeVariableInfo lexicalScopeVariableInfo,
Map<VariableDescriptor, VariableInitState> map
Map<VariableDescriptor, VariableControlFlowState> map
) {
if (variableDescriptor == null) return null;
VariableInitState state = map.get(variableDescriptor);
VariableControlFlowState state = map.get(variableDescriptor);
if (state != null) return state;
return PseudocodeVariablesData.getDefaultValueForInitializers(variableDescriptor, instruction, lexicalScopeVariableInfo);
}
@@ -50,7 +50,7 @@ public class PseudocodeVariablesData {
private final Map<Pseudocode, Set<VariableDescriptor>> declaredVariablesForDeclaration = Maps.newHashMap();
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializers;
private Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> variableInitializers;
public PseudocodeVariablesData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) {
this.pseudocode = pseudocode;
@@ -112,7 +112,7 @@ public class PseudocodeVariablesData {
// variable initializers
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers() {
public Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> getVariableInitializers() {
if (variableInitializers == null) {
variableInitializers = computeVariableInitializers();
}
@@ -121,31 +121,31 @@ public class PseudocodeVariablesData {
}
@NotNull
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> computeVariableInitializers() {
private Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> computeVariableInitializers() {
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
return pseudocodeVariableDataCollector.collectData(
FORWARD, /*mergeDataWithLocalDeclarations=*/ false,
new InstructionDataMergeStrategy<VariableInitState>() {
new InstructionDataMergeStrategy<VariableControlFlowState>() {
@NotNull
@Override
public Edges<Map<VariableDescriptor, VariableInitState>> invoke(
public Edges<Map<VariableDescriptor, VariableControlFlowState>> invoke(
@NotNull Instruction instruction,
@NotNull Collection<? extends Map<VariableDescriptor, VariableInitState>> incomingEdgesData
@NotNull Collection<? extends Map<VariableDescriptor, VariableControlFlowState>> incomingEdgesData
) {
Map<VariableDescriptor, VariableInitState> enterInstructionData =
Map<VariableDescriptor, VariableControlFlowState> enterInstructionData =
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
Map<VariableDescriptor, VariableControlFlowState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
instruction, enterInstructionData, lexicalScopeVariableInfo);
return new Edges<Map<VariableDescriptor, VariableInitState>>(enterInstructionData, exitInstructionData);
return new Edges<Map<VariableDescriptor, VariableControlFlowState>>(enterInstructionData, exitInstructionData);
}
}
);
}
public static VariableInitState getDefaultValueForInitializers(
public static VariableControlFlowState getDefaultValueForInitializers(
@NotNull VariableDescriptor variable,
@NotNull Instruction instruction,
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
@@ -155,24 +155,24 @@ public class PseudocodeVariablesData {
boolean declaredOutsideThisDeclaration =
declaredIn == null //declared outside this pseudocode
|| declaredIn.getLexicalScopeForContainingDeclaration() != instruction.getLexicalScope().getLexicalScopeForContainingDeclaration();
return VariableInitState.create(/*initState=*/declaredOutsideThisDeclaration);
return VariableControlFlowState.create(/*initState=*/declaredOutsideThisDeclaration);
}
@NotNull
private static Map<VariableDescriptor, VariableInitState> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<? extends Map<VariableDescriptor, VariableInitState>> incomingEdgesData
private static Map<VariableDescriptor, VariableControlFlowState> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<? extends Map<VariableDescriptor, VariableControlFlowState>> incomingEdgesData
) {
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
for (Map<VariableDescriptor, VariableControlFlowState> edgeData : incomingEdgesData) {
variablesInScope.addAll(edgeData.keySet());
}
Map<VariableDescriptor, VariableInitState> enterInstructionData = Maps.newHashMap();
Map<VariableDescriptor, VariableControlFlowState> enterInstructionData = Maps.newHashMap();
for (VariableDescriptor variable : variablesInScope) {
TriInitState initState = null;
boolean isDeclared = true;
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
VariableInitState varControlFlowState = edgeData.get(variable);
for (Map<VariableDescriptor, VariableControlFlowState> edgeData : incomingEdgesData) {
VariableControlFlowState varControlFlowState = edgeData.get(variable);
if (varControlFlowState != null) {
initState = initState != null ? initState.merge(varControlFlowState.initState) : varControlFlowState.initState;
if (!varControlFlowState.isDeclared) {
@@ -183,15 +183,15 @@ public class PseudocodeVariablesData {
if (initState == null) {
throw new AssertionError("An empty set of incoming edges data");
}
enterInstructionData.put(variable, VariableInitState.create(initState, isDeclared));
enterInstructionData.put(variable, VariableControlFlowState.create(initState, isDeclared));
}
return enterInstructionData;
}
@NotNull
private Map<VariableDescriptor, VariableInitState> addVariableInitStateFromCurrentInstructionIfAny(
private Map<VariableDescriptor, VariableControlFlowState> addVariableInitStateFromCurrentInstructionIfAny(
@NotNull Instruction instruction,
@NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData,
@NotNull Map<VariableDescriptor, VariableControlFlowState> enterInstructionData,
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
) {
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
@@ -201,26 +201,27 @@ public class PseudocodeVariablesData {
if (variable == null) {
return enterInstructionData;
}
Map<VariableDescriptor, VariableInitState> exitInstructionData = Maps.newHashMap(enterInstructionData);
Map<VariableDescriptor, VariableControlFlowState> exitInstructionData = Maps.newHashMap(enterInstructionData);
if (instruction instanceof WriteValueInstruction) {
// if writing to already initialized object
if (!PseudocodeUtil.isThisOrNoDispatchReceiver((WriteValueInstruction) instruction, bindingContext)) {
return enterInstructionData;
}
VariableInitState enterInitState = enterInstructionData.get(variable);
VariableInitState initializationAtThisElement =
VariableInitState.create(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState);
VariableControlFlowState enterInitState = enterInstructionData.get(variable);
VariableControlFlowState initializationAtThisElement =
VariableControlFlowState
.create(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState);
exitInstructionData.put(variable, initializationAtThisElement);
}
else { // instruction instanceof VariableDeclarationInstruction
VariableInitState enterInitState = enterInstructionData.get(variable);
VariableControlFlowState enterInitState = enterInstructionData.get(variable);
if (enterInitState == null) {
enterInitState = getDefaultValueForInitializers(variable, instruction, lexicalScopeVariableInfo);
}
if (enterInitState == null || !enterInitState.mayBeInitialized() || !enterInitState.isDeclared) {
boolean isInitialized = enterInitState != null && enterInitState.mayBeInitialized();
VariableInitState variableDeclarationInfo = VariableInitState.create(isInitialized, true);
VariableControlFlowState variableDeclarationInfo = VariableControlFlowState.create(isInitialized, true);
exitInstructionData.put(variable, variableDeclarationInfo);
}
}
@@ -300,25 +301,25 @@ public class PseudocodeVariablesData {
}
}
public static class VariableInitState {
public static class VariableControlFlowState {
public final TriInitState initState;
public final boolean isDeclared;
private VariableInitState(TriInitState initState, boolean isDeclared) {
private VariableControlFlowState(TriInitState initState, boolean isDeclared) {
this.initState = initState;
this.isDeclared = isDeclared;
}
private static final VariableInitState VS_IT = new VariableInitState(TriInitState.INITIALIZED, true);
private static final VariableInitState VS_IF = new VariableInitState(TriInitState.INITIALIZED, false);
private static final VariableInitState VS_UT = new VariableInitState(TriInitState.UNKNOWN, true);
private static final VariableInitState VS_UF = new VariableInitState(TriInitState.UNKNOWN, false);
private static final VariableInitState VS_NT = new VariableInitState(TriInitState.NOT_INITIALIZED, true);
private static final VariableInitState VS_NF = new VariableInitState(TriInitState.NOT_INITIALIZED, false);
private static final VariableControlFlowState VS_IT = new VariableControlFlowState(TriInitState.INITIALIZED, true);
private static final VariableControlFlowState VS_IF = new VariableControlFlowState(TriInitState.INITIALIZED, false);
private static final VariableControlFlowState VS_UT = new VariableControlFlowState(TriInitState.UNKNOWN, true);
private static final VariableControlFlowState VS_UF = new VariableControlFlowState(TriInitState.UNKNOWN, false);
private static final VariableControlFlowState VS_NT = new VariableControlFlowState(TriInitState.NOT_INITIALIZED, true);
private static final VariableControlFlowState VS_NF = new VariableControlFlowState(TriInitState.NOT_INITIALIZED, false);
private static VariableInitState create(TriInitState initState, boolean isDeclared) {
private static VariableControlFlowState create(TriInitState initState, boolean isDeclared) {
switch (initState) {
case INITIALIZED: return isDeclared ? VS_IT : VS_IF;
case UNKNOWN: return isDeclared ? VS_UT : VS_UF;
@@ -326,15 +327,15 @@ public class PseudocodeVariablesData {
}
}
private static VariableInitState create(boolean isInitialized, boolean isDeclared) {
private static VariableControlFlowState create(boolean isInitialized, boolean isDeclared) {
return create(isInitialized ? TriInitState.INITIALIZED : TriInitState.NOT_INITIALIZED, isDeclared);
}
private static VariableInitState create(boolean isInitialized) {
private static VariableControlFlowState create(boolean isInitialized) {
return create(isInitialized, false);
}
private static VariableInitState create(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) {
private static VariableControlFlowState create(boolean isDeclaredHere, @Nullable VariableControlFlowState mergedEdgesData) {
return create(true, isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared));
}
@@ -30,7 +30,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableInitState;
import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableControlFlowState;
import static org.jetbrains.kotlin.cfg.PseudocodeVariablesData.VariableUseState;
public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest {
@@ -42,7 +42,7 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest {
@NotNull BindingContext bindingContext
) {
PseudocodeVariablesData pseudocodeVariablesData = new PseudocodeVariablesData(pseudocode.getRootPseudocode(), bindingContext);
final Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializers =
final Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> variableInitializers =
pseudocodeVariablesData.getVariableInitializers();
final Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> useStatusData =
pseudocodeVariablesData.getVariableUseStatusData();
@@ -54,8 +54,8 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest {
@Override
public String invoke(Instruction instruction, Instruction next, Instruction prev) {
StringBuilder result = new StringBuilder();
Edges<Map<VariableDescriptor, VariableInitState>> initializersEdges = variableInitializers.get(instruction);
Edges<Map<VariableDescriptor, VariableInitState>> previousInitializersEdges = variableInitializers.get(prev);
Edges<Map<VariableDescriptor, VariableControlFlowState>> initializersEdges = variableInitializers.get(instruction);
Edges<Map<VariableDescriptor, VariableControlFlowState>> previousInitializersEdges = variableInitializers.get(prev);
String initializersData = "";
if (initializersEdges != null && !initializersEdges.equals(previousInitializersEdges)) {
initializersData = dumpEdgesData(initPrefix, initializersEdges);
@@ -75,11 +75,11 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest {
private static int countDataColumnWidth(
@NotNull String prefix,
@NotNull List<Instruction> instructions,
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> data
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, VariableControlFlowState>>> data
) {
int maxWidth = 0;
for (Instruction instruction : instructions) {
Edges<Map<VariableDescriptor, VariableInitState>> edges = data.get(instruction);
Edges<Map<VariableDescriptor, VariableControlFlowState>> edges = data.get(instruction);
if (edges == null) continue;
int length = dumpEdgesData(prefix, edges).length();
if (maxWidth < length) {