mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
never ending def use
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user