2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.jvm.bytecode;
20 import gov.nasa.jpf.vm.Instruction;
21 import gov.nasa.jpf.vm.ElementInfo;
22 import gov.nasa.jpf.vm.StackFrame;
23 import gov.nasa.jpf.vm.ThreadInfo;
24 import gov.nasa.jpf.vm.bytecode.ReturnInstruction;
26 import java.util.Iterator;
30 * abstraction for the various return instructions
32 public abstract class JVMReturnInstruction extends ReturnInstruction implements JVMInstruction {
34 // to store where we came from
35 protected StackFrame returnFrame;
37 abstract public int getReturnTypeSize();
38 abstract protected Object getReturnedOperandAttr(StackFrame frame);
40 // note these are only callable from within the same enter - thread interleavings
42 abstract protected void getAndSaveReturnValue (StackFrame frame);
43 abstract protected void pushReturnValue (StackFrame frame);
45 public abstract Object getReturnValue(ThreadInfo ti);
47 public StackFrame getReturnFrame() {
51 public void setReturnFrame(StackFrame frame){
56 * this is important since keeping the StackFrame alive would be a major
60 public void cleanupTransients(){
64 //--- attribute accessors
66 // the accessors are here to save the client some effort regarding the
67 // return type (slot size).
68 // Since these are all public methods that can be called by listeners,
69 // we stick to the ThreadInfo argument
71 public boolean hasReturnAttr (ThreadInfo ti){
72 StackFrame frame = ti.getTopFrame();
73 return frame.hasOperandAttr();
75 public boolean hasReturnAttr (ThreadInfo ti, Class<?> type){
76 StackFrame frame = ti.getTopFrame();
77 return frame.hasOperandAttr(type);
81 * this returns all of them - use either if you know there will be only
82 * one attribute at a time, or check/process result with ObjectList
84 * obviously, this only makes sense from an instructionExecuted(), since
85 * the value is pushed during the enter(). Use ObjectList to access values
87 public Object getReturnAttr (ThreadInfo ti){
88 StackFrame frame = ti.getTopFrame();
89 return frame.getOperandAttr();
93 * this replaces all of them - use only if you know
94 * - there will be only one attribute at a time
95 * - you obtained the value you set by a previous getXAttr()
96 * - you constructed a multi value list with ObjectList.createList()
98 * we don't clone since pushing a return value already changed the caller frame
100 public void setReturnAttr (ThreadInfo ti, Object a){
101 StackFrame frame = ti.getModifiableTopFrame();
102 frame.setOperandAttr(a);
105 public void addReturnAttr (ThreadInfo ti, Object attr){
106 StackFrame frame = ti.getModifiableTopFrame();
107 frame.addOperandAttr(attr);
111 * this only returns the first attr of this type, there can be more
112 * if you don't use client private types or the provided type is too general
114 public <T> T getReturnAttr (ThreadInfo ti, Class<T> type){
115 StackFrame frame = ti.getTopFrame();
116 return frame.getOperandAttr(type);
118 public <T> T getNextReturnAttr (ThreadInfo ti, Class<T> type, Object prev){
119 StackFrame frame = ti.getTopFrame();
120 return frame.getNextOperandAttr(type, prev);
122 public Iterator<?> returnAttrIterator (ThreadInfo ti){
123 StackFrame frame = ti.getTopFrame();
124 return frame.operandAttrIterator();
126 public <T> Iterator<T> returnAttrIterator (ThreadInfo ti, Class<T> type){
127 StackFrame frame = ti.getTopFrame();
128 return frame.operandAttrIterator(type);
131 // -- end attribute accessors --
134 public Instruction execute (ThreadInfo ti) {
135 boolean didUnblock = false;
137 if (!ti.isFirstStepInsn()) {
138 didUnblock = ti.leave(); // takes care of unlocking before potentially creating a CG
141 if (mi.isSynchronized()) {
142 int objref = mi.isStatic() ? mi.getClassInfo().getClassObjectRef() : ti.getThis();
143 ElementInfo ei = ti.getElementInfo(objref);
145 if (ei.getLockCount() == 0) {
146 if (ti.getScheduler().setsLockReleaseCG(ti, ei, didUnblock)){
152 StackFrame frame = ti.getModifiableTopFrame();
154 Object attr = getReturnedOperandAttr(frame); // the return attr - get this before we pop
155 getAndSaveReturnValue(frame);
157 // note that this is never the first frame, since we start all threads (incl. main)
158 // through a direct call
159 frame = ti.popAndGetModifiableTopFrame();
161 // remove args, push return value and continue with next insn
162 // (DirectCallStackFrames don't use this)
163 frame.removeArguments(mi);
164 pushReturnValue(frame);
167 setReturnAttr(ti, attr);
170 return frame.getPC().getNext();
174 public void accept(JVMInstructionVisitor insVisitor) {
175 insVisitor.visit(this);
179 public String toPostExecString() {
180 return getMnemonic() + " [" + mi.getFullName() + ']';