1 package gov.nasa.jpf.jvm; 20 21 import gov.nasa.jpf.Config; 22 import gov.nasa.jpf.JPFException; 23 import gov.nasa.jpf.jvm.bytecode.INVOKESTATIC; 24 import gov.nasa.jpf.jvm.bytecode.Instruction; 25 import gov.nasa.jpf.jvm.bytecode.InvokeInstruction; 26 import gov.nasa.jpf.jvm.bytecode.MONITORENTER; 27 import gov.nasa.jpf.jvm.bytecode.ReturnInstruction; 28 import gov.nasa.jpf.util.CoverageManager; 29 import gov.nasa.jpf.util.Debug; 30 import gov.nasa.jpf.util.HashData; 31 import gov.nasa.jpf.util.HashPool; 32 33 import java.io.PrintWriter ; 34 35 import java.util.BitSet ; 36 import java.util.Iterator ; 37 import java.util.LinkedList ; 38 39 40 46 public class ThreadInfo implements Storable { 47 48 49 static final int LIVELOCK_STEPS = 5000; 50 51 static final int NEW = 0; 52 static final int RUNNING = 1; 53 54 public static final int SYNC_RUNNING = 2; 57 public static final int WAITING = 3; 58 public static final int NOTIFIED = 4; 59 public static final int STOPPED = 5; 60 public static final int INTERRUPTED = 6; 61 public static final int TERMINATED = 7; 62 63 64 protected static HashPool threadDataPool = new HashPool(); 65 66 67 protected static HashPool stackFramePool = new HashPool(); 68 69 static ThreadInfo current; 70 71 72 boolean yield; 73 74 protected ExceptionInfo pendingException; 75 76 77 protected ThreadData threadData; 78 79 83 protected AtomicData atomicData; 84 85 90 protected StackFrame[] stack; 91 92 95 public ThreadList list; 96 97 100 public int index; 101 102 105 public int tdIndex = -1; 106 107 110 public BitSet hasChanged; 111 112 115 public boolean anyChanged; 116 117 120 protected int[] data; 121 122 125 protected int lowestChanged; 126 127 130 long returnValue; 131 132 138 MJIEnv env; 139 140 146 JVM vm; 147 148 153 LinkedList lockedObjects = new LinkedList (); 154 155 156 162 165 static boolean haltOnThrow; 166 167 168 static boolean porInEffect; 169 170 173 static boolean porFieldBoundaries; 174 175 179 static boolean porSyncDetection; 180 181 static boolean init (Config config) { 182 threadDataPool = new HashPool(); 183 stackFramePool = new HashPool(); 184 current = null; 185 186 haltOnThrow = config.getBoolean("vm.halt_on_throw"); 187 porInEffect = config.getBoolean("vm.por"); 188 porFieldBoundaries = config.getBoolean("vm.por.field_boundaries"); 189 porSyncDetection = config.getBoolean("vm.por.sync_detection"); 190 191 return true; 192 } 193 194 198 public ThreadInfo (JVM vm, int o) { 199 DynamicArea da = vm.getDynamicArea(); 200 ElementInfo ei = da.get(o); 201 202 this.vm = vm; 203 204 threadData = new ThreadData(); 205 threadData.status = NEW; 206 207 if (o != -1) { 208 threadData.ci = ei.getClassInfo(); 209 } 210 211 threadData.objref = o; 212 threadData.target = -1; 213 threadData.lockCount = 0; 214 215 218 atomicData = new AtomicData(); 219 atomicData.currentMethod = null; 220 atomicData.line = -1; 221 atomicData.inSameMethod = false; 222 223 stack = new StackFrame[0]; 224 225 hasChanged = new BitSet (); 226 anyChanged = false; 227 data = new int[0]; 228 lowestChanged = -1; 229 230 env = new MJIEnv(this); 231 } 232 233 public ThreadInfo (ThreadInfo ti) { 234 if (ti.tdIndex == -1) { 235 threadData = (ThreadData) ti.threadData.clone(); 236 } else { 237 threadData = ti.threadData; 238 } 239 240 atomicData = (AtomicData) ti.atomicData.clone(); 241 242 if (ti.stack != null) { 243 int l = ti.stack.length; 244 stack = new StackFrame[l]; 245 246 if (ti.anyChanged) { 247 for (int i = 0; i < l; i++) { 248 if (ti.hasChanged.get(i)) { 249 stack[i] = (StackFrame) ti.stack[i].clone(); 250 } else { 251 stack[i] = ti.stack[i]; 252 } 253 } 254 } else { 255 System.arraycopy(ti.stack, 0, stack, 0, l); 256 } 257 } else { 258 stack = null; 259 } 260 261 vm = ti.vm; 262 list = null; 263 index = -1; 264 tdIndex = ti.tdIndex; 265 hasChanged = (BitSet ) ti.hasChanged.clone(); 266 anyChanged = ti.anyChanged; 267 data = ti.data; 268 lowestChanged = ti.lowestChanged; 269 270 env = new MJIEnv(this); 271 } 272 273 276 ThreadInfo (ThreadList l, int i) { 277 list = l; 278 index = i; 279 280 stack = new StackFrame[0]; 281 tdIndex = -1; 282 data = new int[0]; 283 hasChanged = new BitSet (); 284 285 vm = JVM.getVM(); 287 env = new MJIEnv(this); 288 289 } 291 292 public static ThreadInfo getCurrent() { 293 return current; 294 } 295 296 public boolean holdsLock (ElementInfo ei) { 297 return lockedObjects.contains(ei); 298 } 299 300 public JVM getVM () { 301 return vm; 302 } 303 304 305 public void setReturnValue (long ret) { 306 returnValue = ret; 307 } 308 313 public long getReturnValue () { 314 return returnValue; 315 } 316 317 public boolean usePor () { 318 return porInEffect; 319 } 320 321 public boolean usePorFieldBoundaries () { 322 return porFieldBoundaries; 323 } 324 325 public boolean usePorSyncDetection () { 326 return porSyncDetection; 327 } 328 329 333 public boolean isAbstractionNonDeterministic () { 334 if (getPC() == null) { 335 return false; 336 } 337 338 return getPC().examineAbstraction(list.ks.ss, list.ks, this); 339 } 340 341 344 public boolean isAlive () { 345 return (threadData.status != TERMINATED); 346 355 } 356 357 360 public Object getBacktrackData () { 361 return atomicData.clone(); 362 } 363 364 public boolean getBooleanLocal (String lname) { 365 return Types.intToBoolean(getLocalVariable(lname)); 366 } 367 368 public boolean getBooleanLocal (int lindex) { 369 return Types.intToBoolean(getLocalVariable(lindex)); 370 } 371 372 public boolean getBooleanLocal (int fr, String lname) { 373 return Types.intToBoolean(getLocalVariable(fr, lname)); 374 } 375 376 public boolean getBooleanLocal (int fr, int lindex) { 377 return Types.intToBoolean(getLocalVariable(fr, lindex)); 378 } 379 380 public boolean getBooleanReturnValue () { 381 return Types.intToBoolean(peek()); 382 } 383 384 public byte getByteLocal (String lname) { 385 return (byte) getLocalVariable(lname); 386 } 387 388 public byte getByteLocal (int lindex) { 389 return (byte) getLocalVariable(lindex); 390 } 391 392 public byte getByteLocal (int fr, String lname) { 393 return (byte) getLocalVariable(fr, lname); 394 } 395 396 public byte getByteLocal (int fr, int lindex) { 397 return (byte) getLocalVariable(fr, lindex); 398 } 399 400 public byte getByteReturnValue () { 401 return (byte) peek(); 402 } 403 404 public String [] getCallStack () { 405 int size = stack.length; 406 String [] callStack = new String [size]; 407 408 for (int i = 0; i < size; i++) { 409 callStack[i] = frame(i).getStackTrace(); 410 } 411 412 return callStack; 413 } 414 415 public String getCallStackClass (int i) { 416 if (i < stack.length) { 417 StackFrame fr = frame(i); 418 419 return fr.getClassInfo().getName(); 420 } 421 422 return null; 423 } 424 425 public String getCallStackFile (int i) { 426 if (i < stack.length) { 427 StackFrame fr = frame(i); 428 429 return fr.getClassInfo().getSourceFileName(); 430 } 431 432 return null; 433 } 434 435 public int getCallStackLine (int i) { 436 if (i < stack.length) { 437 StackFrame fr = frame(i); 438 439 return fr.getLine(); 440 } 441 442 return 0; 443 } 444 445 public String getCallStackMethod (int i) { 446 if (i < stack.length) { 447 StackFrame fr = frame(i); 448 449 return fr.getMethodInfo().getName(); 450 } 451 452 return null; 453 } 454 455 458 public int getCalleeThis (MethodInfo mi) { 459 return top().getCalleeThis(mi); 460 } 461 462 465 public int getCalleeThis (int size) { 466 return top().getCalleeThis(size); 467 } 468 469 public boolean isCalleeThis (Reference r) { 470 if ((stack.length == 0) || (r == null)) { 471 return false; 472 } 473 474 Instruction pc = getPC(); 475 476 if (pc == null) { 477 return false; 478 } 479 480 if (!(pc instanceof InvokeInstruction)) { 481 return false; 482 } 483 484 if (pc instanceof INVOKESTATIC) { 485 return false; 486 } 487 488 InvokeInstruction i = (InvokeInstruction) pc; 489 490 return getCalleeThis(Types.getArgumentsSize(i.signature) + 1) == ((ElementInfo) r).getIndex(); 491 } 492 493 public char getCharLocal (String lname) { 494 return (char) getLocalVariable(lname); 495 } 496 497 public char getCharLocal (int lindex) { 498 return (char) getLocalVariable(lindex); 499 } 500 501 public char getCharLocal (int fr, String lname) { 502 return (char) getLocalVariable(fr, lname); 503 } 504 505 public char getCharLocal (int fr, int lindex) { 506 return (char) getLocalVariable(fr, lindex); 507 } 508 509 public char getCharReturnValue () { 510 return (char) peek(); 511 } 512 513 516 public ClassInfo getClassInfo () { 517 return threadData.ci; 518 } 519 520 public double getDoubleLocal (String lname) { 521 return Types.longToDouble(getLongLocalVariable(lname)); 522 } 523 524 public double getDoubleLocal (int lindex) { 525 return Types.longToDouble(getLongLocalVariable(lindex)); 526 } 527 528 public double getDoubleLocal (int fr, String lname) { 529 return Types.longToDouble(getLongLocalVariable(fr, lname)); 530 } 531 532 public double getDoubleLocal (int fr, int lindex) { 533 return Types.longToDouble(getLongLocalVariable(fr, lindex)); 534 } 535 536 public double getDoubleReturnValue () { 537 return Types.longToDouble(longPeek()); 538 } 539 540 543 public boolean isEnabled () { 544 boolean isEnabled = (threadData.status == RUNNING) || 545 (threadData.status == SYNC_RUNNING) || 546 (threadData.status == INTERRUPTED) || 547 (threadData.status == NOTIFIED); 548 return isEnabled; 549 } 550 551 public float getFloatLocal (String lname) { 552 return Types.intToFloat(getLocalVariable(lname)); 553 } 554 555 public float getFloatLocal (int lindex) { 556 return Types.intToFloat(getLocalVariable(lindex)); 557 } 558 559 public float getFloatLocal (int fr, String lname) { 560 return Types.intToFloat(getLocalVariable(fr, lname)); 561 } 562 563 public float getFloatLocal (int fr, int lindex) { 564 return Types.intToFloat(getLocalVariable(fr, lindex)); 565 } 566 567 public float getFloatReturnValue () { 568 return Types.intToFloat(peek()); 569 } 570 571 public int getIntLocal (String lname) { 572 return getLocalVariable(lname); 573 } 574 575 public int getIntLocal (int lindex) { 576 return getLocalVariable(lindex); 577 } 578 579 public int getIntLocal (int fr, String lname) { 580 return getLocalVariable(fr, lname); 581 } 582 583 public int getIntLocal (int fr, int lindex) { 584 return getLocalVariable(fr, lindex); 585 } 586 587 public int getIntReturnValue () { 588 return peek(); 589 } 590 591 public boolean isInterrupted (boolean resetStatus) { 592 boolean ret = (getStatus() == INTERRUPTED); 593 594 if (resetStatus) { 595 setStatus(RUNNING); 597 } 598 599 return ret; 600 } 601 602 605 public int getIndex () { 606 return index; 607 } 608 609 612 public int getLine () { 613 if (stack.length == 0) return -1; 614 615 return top().getLine(); 616 } 617 618 621 public int getLine (int idx) { 622 return frame(idx).getLine(); 623 } 624 625 public String [] getLocalNames () { 626 return top().getLocalVariableNames(); 627 } 628 629 public String [] getLocalNames (int fr) { 630 return frame(fr).getLocalVariableNames(); 631 } 632 633 636 public void setLocalVariable (int idx, int v, boolean ref) { 637 topClone().setLocalVariable(idx, v, ref); 638 } 639 640 643 public int getLocalVariable (int fr, int idx) { 644 return frame(fr).getLocalVariable(idx); 645 } 646 647 650 public int getLocalVariable (int idx) { 651 return top().getLocalVariable(idx); 652 } 653 654 657 public int getLocalVariable (int fr, String name) { 658 return frame(fr).getLocalVariable(name); 659 } 660 661 664 public int getLocalVariable (String name) { 665 return top().getLocalVariable(name); 666 } 667 668 671 public boolean isLocalVariableRef (int idx) { 672 return top().isLocalVariableRef(idx); 673 } 674 675 678 public String getLocalVariableType (int fr, String name) { 679 return frame(fr).getLocalVariableType(name); 680 } 681 682 685 public String getLocalVariableType (String name) { 686 return top().getLocalVariableType(name); 687 } 688 689 692 public void setLockCount (int l) { 693 if (threadData.lockCount != l) { 694 threadDataClone().lockCount = l; 695 } 696 } 697 698 701 public int getLockCount () { 702 return threadData.lockCount; 703 } 704 705 public LinkedList getLockedObjects () { 706 return lockedObjects; 707 } 708 709 public int[] getLockedObjectReferences () { 710 int[] a = new int[lockedObjects.size()]; 711 int i=0; 712 for (Iterator it=lockedObjects.iterator(); it.hasNext();) { 713 a[i++] = ((ElementInfo)it.next()).getIndex(); 714 } 715 716 return a; 717 } 718 719 public long getLongLocal (String lname) { 720 return getLongLocalVariable(lname); 721 } 722 723 public long getLongLocal (int lindex) { 724 return getLongLocalVariable(lindex); 725 } 726 727 public long getLongLocal (int fr, String lname) { 728 return getLongLocalVariable(fr, lname); 729 } 730 731 public long getLongLocal (int fr, int lindex) { 732 return getLongLocalVariable(fr, lindex); 733 } 734 735 738 public void setLongLocalVariable (int idx, long v) { 739 topClone().setLongLocalVariable(idx, v); 740 } 741 742 745 public long getLongLocalVariable (int fr, int idx) { 746 return frame(fr).getLongLocalVariable(idx); 747 } 748 749 752 public long getLongLocalVariable (int idx) { 753 return top().getLongLocalVariable(idx); 754 } 755 756 759 public long getLongLocalVariable (int fr, String name) { 760 return frame(fr).getLongLocalVariable(name); 761 } 762 763 766 public long getLongLocalVariable (String name) { 767 return top().getLongLocalVariable(name); 768 } 769 770 public long getLongReturnValue () { 771 return longPeek(); 772 } 773 774 777 public MethodInfo getMethod () { 778 if (stack.length > 0) { 779 return top().getMethodInfo(); 780 } else { 781 return null; 782 } 783 } 784 785 public boolean isInCtor () { 786 MethodInfo mi = getMethod(); 789 return mi.isCtor(); 790 } 791 792 795 public MethodInfo getMethod (int idx) { 796 if (stack.length > 0) { 797 return frame(idx).getMethodInfo(); 798 } else { 799 return null; 800 } 801 } 802 803 public String getName () { 804 return threadData.name; 805 } 806 807 814 public boolean isNonDeterministic () { 815 if (getPC() == null) { 816 return false; 817 } 818 819 return !getPC().isDeterministic(list.ks.ss, list.ks, this); 820 } 821 822 public Reference getObjectLocal (String lname) { 823 return list.ks.da.get(getLocalVariable(lname)); 824 } 825 826 public Reference getObjectLocal (int lindex) { 827 return list.ks.da.get(getLocalVariable(lindex)); 828 } 829 830 public Reference getObjectLocal (int fr, String lname) { 831 return list.ks.da.get(getLocalVariable(fr, lname)); 832 } 833 834 public Reference getObjectLocal (int fr, int lindex) { 835 return list.ks.da.get(getLocalVariable(fr, lindex)); 836 } 837 838 841 public int getObjectReference () { 842 return threadData.objref; 843 } 844 845 public Reference getObjectReturnValue () { 846 return list.ks.da.get(peek()); 847 } 848 849 public Object getOperandAttr () { 850 return top().getOperandAttr(); 851 } 852 853 public Object getOperandAttr (int opStackOffset) { 854 return top().getOperandAttr(opStackOffset); 855 } 856 857 public void setOperandAttr (Object attr) { 858 top().setOperandAttr(attr); 859 } 860 861 864 public boolean isOperandRef () { 865 return top().isOperandRef(); 866 } 867 868 871 public boolean isOperandRef (int idx) { 872 return top().isOperandRef(idx); 873 } 874 875 878 public void setPC (Instruction pc) { 879 topClone().setPC(pc); 880 } 881 882 885 public Instruction getPC (int i) { 886 return frame(i).getPC(); 887 } 888 889 892 public Instruction getPC () { 893 if (stack.length == 0) { 894 return null; 895 } 896 897 return top().getPC(); 898 } 899 900 public ExceptionInfo getPendingException () { 901 return pendingException; 902 } 903 904 912 public boolean isRunnable () { 913 if (!isEnabled()) { 914 return false; 916 } 917 918 if (threadData.status == SYNC_RUNNING) { 920 int sync = (threadData.target != -1) 921 ? threadData.target : threadData.objref; 922 ElementInfo ei = list.ks.da.get(sync); 923 924 if ((ei != null) && !ei.canLock(this)) { 925 return false; 926 } 927 } 928 929 Instruction pc = getPC(); 930 931 if (pc == null) { 932 return false; 933 } 934 935 return pc.isExecutable(list.ks.ss, list.ks, this); 939 } 940 941 public short getShortLocal (String lname) { 942 return (short) getLocalVariable(lname); 943 } 944 945 public short getShortLocal (int lindex) { 946 return (short) getLocalVariable(lindex); 947 } 948 949 public short getShortLocal (int fr, String lname) { 950 return (short) getLocalVariable(fr, lname); 951 } 952 953 public short getShortLocal (int fr, int lindex) { 954 return (short) getLocalVariable(fr, lindex); 955 } 956 957 public short getShortReturnValue () { 958 return (short) peek(); 959 } 960 961 968 public String getStackTrace () { 969 StringBuffer sb = new StringBuffer (256); 970 971 for (int i = stack.length - 1; i >= 0; i--) { 972 StackFrame sf = frame(i); 973 MethodInfo mi = sf.getMethodInfo(); 974 975 if (mi.isCtor()){ 976 ClassInfo ci = mi.getClassInfo(); 977 if (ci.instanceOf("java.lang.Throwable")) { 978 continue; 979 } 980 } 981 982 sb.append(frame(i).getStackTrace()); 983 sb.append("\n"); 984 } 985 986 return sb.toString(); 987 } 988 989 992 public void setStatus (int s) { 993 if (threadData.status != s) { 994 995 if ((s == RUNNING) || (s == SYNC_RUNNING)) { 996 JVM.getVM().notifyThreadStarted(this); 997 } else if (s == TERMINATED) { 998 JVM.getVM().notifyThreadTerminated(this); 999 } 1000 1001 threadDataClone().status = s; 1002 } 1003 } 1004 1005 1008 public int getStatus () { 1009 return threadData.status; 1010 } 1011 1012 1019 public int[] getStoringData () { 1020 int length = stack.length; 1021 1022 int[] data = new int[length + 2]; 1023 data[0] = getThreadDataIndex(); 1024 data[1] = length; 1025 1026 if (anyChanged) { 1027 if (lowestChanged > 0) { 1028 System.arraycopy(this.data, 2, data, 2, lowestChanged); 1029 } 1030 1031 for (int i = lowestChanged, j = i + 2; i < length; i++, j++) { 1032 data[j] = getStackFrameIndex(i); 1033 } 1034 } else if (length > 0) { 1035 System.arraycopy(this.data, 2, data, 2, length); 1036 } 1037 1038 anyChanged = false; 1039 hasChanged = new BitSet (); 1040 lowestChanged = -1; 1041 1042 this.data = data; 1043 1044 return data; 1045 } 1046 1047 public String getStringLocal (String lname) { 1048 return list.ks.da.get(getLocalVariable(lname)).asString(); 1049 } 1050 1051 public String getStringLocal (int lindex) { 1052 return list.ks.da.get(getLocalVariable(lindex)).asString(); 1053 } 1054 1055 public String getStringLocal (int fr, String lname) { 1056 return list.ks.da.get(getLocalVariable(fr, lname)).asString(); 1057 } 1058 1059 public String getStringLocal (int fr, int lindex) { 1060 return list.ks.da.get(getLocalVariable(fr, lindex)).asString(); 1061 } 1062 1063 public String getStringReturnValue () { 1064 return list.ks.da.get(peek()).asString(); 1065 } 1066 1067 1070 public void setTarget (int t) { 1071 if (threadData.target != t) { 1072 threadDataClone().target = t; 1073 } 1074 } 1075 1076 1079 public int getTarget () { 1080 return threadData.target; 1081 } 1082 1083 1086 public int getThis () { 1087 return top().getThis(); 1088 } 1089 1090 public boolean isThis (Reference r) { 1091 if (r == null) { 1092 return false; 1093 } 1094 1095 if (stack.length == 0) { 1096 return false; 1097 } 1098 1099 return getMethod().isStatic() 1100 ? false : ((ElementInfo) r).getIndex() == getLocalVariable(0); 1101 } 1102 1103 public boolean atInvoke (String mname) { 1104 if (stack.length == 0) { 1105 return false; 1106 } 1107 1108 Instruction pc = getPC(); 1109 1110 if (!(pc instanceof InvokeInstruction)) { 1111 return false; 1112 } 1113 1114 InvokeInstruction i = (InvokeInstruction) pc; 1115 1116 return mname.equals(i.cname + "." + i.mname); 1117 } 1118 1119 public boolean atLabel (String label) { 1120 return Labels.isAt(label, this); 1121 } 1122 1123 public boolean atMethod (String mname) { 1124 if (stack.length == 0) { 1125 return false; 1126 } 1127 1128 return getMethod().getCompleteName().equals(mname); 1129 } 1130 1131 public boolean atPosition (int position) { 1132 if (stack.length == 0) { 1133 return false; 1134 } 1135 1136 Instruction pc = getPC(); 1137 1138 if (pc == null) { 1139 return false; 1140 } 1141 1142 return pc.getPosition() == position; 1143 } 1144 1145 public boolean atReturn () { 1146 if (stack.length == 0) { 1147 return false; 1148 } 1149 1150 Instruction pc = getPC(); 1151 1152 if (pc == null) { 1153 return false; 1154 } 1155 1156 return pc instanceof ReturnInstruction; 1157 } 1158 1159 1160 1164 void resetVolatiles () { 1165 lockedObjects = new LinkedList (); 1167 } 1168 1169 void addLockedObject (ElementInfo ei) { 1170 lockedObjects.add(ei); 1171 } 1172 1173 void removeLockedObject (ElementInfo ei) { 1174 lockedObjects.remove(ei); 1175 } 1176 1177 1180 public void backtrackTo (ArrayOffset storing, Object backtrack) { 1181 1182 resetVolatiles(); 1183 1184 setThreadDataIndex(storing.get()); 1185 1186 int length = storing.get(); 1187 int l = stack.length; 1188 1189 int[] data = new int[length + 2]; 1190 data[0] = tdIndex; 1191 data[1] = length; 1192 System.arraycopy(storing.data, storing.offset, data, 2, length); 1193 1194 if (length != l) { 1195 if (l > length) { 1196 l = length; 1197 } 1198 1199 StackFrame[] n = new StackFrame[length]; 1200 1201 if (l > 0) { 1202 System.arraycopy(stack, 0, n, 0, l); 1203 } 1204 1205 stack = n; 1206 } 1207 1208 for (int i = 0; i < length; i++) { 1209 setStackFrameIndex(i, storing.get()); 1210 } 1211 1212 atomicData = (AtomicData) backtrack; 1213 1214 anyChanged = false; 1215 hasChanged = new BitSet (); 1216 lowestChanged = -1; 1217 1218 this.data = data; 1219 } 1220 1221 1224 public void callerPop (int n) { 1225 frameClone(-1).pop(n); 1226 } 1227 1228 1231 public void clearOperandStack () { 1232 topClone().clearOperandStack(); 1233 } 1234 1235 public Object clone () { 1236 return new ThreadInfo(this); 1237 } 1238 1239 public StackFrame[] cloneStack() { 1240 StackFrame[] sf = null; 1241 1242 1245 MethodInfo nativeMth = env.getMethodInfo(); 1250 if (nativeMth != null){ 1251 sf = new StackFrame[stack.length +1]; 1252 System.arraycopy(stack, 0, sf, 0, stack.length); 1253 sf[stack.length] = new StackFrame(nativeMth, false, null); 1254 } else { 1256 sf = (StackFrame[]) stack.clone(); 1257 } 1258 1259 return sf; 1260 } 1261 1262 1265 public int countStackFrames () { 1266 return stack.length; 1267 } 1268 1269 int createStackTraceElement ( String clsName, String mthName, String fileName, int line) { 1270 DynamicArea da = DynamicArea.getHeap(); 1271 1272 ClassInfo ci = ClassInfo.getClassInfo("java.lang.StackTraceElement"); 1273 int sRef = da.newObject(ci, this); 1274 1275 ElementInfo sei = da.get(sRef); 1276 sei.setReferenceField("clsName", da.newString(clsName, this)); 1277 sei.setReferenceField("mthName", da.newString(mthName, this)); 1278 sei.setReferenceField("fileName", da.newString(fileName, this)); 1279 sei.setIntField("line", line); 1280 1281 return sRef; 1282 } 1283 1284 public int getStackTrace (int objref) { 1285 DynamicArea da = DynamicArea.getHeap(); 1286 int stackDepth = countStackFrames(); 1287 int i, j=0; 1288 int aRef; 1289 ElementInfo aei; 1290 1291 MethodInfo nativeMth = env.getMethodInfo(); 1293 if (nativeMth != null){ 1294 aRef = da.newArray("Ljava/lang/StackTraceElement", stackDepth+1, this); 1295 aei = da.get(aRef); 1296 1297 aei.setElement( j++, 1298 createStackTraceElement( nativeMth.getClassInfo().getName(), 1299 nativeMth.getName(), 1300 nativeMth.getClassInfo().getSourceFileName(), -1)); 1301 } else { 1302 aRef = da.newArray("Ljava/lang/StackTraceElement", stackDepth, this); 1303 aei = da.get(aRef); 1304 } 1305 1306 for (i = stackDepth - 1; i >= 0; i--, j++) { 1307 aei.setElement( j, 1308 createStackTraceElement( getCallStackClass(i), getCallStackMethod(i), 1309 getCallStackFile(i), getCallStackLine(i))); 1310 } 1311 1312 return aRef; 1313 } 1314 1315 void print (PrintWriter pw, String s) { 1316 if (pw != null){ 1317 pw.print(s); 1318 } else { 1319 vm.print(s); 1320 } 1321 } 1322 1323 public void printStackTrace (int objRef) { 1324 printStackTrace(null, objRef); 1325 } 1326 1327 public void printPendingExceptionOn (PrintWriter pw) { 1328 if (pendingException != null) { 1329 printStackTrace( pw, pendingException.getExceptionReference()); 1330 } 1331 } 1332 1333 public void printStackTrace (PrintWriter pw, int objRef) { 1334 print(pw, env.getClassInfo(objRef).getName()); 1338 1339 int msgRef = env.getReferenceField(objRef,"detailMessage"); 1340 if (msgRef != MJIEnv.NULL) { 1341 print(pw, ": "); 1342 print(pw, env.getStringObject(msgRef)); 1343 } 1344 print(pw, "\n"); 1345 1346 int aRef = env.getReferenceField(objRef, "stackTrace"); if (aRef != MJIEnv.NULL) { 1348 int len = env.getArrayLength(aRef); 1349 for (int i=0; i<len; i++) { 1350 int sRef = env.getReferenceArrayElement(aRef, i); 1351 String clsName = env.getStringObject(env.getReferenceField(sRef, "clsName")); 1352 String mthName = env.getStringObject(env.getReferenceField(sRef, "mthName")); 1353 String fileName = env.getStringObject(env.getReferenceField(sRef, "fileName")); 1354 int line = env.getIntField(sRef, "line"); 1355 1356 print(pw, "\tat "); 1357 print(pw, clsName); 1358 print(pw, "."); 1359 print(pw, mthName); 1360 print(pw, "("); 1361 print(pw, fileName); 1362 print(pw, ":"); 1363 1364 if (line < 0){ 1365 print(pw, "native"); 1366 } else { 1367 print(pw, Integer.toString(line)); 1368 } 1369 1370 print(pw, ")"); 1371 print(pw, "\n"); 1372 } 1373 } 1374 } 1375 1376 void callThrowableCtor (ClassInfo ci, int objRef, int msgRef) { 1378 MethodInfo mi = ci.getMethod("<init>(Ljava/lang/String;)", true); 1379 if (mi != null) { 1380 push(objRef, true); 1381 push(msgRef, true); 1382 executeMethod(mi); 1383 } 1384 } 1385 1386 1389 public Instruction createAndThrowException (ClassInfo ci, String details) { 1390 DynamicArea da = DynamicArea.getHeap(); 1391 int objref = da.newObject(ci, this); 1392 int msgref = -1; 1393 1394 ElementInfo ei = da.get(objref); 1395 1396 if (details != null) { 1399 msgref = da.newString(details, this); 1400 ei.setReferenceField("detailMessage", "java.lang.Throwable", msgref); 1401 } 1402 1403 return throwException(objref); 1404 } 1405 1406 1409 public Instruction createAndThrowException (String cname) { 1410 return createAndThrowException(ClassInfo.getClassInfo(cname), null); 1411 } 1412 1413 public Instruction createAndThrowException (String cname, String details) { 1414 return createAndThrowException(ClassInfo.getClassInfo(cname), details); 1415 } 1416 1417 1420 public void dup () { 1421 topClone().dup(); 1422 } 1423 1424 1427 public void dup2 () { 1428 topClone().dup2(); 1429 } 1430 1431 1434 public void dup2_x1 () { 1435 topClone().dup2_x1(); 1436 } 1437 1438 1441 public void dup2_x2 () { 1442 topClone().dup2_x2(); 1443 } 1444 1445 1448 public void dup_x1 () { 1449 topClone().dup_x1(); 1450 } 1451 1452 1455 public void dup_x2 () { 1456 topClone().dup_x2(); 1457 } 1458 1459 1462 public Instruction executeInstruction () { 1463 if (threadData.status == SYNC_RUNNING) { 1467 int sync = (threadData.target != -1) 1468 ? threadData.target : threadData.objref; 1469 ElementInfo ei = list.ks.da.get(sync); 1470 ei.lock(this); 1472 setStatus(RUNNING); 1473 } 1474 1475 Instruction pc = getPC(); 1476 1477 CoverageManager.incInstruction(pc, index); 1479 TrailInfo trail = list.ks.ss.trail(); 1480 Step step = new Step(getMethod().getClassInfo().getSourceFileName(), 1481 getLine(), pc); 1482 trail.addStep(step); 1483 1484 if (pc.isFirstInstruction() && getMethod().isAtomic()) { 1485 list.ks.setAtomic(); 1486 } 1487 1488 Instruction nextPc = pc.execute(list.ks.ss, list.ks, this); 1491 1492 if (stack.length != 0) { 1494 setPC(nextPc); 1495 } 1496 1497 vm.notifyInstructionExecuted(this, pc, nextPc); 1501 1502 return nextPc; 1503 } 1504 1505 1506 1513 public void executeMethod (MethodInfo mi) { 1514 int depth = countStackFrames(); 1515 1516 mi.execute(this, true); 1517 1518 KernelState ks = list.ks; 1519 SystemState ss = ks.ss; 1520 1521 while (depth < countStackFrames()) { 1522 Instruction pc = executeInstruction(); 1523 1524 if (ss.violatedAssertion) { 1525 break; 1526 } 1527 1528 if (pc == null) { break; 1530 } 1531 1532 if (!pc.isExecutable(ss, ks, this)) { 1533 throw new BlockedAtomicException(); 1534 } 1535 } 1536 } 1537 1538 1542 public boolean executeStep () throws JPFException { 1543 current = this; 1544 1545 if (porInEffect) { 1546 return executePorStep(); 1547 } else { 1548 return executeAtomicLinesStep(); 1549 } 1550 } 1551 1552 public void finish () { 1554 setStatus(TERMINATED); 1555 1556 int objref = getObjectReference(); 1558 ElementInfo ei = list.ks.da.get(objref); 1559 1560 ei.lock(this); 1561 ei.notifiesAll(); 1562 ei.unlock(this); 1563 1564 list.ks.ss.activateGC(); 1566 1567 } 1569 1570 public void hash (HashData hd) { 1571 threadData.hash(hd); 1572 atomicData.hash(hd); 1573 1574 for (int i = 0, l = stack.length; i < l; i++) { 1575 frame(i).hash(hd); 1576 } 1577 } 1578 1579 public int hashCode () { 1580 HashData hd = new HashData(); 1581 1582 hash(hd); 1583 1584 return hd.getValue(); 1585 } 1586 1587 public void interrupt () { 1588 if (getStatus() != WAITING) { 1589 return; 1590 } 1591 1592 setStatus(INTERRUPTED); 1593 } 1594 1595 1599 public void lock (Ref ref) { 1600 } 1601 1602 public void log () { 1603 Debug.println(Debug.MESSAGE, 1604 "TH#" + index + " #" + threadData.target + " #" + 1605 threadData.objref + " " + threadData.status); 1606 1607 for (int i = 0; i < stack.length; i++) { 1608 frame(i).log(i); 1609 } 1610 } 1611 1612 1615 public long longPeek () { 1616 return top().longPeek(); 1617 } 1618 1619 1622 public long longPeek (int n) { 1623 return top().longPeek(n); 1624 } 1625 1626 1629 public long longPop () { 1630 return topClone().longPop(); 1631 } 1632 1633 1636 public void longPush (long v) { 1637 topClone().longPush(v); 1638 } 1639 1640 1641 1646 void markRoots () { 1647 DynamicArea heap = DynamicArea.getHeap(); 1648 1649 heap.markThreadRoot(threadData.objref, index); 1651 1652 if (threadData.target != -1) { 1654 heap.markThreadRoot(threadData.target,index); 1655 } 1656 1657 for (int i = 0, l = stack.length; i < l; i++) { 1659 frame(i).markThreadRoots(index); 1660 } 1661 } 1662 1663 1668 public void pushFrame (StackFrame frame) { 1669 atomicData.inSameMethod = false; 1670 1671 int depth = stack.length; 1672 StackFrame[] n = new StackFrame[depth + 1]; 1673 System.arraycopy(stack, 0, n, 0, depth); 1674 stack = n; 1675 1676 stack[depth] = frame; 1677 1678 hasChanged.set(depth); 1679 anyChanged = true; 1680 list.ks.data = null; 1681 1682 if ((lowestChanged == -1) || (lowestChanged > depth)) { 1683 lowestChanged = depth; 1684 } 1685 } 1686 1687 public ElementInfo objectAtBlockedSynchronized () { 1688 if (stack.length == 0) { 1689 return null; 1690 } 1691 1692 Instruction pc = getPC(); 1693 1694 if (pc == null) { 1695 return null; 1696 } 1697 1698 if (pc instanceof InvokeInstruction) { 1699 if (!getMethod().canEnter(this)) { 1700 return getMethod().getBlockedObject(this, true); 1701 } 1702 } 1703 1704 if (pc instanceof MONITORENTER) { 1705 if (!pc.isExecutable(list.ks.ss, list.ks, this)) { 1706 return list.ks.da.get(peek()); 1707 } 1708 } 1709 1710 return null; 1711 } 1712 1713 1716 public int peek () { 1717 if (stack.length > 0) { 1718 return top().peek(); 1719 } else { 1720 return -1; 1722 } 1723 } 1724 1725 1728 public int peek (int n) { 1729 if (stack.length > 0) { 1730 return top().peek(n); 1731 } else { 1732 return -1; 1734 } 1735 } 1736 1737 1740 public int pop () { 1741 if (stack.length > 0) { 1742 return topClone().pop(); 1743 } else { 1744 return -1; 1746 } 1747 } 1748 1749 1752 public void pop (int n) { 1753 if (stack.length > 0) { 1754 topClone().pop(n); 1755 } 1756 } 1757 1758 1761 public boolean popFrame () { 1762 int last = stack.length - 1; 1763 StackFrame sf = stack[last]; 1764 1765 if (getMethod().isAtomic()) { 1766 list.ks.clearAtomic(); 1767 } 1768 1769 if (sf.hasAnyRef()) { 1770 ((SystemState) JVM.getVM().getSystemState()).activateGC(); 1771 } 1772 1773 StackFrame[] n = new StackFrame[last]; 1774 System.arraycopy(stack, 0, n, 0, last); 1775 stack = n; 1776 1777 if (last == 0) { 1778 atomicData.inSameMethod = false; 1779 finish(); 1780 } else { 1781 atomicData.inSameMethod = (getMethod() == atomicData.currentMethod); 1782 } 1783 1784 hasChanged.set(last); 1785 anyChanged = true; 1786 list.ks.data = null; 1787 1788 if ((lowestChanged == -1) || (lowestChanged > last)) { 1789 lowestChanged = last; 1790 } 1791 1792 return (last > 0); 1793 } 1794 1795 public void printInternalErrorTrace (Throwable e) { 1796 String msg = e.getMessage(); 1797 1798 if (msg != null) { 1799 Debug.println(Debug.ERROR, 1800 "exception " + e.getClass().getName() + ": " + msg); 1801 } else { 1802 Debug.println(Debug.ERROR, "exception " + e.getClass().getName()); 1803 } 1804 1805 printStackTrace(); 1806 1807 if (msg != null) { 1808 Debug.println(Debug.ERROR, 1809 "exception " + e.getClass().getName() + ": " + msg); 1810 } else { 1811 Debug.println(Debug.ERROR, "exception " + e.getClass().getName()); 1812 } 1813 1814 printStackContent(); 1815 } 1816 1817 1820 public void printStackContent () { 1821 for (int i = stack.length - 1; i >= 0; i--) { 1822 frame(i).printStackContent(); 1823 } 1824 } 1825 1826 1829 public void printStackTrace () { 1830 for (int i = stack.length - 1; i >= 0; i--) { 1831 frame(i).printStackTrace(); 1832 } 1833 } 1834 1835 1838 public void push (int v, boolean ref) { 1839 if (stack.length > 0) { topClone().push(v, ref); 1841 } 1842 } 1843 1844 1847 public void removeArguments (MethodInfo mi) { 1848 int i = mi.getArgumentsSize(); 1849 1850 if (i != 0) { 1851 pop(i); 1852 } 1853 } 1854 1855 1858 public void swap () { 1859 topClone().swap(); 1860 } 1861 1862 1865 public Instruction throwException (int objref) { 1866 DynamicArea da = DynamicArea.getHeap(); 1867 ElementInfo ei = da.get(objref); 1868 ClassInfo ci = ei.getClassInfo(); 1869 MethodInfo mi; 1870 Instruction insn; 1871 int nFrames = countStackFrames(); 1872 int i, j; 1873 1874 1876 int stRef = getStackTrace(objref); 1881 ei.setReferenceField("stackTrace", "java.lang.Throwable", stRef); 1882 1883 pendingException = new ExceptionInfo(this, ei); 1887 1888 vm.notifyExceptionThrown(this, ei); 1889 1890 if (!haltOnThrow) { 1891 for (j=0; j<nFrames; j++) { 1892 mi = getMethod(); 1893 insn = getPC(); 1894 1895 ExceptionHandler[] exceptions = mi.getExceptions(); 1896 if ( (j==0) || (insn instanceof InvokeInstruction)) { 1901 int p = insn.getPosition(); 1902 1903 if (exceptions != null) { 1904 for (i = 0; i < exceptions.length; i++) { 1906 ExceptionHandler eh = exceptions[i]; 1907 1908 if ((p >= eh.getBegin()) && (p <= eh.getEnd())) { 1910 String en = eh.getName(); 1911 1913 if ((en == null) || ci.instanceOf(en)) { 1915 clearOperandStack(); 1918 1919 push(objref, true); 1921 1922 Instruction startOfHandlerBlock = mi.getInstructionAt(eh.getHandler()); 1924 setPC(startOfHandlerBlock); 1926 pendingException = null; 1928 return startOfHandlerBlock; 1929 } 1930 } 1931 } 1932 } 1933 1934 if ("<clinit>".equals(mi.getName())) { 1935 break; 1940 } 1941 1942 } else { } 1944 1945 mi.leave(this); 1946 1947 popFrame(); 1949 } 1950 1951 } 1956 1957 1959 NoUncaughtExceptionsProperty.setExceptionInfo(pendingException); 1965 throw new UncaughtException(this, objref); 1966 } 1967 1968 1972 public void unlock (Ref ref) { 1973 } 1974 1975 protected void setStackFrameIndex (int i, int idx) { 1976 if (hasChanged.get(i) || ((i + 2) >= data.length) || 1977 (data[i + 2] != idx)) { 1978 stack[i] = (StackFrame) stackFramePool.getObject(idx); 1979 } 1980 } 1981 1982 protected int getStackFrameIndex (int i) { 1983 if (hasChanged.get(i)) { 1984 HashPool.PoolEntry e = stackFramePool.getEntry(stack[i]); 1985 1986 stack[i] = (StackFrame) e.getObject(); 1987 1988 return e.getIndex(); 1989 } else { 1990 return data[i + 2]; 1991 } 1992 } 1993 1994 protected void setThreadDataIndex (int idx) { 1995 if (tdIndex == idx) { 1996 return; 1997 } 1998 1999 tdIndex = idx; 2000 threadData = (ThreadData) threadDataPool.getObject(idx); 2001 } 2002 2003 protected int getThreadDataIndex () { 2004 if (tdIndex != -1) { 2005 return tdIndex; 2006 } 2007 2008 HashPool.PoolEntry e = threadDataPool.getEntry(threadData); 2009 threadData = (ThreadData) e.getObject(); 2010 2011 return tdIndex = e.getIndex(); 2012 } 2013 2014 2018 protected boolean executeAtomicLinesStep () throws JPFException { 2019 atomicData.line = getLine(); 2020 atomicData.currentMethod = getMethod(); 2021 atomicData.inSameMethod = true; 2022 2023 int[] lines = atomicData.currentMethod.getLineNumbers(); 2024 2025 while (true) { 2026 Instruction pc = executeInstruction(); 2027 2028 if (list.ks.ss.violatedAssertion) { 2029 break; 2030 } 2031 2032 if (pc == null) { 2033 break; 2034 } 2035 2036 if (pc.isObservable()) { 2037 list.ks.ss.trail().setAnnotation("observable instruction"); 2038 return false; 2039 } 2040 2041 if (list.ks.ss.isIgnored()) { 2042 throw new IgnoreIfException(); 2043 } 2044 2045 if (!pc.isDeterministic(list.ks.ss, list.ks, this)) { 2046 return false; 2047 } 2048 2049 if (list.ks.atomicLevel > 0) { 2050 if (!isRunnable()) { 2051 throw new BlockedAtomicException(); 2052 } 2053 2054 continue; } 2056 2057 if (!isRunnable()) { 2058 break; 2059 } 2060 2061 if (!atomicData.inSameMethod || (lines == null) || 2065 (atomicData.line != lines[pc.getOffset()] && 2066 !(pc instanceof ReturnInstruction))) { 2067 atomicData.currentMethod = null; 2068 atomicData.line = -1; 2069 2070 break; 2071 } 2072 } 2073 2074 return true; 2075 } 2076 2077 2080 protected boolean executePorStep () throws JPFException { 2081 2082 while (true) { 2083 Instruction pc = executeInstruction(); 2084 2085 if (list.ks.ss.violatedAssertion) { 2086 break; 2087 } 2088 2089 if (pc == null) { 2090 break; 2091 } 2092 2093 if (pc.isObservable()) { 2094 list.ks.ss.trail().setAnnotation("observable instruction"); 2095 return false; 2096 } 2097 2098 if (list.ks.ss.isIgnored()) { 2099 throw new IgnoreIfException(); 2100 } 2101 2102 if (!pc.isDeterministic(list.ks.ss, list.ks, this)) { 2103 return false; 2104 } 2105 2106 if (list.ks.atomicLevel > 0) { 2107 if (!isRunnable()) { 2110 throw new BlockedAtomicException(); 2111 } 2112 continue; } 2114 2115 if (!isRunnable()) { 2117 return true; 2118 } 2119 2120 if ( yield || pc.isSchedulingRelevant(list.ks.ss, list.ks, this)) { 2127 yield = false; 2128 break; 2129 } 2130 } 2131 2132 return true; 2133 } 2134 2135 2139 public void yield () { 2140 yield = true; 2141 } 2142 2143 public boolean hasOtherRunnables () { 2144 return list.hasOtherRunnablesThan(index); 2145 } 2146 2147 2150 protected StackFrame frame (int idx) { 2151 if (idx < 0) { 2152 idx += (stack.length - 1); 2153 } 2154 2155 return stack[idx]; 2156 } 2157 2158 2161 protected StackFrame frameClone (int i) { 2162 if (i < 0) { 2163 i += (stack.length - 1); 2164 } 2165 2166 if (hasChanged.get(i)) { 2167 return stack[i]; 2168 } 2169 2170 hasChanged.set(i); 2171 anyChanged = true; 2172 list.ks.data = null; 2173 2174 if ((lowestChanged == -1) || (lowestChanged > i)) { 2175 lowestChanged = i; 2176 } 2177 2178 return stack[i] = (StackFrame) stack[i].clone(); 2179 } 2180 2181 2184 protected ThreadData threadDataClone () { 2185 if (tdIndex == -1) { 2186 return threadData; 2187 } 2188 2189 tdIndex = -1; 2190 list.ks.data = null; 2191 2192 return threadData = (ThreadData) threadData.clone(); 2193 } 2194 2195 2198 public StackFrame top () { 2199 if (stack.length > 0) { 2200 return stack[stack.length - 1]; 2201 } else { 2202 return null; 2203 } 2204 } 2205 2206 2209 protected StackFrame topClone () { 2210 int i = stack.length - 1; 2211 2212 if (hasChanged.get(i)) { 2213 return stack[i]; 2214 } 2215 2216 hasChanged.set(i); 2217 anyChanged = true; 2218 list.ks.data = null; 2219 2220 if ((lowestChanged == -1) || (lowestChanged > i)) { 2221 lowestChanged = i; 2222 } 2223 2224 return stack[i] = (StackFrame) stack[i].clone(); 2225 } 2226 2227 void setDaemon (boolean isDaemon) { 2228 threadDataClone().isDaemon = isDaemon; 2229 } 2230 2231 boolean isDaemon () { 2232 return threadData.isDaemon; 2233 } 2234 2235 MJIEnv getMJIEnv () { 2236 return env; 2237 } 2238 2239 void setName (String newName) { 2240 threadDataClone().name = newName; 2241 2242 } 2245 2246 void setPriority (int newPrio) { 2247 if (threadData.priority != newPrio) { 2248 threadDataClone().priority = newPrio; 2249 2250 } 2256 } 2257 2258 int getPriority () { 2259 return threadData.priority; 2260 } 2261 2262 2268 void init (int rGroup, int rRunnable, int rName, long stackSize, 2269 boolean setPriority) { 2270 DynamicArea da = JVM.getVM().getDynamicArea(); 2271 ElementInfo ei = da.get(rName); 2272 2273 ThreadData td = threadDataClone(); 2274 threadData.name = ei.asString(); 2275 threadData.target = rRunnable; 2276 2277 } 2279 2280 2283 public boolean wasDirectCall () { 2284 return top().isDirectCall(); 2285 } 2286} 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 | Popular Tags |