Fixing the ClassLoader.defineClass() method issue that could not find the necessary...
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_sun_misc_Unsafe.java
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.JPFException;
21 import gov.nasa.jpf.annotation.MJI;
22 import gov.nasa.jpf.vm.ArrayFields;
23 import gov.nasa.jpf.vm.ElementInfo;
24 import gov.nasa.jpf.vm.FieldInfo;
25 import gov.nasa.jpf.vm.MJIEnv;
26 import gov.nasa.jpf.vm.NativePeer;
27 import gov.nasa.jpf.vm.SystemState;
28 import gov.nasa.jpf.vm.ThreadInfo;
29
30
31 /**
32  * we don't want this class! This is a hodgepodge of stuff that shouldn't be in Java, but
33  * is handy for some hacks. The reason we have it here - very rudimentary - is that
34  * java.util.concurrent makes use of the atomic compare&swap which is in it.
35  * The choice was to duplicate a lot of relatively difficult code in the "right" class
36  * (java.util.concurrent.locks.AbstractQueuedSynchronizer) or a small amount of straight forward
37  * code in the "wrong" class (sun.misc.Unsafe). Knowing a bit about the "library chase" game,
38  * we opt for the latter
39  *
40  * <2do> this might change with better modeling of high level java.util.concurrent constructs
41  */
42 public class JPF_sun_misc_Unsafe extends NativePeer {
43
44   @MJI
45   public int getUnsafe____Lsun_misc_Unsafe_2 (MJIEnv env, int clsRef) {
46     int objRef = env.getStaticReferenceField("sun.misc.Unsafe", "theUnsafe");
47     return objRef;
48   }
49
50   @MJI
51   public long objectFieldOffset__Ljava_lang_reflect_Field_2__J (MJIEnv env, int unsafeRef, int fieldRef) {
52     return fieldOffset__Ljava_lang_reflect_Field_2__I(env, unsafeRef, fieldRef);
53   }
54
55   /**
56    * we don't really return an offset here, since that would be useless. What we really want is
57    * to identify the corresponding FieldInfo, and that's much easier done with the Field
58    * registration id
59    */
60   @MJI
61   public int fieldOffset__Ljava_lang_reflect_Field_2__I (MJIEnv env, int unsafeRef, int fieldRef) {
62     //FieldInfo fi = JPF_java_lang_reflect_Field.getFieldInfo(env, fieldRef);
63     //return fi.getStorageOffset();
64     return env.getIntField(fieldRef, "regIdx");
65   }
66
67   @MJI
68   public boolean compareAndSwapObject__Ljava_lang_Object_2JLjava_lang_Object_2Ljava_lang_Object_2__Z (MJIEnv env, int unsafeRef,
69                                                                                                              int objRef, long fieldOffset,
70                                                                                                              int expectRef, int updateRef) {
71     int actual = getObject__Ljava_lang_Object_2J__Ljava_lang_Object_2(env, unsafeRef, objRef, fieldOffset);
72     if (actual == expectRef) {
73       putObject__Ljava_lang_Object_2JLjava_lang_Object_2__V(env, unsafeRef, objRef, fieldOffset, updateRef);
74       return true;
75     }
76     return false;
77   }
78
79   @MJI
80   public boolean compareAndSwapInt__Ljava_lang_Object_2JII__Z (MJIEnv env, int unsafeRef,
81                                                                       int objRef, long fieldOffset, int expect, int update) {
82     int actual = getInt__Ljava_lang_Object_2J__I(env, unsafeRef, objRef, fieldOffset);
83     if (actual == expect) {
84       putInt__Ljava_lang_Object_2JI__V(env, unsafeRef, objRef, fieldOffset, update);
85       return true;
86     }
87     return false;
88   }
89
90   @MJI
91   public boolean compareAndSwapLong__Ljava_lang_Object_2JJJ__Z (MJIEnv env, int unsafeRef,
92                                                                        int objRef, long fieldOffset, long expect, long update) {
93     long actual = getLong__Ljava_lang_Object_2J__J(env, unsafeRef, objRef, fieldOffset);
94     if (actual == expect) {
95       putLong__Ljava_lang_Object_2JJ__V(env, unsafeRef, objRef, fieldOffset, update);
96       return true;
97     }
98     return false;
99   }
100
101
102   // this is a specialized, native wait() for the current thread that does not require a lock, and that can
103   // be turned off by a preceding unpark() call (which is not accumulative)
104   // park can be interrupted, but it doesn't throw an InterruptedException, and it doesn't clear the status
105   // it can only be called from the current (parking) thread
106   @MJI
107   public void park__ZJ__V (MJIEnv env, int unsafeRef, boolean isAbsoluteTime, long timeout) {
108     ThreadInfo ti = env.getThreadInfo();
109     int objRef = ti.getThreadObjectRef();
110     int permitRef = env.getReferenceField( objRef, "permit");
111     ElementInfo ei = env.getModifiableElementInfo(permitRef);
112
113     if (ti.isInterrupted(false)) {
114       // there is no lock, so we go directly back to running and therefore
115       // have to remove ourself from the contender list
116       ei.setMonitorWithoutLocked(ti);
117
118       // note that park() does not throw an InterruptedException
119       return;
120     }
121     
122     if (!ti.isFirstStepInsn()){
123       if (ei.getBooleanField("blockPark")) { // we have to wait, but don't need a lock
124         // running -> waiting | timeout_waiting
125         ei.wait(ti, timeout, false);
126         
127       } else {
128         ei.setBooleanField("blockPark", true); // re-arm for next park
129         return;
130       }
131     }
132     
133     // scheduling point
134     if (ti.getScheduler().setsParkCG( ti, isAbsoluteTime, timeout)) {
135       env.repeatInvocation();
136       return;
137     }
138     
139     switch (ti.getState()) {
140       case WAITING:
141       case TIMEOUT_WAITING:
142         throw new JPFException("blocking park() without transition break");   
143       
144       case NOTIFIED:
145       case TIMEDOUT:
146       case INTERRUPTED:
147         ti.resetLockRef();
148         ti.setRunning();
149         break;
150         
151       default:
152         // nothing
153     } 
154   }
155
156   @MJI
157   public void unpark__Ljava_lang_Object_2__V (MJIEnv env, int unsafeRef, int objRef) {
158     ThreadInfo tiCurrent = env.getThreadInfo();
159     ThreadInfo tiParked = env.getThreadInfoForObjRef(objRef);
160       
161     if (tiParked.isTerminated()){
162       return; // nothing to do
163     }
164     
165     if (!tiCurrent.isFirstStepInsn()){
166       SystemState ss = env.getSystemState();
167       int permitRef = env.getReferenceField( objRef, "permit");
168       ElementInfo eiPermit = env.getModifiableElementInfo(permitRef);
169
170       if (tiParked.getLockObject() == eiPermit){
171         // note that 'permit' is only used in park/unpark, so there never is more than
172         // one waiter, which immediately becomes runnable again because it doesn't hold a lock
173         // (park is a lockfree wait). unpark() therefore has to be a right mover
174         // and we have to register a ThreadCG here
175         eiPermit.notifies(ss, tiCurrent, false);
176         
177       } else {
178         eiPermit.setBooleanField("blockPark", false);
179         return;
180       }
181     }
182     
183     if (tiCurrent.getScheduler().setsUnparkCG(tiCurrent, tiParked)){
184       env.repeatInvocation();
185       return;
186     }
187   }
188   
189   @MJI
190   public void ensureClassInitialized__Ljava_lang_Class_2__V (MJIEnv env, int unsafeRef, int clsObjRef) {
191     // <2do> not sure if we have to do anyting here - if we have a class object, the class should already
192     // be initialized
193   }
194
195   @MJI
196   public int getObject__Ljava_lang_Object_2J__Ljava_lang_Object_2 (MJIEnv env, int unsafeRef,
197                                                                           int objRef, long fieldOffset) {
198     ElementInfo ei = env.getElementInfo(objRef);
199     if (!ei.isArray()) {
200       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
201       return ei.getReferenceField(fi);
202     } else {
203       return ei.getReferenceElement((int)fieldOffset);
204     }
205   }
206   
207   @MJI
208   public int getObjectVolatile__Ljava_lang_Object_2J__Ljava_lang_Object_2 (MJIEnv env, int unsafeRef,
209       int objRef, long fieldOffset) {
210     return getObject__Ljava_lang_Object_2J__Ljava_lang_Object_2( env, unsafeRef, objRef, fieldOffset);
211   }  
212
213   @MJI
214   public void putObject__Ljava_lang_Object_2JLjava_lang_Object_2__V (MJIEnv env, int unsafeRef,
215                                                                             int objRef, long fieldOffset, int valRef) {
216     ElementInfo ei = env.getModifiableElementInfo(objRef);
217     
218     if (!ei.isArray()) {
219       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
220       ei.setReferenceField(fi, valRef);
221     } else {
222       ei.setReferenceElement((int)fieldOffset, valRef);
223     }
224   }
225   
226   @MJI
227   public void putObjectVolatile__Ljava_lang_Object_2JLjava_lang_Object_2__V (MJIEnv env, int unsafeRef,
228       int objRef, long fieldOffset, int valRef) {
229     putObject__Ljava_lang_Object_2JLjava_lang_Object_2__V( env, unsafeRef, objRef, fieldOffset, valRef);
230   }
231
232   @MJI
233   public void putOrderedObject__Ljava_lang_Object_2JLjava_lang_Object_2__V(
234                                                                                   MJIEnv env,
235                                                                                   int unsafeRef,
236                                                                                   int objRef,
237                                                                                   long fieldOffset,
238                                                                                   int valRef) {
239     putObject__Ljava_lang_Object_2JLjava_lang_Object_2__V(env, unsafeRef, objRef, fieldOffset, valRef);
240   }
241   
242   @MJI
243   public boolean getBoolean__Ljava_lang_Object_2J__Z(MJIEnv env,
244                                                             int unsafeRef,
245                                                             int objRef,
246                                                             long fieldOffset) {
247     ElementInfo ei = env.getElementInfo(objRef);
248     if (!ei.isArray()) {
249       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
250       return ei.getBooleanField(fi);
251     } else {
252       return ei.getBooleanElement((int)fieldOffset);
253     }
254   }
255
256   @MJI
257   public boolean getBooleanVolatile__Ljava_lang_Object_2J__Z(MJIEnv env, int unsafeRef,int objRef,long fieldOffset) {
258     return getBoolean__Ljava_lang_Object_2J__Z( env, unsafeRef, objRef, fieldOffset);
259   }
260   
261   @MJI
262   public void putBoolean__Ljava_lang_Object_2JZ__V (MJIEnv env, int unsafeRef,
263                                                        int objRef, long fieldOffset, boolean val){
264     ElementInfo ei = env.getModifiableElementInfo(objRef);
265     if (!ei.isArray()) {
266       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
267       ei.setBooleanField(fi, val);
268     } else {
269       ei.setBooleanElement((int)fieldOffset, val);
270     }
271   }
272
273   @MJI
274   public void putBooleanVolatile__Ljava_lang_Object_2JZ__V (MJIEnv env, int unsafeRef, int objRef, long fieldOffset, boolean val){
275     putBoolean__Ljava_lang_Object_2JZ__V( env, unsafeRef, objRef, fieldOffset, val);
276   }
277
278   @MJI
279   public byte getByte__Ljava_lang_Object_2J__B(MJIEnv env,
280                                                       int unsafeRef,
281                                                       int objRef,
282                                                       long fieldOffset) {
283     ElementInfo ei = env.getElementInfo(objRef);
284     if (!ei.isArray()) {
285       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
286       return ei.getByteField(fi);
287     } else {
288       return ei.getByteElement((int)fieldOffset);
289     }
290   }
291
292   @MJI
293   public byte getByteVolatile__Ljava_lang_Object_2J__B(MJIEnv env,int unsafeRef,int objRef,long fieldOffset) {
294     return getByte__Ljava_lang_Object_2J__B(env, unsafeRef, objRef, fieldOffset);
295   }
296
297   @MJI
298   public void putByte__Ljava_lang_Object_2JB__V (MJIEnv env, int unsafeRef,
299                                                        int objRef, long fieldOffset, byte val){
300     ElementInfo ei = env.getModifiableElementInfo(objRef);
301     if (!ei.isArray()) {
302       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
303       ei.setByteField(fi, val);
304     } else {
305       ei.setByteElement((int)fieldOffset, val);
306     }
307   }
308
309   @MJI
310   public void putByteVolatile__Ljava_lang_Object_2JB__V (MJIEnv env, int unsafeRef,int objRef, long fieldOffset, byte val){
311     putByte__Ljava_lang_Object_2JB__V( env, unsafeRef, objRef, fieldOffset, val);
312   }
313
314   @MJI
315   public char getChar__Ljava_lang_Object_2J__C(MJIEnv env,
316                                                       int unsafeRef,
317                                                       int objRef,
318                                                       long fieldOffset) {
319     ElementInfo ei = env.getElementInfo(objRef);
320     if (!ei.isArray()) {
321       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
322       return ei.getCharField(fi);
323     } else {
324       return ei.getCharElement((int)fieldOffset);
325     }
326   }
327
328   @MJI
329   public char getCharVolatile__Ljava_lang_Object_2J__C(MJIEnv env,int unsafeRef,int objRef,long fieldOffset) {
330     return getChar__Ljava_lang_Object_2J__C( env, unsafeRef, objRef, fieldOffset);
331   }
332   
333   @MJI
334   public void putChar__Ljava_lang_Object_2JC__V (MJIEnv env, int unsafeRef,
335                                                        int objRef, long fieldOffset, char val){
336     ElementInfo ei = env.getModifiableElementInfo(objRef);
337     if (!ei.isArray()) {
338       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
339       ei.setCharField(fi, val);
340     } else {
341       ei.setCharElement((int)fieldOffset, val);
342     }
343   }
344
345   @MJI
346   public void putCharVolatile__Ljava_lang_Object_2JC__V (MJIEnv env, int unsafeRef,int objRef, long fieldOffset, char val){
347     putChar__Ljava_lang_Object_2JC__V( env, unsafeRef, objRef, fieldOffset, val);
348   }
349   
350   @MJI
351   public short getShort__Ljava_lang_Object_2J__S(MJIEnv env,
352                                                         int unsafeRef,
353                                                         int objRef,
354                                                         long fieldOffset) {
355     ElementInfo ei = env.getElementInfo(objRef);
356     if (!ei.isArray()) {
357       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
358       return ei.getShortField(fi);
359     } else {
360       return ei.getShortElement((int)fieldOffset);
361     }
362   }
363
364   @MJI
365   public short getShortVolatile__Ljava_lang_Object_2J__S(MJIEnv env,int unsafeRef,int objRef,long fieldOffset) {
366     return getShort__Ljava_lang_Object_2J__S( env, unsafeRef, objRef, fieldOffset);
367   }
368   
369   @MJI
370   public void putShort__Ljava_lang_Object_2JS__V (MJIEnv env, int unsafeRef,
371                                                        int objRef, long fieldOffset, short val){
372     ElementInfo ei = env.getModifiableElementInfo(objRef);
373     if (!ei.isArray()) {
374       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
375       ei.setShortField(fi, val);
376     } else {
377       ei.setShortElement((int)fieldOffset, val);
378     }
379   }
380
381   @MJI
382   public void putShortVolatile__Ljava_lang_Object_2JS__V (MJIEnv env, int unsafeRef,int objRef, long fieldOffset, short val){
383     putShort__Ljava_lang_Object_2JS__V( env, unsafeRef, objRef, fieldOffset, val);
384   }  
385
386   @MJI
387   public int getInt__Ljava_lang_Object_2J__I(MJIEnv env, int unsafeRef,
388                                                     int objRef, long fieldOffset) {
389     ElementInfo ei = env.getElementInfo(objRef);
390     if (!ei.isArray()) {
391       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
392       return ei.getIntField(fi);
393     } else {
394       return ei.getIntElement((int)fieldOffset);
395     }
396   }
397
398   @MJI
399   public int getIntVolatile__Ljava_lang_Object_2J__I(MJIEnv env, int unsafeRef, int objRef, long fieldOffset) {
400     return getInt__Ljava_lang_Object_2J__I( env, unsafeRef, objRef, fieldOffset);
401   }
402   
403   @MJI
404   public void putInt__Ljava_lang_Object_2JI__V (MJIEnv env, int unsafeRef,
405                                                        int objRef, long fieldOffset, int val){
406     ElementInfo ei = env.getModifiableElementInfo(objRef);
407     if (!ei.isArray()) {
408       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
409       ei.setIntField(fi, val);
410     } else {
411       ei.setIntElement((int)fieldOffset, val);
412     }
413   }
414
415   @MJI
416   public void putIntVolatile__Ljava_lang_Object_2JI__V (MJIEnv env, int unsafeRef, int objRef, long fieldOffset, int val){
417     putInt__Ljava_lang_Object_2JI__V(env, unsafeRef, objRef, fieldOffset, val);
418   }  
419
420   @MJI
421   public void putOrderedInt__Ljava_lang_Object_2JI__V(MJIEnv env,
422                                                              int unsafeRef,
423                                                              int objRef,
424                                                              long fieldOffset,
425                                                              int val) {
426     // volatile?
427     putInt__Ljava_lang_Object_2JI__V(env, unsafeRef, objRef, fieldOffset, val);
428   }
429
430   @MJI
431   public float getFloat__Ljava_lang_Object_2J__F(MJIEnv env,
432                                                         int unsafeRef,
433                                                         int objRef,
434                                                         long fieldOffset) {
435     ElementInfo ei = env.getElementInfo(objRef);
436     if (!ei.isArray()) {
437       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
438       return ei.getFloatField(fi);
439     } else {
440       return ei.getFloatElement((int)fieldOffset);
441     }
442   }
443
444   @MJI
445   public float getFloatVolatile__Ljava_lang_Object_2J__F(MJIEnv env,int unsafeRef,int objRef,long fieldOffset) {
446     return getFloat__Ljava_lang_Object_2J__F( env, unsafeRef, objRef, fieldOffset);
447   }  
448
449   @MJI
450   public void putFloat__Ljava_lang_Object_2JF__V (MJIEnv env, int unsafeRef,
451                                                        int objRef, long fieldOffset, float val){
452     ElementInfo ei = env.getModifiableElementInfo(objRef);
453     if (!ei.isArray()) {
454       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
455       ei.setFloatField(fi, val);
456     } else {
457       ei.setFloatElement((int)fieldOffset, val);
458     }
459   }
460
461   @MJI
462   public void putFloatVolatile__Ljava_lang_Object_2JF__V (MJIEnv env, int unsafeRef,int objRef, long fieldOffset, float val){
463     putFloat__Ljava_lang_Object_2JF__V( env, unsafeRef, objRef, fieldOffset, val);
464   }  
465
466   @MJI
467   public long getLong__Ljava_lang_Object_2J__J(MJIEnv env,
468                                                       int unsafeRef,
469                                                       int objRef,
470                                                       long fieldOffset) {
471     ElementInfo ei = env.getElementInfo(objRef);
472     if (!ei.isArray()) {
473       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
474       return ei.getLongField(fi);
475     } else {
476       return ei.getLongElement((int)fieldOffset);
477     }
478   }
479
480   @MJI
481   public long getLongVolatile__Ljava_lang_Object_2J__J(MJIEnv env, int unsafeRef, int objRef, long fieldOffset) {
482     return getLong__Ljava_lang_Object_2J__J( env, unsafeRef, objRef, fieldOffset);
483   }
484
485   @MJI
486   public void putLong__Ljava_lang_Object_2JJ__V (MJIEnv env, int unsafeRef,
487                                                        int objRef, long fieldOffset, long val){
488     ElementInfo ei = env.getModifiableElementInfo(objRef);
489     if (!ei.isArray()) {
490       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
491       ei.setLongField(fi, val);
492     } else {
493       ei.setLongElement((int)fieldOffset, val);
494     }
495   }
496
497   @MJI
498   public void putLongVolatile__Ljava_lang_Object_2JJ__V (MJIEnv env, int unsafeRef, int objRef, long fieldOffset, long val){
499     putLong__Ljava_lang_Object_2JJ__V( env, unsafeRef, objRef, fieldOffset, val);
500   }  
501
502   @MJI
503   public void putOrderedLong__Ljava_lang_Object_2JJ__V (MJIEnv env, int unsafeRef,
504                                                         int objRef, long fieldOffset, long val) {
505     putLong__Ljava_lang_Object_2JJ__V(env, unsafeRef, objRef, fieldOffset, val);
506   }
507
508   @MJI
509   public double getDouble__Ljava_lang_Object_2J__D(MJIEnv env,
510                                                          int unsafeRef,
511                                                          int objRef,
512                                                          long fieldOffset) {
513     ElementInfo ei = env.getElementInfo(objRef);
514     if (!ei.isArray()) {
515       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
516       return ei.getDoubleField(fi);
517     } else {
518       return ei.getDoubleElement((int)fieldOffset);
519     }
520   }
521
522   @MJI
523   public double getDoubleVolatile__Ljava_lang_Object_2J__D(MJIEnv env,int unsafeRef,int objRef,long fieldOffset) {
524     return getDouble__Ljava_lang_Object_2J__D( env, unsafeRef, objRef, fieldOffset);
525   }
526   
527   @MJI
528   public void putDouble__Ljava_lang_Object_2JD__V (MJIEnv env, int unsafeRef,
529                                                        int objRef, long fieldOffset, double val){
530     ElementInfo ei = env.getModifiableElementInfo(objRef);
531     if (!ei.isArray()) {
532       FieldInfo fi = getRegisteredFieldInfo(fieldOffset);
533       ei.setDoubleField(fi, val);
534     } else {
535       ei.setDoubleElement((int)fieldOffset, val);
536     }
537   }
538
539   @MJI
540   public void putDoubleVolatile__Ljava_lang_Object_2JD__V (MJIEnv env, int unsafeRef, int objRef, long fieldOffset, double val){
541     putDouble__Ljava_lang_Object_2JD__V( env, unsafeRef, objRef, fieldOffset, val);
542   }
543   
544   @MJI
545   public int arrayBaseOffset__Ljava_lang_Class_2__I (MJIEnv env, int unsafeRef, int clazz) {
546     return 0;
547   }
548
549   @MJI
550   public int arrayIndexScale__Ljava_lang_Class_2__I (MJIEnv env, int unsafeRef, int clazz) {
551     return 1;
552   }
553
554   private static FieldInfo getRegisteredFieldInfo(long fieldOffset) {
555     return JPF_java_lang_reflect_Field.getRegisteredFieldInfo((int)fieldOffset);
556   }
557
558   
559   //--- the explicit memory buffer allocation/free + access methods - evil pointer arithmetic
560
561   /*
562    * we shy away from maintaining our own address table by means of knowing that
563    * the byte[] object stored in the ArrayFields will not be recycled, and hashCode() will
564    * return its address, so the start/endAdr pairs we get from that have to be
565    * non-overlapping. Of course that falls apart if  hashCode() would do something
566    * different, which is the case for any address that exceeds 32bit
567    */
568   
569   static class Alloc {
570     int objRef;
571     
572     int startAdr;
573     int endAdr;
574     
575     Alloc next;
576     
577     Alloc (MJIEnv env, int baRef, long length){
578       this.objRef = baRef;
579
580       ElementInfo ei = env.getElementInfo(baRef);
581       ArrayFields afi = (ArrayFields) ei.getFields();
582       byte[] mem = afi.asByteArray();
583
584       startAdr = mem.hashCode();
585       endAdr = startAdr + (int)length -1;
586     }
587     
588     @Override
589         public String toString(){
590       return String.format("Alloc[objRef=%x,startAdr=%x,endAdr=%x]", objRef, startAdr, endAdr);
591     }
592   }
593   
594   Alloc firstAlloc;
595   
596   // for debugging purposes only
597   private void dumpAllocs(){
598     System.out.println("Unsafe allocated memory blocks:{");
599     for (Alloc a = firstAlloc; a != null; a = a.next){
600       System.out.print("  ");
601       System.out.println(a);
602     }
603     System.out.println('}');
604   }
605   
606   private void sortInAlloc(Alloc newAlloc){
607     int startAdr = newAlloc.startAdr;
608     
609     if (firstAlloc == null){
610       firstAlloc = newAlloc;
611       
612     } else {
613       Alloc prev = null;
614       for (Alloc a = firstAlloc; a != null; prev = a, a = a.next){
615         if (startAdr < a.startAdr){
616           newAlloc.next = a;
617           if (prev == null){
618             firstAlloc = newAlloc;
619           } else {
620             prev.next = newAlloc;
621           }
622         }
623       }
624     }
625   }
626   
627   private Alloc getAlloc (int address){
628     for (Alloc a = firstAlloc; a != null; a = a.next){
629       if (address >= a.startAdr && address <= a.endAdr){
630         return a;
631       }
632     }
633     
634     return null;
635   }
636   
637   private Alloc removeAlloc (int startAddress){
638     Alloc prev = null;
639     for (Alloc a = firstAlloc; a != null; prev = a, a = a.next) {
640       if (a.startAdr == startAddress){
641         if (prev == null){
642           firstAlloc = a.next;
643         } else {
644           prev.next = a.next;
645         }
646         
647         return a;
648       }
649     }
650     
651     return null;
652   }
653   
654   @MJI
655   public long allocateMemory__J__J (MJIEnv env, int unsafeRef, long nBytes) {
656     if (nBytes < 0 || nBytes > Integer.MAX_VALUE) {
657       env.throwException("java.lang.IllegalArgumentException", "invalid memory block size: " + nBytes);
658       return 0;
659     }
660     
661     // <2do> we should probably also throw OutOfMemoryErrors on configured thresholds 
662     
663     int baRef = env.newByteArray((int) nBytes);
664     // the corresponding objects have to be freed explicitly
665     env.registerPinDown(baRef);
666     
667     Alloc alloc = new Alloc(env, baRef, nBytes);
668     sortInAlloc(alloc);
669     
670     return alloc.startAdr;
671   }
672   
673   @MJI
674   public void freeMemory__J__V (MJIEnv env, int unsafeRef, long startAddress) {
675     int addr = (int)startAddress;
676
677     if (startAddress != MJIEnv.NULL){
678       Alloc a = removeAlloc(addr);
679       if (a == null){
680         env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
681       } else {
682         env.releasePinDown(a.objRef);
683       }
684     }
685   }
686   
687   @MJI
688   public byte getByte__J__B (MJIEnv env, int unsafeRef, long address) {
689     int addr = (int)address;
690     Alloc a = getAlloc(addr);
691     
692     if (a == null) {
693       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
694       return 0;
695     }
696     
697     ElementInfo ei = env.getElementInfo(a.objRef);
698     return ei.getByteElement(addr - a.startAdr);
699   }
700
701   @MJI
702   public void putByte__JB__V (MJIEnv env, int unsafeRef, long address, byte val) {
703     int addr = (int)address;
704     Alloc a = getAlloc(addr);
705     
706     if (a == null) {
707       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
708       return;
709     }
710     
711     ElementInfo ei = env.getModifiableElementInfo(a.objRef);
712     ei.setByteElement(addr - a.startAdr, val);
713   }
714   
715   @MJI
716   public char getChar__J__C (MJIEnv env, int unsafeRef, long address) {
717     int addr = (int)address;
718     Alloc a = getAlloc(addr);
719     
720     if (a == null) {
721       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
722       return 0;
723     }
724     
725     ElementInfo ei = env.getElementInfo(a.objRef);
726     byte[] ba = ei.asByteArray();
727     
728     byte b0 = ba[addr];
729     byte b1 = ba[addr+1];
730     
731     char val;
732     if (env.isBigEndianPlatform()){
733       val = (char) ((b0 << 8) | b1);
734     } else {
735       val = (char) ((b1 << 8) | b0);      
736     }
737     
738     return val;
739   }
740
741   @MJI
742   public void putChar__JC__V (MJIEnv env, int unsafeRef, long address, char val) {
743     int addr = (int)address;
744     Alloc a = getAlloc(addr);
745     
746     if (a == null) {
747       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
748       return;
749     }
750         
751     byte b1 = (byte)(0xff & val);
752     byte b0 = (byte)(0xff & (val >>> 8));
753     
754     ElementInfo ei = env.getModifiableElementInfo(a.objRef);
755
756     if (env.isBigEndianPlatform()){
757       ei.setByteElement(addr,   b0);
758       ei.setByteElement(addr+1, b1);
759     } else {
760       ei.setByteElement(addr,   b1);
761       ei.setByteElement(addr+1, b0);      
762     }
763   }
764
765   @MJI
766   public int getInt__J__I (MJIEnv env, int unsafeRef, long address) {
767     int addr = (int)address;
768     Alloc a = getAlloc(addr);
769     
770     if (a == null) {
771       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
772       return 0;
773     }
774     
775     ElementInfo ei = env.getElementInfo(a.objRef);
776     byte[] ba = ei.asByteArray();
777     
778     byte b0 = ba[addr];
779     byte b1 = ba[addr+1];
780     byte b2 = ba[addr+2];
781     byte b3 = ba[addr+3];
782     
783     int val;
784     if (env.isBigEndianPlatform()){
785       val = b0;
786       val = (val << 8) | b1;
787       val = (val << 8) | b2;
788       val = (val << 8) | b3;
789
790     } else {
791       val = b3;
792       val = (val << 8) | b2;
793       val = (val << 8) | b1;
794       val = (val << 8) | b0;
795     }
796     
797     return val;
798   }
799
800   @MJI
801   public void putInt__JI__V (MJIEnv env, int unsafeRef, long address, int val) {
802     int addr = (int)address;
803     Alloc a = getAlloc(addr);
804     
805     if (a == null) {
806       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
807       return;
808     }
809         
810     byte b3 = (byte)(0xff & val);
811     byte b2 = (byte)(0xff & (val >>> 8));
812     byte b1 = (byte)(0xff & (val >>> 16));
813     byte b0 = (byte)(0xff & (val >>> 24));    
814     
815     ElementInfo ei = env.getModifiableElementInfo(a.objRef);
816
817     if (env.isBigEndianPlatform()){
818       ei.setByteElement(addr,   b0);
819       ei.setByteElement(addr+1, b1);
820       ei.setByteElement(addr+2, b2);
821       ei.setByteElement(addr+3, b3);
822     } else {
823       ei.setByteElement(addr,   b3);
824       ei.setByteElement(addr+1, b2);
825       ei.setByteElement(addr+2, b1);
826       ei.setByteElement(addr+3, b0);
827     }
828   }
829
830   @MJI
831   public long getLong__J__J (MJIEnv env, int unsafeRef, long address) {
832     int addr = (int)address;
833     Alloc a = getAlloc(addr);
834     
835     if (a == null) {
836       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
837       return 0;
838     }
839     
840     ElementInfo ei = env.getElementInfo(a.objRef);
841     byte[] ba = ei.asByteArray();
842     int offset = addr - a.startAdr;
843     
844     byte b0 = ba[offset];
845     byte b1 = ba[offset+1];
846     byte b2 = ba[offset+2];
847     byte b3 = ba[offset+3];
848     byte b4 = ba[offset+4];
849     byte b5 = ba[offset+5];
850     byte b6 = ba[offset+6];
851     byte b7 = ba[offset+7];
852     
853     int val;
854     if (env.isBigEndianPlatform()){
855       val = b0;
856       val = (val << 8) | b1;
857       val = (val << 8) | b2;
858       val = (val << 8) | b3;
859       val = (val << 8) | b4;
860       val = (val << 8) | b5;
861       val = (val << 8) | b6;
862       val = (val << 8) | b7;
863
864     } else {
865       val = b7;
866       val = (val << 8) | b6;
867       val = (val << 8) | b5;
868       val = (val << 8) | b4;
869       val = (val << 8) | b3;
870       val = (val << 8) | b2;
871       val = (val << 8) | b1;
872       val = (val << 8) | b0;
873     }
874     
875     return val;
876   }
877
878   @MJI
879   public void putLong__JJ__V (MJIEnv env, int unsafeRef, long address, long val) {
880     int addr = (int)address;
881     Alloc a = getAlloc(addr);
882     
883     if (a == null) {
884       env.throwException("java.lang.IllegalArgumentException", "invalid memory address: " + Integer.toHexString(addr));
885       return;
886     }
887         
888     byte b7 = (byte)(0xff & val);
889     byte b6 = (byte)(0xff & (val >>> 8));
890     byte b5 = (byte)(0xff & (val >>> 16));
891     byte b4 = (byte)(0xff & (val >>> 24));    
892     byte b3 = (byte)(0xff & (val >>> 32));    
893     byte b2 = (byte)(0xff & (val >>> 40));    
894     byte b1 = (byte)(0xff & (val >>> 48));    
895     byte b0 = (byte)(0xff & (val >>> 56));    
896
897     ElementInfo ei = env.getModifiableElementInfo(a.objRef);
898     int offset = addr - a.startAdr;
899     
900     if (env.isBigEndianPlatform()){
901       ei.setByteElement(offset,   b0);
902       ei.setByteElement(offset+1, b1);
903       ei.setByteElement(offset+2, b2);
904       ei.setByteElement(offset+3, b3);
905       ei.setByteElement(offset+4, b4);
906       ei.setByteElement(offset+5, b5);
907       ei.setByteElement(offset+6, b6);
908       ei.setByteElement(offset+7, b7);
909       
910     } else {
911       ei.setByteElement(offset,   b7);
912       ei.setByteElement(offset+1, b6);
913       ei.setByteElement(offset+2, b5);
914       ei.setByteElement(offset+3, b4);
915       ei.setByteElement(offset+4, b3);
916       ei.setByteElement(offset+5, b2);
917       ei.setByteElement(offset+6, b1);
918       ei.setByteElement(offset+7, b0);
919     }
920   }
921
922 }
923