arrays and primitive collections

(annotations.xml was changed because the order of graph construction was changed - this particular case is a tricky one with loop, exception and synchronization)
This commit is contained in:
Ilya Klyuchnikov
2014-07-10 10:35:46 +02:00
committed by peter
parent 658b710762
commit 0db25e9166
5 changed files with 45 additions and 38 deletions
@@ -205,10 +205,9 @@ class ProceedState<Res> implements PendingAction<Res> {
class MakeResult<Res> implements PendingAction<Res> {
final State state;
final Res subResult;
final List<Integer> indices;
final int[] indices;
// TODO - indices array
MakeResult(State state, Res subResult, List<Integer> indices) {
MakeResult(State state, Res subResult, int[] indices) {
this.state = state;
this.subResult = subResult;
this.indices = indices;
@@ -144,7 +144,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = inValue == Value.Null ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
@@ -152,7 +152,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = inValue == Value.NotNull ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
@@ -160,7 +160,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue && inValue == Value.Null) {
int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
@@ -168,7 +168,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue && inValue == Value.Null) {
int nextInsnIndex = insnIndex + 1;
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
@@ -176,7 +176,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFEQ && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = inValue == Value.True ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
@@ -184,16 +184,18 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
if (opcode == IFNE && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = inValue == Value.False ? insnIndex + 1 : methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, false);
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, new int[]{nextState.index}));
pending.push(new ProceedState<Result<Key, Value>>(nextState));
return;
}
// general case
List<Integer> nextInsnIndices = controlFlow.transitions[insnIndex];
List<State> nextStates = new ArrayList<State>();
List<Integer> subIndices = new ArrayList<Integer>();
for (int nextInsnIndex : nextInsnIndices) {
int[] nextInsnIndices = controlFlow.transitions[insnIndex];
List<State> nextStates = new ArrayList<State>(nextInsnIndices.length);
int[] subIndices = new int[nextInsnIndices.length];
for (int i = 0; i < nextInsnIndices.length; i++) {
int nextInsnIndex = nextInsnIndices[i];
Frame<BasicValue> nextFrame1 = nextFrame;
if (controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
nextFrame1 = new Frame<BasicValue>(frame);
@@ -201,7 +203,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
nextFrame1.push(new BasicValue(Type.getType("java/lang/Throwable")));
}
nextStates.add(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, false));
subIndices.add(id);
subIndices[i] = id;
}
pending.push(new MakeResult<Result<Key, Value>>(state, myIdentity, subIndices));
@@ -16,6 +16,7 @@
package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.openapi.diagnostic.Logger;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntHashSet;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.InsnList;
@@ -158,7 +159,7 @@ final class cfg {
// Graphs: Theory and Algorithms. by K. Thulasiraman , M. N. S. Swamy (1992)
// 11.7.2 DFS of a directed graph
static DFSTree buildDFSTree(List<Integer>[] transitions) {
static DFSTree buildDFSTree(int[][] transitions) {
Set<Edge> tree = new HashSet<Edge>();
Set<Edge> forward = new HashSet<Edge>();
Set<Edge> back = new HashSet<Edge>();
@@ -307,10 +308,10 @@ final class Edge {
final class ControlFlowGraph {
final String className;
final MethodNode methodNode;
final List<Integer>[] transitions;
final int[][] transitions;
final Set<Edge> errorTransitions;
ControlFlowGraph(String className, MethodNode methodNode, List<Integer>[] transitions, Set<Edge> errorTransitions) {
ControlFlowGraph(String className, MethodNode methodNode, int[][] transitions, Set<Edge> errorTransitions) {
this.className = className;
this.methodNode = methodNode;
this.transitions = transitions;
@@ -340,34 +341,42 @@ final class ControlFlowBuilder extends Analyzer<BasicValue> {
static final BasicInterpreter INTERPRETER = new BasicInterpreter();
final String className;
final MethodNode methodNode;
final LinkedList<Integer>[] transitions;
final TIntArrayList[] transitions;
final Set<Edge> errorTransitions;
ControlFlowBuilder(String className, MethodNode methodNode) {
super(INTERPRETER);
this.className = className;
this.methodNode = methodNode;
transitions = new LinkedList[methodNode.instructions.size()];
transitions = new TIntArrayList[methodNode.instructions.size()];
for (int i = 0; i < transitions.length; i++) {
transitions[i] = new LinkedList<Integer>();
transitions[i] = new TIntArrayList();
}
errorTransitions = new HashSet<Edge>();
}
final ControlFlowGraph buildCFG() throws AnalyzerException {
analyze(className, methodNode);
return new ControlFlowGraph(className, methodNode, transitions, errorTransitions);
int[][] resultTransitions = new int[transitions.length][];
for (int i = 0; i < resultTransitions.length; i++) {
resultTransitions[i] = transitions[i].toNativeArray();
}
return new ControlFlowGraph(className, methodNode, resultTransitions, errorTransitions);
}
@Override
protected final void newControlFlowEdge(int insn, int successor) {
transitions[insn].addFirst(successor);
if (!transitions[insn].contains(successor)) {
transitions[insn].add(successor);
}
}
@Override
protected final boolean newControlFlowExceptionEdge(int insn, int successor) {
transitions[insn].addFirst(successor);
errorTransitions.add(new Edge(insn, successor));
if (!transitions[insn].contains(successor)) {
transitions[insn].add(successor);
errorTransitions.add(new Edge(insn, successor));
}
return true;
}
}
@@ -217,7 +217,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
if (opcode == IFNONNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = insnIndex + 1;
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, hasCompanions || notEmptySubResult);
pending.push(new MakeResult<PResult>(state, subResult, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<PResult>(state, subResult, new int[]{nextState.index}));
pending.push(new ProceedState<PResult>(nextState));
return;
}
@@ -225,7 +225,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
if (opcode == IFNULL && popValue(frame) instanceof ParamValue) {
int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, hasCompanions || notEmptySubResult);
pending.push(new MakeResult<PResult>(state, subResult, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<PResult>(state, subResult, new int[]{nextState.index}));
pending.push(new ProceedState<PResult>(nextState));
return;
}
@@ -233,7 +233,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
if (opcode == IFEQ && popValue(frame) == InstanceOfCheckValue) {
int nextInsnIndex = methodNode.instructions.indexOf(((JumpInsnNode)insnNode).label);
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, hasCompanions || notEmptySubResult);
pending.push(new MakeResult<PResult>(state, subResult, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<PResult>(state, subResult, new int[]{nextState.index}));
pending.push(new ProceedState<PResult>(nextState));
return;
}
@@ -241,16 +241,18 @@ class NonNullInAnalysis extends Analysis<PResult> {
if (opcode == IFNE && popValue(frame) == InstanceOfCheckValue) {
int nextInsnIndex = insnIndex + 1;
State nextState = new State(++id, new Conf(nextInsnIndex, nextFrame), nextHistory, true, hasCompanions || notEmptySubResult);
pending.push(new MakeResult<PResult>(state, subResult, Collections.singletonList(nextState.index)));
pending.push(new MakeResult<PResult>(state, subResult, new int[]{nextState.index}));
pending.push(new ProceedState<PResult>(nextState));
return;
}
// general case
List<Integer> nextInsnIndices = controlFlow.transitions[insnIndex];
List<State> nextStates = new ArrayList<State>();
List<Integer> subIndices = new ArrayList<Integer>();
for (int nextInsnIndex : nextInsnIndices) {
int[] nextInsnIndices = controlFlow.transitions[insnIndex];
List<State> nextStates = new ArrayList<State>(nextInsnIndices.length);
int[] subIndices = new int[nextInsnIndices.length];
for (int i = 0; i < nextInsnIndices.length; i++) {
int nextInsnIndex = nextInsnIndices[i];
Frame<BasicValue> nextFrame1 = nextFrame;
if (controlFlow.errorTransitions.contains(new Edge(insnIndex, nextInsnIndex))) {
nextFrame1 = new Frame<BasicValue>(frame);
@@ -258,7 +260,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
nextFrame1.push(new BasicValue(Type.getType("java/lang/Throwable")));
}
nextStates.add(new State(++id, new Conf(nextInsnIndex, nextFrame1), nextHistory, taken, hasCompanions || notEmptySubResult));
subIndices.add(id);
subIndices[i] = (id);
}
pending.push(new MakeResult<PResult>(state, subResult, subIndices));
@@ -61,11 +61,6 @@
<item name="java.net.InetAddress int checkNumericZone(java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>
<item name="java.net.InetAddress java.lang.Object checkLookupTable(java.lang.String)">
<annotation name="org.jetbrains.annotations.Contract">
<val val="&quot;null-&gt;null&quot;"/>
</annotation>
</item>
<item name="java.net.InetAddress java.lang.Object getCachedAddress(java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>