Mercurial > hg > Members > kono > jpf-core
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 } |