1 package gov.nasa.jpf.jvm; 20 21 import gov.nasa.jpf.JPFException; 22 import gov.nasa.jpf.jvm.bytecode.Instruction; 23 import gov.nasa.jpf.util.Debug; 24 import gov.nasa.jpf.util.HashData; 25 26 import java.util.Random ; 27 28 import org.apache.bcel.Constants; 29 30 31 40 public class StackFrame implements Constants { 41 44 private static Random random = new Random (); 45 46 47 int top; 48 49 52 int thisRef = -1; 53 54 55 int[] operands; 56 boolean[] isOperandRef; 57 58 62 Object [] operandAttr; 63 64 67 int[] locals; 68 boolean[] isLocalRef; 69 70 71 74 private Instruction pc; 75 76 79 private MethodInfo mi; 80 81 85 private boolean isDirectCall; 86 87 94 public StackFrame (MethodInfo m, boolean isDirect, StackFrame caller) { 95 mi = m; 96 pc = mi.getInstruction(0); 97 98 int nOperands = mi.getMaxStack(); 99 operands = new int[nOperands]; 100 isOperandRef = new boolean[nOperands]; 101 operandAttr = new Object [nOperands]; 102 top = -1; 104 int nargs = mi.getArgumentsSize(); 105 int nlocals = (pc == null) ? nargs : mi.getMaxLocals(); 106 locals = new int[nlocals]; 107 isLocalRef = new boolean[nlocals]; 108 109 isDirectCall = isDirect; 110 111 if (nargs > 0 && (caller != null)) { 113 int[] a = caller.operands; 114 boolean[] r = caller.isOperandRef; 115 116 for (int i=0, j=caller.top-nargs+1; i<nargs; i++, j++) { 117 locals[i] = a[j]; 118 isLocalRef[i] = r[j]; 119 } 120 121 if (!mi.isStatic()) { thisRef = locals[0]; 123 } 124 } 125 } 126 127 public StackFrame (MethodInfo m, boolean isDirect, int objRef) { 128 this(m, isDirect, null); 129 130 132 thisRef = objRef; 133 134 locals[0] = thisRef; 135 isLocalRef[0] = true; 136 } 137 138 141 private StackFrame () { 142 } 143 144 public boolean isDirectCall () { 145 return isDirectCall; 146 } 147 148 153 public int getCalleeThis (MethodInfo mi) { 154 return getCalleeThis(mi.getArgumentsSize()); 155 } 156 157 161 public int getCalleeThis (int size) { 162 int i = size-1; 164 if (top < i) { 165 return -1; 166 } 167 168 return operands[top-i]; 169 } 170 171 public ClassInfo getClassInfo () { 172 return mi.getClassInfo(); 173 } 174 175 public int getLine () { 177 return mi.getLineNumber(pc); 178 } 179 180 public void setOperandAttr (Object o) { 181 operandAttr[top] = o; 182 } 183 184 public Object getOperandAttr () { 185 if (top >=0 ){ 186 return operandAttr[top]; 187 } else { 188 return null; 189 } 190 } 191 192 public Object getOperandAttr (int offset) { 193 if (top >= offset) { 194 return operandAttr[top-offset]; 195 } else { 196 return null; 197 } 198 } 199 200 public void setLocalVariable (int index, int v, boolean ref) { 201 boolean activateGc = (isLocalRef[index] && (locals[index] != -1)); 202 203 locals[index] = v; 204 isLocalRef[index] = ref; 205 206 if (ref) { 207 if (v != -1) activateGc = true; 208 } 209 210 if (activateGc) { 211 JVM.getVM().getSystemState().activateGC(); 212 } 213 } 214 215 public int getLocalVariable (int i) { 216 return locals[i]; 217 } 218 219 public int getLocalVariable (String name) { 220 return getLocalVariable(getLocalVariableOffset(name)); 221 } 222 223 public String [] getLocalVariableNames () { 224 return mi.getLocalVariableNames(); 225 } 226 227 public boolean isLocalVariableRef (int idx) { 228 return isLocalRef[idx]; 229 } 230 231 public String getLocalVariableType (String name) { 232 String [] lNames = mi.getLocalVariableNames(); 233 String [] lTypes = mi.getLocalVariableTypes(); 234 235 if ((lNames != null) && (lTypes != null)) { 236 for (int i = 0, l = lNames.length; i < l; i++) { 237 if (name.equals(lNames[i])) { 238 return lTypes[i]; 239 } 240 } 241 } 242 243 throw new JPFException("Local variable " + name + " not found"); 244 } 245 246 public int[] getLocalVariables () { 247 return locals; 248 } 249 250 public void setLongLocalVariable (int index, long v) { 251 252 255 locals[index + 1] = Types.loLong(v); 256 locals[index] = Types.hiLong(v); 257 } 258 259 public long getLongLocalVariable (int i) { 260 return Types.intsToLong(locals[i + 1], locals[i]); 261 } 262 263 public long getLongLocalVariable (String name) { 264 return getLongLocalVariable(getLocalVariableOffset(name)); 265 } 266 267 public MethodInfo getMethodInfo () { 268 return mi; 269 } 270 271 public String getMethodName () { 272 return mi.getName(); 273 } 274 275 public boolean isOperandRef (int idx) { 276 return isOperandRef[top-idx]; 277 } 278 279 public boolean isOperandRef () { 280 return isOperandRef[top]; 281 } 282 283 public void setPC (Instruction newpc) { 284 pc = newpc; 285 } 286 287 public Instruction getPC () { 288 return pc; 289 } 290 291 public String getStackTrace () { 292 StringBuffer sb = new StringBuffer (128); 293 sb.append("\tat "); 294 sb.append(mi.getClassInfo().getName()); 295 sb.append("."); 296 sb.append(mi.getName()); 297 298 if (pc != null) { 299 sb.append("("); 300 sb.append(mi.getClassInfo().getSourceFileName()); 301 sb.append(":"); 302 sb.append(getLine()); 303 sb.append(")"); 304 } else { 305 sb.append("(Native Method)"); 306 } 307 309 return sb.toString(); 310 } 311 312 316 public int getThis () { 317 return thisRef; 318 } 319 320 public void clearOperandStack () { 322 top = -1; 323 } 324 325 public Object clone () { 328 StackFrame sf = new StackFrame(); 329 330 sf.operands = new int[operands.length]; 331 System.arraycopy(operands,0,sf.operands,0,top+1); 332 333 sf.isOperandRef = new boolean[operands.length]; 334 System.arraycopy( isOperandRef, 0, sf.isOperandRef, 0, top+1); 335 336 sf.operandAttr = new Object [operands.length]; 337 System.arraycopy(operandAttr, 0, sf.operandAttr, 0, top+1); 338 339 sf.top = top; 340 341 sf.locals = new int[locals.length]; 342 System.arraycopy(locals, 0, sf.locals, 0, locals.length); 343 344 sf.isLocalRef = new boolean[locals.length]; 345 System.arraycopy(isLocalRef, 0, sf.isLocalRef, 0, locals.length); 346 347 sf.pc = pc; 348 sf.mi = mi; 349 350 sf.isDirectCall = isDirectCall; 351 sf.thisRef = thisRef; 352 353 return sf; 354 } 355 356 359 public void dup () { 360 int t= top; 362 top++; 363 364 operands[top] = operands[t]; 365 isOperandRef[top] = isOperandRef[t]; 366 operandAttr[top] = operandAttr[t]; 367 } 368 369 public void dup2 () { 370 int td = top+1; 372 int ts = top-1; 373 operands[td] = operands[ts]; 374 isOperandRef[td] = isOperandRef[ts]; 375 operandAttr[td] = operandAttr[ts]; 376 377 td++; ts++; 378 operands[td] = operands[ts]; 379 isOperandRef[td] = isOperandRef[ts]; 380 operandAttr[td] = operandAttr[ts]; 381 382 top = td; 383 } 384 385 public void dup2_x1 () { 386 388 int b, c; 389 boolean bRef, cRef; 390 Object bAnn, cAnn; 391 int ts, td; 392 393 ts = top-1; td = top+1; 395 operands[td] = b = operands[ts]; 396 isOperandRef[td] = bRef = isOperandRef[ts]; 397 operandAttr[td] = bAnn = operandAttr[ts]; 398 399 ts=top; td++; 401 operands[td] = c = operands[ts]; 402 isOperandRef[td] = cRef = isOperandRef[ts]; 403 operandAttr[td] = cAnn = operandAttr[ts]; 404 405 ts=top-2; td=top; 407 operands[td] = operands[ts]; 408 isOperandRef[td] = isOperandRef[ts]; 409 operandAttr[td] = operandAttr[ts]; 410 411 td = ts; 413 operands[td] = b; 414 isOperandRef[td] = bRef; 415 operandAttr[td] = bAnn; 416 417 td++; 419 operands[td] = c; 420 isOperandRef[td] = cRef; 421 operandAttr[td] = cAnn; 422 423 top += 2; 424 } 425 426 public void dup2_x2 () { 427 429 int c, d; 430 boolean cRef, dRef; 431 Object cAnn, dAnn; 432 int ts, td; 433 434 ts = top-1; td = top+1; 436 operands[td] = c = operands[ts]; 437 isOperandRef[td] = cRef = isOperandRef[ts]; 438 operandAttr[td] = cAnn = operandAttr[ts]; 439 440 ts=top; td++; 442 operands[td] = d = operands[ts]; 443 isOperandRef[td] = dRef = isOperandRef[ts]; 444 operandAttr[td] = dAnn = operandAttr[ts]; 445 446 ts = top-3; td = top-1; 448 operands[td] = operands[ts]; 449 isOperandRef[td] = isOperandRef[ts]; 450 operandAttr[td] = operandAttr[ts]; 451 452 ts++; td = top; 454 operands[td] = operands[ts]; 455 isOperandRef[td] = isOperandRef[ts]; 456 operandAttr[td] = operandAttr[ts]; 457 458 td=ts; 460 operands[td] = c; 461 isOperandRef[td] = cRef; 462 operandAttr[td] = cAnn; 463 464 td++; 466 operands[td] = d; 467 isOperandRef[td] = dRef; 468 operandAttr[td] = dAnn; 469 470 top += 2; 471 } 472 473 public void dup_x1 () { 474 476 int b; 477 boolean bRef; 478 Object bAnn; 479 int ts, td; 480 481 ts = top; td = top+1; 483 operands[td] = b = operands[ts]; 484 isOperandRef[td] = bRef = isOperandRef[ts]; 485 operandAttr[td] = bAnn = operandAttr[ts]; 486 487 ts = top-1; td = top; 489 operands[td] = operands[ts]; 490 isOperandRef[td] = isOperandRef[ts]; 491 operandAttr[td] = operandAttr[ts]; 492 493 td = ts; 495 operands[td] = b; 496 isOperandRef[td] = bRef; 497 operandAttr[td] = bAnn; 498 499 top++; 500 } 501 502 public void dup_x2 () { 503 505 int c; 506 boolean cRef; 507 Object cAnn; 508 int ts, td; 509 510 ts = top; td = top+1; 512 operands[td] = c = operands[ts]; 513 isOperandRef[td] = cRef = isOperandRef[ts]; 514 operandAttr[td] = cAnn = operandAttr[ts]; 515 516 ts=top-1; td=top; 518 operands[td] = operands[ts]; 519 isOperandRef[td] = isOperandRef[ts]; 520 operandAttr[td] = operandAttr[ts]; 521 522 td=ts; ts--; 524 operands[td] = operands[ts]; 525 isOperandRef[td] = isOperandRef[ts]; 526 operandAttr[td] = operandAttr[ts]; 527 528 td = ts; 530 operands[td] = c; 531 isOperandRef[td] = cRef; 532 operandAttr[td] = cAnn; 533 534 top++; 535 } 536 537 538 public boolean equals (Object object) { 541 StackFrame sf = (StackFrame) object; 543 544 if (pc != sf.pc) { 548 return false; 549 } 550 551 if (mi != sf.mi) { 552 return false; 553 } 554 555 int[] l = sf.locals; 557 boolean[] lr = sf.isLocalRef; 558 int nlocals = locals.length; 559 560 if (nlocals != l.length) { 561 return false; 562 } 563 for (int idx = 0; idx < nlocals; idx++) { 564 if ((locals[idx] != l[idx]) || (isLocalRef[idx] != lr[idx])) { 565 return false; 566 } 567 } 568 569 int[] o = sf.operands; 571 boolean[] or = sf.isOperandRef; 572 573 if (top != sf.top) { 574 return false; 575 } 576 for (int idx = 0; idx <= top; idx++) { 577 if ((operands[idx] != o[idx]) || (isOperandRef[idx] != or[idx]) ) { 578 return false; 579 } 580 } 581 582 return true; 583 } 584 585 public boolean hasAnyRef () { 586 for (int i=0; i<=top; i++) { 587 if (isOperandRef[i]) { 588 return true; 589 } 590 } 591 592 for (int i = 0, l = locals.length; i < l; i++) { 593 if (isLocalRef[i]) { 594 return true; 595 } 596 } 597 598 return false; 599 } 600 601 public void hash (HashData hd) { 602 for (int i = 0, l = locals.length; i < l; i++) { 603 hd.add(locals[i]); 604 } 605 606 for (int i=0; i<=top; i++) { 607 hd.add(operands[i]); 608 } 609 } 610 611 public int hashCode () { 615 HashData hd = new HashData(); 616 617 hash(hd); 618 619 return hd.getValue(); 620 } 621 622 public void log (int id) { 623 Debug.print(Debug.MESSAGE, " SF#" + id + " S("); 624 625 for (int i = 0; i <=top; i++) { 626 Debug.print(Debug.MESSAGE, " "); 627 628 if (isOperandRef[i]) { 629 Debug.print(Debug.MESSAGE, "#"); 630 } 631 632 Debug.print(Debug.MESSAGE, operands[i] + ""); 633 } 634 635 Debug.print(Debug.MESSAGE, " ) L("); 636 637 for (int i = 0; i < locals.length; i++) { 638 int j = locals[i]; 639 Debug.print(Debug.MESSAGE, " "); 640 641 if (isLocalRef[i]) { 642 Debug.print(Debug.MESSAGE, "#"); 643 } 644 645 Debug.print(Debug.MESSAGE, j + ""); 646 } 647 648 Debug.print(Debug.MESSAGE, " ) "); 649 650 if (mi == null) { 651 Debug.print(Debug.MESSAGE, "null"); 652 } else { 653 Debug.print(Debug.MESSAGE, mi.getCompleteName()); 654 } 655 656 Debug.print(Debug.MESSAGE, ":"); 657 658 if (pc == null) { 659 Debug.println(Debug.MESSAGE, "null"); 660 } else { 661 Debug.println(Debug.MESSAGE, pc.getPosition() + " " + pc); 662 } 663 } 664 665 671 public void markThreadRoots (int tid) { 672 DynamicArea heap = DynamicArea.getHeap(); 673 int objRef; 674 675 for (int i=0; i<= top; i++) { 676 if (isOperandRef[i]) { 677 heap.markThreadRoot(operands[i], tid); 678 } 679 } 680 681 for (int i = 0, l = locals.length; i < l; i++) { 682 if (isLocalRef[i]) { 683 heap.markThreadRoot(locals[i], tid); 684 } 685 } 686 } 687 688 689 public void printStackContent () { 690 Debug.print(Debug.ERROR, "\tat "); 691 Debug.print(Debug.ERROR, mi.getCompleteName()); 692 693 if (pc != null) { 694 Debug.println(Debug.ERROR, ":" + pc.getPosition()); 695 } else { 696 Debug.println(Debug.ERROR); 697 } 698 699 Debug.println(Debug.ERROR, "\t Operand stack is:"); 700 701 for (int i = 0; i <=top; i++) { 702 Debug.print(Debug.ERROR, "\t "); 703 704 if (isOperandRef[i]) { 705 Debug.print(Debug.ERROR, "#"); 706 } 707 708 Debug.println(Debug.ERROR, operands[i]); 709 } 710 711 Debug.println(Debug.ERROR, "\t Local variables are:"); 712 713 for (int i = 0, l = locals.length; i < l; i++) { 714 Debug.print(Debug.ERROR, "\t "); 715 716 if (isLocalRef[i]) { 717 Debug.print(Debug.ERROR, "#"); 718 } 719 720 Debug.println(Debug.ERROR, "" + locals[i]); 721 } 722 } 723 724 public void printStackTrace () { 725 Debug.println(Debug.ERROR, getStackTrace()); 726 } 727 728 public void swap () { 729 int t = top-1; 730 int v = operands[top]; 731 boolean isRef = isOperandRef[top]; 732 Object a = operandAttr[top]; 733 734 operands[top] = operands[t]; 735 isOperandRef[top] = isOperandRef[t]; 736 operandAttr[top] = operandAttr[t]; 737 738 operands[t] = v; 739 isOperandRef[t] = isRef; 740 operandAttr[t] = a; 741 } 742 743 public String toString () { 744 StringBuffer sb = new StringBuffer (); 745 746 sb.append("StackFrame("); 747 sb.append("top="); sb.append(top); 748 sb.append("operands="); 749 sb.append('['); 750 751 for (int i = 0; i <= top; i++) { 752 if (i != 0) { 753 sb.append(','); 754 } 755 756 sb.append(operands[i]); 757 if (operandAttr[i] != null) { 758 sb.append('('); 759 sb.append(operandAttr[i]); 760 sb.append(')'); 761 } 762 } 763 764 sb.append(']'); 765 sb.append(','); 766 sb.append("locals="); 767 sb.append('['); 768 769 for (int i = 0; i < locals.length; i++) { 770 if (i != 0) { 771 sb.append(','); 772 } 773 774 sb.append(locals[i]); 775 } 776 777 sb.append(']'); 778 sb.append(','); 779 sb.append("pc="); 780 sb.append(pc.getPosition()); 781 sb.append(','); 782 sb.append("oRefs="); 783 784 for (int i = 0; i <= top; i++) { 785 sb.append(isOperandRef[i] ? 'R' : '-'); 786 } 787 788 sb.append(','); 789 sb.append("lRefs="); 790 791 for (int i = 0; i < locals.length; i++) { 792 sb.append(isLocalRef[i] ? 'R' : '-'); 793 } 794 795 sb.append(')'); 796 797 return sb.toString(); 798 } 799 800 long longPeek () { 801 return Types.intsToLong( operands[top], operands[top-1]); 802 } 803 804 long longPeek (int n) { 805 int i = top - n; 806 return Types.intsToLong( operands[i], operands[i-1]); 807 } 808 809 long longPop () { 810 int lo = pop(); 811 int hi = pop(); 812 813 return Types.intsToLong(lo, hi); 814 } 815 816 void longPush (long v) { 817 push(Types.hiLong(v), false); 818 push(Types.loLong(v), false); 819 } 820 821 int peek () { 822 return operands[top]; 823 } 824 825 int peek (int n) { 826 return operands[top-n]; 827 } 828 829 void pop (int n) { 830 int t = top - n; 831 for (int i=top; i>t; i--) { 832 if (isOperandRef[i] && (operands[i] != -1)) { 833 JVM.getVM().getSystemState().activateGC(); 834 break; 835 } 836 } 837 838 top = t; 839 } 840 841 int pop () { 842 int v = operands[top]; 843 844 if (isOperandRef[top]) { 845 if (v != -1) { 846 JVM.getVM().getSystemState().activateGC(); 847 } 848 } 849 top--; 850 851 855 return v; 856 } 857 858 void push (int v, boolean ref) { 859 top++; 860 operands[top] = v; 861 isOperandRef[top] = ref; 862 operandAttr[top] = null; 863 864 if (ref && (v != -1)) { 865 JVM.getVM().getSystemState().activateGC(); 866 } 867 } 868 869 private int getLocalVariableOffset (String name) { 871 String [] lNames = mi.getLocalVariableNames(); 872 String [] lTypes = mi.getLocalVariableTypes(); 873 874 int offset = 0; 875 876 for (int i = 0, l = lNames.length; i < l; i++) { 877 if (name.equals(lNames[i])) { 878 return offset; 879 } else { 880 offset += Types.getTypeSize(lTypes[i]); 881 } 882 } 883 884 throw new JPFException("Local variable " + name + " not found"); 885 } 886 887 } 888 889 | Popular Tags |