00001 package gov.nasa.arc.ase.jpf.jvm;
00002
00003 import de.fub.bytecode.*;
00004 import de.fub.bytecode.classfile.*;
00005 import de.fub.bytecode.generic.*;
00006 import gov.nasa.arc.ase.jpf.*;
00007 import gov.nasa.arc.ase.util.Debug;
00008 import gov.nasa.arc.ase.util.HashData;
00009 import gov.nasa.arc.ase.util.PoolObject;
00010 import java.io.*;
00011 import java.util.*;
00012 import java.util.Random;
00013
00014 public class StackFrame extends PoolObject implements Constants {
00015 static private Random random = new Random();
00016
00017
00018 Stack operands;
00019 int[] locals;
00020
00021 InstructionHandle pc;
00022 ClassInfo ci;
00023 MethodInfo mi;
00024 ConstantPoolGen cpg;
00025 LocalVariableGen[] localInfo;
00026
00027
00028 BitSet localrefs = new BitSet();
00029 BitSet operandrefs = new BitSet();
00030
00031 private int upto = 0;
00032
00033 public StackFrame(ClassInfo c, MethodInfo m, int[] ls, Stack os, InstructionHandle p) {
00034 ci = c;
00035 mi = m;
00036 locals = ls;
00037 operands = os;
00038 pc = p;
00039 cpg = mi.getConstantPool();
00040 localInfo = mi.getMethodGen().getLocalVariables();
00041 }
00042
00043
00044
00045 public StackFrame(MethodInfo m, ClassInfo c) {
00046 mi = m;
00047 ci = c;
00048
00049 operands = new Stack();
00050 cpg = mi.getConstantPool();
00051 localInfo = mi.getMethodGen().getLocalVariables();
00052
00053
00054 if (localInfo == null)
00055 Debug.println(Debug.WARNING, "No local Variable information: use javac -g");
00056
00057
00058 pc = mi.getFirstInstruction();
00059
00060 int nlocals = mi.getMethodGen().getMaxLocals();
00061 if(pc == null) nlocals = mi.getArgumentSize();
00062
00063 locals = new int[nlocals];
00064 }
00065
00066 public void clearOperandStack() {
00067 operands.removeAllElements();
00068 }
00069
00070 public Object clone(){
00071 try{
00072
00073 StackFrame sf = (StackFrame)super.clone();
00074
00075
00076 sf.operands = (Stack)operands.clone();
00077
00078
00079 int nlocals = locals.length;
00080 sf.locals = new int[nlocals];
00081 System.arraycopy(locals, 0, sf.locals, 0, nlocals);
00082
00083
00084
00085 sf.localrefs = (BitSet)localrefs.clone();
00086 sf.operandrefs = (BitSet)operandrefs.clone();
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 return sf;
00097 } catch(CloneNotSupportedException e){
00098 throw new InternalError(e.toString());
00099 }
00100 }
00101
00102
00103
00104 public InstructionHandle createAndThrowException(String classname,
00105 SystemState ss, KernelState ks, ThreadInfo th) {
00106
00107 JPFVM jpfvm = JPFVM.getJPFVM();
00108 ClassInfo ci = jpfvm.getClass(classname);
00109 if (!ks.static_area.hasClass(classname)) {
00110 ks.static_area.addClass(ci);
00111 return ci.initialize(ss, ks, th);
00112 }
00113
00114
00115 int objref = ks.dynamic_area.newObject(ci, th);
00116
00117
00118 push(objref);
00119
00120 setOperandRef();
00121
00122
00123
00124
00125
00126
00127
00128 return new ATHROW().execute(ss, ks, th);
00129 }
00130
00131 public int doRandom(int max, Scheduler sch) {
00132
00133 if (((JPFOptions)Engine.options).verify){
00134
00135 int randomValue = sch.getCurrentRandom();
00136
00137
00138
00139
00140 if ((randomValue+1) < max) {
00141
00142
00143
00144 TransitionResult.setRandom();
00145 } else {
00146
00147
00148
00149 TransitionResult.clearRandom();
00150 }
00151 return randomValue;
00152 } else {
00153
00154
00155
00156 return Math.abs(random.nextInt() % max);
00157 }
00158 }
00159 public void dup() {
00160
00161 boolean ref = isOperandRef();
00162 operands.push(operands.peek());
00163 if(ref) setOperandRef();
00164
00165
00166
00167 }
00168 public void dup_x1() {
00169
00170
00171
00172
00173 boolean bref = isOperandRef(); int b = xpop();
00174 boolean aref = isOperandRef(); int a = xpop();
00175 push(b); if(bref) setOperandRef();
00176 push(a); if(aref) xSetOperandRef();
00177 push(b); if(bref) xSetOperandRef();
00178
00179
00180
00181
00182
00183
00184
00185 }
00186 public void dup_x2() {
00187
00188
00189
00190
00191 boolean cref = isOperandRef(); int c = xpop();
00192 boolean bref = isOperandRef(); int b = xpop();
00193 boolean aref = isOperandRef(); int a = xpop();
00194 push(c); if(cref) setOperandRef();
00195 push(a); if(aref) xSetOperandRef();
00196 push(b); if(bref) xSetOperandRef();
00197 push(c); if(cref) xSetOperandRef();
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 }
00208 public void dup2() {
00209
00210 boolean bref = isOperandRef(); int b = xpop();
00211 boolean aref = isOperandRef(); int a = xpop();
00212 push(a); if(aref) xSetOperandRef();
00213 push(b); if(bref) xSetOperandRef();
00214 push(a); if(aref) setOperandRef();
00215 push(b); if(bref) setOperandRef();
00216
00217
00218
00219 }
00220 public void dup2_x1() {
00221
00222
00223
00224
00225 boolean cref = isOperandRef(); int c = xpop();
00226 boolean bref = isOperandRef(); int b = xpop();
00227 boolean aref = isOperandRef(); int a = xpop();
00228 push(b); if(bref) setOperandRef();
00229 push(c); if(cref) setOperandRef();
00230 push(a); if(aref) xSetOperandRef();
00231 push(b); if(bref) xSetOperandRef();
00232 push(c); if(cref) xSetOperandRef();
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 }
00244 public void dup2_x2() {
00245
00246
00247
00248
00249 boolean dref = isOperandRef(); int d = xpop();
00250 boolean cref = isOperandRef(); int c = xpop();
00251 boolean bref = isOperandRef(); int b = xpop();
00252 boolean aref = isOperandRef(); int a = xpop();
00253 push(c); if(cref) setOperandRef();
00254 push(d); if(dref) setOperandRef();
00255 push(a); if(aref) xSetOperandRef();
00256 push(b); if(bref) xSetOperandRef();
00257 push(c); if(cref) xSetOperandRef();
00258 push(d); if(dref) xSetOperandRef();
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 }
00272 public boolean equals(Object object) {
00273
00274 StackFrame sf = (StackFrame)object;
00275
00276
00277
00278
00279 if (pc != sf.pc) return false;
00280 if (!mi.getFullName().equals(sf.mi.getFullName())) return false;
00281
00282
00283 if (!localrefs.equals(sf.localrefs)) return false;
00284 if (!operandrefs.equals(sf.operandrefs)) return false;
00285
00286
00287
00288
00289 int[] l = sf.locals;
00290 int nlocals = locals.length;
00291
00292 if (nlocals != l.length) return false;
00293 for (int idx = 0; idx < nlocals; idx++)
00294 if(locals[idx] != l[idx]) return false;
00295
00296 Stack o = sf.operands;
00297 int noperands = operands.size();
00298
00299 if (noperands != o.size()) return false;
00300 for (int idx = 0; idx < noperands; idx++)
00301 if (!operands.get(idx).equals(o.get(idx)))
00302 return false;
00303
00304 return true;
00305 }
00306
00307 public int getCalleeThis(int locals) {
00308 return ((Integer)operands.get(operands.size() - locals)).intValue();
00309 }
00310 public ClassInfo getClassInfo() {
00311 return ci;
00312 }
00313 public ConstantPoolGen getConstantPool() {
00314 return cpg;
00315 }
00316
00317 public int getCurrentLine() {
00318 return mi.getLineNumbers().getSourceLine(pc.getPosition());
00319 }
00320 public int getLocalVariable(int i) {
00321 return locals[i];
00322 }
00323
00324 public long getLocalVariable(String name) {
00325 for(int idx = 0; idx < localInfo.length; idx++)
00326 if (name.equals(localInfo[idx].getName())) {
00327 switch(localInfo[idx].getType().getType()) {
00328 case T_BOOLEAN:
00329 case T_BYTE:
00330 case T_CHAR:
00331 case T_FLOAT:
00332 case T_INT:
00333 case T_REFERENCE:
00334 case T_ARRAY:
00335 case T_SHORT:
00336 return (long)getLocalVariable(localInfo[idx].getIndex());
00337
00338 case T_DOUBLE:
00339 case T_LONG:
00340 return getLongLocalVariable(localInfo[idx].getIndex());
00341 }
00342
00343 Debug.println(Debug.ERROR, "unknown local type - " + localInfo[idx].getType().getType());
00344 return -1;
00345 }
00346
00347
00348 Debug.println(Debug.ERROR, "unknown local variable - " + name);
00349 return -1;
00350 }
00351 public int[] getLocalVariables() {
00352 return locals;
00353 }
00354 public long getLongLocalVariable(int i) {
00355 return Types.intsToLong(locals[i], locals[i+1]);
00356 }
00357 public MethodInfo getMethodInfo() {
00358 return mi;
00359 }
00360 public String getMethodName() {
00361 return mi.getMethodName();
00362 }
00363 public Stack getOperandStack() {
00364 return operands;
00365 }
00366 public InstructionHandle getPC() {
00367 return pc;
00368 }
00369 public int getThis() {
00370 if(locals.length == 0) return -1;
00371
00372 return locals[0];
00373 }
00374
00375
00376
00377 public int getType(String name) {
00378 for(int idx = 0; idx < localInfo.length; idx++)
00379 if (name.equals(localInfo[idx].getName()))
00380 return localInfo[idx].getType().getType();
00381
00382
00383 Debug.println(Debug.ERROR, "local variable name mismatch");
00384
00385 return Constants.T_VOID;
00386 }
00387
00388 public boolean hasAnyRef() {
00389 for(int i = 0, l = operandrefs.length(); i < l; i++)
00390 if(operandrefs.get(i)) return true;
00391 for(int i = 0, l = localrefs.length(); i < l; i++)
00392 if(localrefs.get(i)) return true;
00393
00394 return false;
00395 }
00396 public void hash(HashData hd) {
00397 for(int i = 0, l = locals.length; i < l; i++)
00398 hd.add(locals[i]);
00399
00400 for(int i = 0, l = operands.size(); i < l; i++)
00401 hd.add(((Integer)operands.get(i)).intValue());
00402 }
00403
00404
00405
00406 public int hashCode() {
00407 HashData hd = new HashData();
00408
00409 for(int i = 0, l = locals.length; i < l; i++)
00410 hd.add(locals[i]);
00411
00412 for(int i = 0, l = operands.size(); i < l; i++)
00413 hd.add(((Integer)operands.get(i)).intValue());
00414
00415 return hd.getValue();
00416 }
00417
00418 public void incIntLocalVariable(int index, int number) {
00419 locals[index] += number;
00420 }
00421 public boolean isOperandRef() {
00422 return operandrefs.get(operands.size()-1);
00423 }
00424 public boolean isOperandRef(int idx) {
00425 return operandrefs.get(operands.size()-idx-1);
00426 }
00427 public boolean isSafe() {
00428 return ci.isSafe(getCurrentLine());
00429 }
00430 public void local2stack(int index) {
00431 push(locals[index]);
00432 }
00433 public void local2stack2(int index) {
00434 push(locals[index]);
00435 push(locals[index+1]);
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 public void log(int id) {
00455 Debug.print(Debug.MESSAGE, " SF#" + id + " S(");
00456 for(int i = 0; i < operands.size(); i++) {
00457 int j = ((Integer)operands.get(i)).intValue();
00458 Debug.print(Debug.MESSAGE, " ");
00459
00460 if(operandrefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00461
00462 Debug.print(Debug.MESSAGE, j + "");
00463 }
00464 Debug.print(Debug.MESSAGE, " ) L(");
00465 for(int i = 0; i < locals.length; i++) {
00466 int j = locals[i];
00467 Debug.print(Debug.MESSAGE, " ");
00468
00469 if(localrefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00470
00471 Debug.print(Debug.MESSAGE, j + "");
00472 }
00473 Debug.println(Debug.MESSAGE, " )");
00474 }
00475
00476 public void mark(DynamicArea da) {
00477 for(int i = 0, l = operands.size(); i < l; i++)
00478 if(operandrefs.get(i))
00479 da.mark(((Integer)operands.get(i)).intValue());
00480
00481 for(int i = 0, l = locals.length; i < l; i++)
00482 if(localrefs.get(i))
00483 da.mark(locals[i]);
00484 }
00485 public int pcs() { return upto + (pc == null ? 0 : pc.getPosition()); }
00486 int peek() {
00487 return ((Integer)operands.peek()).intValue();
00488 }
00489 int peek(int n) {
00490 return ((Integer)operands.get(operands.size() - 1 - n)).intValue();
00491 }
00492 long peek2() {
00493 int lo = ((Integer)operands.peek()).intValue();
00494 int hi = ((Integer)operands.get(operands.size() - 2)).intValue();
00495
00496 return Types.intsToLong(lo, hi);
00497 }
00498 long peek2(int n) {
00499 int lo = ((Integer)operands.get(operands.size() - 1 - n)).intValue();
00500 int hi = ((Integer)operands.get(operands.size() - 2 - n)).intValue();
00501
00502 return Types.intsToLong(lo, hi);
00503 }
00504 int pop() {
00505
00506 if(isOperandRef()) {
00507 VirtualMachine.activateGC();
00508 operandrefs.clear(operands.size()-1);
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 return ((Integer)operands.pop()).intValue();
00519 }
00520 void pop(int n) {
00521 for(int i = 0; i < n; i++) {
00522
00523 if(isOperandRef()) {
00524 VirtualMachine.activateGC();
00525 operandrefs.clear(operands.size()-1);
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535 operands.pop();
00536 }
00537 }
00538 long pop2() {
00539 int lo = ((Integer)operands.pop()).intValue();
00540 int hi = ((Integer)operands.pop()).intValue();
00541
00542 return Types.intsToLong(lo, hi);
00543 }
00544
00545
00546
00547
00548
00549
00550 public void printStackContent() {
00551 Debug.print(Debug.ERROR, "\tat ");
00552 Debug.print(Debug.ERROR, mi.getFullName());
00553 if(pc != null)
00554 Debug.println(Debug.ERROR, ":" + pc.getPosition());
00555 else
00556 Debug.println(Debug.ERROR);
00557 Debug.println(Debug.ERROR, "\t Operand stack is:");
00558 for(int i = 0, l = operands.size(); i < l; i++) {
00559 Debug.print(Debug.ERROR, "\t ");
00560
00561 if(operandrefs.get(i))
00562 Debug.print(Debug.ERROR, "#");
00563
00564 Debug.println(Debug.ERROR, operands.get(i));
00565 }
00566 Debug.println(Debug.ERROR, "\t Local variables are:");
00567 for(int i = 0, l = locals.length; i < l; i++) {
00568 Debug.print(Debug.ERROR, "\t ");
00569
00570 if(localrefs.get(i))
00571 Debug.print(Debug.ERROR, "#");
00572
00573 Debug.println(Debug.ERROR, ""+locals[i]);
00574 }
00575 }
00576 public void printStackTrace() {
00577 Debug.print(Debug.ERROR, "\tat ");
00578 Debug.print(Debug.ERROR, ci.getClassName());
00579 Debug.print(Debug.ERROR, ".");
00580 Debug.print(Debug.ERROR, mi.getMethodName());
00581 if(pc != null) {
00582 Debug.print(Debug.ERROR, "(");
00583 Debug.print(Debug.ERROR, Source.getSourceName(ci.getClassName()));
00584 Debug.print(Debug.ERROR, ":");
00585 Debug.println(Debug.ERROR, getCurrentLine() + ")");
00586 } else
00587 Debug.println(Debug.ERROR, "(Native Method)");
00588 }
00589 void push(int v) {
00590 operands.push(new Integer(v));
00591 }
00592 void push2(long v) {
00593 operands.push(new Integer(Types.hiLong(v)));
00594 operands.push(new Integer(Types.loLong(v)));
00595 }
00596 public void setLocalVariable(int index, int v) {
00597
00598 if(localrefs.get(index)
00599 && locals[index] != -1
00600 && locals[index] != v)
00601 VirtualMachine.activateGC();
00602
00603
00604
00605
00606
00607
00608
00609
00610 locals[index] = v;
00611 }
00612
00613
00614
00615 public void setLocalVariableRef(int idx) {
00616
00617
00618
00619
00620 localrefs.set(idx);
00621 }
00622 public void setLongLocalVariable(int index, long v) {
00623 locals[index] = Types.loLong(v);
00624 locals[index+1] = Types.hiLong(v);
00625 }
00626 public void setOperandRef() {
00627 operandrefs.set(operands.size()-1);
00628
00629
00630
00631
00632 }
00633 public void setPC(InstructionHandle newpc) {
00634 pc = newpc;
00635 }
00636 public void setUpto(int u) { upto = u; }
00637 public void stack2local(int index) {
00638
00639 boolean aref = isOperandRef(); int a = peek();
00640
00641
00642
00643 if(localrefs.get(index)
00644 && locals[index] != -1
00645 && (locals[index] != a || !aref)) {
00646 VirtualMachine.activateGC();
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 if(aref)
00663 localrefs.set(index);
00664 else
00665 localrefs.clear(index);
00666
00667
00668 locals[index] = pop();
00669 }
00670 public void stack2local2(int index) {
00671
00672 boolean aref = isOperandRef(); int a = peek();
00673 boolean bref = isOperandRef(); int b = peek();
00674
00675
00676
00677 if(localrefs.get(index)
00678 && locals[index] != -1
00679 && (locals[index] != a || !aref)) {
00680 VirtualMachine.activateGC();
00681 }
00682 if(localrefs.get(index+1)
00683 && locals[index+1] != -1
00684 && (locals[index+1] != b || !bref)) {
00685 VirtualMachine.activateGC();
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 if(aref)
00711 localrefs.set(index);
00712 else
00713 localrefs.clear(index);
00714
00715 if(bref)
00716 localrefs.set(index+1);
00717 else
00718 localrefs.clear(index+1);
00719
00720
00721 locals[index] = pop();
00722 locals[index+1] = pop();
00723 }
00724 public void swap() {
00725
00726
00727
00728 boolean bref = isOperandRef(); int b = xpop();
00729 boolean aref = isOperandRef(); int a = xpop();
00730 push(b); if(bref) xSetOperandRef();
00731 push(a); if(aref) xSetOperandRef();
00732
00733
00734
00735
00736
00737
00738 }
00739 int xpop() {
00740
00741 operandrefs.clear(operands.size()-1);
00742
00743 return ((Integer)operands.pop()).intValue();
00744 }
00745 public void xSetLocalVariableRef(int idx) {
00746 localrefs.set(idx);
00747 }
00748 public void xSetOperandRef() {
00749 operandrefs.set(operands.size()-1);
00750 }
00751 }