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.
19 package gov.nasa.jpf.vm;
21 import gov.nasa.jpf.JPFException;
22 import gov.nasa.jpf.jvm.bytecode.NATIVERETURN;
23 import gov.nasa.jpf.util.HashData;
24 import gov.nasa.jpf.util.Misc;
26 import java.io.PrintWriter;
27 import java.io.StringWriter;
30 * a stack frame for MJI methods
32 * This is a special Stackframe to execute NativeMethodInfos, which are just a wrapper around Java reflection
33 * calls. As required by the Java reflection API, they can store argument and return values as object references
35 * NOTE: operands and locals can be, but are not automatically used during
36 * native method execution.
38 public abstract class NativeStackFrame extends StackFrame {
41 // we don't use the operand stack or locals for arguments and return value
42 // because (1) they don't have the right representation (host VM),
43 // (2) for performance reasons (no array alloc), and (3) because there is no
44 // choice point once we enter a native method, so there is no need to do
45 // copy-on-write on the ThreadInfo callstack. Native method execution is
46 // atomic (leave alone roundtrips of course)
48 // return value registers
50 protected Object retAttr;
52 // our argument registers
53 protected Object[] args;
55 public NativeStackFrame (NativeMethodInfo mi){
59 public void setArgs (Object[] args){
64 public StackFrame clone () {
65 NativeStackFrame sf = (NativeStackFrame) super.clone();
68 sf.args = args.clone();
75 public boolean isNative() {
80 public boolean isSynthetic() {
85 public boolean modifiesState() {
86 // native stackframes don't do anything with their operands or locals per se
87 // they are executed atomically, so there is no need to ever restore them
92 public boolean hasAnyRef() {
96 public void setReturnAttr (Object a){
100 public void setReturnValue(Object r){
104 public void clearReturnValue() {
109 public Object getReturnValue() {
113 public Object getReturnAttr() {
117 public Object[] getArguments() {
122 public void markThreadRoots (Heap heap, int tid) {
123 // what if some listener creates a CG post-EXECUTENATIVE or pre-NATIVERETURN?
124 // and the native method returned an object?
125 // on the other hand, we have to make sure we don't mark a return value from
126 // a previous transition
128 if (pc instanceof NATIVERETURN){
129 if (ret != null && ret instanceof Integer && mi.isReferenceReturnType()) {
130 int ref = ((Integer) ret).intValue();
131 heap.markThreadRoot(ref, tid);
137 protected void hash (HashData hd) {
143 if (retAttr != null){
147 for (Object a : args){
153 public boolean equals (Object object) {
154 if (object == null || !(object instanceof NativeStackFrame)){
158 if (!super.equals(object)){
162 NativeStackFrame o = (NativeStackFrame)object;
167 if (retAttr != o.retAttr){
171 if (args.length != o.args.length){
175 if (!Misc.compare(args.length, args, o.args)){
183 public String toString () {
184 StringWriter sw = new StringWriter(128);
185 PrintWriter pw = new PrintWriter(sw);
187 pw.print("NativeStackFrame@");
188 pw.print(Integer.toHexString(objectHashCode()));
191 if (retAttr != null){
200 return sw.toString();
203 //--- NativeStackFrames aren't called directly and have special return value processing (in NATIVERETURN.execute())
205 public void setArgumentLocal (int idx, int value, Object attr){
206 throw new JPFException("NativeStackFrames don't support setting argument locals");
209 public void setLongArgumentLocal (int idx, long value, Object attr){
210 throw new JPFException("NativeStackFrames don't support setting argument locals");
213 public void setReferenceArgumentLocal (int idx, int ref, Object attr){
214 throw new JPFException("NativeStackFrames don't support setting argument locals");
219 public void setExceptionReference (int exRef){
220 throw new JPFException("NativeStackFrames don't support exception handlers");
224 public int getExceptionReference (){
225 throw new JPFException("NativeStackFrames don't support exception handlers");
229 public void setExceptionReferenceAttribute (Object attr){
230 throw new JPFException("NativeStackFrames don't support exception handlers");
234 public Object getExceptionReferenceAttribute (){
235 throw new JPFException("NativeStackFrames don't support exception handlers");
239 public int getResult(){
242 if (r instanceof Number){
243 if (r instanceof Double){
244 throw new JPFException("result " + ret + " can't be converted into int");
245 } else if (r instanceof Float){
246 return Float.floatToIntBits((Float)r);
248 return ((Number)r).intValue();
250 } else if (r instanceof Boolean){
251 return (r == Boolean.TRUE) ? 1 : 0;
253 throw new JPFException("result " + ret + " can't be converted into raw int value");
258 public int getReferenceResult(){
259 if (ret instanceof Integer){
260 return (Integer)ret; // MJI requires references to be returned as 'int'
262 throw new JPFException("result " + ret + " can't be converted into JPF refrence value");
267 public long getLongResult(){
269 if (r instanceof Long){
271 } else if (r instanceof Double){
272 return Double.doubleToLongBits((Double)r);
274 throw new JPFException("result " + ret + " can't be converted into raw long value");
279 public Object getResultAttr(){
283 public Object getLongResultAttr(){