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

MethodInfo.java

00001 package gov.nasa.arc.ase.jpf.jvm;
00002 
00003 import de.fub.bytecode.classfile.Code;
00004 import de.fub.bytecode.classfile.CodeException;
00005 import de.fub.bytecode.classfile.ConstantPool;
00006 import de.fub.bytecode.classfile.ExceptionTable;
00007 import de.fub.bytecode.classfile.LineNumberTable;
00008 import de.fub.bytecode.classfile.LocalVariable;
00009 import de.fub.bytecode.classfile.LocalVariableTable;
00010 import de.fub.bytecode.classfile.Method;
00011 import de.fub.bytecode.Constants;
00012 import de.fub.bytecode.generic.InstructionHandle;
00013 import de.fub.bytecode.generic.InstructionList;
00014 import gov.nasa.arc.ase.jpf.InternalErrorException;
00015 import gov.nasa.arc.ase.jpf.jvm.bytecode.Instruction;
00016 import gov.nasa.arc.ase.util.Debug;
00017 
00018 /**
00019  * Represents the information associated with a method.
00020  */
00021 public class MethodInfo {
00022   /**
00023    * Name of the method.
00024    */
00025   private String name;
00026 
00027   /**
00028    * Signature of the method.
00029    */
00030   private String signature;
00031 
00032   /**
00033    * Class the method belongs to.
00034    */
00035   private ClassInfo ci;
00036 
00037   /**
00038    * Instructions associated with the method.
00039    */
00040   private Instruction[] code;
00041   
00042   /**
00043    * Exception handlers.
00044    */
00045   private ExceptionHandler[] exceptions;
00046 
00047   /**
00048    * Table used for line numbers.
00049    */
00050   private int[] lineNumbers;
00051 
00052   /**
00053    * Local variables names.
00054    */
00055   private String[] localVariableNames;
00056 
00057   /**
00058    * Local variables types.
00059    */
00060   private String[] localVariableTypes;
00061 
00062   /**
00063    * Static method.
00064    */
00065   private boolean isStatic;
00066 
00067   /**
00068    * Synchronized method.
00069    */
00070   private boolean isSynchronized;
00071 
00072   /**
00073    * Native method.
00074    */
00075   private boolean isNative;
00076 
00077   /**
00078    * Maximum number of local variables.
00079    */
00080   private int maxLocals;
00081 
00082   /**
00083    * Maximum number of elements on the stack.
00084    */
00085   private int maxStack;
00086 
00087   /**
00088    * Used to warn about local variable information.
00089    */
00090   private static boolean warnedLocalInfo = false;
00091 
00092   /**
00093    * Creates a new method info.
00094    */
00095   public MethodInfo(Method m, ClassInfo c) {
00096     name = m.getName();
00097     signature = m.getSignature();
00098     ci = c;
00099     code = loadCode(m);
00100     exceptions = loadExceptions(m);
00101     lineNumbers = loadLineNumbers(m);
00102     localVariableNames = loadLocalVariableNames(m);
00103     localVariableTypes = loadLocalVariableTypes(m);
00104     isStatic = m.isStatic();
00105     isSynchronized = m.isSynchronized();
00106     isNative = m.isNative();
00107     maxLocals = getMaxLocals(m);
00108     maxStack = getMaxStack(m);
00109 
00110   }  
00111   public boolean canEnter(ThreadInfo th) {
00112     if(isSynchronized)
00113       if(isStatic) 
00114     return th.list.ks.sa.get(ci.getName()).canLock(th);
00115       else
00116     return th.list.ks.da.get(th.getCalleeThis(this)).canLock(th);
00117 
00118     return true;
00119   }  
00120   public void enter(ThreadInfo th) {
00121     if(isSynchronized)
00122       if(isStatic)
00123     th.list.ks.sa.get(ci.getName()).lock(th);
00124       else
00125     th.list.ks.da.get(th.getThis()).lock(th);
00126   }  
00127   /**
00128    * Returns the size of the arguments.
00129    */
00130   public int getArgumentsSize() {
00131     if(isStatic) 
00132       return Types.getArgumentsSize(signature);
00133     else
00134       return Types.getArgumentsSize(signature) + 1;
00135   }  
00136   /**
00137    * Returns the class the method belongs to.
00138    */
00139   public ClassInfo getClassInfo() {
00140     return ci;
00141   }  
00142   /**
00143    * Return the complete name of the method, including the class name.
00144    */
00145   public String getCompleteName() {
00146     return ci.getName() + "." + name + signature;
00147   }  
00148   public ExceptionHandler[] getExceptions() {
00149     return exceptions;
00150   }  
00151   /**
00152    * Returns the full name of the method, name and signature.
00153    */
00154   public String getFullName() {
00155     return name + signature;
00156   }  
00157   /**
00158    * Returns a specific instruction.
00159    */
00160   public Instruction getInstruction(int i) {
00161     if(code == null) return null;
00162 
00163     if(i < 0 || i >= code.length) return null;
00164 
00165     return code[i];
00166   }  
00167   /**
00168    * Returns the instruction at a certain position.
00169    */
00170   public Instruction getInstructionAt(int position) {
00171     if(code == null) return null;
00172 
00173     for(int i = 0, l = code.length; i < l; i++)
00174       if(code[i] != null && code[i].getPosition() == position)
00175     return code[i];
00176 
00177     throw new InternalErrorException("instruction not found");
00178   }  
00179   /**
00180    * Returns the instructions of the method.
00181    */
00182   public Instruction[] getInstructions() {
00183     return code;
00184   }  
00185   /**
00186    * Returns the line number for a given position.
00187    */
00188   public int getLineNumber(Instruction pc) {
00189     if(lineNumbers == null)
00190       return pc.getPosition();
00191 
00192     return lineNumbers[pc.getOffset()];
00193   }  
00194   /**
00195    * Returns a table to translate positions into line numbers.
00196    */
00197   public int[] getLineNumbers() {
00198     return lineNumbers;
00199   }  
00200   public String[] getLocalVariableNames() {
00201     return localVariableNames;
00202   }  
00203   public String[] getLocalVariableTypes() {
00204     return localVariableTypes;
00205   }  
00206   public int getMaxLocals() {
00207     return maxLocals;
00208   }  
00209   public static int getMaxLocals(Method m) {
00210     Code c = m.getCode();
00211 
00212     if(c == null) return 0;
00213 
00214     return c.getMaxLocals();
00215   }  
00216   public int getMaxStack() {
00217     return maxStack;
00218   }  
00219   public static int getMaxStack(Method m) {
00220     Code c = m.getCode();
00221 
00222     if(c == null) return 0;
00223 
00224     return c.getMaxStack();
00225   }  
00226   /**
00227    * Returns the name of the method.
00228    */
00229   public String getName() {
00230     return name;
00231   }  
00232   /**
00233    * Returns the signature of the method.
00234    */
00235   public String getSignature() {
00236     return signature;
00237   }  
00238   /**
00239    * Returns true if the field is native.
00240    */
00241   public boolean isNative() {
00242     return isNative;
00243   }  
00244   /**
00245    * Returns true if the field is static.
00246    */
00247   public boolean isStatic() {
00248     return isStatic;
00249   }  
00250   /**
00251    * Returns true if the field is synchronized.
00252    */
00253   public boolean isSynchronized() {
00254     return isSynchronized;
00255   }  
00256   /**
00257    * Returns true if the method is a system method.
00258    */
00259   public boolean isSystemMethod() {
00260     if(name.equals("<clinit>") && signature.equals("()V")) {
00261       return true;
00262     }
00263 
00264     /************************************************************\
00265     if(VirtualMachine.options.atomic_init && name.equals("<init>")) {
00266       return true;
00267     }
00268     \************************************************************/
00269 
00270     if(ci.isSystemClass())
00271       return true;
00272 
00273     return false;
00274   }  
00275   public void leave(ThreadInfo th) {
00276     if(isSynchronized)
00277       if(isStatic)
00278     th.list.ks.sa.get(ci.getName()).unlock(th);
00279       else
00280     th.list.ks.da.get(th.getThis()).unlock(th);
00281   }  
00282   /**
00283    * Loads the code of the method.
00284    */
00285   private Instruction[] loadCode(Method m) {
00286     Code c = m.getCode();
00287 
00288     if(c == null) return null;
00289 
00290     InstructionList il = new InstructionList(c.getCode());
00291 
00292     InstructionHandle[] hs = il.getInstructionHandles();
00293     int length = hs.length;
00294 
00295     Instruction[] is = new Instruction[length];
00296 
00297     for(int i = 0; i < length; i++) {
00298       is[i] = Instruction.create(hs[i], i, this, m.getConstantPool());
00299 //#ifdef COVERAGE
00300 
00301 
00302 
00303 
00304 //#endif COVERAGE
00305     }
00306     return is;
00307   }  
00308   /**
00309    * Returns the exceptions of the method.
00310    */
00311   private ExceptionHandler[] loadExceptions(Method m) {
00312     Code c = m.getCode();
00313     if(c == null) return null;
00314 
00315     CodeException[] ce = c.getExceptionTable();
00316     if(ce.length == 0) return null;
00317 
00318     int length = ce.length;
00319     ExceptionHandler[] eh = new ExceptionHandler[length];
00320 
00321     ConstantPool cp = m.getConstantPool();
00322 
00323     for(int i = 0; i < length; i++) {
00324       int ct = ce[i].getCatchType();
00325       eh[i] = new ExceptionHandler(
00326       (ct == 0 ?
00327        null :
00328        cp.getConstantString(ct, Constants.CONSTANT_Class).replace('/', '.')
00329       ),
00330       ce[i].getStartPC(),
00331       ce[i].getEndPC(),
00332       ce[i].getHandlerPC());
00333     }
00334 
00335     return eh;
00336   }  
00337   /**
00338    * Loads the line numbers for the method.
00339    */
00340   private int[] loadLineNumbers(Method m) {
00341     Code c = m.getCode();
00342 
00343     if(c == null) return null;
00344 
00345     LineNumberTable lnt = c.getLineNumberTable();
00346 
00347     int length = code.length;
00348     int[] ln = new int[length];
00349 
00350     if(lnt == null)
00351       // no line information
00352       return null;
00353     else
00354       for(int i = 0; i < length; i++)
00355     ln[i] = lnt.getSourceLine(code[i].getPosition());
00356 
00357     return ln;
00358   }  
00359   /**
00360    * Loads the names of the local variables.
00361    */
00362   private String[] loadLocalVariableNames(Method m) {
00363     Code c = m.getCode();
00364     
00365     if(c == null) return null;
00366 
00367     LocalVariableTable lvt = c.getLocalVariableTable();
00368 
00369     if(lvt == null) {
00370       if(!warnedLocalInfo && !ci.isSystemClass()) {
00371     Debug.println(Debug.WARNING);
00372     Debug.println(Debug.WARNING, "No local variable information available");
00373     Debug.println(Debug.WARNING, "for " + getCompleteName());
00374     Debug.println(Debug.WARNING, "Recompile with -g to include this information");
00375     Debug.println(Debug.WARNING);
00376     warnedLocalInfo = true;
00377       }
00378       return null;
00379     }
00380 
00381     LocalVariable[] lv = lvt.getLocalVariableTable();
00382 
00383     int length = lv.length;
00384     String[] lvn = new String[length];
00385 
00386     for(int i = 0; i < length; i++)
00387       lvn[i] = lv[i].getName();
00388 
00389     return lvn;
00390   }  
00391   /**
00392    * Loads the types of the local variables.
00393    */
00394   private String[] loadLocalVariableTypes(Method m) {
00395     Code c = m.getCode();
00396     
00397     if(c == null) return null;
00398 
00399     LocalVariableTable lvt = c.getLocalVariableTable();
00400 
00401     if(lvt == null) {
00402       if(!warnedLocalInfo && !ci.isSystemClass()) {
00403     Debug.println(Debug.WARNING, "No local variable information available");
00404     Debug.println(Debug.WARNING, "for " + getCompleteName());
00405     Debug.println(Debug.WARNING, "Recompile with -g to include this information");
00406     Debug.println(Debug.WARNING);
00407     warnedLocalInfo = true;
00408       }
00409       return null;
00410     }
00411 
00412     LocalVariable[] lv = lvt.getLocalVariableTable();
00413     int length = lv.length;
00414     String[] lvn = new String[length];
00415 
00416     for(int i = 0; i < length; i++)
00417       lvn[i] = lv[i].getSignature();
00418 
00419     return lvn;
00420   }  
00421 }

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