001: //
002: // Copyright (C) 2005 United States Government as represented by the
003: // Administrator of the National Aeronautics and Space Administration
004: // (NASA). All Rights Reserved.
005: //
006: // This software is distributed under the NASA Open Source Agreement
007: // (NOSA), version 1.3. The NOSA has been approved by the Open Source
008: // Initiative. See the file NOSA-1.3-JPF at the top of the distribution
009: // directory tree for the complete NOSA document.
010: //
011: // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
012: // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
013: // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
014: // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
015: // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
016: // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
017: // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
018: //
019: package gov.nasa.jpf.jvm.bytecode;
020:
021: import gov.nasa.jpf.jvm.ClassInfo;
022: import gov.nasa.jpf.jvm.KernelState;
023: import gov.nasa.jpf.jvm.MethodInfo;
024: import gov.nasa.jpf.jvm.SystemState;
025: import gov.nasa.jpf.jvm.ThreadInfo;
026:
027: /**
028: * a base class for virtual call instructions
029: */
030: public abstract class VirtualInvocation extends InvokeInstruction {
031:
032: protected VirtualInvocation() {
033: }
034:
035: protected VirtualInvocation(MethodInfo mi, String cname,
036: String mname, String signature, int offset, int position) {
037: super (mi, cname, mname, signature, offset, position);
038: }
039:
040: public boolean isDeterministic(SystemState ss, KernelState ks,
041: ThreadInfo ti) {
042: int objRef = getCalleeThis(ti);
043: MethodInfo mi = getInvokedMethod(ks, objRef);
044:
045: if ((objRef == -1) || (mi == null)) {
046: return true; // doesn't really matter, just make sure we execute
047: }
048:
049: return mi.isDeterministic(ti);
050: }
051:
052: public boolean isExecutable(SystemState ss, KernelState ks,
053: ThreadInfo ti) {
054: int objRef = getCalleeThis(ti);
055: MethodInfo mi = getInvokedMethod(ks, objRef);
056:
057: if ((objRef == -1) || (mi == null)) {
058: return true; // make sure we execute so that we get the exception
059: }
060:
061: return mi.isExecutable(ti);
062: }
063:
064: public Instruction execute(SystemState ss, KernelState ks,
065: ThreadInfo ti) {
066: int objRef = getCalleeThis(ti);
067:
068: if (objRef == -1) { // NPE
069: return ti.createAndThrowException(
070: "java.lang.NullPointerException", "calling '"
071: + mname + "' on null object");
072: }
073:
074: MethodInfo mi = getInvokedMethod(ks, objRef);
075: if (mi == null) {
076: return ti.createAndThrowException(
077: "java.lang.NoSuchMethodException",
078: getCalleeClassInfo(ks, objRef).getName() + "."
079: + mname);
080: }
081:
082: return mi.execute(ti, false);
083: }
084:
085: int getCalleeThis(ThreadInfo ti) {
086: return ti.getCalleeThis(getArgSize());
087: }
088:
089: ClassInfo getCalleeClassInfo(KernelState ks, int objRef) {
090: return ks.da.get(objRef).getClassInfo();
091: }
092:
093: /**
094: * cache the actual callee class MethodInfo
095: */
096: MethodInfo getInvokedMethod(KernelState ks, int objRef) {
097: if (objRef != -1) {
098:
099: // <?> - can this be ambiguous? probably yes if we had a backtrace
100: // with different heap state where the heap symmetry didn't work
101: if (lastObj != objRef) { // it's good we are not multithreaded
102:
103: ClassInfo mci = getCalleeClassInfo(ks, objRef);
104: invokedMethod = mci.getMethod(mname, true);
105:
106: // here we could catch the NoSuchMethodError
107: if (invokedMethod == null) {
108: lastObj = -1;
109: } else {
110: lastObj = objRef;
111: }
112: }
113: } else {
114: lastObj = -1;
115: }
116:
117: return invokedMethod;
118: }
119:
120: public boolean isSchedulingRelevant(SystemState ss, KernelState ks,
121: ThreadInfo ti) {
122:
123: // if it's not synchronized, we can just go on
124: int objRef = getCalleeThis(ti);
125: MethodInfo mi = getInvokedMethod(ks, objRef);
126:
127: if ((objRef == -1) || (mi == null)) {
128: return false; // we are going to have an exception, force
129: }
130:
131: return mi.isSchedulingRelevant(ti, ks.da.get(objRef));
132: }
133: }
|