1 19 20 package jode.flow; 21 import jode.decompiler.LocalInfo; 22 import jode.expr.Expression; 23 import jode.expr.LocalLoadOperator; 24 import jode.expr.Operator; 25 26 35 public class VariableStack { 36 public final static VariableStack EMPTY = new VariableStack(); 37 38 final LocalInfo[] stackMap; 39 40 private VariableStack() { 41 stackMap = new LocalInfo[0]; 42 } 43 44 private VariableStack(LocalInfo[] stack) { 45 stackMap = stack; 46 } 47 48 public boolean isEmpty() { 49 return stackMap.length == 0; 50 } 51 52 public VariableStack pop(int count) { 53 LocalInfo[] newStack = new LocalInfo[stackMap.length - count]; 54 System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count); 55 return new VariableStack(newStack); 56 } 57 58 public VariableStack push(LocalInfo li) { 59 return poppush(0, li); 60 } 61 62 public VariableStack poppush(int count, LocalInfo li) { 63 LocalInfo[] newStack = new LocalInfo[stackMap.length - count + 1]; 64 System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count); 65 newStack[stackMap.length - count] = li; 66 return new VariableStack(newStack); 67 } 68 69 public VariableStack peek(int count) { 70 LocalInfo[] peeked = new LocalInfo[count]; 71 System.arraycopy(stackMap, stackMap.length - count, peeked, 0, count); 72 return new VariableStack(peeked); 73 } 74 75 public void merge(VariableStack other) { 76 if (stackMap.length != other.stackMap.length) 77 throw new IllegalArgumentException ("stack length differs"); 78 for (int i=0; i<stackMap.length; i++) { 79 if (stackMap[i].getType().stackSize() 80 != other.stackMap[i].getType().stackSize()) 81 throw new IllegalArgumentException 82 ("stack element length differs at "+i); 83 stackMap[i].combineWith(other.stackMap[i]); 84 } 85 } 86 87 91 public static VariableStack merge(VariableStack first, 92 VariableStack second) { 93 if (first == null) 94 return second; 95 else if (second == null) 96 return first; 97 first.merge(second); 98 return first; 99 } 100 101 public Expression mergeIntoExpression(Expression expr) { 102 103 104 for (int i = stackMap.length-1; i >= 0; i--) { 105 expr = expr.addOperand 108 (new LocalLoadOperator(stackMap[i].getType(), null, 109 stackMap[i])); 110 } 111 return expr; 112 } 113 114 public VariableStack executeSpecial(SpecialBlock special) { 115 if (special.type == special.POP) { 116 int popped = 0; 117 int newLength = stackMap.length; 118 while (popped < special.count) { 119 newLength--; 120 popped += stackMap[newLength].getType().stackSize(); 121 } 122 if (popped != special.count) 123 throw new IllegalArgumentException ("wrong POP"); 124 LocalInfo[] newStack = new LocalInfo[newLength]; 125 System.arraycopy(stackMap, 0, newStack, 0, newLength); 126 return new VariableStack(newStack); 127 } else if (special.type == special.DUP) { 128 int popped = 0; 129 int numDup = 0; 130 int startDup = stackMap.length; 131 while (popped < special.count) { 132 startDup--; 133 numDup++; 134 popped += stackMap[startDup].getType().stackSize(); 135 } 136 if (popped != special.count) 137 throw new IllegalArgumentException ("wrong DUP"); 138 int destDup = startDup; 139 int depth = 0; 140 while (depth < special.depth) { 141 destDup--; 142 depth += stackMap[destDup].getType().stackSize(); 143 } 144 if (depth != special.depth) 145 throw new IllegalArgumentException ("wrong DUP"); 146 LocalInfo[] newStack = new LocalInfo[stackMap.length + numDup]; 147 System.arraycopy(stackMap, 0, newStack, 0, destDup); 148 System.arraycopy(stackMap, startDup, newStack, destDup, numDup); 149 System.arraycopy(stackMap, destDup, newStack, destDup + numDup, 150 startDup - destDup); 151 System.arraycopy(stackMap, startDup, newStack, startDup + numDup, 152 numDup); 153 return new VariableStack(newStack); 154 } else if (special.type == special.SWAP) { 155 LocalInfo[] newStack = new LocalInfo[stackMap.length]; 156 System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - 2); 157 if (stackMap[stackMap.length-2].getType().stackSize() != 1 158 || stackMap[stackMap.length-1].getType().stackSize() != 1) 159 throw new IllegalArgumentException ("wrong SWAP"); 160 newStack[stackMap.length-2] = stackMap[stackMap.length-1]; 161 newStack[stackMap.length-1] = stackMap[stackMap.length-2]; 162 return new VariableStack(newStack); 163 } else 164 throw new jode.AssertError("Unknown SpecialBlock"); 165 } 166 167 public String toString() { 168 StringBuffer result = new StringBuffer ("["); 169 for (int i=0; i < stackMap.length; i++) { 170 if (i>0) 171 result.append(", "); 172 result.append(stackMap[i].getName()); 173 } 174 return result.append("]").toString(); 175 } 176 } 177 | Popular Tags |