package gov.nasa.jpf.vm.va; import java.util.Collection; import java.util.LinkedList; import java.util.List; import gov.nasa.jpf.vm.MJIEnv; /** * * @author Jens * */ public class Stack { public int top; public Entry[] slots; public Stack(int nOperands) { top = -1; slots = new Entry[nOperands]; } public void clear() { for (; top > -1; top--) { slots[top] = null; } } public void setRef(int index, boolean ref) { if (slots[index] != null) { slots[index].isRef = ref; } } public boolean hasAnyRef() { for (Entry e : slots) { if (e != null && e.isRef) { return true; } } return false; } public int[] getSlots() { int[] clone = new int[slots.length]; for (int i = 0; i < slots.length; i++) { if (slots[i] != null) { clone[i] = slots[i].value; } } return clone; } public Integer get(int index) { if (index < 0) { return -1; } if (slots[index] != null) { return slots[index].value; } return MJIEnv.NULL; } public Integer peek(int offset) { if (top < offset) { return -1; } if (slots[top - offset] == null) { return MJIEnv.NULL; } return slots[top - offset].value; } public Integer pop() { Integer res = slots[top] == null ? MJIEnv.NULL : slots[top].value; slots[top] = null; top--; return res; } public Entry popEntry() { return slots[top--]; } public void push(Integer value, boolean isRef) { slots[++top] = new Entry(value, isRef); } public void push(Entry entry) { slots[++top] = entry; } public boolean isRef(int offset) { // if (top - offset < 0) { // return false; // } return slots[top - offset].isRef; } public boolean isRefIndex(int index) { if (slots[index] != null) { return slots[index].isRef; } return false; } public void set(int offset, int value, boolean isRef) { slots[top - offset] = new Entry(value, isRef); } public void setIndex(int index, Integer value, boolean isRef) { slots[index] = new Entry(value, isRef); } Stack copy() { Stack clone = new Stack(slots.length); clone.top = top; System.arraycopy(slots, 0, clone.slots, 0, top + 1); return clone; } @Override public String toString() { StringBuilder string = new StringBuilder(); string.append('{'); int i = 0; for (Entry e : slots) { if (i == top) { string.append(" =>"); } if (e == null) { string.append(" null "); } else { string.append(e); } if (i == top) { string.append("<= "); } i++; } string.append('}'); return string.toString(); } @Override public boolean equals(Object o) { if (o instanceof Stack) { if (((Stack) o).top != top) { return false; } for (int i = 0; i <= top; i++) { if (((Stack) o).slots[i] == null) { if (slots[i] == null) { continue; } else { return false; } } if (!((Stack) o).slots[i].equals(slots[i])) { return false; } } return true; } return false; } /** * .. A B => .. B A B */ public void dup_x1() { Entry A = slots[top - 1]; Entry B = slots[top]; slots[top - 1] = B; slots[top] = A; slots[top + 1] = B; top++; } /** * .. A B C D => .. C D A B C D */ public void dup2_x2() { Entry A = slots[top - 3]; Entry B = slots[top - 2]; Entry C = slots[top - 1]; Entry D = slots[top]; slots[top - 3] = C; slots[top - 2] = D; slots[top - 1] = A; slots[top] = B; slots[top + 1] = C; slots[top + 2] = D; top += 2; } /** * .. A B C => .. B C A B C */ public void dup2_x1() { Entry A = slots[top - 2]; Entry B = slots[top - 1]; Entry C = slots[top]; slots[top - 2] = B; slots[top - 1] = C; slots[top] = A; slots[top + 1] = B; slots[top + 2] = C; top += 2; } /** * .. A B => .. A B A B */ public void dup2() { Entry A = slots[top - 1]; Entry B = slots[top]; slots[top - 1] = A; slots[top] = B; slots[top + 1] = A; slots[top + 2] = B; top += 2; } /** * .. A => .. A A */ public void dup() { slots[top + 1] = slots[top]; top++; } /** * .. A B C => .. C A B C */ public void dup_x2() { Entry A = slots[top - 2]; Entry B = slots[top - 1]; Entry C = slots[top]; slots[top - 2] = C; slots[top - 1] = A; slots[top] = B; slots[top + 1] = C; top++; } /** * .. A B => .. B A */ public void swap() { Entry A = slots[top - 1]; Entry B = slots[top]; slots[top - 1] = B; slots[top] = A; } @Override public int hashCode() { int hash = 7; for (Entry e : slots) { if (e != null) { hash = hash * 31 + e.value; } } return hash; } public Collection<Integer> getReferences() { List<Integer> references = new LinkedList<>(); for (int i = 0; i <= top; i++) { Entry e = slots[i]; if (e.isRef) { references.add(e.value); } } return references; } } class Entry { boolean isRef = false; final int value; // final Integer attr; Entry copy() { return new Entry(value, isRef); } public Entry(int value, boolean isRef) { this.value = value; this.isRef = isRef; } @Override public String toString() { if (isRef) { return " <" + value + "> "; } return " [" + value + "] "; } @Override public boolean equals(Object o) { return ((Entry) o).value == value && ((Entry) o).isRef == isRef; } @Override public int hashCode() { return value; } static Entry[] references = new Entry[128]; static Entry[] values = new Entry[128]; static { for (int i = 0; i < 128;i++) { references[i] = new Entry(i - 1, true); values[i] = new Entry(i - 1, false); } } static Entry create(int value, boolean isRef) { if (value >= -1 && value < 127) { if (isRef) { return references[value + 1]; } else { return values[value + 1]; } } return new Entry(value, isRef); } }