* src/lib/gnu/sun/misc/Unsafe.java: Updated to openjdk rev239.
[cacao.git] / src / native / vm / sun_misc_Unsafe.c
1 /* src/native/vm/sun_misc_Unsafe.c - sun/misc/Unsafe
2
3    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: java_lang_VMObject.c 5153 2006-07-18 08:19:24Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdint.h>
33
34 #include "mm/memory.h"
35
36 #include "native/jni.h"
37 #include "native/native.h"
38
39 #include "native/include/java_lang_Object.h"                  /* before c.l.C */
40 #include "native/include/java_lang_String.h"            /* required by j.l.CL */
41
42 #if defined(WITH_CLASSPATH_SUN)
43 # include "native/include/java_nio_ByteBuffer.h"        /* required by j.l.CL */
44 #endif
45
46 #include "native/include/java_lang_ClassLoader.h"        /* required by j.l.C */
47 #include "native/include/java_lang_Class.h"
48 #include "native/include/java_lang_reflect_Field.h"
49 #include "native/include/java_lang_Thread.h"             /* required by s.m.U */
50 #include "native/include/java_lang_Throwable.h"
51
52 #if defined(WITH_CLASSPATH_SUN)
53 # include "native/include/java_security_ProtectionDomain.h" /* required by smU*/
54 #endif
55
56 #include "native/include/sun_misc_Unsafe.h"
57
58 #include "vm/exceptions.h"
59 #include "vm/initialize.h"
60
61 #include "vmcore/utf8.h"
62
63
64 /* native methods implemented by this file ************************************/
65
66 static JNINativeMethod methods[] = {
67         { "registerNatives",        "()V",                                                        (void *) (intptr_t) &Java_sun_misc_Unsafe_registerNatives                },
68         { "getInt",                 "(Ljava/lang/Object;J)I",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J   },
69         { "getBoolean",             "(Ljava/lang/Object;J)Z",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getBoolean                     },
70         { "putBoolean",             "(Ljava/lang/Object;JZ)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putBoolean                     },
71         { "getByte",                "(Ljava/lang/Object;J)B",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J  },
72         { "putByte",                "(Ljava/lang/Object;JB)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB },
73         { "getChar",                "(Ljava/lang/Object;J)C",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J  },
74         { "putChar",                "(Ljava/lang/Object;JC)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC },
75         { "getByte",                "(J)B",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__J                     },
76         { "getInt",                 "(J)I",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__J                      },
77         { "getLong",                "(J)J",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__J                     },
78         { "putLong",                "(JJ)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putLong__JJ                    },
79         { "objectFieldOffset",      "(Ljava/lang/reflect/Field;)J",                               (void *) (intptr_t) &Java_sun_misc_Unsafe_objectFieldOffset              },
80         { "allocateMemory",         "(J)J",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateMemory                 },
81         { "freeMemory",             "(J)V",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_freeMemory                     },
82         { "staticFieldOffset",      "(Ljava/lang/reflect/Field;)J",                               (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldOffset              },
83         { "staticFieldBase",        "(Ljava/lang/reflect/Field;)Ljava/lang/Object;",              (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldBase                },
84         { "ensureClassInitialized", "(Ljava/lang/Class;)V",                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_ensureClassInitialized         },
85         { "arrayBaseOffset",        "(Ljava/lang/Class;)I",                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayBaseOffset                },
86         { "arrayIndexScale",        "(Ljava/lang/Class;)I",                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayIndexScale                },
87         { "addressSize",            "()I",                                                        (void *) (intptr_t) &Java_sun_misc_Unsafe_addressSize                    },
88         { "throwException",         "(Ljava/lang/Throwable;)V",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_throwException                 },
89         { "compareAndSwapObject",   "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapObject           },
90         { "compareAndSwapInt",      "(Ljava/lang/Object;JII)Z",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapInt              },
91         { "compareAndSwapLong",     "(Ljava/lang/Object;JJJ)Z",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong             },
92         { "getObjectVolatile",      "(Ljava/lang/Object;J)Ljava/lang/Object;",                    (void *) (intptr_t) &Java_sun_misc_Unsafe_getObjectVolatile              },
93         { "getIntVolatile",         "(Ljava/lang/Object;J)I",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getIntVolatile                 },
94 };
95
96
97 /* _Jv_sun_misc_Unsafe_init ****************************************************
98
99    Register native functions.
100
101 *******************************************************************************/
102
103 void _Jv_sun_misc_Unsafe_init(void)
104 {
105         utf *u;
106
107         u = utf_new_char("sun/misc/Unsafe");
108
109         native_method_register(u, methods, NATIVE_METHODS_COUNT);
110 }
111
112
113 /*
114  * Class:     sun/misc/Unsafe
115  * Method:    registerNatives
116  * Signature: ()V
117  */
118 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_registerNatives(JNIEnv *env, jclass clazz)
119 {
120         /* The native methods of this function are already registered in
121            _Jv_sun_misc_Unsafe_init() which is called during VM
122            startup. */
123 }
124
125
126 /*
127  * Class:     sun/misc/Unsafe
128  * Method:    getInt
129  * Signature: (Ljava/lang/Object;J)I
130  */
131 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
132 {
133         int32_t *p;
134         int32_t  value;
135
136         p = (int32_t *) (((uint8_t *) o) + offset);
137
138         value = *p;
139
140         return value;
141 }
142
143
144 /*
145  * Class:     sun/misc/Unsafe
146  * Method:    getBoolean
147  * Signature: (Ljava/lang/Object;J)Z
148  */
149 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getBoolean(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
150 {
151         int32_t *p;
152         int32_t  value;
153
154         p = (int32_t *) (((uint8_t *) o) + offset);
155
156         value = *p;
157
158         return value;
159 }
160
161
162 /*
163  * Class:     sun/misc/Unsafe
164  * Method:    putBoolean
165  * Signature: (Ljava/lang/Object;JZ)V
166  */
167 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putBoolean(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
168 {
169         int32_t *p;
170
171         p = (int32_t *) (((uint8_t *) o) + offset);
172
173         *p = x;
174 }
175
176
177 /*
178  * Class:     sun/misc/Unsafe
179  * Method:    getByte
180  * Signature: (Ljava/lang/Object;J)B
181  */
182 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
183 {
184         int32_t *p;
185         int32_t  value;
186
187         p = (int32_t *) (((uint8_t *) o) + offset);
188
189         value = *p;
190
191         return value;
192 }
193
194
195 /*
196  * Class:     sun/misc/Unsafe
197  * Method:    putByte
198  * Signature: (Ljava/lang/Object;JB)V
199  */
200 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
201 {
202         int32_t *p;
203
204         p = (int32_t *) (((uint8_t *) o) + offset);
205
206         *p = x;
207 }
208
209
210 /*
211  * Class:     sun/misc/Unsafe
212  * Method:    getChar
213  * Signature: (Ljava/lang/Object;J)C
214  */
215 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
216 {
217         int32_t *p;
218         int32_t  value;
219
220         p = (int32_t *) (((uint8_t *) o) + offset);
221
222         value = *p;
223
224         return value;
225 }
226
227
228 /*
229  * Class:     sun/misc/Unsafe
230  * Method:    putChar
231  * Signature: (Ljava/lang/Object;JC)V
232  */
233 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
234 {
235         int32_t *p;
236
237         p = (int32_t *) (((uint8_t *) o) + offset);
238
239         *p = x;
240 }
241
242
243 /*
244  * Class:     sun/misc/Unsafe
245  * Method:    getByte
246  * Signature: (J)B
247  */
248 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getByte__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
249 {
250         int8_t *p;
251         int8_t  value;
252
253         p = (int8_t *) (intptr_t) address;
254
255         value = *p;
256
257         return (int32_t) value;
258 }
259
260
261 /*
262  * Class:     sun/misc/Unsafe
263  * Method:    getInt
264  * Signature: (J)I
265  */
266 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getInt__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
267 {
268         int32_t *p;
269         int32_t  value;
270
271         p = (int32_t *) (intptr_t) address;
272
273         value = *p;
274
275         return value;
276 }
277
278
279 /*
280  * Class:     sun/misc/Unsafe
281  * Method:    getLong
282  * Signature: (J)J
283  */
284 JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLong__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
285 {
286         int64_t *p;
287         int64_t  value;
288
289         p = (int64_t *) (intptr_t) address;
290
291         value = *p;
292
293         return value;
294 }
295
296
297 /*
298  * Class:     sun/misc/Unsafe
299  * Method:    putLong
300  * Signature: (JJ)V
301  */
302 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__JJ(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int64_t value)
303 {
304         int64_t *p;
305
306         p = (int64_t *) (intptr_t) address;
307
308         *p = value;
309 }
310
311
312 /*
313  * Class:     sun/misc/Unsafe
314  * Method:    objectFieldOffset
315  * Signature: (Ljava/lang/reflect/Field;)J
316  */
317 JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_objectFieldOffset(JNIEnv *env, sun_misc_Unsafe* this, java_lang_reflect_Field* field)
318 {
319         classinfo *c;
320         fieldinfo *f;
321
322         c = (classinfo *) field->clazz;
323         f = &c->fields[field->slot];
324
325         return (int64_t) f->offset;
326 }
327
328
329 /*
330  * Class:     sun/misc/Unsafe
331  * Method:    allocateMemory
332  * Signature: (J)J
333  */
334 JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_allocateMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t bytes)
335 {
336         size_t  length;
337         void   *p;
338
339         length = (size_t) bytes;
340
341         if ((length != (uint64_t) bytes) || (bytes < 0)) {
342                 exceptions_throw_illegalargumentexception();
343                 return 0;
344         }
345
346         p = MNEW(uint8_t, length);
347
348         return (int64_t) (intptr_t) p;
349 }
350
351
352 /*
353  * Class:     sun/misc/Unsafe
354  * Method:    freeMemory
355  * Signature: (J)V
356  */
357 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_freeMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
358 {
359         void *p;
360
361         p = (void *) (intptr_t) address;
362
363         if (p == NULL)
364                 return;
365
366         /* we pass length 1 to trick the free function */
367
368         MFREE(p, uint8_t, 1);
369 }
370
371
372 /*
373  * Class:     sun/misc/Unsafe
374  * Method:    staticFieldOffset
375  * Signature: (Ljava/lang/reflect/Field;)J
376  */
377 JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *field)
378 {
379         classinfo *c;
380         fieldinfo *f;
381
382         c = (classinfo *) field->clazz;
383         f = &(c->fields[field->slot]);
384
385         return (int64_t) (intptr_t) &(f->value);
386 }
387
388
389 /*
390  * Class:     sun/misc/Unsafe
391  * Method:    staticFieldBase
392  * Signature: (Ljava/lang/reflect/Field;)Ljava/lang/Object;
393  */
394 JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_staticFieldBase(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *f)
395 {
396         /* In CACAO we return the absolute address in staticFieldOffset. */
397
398         return NULL;
399 }
400
401
402 /*
403  * Class:     sun/misc/Unsafe
404  * Method:    ensureClassInitialized
405  * Signature: (Ljava/lang/Class;)V
406  */
407 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_ensureClassInitialized(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *class)
408 {
409         classinfo *c;
410
411         c = (classinfo *) class;
412
413         if (!(c->state & CLASS_INITIALIZED))
414                 initialize_class(c);
415 }
416
417
418 /*
419  * Class:     sun/misc/Unsafe
420  * Method:    arrayBaseOffset
421  * Signature: (Ljava/lang/Class;)I
422  */
423 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *arrayClass)
424 {
425         classinfo       *c;
426         arraydescriptor *ad;
427
428         c  = (classinfo *) arrayClass;
429         ad = c->vftbl->arraydesc;
430
431         if (ad == NULL) {
432                 /* XXX does that exception exist? */
433                 exceptions_throw_internalerror("java/lang/InvalidClassException");
434                 return 0;
435         }
436
437         return ad->dataoffset;
438 }
439
440
441 /*
442  * Class:     sun/misc/Unsafe
443  * Method:    arrayIndexScale
444  * Signature: (Ljava/lang/Class;)I
445  */
446 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayIndexScale(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *arrayClass)
447 {
448         classinfo       *c;
449         arraydescriptor *ad;
450
451         c  = (classinfo *) arrayClass;
452         ad = c->vftbl->arraydesc;
453
454         if (ad == NULL) {
455                 /* XXX does that exception exist? */
456                 exceptions_throw_internalerror("java/lang/InvalidClassException");
457                 return 0;
458         }
459
460         return ad->componentsize;
461 }
462
463
464 /*
465  * Class:     sun/misc/Unsafe
466  * Method:    addressSize
467  * Signature: ()I
468  */
469 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_addressSize(JNIEnv *env, sun_misc_Unsafe *this)
470 {
471         return SIZEOF_VOID_P;
472 }
473
474
475 /*
476  * Class:     sun/misc/Unsafe
477  * Method:    throwException
478  * Signature: (Ljava/lang/Throwable;)V
479  */
480 JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Throwable *ee)
481 {
482         java_objectheader *o;
483
484         o = (java_objectheader *) ee;
485
486         exceptions_set_exception(o);
487 }
488
489
490 /*
491  * Class:     sun/misc/Unsafe
492  * Method:    compareAndSwapObject
493  * Signature: (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z
494  */
495 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *expected, java_lang_Object *x)
496 {
497         void **p;
498         void  *value;
499
500         p = (void **) (((uint8_t *) o) + offset);
501
502         /* XXX this should be atomic */
503
504         value = *p;
505
506         if (value == expected) {
507                 *p = x;
508
509                 return true;
510         }
511
512         return false;
513 }
514
515
516 /*
517  * Class:     sun/misc/Unsafe
518  * Method:    compareAndSwapInt
519  * Signature: (Ljava/lang/Object;JII)Z
520  */
521 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, sun_misc_Unsafe* this, java_lang_Object* obj, int64_t offset, int32_t expect, int32_t update)
522 {
523         int32_t *p;
524         int32_t  value;
525
526         p = (int32_t *) (((uint8_t *) obj) + offset);
527
528         /* XXX this should be atomic */
529
530         value = *p;
531
532         if (value == expect) {
533                 *p = update;
534
535                 return true;
536         }
537
538         return false;
539 }
540
541
542 /*
543  * Class:     sun/misc/Unsafe
544  * Method:    compareAndSwapLong
545  * Signature: (Ljava/lang/Object;JJJ)Z
546  */
547 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapLong(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t expected, int64_t x)
548 {
549         int64_t *p;
550         int64_t  value;
551
552         p = (int64_t *) (((uint8_t *) o) + offset);
553
554         /* XXX this should be atomic */
555
556         value = *p;
557
558         if (value == expected) {
559                 *p = x;
560
561                 return true;
562         }
563
564         return false;
565 }
566
567
568 /*
569  * Class:     sun/misc/Unsafe
570  * Method:    getObjectVolatile
571  * Signature: (Ljava/lang/Object;J)Ljava/lang/Object;
572  */
573 JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
574 {
575         volatile void **p;
576         volatile void  *value;
577
578         p = (volatile void **) (((uint8_t *) o) + offset);
579
580         value = *p;
581
582         return (java_lang_Object *) value;
583 }
584
585
586 /*
587  * Class:     sun/misc/Unsafe
588  * Method:    getIntVolatile
589  * Signature: (Ljava/lang/Object;J)I
590  */
591 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
592 {
593         volatile int32_t *p;
594         volatile int32_t  value;
595
596         p = (volatile int32_t *) (((uint8_t *) o) + offset);
597
598         value = *p;
599
600         return value;
601 }
602
603
604 /*
605  * These are local overrides for various environment variables in Emacs.
606  * Please do not remove this and leave it at the end of the file, where
607  * Emacs will automagically detect them.
608  * ---------------------------------------------------------------------
609  * Local variables:
610  * mode: c
611  * indent-tabs-mode: t
612  * c-basic-offset: 4
613  * tab-width: 4
614  * End:
615  */