GNU header update.
[cacao.git] / src / native / jni.c
index cae0687476105560d3554deb2bf44f42068e820b..44bde5b31fe65184c6997ad55d9c7db918dbebc4 100644 (file)
@@ -1,9 +1,9 @@
-/* jni.c - implementation of the Java Native Interface functions
+/* native/jni.c - implementation of the Java Native Interface functions
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger, M. Platter
+   Copyright (C) 1996-2005 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
 
    This file is part of CACAO.
 
 
    Changes: Joseph Wenninger, Martin Platter
 
-   $Id: jni.c 1424 2004-10-30 11:15:23Z motse $
+   $Id: jni.c 1735 2004-12-07 14:33:27Z twisti $
 
 */
 
 
 #include <string.h>
-#include "exceptions.h"
-#include "main.h"
-#include "jni.h"
-#include "global.h"
-#include "loader.h"
-#include "tables.h"
-#include "native.h"
-#include "builtin.h"
-#include "options.h"
-#include "statistics.h"
-#include "threads/thread.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "nat/java_lang_Byte.h"
-#include "nat/java_lang_Character.h"
-#include "nat/java_lang_Short.h"
-#include "nat/java_lang_Integer.h"
-#include "nat/java_lang_Boolean.h"
-#include "nat/java_lang_Long.h"
-#include "nat/java_lang_Float.h"
-#include "nat/java_lang_Double.h"
-#include "nat/java_lang_Throwable.h"
-#include "jit/jit.h"
-#include "asmpart.h"
+
 #include "mm/boehm.h"
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "native/include/java_lang_Byte.h"
+#include "native/include/java_lang_Character.h"
+#include "native/include/java_lang_Short.h"
+#include "native/include/java_lang_Integer.h"
+#include "native/include/java_lang_Boolean.h"
+#include "native/include/java_lang_Long.h"
+#include "native/include/java_lang_Float.h"
+#include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_Throwable.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+#  include "threads/native/threads.h"
+# else
+#  include "threads/green/threads.h"
+# endif
+#endif
+
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+
+
 #define JNI_VERSION       0x00010002
 
 
@@ -75,6 +85,7 @@ static utf* utf_double = 0;
 
 /* global reference table */
 static jobject *global_ref_table;
+static bool initrunning=false;
 
 /* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
 static jmethodID getmid = NULL;
@@ -563,7 +574,7 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, 'O');
        /*      printf("parameter: obj: %p",blk[0].item); */
@@ -624,7 +635,7 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, retType);
 
@@ -682,7 +693,7 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock,/* 4 */argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, 'J');
 
@@ -723,7 +734,7 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy
        }
 #endif
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */ argcount+2);
 
        fill_callblock(obj, methodID->descriptor, blk, args, retType);
 
@@ -3072,46 +3083,61 @@ void DeleteWeakGlobalRef (JNIEnv* env, jweak ref)
 /** Creates a new global reference to the object referred to by the obj argument **/
     
 jobject NewGlobalRef(JNIEnv* env, jobject lobj)
-{      
-       MonitorEnter(env,*global_ref_table);
-       jobject refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
-       jint val = (refcount == NULL) ? 0 : CallIntMethod(env,refcount,intvalue);
-       jobject newval = NewObject(env,intclass,newint,val+1);
-       if (newval != NULL) {
+{
+       jobject refcount;
+       jint val;
+       jobject newval;
 
-               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
+       MonitorEnter(env, *global_ref_table);
+       
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj);
+       val = (refcount == NULL) ? 0 : CallIntMethod(env, refcount, intvalue);
+       newval = NewObject(env, intclass, newint, val + 1);
 
-               MonitorExit(env,*global_ref_table);
+       if (newval != NULL) {
+               CallObjectMethod(env, *global_ref_table, putmid, lobj, newval);
+               MonitorExit(env, *global_ref_table);
                return lobj;
+
        } else {
                log_text("JNI-NewGlobalRef: unable to create new java.lang.Integer");
-               MonitorExit(env,*global_ref_table);
+               MonitorExit(env, *global_ref_table);
                return NULL;
        }
 }
 
 /*************  Deletes the global reference pointed to by globalRef **************/
 
-void DeleteGlobalRef (JNIEnv* env, jobject gref)
+void DeleteGlobalRef(JNIEnv* env, jobject gref)
 {
-       MonitorEnter(env,*global_ref_table);
-       jobject refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+       jobject refcount;
+       jint val;
+
+       MonitorEnter(env, *global_ref_table);
+       refcount = CallObjectMethod(env, *global_ref_table, getmid, gref);
+
        if (refcount == NULL) {
                log_text("JNI-DeleteGlobalRef: unable to find global reference");
                return;
        }
-       jint val = CallIntMethod(env,refcount,intvalue);
+
+       val = CallIntMethod(env, refcount, intvalue);
        val--;
+
        if (val == 0) {
                CallObjectMethod(env, *global_ref_table, removemid,refcount);
+
        } else {
-               jobject newval = NewObject(env,intclass,newint,val);
+               jobject newval = NewObject(env, intclass, newint, val);
+
                if (newval != NULL) {
                        CallObjectMethod(env,*global_ref_table, putmid,newval);
+
                } else {
                        log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer");
                }
        }
+
        MonitorExit(env,*global_ref_table);
 }
 
@@ -3169,6 +3195,109 @@ jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2)
        return 0;
 }
 
