comparison src/main/gov/nasa/jpf/vm/NativeStackFrame.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
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
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
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.
17 */
18
19 package gov.nasa.jpf.vm;
20
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;
25
26 import java.io.PrintWriter;
27 import java.io.StringWriter;
28
29 /**
30 * a stack frame for MJI methods
31 *
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
34 *
35 * NOTE: operands and locals can be, but are not automatically used during
36 * native method execution.
37 */
38 public abstract class NativeStackFrame extends StackFrame {
39
40
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)
47
48 // return value registers
49 protected Object ret;
50 protected Object retAttr;
51
52 // our argument registers
53 protected Object[] args;
54
55 public NativeStackFrame (NativeMethodInfo mi){
56 super( mi, 0, 0);
57 }
58
59 public void setArgs (Object[] args){
60 this.args = args;
61 }
62
63 @Override
64 public StackFrame clone () {
65 NativeStackFrame sf = (NativeStackFrame) super.clone();
66
67 if (args != null) {
68 sf.args = args.clone();
69 }
70
71 return sf;
72 }
73
74 @Override
75 public boolean isNative() {
76 return true;
77 }
78
79 @Override
80 public boolean isSynthetic() {
81 return true;
82 }
83
84 @Override
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
88 return false;
89 }
90
91 @Override
92 public boolean hasAnyRef() {
93 return false;
94 }
95
96 public void setReturnAttr (Object a){
97 retAttr = a;
98 }
99
100 public void setReturnValue(Object r){
101 ret = r;
102 }
103
104 public void clearReturnValue() {
105 ret = null;
106 retAttr = null;
107 }
108
109 public Object getReturnValue() {
110 return ret;
111 }
112
113 public Object getReturnAttr() {
114 return retAttr;
115 }
116
117 public Object[] getArguments() {
118 return args;
119 }
120
121 @Override
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
127
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);
132 }
133 }
134 }
135
136 @Override
137 protected void hash (HashData hd) {
138 super.hash(hd);
139
140 if (ret != null){
141 hd.add(ret);
142 }
143 if (retAttr != null){
144 hd.add(retAttr);
145 }
146
147 for (Object a : args){
148 hd.add(a);
149 }
150 }
151
152 @Override
153 public boolean equals (Object object) {
154 if (object == null || !(object instanceof NativeStackFrame)){
155 return false;
156 }
157
158 if (!super.equals(object)){
159 return false;
160 }
161
162 NativeStackFrame o = (NativeStackFrame)object;
163
164 if (ret != o.ret){
165 return false;
166 }
167 if (retAttr != o.retAttr){
168 return false;
169 }
170
171 if (args.length != o.args.length){
172 return false;
173 }
174
175 if (!Misc.compare(args.length, args, o.args)){
176 return false;
177 }
178
179 return true;
180 }
181
182 @Override
183 public String toString () {
184 StringWriter sw = new StringWriter(128);
185 PrintWriter pw = new PrintWriter(sw);
186
187 pw.print("NativeStackFrame@");
188 pw.print(Integer.toHexString(objectHashCode()));
189 pw.print("{ret=");
190 pw.print(ret);
191 if (retAttr != null){
192 pw.print('(');
193 pw.print(retAttr);
194 pw.print(')');
195 }
196 pw.print(',');
197 printContentsOn(pw);
198 pw.print('}');
199
200 return sw.toString();
201 }
202
203 //--- NativeStackFrames aren't called directly and have special return value processing (in NATIVERETURN.execute())
204 @Override
205 public void setArgumentLocal (int idx, int value, Object attr){
206 throw new JPFException("NativeStackFrames don't support setting argument locals");
207 }
208 @Override
209 public void setLongArgumentLocal (int idx, long value, Object attr){
210 throw new JPFException("NativeStackFrames don't support setting argument locals");
211 }
212 @Override
213 public void setReferenceArgumentLocal (int idx, int ref, Object attr){
214 throw new JPFException("NativeStackFrames don't support setting argument locals");
215 }
216
217 //--- exception refs
218 @Override
219 public void setExceptionReference (int exRef){
220 throw new JPFException("NativeStackFrames don't support exception handlers");
221 }
222
223 @Override
224 public int getExceptionReference (){
225 throw new JPFException("NativeStackFrames don't support exception handlers");
226 }
227
228 @Override
229 public void setExceptionReferenceAttribute (Object attr){
230 throw new JPFException("NativeStackFrames don't support exception handlers");
231 }
232
233 @Override
234 public Object getExceptionReferenceAttribute (){
235 throw new JPFException("NativeStackFrames don't support exception handlers");
236 }
237
238 @Override
239 public int getResult(){
240 Object r = ret;
241
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);
247 } else {
248 return ((Number)r).intValue();
249 }
250 } else if (r instanceof Boolean){
251 return (r == Boolean.TRUE) ? 1 : 0;
252 } else {
253 throw new JPFException("result " + ret + " can't be converted into raw int value");
254 }
255 }
256
257 @Override
258 public int getReferenceResult(){
259 if (ret instanceof Integer){
260 return (Integer)ret; // MJI requires references to be returned as 'int'
261 } else {
262 throw new JPFException("result " + ret + " can't be converted into JPF refrence value");
263 }
264 }
265
266 @Override
267 public long getLongResult(){
268 Object r = ret;
269 if (r instanceof Long){
270 return (Long)r;
271 } else if (r instanceof Double){
272 return Double.doubleToLongBits((Double)r);
273 } else {
274 throw new JPFException("result " + ret + " can't be converted into raw long value");
275 }
276 }
277
278 @Override
279 public Object getResultAttr(){
280 return retAttr;
281 }
282 @Override
283 public Object getLongResultAttr(){
284 return retAttr;
285 }
286 }