1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.util.ArrayList ; 23 import java.util.BitSet ; 24 import java.util.Collection ; 25 import java.util.Collections ; 26 27 import org.apache.bcel.Constants; 28 import org.apache.bcel.generic.ConstantPoolGen; 29 import org.apache.bcel.generic.INVOKESTATIC; 30 import org.apache.bcel.generic.Instruction; 31 import org.apache.bcel.generic.InvokeInstruction; 32 import org.apache.bcel.generic.StackConsumer; 33 34 import edu.umd.cs.findbugs.SystemProperties; 35 import edu.umd.cs.findbugs.ba.vna.ValueNumber; 36 import static edu.umd.cs.findbugs.ba.Debug.*; 37 38 62 public abstract class Frame<ValueType> { 63 64 68 private int lastUpdateTimestamp; 69 70 73 private int numLocals; 74 75 78 private ArrayList <ValueType> slotList; 79 80 84 private boolean isTop; 85 86 90 private boolean isBottom; 91 92 95 private static final int DEFAULT_STACK_CAPACITY = 10; 96 97 101 109 public Frame(int numLocals) { 110 this.numLocals = numLocals; 111 this.slotList = new ArrayList <ValueType>(numLocals 112 + DEFAULT_STACK_CAPACITY); 113 for (int i = 0; i < numLocals; ++i) 114 slotList.add(null); 115 } 116 117 121 public boolean isTop() { 122 return isTop; 123 } 124 125 129 public void setTop() { 130 isTop = true; 131 isBottom = false; 132 lastUpdateTimestamp = 0; 133 } 134 135 139 public boolean isBottom() { 140 return isBottom; 141 } 142 143 147 public void setBottom() { 148 isBottom = true; 149 isTop = false; 150 } 151 152 155 public void setValid() { 156 isTop = isBottom = false; 157 } 158 159 162 public boolean isValid() { 163 return !isTop() && !isBottom(); 164 } 165 166 172 public void pushValue(ValueType value) { 173 if (VERIFY_INTEGRITY && value == null) 174 throw new IllegalArgumentException (); 175 if (!isValid()) 176 throw new IllegalStateException ("accessing top or bottom frame"); 177 slotList.add(value); 178 } 179 180 187 public ValueType popValue() throws DataflowAnalysisException { 188 if (!isValid()) 189 throw new DataflowAnalysisException("accessing top or bottom frame"); 190 if (slotList.size() == numLocals) 191 throw new DataflowAnalysisException("operand stack empty"); 192 return slotList.remove(slotList.size() - 1); 193 } 194 195 201 public ValueType getTopValue() throws DataflowAnalysisException { 202 if (!isValid()) 203 throw new DataflowAnalysisException("accessing top or bottom frame"); 204 assert slotList.size() >= numLocals; 205 if (slotList.size() == numLocals) 206 throw new DataflowAnalysisException("operand stack is empty"); 207 return slotList.get(slotList.size() - 1); 208 } 209 210 215 public void getTopStackWords(ValueType[] valueList) 216 throws DataflowAnalysisException { 217 int stackDepth = getStackDepth(); 218 if (valueList.length > stackDepth) 219 throw new DataflowAnalysisException("not enough values on stack"); 220 int numSlots = slotList.size(); 221 for (int i = numSlots - valueList.length, j = 0; i < numSlots; ++i, ++j) { 222 valueList[j] = slotList.get(i); 223 } 224 } 225 226 233 public ValueType getStackValue(int loc) throws DataflowAnalysisException { 234 if (!isValid()) 235 throw new DataflowAnalysisException( 236 "Accessing TOP or BOTTOM frame!"); 237 int stackDepth = getStackDepth(); 238 if (loc >= stackDepth) 239 throw new DataflowAnalysisException( 240 "not enough values on stack: access=" + loc + ", avail=" 241 + stackDepth); 242 return slotList.get(slotList.size() - (loc + 1)); 243 } 244 245 252 public int getStackLocation(int loc) throws DataflowAnalysisException { 253 int stackDepth = getStackDepth(); 254 if (loc >= stackDepth) 255 throw new DataflowAnalysisException( 256 "not enough values on stack: access=" + loc + ", avail=" 257 + stackDepth); 258 return slotList.size() - (loc + 1); 259 } 260 261 272 public ValueType getInstance(Instruction ins, ConstantPoolGen cpg) 273 throws DataflowAnalysisException { 274 return getStackValue(getInstanceStackLocation(ins, cpg)); 275 } 276 277 296 public int getInstanceStackLocation(Instruction ins, ConstantPoolGen cpg) 297 throws DataflowAnalysisException { 298 int numConsumed = ins.consumeStack(cpg); 299 if (numConsumed == Constants.UNPREDICTABLE) 300 throw new DataflowAnalysisException( 301 "Unpredictable stack consumption in " + ins); 302 return numConsumed - 1; 303 } 304 305 316 public int getInstanceSlot(Instruction ins, ConstantPoolGen cpg) 317 throws DataflowAnalysisException { 318 if (!isValid()) { 319 throw new DataflowAnalysisException("Accessing invalid frame at " 320 + ins); 321 } 322 int numConsumed = ins.consumeStack(cpg); 323 if (numConsumed == Constants.UNPREDICTABLE) 324 throw new DataflowAnalysisException( 325 "Unpredictable stack consumption in " + ins); 326 if (numConsumed > getStackDepth()) 327 throw new DataflowAnalysisException("Stack underflow " + ins); 328 return getNumSlots() - numConsumed; 329 } 330 331 342 public int getNumArguments(InvokeInstruction ins, ConstantPoolGen cpg) 343 throws DataflowAnalysisException { 344 int numConsumed = getNumArgumentsIncludingObjectInstance(ins, cpg); 345 return (ins instanceof INVOKESTATIC) ? numConsumed : numConsumed - 1; 346 } 347 348 359 public int getNumArgumentsIncludingObjectInstance(InvokeInstruction ins, 360 ConstantPoolGen cpg) throws DataflowAnalysisException { 361 int numConsumed = ins.consumeStack(cpg); 362 if (numConsumed == Constants.UNPREDICTABLE) 363 throw new DataflowAnalysisException( 364 "Unpredictable stack consumption in " + ins); 365 return numConsumed; 366 } 367 368 382 public ValueType getArgument(InvokeInstruction ins, ConstantPoolGen cpg, 383 int i, int numArguments) throws DataflowAnalysisException { 384 if (i >= numArguments) 385 throw new IllegalArgumentException (); 386 return getStackValue((numArguments - 1) - i); 387 } 388 389 400 public int getArgumentSlot(int i, int numArguments) { 401 if (i >= numArguments) 402 throw new IllegalArgumentException (); 403 404 return (slotList.size() - numArguments) + i; 405 } 406 407 419 public ValueType getOperand(StackConsumer ins, ConstantPoolGen cpg, int i) 420 throws DataflowAnalysisException { 421 int numOperands = ins.consumeStack(cpg); 422 if (numOperands == Constants.UNPREDICTABLE) 423 throw new DataflowAnalysisException( 424 "Unpredictable stack consumption in " + ins); 425 return getStackValue((numOperands - 1) - i); 426 } 427 428 443 public BitSet getArgumentSet(InvokeInstruction invokeInstruction, 444 ConstantPoolGen cpg, DataflowValueChooser<ValueType> chooser) 445 throws DataflowAnalysisException { 446 BitSet chosenArgSet = new BitSet (); 447 int numArguments = getNumArguments(invokeInstruction, cpg); 448 449 for (int i = 0; i < numArguments; ++i) { 450 ValueType value = getArgument(invokeInstruction, cpg, i, 451 numArguments); 452 if (chooser.choose(value)) 453 chosenArgSet.set(i); 454 } 455 456 return chosenArgSet; 457 } 458 459 463 public void clearStack() { 464 if (!isValid()) 465 throw new IllegalStateException ("accessing top or bottom frame"); 466 assert slotList.size() >= numLocals; 467 if (slotList.size() > numLocals) 468 slotList.subList(numLocals, slotList.size()).clear(); 469 } 470 471 474 public int getStackDepth() { 475 return slotList.size() - numLocals; 476 } 477 478 481 public int getNumLocals() { 482 return numLocals; 483 } 484 485 488 public int getNumSlots() { 489 return slotList.size(); 490 } 491 492 499 public ValueType getValue(int n) { 500 if (!isValid()) 501 throw new IllegalStateException ("accessing top or bottom frame"); 502 return slotList.get(n); 503 } 504 505 513 public void setValue(int n, ValueType value) { 514 if (VERIFY_INTEGRITY && value == null) 515 throw new IllegalArgumentException (); 516 if (!isValid()) 517 throw new IllegalStateException ("accessing top or bottom frame"); 518 slotList.set(n, value); 519 } 520 521 529 public boolean sameAs(Frame<ValueType> other) { 530 if (isTop != other.isTop) 531 return false; 532 533 if (isTop && other.isTop) 534 return true; 535 536 if (isBottom != other.isBottom) 537 return false; 538 539 if (isBottom && other.isBottom) 540 return true; 541 542 if (getNumSlots() != other.getNumSlots()) 543 return false; 544 545 for (int i = 0; i < getNumSlots(); ++i) 546 if (!getValue(i).equals(other.getValue(i))) 547 return false; 548 549 return true; 550 } 551 552 558 public void copyFrom(Frame<ValueType> other) { 559 lastUpdateTimestamp = other.lastUpdateTimestamp; 560 int size = slotList.size(); 561 if (size == other.slotList.size()) { 562 for (int i = 0; i < size; i++) 563 slotList.set(i, other.slotList.get(i)); 564 } else { 565 slotList.clear(); 566 for (ValueType v : other.slotList) 567 slotList.add(v); 568 } 569 isTop = other.isTop; 570 isBottom = other.isBottom; 571 } 572 573 private static final boolean STACK_ONLY = SystemProperties 574 .getBoolean("dataflow.stackonly"); 575 576 579 @Override 580 public String toString() { 581 if (isTop()) 582 return "[TOP]"; 583 if (isBottom()) 584 return "[BOTTOM]"; 585 StringBuffer buf = new StringBuffer (); 586 buf.append('['); 587 int numSlots = getNumSlots(); 588 int start = STACK_ONLY ? getNumLocals() : 0; 589 for (int i = start; i < numSlots; ++i) { 590 if (!STACK_ONLY && i == getNumLocals()) { 591 int last = buf.length() - 1; 594 if (last >= 0) { 595 if (buf.charAt(last) == ',') 596 buf.deleteCharAt(last); 597 } 598 buf.append('|'); 599 } 600 String value = valueToString(getValue(i)); 601 if (i == numSlots - 1 && value.endsWith(",")) 602 value = value.substring(0, value.length() - 1); 603 buf.append(value); 604 } 606 buf.append(']'); 607 return buf.toString(); 608 } 609 610 615 protected String valueToString(ValueType value) { 616 return value.toString(); 617 } 618 619 622 public Collection <ValueType> allSlots() { 623 if (slotList == null) 624 return Collections.EMPTY_LIST; 625 return Collections.unmodifiableCollection(slotList); 626 } 627 628 632 public void setLastUpdateTimestamp(int lastUpdateTimestamp) { 633 this.lastUpdateTimestamp = lastUpdateTimestamp; 634 } 635 636 639 public int getLastUpdateTimestamp() { 640 return lastUpdateTimestamp; 641 } 642 643 } 644 645 | Popular Tags |