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
00015
00016
00017 import java.util.LinkedList;
00018
00019
00020
00021
00022
00023 public class StackFrame implements Constants {
00024
00025
00026
00027 private static Random random = new Random();
00028
00029
00030
00031
00032
00033 private LinkedList operands;
00034
00035
00036
00037
00038 private int[] locals;
00039
00040
00041
00042
00043 private Instruction pc;
00044
00045
00046
00047
00048 private MethodInfo mi;
00049
00050
00051
00052
00053 private BitSet oRefs;
00054
00055
00056
00057
00058 private BitSet lRefs;
00059
00060
00061
00062
00063 private StackFrame() {
00064 }
00065
00066
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
00077 oRefs = new BitSet();
00078 lRefs = new BitSet(nlocals);
00079
00080 }
00081
00082 public void clearOperandStack() {
00083 while(operands.size() != 0)
00084 pop();
00085 }
00086
00087
00088
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
00100 sf.oRefs = (BitSet)oRefs.clone();
00101 sf.lRefs = (BitSet)lRefs.clone();
00102
00103
00104 return sf;
00105 }
00106 private void deref(int v) {
00107
00108 VirtualMachine.getSS().activateGC();
00109
00110
00111
00112
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
00131
00132
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
00141
00142
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
00161
00162
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
00174
00175
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
00189 StackFrame sf = (StackFrame)object;
00190
00191
00192
00193
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
00201
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
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
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
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
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
00304
00305
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
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
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
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
00353 if(oRefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00354
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
00362 if(lRefs.get(i)) Debug.print(Debug.MESSAGE, "#");
00363
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
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
00426
00427
00428
00429
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
00442 if(oRefs.get(i))
00443 Debug.print(Debug.ERROR, "#");
00444
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
00451 if(lRefs.get(i))
00452 Debug.print(Debug.ERROR, "#");
00453
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
00484 VirtualMachine.getSS().activateGC();
00485
00486
00487
00488
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
00526
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 }