never ending def use

This commit is contained in:
Alexey Kudravtsev
2010-09-06 12:51:31 +04:00
parent 003f83bda8
commit d03fcb1710
5 changed files with 198 additions and 125 deletions
@@ -30,6 +30,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.IntArrayList;
import com.intellij.util.containers.Queue;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -105,25 +106,24 @@ public class DefUseUtil {
return result;
}
void touch() {
private void touch() {
if (myVariablesUseArmed == null) myVariablesUseArmed = new THashSet<PsiVariable>();
}
public boolean equals(Object obj) {
InstructionState state = (InstructionState) obj;
if (myVariablesUseArmed == null && state.myVariablesUseArmed == null) return true;
if (myVariablesUseArmed == null || state.myVariablesUseArmed == null) return false;
return myVariablesUseArmed.equals(state.myVariablesUseArmed);
}
public void merge(InstructionState state) {
touch();
myVariablesUseArmed.addAll(state.myVariablesUseArmed);
}
public void markVisited() {
public boolean contains(InstructionState state) {
return myVariablesUseArmed != null && state.myVariablesUseArmed != null &&
myVariablesUseArmed.containsAll(state.myVariablesUseArmed);
}
public boolean markVisited() {
boolean old = myIsVisited;
myIsVisited = true;
return old;
}
public boolean isVisited() {
@@ -172,9 +172,8 @@ public class DefUseUtil {
InstructionState[] states = getStates(instructions);
boolean[] defsArmed = new boolean[instructions.size()];
for (int i = 0; i < defsArmed.length; i++) defsArmed[i] = false;
List<InstructionState> queue = new ArrayList<InstructionState>();
Queue<InstructionState> queue = new Queue<InstructionState>(8);
for (int i = states.length - 1; i >= 0; i--) {
final InstructionState outerState = states[i];
@@ -186,11 +185,11 @@ public class DefUseUtil {
outerState.mergeUseArmed(psiVariable);
}
}
queue.add(outerState);
queue.addLast(outerState);
while (!queue.isEmpty()) {
ProgressManager.checkCanceled();
InstructionState state = queue.remove(0);
InstructionState state = queue.pullFirst();
state.markVisited();
int idx = state.getInstructionIdx();
@@ -215,11 +214,13 @@ public class DefUseUtil {
}
}
for (int j = 0; j < state.getBackwardTraces().size(); j++) {
int prevIdx = state.getBackwardTraces().get(j);
if (!state.equals(states[prevIdx])) {
states[prevIdx].merge(state);
queue.add(states[prevIdx]);
IntArrayList backwardTraces = state.getBackwardTraces();
for (int j = 0; j < backwardTraces.size(); j++) {
int prevIdx = backwardTraces.get(j);
InstructionState prevState = states[prevIdx];
if (!prevState.contains(state)) {
prevState.merge(state);
queue.addLast(prevState);
}
}
}
@@ -255,9 +256,8 @@ public class DefUseUtil {
@NotNull
public static PsiElement[] getDefs(PsiCodeBlock body, final PsiVariable def, PsiElement ref) {
try {
return new RefsDefs(body) {
final InstructionState[] states = getStates(instructions);
RefsDefs refsDefs = new RefsDefs(body) {
private final InstructionState[] states = getStates(instructions);
protected int nNext(int index) {
return states[index].getBackwardTraces().size();
@@ -267,7 +267,9 @@ public class DefUseUtil {
return states[index].getBackwardTraces().get(no);
}
protected boolean defs() { return true; }
protected boolean defs() {
return true;
}
protected void processInstruction(final Set<PsiElement> res, final Instruction instruction, int index) {
if (instruction instanceof WriteVariableInstruction) {
@@ -276,14 +278,17 @@ public class DefUseUtil {
final PsiElement element = flow.getElement(index);
element.accept(new JavaRecursiveElementWalkingVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression ref) {
@Override
public void visitReferenceExpression(PsiReferenceExpression ref) {
if (PsiUtil.isAccessedForWriting(ref)) {
if (ref.resolve() == def) {
res.add(ref);
}
}
}
@Override public void visitVariable(PsiVariable var) {
@Override
public void visitVariable(PsiVariable var) {
if (var == def && (var instanceof PsiParameter || var.hasInitializer())) {
res.add(var);
}
@@ -292,7 +297,8 @@ public class DefUseUtil {
}
}
}
}.get(def, ref);
};
return refsDefs.get(def, ref);
}
catch (AnalysisCanceledException e) {
return PsiElement.EMPTY_ARRAY;
@@ -302,8 +308,7 @@ public class DefUseUtil {
@NotNull
public static PsiElement[] getRefs(PsiCodeBlock body, final PsiVariable def, PsiElement ref) {
try {
return new RefsDefs(body) {
RefsDefs refsDefs = new RefsDefs(body) {
protected int nNext(int index) {
return instructions.get(index).nNext();
}
@@ -312,7 +317,9 @@ public class DefUseUtil {
return instructions.get(index).getNext(index, no);
}
protected boolean defs() { return false; }
protected boolean defs() {
return false;
}
protected void processInstruction(final Set<PsiElement> res, final Instruction instruction, int index) {
if (instruction instanceof ReadVariableInstruction) {
@@ -321,7 +328,8 @@ public class DefUseUtil {
final PsiElement element = flow.getElement(index);
element.accept(new JavaRecursiveElementWalkingVisitor() {
@Override public void visitReferenceExpression(PsiReferenceExpression ref) {
@Override
public void visitReferenceExpression(PsiReferenceExpression ref) {
if (ref.resolve() == def) {
res.add(ref);
}
@@ -330,15 +338,15 @@ public class DefUseUtil {
}
}
}
}.get(def, ref);
};
return refsDefs.get(def, ref);
}
catch (AnalysisCanceledException e) {
return PsiElement.EMPTY_ARRAY;
}
}
protected abstract static class RefsDefs {
private abstract static class RefsDefs {
protected abstract int nNext(int index);
protected abstract int getNext(int index, int no);
@@ -357,7 +365,7 @@ public class DefUseUtil {
protected abstract boolean defs ();
@NotNull
PsiElement[] get (final PsiVariable def, PsiElement refOrDef) {
private PsiElement[] get (final PsiVariable def, PsiElement refOrDef) {
if (body == null) {
return PsiElement.EMPTY_ARRAY;
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
</problems>
@@ -0,0 +1,109 @@
public class DefUse {
private int deflate_fast(int flush, int lookahead, int match_length) {
// short hash_head = 0; // head of the hash chain
int hash_head = 0; // head of the hash chain
boolean bflush; // set if current block must be flushed
while (true) {
// Make sure that we always have enough lookahead, except
// at the end of the input file. We need MAX_MATCH bytes
// for the next match, plus MIN_MATCH bytes to insert the
// string following the next match.
if (lookahead < 1) {
if (lookahead < 1 && flush == JZlib.Z_NO_FLUSH) {
return 0;
}
if (lookahead == 0) {
break; // flush the current block
}
}
// Insert the string window[strstart .. strstart+2] in the
// dictionary, and set hash_head to the head of the hash chain:
if (lookahead >= 0) {
ins_h = (ins_h << hash_shift ^ window[strstart + 0 - 1] & 0xff) &
hash_mask;
// prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = 0xffff;
}
// Find the longest match, discarding those <= prev_length.
// At this point we have always match_length < MIN_MATCH
if (hash_head != 0L &&
(strstart - hash_head & 0xffff) <= w_size - 1) {
// To simplify the code, we prevent matches with the string
// of window index 0 (in particular we have to avoid a match
// of the string with itself at the start of the input file).
if (strategy != JZlib.Z_HUFFMAN_ONLY) {
match_length = longest_match(hash_head);
}
// longest_match() sets match_start
}
if (match_length >= 0) {
// check_match(strstart, match_start, match_length);
bflush = _tr_tally(strstart - match_start, match_length -
0);
lookahead -= match_length;
// Insert new strings in the hash table only if the match length
// is not too large. This saves time but degrades compression.
if (match_length <= max_lazy_match && lookahead >= 0) {
match_length --; // string at strstart already in hash table
do {
strstart ++;
ins_h = (ins_h << hash_shift ^ window[strstart +
0 - 1] & 0xff) &
hash_mask;
// prev[strstart&w_mask]=hash_head=head[ins_h];
hash_head = head[ins_h] & 0xffff;
prev[strstart & w_mask] = head[ins_h];
head[ins_h] = (short) strstart;
// strstart never exceeds WSIZE-MAX_MATCH, so there are
// always MIN_MATCH bytes ahead.
} while (-- match_length != 0);
strstart ++;
} else {
strstart += match_length;
match_length = 0;
ins_h = window[strstart] & 0xff;
ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) &
hash_mask;
// If lookahead < MIN_MATCH, ins_h is garbage, but it does not
// matter since it will be recomputed at next deflate call.
}
} else {
// No match, output a literal byte
bflush = _tr_tally(0, window[strstart] & 0xff);
lookahead --;
strstart ++;
}
if (bflush) {
flush_block_only(false);
if (strm.avail_out == 0) {
return 0;
}
}
}
flush_block_only(flush == JZlib.Z_FINISH);
if (flush == 0) {
if (flush == JZlib.Z_FINISH) {
return 1;
} else {
return 0;
}
}
return flush == JZlib.Z_FINISH? 1 : 0;
}
}
@@ -30,21 +30,14 @@ public class DefUseTest extends InspectionTestCase {
public void testarrayIndexUsages() throws Exception {
doTest();
}
/* TODO:
// TODO:
public void testSCR28019() throws Exception {
doTest();
}
*/
public void testSCR40364() throws Exception {
doTest();
}
public void testArrayLength() throws Exception {
doTest();
}
public void testUsedInArrayInitializer() throws Exception {
doTest();
}
public void testSCR40364() throws Exception { doTest(); }
public void testArrayLength() throws Exception { doTest(); }
public void testUsedInArrayInitializer() throws Exception { doTest(); }
public void testHang() throws Exception { doTest(); }
}
@@ -19,31 +19,29 @@ import java.util.Arrays;
import java.util.List;
public class Queue<T> {
private final NormalState NORMAL_STATE = new NormalState();
private final InvertedState INVERTED_STATE = new InvertedState();
private Object[] myArray;
private int myFirst = 0;
private int myLast = 0;
private QueueState myState = NORMAL_STATE;
private int myFirst;
private int myLast;
private boolean isInverted;
public Queue(int initialCapacity) {
myArray = new Object[initialCapacity];
}
public void addLast(T object) {
int currrentSize = size();
if (currrentSize == myArray.length) {
myArray = myState.normalize(currrentSize * 2);
int currentSize = size();
if (currentSize == myArray.length) {
myArray = normalize(currentSize * 2);
myFirst = 0;
myLast = currrentSize;
myState = NORMAL_STATE;
myLast = currentSize;
isInverted = false;
}
myArray[myLast] = object;
myLast++;
if (myLast == myArray.length) {
isInverted = !isInverted;
myLast = 0;
}
myState.addLast(object);
}
public T pullFirst() {
return myState.pullFirst();
}
public boolean isEmpty() {
@@ -51,79 +49,40 @@ public class Queue<T> {
}
public int size() {
return myState.calculateSize();
return isInverted ? myArray.length - myFirst + myLast : myLast - myFirst;
}
public List<T> toList() {
return Arrays.asList(myState.normalize(size()));
return Arrays.asList(normalize(size()));
}
private abstract class QueueState {
public abstract T[] normalize(int capacity);
public T pullFirst() {
T result = (T)myArray[myFirst];
myArray[myFirst] = null;
myFirst++;
if (myFirst == myArray.length) {
myFirst = 0;
myState = inverted();
}
return result;
}
public void addLast(T object) {
myArray[myLast] = object;
myLast++;
if (myLast == myArray.length) {
myState = inverted();
myLast = 0;
}
}
protected abstract QueueState inverted();
public abstract int calculateSize();
protected int copyFromTo(int first, int last, T[] result, int destPos) {
int length = last - first;
System.arraycopy(myArray, first, result, destPos, length);
return length;
public T pullFirst() {
T result = (T)myArray[myFirst];
myArray[myFirst] = null;
myFirst++;
if (myFirst == myArray.length) {
myFirst = 0;
isInverted = !isInverted;
}
return result;
}
private class NormalState extends QueueState {
public T[] normalize(int capacity) {
T[] result = (T[])new Object[capacity];
copyFromTo(myFirst, myLast, result, 0);
return result;
}
protected QueueState inverted() {
return INVERTED_STATE;
}
public int calculateSize() {
return myLast - myFirst;
}
private int copyFromTo(int first, int last, T[] result, int destPos) {
int length = last - first;
System.arraycopy(myArray, first, result, destPos, length);
return length;
}
private class InvertedState extends QueueState {
public T[] normalize(int capasity) {
T[] result = (T[])new Object[capasity];
int tailLength = copyFromTo(myFirst, myArray.length, result, 0);
copyFromTo(0, myLast, result, tailLength);
return result;
private T[] normalize(int capacity) {
T[] result = (T[])new Object[capacity];
int tailLength;
if (isInverted) {
tailLength = copyFromTo(myFirst, myArray.length, result, 0);
}
protected QueueState inverted() {
return NORMAL_STATE;
}
public int calculateSize() {
return myArray.length - myFirst + myLast;
else {
tailLength = 0;
}
copyFromTo(0, myLast, result, tailLength);
return result;
}
}