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
00020
00021 public class MethodInfo {
00022
00023
00024
00025 private String name;
00026
00027
00028
00029
00030 private String signature;
00031
00032
00033
00034
00035 private ClassInfo ci;
00036
00037
00038
00039
00040 private Instruction[] code;
00041
00042
00043
00044
00045 private ExceptionHandler[] exceptions;
00046
00047
00048
00049
00050 private int[] lineNumbers;
00051
00052
00053
00054
00055 private String[] localVariableNames;
00056
00057
00058
00059
00060 private String[] localVariableTypes;
00061
00062
00063
00064
00065 private boolean isStatic;
00066
00067
00068
00069
00070 private boolean isSynchronized;
00071
00072
00073
00074
00075 private boolean isNative;
00076
00077
00078
00079
00080 private int maxLocals;
00081
00082
00083
00084
00085 private int maxStack;
00086
00087
00088
00089
00090 private static boolean warnedLocalInfo = false;
00091
00092
00093
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
00129
00130 public int getArgumentsSize() {
00131 if(isStatic)
00132 return Types.getArgumentsSize(signature);
00133 else
00134 return Types.getArgumentsSize(signature) + 1;
00135 }
00136
00137
00138
00139 public ClassInfo getClassInfo() {
00140 return ci;
00141 }
00142
00143
00144
00145 public String getCompleteName() {
00146 return ci.getName() + "." + name + signature;
00147 }
00148 public ExceptionHandler[] getExceptions() {
00149 return exceptions;
00150 }
00151
00152
00153
00154 public String getFullName() {
00155 return name + signature;
00156 }
00157
00158
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
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
00181
00182 public Instruction[] getInstructions() {
00183 return code;
00184 }
00185
00186
00187
00188 public int getLineNumber(Instruction pc) {
00189 if(lineNumbers == null)
00190 return pc.getPosition();
00191
00192 return lineNumbers[pc.getOffset()];
00193 }
00194
00195
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
00228
00229 public String getName() {
00230 return name;
00231 }
00232
00233
00234
00235 public String getSignature() {
00236 return signature;
00237 }
00238
00239
00240
00241 public boolean isNative() {
00242 return isNative;
00243 }
00244
00245
00246
00247 public boolean isStatic() {
00248 return isStatic;
00249 }
00250
00251
00252
00253 public boolean isSynchronized() {
00254 return isSynchronized;
00255 }
00256
00257
00258
00259 public boolean isSystemMethod() {
00260 if(name.equals("<clinit>") && signature.equals("()V")) {
00261 return true;
00262 }
00263
00264
00265
00266
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
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
00300
00301
00302
00303
00304
00305 }
00306 return is;
00307 }
00308
00309
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
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
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
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
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 }