1 21 package proguard.evaluation; 22 23 import proguard.evaluation.value.*; 24 25 31 public class Stack 32 { 33 private static final TopValue TOP_VALUE = new TopValue(); 34 35 36 protected Value[] values; 37 protected int currentSize; 38 protected int actualMaxSize; 39 40 41 45 public Stack(int maxSize) 46 { 47 values = new Value[maxSize]; 48 } 49 50 51 54 public Stack(Stack stack) 55 { 56 this(stack.values.length); 58 59 copy(stack); 61 } 62 63 64 68 public int getActualMaxSize() 69 { 70 return actualMaxSize; 71 } 72 73 74 77 public void reset(int maxSize) 78 { 79 if (maxSize > values.length) 81 { 82 values = new Value[maxSize]; 84 } 85 86 clear(); 88 89 actualMaxSize = 0; 90 } 91 92 93 96 public void copy(Stack other) 97 { 98 if (other.values.length > values.length) 100 { 101 values = new Value[other.values.length]; 103 } 104 105 System.arraycopy(other.values, 0, this.values, 0, other.currentSize); 107 108 currentSize = other.currentSize; 110 actualMaxSize = other.actualMaxSize; 111 } 112 113 114 119 public boolean generalize(Stack other) 120 { 121 if (this.currentSize != other.currentSize) 122 { 123 throw new IllegalArgumentException ("Stacks have different current sizes ["+this.currentSize+"] and ["+other.currentSize+"]"); 124 } 125 126 boolean changed = false; 127 128 for (int index = 0; index < currentSize; index++) 130 { 131 Value thisValue = this.values[index]; 132 133 if (thisValue != null) 134 { 135 Value newValue = null; 136 137 Value otherValue = other.values[index]; 138 139 if (otherValue != null) 140 { 141 newValue = thisValue.generalize(otherValue); 142 } 143 144 changed = changed || !thisValue.equals(newValue); 145 146 values[index] = newValue; 147 } 148 } 149 150 if (this.actualMaxSize < other.actualMaxSize) 152 { 153 this.actualMaxSize = other.actualMaxSize; 154 } 155 156 return changed; 157 } 158 159 160 163 public void clear() 164 { 165 for (int index = 0; index < currentSize; index++) 167 { 168 values[index] = null; 169 } 170 171 currentSize = 0; 172 } 173 174 175 179 public int size() 180 { 181 return currentSize; 182 } 183 184 185 191 public Value getBottom(int index) 192 { 193 return values[index]; 194 } 195 196 197 203 public void setBottom(int index, Value value) 204 { 205 values[index] = value; 206 } 207 208 209 215 public Value getTop(int index) 216 { 217 return values[currentSize - index - 1]; 218 } 219 220 221 227 public void setTop(int index, Value value) 228 { 229 values[currentSize - index - 1] = value; 230 } 231 232 233 238 public void removeTop(int index) 239 { 240 System.arraycopy(values, currentSize - index, 241 values, currentSize - index - 1, 242 index); 243 currentSize--; 244 } 245 246 247 250 public void push(Value value) 251 { 252 if (value.isCategory2()) 254 { 255 values[currentSize++] = TOP_VALUE; 256 } 257 258 values[currentSize++] = value; 260 261 if (actualMaxSize < currentSize) 263 { 264 actualMaxSize = currentSize; 265 } 266 } 267 268 269 272 public Value pop() 273 { 274 Value value = values[--currentSize]; 275 276 values[currentSize] = null; 277 278 if (value.isCategory2()) 280 { 281 values[--currentSize] = null; 282 } 283 284 return value; 285 } 286 287 288 290 293 public IntegerValue ipop() 294 { 295 return pop().integerValue(); 296 } 297 298 299 302 public LongValue lpop() 303 { 304 return pop().longValue(); 305 } 306 307 308 311 public FloatValue fpop() 312 { 313 return pop().floatValue(); 314 } 315 316 317 320 public DoubleValue dpop() 321 { 322 return pop().doubleValue(); 323 } 324 325 326 329 public ReferenceValue apop() 330 { 331 return pop().referenceValue(); 332 } 333 334 335 338 public InstructionOffsetValue opop() 339 { 340 return pop().instructionOffsetValue(); 341 } 342 343 344 347 public void pop1() 348 { 349 values[--currentSize] = null; 350 } 351 352 353 357 public void pop2() 358 { 359 values[--currentSize] = null; 360 values[--currentSize] = null; 361 } 362 363 364 367 public void dup() 368 { 369 values[currentSize] = values[currentSize - 1].category1Value(); 370 371 currentSize++; 372 373 if (actualMaxSize < currentSize) 375 { 376 actualMaxSize = currentSize; 377 } 378 } 379 380 381 385 public void dup_x1() 386 { 387 values[currentSize] = values[currentSize - 1].category1Value(); 388 values[currentSize - 1] = values[currentSize - 2].category1Value(); 389 values[currentSize - 2] = values[currentSize ]; 390 391 currentSize++; 392 393 if (actualMaxSize < currentSize) 395 { 396 actualMaxSize = currentSize; 397 } 398 } 399 400 401 405 public void dup_x2() 406 { 407 values[currentSize] = values[currentSize - 1].category1Value(); 408 values[currentSize - 1] = values[currentSize - 2]; 409 values[currentSize - 2] = values[currentSize - 3]; 410 values[currentSize - 3] = values[currentSize ]; 411 412 currentSize++; 413 414 if (actualMaxSize < currentSize) 416 { 417 actualMaxSize = currentSize; 418 } 419 } 420 421 425 public void dup2() 426 { 427 values[currentSize ] = values[currentSize - 2]; 428 values[currentSize + 1] = values[currentSize - 1]; 429 430 currentSize += 2; 431 432 if (actualMaxSize < currentSize) 434 { 435 actualMaxSize = currentSize; 436 } 437 } 438 439 440 444 public void dup2_x1() 445 { 446 values[currentSize + 1] = values[currentSize - 1]; 447 values[currentSize ] = values[currentSize - 2]; 448 values[currentSize - 1] = values[currentSize - 3]; 449 values[currentSize - 2] = values[currentSize + 1]; 450 values[currentSize - 3] = values[currentSize ]; 451 452 currentSize += 2; 453 454 if (actualMaxSize < currentSize) 456 { 457 actualMaxSize = currentSize; 458 } 459 } 460 461 462 466 public void dup2_x2() 467 { 468 values[currentSize + 1] = values[currentSize - 1]; 469 values[currentSize ] = values[currentSize - 2]; 470 values[currentSize - 1] = values[currentSize - 3]; 471 values[currentSize - 2] = values[currentSize - 4]; 472 values[currentSize - 3] = values[currentSize + 1]; 473 values[currentSize - 4] = values[currentSize ]; 474 475 currentSize += 2; 476 477 if (actualMaxSize < currentSize) 479 { 480 actualMaxSize = currentSize; 481 } 482 } 483 484 485 488 public void swap() 489 { 490 Value value1 = values[currentSize - 1].category1Value(); 491 Value value2 = values[currentSize - 2].category1Value(); 492 493 values[currentSize - 1] = value2; 494 values[currentSize - 2] = value1; 495 } 496 497 498 500 public boolean equals(Object object) 501 { 502 if (object == null || 503 this.getClass() != object.getClass()) 504 { 505 return false; 506 } 507 508 Stack other = (Stack)object; 509 510 if (this.currentSize != other.currentSize) 511 { 512 return false; 513 } 514 515 for (int index = 0; index < currentSize; index++) 516 { 517 Value thisValue = this.values[index]; 518 Value otherValue = other.values[index]; 519 if (thisValue == null ? otherValue != null : 520 !thisValue.equals(otherValue)) 521 { 522 return false; 523 } 524 } 525 526 return true; 527 } 528 529 530 public int hashCode() 531 { 532 int hashCode = currentSize; 533 534 for (int index = 0; index < currentSize; index++) 535 { 536 Value value = values[index]; 537 if (value != null) 538 { 539 hashCode ^= value.hashCode(); 540 } 541 } 542 543 return hashCode; 544 } 545 546 547 public String toString() 548 { 549 StringBuffer buffer = new StringBuffer (); 550 551 for (int index = 0; index < currentSize; index++) 552 { 553 Value value = values[index]; 554 buffer = buffer.append('[') 555 .append(value == null ? "empty" : value.toString()) 556 .append(']'); 557 } 558 559 return buffer.toString(); 560 } 561 } 562 | Popular Tags |