Mercurial > hg > Members > kono > jpf-core
comparison src/main/gov/nasa/jpf/vm/MJIEnv.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 | caa0924e093d |
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 package gov.nasa.jpf.vm; | |
19 | |
20 import gov.nasa.jpf.Config; | |
21 import gov.nasa.jpf.JPF; | |
22 import gov.nasa.jpf.JPFException; | |
23 import gov.nasa.jpf.JPFListener; | |
24 | |
25 import java.util.Date; | |
26 import java.util.Locale; | |
27 | |
28 | |
29 /** | |
30 * MJIEnv is the call environment for "native" methods, i.e. code that | |
31 * is executed by the VM, not by JPF. | |
32 * | |
33 * Since library abstractions are supposed to be "user code", we provide | |
34 * this class as a (little bit of) insulation towards the inner JPF workings. | |
35 * | |
36 * There are two APIs exported by this class. The public methods (like | |
37 * getStringObject) don't expose JPF internals, and can be used from non | |
38 * gov.nasa.jpf.vm NativePeer classes). The rest is package-default | |
39 * and can be used to fiddle around as much as you like to (if you are in | |
40 * the ..jvm package) | |
41 * | |
42 * Note that MJIEnv objects are now per-ThreadInfo (i.e. the variable | |
43 * call envionment only includes MethodInfo and ClassInfo), which means | |
44 * MJIEnv can be used in non-native methods (but only carefully, if you | |
45 * don't need mi or ciMth). | |
46 * | |
47 * Note also this only works because we are not getting recursive in | |
48 * native method calls. In fact, the whole DirectCallStackFrame / repeatTopInstruction | |
49 * mechanism is there to turn logial recursion (JPF calling native, calling | |
50 * JPF, calling native,..) into iteration. Otherwise we couldn't backtrack | |
51 */ | |
52 public class MJIEnv { | |
53 public static final int NULL = 0; | |
54 | |
55 VM vm; | |
56 ClassInfo ciMth; // the ClassInfo of the method this is called from | |
57 MethodInfo mi; | |
58 ThreadInfo ti; | |
59 Heap heap; | |
60 | |
61 // those are various attributes set by the execution. note that | |
62 // NativePeer.invoke never gets recursive in a roundtrip (at least if | |
63 // used correctly, so we don't have to be afraid to overwrite any of these | |
64 boolean repeat; | |
65 Object returnAttr; | |
66 | |
67 // exception to be thrown upon return from native method | |
68 // NOTE: this is only transient - don't expect this to be preserved over | |
69 // transition boundaries | |
70 int exceptionRef; | |
71 | |
72 MJIEnv (ThreadInfo ti) { | |
73 this.ti = ti; | |
74 | |
75 // set those here so that we don't have an inconsistent state between | |
76 // creation of an MJI object and the first native method call in | |
77 // this thread (where any access to the heap or sa would bomb) | |
78 vm = ti.getVM(); | |
79 heap = vm.getHeap(); | |
80 | |
81 exceptionRef = NULL; | |
82 } | |
83 | |
84 public VM getVM () { | |
85 return vm; | |
86 } | |
87 | |
88 public JPF getJPF () { | |
89 return vm.getJPF(); | |
90 } | |
91 | |
92 public boolean isBigEndianPlatform(){ | |
93 return vm.isBigEndianPlatform(); | |
94 } | |
95 | |
96 public void addListener (JPFListener l){ | |
97 vm.getJPF().addListener(l); | |
98 } | |
99 | |
100 public void removeListener (JPFListener l){ | |
101 vm.getJPF().removeListener(l); | |
102 } | |
103 | |
104 public Config getConfig() { | |
105 return vm.getConfig(); | |
106 } | |
107 | |
108 public void gc() { | |
109 heap.gc(); | |
110 } | |
111 | |
112 public void ignoreTransition () { | |
113 getSystemState().setIgnored(true); | |
114 } | |
115 | |
116 public boolean isArray (int objref) { | |
117 return heap.get(objref).isArray(); | |
118 } | |
119 | |
120 public int getArrayLength (int objref) { | |
121 if (isArray(objref)) { | |
122 return heap.get(objref).arrayLength(); | |
123 } else { | |
124 throwException("java.lang.IllegalArgumentException"); | |
125 | |
126 return 0; | |
127 } | |
128 } | |
129 | |
130 public String getArrayType (int objref) { | |
131 return heap.get(objref).getArrayType(); | |
132 } | |
133 | |
134 public int getArrayTypeSize (int objref) { | |
135 return Types.getTypeSize(getArrayType(objref)); | |
136 } | |
137 | |
138 //=== various attribute accessors ============================================ | |
139 // we only support some attribute APIs here, since MJIEnv adds little value | |
140 // other than hiding the ElementInfo access. If the client already has | |
141 // an ElementInfo reference, it should use that one to retrieve/enumerate/set | |
142 // attributes since this avoids repeated Heap.get() calls | |
143 | |
144 //--- object attributes | |
145 | |
146 public boolean hasObjectAttr (int objref){ | |
147 if (objref != NULL){ | |
148 ElementInfo ei = heap.get(objref); | |
149 return ei.hasObjectAttr(); | |
150 } | |
151 | |
152 return false; | |
153 } | |
154 | |
155 public boolean hasObjectAttr (int objref, Class<?> type){ | |
156 if (objref != NULL){ | |
157 ElementInfo ei = heap.get(objref); | |
158 return ei.hasObjectAttr(type); | |
159 } | |
160 | |
161 return false; | |
162 } | |
163 | |
164 /** | |
165 * this returns all of them - use either if you know there will be only | |
166 * one attribute at a time, or check/process result with ObjectList | |
167 */ | |
168 public Object getObjectAttr (int objref){ | |
169 if (objref != NULL){ | |
170 ElementInfo ei = heap.get(objref); | |
171 return ei.getObjectAttr(); | |
172 } | |
173 return null; | |
174 } | |
175 | |
176 /** | |
177 * this replaces all of them - use only if you know | |
178 * - there will be only one attribute at a time | |
179 * - you obtained the value you set by a previous getXAttr() | |
180 * - you constructed a multi value list with ObjectList.createList() | |
181 */ | |
182 public void setObjectAttr (int objref, Object a){ | |
183 if (objref != NULL){ | |
184 ElementInfo ei = heap.get(objref); | |
185 ei.setObjectAttr(a); | |
186 } | |
187 } | |
188 | |
189 public void addObjectAttr (int objref, Object a){ | |
190 if (objref != NULL){ | |
191 ElementInfo ei = heap.getModifiable(objref); | |
192 ei.addObjectAttr(a); | |
193 } | |
194 } | |
195 | |
196 | |
197 /** | |
198 * this only returns the first attr of this type, there can be more | |
199 * if you don't use client private types or the provided type is too general | |
200 */ | |
201 public <T> T getObjectAttr (int objref, Class<T> attrType){ | |
202 ElementInfo ei = heap.get(objref); | |
203 return ei.getObjectAttr(attrType); | |
204 } | |
205 | |
206 //--- field attributes | |
207 | |
208 public boolean hasFieldAttr (int objref){ | |
209 if (objref != NULL){ | |
210 ElementInfo ei = heap.get(objref); | |
211 return ei.hasFieldAttr(); | |
212 } | |
213 | |
214 return false; | |
215 } | |
216 | |
217 public boolean hasFieldAttr (int objref, Class<?> type){ | |
218 if (objref != NULL){ | |
219 ElementInfo ei = heap.get(objref); | |
220 return ei.hasFieldAttr(type); | |
221 } | |
222 | |
223 return false; | |
224 } | |
225 | |
226 /** | |
227 * this returns all of them - use either if you know there will be only | |
228 * one attribute at a time, or check/process result with ObjectList | |
229 */ | |
230 public Object getFieldAttr (int objref, String fname){ | |
231 ElementInfo ei = heap.get(objref); | |
232 FieldInfo fi = ei.getFieldInfo(fname); | |
233 if (fi != null){ | |
234 return ei.getFieldAttr(fi); | |
235 } else { | |
236 throw new JPFException("no such field: " + fname); | |
237 } | |
238 } | |
239 | |
240 /** | |
241 * this replaces all of them - use only if you know | |
242 * - there will be only one attribute at a time | |
243 * - you obtained the value you set by a previous getXAttr() | |
244 * - you constructed a multi value list with ObjectList.createList() | |
245 */ | |
246 public void setFieldAttr (int objref, String fname, Object a){ | |
247 if (objref != NULL){ | |
248 ElementInfo ei = heap.get(objref); | |
249 FieldInfo fi = ei.getFieldInfo(fname); | |
250 ei.setFieldAttr(fi, a); | |
251 } | |
252 } | |
253 | |
254 public void addFieldAttr (int objref, String fname, Object a){ | |
255 if (objref != NULL){ | |
256 ElementInfo ei = heap.getModifiable(objref); | |
257 FieldInfo fi = ei.getFieldInfo(fname); | |
258 ei.addFieldAttr(fi, a); | |
259 } | |
260 } | |
261 | |
262 | |
263 /** | |
264 * this only returns the first attr of this type, there can be more | |
265 * if you don't use client private types or the provided type is too general | |
266 */ | |
267 public <T> T getFieldAttr (int objref, String fname, Class<T> attrType){ | |
268 ElementInfo ei = heap.get(objref); | |
269 FieldInfo fi = ei.getFieldInfo(fname); | |
270 if (fi != null){ | |
271 return ei.getFieldAttr(fi, attrType); | |
272 } else { | |
273 throw new JPFException("no such field: " + fname); | |
274 } | |
275 } | |
276 | |
277 | |
278 //--- element attrs | |
279 | |
280 public boolean hasElementdAttr (int objref){ | |
281 if (objref != NULL){ | |
282 ElementInfo ei = heap.get(objref); | |
283 return ei.hasElementAttr(); | |
284 } | |
285 | |
286 return false; | |
287 } | |
288 | |
289 public boolean hasElementAttr (int objref, Class<?> type){ | |
290 if (objref != NULL){ | |
291 ElementInfo ei = heap.get(objref); | |
292 return ei.hasElementAttr(type); | |
293 } | |
294 | |
295 return false; | |
296 } | |
297 | |
298 /** | |
299 * this returns all of them - use either if you know there will be only | |
300 * one attribute at a time, or check/process result with ObjectList | |
301 */ | |
302 public Object getElementAttr (int objref, int idx){ | |
303 ElementInfo ei = heap.get(objref); | |
304 return ei.getElementAttr(idx); | |
305 } | |
306 | |
307 /** | |
308 * this replaces all of them - use only if you know | |
309 * - there will be only one attribute at a time | |
310 * - you obtained the value you set by a previous getXAttr() | |
311 * - you constructed a multi value list with ObjectList.createList() | |
312 */ | |
313 public void setElementAttr (int objref, int idx, Object a){ | |
314 ElementInfo ei = heap.get(objref); | |
315 ei.setElementAttr(idx, a); | |
316 } | |
317 | |
318 public void addElementAttr (int objref, int idx, Object a){ | |
319 ElementInfo ei = heap.getModifiable(objref); | |
320 ei.addElementAttr(idx, a); | |
321 } | |
322 | |
323 | |
324 /** | |
325 * this only returns the first attr of this type, there can be more | |
326 * if you don't use client private types or the provided type is too general | |
327 */ | |
328 public <T> T getElementAttr (int objref, int idx, Class<T> attrType){ | |
329 if (objref != NULL){ | |
330 ElementInfo ei = heap.get(objref); | |
331 return ei.getElementAttr(idx, attrType); | |
332 } | |
333 return null; | |
334 } | |
335 | |
336 | |
337 | |
338 // == end attrs == | |
339 | |
340 | |
341 | |
342 // the instance field setters | |
343 public void setBooleanField (int objref, String fname, boolean val) { | |
344 heap.getModifiable(objref).setBooleanField(fname, val); | |
345 } | |
346 | |
347 public boolean getBooleanField (int objref, String fname) { | |
348 return heap.get(objref).getBooleanField(fname); | |
349 } | |
350 | |
351 public boolean getBooleanArrayElement (int objref, int index) { | |
352 return heap.get(objref).getBooleanElement(index); | |
353 } | |
354 | |
355 public void setBooleanArrayElement (int objref, int index, boolean value) { | |
356 heap.getModifiable(objref).setBooleanElement(index, value); | |
357 } | |
358 | |
359 | |
360 public void setByteField (int objref, String fname, byte val) { | |
361 heap.getModifiable(objref).setByteField(fname, val); | |
362 } | |
363 | |
364 public byte getByteField (int objref, String fname) { | |
365 return heap.get(objref).getByteField(fname); | |
366 } | |
367 | |
368 public void setCharField (int objref, String fname, char val) { | |
369 heap.getModifiable(objref).setCharField(fname, val); | |
370 } | |
371 | |
372 public char getCharField (int objref, String fname) { | |
373 return heap.get(objref).getCharField(fname); | |
374 } | |
375 | |
376 public void setDoubleField (int objref, String fname, double val) { | |
377 heap.getModifiable(objref).setDoubleField(fname, val); | |
378 } | |
379 | |
380 public double getDoubleField (int objref, String fname) { | |
381 return heap.get(objref).getDoubleField(fname); | |
382 } | |
383 | |
384 public void setFloatField (int objref, String fname, float val) { | |
385 heap.getModifiable(objref).setFloatField(fname, val); | |
386 } | |
387 | |
388 public float getFloatField (int objref, String fname) { | |
389 return heap.get(objref).getFloatField(fname); | |
390 } | |
391 | |
392 | |
393 public void setByteArrayElement (int objref, int index, byte value) { | |
394 heap.getModifiable(objref).setByteElement(index, value); | |
395 } | |
396 | |
397 public byte getByteArrayElement (int objref, int index) { | |
398 return heap.get(objref).getByteElement(index); | |
399 } | |
400 | |
401 public void setCharArrayElement (int objref, int index, char value) { | |
402 heap.getModifiable(objref).setCharElement(index, value); | |
403 } | |
404 | |
405 public void setIntArrayElement (int objref, int index, int value) { | |
406 heap.getModifiable(objref).setIntElement(index, value); | |
407 } | |
408 | |
409 public void setShortArrayElement (int objref, int index, short value) { | |
410 heap.getModifiable(objref).setShortElement(index, value); | |
411 } | |
412 | |
413 public void setFloatArrayElement (int objref, int index, float value) { | |
414 heap.getModifiable(objref).setFloatElement(index, value); | |
415 } | |
416 | |
417 public float getFloatArrayElement (int objref, int index) { | |
418 return heap.get(objref).getFloatElement(index); | |
419 } | |
420 | |
421 public double getDoubleArrayElement (int objref, int index) { | |
422 return heap.get(objref).getDoubleElement(index); | |
423 } | |
424 public void setDoubleArrayElement (int objref, int index, double value) { | |
425 heap.getModifiable(objref).setDoubleElement(index, value); | |
426 } | |
427 | |
428 public short getShortArrayElement (int objref, int index) { | |
429 return heap.get(objref).getShortElement(index); | |
430 } | |
431 | |
432 public int getIntArrayElement (int objref, int index) { | |
433 return heap.get(objref).getIntElement(index); | |
434 } | |
435 | |
436 public char getCharArrayElement (int objref, int index) { | |
437 return heap.get(objref).getCharElement(index); | |
438 } | |
439 | |
440 public void setIntField (int objref, String fname, int val) { | |
441 ElementInfo ei = heap.getModifiable(objref); | |
442 ei.setIntField(fname, val); | |
443 } | |
444 | |
445 // these two are the workhorses | |
446 public void setDeclaredIntField (int objref, String refType, String fname, int val) { | |
447 ElementInfo ei = heap.getModifiable(objref); | |
448 ei.setDeclaredIntField(fname, refType, val); | |
449 } | |
450 | |
451 public int getIntField (int objref, String fname) { | |
452 ElementInfo ei = heap.get(objref); | |
453 return ei.getIntField(fname); | |
454 } | |
455 | |
456 public int getDeclaredIntField (int objref, String refType, String fname) { | |
457 ElementInfo ei = heap.get(objref); | |
458 return ei.getDeclaredIntField(fname, refType); | |
459 } | |
460 | |
461 // these two are the workhorses | |
462 public void setDeclaredReferenceField (int objref, String refType, String fname, int val) { | |
463 ElementInfo ei = heap.getModifiable(objref); | |
464 ei.setDeclaredReferenceField(fname, refType, val); | |
465 } | |
466 | |
467 public void setReferenceField (int objref, String fname, int ref) { | |
468 ElementInfo ei = heap.getModifiable(objref); | |
469 ei.setReferenceField(fname, ref); | |
470 } | |
471 | |
472 public int getReferenceField (int objref, String fname) { | |
473 ElementInfo ei = heap.get(objref); | |
474 return ei.getReferenceField(fname); | |
475 } | |
476 | |
477 // we need this in case of a masked field | |
478 public int getReferenceField (int objref, FieldInfo fi) { | |
479 ElementInfo ei = heap.get(objref); | |
480 return ei.getReferenceField(fi); | |
481 } | |
482 | |
483 public String getStringField (int objref, String fname){ | |
484 int ref = getReferenceField(objref, fname); | |
485 return getStringObject(ref); | |
486 } | |
487 | |
488 // the box object accessors (should probably test for the appropriate class) | |
489 public boolean getBooleanValue (int objref) { | |
490 return getBooleanField(objref, "value"); | |
491 } | |
492 | |
493 public byte getByteValue (int objref) { | |
494 return getByteField(objref, "value"); | |
495 } | |
496 | |
497 public char getCharValue (int objref) { | |
498 return getCharField(objref, "value"); | |
499 } | |
500 | |
501 public short getShortValue (int objref) { | |
502 return getShortField(objref, "value"); | |
503 } | |
504 | |
505 public int getIntValue (int objref) { | |
506 return getIntField(objref, "value"); | |
507 } | |
508 | |
509 public long getLongValue (int objref) { | |
510 return getLongField(objref, "value"); | |
511 } | |
512 | |
513 public float getFloatValue (int objref) { | |
514 return getFloatField(objref, "value"); | |
515 } | |
516 | |
517 public double getDoubleValue (int objref) { | |
518 return getDoubleField(objref, "value"); | |
519 } | |
520 | |
521 | |
522 public void setLongArrayElement (int objref, int index, long value) { | |
523 heap.getModifiable(objref).setLongElement(index, value); | |
524 } | |
525 | |
526 public long getLongArrayElement (int objref, int index) { | |
527 return heap.get(objref).getLongElement(index); | |
528 } | |
529 | |
530 public void setLongField (int objref, String fname, long val) { | |
531 ElementInfo ei = heap.getModifiable(objref); | |
532 ei.setLongField(fname, val); | |
533 } | |
534 | |
535 // public void setLongField (int objref, String refType, String fname, long val) { | |
536 // ElementInfo ei = heap.get(objref); | |
537 // ei.setLongField(fname, refType, val); | |
538 // } | |
539 | |
540 public long getLongField (int objref, String fname) { | |
541 ElementInfo ei = heap.get(objref); | |
542 return ei.getLongField(fname); | |
543 } | |
544 | |
545 // public long getLongField (int objref, String refType, String fname) { | |
546 // ElementInfo ei = heap.get(objref); | |
547 // return ei.getLongField(fname, refType); | |
548 // } | |
549 | |
550 public void setReferenceArrayElement (int objref, int index, int eRef) { | |
551 heap.getModifiable(objref).setReferenceElement(index, eRef); | |
552 } | |
553 | |
554 public int getReferenceArrayElement (int objref, int index) { | |
555 return heap.get(objref).getReferenceElement(index); | |
556 } | |
557 | |
558 public void setShortField (int objref, String fname, short val) { | |
559 setIntField(objref, fname, /*(int)*/ val); | |
560 } | |
561 | |
562 public short getShortField (int objref, String fname) { | |
563 return (short) getIntField(objref, fname); | |
564 } | |
565 | |
566 /** | |
567 * NOTE - this doesn't support element type checks or overlapping in-array copy | |
568 */ | |
569 public void arrayCopy (int srcRef, int srcPos, int dstRef, int dstPos, int len){ | |
570 ElementInfo eiSrc = heap.get(srcRef); | |
571 ElementInfo eiDst = heap.get(dstRef); | |
572 | |
573 eiDst.arrayCopy(eiSrc, srcPos, dstPos, len); | |
574 } | |
575 | |
576 public String getTypeName (int objref) { | |
577 return heap.get(objref).getType(); | |
578 } | |
579 | |
580 public boolean isInstanceOf (int objref, String clsName) { | |
581 ClassInfo ci = getClassInfo(objref); | |
582 return ci.isInstanceOf(clsName); | |
583 } | |
584 | |
585 public boolean isInstanceOf (int objref, ClassInfo cls) { | |
586 ClassInfo ci = getClassInfo(objref); | |
587 return ci.isInstanceOf(cls); | |
588 } | |
589 | |
590 //--- the static field accessors | |
591 // NOTE - it is the callers responsibility to ensure the class is | |
592 // properly initialized, since calling <clinit> requires a roundtrip | |
593 // (i.e. cannot be done synchronously from one of the following methods) | |
594 | |
595 // <2do> this uses the current system CL, we should probably use an explicit CL argument | |
596 | |
597 public void setStaticBooleanField (String clsName, String fname, | |
598 boolean value) { | |
599 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
600 ci.getStaticElementInfo().setBooleanField(fname, value); | |
601 } | |
602 public void setStaticBooleanField (int clsObjRef, String fname, boolean val) { | |
603 ElementInfo cei = getStaticElementInfo(clsObjRef); | |
604 cei.setBooleanField(fname, val); | |
605 } | |
606 | |
607 public boolean getStaticBooleanField (String clsName, String fname) { | |
608 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
609 return ci.getStaticElementInfo().getBooleanField(fname); | |
610 } | |
611 | |
612 public void setStaticByteField (String clsName, String fname, byte value) { | |
613 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
614 ci.getStaticElementInfo().setByteField(fname, value); } | |
615 | |
616 public byte getStaticByteField (String clsName, String fname) { | |
617 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
618 return ci.getStaticElementInfo().getByteField(fname); | |
619 } | |
620 | |
621 public void setStaticCharField (String clsName, String fname, char value) { | |
622 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
623 ci.getStaticElementInfo().setCharField(fname, value); } | |
624 | |
625 public char getStaticCharField (String clsName, String fname) { | |
626 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
627 return ci.getStaticElementInfo().getCharField(fname); | |
628 } | |
629 | |
630 public void setStaticDoubleField (String clsName, String fname, double val) { | |
631 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
632 ci.getStaticElementInfo().setDoubleField(fname, val); | |
633 } | |
634 | |
635 public double getStaticDoubleField (String clsName, String fname) { | |
636 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
637 return ci.getStaticElementInfo().getDoubleField(fname); | |
638 } | |
639 | |
640 public double getStaticDoubleField (int clsObjRef, String fname) { | |
641 ElementInfo cei = getStaticElementInfo(clsObjRef); | |
642 return cei.getDoubleField(fname); | |
643 } | |
644 | |
645 public double getStaticDoubleField (ClassInfo ci, String fname) { | |
646 ElementInfo ei = ci.getStaticElementInfo(); | |
647 return ei.getDoubleField(fname); | |
648 } | |
649 | |
650 public void setStaticFloatField (String clsName, String fname, float val) { | |
651 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
652 ci.getStaticElementInfo().setFloatField(fname, val); | |
653 } | |
654 | |
655 public float getStaticFloatField (String clsName, String fname) { | |
656 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
657 return ci.getStaticElementInfo().getFloatField(fname); | |
658 } | |
659 | |
660 public void setStaticIntField (String clsName, String fname, int val) { | |
661 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
662 ci.getStaticElementInfo().setIntField(fname, val); | |
663 } | |
664 | |
665 public void setStaticIntField (int clsObjRef, String fname, int val) { | |
666 ElementInfo cei = getStaticElementInfo(clsObjRef); | |
667 cei.setIntField(fname, val); | |
668 } | |
669 | |
670 public int getStaticIntField (String clsName, String fname) { | |
671 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
672 return ci.getStaticElementInfo().getIntField(fname); | |
673 } | |
674 | |
675 public int getStaticIntField (int clsObjRef, String fname) { | |
676 ElementInfo cei = getStaticElementInfo(clsObjRef); | |
677 return cei.getIntField(fname); | |
678 } | |
679 | |
680 public int getStaticIntField (ClassInfo ci, String fname) { | |
681 ElementInfo ei = ci.getStaticElementInfo(); | |
682 return ei.getIntField(fname); | |
683 } | |
684 | |
685 public void setStaticLongField (String clsName, String fname, long value) { | |
686 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
687 ci.getStaticElementInfo().setLongField(fname, value); | |
688 } | |
689 | |
690 public void setStaticLongField (int clsObjRef, String fname, long val) { | |
691 ElementInfo cei = getModifiableStaticElementInfo(clsObjRef); | |
692 cei.setLongField(fname, val); | |
693 } | |
694 | |
695 public long getStaticLongField (int clsRef, String fname) { | |
696 ClassInfo ci = getReferredClassInfo(clsRef); | |
697 return getStaticLongField(ci,fname); | |
698 } | |
699 | |
700 public long getStaticLongField (String clsName, String fname) { | |
701 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
702 return getStaticLongField(ci, fname); | |
703 } | |
704 | |
705 public long getStaticLongField (ClassInfo ci, String fname){ | |
706 ElementInfo ei = ci.getStaticElementInfo(); | |
707 return ei.getLongField(fname); | |
708 } | |
709 | |
710 public void setStaticReferenceField (String clsName, String fname, int objref) { | |
711 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
712 | |
713 // <2do> - we should REALLY check for type compatibility here | |
714 ci.getModifiableStaticElementInfo().setReferenceField(fname, objref); | |
715 } | |
716 | |
717 public void setStaticReferenceField (int clsObjRef, String fname, int objref) { | |
718 ElementInfo cei = getModifiableStaticElementInfo(clsObjRef); | |
719 | |
720 // <2do> - we should REALLY check for type compatibility here | |
721 cei.setReferenceField(fname, objref); | |
722 } | |
723 | |
724 public int getStaticReferenceField (String clsName, String fname) { | |
725 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
726 return ci.getStaticElementInfo().getReferenceField(fname); | |
727 } | |
728 | |
729 public int getStaticReferenceField (int clsObjRef, String fname) { | |
730 ElementInfo cei = getStaticElementInfo(clsObjRef); | |
731 return cei.getReferenceField(fname); | |
732 } | |
733 | |
734 public int getStaticReferenceField (ClassInfo ci, String fname){ | |
735 return ci.getStaticElementInfo().getReferenceField(fname); | |
736 } | |
737 | |
738 public short getStaticShortField (String clsName, String fname) { | |
739 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
740 return ci.getStaticElementInfo().getShortField(fname); | |
741 } | |
742 | |
743 public char[] getStringChars (int objRef){ | |
744 if (objRef != MJIEnv.NULL) { | |
745 ElementInfo ei = getElementInfo(objRef); | |
746 return ei.getStringChars(); | |
747 | |
748 } else { | |
749 return null; | |
750 } | |
751 | |
752 } | |
753 | |
754 /** | |
755 * turn JPF String object into a VM String object | |
756 * (this is a method available for non gov..jvm NativePeer classes) | |
757 */ | |
758 public String getStringObject (int objRef) { | |
759 if (objRef != MJIEnv.NULL) { | |
760 ElementInfo ei = getElementInfo(objRef); | |
761 return ei.asString(); | |
762 | |
763 } else { | |
764 return null; | |
765 } | |
766 } | |
767 | |
768 public String[] getStringArrayObject (int aRef){ | |
769 String[] sa = null; | |
770 | |
771 if (aRef == NULL) return sa; | |
772 | |
773 ClassInfo aci = getClassInfo(aRef); | |
774 if (aci.isArray()){ | |
775 ClassInfo eci = aci.getComponentClassInfo(); | |
776 if (eci.getName().equals("java.lang.String")){ | |
777 int len = getArrayLength(aRef); | |
778 sa = new String[len]; | |
779 | |
780 for (int i=0; i<len; i++){ | |
781 int sRef = getReferenceArrayElement(aRef,i); | |
782 sa[i] = getStringObject(sRef); | |
783 } | |
784 | |
785 return sa; | |
786 | |
787 } else { | |
788 throw new IllegalArgumentException("not a String[] array: " + aci.getName()); | |
789 } | |
790 } else { | |
791 throw new IllegalArgumentException("not an array reference: " + aci.getName()); | |
792 } | |
793 } | |
794 | |
795 public Date getDateObject (int objref) { | |
796 if (objref != MJIEnv.NULL) { | |
797 ElementInfo ei = getElementInfo(objref); | |
798 if (ei.getClassInfo().getName().equals("java.util.Date")) { | |
799 // <2do> this is not complete yet | |
800 long fastTime = ei.getLongField("fastTime"); | |
801 Date d = new Date(fastTime); | |
802 return d; | |
803 } else { | |
804 throw new JPFException("not a Date object reference: " + ei); | |
805 } | |
806 } else { | |
807 return null; | |
808 } | |
809 | |
810 } | |
811 | |
812 public Object[] getArgumentArray (int argRef) { | |
813 Object[] args = null; | |
814 if (argRef == NULL) return args; | |
815 | |
816 int nArgs = getArrayLength(argRef); | |
817 args = new Object[nArgs]; | |
818 | |
819 for (int i=0; i<nArgs; i++){ | |
820 int aref = getReferenceArrayElement(argRef,i); | |
821 ClassInfo ci = getClassInfo(aref); | |
822 String clsName = ci.getName(); | |
823 if (clsName.equals("java.lang.Boolean")){ | |
824 args[i] = Boolean.valueOf(getBooleanField(aref,"value")); | |
825 } else if (clsName.equals("java.lang.Integer")){ | |
826 args[i] = Integer.valueOf(getIntField(aref,"value")); | |
827 } else if (clsName.equals("java.lang.Double")){ | |
828 args[i] = Double.valueOf(getDoubleField(aref,"value")); | |
829 } else if (clsName.equals("java.lang.String")){ | |
830 args[i] = getStringObject(aref); | |
831 } | |
832 } | |
833 | |
834 return args; | |
835 } | |
836 | |
837 public Boolean getBooleanObject (int objref){ | |
838 return Boolean.valueOf(getBooleanField(objref, "value")); | |
839 } | |
840 | |
841 public Byte getByteObject (int objref){ | |
842 return new Byte(getByteField(objref, "value")); | |
843 } | |
844 | |
845 public Character getCharObject (int objref){ | |
846 return new Character(getCharField(objref, "value")); | |
847 } | |
848 | |
849 public Short getShortObject (int objref){ | |
850 return new Short(getShortField(objref, "value")); | |
851 } | |
852 | |
853 public Integer getIntegerObject (int objref){ | |
854 return new Integer(getIntField(objref, "value")); | |
855 } | |
856 | |
857 public Long getLongObject (int objref){ | |
858 return new Long(getLongField(objref, "value")); | |
859 } | |
860 | |
861 public Float getFloatObject (int objref){ | |
862 return new Float(getFloatField(objref, "value")); | |
863 } | |
864 | |
865 public Double getDoubleObject (int objref){ | |
866 return new Double(getDoubleField(objref, "value")); | |
867 } | |
868 | |
869 // danger - the returned arrays could be used to modify contents of stored objects | |
870 | |
871 public byte[] getByteArrayObject (int objref) { | |
872 ElementInfo ei = getElementInfo(objref); | |
873 byte[] a = ei.asByteArray(); | |
874 | |
875 return a; | |
876 } | |
877 | |
878 public char[] getCharArrayObject (int objref) { | |
879 ElementInfo ei = getElementInfo(objref); | |
880 char[] a = ei.asCharArray(); | |
881 | |
882 return a; | |
883 } | |
884 | |
885 public short[] getShortArrayObject (int objref) { | |
886 ElementInfo ei = getElementInfo(objref); | |
887 short[] a = ei.asShortArray(); | |
888 | |
889 return a; | |
890 } | |
891 | |
892 public int[] getIntArrayObject (int objref) { | |
893 ElementInfo ei = getElementInfo(objref); | |
894 int[] a = ei.asIntArray(); | |
895 | |
896 return a; | |
897 } | |
898 | |
899 public long[] getLongArrayObject (int objref) { | |
900 ElementInfo ei = getElementInfo(objref); | |
901 long[] a = ei.asLongArray(); | |
902 | |
903 return a; | |
904 } | |
905 | |
906 public float[] getFloatArrayObject (int objref) { | |
907 ElementInfo ei = getElementInfo(objref); | |
908 float[] a = ei.asFloatArray(); | |
909 | |
910 return a; | |
911 } | |
912 | |
913 public double[] getDoubleArrayObject (int objref) { | |
914 ElementInfo ei = getElementInfo(objref); | |
915 double[] a = ei.asDoubleArray(); | |
916 | |
917 return a; | |
918 } | |
919 | |
920 public boolean[] getBooleanArrayObject (int objref) { | |
921 ElementInfo ei = getElementInfo(objref); | |
922 boolean[] a = ei.asBooleanArray(); | |
923 | |
924 return a; | |
925 } | |
926 | |
927 public int[] getReferenceArrayObject (int objref){ | |
928 ElementInfo ei = getElementInfo(objref); | |
929 int[] a = ei.asReferenceArray(); | |
930 | |
931 return a; | |
932 } | |
933 | |
934 public boolean canLock (int objref) { | |
935 ElementInfo ei = getElementInfo(objref); | |
936 | |
937 return ei.canLock(ti); | |
938 } | |
939 | |
940 public int newBooleanArray (int size) { | |
941 return heap.newArray("Z", size, ti).getObjectRef(); | |
942 } | |
943 | |
944 public int newByteArray (int size) { | |
945 return heap.newArray("B", size, ti).getObjectRef(); | |
946 } | |
947 | |
948 public int newByteArray (byte[] buf){ | |
949 ElementInfo eiArray = heap.newArray("B", buf.length, ti); | |
950 for (int i=0; i<buf.length; i++){ | |
951 eiArray.setByteElement( i, buf[i]); | |
952 } | |
953 return eiArray.getObjectRef(); | |
954 } | |
955 | |
956 public int newCharArray (int size) { | |
957 return heap.newArray("C", size, ti).getObjectRef(); | |
958 } | |
959 | |
960 public int newCharArray (char[] buf){ | |
961 ElementInfo eiArray = heap.newArray("C", buf.length, ti); | |
962 for (int i=0; i<buf.length; i++){ | |
963 eiArray.setCharElement( i, buf[i]); | |
964 } | |
965 return eiArray.getObjectRef(); | |
966 } | |
967 | |
968 public int newShortArray (int size) { | |
969 return heap.newArray("S", size, ti).getObjectRef(); | |
970 } | |
971 | |
972 public int newShortArray (short[] buf){ | |
973 ElementInfo eiArray = heap.newArray("S", buf.length, ti); | |
974 for (int i=0; i<buf.length; i++){ | |
975 eiArray.setShortElement(i, buf[i]); | |
976 } | |
977 return eiArray.getObjectRef(); | |
978 } | |
979 | |
980 public int newDoubleArray (int size) { | |
981 return heap.newArray("D", size, ti).getObjectRef(); | |
982 } | |
983 | |
984 public int newDoubleArray (double[] buf){ | |
985 ElementInfo eiArray = heap.newArray("D", buf.length, ti); | |
986 for (int i=0; i<buf.length; i++){ | |
987 eiArray.setDoubleElement(i, buf[i]); | |
988 } | |
989 return eiArray.getObjectRef(); | |
990 } | |
991 | |
992 public int newFloatArray (int size) { | |
993 return heap.newArray("F", size, ti).getObjectRef(); | |
994 } | |
995 | |
996 public int newFloatArray (float[] buf){ | |
997 ElementInfo eiArray = heap.newArray("F", buf.length, ti); | |
998 for (int i=0; i<buf.length; i++){ | |
999 eiArray.setFloatElement( i, buf[i]); | |
1000 } | |
1001 return eiArray.getObjectRef(); | |
1002 } | |
1003 | |
1004 public int newIntArray (int size) { | |
1005 return heap.newArray("I", size, ti).getObjectRef(); | |
1006 } | |
1007 | |
1008 public int newIntArray (int[] buf){ | |
1009 ElementInfo eiArray = heap.newArray("I", buf.length, ti); | |
1010 for (int i=0; i<buf.length; i++){ | |
1011 eiArray.setIntElement( i, buf[i]); | |
1012 } | |
1013 return eiArray.getObjectRef(); | |
1014 } | |
1015 | |
1016 public int newLongArray (int size) { | |
1017 return heap.newArray("J", size, ti).getObjectRef(); | |
1018 } | |
1019 | |
1020 public int newLongArray (long[] buf){ | |
1021 ElementInfo eiArray = heap.newArray("J", buf.length, ti); | |
1022 for (int i=0; i<buf.length; i++){ | |
1023 eiArray.setLongElement( i, buf[i]); | |
1024 } | |
1025 return eiArray.getObjectRef(); | |
1026 } | |
1027 | |
1028 public int newObjectArray (String elementClsName, int size) { | |
1029 if (!elementClsName.endsWith(";")) { | |
1030 elementClsName = Types.getTypeSignature(elementClsName, false); | |
1031 } | |
1032 | |
1033 return heap.newArray(elementClsName, size, ti).getObjectRef(); | |
1034 } | |
1035 | |
1036 public ElementInfo newElementInfo (ClassInfo ci){ | |
1037 if (ci.pushRequiredClinits(ti)){ | |
1038 throw new ClinitRequired(ci); | |
1039 } | |
1040 | |
1041 return heap.newObject(ci, ti); | |
1042 } | |
1043 | |
1044 /** | |
1045 * check if the ClassInfo is properly initialized | |
1046 * if yes, create a new instance of it but don't call any ctor | |
1047 * if no, throw a ClinitRequired exception | |
1048 */ | |
1049 public int newObject (ClassInfo ci) { | |
1050 ElementInfo ei = newElementInfo(ci); | |
1051 return ei.getObjectRef(); | |
1052 } | |
1053 | |
1054 /** | |
1055 * this creates a new object without checking if the ClassInfo needs | |
1056 * initialization. This is useful in a context that already | |
1057 * is aware and handles re-execution | |
1058 */ | |
1059 public int newObjectOfUncheckedClass (ClassInfo ci){ | |
1060 ElementInfo ei = heap.newObject(ci, ti); | |
1061 return ei.getObjectRef(); | |
1062 } | |
1063 | |
1064 public ElementInfo newElementInfo (String clsName) { | |
1065 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
1066 if (ci != null){ | |
1067 return newElementInfo(ci); | |
1068 } else { | |
1069 return null; | |
1070 } | |
1071 } | |
1072 | |
1073 public int newObject (String clsName) { | |
1074 ElementInfo ei = newElementInfo(clsName); | |
1075 if (ei != null){ | |
1076 return ei.getObjectRef(); | |
1077 } else { | |
1078 return NULL; | |
1079 } | |
1080 } | |
1081 | |
1082 public int newString (String s) { | |
1083 if (s == null){ | |
1084 return NULL; | |
1085 } else { | |
1086 return heap.newString(s, ti).getObjectRef(); | |
1087 } | |
1088 } | |
1089 | |
1090 public int newStringArray (String[] a){ | |
1091 int aref = newObjectArray("Ljava/lang/String;", a.length); | |
1092 | |
1093 for (int i=0; i<a.length; i++){ | |
1094 setReferenceArrayElement(aref, i, newString(a[i])); | |
1095 } | |
1096 | |
1097 return aref; | |
1098 } | |
1099 | |
1100 public int newString (int arrayRef) { | |
1101 String t = getArrayType(arrayRef); | |
1102 String s = null; | |
1103 | |
1104 if ("C".equals(t)) { // character array | |
1105 char[] ca = getCharArrayObject(arrayRef); | |
1106 s = new String(ca); | |
1107 } else if ("B".equals(t)) { // byte array | |
1108 byte[] ba = getByteArrayObject(arrayRef); | |
1109 s = new String(ba); | |
1110 } | |
1111 | |
1112 if (s == null) { | |
1113 return NULL; | |
1114 } | |
1115 | |
1116 return newString(s); | |
1117 } | |
1118 | |
1119 public String format (int fmtRef, int argRef){ | |
1120 String format = getStringObject(fmtRef); | |
1121 int len = getArrayLength(argRef); | |
1122 Object[] arg = new Object[len]; | |
1123 | |
1124 for (int i=0; i<len; i++){ | |
1125 int ref = getReferenceArrayElement(argRef,i); | |
1126 if (ref != NULL) { | |
1127 String clsName = getClassName(ref); | |
1128 if (clsName.equals("java.lang.String")) { | |
1129 arg[i] = getStringObject(ref); | |
1130 } else if (clsName.equals("java.lang.Boolean")){ | |
1131 arg[i] = getBooleanObject(ref); | |
1132 } else if (clsName.equals("java.lang.Byte")) { | |
1133 arg[i] = getByteObject(ref); | |
1134 } else if (clsName.equals("java.lang.Char")) { | |
1135 arg[i] = getCharObject(ref); | |
1136 } else if (clsName.equals("java.lang.Short")) { | |
1137 arg[i] = getShortObject(ref); | |
1138 } else if (clsName.equals("java.lang.Integer")) { | |
1139 arg[i] = getIntegerObject(ref); | |
1140 } else if (clsName.equals("java.lang.Long")) { | |
1141 arg[i] = getLongObject(ref); | |
1142 } else if (clsName.equals("java.lang.Float")) { | |
1143 arg[i] = getFloatObject(ref); | |
1144 } else if (clsName.equals("java.lang.Double")) { | |
1145 arg[i] = getDoubleObject(ref); | |
1146 } else { | |
1147 // need a toString() here | |
1148 arg[i] = "??"; | |
1149 } | |
1150 } | |
1151 } | |
1152 | |
1153 return String.format(format,arg); | |
1154 } | |
1155 | |
1156 public String format (Locale l,int fmtRef, int argRef){ | |
1157 String format = getStringObject(fmtRef); | |
1158 int len = getArrayLength(argRef); | |
1159 Object[] arg = new Object[len]; | |
1160 | |
1161 for (int i=0; i<len; i++){ | |
1162 int ref = getReferenceArrayElement(argRef,i); | |
1163 if (ref != NULL) { | |
1164 String clsName = getClassName(ref); | |
1165 if (clsName.equals("java.lang.String")) { | |
1166 arg[i] = getStringObject(ref); | |
1167 } else if (clsName.equals("java.lang.Byte")) { | |
1168 arg[i] = getByteObject(ref); | |
1169 } else if (clsName.equals("java.lang.Char")) { | |
1170 arg[i] = getCharObject(ref); | |
1171 } else if (clsName.equals("java.lang.Short")) { | |
1172 arg[i] = getShortObject(ref); | |
1173 } else if (clsName.equals("java.lang.Integer")) { | |
1174 arg[i] = getIntegerObject(ref); | |
1175 } else if (clsName.equals("java.lang.Long")) { | |
1176 arg[i] = getLongObject(ref); | |
1177 } else if (clsName.equals("java.lang.Float")) { | |
1178 arg[i] = getFloatObject(ref); | |
1179 } else if (clsName.equals("java.lang.Double")) { | |
1180 arg[i] = getDoubleObject(ref); | |
1181 } else { | |
1182 // need a toString() here | |
1183 arg[i] = "??"; | |
1184 } | |
1185 } | |
1186 } | |
1187 | |
1188 return String.format(l,format,arg); | |
1189 } | |
1190 | |
1191 | |
1192 public int newBoolean (boolean b){ | |
1193 return getStaticReferenceField("java.lang.Boolean", b ? "TRUE" : "FALSE"); | |
1194 } | |
1195 | |
1196 public int newInteger (int n){ | |
1197 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Integer"), ti); | |
1198 ei.setIntField("value",n); | |
1199 return ei.getObjectRef(); | |
1200 } | |
1201 | |
1202 public int newLong (long l){ | |
1203 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Long"), ti); | |
1204 ei.setLongField("value",l); | |
1205 return ei.getObjectRef(); | |
1206 } | |
1207 | |
1208 public int newDouble (double d){ | |
1209 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Double"), ti); | |
1210 ei.setDoubleField("value",d); | |
1211 return ei.getObjectRef(); | |
1212 } | |
1213 | |
1214 public int newFloat (float f){ | |
1215 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Float"), ti); | |
1216 ei.setFloatField("value",f); | |
1217 return ei.getObjectRef(); | |
1218 } | |
1219 | |
1220 public int newByte (byte b){ | |
1221 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Byte"), ti); | |
1222 ei.setByteField("value",b); | |
1223 return ei.getObjectRef(); | |
1224 } | |
1225 | |
1226 public int newShort (short s){ | |
1227 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Short"), ti); | |
1228 ei.setShortField("value",s); | |
1229 return ei.getObjectRef(); | |
1230 } | |
1231 | |
1232 public int newCharacter (char c){ | |
1233 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Character"), ti); | |
1234 ei.setCharField("value",c); | |
1235 return ei.getObjectRef(); | |
1236 } | |
1237 | |
1238 | |
1239 public boolean notify (int objref) { | |
1240 // objref can't be NULL since the corresponding INVOKE would have failed | |
1241 ElementInfo ei = getModifiableElementInfo(objref); | |
1242 return notify(ei); | |
1243 } | |
1244 | |
1245 public boolean notify (ElementInfo ei) { | |
1246 if (!ei.isLockedBy(ti)){ | |
1247 throwException("java.lang.IllegalMonitorStateException", | |
1248 "un-synchronized notify"); | |
1249 return false; | |
1250 } | |
1251 | |
1252 return ei.notifies(getSystemState(), ti); | |
1253 } | |
1254 | |
1255 public boolean notifyAll (int objref) { | |
1256 // objref can't be NULL since the corresponding INVOKE would have failed | |
1257 ElementInfo ei = getElementInfo(objref); | |
1258 return notifyAll(ei); | |
1259 } | |
1260 | |
1261 public boolean notifyAll (ElementInfo ei) { | |
1262 if (!ei.isLockedBy(ti)){ | |
1263 throwException("java.lang.IllegalMonitorStateException", | |
1264 "un-synchronized notifyAll"); | |
1265 return false; | |
1266 } | |
1267 | |
1268 return ei.notifiesAll(); | |
1269 } | |
1270 | |
1271 public void registerPinDown(int objref){ | |
1272 heap.registerPinDown(objref); | |
1273 } | |
1274 public void registerPinDown (ElementInfo ei){ | |
1275 registerPinDown(ei.getObjectRef()); | |
1276 } | |
1277 | |
1278 public void releasePinDown(int objref){ | |
1279 heap.releasePinDown(objref); | |
1280 } | |
1281 public void releasePinDown (ElementInfo ei){ | |
1282 releasePinDown(ei.getObjectRef()); | |
1283 } | |
1284 | |
1285 /** | |
1286 * use this whenever a peer performs an operation on a class that might not be initialized yet | |
1287 * Do a repeatInvocation() in this case | |
1288 */ | |
1289 public boolean requiresClinitExecution(ClassInfo ci) { | |
1290 return ci.pushRequiredClinits(ti); | |
1291 } | |
1292 | |
1293 /** | |
1294 * repeat execution of the instruction that caused a native method call | |
1295 * NOTE - this does NOT mean it's the NEXT executed insn, since the native method | |
1296 * might have pushed direct call frames on the stack before asking us to repeat it. | |
1297 */ | |
1298 public void repeatInvocation () { | |
1299 repeat = true; | |
1300 } | |
1301 | |
1302 public boolean isInvocationRepeated() { | |
1303 return repeat; | |
1304 } | |
1305 | |
1306 | |
1307 public boolean setNextChoiceGenerator (ChoiceGenerator<?> cg){ | |
1308 return vm.getSystemState().setNextChoiceGenerator(cg); | |
1309 } | |
1310 | |
1311 public void setMandatoryNextChoiceGenerator(ChoiceGenerator<?> cg, String failMsg){ | |
1312 vm.getSystemState().setMandatoryNextChoiceGenerator(cg, failMsg); | |
1313 } | |
1314 | |
1315 public ChoiceGenerator<?> getChoiceGenerator () { | |
1316 return vm.getSystemState().getChoiceGenerator(); | |
1317 } | |
1318 | |
1319 // note this only makes sense if we actually do return something | |
1320 public void setReturnAttribute (Object attr) { | |
1321 returnAttr = attr; | |
1322 } | |
1323 | |
1324 /** | |
1325 * return attr list of all arguments. Use ObjectList to retrieve values | |
1326 * from this list | |
1327 * | |
1328 * NOTE - this can only be called from a native method context, since | |
1329 * otherwise the top frame is the callee | |
1330 */ | |
1331 public Object[] getArgAttributes () { | |
1332 StackFrame caller = getCallerStackFrame(); | |
1333 return caller.getArgumentAttrs(mi); | |
1334 } | |
1335 | |
1336 public Object getReturnAttribute() { | |
1337 return returnAttr; | |
1338 } | |
1339 | |
1340 // if any of the next methods is called from the bottom | |
1341 // half of a CG method, you might want to check if another thread | |
1342 // or a listener has already set an exception you don't want to override | |
1343 // (this is for instance used in Thread.stop()) | |
1344 | |
1345 public void throwException (int xRef){ | |
1346 assert isInstanceOf(xRef, "java.lang.Throwable"); | |
1347 exceptionRef = xRef; | |
1348 } | |
1349 | |
1350 public void throwException (String clsName) { | |
1351 ClassInfo ciX = ClassInfo.getInitializedClassInfo(clsName, ti); | |
1352 assert ciX.isInstanceOf("java.lang.Throwable"); | |
1353 exceptionRef = ti.createException(ciX, null, NULL); | |
1354 } | |
1355 | |
1356 public void throwException (String clsName, String details) { | |
1357 ClassInfo ciX = ClassInfo.getInitializedClassInfo(clsName, ti); | |
1358 assert ciX.isInstanceOf("java.lang.Throwable"); | |
1359 exceptionRef = ti.createException(ciX, details, NULL); | |
1360 } | |
1361 | |
1362 public void throwAssertion (String details) { | |
1363 throwException("java.lang.AssertionError", details); | |
1364 } | |
1365 | |
1366 public void throwInterrupt(){ | |
1367 throwException("java.lang.InterruptedException"); | |
1368 } | |
1369 | |
1370 public void stopThread(){ | |
1371 stopThreadWithException(MJIEnv.NULL); | |
1372 } | |
1373 | |
1374 public void stopThreadWithException (int xRef){ | |
1375 // this will call throwException(xRef) with the proper Throwable | |
1376 ti.setStopped(xRef); | |
1377 } | |
1378 | |
1379 void setCallEnvironment (MethodInfo mi) { | |
1380 this.mi = mi; | |
1381 | |
1382 if (mi != null){ | |
1383 ciMth = mi.getClassInfo(); | |
1384 } else { | |
1385 //ciMth = null; | |
1386 //mi = null; | |
1387 } | |
1388 | |
1389 repeat = false; | |
1390 returnAttr = null; | |
1391 | |
1392 // we should NOT reset exceptionRef here because it might have been set | |
1393 // at the beginning of the transition. It gets reset upon return from the | |
1394 // native method | |
1395 //exceptionRef = NULL; | |
1396 } | |
1397 | |
1398 void clearCallEnvironment () { | |
1399 setCallEnvironment(null); | |
1400 } | |
1401 | |
1402 ElementInfo getStaticElementInfo (int clsObjRef) { | |
1403 ClassInfo ci = getReferredClassInfo( clsObjRef); | |
1404 if (ci != null) { | |
1405 return ci.getStaticElementInfo(); | |
1406 } | |
1407 | |
1408 return null; | |
1409 } | |
1410 | |
1411 ElementInfo getModifiableStaticElementInfo (int clsObjRef) { | |
1412 ClassInfo ci = getReferredClassInfo( clsObjRef); | |
1413 if (ci != null) { | |
1414 return ci.getModifiableStaticElementInfo(); | |
1415 } | |
1416 | |
1417 return null; | |
1418 } | |
1419 | |
1420 | |
1421 ClassInfo getClassInfo () { | |
1422 return ciMth; | |
1423 } | |
1424 | |
1425 public ClassInfo getReferredClassInfo (int clsObjRef) { | |
1426 ElementInfo ei = getElementInfo(clsObjRef); | |
1427 if (ei.getClassInfo().getName().equals("java.lang.Class")) { | |
1428 int ciId = ei.getIntField( ClassInfo.ID_FIELD); | |
1429 int clref = ei.getReferenceField("classLoader"); | |
1430 | |
1431 ElementInfo eiCl = getElementInfo(clref); | |
1432 int cliId = eiCl.getIntField(ClassLoaderInfo.ID_FIELD); | |
1433 | |
1434 ClassLoaderInfo cli = getVM().getClassLoader(cliId); | |
1435 ClassInfo referredCi = cli.getClassInfo(ciId); | |
1436 | |
1437 return referredCi; | |
1438 | |
1439 } else { | |
1440 throw new JPFException("not a java.lang.Class object: " + ei); | |
1441 } | |
1442 } | |
1443 | |
1444 public ClassInfo getClassInfo (int objref) { | |
1445 ElementInfo ei = getElementInfo(objref); | |
1446 if (ei != null){ | |
1447 return ei.getClassInfo(); | |
1448 } else { | |
1449 return null; | |
1450 } | |
1451 } | |
1452 | |
1453 public String getClassName (int objref) { | |
1454 return getClassInfo(objref).getName(); | |
1455 } | |
1456 | |
1457 public Heap getHeap () { | |
1458 return vm.getHeap(); | |
1459 } | |
1460 | |
1461 public ElementInfo getElementInfo (int objref) { | |
1462 return heap.get(objref); | |
1463 } | |
1464 | |
1465 public ElementInfo getModifiableElementInfo (int objref) { | |
1466 return heap.getModifiable(objref); | |
1467 } | |
1468 | |
1469 | |
1470 public int getStateId () { | |
1471 return VM.getVM().getStateId(); | |
1472 } | |
1473 | |
1474 void clearException(){ | |
1475 exceptionRef = MJIEnv.NULL; | |
1476 } | |
1477 | |
1478 public int peekException () { | |
1479 return exceptionRef; | |
1480 } | |
1481 | |
1482 public int popException () { | |
1483 int ret = exceptionRef; | |
1484 exceptionRef = NULL; | |
1485 return ret; | |
1486 } | |
1487 | |
1488 public boolean hasException(){ | |
1489 return (exceptionRef != NULL); | |
1490 } | |
1491 | |
1492 public boolean hasPendingInterrupt(){ | |
1493 return (exceptionRef != NULL && isInstanceOf(exceptionRef, "java.lang.InterruptedException")); | |
1494 } | |
1495 | |
1496 //-- time is managed by the VM | |
1497 public long currentTimeMillis(){ | |
1498 return vm.currentTimeMillis(); | |
1499 } | |
1500 | |
1501 public long nanoTime(){ | |
1502 return vm.nanoTime(); | |
1503 } | |
1504 | |
1505 //--- those are not public since they refer to JPF internals | |
1506 public KernelState getKernelState () { | |
1507 return VM.getVM().getKernelState(); | |
1508 } | |
1509 | |
1510 public MethodInfo getMethodInfo () { | |
1511 return mi; | |
1512 } | |
1513 | |
1514 public Instruction getInstruction () { | |
1515 return ti.getPC(); | |
1516 } | |
1517 | |
1518 /** | |
1519 * It returns the ClassLoaderInfo corresponding to the given classloader object | |
1520 * reference | |
1521 */ | |
1522 public ClassLoaderInfo getClassLoaderInfo(int clObjRef) { | |
1523 if(clObjRef == MJIEnv.NULL) { | |
1524 return null; | |
1525 } | |
1526 | |
1527 int cliId = heap.get(clObjRef).getIntField(ClassLoaderInfo.ID_FIELD); | |
1528 return getVM().getClassLoader(cliId); | |
1529 } | |
1530 | |
1531 // <2do> that's not correct - it should return the current SystemClassLoader, NOT the startup SystemClassLoader | |
1532 // (we can instantiate them explicitly) | |
1533 public ClassLoaderInfo getSystemClassLoaderInfo() { | |
1534 return ti.getSystemClassLoaderInfo(); | |
1535 } | |
1536 | |
1537 public SystemState getSystemState () { | |
1538 return ti.getVM().getSystemState(); | |
1539 } | |
1540 | |
1541 public ApplicationContext getApplicationContext (){ | |
1542 return ti.getApplicationContext(); | |
1543 } | |
1544 | |
1545 public ThreadInfo getThreadInfo () { | |
1546 return ti; | |
1547 } | |
1548 | |
1549 /** | |
1550 * NOTE - callers have to be prepared this might return null in case | |
1551 * the thread got already terminated | |
1552 */ | |
1553 public ThreadInfo getThreadInfoForId (int id){ | |
1554 return vm.getThreadList().getThreadInfoForId(id); | |
1555 } | |
1556 | |
1557 public ThreadInfo getLiveThreadInfoForId (int id){ | |
1558 ThreadInfo ti = vm.getThreadList().getThreadInfoForId(id); | |
1559 if (ti != null && ti.isAlive()){ | |
1560 return ti; | |
1561 } | |
1562 | |
1563 return null; | |
1564 } | |
1565 | |
1566 /** | |
1567 * NOTE - callers have to be prepared this might return null in case | |
1568 * the thread got already terminated | |
1569 */ | |
1570 public ThreadInfo getThreadInfoForObjRef (int id){ | |
1571 return vm.getThreadList().getThreadInfoForObjRef(id); | |
1572 } | |
1573 | |
1574 public ThreadInfo getLiveThreadInfoForObjRef (int id){ | |
1575 ThreadInfo ti = vm.getThreadList().getThreadInfoForObjRef(id); | |
1576 if (ti != null && ti.isAlive()){ | |
1577 return ti; | |
1578 } | |
1579 | |
1580 return null; | |
1581 } | |
1582 | |
1583 | |
1584 | |
1585 public ThreadInfo[] getLiveThreads(){ | |
1586 return getVM().getLiveThreads(); | |
1587 } | |
1588 | |
1589 // <2do> - naming? not very intuitive | |
1590 void lockNotified (int objref) { | |
1591 ElementInfo ei = getModifiableElementInfo(objref); | |
1592 ei.lockNotified(ti); | |
1593 } | |
1594 | |
1595 void initAnnotationProxyField (int proxyRef, FieldInfo fi, Object v) throws ClinitRequired { | |
1596 String fname = fi.getName(); | |
1597 String ftype = fi.getType(); | |
1598 | |
1599 if (v instanceof String){ | |
1600 setReferenceField(proxyRef, fname, newString((String)v)); | |
1601 } else if (v instanceof Boolean){ | |
1602 setBooleanField(proxyRef, fname, ((Boolean)v).booleanValue()); | |
1603 } else if (v instanceof Integer){ | |
1604 setIntField(proxyRef, fname, ((Integer)v).intValue()); | |
1605 } else if (v instanceof Long){ | |
1606 setLongField(proxyRef, fname, ((Long)v).longValue()); | |
1607 } else if (v instanceof Float){ | |
1608 setFloatField(proxyRef, fname, ((Float)v).floatValue()); | |
1609 } else if (v instanceof Short){ | |
1610 setShortField(proxyRef, fname, ((Short)v).shortValue()); | |
1611 } else if (v instanceof Character){ | |
1612 setCharField(proxyRef, fname, ((Character)v).charValue()); | |
1613 } else if (v instanceof Byte){ | |
1614 setByteField(proxyRef, fname, ((Byte)v).byteValue()); | |
1615 } else if (v instanceof Double){ | |
1616 setDoubleField(proxyRef, fname, ((Double)v).doubleValue()); | |
1617 | |
1618 } else if (v instanceof AnnotationInfo.EnumValue){ // an enum constant | |
1619 AnnotationInfo.EnumValue ev = (AnnotationInfo.EnumValue)v; | |
1620 String eCls = ev.getEnumClassName(); | |
1621 String eConst = ev.getEnumConstName(); | |
1622 | |
1623 ClassInfo eci = ClassLoaderInfo.getCurrentResolvedClassInfo(eCls); | |
1624 if (!eci.isInitialized()){ | |
1625 throw new ClinitRequired(eci); | |
1626 } | |
1627 | |
1628 StaticElementInfo sei = eci.getStaticElementInfo(); | |
1629 int eref = sei.getReferenceField(eConst); | |
1630 setReferenceField(proxyRef, fname, eref); | |
1631 | |
1632 } else if (v instanceof AnnotationInfo.ClassValue){ // a class | |
1633 String clsName = v.toString(); | |
1634 ClassInfo cci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
1635 // <2do> should throw ClassNotFoundError here if cci is null | |
1636 | |
1637 if (!cci.isInitialized()){ | |
1638 throw new ClinitRequired(cci); | |
1639 } | |
1640 | |
1641 int cref = cci.getClassObjectRef(); | |
1642 setReferenceField(proxyRef, fname, cref); | |
1643 | |
1644 } else if (v.getClass().isArray()){ // ..or arrays thereof | |
1645 Object[] a = (Object[])v; | |
1646 int aref = NULL; | |
1647 | |
1648 if (ftype.equals("java.lang.String[]")){ | |
1649 aref = newObjectArray("Ljava/lang/String;", a.length); | |
1650 for (int i=0; i<a.length; i++){ | |
1651 setReferenceArrayElement(aref,i,newString(a[i].toString())); | |
1652 } | |
1653 } else if (ftype.equals("int[]")){ | |
1654 aref = newIntArray(a.length); | |
1655 for (int i=0; i<a.length; i++){ | |
1656 setIntArrayElement(aref,i,((Number)a[i]).intValue()); | |
1657 } | |
1658 } else if (ftype.equals("boolean[]")){ | |
1659 aref = newBooleanArray(a.length); | |
1660 for (int i=0; i<a.length; i++){ | |
1661 setBooleanArrayElement(aref,i,((Boolean)a[i]).booleanValue()); | |
1662 } | |
1663 } else if (ftype.equals("long[]")){ | |
1664 aref = newLongArray(a.length); | |
1665 for (int i=0; i<a.length; i++){ | |
1666 setLongArrayElement(aref,i,((Number)a[i]).longValue()); | |
1667 } | |
1668 } else if (ftype.equals("double[]")){ | |
1669 aref = newDoubleArray(a.length); | |
1670 for (int i=0; i<a.length; i++){ | |
1671 setDoubleArrayElement(aref,i,((Number)a[i]).doubleValue()); | |
1672 } | |
1673 } else if (ftype.equals("java.lang.Class[]")){ | |
1674 aref = newObjectArray("java.lang.Class", a.length); | |
1675 for (int i=0; i<a.length; i++){ | |
1676 String clsName = ((AnnotationInfo.ClassValue)a[i]).getName(); | |
1677 ClassInfo cci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName); | |
1678 if (!cci.isInitialized()){ | |
1679 throw new ClinitRequired(cci); | |
1680 } | |
1681 int cref = cci.getClassObjectRef(); | |
1682 setReferenceArrayElement(aref,i,cref); | |
1683 } | |
1684 } | |
1685 | |
1686 if (aref != NULL){ | |
1687 setReferenceField(proxyRef, fname, aref); | |
1688 } else { | |
1689 throwException("AnnotationElement type not supported: " + ftype); | |
1690 } | |
1691 | |
1692 } else { | |
1693 throwException("AnnotationElement type not supported: " + ftype); | |
1694 } | |
1695 } | |
1696 | |
1697 int newAnnotationProxy (ClassInfo aciProxy, AnnotationInfo ai) throws ClinitRequired { | |
1698 | |
1699 int proxyRef = newObject(aciProxy); | |
1700 | |
1701 // init fields of the new object from the AnnotationInfo | |
1702 for (AnnotationInfo.Entry e : ai.getEntries()){ | |
1703 Object v = e.getValue(); | |
1704 String fname = e.getKey(); | |
1705 FieldInfo fi = aciProxy.getInstanceField(fname); | |
1706 | |
1707 initAnnotationProxyField(proxyRef, fi, v); | |
1708 } | |
1709 | |
1710 return proxyRef; | |
1711 } | |
1712 | |
1713 int newAnnotationProxies (AnnotationInfo[] ai) throws ClinitRequired { | |
1714 | |
1715 if ((ai != null) && (ai.length > 0)){ | |
1716 int aref = newObjectArray("Ljava/lang/annotation/Annotation;", ai.length); | |
1717 for (int i=0; i<ai.length; i++){ | |
1718 ClassInfo aci = ClassLoaderInfo.getCurrentResolvedClassInfo(ai[i].getName()); | |
1719 ClassInfo aciProxy = aci.getAnnotationProxy(); | |
1720 | |
1721 int ar = newAnnotationProxy(aciProxy, ai[i]); | |
1722 setReferenceArrayElement(aref, i, ar); | |
1723 } | |
1724 return aref; | |
1725 | |
1726 } else { | |
1727 // on demand init (not too many programs use annotation reflection) | |
1728 int aref = getStaticReferenceField("java.lang.Class", "emptyAnnotations"); | |
1729 if (aref == NULL) { | |
1730 aref = newObjectArray("Ljava/lang/annotation/Annotation;", 0); | |
1731 setStaticReferenceField("java.lang.Class", "emptyAnnotations", aref); | |
1732 } | |
1733 return aref; | |
1734 } | |
1735 } | |
1736 | |
1737 public void handleClinitRequest (ClassInfo ci) { | |
1738 ThreadInfo ti = getThreadInfo(); | |
1739 | |
1740 // NOTE: we have to repeat no matter what, since this is called from | |
1741 // a handler context (if we only had to create a class object w/o | |
1742 // calling clinit, we can't just go on) | |
1743 ci.pushRequiredClinits(ti); | |
1744 repeatInvocation(); | |
1745 } | |
1746 | |
1747 public StackFrame getCallerStackFrame() { | |
1748 // since native methods are now executed within their own stack frames | |
1749 // we provide a little helper to get the caller | |
1750 return ti.getLastNonSyntheticStackFrame(); | |
1751 } | |
1752 | |
1753 public StackFrame getModifiableCallerStackFrame() { | |
1754 // since native methods are now executed within their own stack frames | |
1755 // we provide a little helper to get the caller | |
1756 return ti.getModifiableLastNonSyntheticStackFrame(); | |
1757 } | |
1758 | |
1759 | |
1760 public int valueOfBoolean(boolean b) { | |
1761 return BoxObjectCacheManager.valueOfBoolean(ti, b); | |
1762 } | |
1763 | |
1764 public int valueOfByte(byte b) { | |
1765 return BoxObjectCacheManager.valueOfByte(ti, b); | |
1766 } | |
1767 | |
1768 public int valueOfCharacter(char c) { | |
1769 return BoxObjectCacheManager.valueOfCharacter(ti, c); | |
1770 } | |
1771 | |
1772 public int valueOfShort(short s) { | |
1773 return BoxObjectCacheManager.valueOfShort(ti, s); | |
1774 } | |
1775 | |
1776 public int valueOfInteger(int i) { | |
1777 return BoxObjectCacheManager.valueOfInteger(ti, i); | |
1778 } | |
1779 | |
1780 public int valueOfLong(long l) { | |
1781 return BoxObjectCacheManager.valueOfLong(ti, l); | |
1782 } | |
1783 } |