* m4/classpath.m4: Renamed --with-classpath* options to
[cacao.git] / src / native / vm / sun_misc_Unsafe.c
index 42ce71ac1c604e3507165169d9c66ee41b5db56e..737559da5cafcc99ee642645f7f5c7d593e0cdcd 100644 (file)
@@ -1,9 +1,7 @@
 /* src/native/vm/sun_misc_Unsafe.c - sun/misc/Unsafe
 
-   Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: java_lang_VMObject.c 5153 2006-07-18 08:19:24Z twisti $
-
 */
 
 
 #include "config.h"
 
 #include <stdint.h>
+#include <unistd.h>
+
+#include "machine-instr.h"
 
 #include "mm/memory.h"
 
@@ -40,7 +39,7 @@
 #include "native/include/java_lang_Object.h"                  /* before c.l.C */
 #include "native/include/java_lang_String.h"            /* required by j.l.CL */
 
-#if defined(WITH_CLASSPATH_SUN)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 # include "native/include/java_nio_ByteBuffer.h"        /* required by j.l.CL */
 #endif
 
 #include "native/include/java_lang_Thread.h"             /* required by s.m.U */
 #include "native/include/java_lang_Throwable.h"
 
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+# include "native/include/java_lang_reflect_VMField.h"
+#endif
+
 #include "native/include/java_security_ProtectionDomain.h" /* required by smU */
 
 #include "native/include/sun_misc_Unsafe.h"
 
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/initialize.h"
 #include "vm/stringlocal.h"
 
+#include "vmcore/system.h"
 #include "vmcore/utf8.h"
 
 