+/************* JNI Initialization ****************************************************/
+
+jobject jni_init1(JNIEnv* env, jobject lobj) {
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       return NewGlobalRef(env, lobj); 
+}
+void jni_init2(JNIEnv* env, jobject gref) {
+       log_text("DeleteGlobalref called before NewGlobalref");
+#if defined(USE_THREADS)
+       while (initrunning) {yieldThread();} /* wait until init is done */
+#endif
+       if (global_ref_table == NULL) {
+               jni_init();
+       } 
+#if defined(USE_THREADS)
+       else {
+               /* wait until jni_init is done */
+               MonitorEnter(env, *global_ref_table) ;
+               MonitorExit(env, *global_ref_table);
+       }
+#endif
+       DeleteGlobalRef(env, gref); 
+}
+
+void jni_init(){
+       jmethodID mid;
+
+       initrunning = true;
+       log_text("JNI-Init: initialize global_ref_table");
+       /* initalize global reference table */
+       ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
+       
+       if (ihmclass == NULL) {
+               log_text("JNI-Init: unable to find java.util.IdentityHashMap");
+       }
+
+       mid = GetMethodID(NULL, ihmclass, "<init>","()V");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap");
+       }
+       
+       global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL);
+
+       *global_ref_table = NewObject(NULL,ihmclass,mid);
+
+       if (*global_ref_table == NULL) {
+               log_text("JNI-Init: unable to create new global_ref_table");
+       }
+
+       initrunning = false;
+
+       getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (mid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (getmid == NULL) {
+               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
+       }
+
+       putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+       if (putmid == NULL) {
+               log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap");
+       }
+
+       intclass = FindClass(NULL, "java/lang/Integer");
+       if (intclass == NULL) {
+               log_text("JNI-Init: unable to find java.lang.Integer");
+       }
+
+       newint = GetMethodID(NULL, intclass, "<init>","(I)V");
+       if (newint == NULL) {
+               log_text("JNI-Init: unable to find constructor in java.lang.Integer");
+       }
+
+       intvalue = GetMethodID(NULL, intclass, "intValue","()I");
+       if (intvalue == NULL) {
+               log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer");
+       }
+
+       removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;");
+       if (removemid == NULL) {
+               log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object");
+       }
+       
+       /* set NewGlobalRef, DeleteGlobalRef envTable entry to real implementation */
+       envTable.NewGlobalRef = &NewGlobalRef;
+       envTable.DeleteGlobalRef = &DeleteGlobalRef;
+}
+
 
 /********************************* JNI invocation table ******************************/
 
@@ -3210,8 +3339,8 @@ struct JNI_Table envTable = {
     &FatalError,
     &PushLocalFrame,
     &PopLocalFrame,
-    &NewGlobalRef,
-    &DeleteGlobalRef,
+       &jni_init1, /* &NewGlobalRef,    initialize Global_Ref_Table*/
+       &jni_init2, /* &DeleteGlobalRef,*/
     &DeleteLocalRef,
     &IsSameObject,
     &NewLocalRef,
@@ -3459,14 +3588,15 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
 
 
        if (!(methodID->flags & ACC_STATIC) && (!obj))  {
-               *exceptionptr = new_exception_message(string_java_lang_NullPointerException,
-                                                                                         "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NullPointerException,
+                                                                 "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
                return 0;
        }
 
        if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0;
 
-       blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+       blk = MNEW(jni_callblock, /*4 */argcount+2);
 
        retT = fill_callblock_objA(obj, methodID->descriptor, blk, params);
 
@@ -3617,11 +3747,11 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
 
        default:
                /* if this happens the acception has already been set by fill_callblock_objA*/
-               MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+               MFREE(blk, jni_callblock, /*4 */ argcount+2);
                return (jobject *) 0;
        }
 
-       MFREE(blk, jni_callblock, 4 /*argcount+2*/);
+       MFREE(blk, jni_callblock, /* 4 */ argcount+2);
 
        if (*exceptionptr) {
                java_objectheader *exceptionToWrap = *exceptionptr;
@@ -3648,65 +3778,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        return (jobject *) retVal;
 }
 
-void jni_init() {
-       jmethodID mid;
-
-       log_text("JNI-Init: initialize global_ref_table");
-       // initalize global reference table
-       ihmclass = FindClass(NULL, "java/util/IdentityHashMap");
-       
-       if (ihmclass == NULL) {
-               log_text("JNI-Init: unable to find java.util.IdentityHashMap");
-       }
-
-       mid = GetMethodID(NULL, ihmclass, "<init>","()V");
-       if (mid == NULL) {
-               log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap");
-       }
-       
-       global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL);
-
-       *global_ref_table = NewObject(NULL,ihmclass,mid);
-
-       if (*global_ref_table == NULL) {
-               log_text("JNI-Init: unable to create new global_ref_table");
-       }
-       
-       getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (mid == NULL) {
-               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
-       }
-
-       getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (getmid == NULL) {
-               log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap");
-       }
 
-       putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-       if (putmid == NULL) {
-               log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap");
-       }
-
-       intclass = FindClass(NULL, "java/lang/Integer");
-       if (intclass == NULL) {
-               log_text("JNI-Init: unable to find java.lang.Integer");
-       }
-
-       newint = GetMethodID(NULL, intclass, "<init>","(I)V");
-       if (newint == NULL) {
-               log_text("JNI-Init: unable to find constructor in java.lang.Integer");
-       }
-
-       intvalue = GetMethodID(NULL, intclass, "intValue","()I");
-       if (intvalue == NULL) {
-               log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer");
-       }
-
-       removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;");
-       if (removemid == NULL) {
-               log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object");
-       }
-}
 
 
 /*