//
// Copyright (C) 2005 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.jvm.bytecode;
import gov.nasa.jpf.jvm.JVM;
import gov.nasa.jpf.jvm.MethodInfo;
import gov.nasa.jpf.jvm.ThreadInfo;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.generic.InstructionHandle;
/**
* abstraction for the various return instructions
*/
public abstract class ReturnInstruction extends Instruction {
protected void init (InstructionHandle h, int o, MethodInfo m,
ConstantPool cp) {
super.init(h, o, m, cp);
isObservable |= JVM.observableReturns.contains(mi.getCompleteName());
}
abstract int storeReturnValue (ThreadInfo th);
abstract void pushReturnValue (ThreadInfo th);
protected Instruction cleanUpAndAdvance (ThreadInfo th) {
storeReturnValue(th);
// always check if we have to unlock
mi.leave(th);
if (th.wasDirectCall()) {
// return from something we called ourselves implicitly (i.e. there is
// no corresponding invoke BC in the code)
// there always has to be something on the stack, so we always have to remove
// the args and return the pc that implicitly cause the direct call
th.popFrame();
th.removeArguments(mi);
// we don't push any return value, since it wouldn't be used in the code
return th.getPC();
} else {
if (!th.popFrame()) {
// no more frames, done with this thread (hence no need for a return value push)
return null;
} else {
th.removeArguments(mi);
pushReturnValue(th);
return getNext(th);
}
}
}
}
|