@@ -73,14 +78,37 @@ static JNINativeMethod methods[] = {
        { "putBoolean",             "(Ljava/lang/Object;JZ)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putBoolean                     },
        { "getByte",                "(Ljava/lang/Object;J)B",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J  },
        { "putByte",                "(Ljava/lang/Object;JB)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB },
+       { "getShort",               "(Ljava/lang/Object;J)S",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J },
+       { "putShort",               "(Ljava/lang/Object;JS)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS },
        { "getChar",                "(Ljava/lang/Object;J)C",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J  },
        { "putChar",                "(Ljava/lang/Object;JC)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC },
+       { "getLong",                "(Ljava/lang/Object;J)J",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J  },
+       { "putLong",                "(Ljava/lang/Object;JJ)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ },
+       { "getFloat",               "(Ljava/lang/Object;J)F",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J },
+       { "putFloat",               "(Ljava/lang/Object;JF)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF },
+       { "getDouble",              "(Ljava/lang/Object;J)D",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J },
+       { "putDouble",              "(Ljava/lang/Object;JD)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD },
        { "getByte",                "(J)B",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__J                     },
+       { "putByte",                "(JB)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__JB                    },
+       { "getShort",               "(J)S",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getShort__J                    },
+       { "putShort",               "(JS)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putShort__JS                   },
+       { "getChar",                "(J)C",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__J                     },
+       { "putChar",                "(JC)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__JC                    },
        { "getInt",                 "(J)I",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__J                      },
+       { "putInt",                 "(JI)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putInt__JI                     },
        { "getLong",                "(J)J",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__J                     },
        { "putLong",                "(JJ)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_putLong__JJ                    },
+       { "getFloat",               "(J)F",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_getFloat__J                    },
        { "objectFieldOffset",      "(Ljava/lang/reflect/Field;)J",                               (void *) (intptr_t) &Java_sun_misc_Unsafe_objectFieldOffset              },
        { "allocateMemory",         "(J)J",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateMemory                 },
+#if 0
+       /* OpenJDK 7 */
+       { "setMemory",              "(Ljava/lang/Object;JJB)V",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory                      },
+       { "copyMemory",             "(Ljava/lang/Object;JLjava/lang/Object;JJ)V",                 (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory                     },
+#else
+       { "setMemory",              "(JJB)V",                                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory                      },
+       { "copyMemory",             "(JJJ)V",                                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory                     },
+#endif
        { "freeMemory",             "(J)V",                                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_freeMemory                     },
        { "staticFieldOffset",      "(Ljava/lang/reflect/Field;)J",                               (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldOffset              },
        { "staticFieldBase",        "(Ljava/lang/reflect/Field;)Ljava/lang/Object;",              (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldBase                },
@@ -88,13 +116,22 @@ static JNINativeMethod methods[] = {
        { "arrayBaseOffset",        "(Ljava/lang/Class;)I",                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayBaseOffset                },
        { "arrayIndexScale",        "(Ljava/lang/Class;)I",                                       (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayIndexScale                },
        { "addressSize",            "()I",                                                        (void *) (intptr_t) &Java_sun_misc_Unsafe_addressSize                    },
+       { "pageSize",               "()I",                                                        (void *) (intptr_t) &Java_sun_misc_Unsafe_pageSize                       },
        { "defineClass",            "(Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (intptr_t) &Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2 },
+       { "allocateInstance",       "(Ljava/lang/Class;)Ljava/lang/Object;",                      (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateInstance               },
        { "throwException",         "(Ljava/lang/Throwable;)V",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_throwException                 },
        { "compareAndSwapObject",   "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapObject           },
        { "compareAndSwapInt",      "(Ljava/lang/Object;JII)Z",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapInt              },
        { "compareAndSwapLong",     "(Ljava/lang/Object;JJJ)Z",                                   (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong             },
        { "getObjectVolatile",      "(Ljava/lang/Object;J)Ljava/lang/Object;",                    (void *) (intptr_t) &Java_sun_misc_Unsafe_getObjectVolatile              },
+       { "putObjectVolatile",      "(Ljava/lang/Object;JLjava/lang/Object;)V",                   (void *) (intptr_t) &Java_sun_misc_Unsafe_putObjectVolatile              },
        { "getIntVolatile",         "(Ljava/lang/Object;J)I",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getIntVolatile                 },
+       { "putIntVolatile",         "(Ljava/lang/Object;JI)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putIntVolatile                 },
+       { "getLongVolatile",        "(Ljava/lang/Object;J)J",                                     (void *) (intptr_t) &Java_sun_misc_Unsafe_getLongVolatile                },
+       { "putLongVolatile",        "(Ljava/lang/Object;JJ)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putLongVolatile                },
+       { "putOrderedObject",       "(Ljava/lang/Object;JLjava/lang/Object;)V",                   (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedObject               },
+       { "putOrderedInt",          "(Ljava/lang/Object;JI)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedInt                  },
+       { "putOrderedLong",         "(Ljava/lang/Object;JJ)V",                                    (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedLong                 },
        { "unpark",                 "(Ljava/lang/Object;)V",                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_unpark                         },
        { "park",                   "(ZJ)V",                                                      (void *) (intptr_t) &Java_sun_misc_Unsafe_park                           },
 };
@@ -261,6 +298,39 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEn
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getShort
+ * Signature: (Ljava/lang/Object;J)S
+ */
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
+{
+       int32_t *p;
+       int32_t  value;
+
+       p = (int32_t *) (((uint8_t *) o) + offset);
+
+       value = *p;
+
+       return value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putShort
+ * Signature: (Ljava/lang/Object;JS)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
+{
+       int32_t *p;
+
+       p = (int32_t *) (((uint8_t *) o) + offset);
+
+       *p = x;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    getChar
@@ -294,6 +364,105 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEn
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getLong
+ * Signature: (Ljava/lang/Object;J)J
+ */
+JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
+{
+       int64_t *p;
+       int64_t  value;
+
+       p = (int64_t *) (((uint8_t *) o) + offset);
+
+       value = *p;
+
+       return value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putLong
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
+{
+       int64_t *p;
+
+       p = (int64_t *) (((uint8_t *) o) + offset);
+
+       *p = x;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getFloat
+ * Signature: (Ljava/lang/Object;J)F
+ */
+JNIEXPORT float JNICALL Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
+{
+       float *p;
+       float  value;
+
+       p = (float *) (((uint8_t *) o) + offset);
+
+       value = *p;
+
+       return value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putFloat
+ * Signature: (Ljava/lang/Object;JF)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, float x)
+{
+       float *p;
+
+       p = (float *) (((uint8_t *) o) + offset);
+
+       *p = x;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getDouble
+ * Signature: (Ljava/lang/Object;J)D
+ */
+JNIEXPORT double JNICALL Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
+{
+       double *p;
+       double  value;
+
+       p = (double *) (((uint8_t *) o) + offset);
+
+       value = *p;
+
+       return value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putDouble
+ * Signature: (Ljava/lang/Object;JD)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, double x)
+{
+       double *p;
+
+       p = (double *) (((uint8_t *) o) + offset);
+
+       *p = x;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    getByte
@@ -312,6 +481,87 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getByte__J(JNIEnv *env, sun_misc_
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putByte
+ * Signature: (JB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__JB(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
+{
+       int8_t *p;
+
+       p = (int8_t *) (intptr_t) address;
+
+       *p = (int8_t) value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getShort
+ * Signature: (J)S
+ */
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getShort__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
+{
+       int16_t *p;
+       int16_t  value;
+
+       p = (int16_t *) (intptr_t) address;
+
+       value = *p;
+
+       return (int32_t) value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putShort
+ * Signature: (JS)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__JS(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
+{
+       int16_t *p;
+
+       p = (int16_t *) (intptr_t) address;
+
+       *p = (int16_t) value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getChar
+ * Signature: (J)C
+ */
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getChar__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
+{
+       uint16_t *p;
+       uint16_t  value;
+
+       p = (uint16_t *) (intptr_t) address;
+
+       value = *p;
+
+       return (int32_t) value;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putChar
+ * Signature: (JC)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__JC(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
+{
+       uint16_t *p;
+
+       p = (uint16_t *) (intptr_t) address;
+
+       *p = (uint16_t) value;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    getInt
@@ -330,6 +580,21 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getInt__J(JNIEnv *env, sun_misc_U
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putInt
+ * Signature: (JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__JI(JNIEnv *env, struct sun_misc_Unsafe* this, int64_t address, int32_t value)
+{
+       int32_t *p;
+
+       p = (int32_t *) (intptr_t) address;
+
+       *p = value;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    getLong
@@ -363,20 +628,55 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__JJ(JNIEnv *env, sun_misc_Un
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getFloat
+ * Signature: (J)F
+ */
+JNIEXPORT float JNICALL Java_sun_misc_Unsafe_getFloat__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
+{
+       float *p;
+       float  value;
+
+       p = (float *) (intptr_t) address;
+
+       value = *p;
+
+       return value;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    objectFieldOffset
  * Signature: (Ljava/lang/reflect/Field;)J
  */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_objectFieldOffset(JNIEnv *env, sun_misc_Unsafe* this, java_lang_reflect_Field* field)
+JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_objectFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *field)
 {
        classinfo *c;
        fieldinfo *f;
        int32_t    slot;
 
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       java_lang_reflect_VMField *rvmf;
+#endif
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       LLNI_field_get_ref(field, f,     rvmf);
+       LLNI_field_get_cls(rvmf,  clazz, c);
+       LLNI_field_get_val(rvmf,  slot , slot);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
        LLNI_field_get_cls(field, clazz, c);
        LLNI_field_get_val(field, slot , slot);
-       f = &c->fields[slot];
+
+#else
+# error unknown configuration
+#endif
+
+       f = &(c->fields[slot]);
 
        return (int64_t) f->offset;
 }
@@ -405,6 +705,119 @@ JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_allocateMemory(JNIEnv *env, sun_m
 }
 
 
+#if 0
+/* OpenJDK 7 */
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    setMemory
+ * Signature: (Ljava/lang/Object;JJB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t bytes, int32_t value)
+{
+       size_t  length;
+       void   *p;
+
+       length = (size_t) bytes;
+
+       if ((length != (uint64_t) bytes) || (bytes < 0)) {
+               exceptions_throw_illegalargumentexception();
+               return;
+       }
+
+       /* XXX Missing LLNI: we need to unwrap this object. */
+
+       p = (void *) (((uint8_t *) o) + offset);
+
+       /* XXX Not sure this is correct. */
+
+       system_memset(p, value, length);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    copyMemory
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *srcBase, int64_t srcOffset, java_lang_Object *destBase, int64_t destOffset, int64_t bytes)
+{
+       size_t  length;
+       void   *src;
+       void   *dest;
+
+       if (bytes == 0)
+               return;
+
+       length = (size_t) bytes;
+
+       if ((length != (uint64_t) bytes) || (bytes < 0)) {
+               exceptions_throw_illegalargumentexception();
+               return;
+       }
+
+       /* XXX Missing LLNI: We need to unwrap these objects. */
+
+       src  = (void *) (((uint8_t *) srcBase) + srcOffset);
+       dest = (void *) (((uint8_t *) destBase) + destOffset);
+
+       system_memcpy(dest, src, length);
+}
+#else
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    setMemory
+ * Signature: (JJB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int64_t bytes, int32_t value)
+{
+       size_t  length;
+       void   *p;
+
+       length = (size_t) bytes;
+
+       if ((length != (uint64_t) bytes) || (bytes < 0)) {
+               exceptions_throw_illegalargumentexception();
+               return;
+       }
+
+       p = (void *) (intptr_t) address;
+
+       /* XXX Not sure this is correct. */
+
+       system_memset(p, value, length);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    copyMemory
+ * Signature: (JJJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t srcAddress, int64_t destAddress, int64_t bytes)
+{
+       size_t  length;
+       void   *src;
+       void   *dest;
+
+       if (bytes == 0)
+               return;
+
+       length = (size_t) bytes;
+
+       if ((length != (uint64_t) bytes) || (bytes < 0)) {
+               exceptions_throw_illegalargumentexception();
+               return;
+       }
+
+       src  = (void *) (intptr_t) srcAddress;
+       dest = (void *) (intptr_t) destAddress;
+
+       system_memcpy(dest, src, length);
+}
+#endif
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    freeMemory
@@ -430,17 +843,11 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_freeMemory(JNIEnv *env, sun_misc_Uns
  * Method:    staticFieldOffset
  * Signature: (Ljava/lang/reflect/Field;)J
  */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *field)
+JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *f)
 {
-       classinfo *c;
-       fieldinfo *f;
-       int32_t    slot;
-
-       LLNI_field_get_cls(field, clazz, c);
-       LLNI_field_get_val(field, slot , slot);
-       f = &(c->fields[slot]);
+       /* The offset of static fields is 0. */
 
-       return (int64_t) (intptr_t) f->value;
+       return 0;
 }
 
 
@@ -449,11 +856,34 @@ JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, su
  * Method:    staticFieldBase
  * Signature: (Ljava/lang/reflect/Field;)Ljava/lang/Object;
  */
-JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_staticFieldBase(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *f)
+JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_staticFieldBase(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *rf)
 {
-       /* In CACAO we return the absolute address in staticFieldOffset. */
+       classinfo *c;
+       fieldinfo *f;
+       int32_t    slot;
 
-       return NULL;
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       java_lang_reflect_VMField *rvmf;
+#endif
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       LLNI_field_get_ref(rf,   f,     rvmf);
+       LLNI_field_get_cls(rvmf, clazz, c);
+       LLNI_field_get_val(rvmf, slot , slot);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       LLNI_field_get_cls(rf, clazz, c);
+       LLNI_field_get_val(rf, slot , slot);
+
+#else
+# error unknown configuration
+#endif
+
+       f = &(c->fields[slot]);
+
+       return (java_lang_Object *) (f->value);
 }
 
 
@@ -466,7 +896,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_ensureClassInitialized(JNIEnv *env,
 {
        classinfo *c;
 
-       c = (classinfo *) class;
+       c = LLNI_classinfo_unwrap(class);
 
        if (!(c->state & CLASS_INITIALIZED))
                initialize_class(c);
@@ -483,7 +913,7 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(JNIEnv *env, sun_
        classinfo       *c;
        arraydescriptor *ad;
 
-       c  = (classinfo *) arrayClass;
+       c  = LLNI_classinfo_unwrap(arrayClass);
        ad = c->vftbl->arraydesc;
 
        if (ad == NULL) {
@@ -506,7 +936,7 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayIndexScale(JNIEnv *env, sun_
        classinfo       *c;
        arraydescriptor *ad;
 
-       c  = (classinfo *) arrayClass;
+       c  = LLNI_classinfo_unwrap(arrayClass);
        ad = c->vftbl->arraydesc;
 
        if (ad == NULL) {
@@ -530,6 +960,21 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_addressSize(JNIEnv *env, sun_misc
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    pageSize
+ * Signature: ()I
+ */
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_pageSize(JNIEnv *env, sun_misc_Unsafe *this)
+{
+       int sz;
+
+       sz = getpagesize();
+
+       return sz;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    defineClass
@@ -537,12 +982,12 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_addressSize(JNIEnv *env, sun_misc
  */
 JNIEXPORT java_lang_Class* JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(JNIEnv *env, sun_misc_Unsafe *this, java_lang_String *name, java_handle_bytearray_t *b, int32_t off, int32_t len, java_lang_ClassLoader *loader, java_security_ProtectionDomain *protectionDomain)
 {
-       classloader     *cl;
+       classloader_t   *cl;
        utf             *utfname;
        classinfo       *c;
        java_lang_Class *o;
 
-       cl = (classloader *) loader;
+       cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
        /* check if data was passed */
 
@@ -569,16 +1014,17 @@ JNIEXPORT java_lang_Class* JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_
 
        /* define the class */
 
-       c = class_define(utfname, cl, len, (const uint8_t *) &b->data[off]);
+       c = class_define(utfname, cl, len, (uint8_t *) &(LLNI_array_direct(b, off)),
+                                        (java_handle_t *) protectionDomain);
 
        if (c == NULL)
                return NULL;
 
        /* for convenience */
 
-       o = (java_lang_Class *) c;
+       o = LLNI_classinfo_wrap(c);
 
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        /* set ProtectionDomain */
 
        LLNI_field_set_ref(o, pd, protectionDomain);
@@ -588,6 +1034,24 @@ JNIEXPORT java_lang_Class* JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    allocateInstance
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Object;
+ */
+JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_allocateInstance(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *cls)
+{
+       classinfo     *c;
+       java_handle_t *o;
+
+       c = LLNI_classinfo_unwrap(cls);
+
+       o = builtin_new(c);
+
+       return (java_lang_Object *) o;
+}
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    throwException
@@ -610,6 +1074,7 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(JNIEnv *env, sun_misc
  */
 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)
 {
+#if 1
        void **p;
        void  *value;
 
@@ -626,6 +1091,21 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env,
        }
 
        return false;
+#else
+       volatile void **p;
+       void           *result;
+
+       /* XXX Use LLNI */
+
+       p = (volatile void **) (((uint8_t *) o) + offset);
+
+       result = atomic_compare_and_swap_address(p, expected, x);
+
+       if (result == expected)
+               return true;
+
+       return false;
+#endif
 }
 
 
@@ -634,24 +1114,40 @@ JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env,
  * Method:    compareAndSwapInt
  * Signature: (Ljava/lang/Object;JII)Z
  */
-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)
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, sun_misc_Unsafe* this, java_lang_Object* o, int64_t offset, int32_t expected, int32_t x)
 {
+#if 1
        int32_t *p;
        int32_t  value;
 
-       p = (int32_t *) (((uint8_t *) obj) + offset);
+       p = (int32_t *) (((uint8_t *) o) + offset);
 
        /* XXX this should be atomic */
 
        value = *p;
 
-       if (value == expect) {
-               *p = update;
+       if (value == expected) {
+               *p = x;
 
                return true;
        }
 
        return false;
+#else
+       int32_t *p;
+       int32_t  result;
+
+       /* XXX Use LLNI */
+
+       p = (int32_t *) (((uint8_t *) o) + offset);
+
+       result = atomic_compare_and_swap_int(p, expected, x);
+
+       if (result == expected)
+               return true;
+
+       return false;
+#endif
 }
 
 
@@ -699,6 +1195,60 @@ JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEn
 }
 
 
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putObjectVolatile
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
+{
+       volatile void **p;
+
+       p = (volatile void **) (((uint8_t *) o) + offset);
+
+       *p = x;
+}
+
+
+#define UNSAFE_GET_VOLATILE(type)                                                      \
+       java_handle_t *_h;                                                                              \
+       java_object_t *_o;                                                                              \
+       volatile type *_p;                                                                              \
+       volatile type  _x;                                                                              \
+                                                                                                                       \
+       _h = (java_handle_t *) o;                                                               \
+                                                                                                                       \
+       LLNI_CRITICAL_START;                                                                    \
+                                                                                                                       \
+       _o = LLNI_UNWRAP(_h);                                                                   \
+       _p = (volatile type *) (((uint8_t *) _o) + offset);             \
+                                                                                                                       \
+       _x = *_p;                                                                                               \
+                                                                                                                       \
+       LLNI_CRITICAL_END;                                                                              \
+                                                                                                                       \
+       return _x;
+
+
+#define UNSAFE_PUT_VOLATILE(type)                                                      \
+       java_handle_t *_h;                                                                              \
+       java_object_t *_o;                                                                              \
+       volatile type *_p;                                                                              \
+                                                                                                                       \
+       _h = (java_handle_t *) o;                                                               \
+                                                                                                                       \
+       LLNI_CRITICAL_START;                                                                    \
+                                                                                                                       \
+       _o = LLNI_UNWRAP(_h);                                                                   \
+       _p = (volatile type *) (((uint8_t *) _o) + offset);             \
+                                                                                                                       \
+       *_p = x;                                                                                                \
+                                                                                                                       \
+       MEMORY_BARRIER();                                                                               \
+                                                                                                                       \
+       LLNI_CRITICAL_END;
+
+
 /*
  * Class:     sun/misc/Unsafe
  * Method:    getIntVolatile
@@ -706,14 +1256,92 @@ JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEn
  */
 JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
 {
-       volatile int32_t *p;
-       volatile int32_t  value;
+       UNSAFE_GET_VOLATILE(int32_t);
+}
 
-       p = (volatile int32_t *) (((uint8_t *) o) + offset);
 
-       value = *p;
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putIntVolatile
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
+{
+       UNSAFE_PUT_VOLATILE(int32_t);
+}
 
-       return value;
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getLongVolatile
+ * Signature: (Ljava/lang/Object;J)J
+ */
+JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
+{
+       UNSAFE_GET_VOLATILE(int64_t);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putLongVolatile
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
+{
+       UNSAFE_PUT_VOLATILE(int64_t);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putOrderedObject
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
+{
+       java_handle_t  *_h;
+       java_handle_t  *_hx;
+       java_object_t  *_o;
+       java_object_t  *_x;
+       volatile void **_p;
+
+       _h  = (java_handle_t *) o;
+       _hx = (java_handle_t *) x;
+
+       LLNI_CRITICAL_START;
+
+       _o = LLNI_UNWRAP(_h);
+       _x = LLNI_UNWRAP(_hx);
+       _p = (volatile void **) (((uint8_t *) _o) + offset);
+
+       *_p = _x;
+
+       MEMORY_BARRIER();
+
+       LLNI_CRITICAL_END;
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putOrderedInt
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
+{
+       UNSAFE_PUT_VOLATILE(int32_t);
+}
+
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    putOrderedLong
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
+{
+       UNSAFE_PUT_VOLATILE(int64_t);
 }