00001 package gov.nasa.arc.ase.jpf.jvm;
00002
00003 import gov.nasa.arc.ase.jpf.Engine;
00004 import gov.nasa.arc.ase.jpf.InternalErrorException;
00005 import gov.nasa.arc.ase.jpf.iThreadInfo;
00006 import gov.nasa.arc.ase.jpf.JPFErrorException;
00007 import gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction;
00008 import gov.nasa.arc.ase.jpf.jvm.bytecode.ReturnInstruction;
00009 import gov.nasa.arc.ase.jpf.jvm.bytecode.InvokeInstruction;
00010 import gov.nasa.arc.ase.jpf.jvm.bytecode.INVOKESTATIC;
00011 import gov.nasa.arc.ase.util.Debug;
00012 import gov.nasa.arc.ase.util.HashData;
00013 import gov.nasa.arc.ase.util.HashPool;
00014 import gov.nasa.arc.ase.util.Right;
00015 import java.util.BitSet;
00016 import java.util.Set;
00017 import java.util.HashSet;
00018
00019
00020
00021 import java.util.LinkedList;
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 public class ThreadInfo implements iThreadInfo, Storable, Thread {
00048
00049
00050
00051 private static HashPool threadDataPool = new HashPool();
00052
00053
00054
00055
00056 private static HashPool stackFramePool = new HashPool();
00057
00058
00059
00060
00061 private ThreadData threadData;
00062
00063
00064
00065
00066
00067 private AtomicData atomicData;
00068
00069
00070
00071
00072 private StackFrame[] stack;
00073
00074
00075
00076
00077 public ThreadList list;
00078
00079
00080
00081
00082 public int index;
00083
00084
00085
00086
00087 public int tdIndex = -1;
00088
00089
00090
00091
00092 public BitSet hasChanged;
00093
00094
00095
00096
00097 public boolean anyChanged;
00098
00099
00100
00101
00102 private int[] data;
00103
00104
00105
00106
00107 private int lowestChanged;
00108
00109
00110
00111
00112 ThreadInfo() {
00113 stack = new StackFrame[0];
00114 tdIndex = -1;
00115 data = new int[0];
00116 hasChanged = new BitSet();
00117 }
00118
00119
00120
00121
00122 public ThreadInfo(int o) {
00123 threadData = new ThreadData();
00124 threadData.status = NEW;
00125 if(o != -1)
00126 threadData.ci = VirtualMachine.getSS().ks.da.get(o).getClassInfo();
00127 threadData.objref = o;
00128 threadData.target = -1;
00129 threadData.lockCount = 0;
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 atomicData = new AtomicData();
00147 atomicData.currentMethod = null;
00148 atomicData.line = -1;
00149 atomicData.inSameMethod = false;
00150 atomicData.softAtomicLevel = 0;
00151
00152 stack = new StackFrame[0];
00153
00154 hasChanged = new BitSet();
00155 anyChanged = false;
00156 data = new int[0];
00157 lowestChanged = -1;
00158 }
00159 public ThreadInfo(ThreadInfo ti) {
00160 if(ti.tdIndex == -1)
00161 threadData = (ThreadData)ti.threadData.clone();
00162 else
00163 threadData = ti.threadData;
00164
00165 atomicData = (AtomicData)ti.atomicData.clone();
00166
00167 if(ti.stack != null) {
00168 int l = ti.stack.length;
00169 stack = new StackFrame[l];
00170 if(ti.anyChanged)
00171 for(int i = 0; i < l; i++)
00172 if(ti.hasChanged.get(i))
00173 stack[i] = (StackFrame)ti.stack[i].clone();
00174 else
00175 stack[i] = ti.stack[i];
00176 else
00177 System.arraycopy(ti.stack, 0, stack, 0, l);
00178 } else
00179 stack = null;
00180
00181 list = null;
00182
00183 index = -1;
00184
00185 tdIndex = ti.tdIndex;
00186
00187 hasChanged = (BitSet)ti.hasChanged.clone();
00188
00189 anyChanged = ti.anyChanged;
00190
00191 data = ti.data;
00192
00193 lowestChanged = ti.lowestChanged;
00194 }
00195 public boolean atInvoke(String mname) {
00196 if(stack.length == 0) return false;
00197
00198 Instruction pc = getPC();
00199
00200 if(!(pc instanceof InvokeInstruction)) return false;
00201
00202 InvokeInstruction i = (InvokeInstruction)pc;
00203
00204 return mname.equals(i.cname + "." + i.mname);
00205 }
00206 public boolean atLabel(String label) {
00207
00208 return Labels.isAt(label, this);
00209
00210
00211
00212 }
00213 public boolean atMethod(String mname) {
00214 if(stack.length == 0) return false;
00215
00216 return getMethod().getCompleteName().equals(mname);
00217 }
00218 public boolean atPosition(int position) {
00219 if(stack.length == 0) return false;
00220
00221 Instruction pc = getPC();
00222
00223 if(pc == null) return false;
00224
00225 return pc.getPosition() == position;
00226 }
00227 public boolean atReturn() {
00228 if(stack.length == 0) return false;
00229
00230 Instruction pc = getPC();
00231
00232 if(pc == null) return false;
00233
00234 return pc instanceof ReturnInstruction;
00235 }
00236
00237
00238
00239 public void backtrackTo(ArrayOffset storing, Object backtrack) {
00240 setThreadDataIndex(storing.get());
00241
00242 int length = storing.get();
00243 int l = stack.length;
00244
00245 int[] data = new int[length+2];
00246 data[0] = tdIndex;
00247 data[1] = length;
00248 System.arraycopy(storing.data, storing.offset, data, 2, length);
00249
00250 if(length != l) {
00251 if(l > length) l = length;
00252 StackFrame[] n = new StackFrame[length];
00253 if(l > 0)
00254 System.arraycopy(stack, 0, n, 0, l);
00255 stack = n;
00256 }
00257
00258 for(int i = 0; i < length; i++)
00259 setStackFrameIndex(i, storing.get());
00260
00261 atomicData = (AtomicData)backtrack;
00262
00263 anyChanged = false;
00264 hasChanged = new BitSet();
00265 lowestChanged = -1;
00266
00267 this.data = data;
00268 }
00269
00270
00271
00272 public void callerPop(int n) {
00273 frameClone(-1).pop(n);
00274 }
00275
00276
00277
00278 public void clearOperandStack() {
00279 topClone().clearOperandStack();
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 public Object clone() {
00293 return new ThreadInfo(this);
00294 }
00295
00296
00297
00298 public int countStackFrames() {
00299 return stack.length;
00300 }
00301
00302
00303
00304 public Instruction createAndThrowException(ClassInfo ci) {
00305 int objref = list.ks.da.newObject(ci, this);
00306
00307 return throwException(objref);
00308 }
00309
00310
00311
00312 public Instruction createAndThrowException(String cname) {
00313 return createAndThrowException(ClassInfo.getClassInfo(cname));
00314 }
00315
00316
00317
00318 public void createMethodStackFrame(MethodInfo mi) {
00319 int nargs = mi.getArgumentsSize();
00320 int[] args = new int[nargs];
00321 boolean[] refs = new boolean[nargs];
00322 if(nargs > 0) {
00323 StackFrame sf = top();
00324
00325 for(int i = 0, cnt = nargs-1; i < nargs; i++, cnt--) {
00326 args[cnt] = sf.peek(i);
00327 refs[cnt] = sf.isOperandRef(i);
00328 }
00329 }
00330
00331 newFrame(mi);
00332
00333 if(nargs > 0) {
00334 StackFrame sf = top();
00335
00336 for(int i = 0; i < nargs; i++)
00337 setLocalVariable(i, args[i], refs[i]);
00338 }
00339 }
00340
00341
00342
00343 public void dup() {
00344 topClone().dup();
00345 }
00346
00347
00348
00349 public void dup_x1() {
00350 topClone().dup_x1();
00351 }
00352
00353
00354
00355 public void dup_x2() {
00356 topClone().dup_x2();
00357 }
00358
00359
00360
00361 public void dup2() {
00362 topClone().dup2();
00363 }
00364
00365
00366
00367 public void dup2_x1() {
00368 topClone().dup2_x1();
00369 }
00370
00371
00372
00373 public void dup2_x2() {
00374 topClone().dup2_x2();
00375 }
00376
00377
00378
00379 public void enterSoftAtomic() {
00380 atomicData.softAtomicLevel++;
00381 }
00382
00383
00384
00385
00386 private boolean executeAtomicLinesStep() {
00387 atomicData.line = getLine();
00388 atomicData.currentMethod = getMethod();
00389 atomicData.inSameMethod = true;
00390
00391 int[] lines = atomicData.currentMethod.getLineNumbers();
00392
00393 if(list.ks.ss.ti == null)
00394 list.ks.ss.ti = new TrailInfo(index, list.ks.ss.sch.getRandom());
00395
00396
00397
00398
00399
00400
00401 while(true) {
00402 Instruction pc = executeInstruction();
00403
00404 if(list.ks.ss.violatedAssertion) break;
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 Engine.getJPF().status.instructions++;
00419
00420 if(pc == null) break;
00421
00422
00423 if(pc.isObservable()) {
00424 list.ks.ss.ti.addComment("observable instruction");
00425 return false;
00426 }
00427
00428
00429 if(pc.examine(list.ks.ss, list.ks, this)) {
00430 return false;
00431 }
00432
00433 if(list.ks.atomicLevel != 0) {
00434 if(!isRunnable()) {
00435 printStackTrace();
00436 throw new JPFErrorException("Non-executable statement in atomic block");
00437 }
00438 continue;
00439 }
00440
00441 if(!isRunnable()) break;
00442
00443 if(atomicData.softAtomicLevel != 0) {
00444 continue;
00445 }
00446
00447 if(!atomicData.inSameMethod || (
00448 atomicData.line != lines[pc.getOffset()] &&
00449 !(pc instanceof ReturnInstruction))) {
00450 atomicData.currentMethod = null;
00451 atomicData.line = -1;
00452 break;
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 return true;
00470 }
00471
00472
00473
00474 public Instruction executeInstruction() {
00475 Instruction pc = getPC();
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 list.ks.ss.ti.addStep(getMethod().getClassInfo().getName(), getLine());
00487 list.ks.ss.ti.addBytecode(pc);
00488
00489
00490 pc = pc.execute(list.ks.ss, list.ks, this);
00491
00492
00493 if(stack.length != 0) setPC(pc);
00494
00495 return pc;
00496 }
00497
00498
00499
00500
00501
00502 public void executeMethod(MethodInfo mi) {
00503 int depth = countStackFrames();
00504
00505
00506 if(list.ks.ss.ti == null)
00507 list.ks.ss.ti = new TrailInfo(index, list.ks.ss.sch.getRandom());
00508
00509
00510
00511
00512
00513
00514 mi.getClassInfo().executeMethod(this, mi.getFullName());
00515 while(depth < countStackFrames()) {
00516 Instruction pc = executeInstruction();
00517
00518 if(list.ks.ss.violatedAssertion) break;
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 Engine.getJPF().status.instructions++;
00533
00534 if(pc == null)
00535 throw new InternalErrorException("pc == null in executeMethod");
00536
00537 if(!isRunnable())
00538 throw new InternalErrorException("blocked in executeMethod");
00539 }
00540 }
00541
00542
00543
00544 private boolean executeNoAtomicLinesStep() {
00545
00546 if(list.ks.ss.ti == null)
00547 list.ks.ss.ti = new TrailInfo(index, list.ks.ss.sch.getRandom());
00548
00549
00550
00551
00552
00553
00554 while(true) {
00555 Instruction pc = executeInstruction();
00556
00557 if(list.ks.ss.violatedAssertion) break;
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 Engine.getJPF().status.instructions++;
00571
00572 if(pc == null) break;
00573
00574
00575 if(pc.isObservable()) {
00576 list.ks.ss.ti.addComment("observable instruction");
00577 return false;
00578 }
00579
00580
00581 if(pc.examine(list.ks.ss, list.ks, this))
00582 return false;
00583
00584 if(list.ks.atomicLevel != 0) {
00585 if(!isRunnable()) {
00586 printStackTrace();
00587 throw new JPFErrorException("Non-executable statement in atomic block");
00588 }
00589 continue;
00590 }
00591 if(!isRunnable()) break;
00592 if(atomicData.softAtomicLevel != 0) {
00593 continue;
00594 }
00595
00596 break;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 return true;
00613 }
00614
00615
00616
00617
00618
00619
00620 public void executeStaticMethod(MethodInfo mi) {
00621 int depth = countStackFrames();
00622
00623
00624 if(list.ks.ss.ti == null)
00625 list.ks.ss.ti = new TrailInfo(index, list.ks.ss.sch.getRandom());
00626
00627
00628
00629
00630
00631
00632 mi.getClassInfo().executeStaticMethod(this, mi.getFullName());
00633 while(depth < countStackFrames()) {
00634 Instruction pc = executeInstruction();
00635
00636 if(list.ks.ss.violatedAssertion) break;
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 Engine.getJPF().status.instructions++;
00651
00652 if(pc == null)
00653 break;
00654
00655 if(!pc.isExecutable(list.ks.ss, list.ks, this)) {
00656 list.ks.jvmError(new InternalErrorException("blocked in executeStaticMethod"), this);
00657 }
00658 }
00659 }
00660
00661
00662
00663
00664 public boolean executeStep() {
00665
00666
00667
00668 if(VirtualMachine.options.atomic_lines)
00669 return executeAtomicLinesStep();
00670 else
00671 return executeNoAtomicLinesStep();
00672 }
00673
00674
00675
00676 private StackFrame frame(int idx) {
00677 if(idx < 0) idx += stack.length - 1;
00678
00679 return stack[idx];
00680 }
00681
00682
00683
00684 private StackFrame frameClone(int i) {
00685 if(i < 0) i += stack.length - 1;
00686
00687 if(hasChanged.get(i)) return stack[i];
00688
00689 hasChanged.set(i);
00690 anyChanged = true;
00691 list.ks.data = null;
00692 if(lowestChanged == -1 || lowestChanged > i)
00693 lowestChanged = i;
00694
00695 return stack[i] = (StackFrame)stack[i].clone();
00696 }
00697
00698
00699
00700 public Object getBacktrackData() {
00701 return atomicData.clone();
00702 }
00703 public boolean getBooleanLocal(int lindex) { return Types.intToBoolean(getLocalVariable(lindex)); }
00704 public boolean getBooleanLocal(String lname) { return Types.intToBoolean(getLocalVariable(lname)); }
00705 public boolean getBooleanReturnValue() { return Types.intToBoolean(peek()); }
00706 public byte getByteLocal(int lindex) { return (byte)getLocalVariable(lindex); }
00707 public byte getByteLocal(String lname) { return (byte)getLocalVariable(lname); }
00708 public byte getByteReturnValue() { return (byte)peek(); }
00709
00710
00711
00712 public int getCalleeThis(int size) {
00713 return top().getCalleeThis(size);
00714 }
00715
00716
00717
00718 public int getCalleeThis(MethodInfo mi) {
00719 return top().getCalleeThis(mi);
00720 }
00721 public String[] getCallStack() {
00722 int size = stack.length;
00723 String[] callStack = new String[size];
00724
00725 for(int i = 0; i < size; i++) {
00726 StackFrame sf = frame(i);
00727
00728 callStack[i] = sf.getClassInfo().getName() + "." +
00729 sf.getMethodInfo().getName() + " line " +
00730 sf.getLine();
00731 }
00732
00733 return callStack;
00734 }
00735 public char getCharLocal(int lindex) { return (char)getLocalVariable(lindex); }
00736 public char getCharLocal(String lname) { return (char)getLocalVariable(lname); }
00737 public char getCharReturnValue() { return (char)peek(); }
00738
00739
00740
00741 public ClassInfo getClassInfo() {
00742 return threadData.ci;
00743 }
00744 public double getDoubleLocal(int lindex) { return Types.longToDouble(getLongLocalVariable(lindex)); }
00745 public double getDoubleLocal(String lname) { return Types.longToDouble(getLongLocalVariable(lname)); }
00746 public double getDoubleReturnValue() { return Types.longToDouble(longPeek()); }
00747 public float getFloatLocal(int lindex) { return Types.intToFloat(getLocalVariable(lindex)); }
00748 public float getFloatLocal(String lname) { return Types.intToFloat(getLocalVariable(lname)); }
00749 public float getFloatReturnValue() { return Types.intToFloat(peek()); }
00750 public int getIntLocal(int lindex) { return getLocalVariable(lindex); }
00751 public int getIntLocal(String lname) { return getLocalVariable(lname); }
00752 public int getIntReturnValue() { return peek(); }
00753
00754
00755
00756 public int getLine() {
00757 return top().getLine();
00758 }
00759
00760
00761
00762 public int getLine(int idx) {
00763 return frame(idx).getLine();
00764 }
00765
00766
00767
00768 public int getLocalVariable(int idx) {
00769 return top().getLocalVariable(idx);
00770 }
00771
00772
00773
00774 public int getLocalVariable(String name) {
00775 return top().getLocalVariable(name);
00776 }
00777
00778
00779
00780 public String getLocalVariableType(String name) {
00781 return top().getLocalVariableType(name);
00782 }
00783
00784
00785
00786 public int getLockCount(){
00787 return threadData.lockCount;
00788 }
00789 public long getLongLocal(int lindex) { return getLongLocalVariable(lindex); }
00790 public long getLongLocal(String lname) { return getLongLocalVariable(lname); }
00791
00792
00793
00794 public long getLongLocalVariable(int idx) {
00795 return top().getLongLocalVariable(idx);
00796 }
00797
00798
00799
00800 public long getLongLocalVariable(String name) {
00801 return top().getLongLocalVariable(name);
00802 }
00803 public long getLongReturnValue() { return longPeek(); }
00804
00805
00806
00807 public MethodInfo getMethod() {
00808 return top().getMethodInfo();
00809 }
00810
00811
00812
00813 public MethodInfo getMethod(int idx) {
00814 return frame(idx).getMethodInfo();
00815 }
00816 public Reference getObjectLocal(int lindex) { return list.ks.da.get(getLocalVariable(lindex)); }
00817 public Reference getObjectLocal(String lname) { return list.ks.da.get(getLocalVariable(lname)); }
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 public int getObjectReference() {
00873 return threadData.objref;
00874 }
00875 public Reference getObjectReturnValue() { return list.ks.da.get(peek()); }
00876
00877
00878
00879 public Instruction getPC() {
00880 if(stack.length == 0) return null;
00881
00882 return top().getPC();
00883 }
00884
00885
00886
00887 public Instruction getPC(int i) {
00888 return frame(i).getPC();
00889 }
00890 public short getShortLocal(int lindex) { return (short)getLocalVariable(lindex); }
00891 public short getShortLocal(String lname) { return (short)getLocalVariable(lname); }
00892 public short getShortReturnValue() { return (short)peek(); }
00893 private int getStackFrameIndex(int i) {
00894 if(hasChanged.get(i)) {
00895 HashPool.PoolEntry e = stackFramePool.getEntry(stack[i]);
00896
00897 stack[i] = (StackFrame)e.getObject();
00898
00899 return e.getIndex();
00900 } else
00901 return data[i+2];
00902 }
00903
00904
00905
00906 public int getStatus() {
00907 return threadData.status;
00908 }
00909
00910
00911
00912 public int[] getStoringData() {
00913 int length = stack.length;
00914
00915 int[] data = new int[length+2];
00916 data[0] = getThreadDataIndex();
00917 data[1] = length;
00918
00919 if(anyChanged) {
00920 if(lowestChanged > 0)
00921 System.arraycopy(this.data, 2, data, 2, lowestChanged);
00922
00923 for(int i = lowestChanged, j = i+2; i < length; i++, j++)
00924 data[j] = getStackFrameIndex(i);
00925 } else
00926 if(length > 0)
00927 System.arraycopy(this.data, 2, data, 2, length);
00928
00929 anyChanged = false;
00930 hasChanged = new BitSet();
00931 lowestChanged = -1;
00932
00933 this.data = data;
00934
00935 return data;
00936 }
00937 public String getStringLocal(int lindex) { return list.ks.da.get(getLocalVariable(lindex)).asString(); }
00938 public String getStringLocal(String lname) { return list.ks.da.get(getLocalVariable(lname)).asString(); }
00939 public String getStringReturnValue() { return list.ks.da.get(peek()).asString(); }
00940
00941
00942
00943 public int getTarget() {
00944 return threadData.target;
00945 }
00946
00947
00948
00949 public int getThis() {
00950 return top().getThis();
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 private int getThreadDataIndex() {
00965 if(tdIndex != -1) return tdIndex;
00966
00967 HashPool.PoolEntry e = threadDataPool.getEntry(threadData);
00968 threadData = (ThreadData)e.getObject();
00969
00970 return tdIndex = e.getIndex();
00971 }
00972 public void hash(HashData hd) {
00973 threadData.hash(hd);
00974 atomicData.hash(hd);
00975
00976 for(int i = 0, l = stack.length; i < l; i++)
00977 frame(i).hash(hd);
00978 }
00979 public int hashCode() {
00980 HashData hd = new HashData();
00981
00982 hash(hd);
00983
00984 return hd.getValue();
00985 }
00986 public void interrupt() {
00987 if(getStatus() != WAITING) return;
00988
00989 setStatus(INTERRUPTED);
00990 }
00991
00992
00993
00994 public boolean isAlive(){
00995 return threadData.status == RUNNING ||
00996 threadData.status == WAITING ||
00997 threadData.status == INTERRUPTED ||
00998 threadData.status == NOTIFIED;
00999 }
01000 public boolean isCalleeThis(Reference r) {
01001 if(stack.length == 0) return false;
01002
01003 Instruction pc = getPC();
01004
01005 if(pc == null) return false;
01006
01007 if(!(pc instanceof InvokeInstruction)) return false;
01008 if(pc instanceof INVOKESTATIC) return false;
01009
01010 InvokeInstruction i = (InvokeInstruction)pc;
01011
01012 return getCalleeThis(Types.getArgumentsSize(i.signature)) ==
01013 ((ElementInfo)r).index;
01014 }
01015
01016
01017
01018
01019 public boolean isEnabled() {
01020
01021
01022
01023
01024
01025
01026 return threadData.status == RUNNING ||
01027 threadData.status == INTERRUPTED ||
01028 threadData.status == NOTIFIED;
01029 }
01030
01031
01032
01033 public boolean isLocalVariableRef(int idx) {
01034 return top().isLocalVariableRef(idx);
01035 }
01036
01037
01038
01039 public boolean isOperandRef() {
01040 return top().isOperandRef();
01041 }
01042
01043
01044
01045 public boolean isOperandRef(int idx) {
01046 return top().isOperandRef(idx);
01047 }
01048
01049
01050
01051
01052
01053 public boolean isRunnable() {
01054 if(!isEnabled())
01055 return false;
01056
01057 Instruction i = getPC();
01058
01059 if(i == null) return false;
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 return i.isExecutable(list.ks.ss, list.ks, this);
01082 }
01083
01084
01085
01086
01087 public boolean isSafe() {
01088 if(!isEnabled())
01089 return false;
01090
01091 return top().isSafe();
01092 }
01093 public boolean isThis(Reference r) {
01094 if(stack.length == 0) return false;
01095
01096 return getMethod().isStatic() ?
01097 false :
01098 ((ElementInfo)r).index == getLocalVariable(0);
01099 }
01100
01101
01102
01103 public void leaveSoftAtomic() {
01104 atomicData.softAtomicLevel--;
01105 }
01106 public void log() {
01107 Debug.println(Debug.MESSAGE, "TH#" + index + " #" + threadData.target + " #" + threadData.objref + " " + threadData.status);
01108 for(int i = 0; i < stack.length; i++)
01109 frame(i).log(i);
01110 }
01111
01112
01113
01114 public long longPeek() {
01115 return top().longPeek();
01116 }
01117
01118
01119
01120 public long longPeek(int n) {
01121 return top().longPeek(n);
01122 }
01123
01124
01125
01126 public long longPop() {
01127 return topClone().longPop();
01128 }
01129
01130
01131
01132 public void longPush(long v) {
01133 topClone().longPush(v);
01134 }
01135
01136
01137
01138
01139 public void mark() {
01140 list.ks.da.mark(threadData.objref);
01141 if(threadData.target != -1) list.ks.da.mark(threadData.target);
01142
01143 for(int i = 0, l = stack.length; i < l; i++)
01144 frame(i).mark(list.ks.da);
01145 }
01146
01147
01148
01149 public void newFrame(MethodInfo mi) {
01150 StackFrame sf = new StackFrame(mi);
01151 if(sf.isSystemMethod())
01152 enterSoftAtomic();
01153
01154 atomicData.inSameMethod = false;
01155
01156 int depth = stack.length;
01157 StackFrame[] n = new StackFrame[depth + 1];
01158 System.arraycopy(stack, 0, n, 0, depth);
01159 stack = n;
01160
01161 stack[depth] = sf;
01162
01163 hasChanged.set(depth);
01164 anyChanged = true;
01165 list.ks.data = null;
01166 if(lowestChanged == -1 || lowestChanged > depth)
01167 lowestChanged = depth;
01168 }
01169
01170
01171
01172
01173
01174 public int peek() {
01175 return top().peek();
01176 }
01177
01178
01179
01180 public int peek(int n) {
01181 return top().peek(n);
01182 }
01183
01184
01185
01186 public int pop() {
01187 return topClone().pop();
01188 }
01189
01190
01191
01192 public void pop(int n) {
01193 topClone().pop(n);
01194 }
01195
01196
01197
01198 public void popFrame() {
01199 int last = stack.length - 1;
01200 StackFrame sf = stack[last];
01201
01202 if(sf.hasAnyRef())
01203 VirtualMachine.getSS().activateGC();
01204
01205
01206
01207
01208
01209
01210 if(sf.isSystemMethod())
01211 leaveSoftAtomic();
01212
01213 StackFrame[] n = new StackFrame[last];
01214 System.arraycopy(stack, 0, n, 0, last);
01215 stack = n;
01216
01217 if(last == 0) {
01218 atomicData.inSameMethod = false;
01219 setStatus(STOPPED);
01220 list.ks.da.get(threadData.objref).notifies();
01221 } else
01222 atomicData.inSameMethod = getMethod() == atomicData.currentMethod;
01223
01224 hasChanged.set(last);
01225 anyChanged = true;
01226 list.ks.data = null;
01227 if(lowestChanged == -1 || lowestChanged > last)
01228 lowestChanged = last;
01229 }
01230 public void printInternalErrorTrace(Throwable e) {
01231 String msg = e.getMessage();
01232 if(msg != null)
01233 Debug.println(Debug.ERROR, "exception " + e.getClass().getName() + ": " + msg);
01234 else
01235 Debug.println(Debug.ERROR, "exception " + e.getClass().getName());
01236 printStackTrace();
01237 if(msg != null)
01238 Debug.println(Debug.ERROR, "exception " + e.getClass().getName() + ": " + msg);
01239 else
01240 Debug.println(Debug.ERROR, "exception " + e.getClass().getName());
01241 printStackContent();
01242 }
01243
01244
01245
01246 public void printStackContent() {
01247 for(int i = stack.length - 1; i >= 0; i--)
01248 frame(i).printStackContent();
01249 }
01250
01251
01252
01253 public void printStackTrace() {
01254 for(int i = stack.length-1; i >= 0; i--)
01255 frame(i).printStackTrace();
01256 }
01257
01258
01259
01260 public void push(int v, boolean ref) {
01261 topClone().push(v, ref);
01262 }
01263
01264
01265
01266 public void removeArguments(MethodInfo mi) {
01267 int i = mi.getArgumentsSize();
01268
01269 if(i != 0) pop(i);
01270 }
01271
01272
01273
01274 public void setLocalVariable(int idx, int v, boolean ref) {
01275 topClone().setLocalVariable(idx, v, ref);
01276 }
01277
01278
01279
01280 public void setLockCount(int l){
01281 if(threadData.lockCount != l)
01282 threadDataClone().lockCount = l;
01283 }
01284
01285
01286
01287 public void setLongLocalVariable(int idx, long v) {
01288 topClone().setLongLocalVariable(idx, v);
01289 }
01290
01291
01292
01293 public void setPC(Instruction pc) {
01294 topClone().setPC(pc);
01295 }
01296 private void setStackFrameIndex(int i, int idx) {
01297 if(hasChanged.get(i) || i+2 >= data.length || data[i+2] != idx)
01298 stack[i] = (StackFrame)stackFramePool.getObject(idx);
01299 }
01300
01301
01302
01303 public void setStatus(int s) {
01304 if(threadData.status != s)
01305 threadDataClone().status = s;
01306 }
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319 public void setTarget(int t) {
01320 threadDataClone().target = t;
01321 }
01322 private void setThreadDataIndex(int idx) {
01323 if(tdIndex == idx) return;
01324
01325 tdIndex = idx;
01326 threadData = (ThreadData)threadDataPool.getObject(idx);
01327 }
01328
01329
01330
01331 public void swap() {
01332 topClone().swap();
01333 }
01334
01335
01336
01337 private ThreadData threadDataClone() {
01338 if(tdIndex == -1) return threadData;
01339
01340 tdIndex = -1;
01341 list.ks.data = null;
01342 return threadData = (ThreadData)threadData.clone();
01343 }
01344
01345
01346
01347 public Instruction throwException(int objref) {
01348 ClassInfo ci = list.ks.da.get(objref).getClassInfo();
01349
01350 while (countStackFrames() != 0) {
01351 MethodInfo mi = getMethod();
01352 ExceptionHandler[] exceptions = mi.getExceptions();
01353
01354 if(exceptions != null) {
01355 int p = getPC().getPosition();
01356
01357
01358 for(int i = 0, s = exceptions.length; i < s; i++) {
01359 ExceptionHandler eh = exceptions[i];
01360
01361
01362 if (p >= eh.getBegin() && p <= eh.getEnd()) {
01363 String en = eh.getName();
01364
01365
01366 if(en == null || ci.instanceOf(en)) {
01367
01368 clearOperandStack();
01369
01370
01371 push(objref, true);
01372
01373
01374 return mi.getInstructionAt(eh.getHandler());
01375 }
01376 }
01377 }
01378 }
01379
01380 mi.leave(this);
01381
01382
01383 popFrame();
01384 }
01385
01386
01387 setStatus(STOPPED);
01388 list.ks.da.get(threadData.objref).notifies();
01389 throw new UncaughtException(ci.getName());
01390 }
01391
01392
01393
01394 private StackFrame top() {
01395 return stack[stack.length-1];
01396 }
01397
01398
01399
01400 private StackFrame topClone() {
01401 int i = stack.length - 1;
01402
01403 if(hasChanged.get(i)) return stack[i];
01404
01405 hasChanged.set(i);
01406 anyChanged = true;
01407 list.ks.data = null;
01408 if(lowestChanged == -1 || lowestChanged > i)
01409 lowestChanged = i;
01410
01411 return stack[i] = (StackFrame)stack[i].clone();
01412 }
01413 }