Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

StackFrame.java

00001 package gov.nasa.arc.ase.jpf.jvm;
00002 
00003 import de.fub.bytecode.Constants;
00004 import gov.nasa.arc.ase.jpf.Engine;
00005 import gov.nasa.arc.ase.jpf.InternalErrorException;
00006 import de.fub.bytecode.generic.ConstantPoolGen;
00007 import de.fub.bytecode.generic.LocalVariableGen;
00008 import gov.nasa.arc.ase.jpf.jvm.bytecode.ATHROW;
00009 import gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction;
00010 import gov.nasa.arc.ase.util.Debug;
00011 import gov.nasa.arc.ase.util.HashData;
00012 import java.util.BitSet;
00013 import java.util.Random;
00014 //#ifdef JDK11
00015 
00016 //#else JDK11
00017 import java.util.LinkedList;
00018 //#endif JDK11
00019 
00020 /**
00021  * Describes a stack frame.
00022  */
00023 public class StackFrame implements Constants {
00024   /**
00025    * Used for random choices.
00026    */
00027   private static Random random = new Random();
00028 
00029   /**
00030    * Stores the operand stack.
00031    */
00032   //** warning: should be implemented as an array.          **//
00033   private LinkedList operands;
00034 
00035   /**
00036    * Local variables.
00037    */
00038   private int[] locals;
00039 
00040   /**
00041    * Program counter.
00042    */
00043   private Instruction pc;
00044 
00045   /**
00046    * Method being executed.
00047    */
00048   private MethodInfo mi;
00049 
00050   /**
00051    * Flags saying which operands are references.
00052    */
00053   private BitSet oRefs;
00054 
00055   /**
00056    * Flags saying which local variables are references.
00057    */
00058   private BitSet lRefs;
00059 
00060   /**
00061    * Creates an empty stack frame. Used by clone.
00062    */
00063   private StackFrame() {
00064   }  
00065   /**
00066    * Creates a new stack frame for a method.
00067    */
00068   public StackFrame(MethodInfo m) {
00069     mi = m;
00070     pc = mi.getInstruction(0);
00071     operands = new LinkedList();
00072 
00073     int nlocals = (pc == null) ? mi.getArgumentsSize() : mi.getMaxLocals();
00074     locals = new int[nlocals];
00075 
00076 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00077     oRefs = new BitSet();
00078     lRefs = new BitSet(nlocals);
00079 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00080   }  
00081   // stack operations
00082   public void clearOperandStack() {
00083     while(operands.size() != 0)
00084       pop();
00085   }  
00086   // functions to handle exceptions
00087 
00088   // creates a clone of the stack frame
00089   public Object clone() {
00090     StackFrame sf = new StackFrame();
00091 
00092     sf.operands = new LinkedList();
00093     for(int i = 0; i < operands.size(); i++)
00094       sf.operands.addLast(operands.get(i));
00095     sf.locals = new int[locals.length];
00096     System.arraycopy(locals, 0, sf.locals, 0, locals.length);
00097     sf.pc = pc;
00098     sf.mi = mi;
00099 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00100     sf.oRefs = (BitSet)oRefs.clone();
00101     sf.lRefs = (BitSet)lRefs.clone();
00102 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00103 
00104     return sf;
00105   }  
00106   private void deref(int v) {
00107 //#ifdef MARK_N_SWEEP
00108     VirtualMachine.getSS().activateGC();
00109 //#endif MARK_N_SWEEP
00110 //#ifdef REFERENCE_COUNT
00111 
00112 //#endif REFERENCE_COUNT
00113   }  
00114   private void derefLocal(int idx) {
00115     if(!lRefs.get(idx)) return;
00116 
00117     deref(locals[idx]);
00118   }  
00119   private void derefStack() {
00120     if(!oRefs.get(operands.size()-1)) return;
00121 
00122     deref(peek());
00123   }  
00124   public void dup() {
00125     boolean ref = isOperandRef(); int v =  pop();
00126     push(v, ref);
00127     push(v, ref);
00128   }  
00129   public void dup_x1() {
00130     // what it does on the stack is:
00131     // (top) A B ... => (top) B A B ...
00132     // often used to translate post increment/decremente operators
00133     boolean bref = isOperandRef(); int b = pop();
00134     boolean aref = isOperandRef(); int a = pop();
00135     push(b, bref);
00136     push(a, aref);
00137     push(b, bref);
00138   }  
00139   public void dup_x2() {
00140     // what it does on the stack is:
00141     // (top) A B C ... => (top) C A B C ...
00142     // often used to translate post increment/decremente operators
00143     boolean cref = isOperandRef(); int c = pop();
00144     boolean bref = isOperandRef(); int b = pop();
00145     boolean aref = isOperandRef(); int a = pop();
00146     push(c, cref);
00147     push(a, aref);
00148     push(b, bref);
00149     push(c, cref);
00150   }  
00151   public void dup2() {
00152     boolean bref = isOperandRef(); int b = pop();
00153     boolean aref = isOperandRef(); int a = pop();
00154     push(a, aref);
00155     push(b, bref);
00156     push(a, aref);
00157     push(b, bref);
00158   }  
00159   public void dup2_x1() {
00160     // what it does on the stack is:
00161     // (top) A B C ... => (top) B C A B C ...
00162     // often used to translate post increment/decremente operators
00163     boolean cref = isOperandRef(); int c = pop();
00164     boolean bref = isOperandRef(); int b = pop();
00165     boolean aref = isOperandRef(); int a = pop();
00166     push(b, bref);
00167     push(c, cref);
00168     push(a, aref);
00169     push(b, bref);
00170     push(c, cref);
00171   }  
00172   public void dup2_x2() {
00173     // what it does on the stack is:
00174     // (top) A B C D ... => (top) C D A B C D ...
00175     // often used to translate post increment/decremente operators
00176     boolean dref = isOperandRef(); int d = pop();
00177     boolean cref = isOperandRef(); int c = pop();
00178     boolean bref = isOperandRef(); int b = pop();
00179     boolean aref = isOperandRef(); int a = pop();
00180     push(c, cref);
00181     push(d, dref);
00182     push(a, aref);
00183     push(b, bref);
00184     push(c, cref);
00185     push(d, dref);
00186   }  
00187   public boolean equals(Object object) {
00188     // casts to stack frame
00189     StackFrame sf = (StackFrame)object;
00190 
00191     // compares the program counter REFERENCES
00192     // the code is statically read into the vm so the same
00193     // chunk of code means the same reference
00194     if (pc != sf.pc) return false;
00195     if (mi != sf.mi) return false;
00196     
00197     if (!lRefs.equals(sf.lRefs)) return false;
00198     if (!oRefs.equals(sf.oRefs)) return false;
00199 
00200     // we are going to compare
00201     // the local variables and the operand stack
00202     int[] l = sf.locals;
00203     int nlocals = locals.length;
00204 
00205     if (nlocals != l.length) return false;
00206     for (int idx = 0; idx < nlocals; idx++)
00207       if(locals[idx] != l[idx]) return false;
00208 
00209     LinkedList o = sf.operands;
00210     int noperands = operands.size();
00211 
00212     if (noperands != o.size()) return false;
00213     for (int idx = 0; idx < noperands; idx++)
00214       if (!operands.get(idx).equals(o.get(idx)))
00215     return false;
00216 
00217     return true;
00218   }  
00219   public int getCalleeThis(int size) {
00220     return ((Integer)operands.get(operands.size() - size)).intValue();
00221   }  
00222   // operations on local variables
00223   public int getCalleeThis(MethodInfo mi) {
00224     return ((Integer)operands.get(operands.size() - mi.getArgumentsSize())).intValue();
00225   }  
00226   public ClassInfo getClassInfo() {
00227     return mi.getClassInfo();
00228   }  
00229   // gets and sets some derived information
00230   public int getLine() {
00231     return mi.getLineNumber(pc);
00232   }  
00233   public int getLocalVariable(int i) {
00234     return locals[i];
00235   }  
00236   public int getLocalVariable(String name) {
00237     return getLocalVariable(getLocalVariableOffset(name));
00238   }  
00239   // return the value of a variable given the name
00240   private int getLocalVariableOffset(String name) {
00241     String[] lNames = mi.getLocalVariableNames();
00242     String[] lTypes = mi.getLocalVariableTypes();
00243 
00244     int offset = 0;
00245     for(int i = 0, l = lNames.length; i < l; i++)
00246       if(name.equals(lNames[i]))
00247     return offset;
00248       else
00249     offset += Types.getTypeSize(lTypes[i]);
00250 
00251     throw new InternalErrorException("Local variable not found");
00252   }  
00253   public int[] getLocalVariables() {
00254     return locals;
00255   }  
00256   public String getLocalVariableType(String name) {
00257     String[] lNames = mi.getLocalVariableNames();
00258     String[] lTypes = mi.getLocalVariableTypes();
00259 
00260     if(lNames != null && lTypes != null)
00261       for(int i = 0, l = lNames.length; i < l; i++)
00262     if(name.equals(lNames[i]))
00263       return lTypes[i];
00264 
00265     throw new InternalErrorException("Local variable not found");
00266   }  
00267   public long getLongLocalVariable(int i) {
00268     return Types.intsToLong(locals[i+1], locals[i]);
00269   }  
00270   public long getLongLocalVariable(String name) {
00271     return getLongLocalVariable(getLocalVariableOffset(name));
00272   }  
00273   public MethodInfo getMethodInfo() {
00274     return mi;
00275   }  
00276   public String getMethodName() {
00277     return mi.getName();
00278   }  
00279   public Instruction getPC() {
00280     return pc;
00281   }  
00282   public int getThis() {
00283     if(locals.length == 0) return -1;
00284 
00285     return locals[0];
00286   }  
00287 //#ifdef MARK_N_SWEEP
00288   public boolean hasAnyRef() {
00289     for(int i = 0, l = oRefs.size(); i < l; i++)
00290       if(oRefs.get(i)) return true;
00291     for(int i = 0, l = locals.length; i < l; i++)
00292       if(lRefs.get(i)) return true;
00293 
00294     return false;
00295   }  
00296   public void hash(HashData hd) {
00297     for(int i = 0, l = locals.length; i < l; i++)
00298       hd.add(locals[i]);
00299 
00300     for(int i = 0, l = operands.size(); i < l; i++)
00301       hd.add(((Integer)operands.get(i)).intValue());
00302   }  
00303   // computes an hash code for the hash table
00304   // the default hash code is different for each object
00305   // we need to redifine it to make the hash table work
00306   public int hashCode() {
00307     HashData hd = new HashData();
00308 
00309     hash(hd);
00310 
00311     return hd.getValue();
00312   }  
00313   public boolean isLocalVariableRef(int idx) {
00314     return lRefs.get(idx);
00315   }  
00316   public boolean isOperandRef() {
00317     return oRefs.get(operands.size()-1);
00318   }  
00319 //#endif MARK_N_SWEEP
00320 
00321   public boolean isOperandRef(int idx) {
00322     return oRefs.get(operands.size()-idx-1);
00323   }  
00324   public boolean isSafe() {
00325     return mi.getClassInfo().isSafe(getLine());
00326   }  
00327   public boolean isSystemMethod() {
00328     return mi.isSystemMethod();
00329   }  
00330 //#endif MARK_N_SWEEP
00331 
00332 //#ifdef REFERENCE_COUNT
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 //#endif REFERENCE_COUNT
00346 
00347   public void log(int id) {
00348     Debug.print(Debug.MESSAGE, "  SF#" + id + " S(");
00349     for(int i = 0; i < operands.size(); i++) {
00350       int j = ((Integer)operands.get(i)).intValue();
00351       Debug.print(Debug.MESSAGE, " ");
00352 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00353       if(oRefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00354 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00355       Debug.print(Debug.MESSAGE, j + "");
00356     }
00357     Debug.print(Debug.MESSAGE, " ) L(");
00358     for(int i = 0; i < locals.length; i++) {
00359       int j = locals[i];
00360       Debug.print(Debug.MESSAGE, " ");
00361 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00362       if(lRefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00363 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00364       Debug.print(Debug.MESSAGE, j + "");
00365     }
00366     Debug.print(Debug.MESSAGE, " ) ");
00367     if(mi == null)
00368       Debug.print(Debug.MESSAGE, "null");
00369     else
00370       Debug.print(Debug.MESSAGE, mi.getCompleteName());
00371     Debug.print(Debug.MESSAGE, ":");
00372     if(pc == null)
00373       Debug.println(Debug.MESSAGE, "null");
00374     else
00375       Debug.println(Debug.MESSAGE, pc.getPosition() + "  " + pc);
00376   }  
00377   long longPeek() {
00378     int lo = ((Integer)operands.getLast()).intValue();
00379     int hi = ((Integer)operands.get(operands.size() - 2)).intValue();
00380 
00381     return Types.intsToLong(lo, hi);
00382   }  
00383   long longPeek(int n) {
00384     int lo = ((Integer)operands.get(operands.size() - 1 - n)).intValue();
00385     int hi = ((Integer)operands.get(operands.size() - 2 - n)).intValue();
00386 
00387     return Types.intsToLong(lo, hi);
00388   }  
00389   long longPop() {
00390     int lo = pop();
00391     int hi = pop();
00392 
00393     return Types.intsToLong(lo, hi);
00394   }  
00395   void longPush(long v) {
00396     push(Types.hiLong(v), false);
00397     push(Types.loLong(v), false);
00398   }  
00399 //#ifdef MARK_N_SWEEP
00400   public void mark(DynamicArea da) {
00401     for(int i = 0, l = operands.size(); i < l; i++)
00402       if(oRefs.get(i))
00403     da.mark(((Integer)operands.get(i)).intValue());
00404 
00405     for(int i = 0, l = locals.length; i < l; i++)
00406       if(lRefs.get(i))
00407     da.mark(locals[i]);
00408   }  
00409   int peek() {
00410     return ((Integer)operands.getLast()).intValue();
00411   }  
00412   int peek(int n) {
00413     return ((Integer)operands.get(operands.size() - 1 - n)).intValue();
00414   }  
00415   int pop() {
00416     if(isOperandRef())
00417       derefStack();
00418 
00419     return ((Integer)operands.removeLast()).intValue();
00420   }  
00421   void pop(int n) {
00422     for(int i = 0; i < n; i++)
00423       pop();
00424   }  
00425 //#ifdef DISTRIBUTED
00426 
00427 
00428 
00429 //#endif DISTRIBUTED
00430 
00431   public void printStackContent() {
00432     Debug.print(Debug.ERROR, "\tat ");
00433     Debug.print(Debug.ERROR, mi.getCompleteName());
00434     if(pc != null)
00435       Debug.println(Debug.ERROR, ":" + pc.getPosition());
00436     else
00437       Debug.println(Debug.ERROR);
00438     Debug.println(Debug.ERROR, "\t  Operand stack is:");
00439     for(int i = 0, l = operands.size(); i < l; i++) {
00440       Debug.print(Debug.ERROR, "\t    ");
00441 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00442       if(oRefs.get(i))
00443     Debug.print(Debug.ERROR, "#");
00444 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00445       Debug.println(Debug.ERROR, operands.get(i));
00446     }
00447     Debug.println(Debug.ERROR, "\t  Local variables are:");
00448     for(int i = 0, l = locals.length; i < l; i++) {
00449       Debug.print(Debug.ERROR, "\t    ");
00450 //#ifdef MARK_N_SWEEP || REFERENCE_COUNT
00451       if(lRefs.get(i))
00452     Debug.print(Debug.ERROR, "#");
00453 //#endif MARK_N_SWEEP || REFERENCE_COUNT
00454       Debug.println(Debug.ERROR, ""+locals[i]);
00455     }
00456   }  
00457   public void printStackTrace() {
00458     Debug.print(Debug.ERROR, "\tat ");
00459     Debug.print(Debug.ERROR, mi.getClassInfo().getName());
00460     Debug.print(Debug.ERROR, ".");
00461     Debug.print(Debug.ERROR, mi.getName());
00462     if(pc != null) {
00463       Debug.print(Debug.ERROR, "(");
00464       Debug.print(Debug.ERROR, mi.getClassInfo().getSourceFileName());
00465       Debug.print(Debug.ERROR, ":");
00466       Debug.println(Debug.ERROR, getLine() + ")");
00467     } else
00468       Debug.println(Debug.ERROR, "(Native Method)");
00469   }  
00470   void push(int v, boolean ref) {
00471     operands.addLast(new Integer(v));
00472 
00473     if(ref)
00474       oRefs.set(operands.size()-1);
00475     else
00476       oRefs.clear(operands.size()-1);
00477 
00478     refStack();
00479   }  
00480   private void ref(int v) {
00481     if(v == -1) return;
00482     
00483 //#ifdef MARK_N_SWEEP
00484     VirtualMachine.getSS().activateGC();
00485 //#endif MARK_N_SWEEP
00486 //#ifdef REFERENCE_COUNT
00487 
00488 //#endif REFERENCE_COUNT
00489   }  
00490   private void refLocal(int idx) {
00491     if(!lRefs.get(idx)) return;
00492     ref(locals[idx]);
00493   }  
00494   private void refStack() {
00495     if(!oRefs.get(operands.size()-1)) return;
00496 
00497     ref(peek());
00498   }  
00499   public void setLocalVariable(int index, int v, boolean ref) {
00500     derefLocal(index);
00501 
00502     locals[index] = v;
00503 
00504     if(ref)
00505       lRefs.set(index);
00506     else
00507       lRefs.clear(index);
00508 
00509     refLocal(index);
00510   }  
00511   public void setLongLocalVariable(int index, long v) {
00512     derefLocal(index);
00513     derefLocal(index+1);
00514 
00515     locals[index+1] = Types.loLong(v);
00516     locals[index] = Types.hiLong(v);
00517 
00518     lRefs.clear(index);
00519     lRefs.clear(index);
00520   }  
00521   public void setPC(Instruction newpc) {
00522     pc = newpc;
00523   }  
00524   public void swap() {
00525     // what it does on the stack is:
00526     // (top) A B ... => (top) B A ...
00527     boolean bref = isOperandRef(); int b = pop();
00528     boolean aref = isOperandRef(); int a = pop();
00529     push(b, bref);
00530     push(a, aref);
00531   }  
00532   public String toString() {
00533     StringBuffer sb = new StringBuffer();
00534 
00535     sb.append("StackFrame(");
00536     sb.append("operands=");
00537     sb.append('[');
00538     for(int i = 0; i < operands.size(); i++) {
00539       if(i != 0)
00540     sb.append(',');
00541       sb.append(operands.get(i));
00542     }
00543     sb.append(']');
00544     sb.append(',');
00545     sb.append("locals=");
00546     sb.append('[');
00547     for(int i = 0; i < locals.length; i++) {
00548       if(i != 0)
00549     sb.append(',');
00550       sb.append(locals[i]);
00551     }
00552     sb.append(']');
00553     sb.append(',');
00554     sb.append("pc=");
00555     sb.append(pc.getPosition());
00556     sb.append(',');
00557     sb.append("oRefs=");
00558     for(int i = 0; i < operands.size(); i++) {
00559       sb.append(oRefs.get(i) ? 'R' : '-');
00560     }
00561     sb.append(',');
00562     sb.append("lRefs=");
00563     for(int i = 0; i < locals.length; i++) {
00564       sb.append(lRefs.get(i) ? 'R' : '-');
00565     }
00566     sb.append(')');
00567 
00568     return sb.toString();
00569   }  
00570 }

Generated at Thu Feb 7 06:55:36 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001