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 }