* m4/classpath.m4: Renamed --with-classpath* options to
[cacao.git] / src / native / native.c
index 37f86f45c72fbd3da3442479f1440b929d0d0271..9a4cd343f55d984a39cd2b519d419967c23e6e34 100644 (file)
@@ -1,9 +1,7 @@
 /* src/native/native.c - table of native functions
 
-   Copyright (C) 1996-2005, 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) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 #endif
 
 
-/* include table of native functions ******************************************/
-
-#if defined(WITH_STATIC_CLASSPATH)
-# include "native/nativetable.inc"
-#endif
-
-
-/* tables for methods *********************************************************/
-
-#if defined(WITH_STATIC_CLASSPATH)
-#define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
-
-/* table for fast string comparison */
-static nativecompref nativecomptable[NATIVETABLESIZE];
-
-/* string comparsion table initialized */
-static bool nativecompdone = false;
-#endif
-
-
 /* global variables ***********************************************************/
 
 static avl_tree_t *tree_native_methods;
@@ -111,6 +89,8 @@ static s4 native_tree_native_methods_comparator(const void *treenode, const void
 
 bool native_init(void)
 {
+       TRACESUBSYSTEMINITIALIZATION("native_init");
+
 #if defined(ENABLE_LTDL)
        /* initialize libltdl */
 
@@ -184,7 +164,6 @@ static s4 native_tree_native_methods_comparator(const void *treenode, const void
 
 *******************************************************************************/
 
-#if !defined(WITH_STATIC_CLASSPATH)
 static utf *native_make_overloaded_function(utf *name, utf *descriptor)
 {
        char *newname;
@@ -192,12 +171,12 @@ static utf *native_make_overloaded_function(utf *name, utf *descriptor)
        char *utf_ptr;
        u2    c;
        s4    i;
-       s4    dumpsize;
        utf  *u;
+       int32_t dumpmarker;
 
        /* mark memory */
 
-       dumpsize = dump_size();
+       DMARKER;
 
        utf_ptr = descriptor->text;
        namelen = strlen(name->text) + strlen("__") + strlen("0");
@@ -289,7 +268,7 @@ static utf *native_make_overloaded_function(utf *name, utf *descriptor)
 
        /* release memory */
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return u;
 }
@@ -372,12 +351,12 @@ static utf *native_method_symbol(utf *classname, utf *methodname)
        char *utf_endptr;
        u2    c;
        u4    pos;
-       s4    dumpsize;
        utf  *u;
+       int32_t dumpmarker;
 
        /* mark memory */
 
-       dumpsize = dump_size();
+       DMARKER;
 
        /* Calculate length of native function name.  We multiply the
           class and method name length by 6 as this is the maxium
@@ -433,7 +412,7 @@ static utf *native_method_symbol(utf *classname, utf *methodname)
 
        /* release memory */
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        return u;
 }
@@ -496,7 +475,7 @@ static functionptr native_method_find(methodinfo *m)
 
        /* fill the temporary structure used for searching the tree */
 
-       tmpnmn.classname  = m->class->name;
+       tmpnmn.classname  = m->clazz->name;
        tmpnmn.name       = m->name;
        tmpnmn.descriptor = m->descriptor;
 
@@ -511,10 +490,166 @@ static functionptr native_method_find(methodinfo *m)
 }
 
 
+/* native_method_resolve *******************************************************
+
+   Resolves a native method, maybe from a dynamic library.
+
+   IN:
+       m ... methodinfo of the native Java method to resolve
+
+   RESULT:
+       pointer to the resolved method (symbol)
+
+*******************************************************************************/
+
+functionptr native_method_resolve(methodinfo *m)
+{
+       utf                            *name;
+       utf                            *newname;
+       functionptr                     f;
+#if defined(ENABLE_LTDL)
+       classloader_t                  *cl;
+       hashtable_library_loader_entry *le;
+       hashtable_library_name_entry   *ne;
+       u4                              key;    /* hashkey                        */
+       u4                              slot;   /* slot in hashtable              */
+#endif
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       methodinfo                     *method_findNative;
+       java_handle_t                  *s;
+#endif
+
+       /* verbose output */
+
+       if (opt_verbosejni) {
+               printf("[Dynamic-linking native method ");
+               utf_display_printable_ascii_classname(m->clazz->name);
+               printf(".");
+               utf_display_printable_ascii(m->name);
+               printf(" ... ");
+       }
+
+       /* generate method symbol string */
+
+       name = native_method_symbol(m->clazz->name, m->name);
+
+       /* generate overloaded function (having the types in it's name)           */
+
+       newname = native_make_overloaded_function(name, m->descriptor);
+
+       /* check the library hash entries of the classloader of the
+          methods's class  */
+
+       f = NULL;
+
+#if defined(ENABLE_LTDL)
+       /* Get the classloader. */
+
+       cl = class_get_classloader(m->clazz);
+
+       /* normally addresses are aligned to 4, 8 or 16 bytes */
+
+       key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
+       slot = key & (hashtable_library->size - 1);
+       le   = hashtable_library->ptr[slot];
+
+       /* iterate through loaders in this hash slot */
+
+       while ((le != NULL) && (f == NULL)) {
+               /* iterate through names in this loader */
+
+               ne = le->namelink;
+                       
+               while ((ne != NULL) && (f == NULL)) {
+                       f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
+
+                       if (f == NULL)
+                               f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
+
+                       ne = ne->hashlink;
+               }
+
+               le = le->hashlink;
+       }
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       if (f == NULL) {
+               /* We can resolve the function directly from
+                  java.lang.ClassLoader as it's a static function. */
+               /* XXX should be done in native_init */
+
+               method_findNative =
+                       class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                        utf_findNative,
+                                                                        utf_java_lang_ClassLoader_java_lang_String__J,
+                                                                        class_java_lang_ClassLoader,
+                                                                        true);
+
+               if (method_findNative == NULL)
+                       return NULL;
+
+               /* try the normal name */
+
+               s = javastring_new(name);
+
+               f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
+                                                                                                                NULL, cl, s);
+
+               /* if not found, try the mangled name */
+
+               if (f == NULL) {
+                       s = javastring_new(newname);
+
+                       f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
+                                                                                                                        NULL, cl, s);
+               }
+       }
+# endif
+
+       if (f != NULL)
+               if (opt_verbosejni)
+                       printf("JNI ]\n");
+#endif
+
+       /* If not found, try to find the native function symbol in the
+          main program. */
+
+       if (f == NULL) {
+               f = native_method_find(m);
+
+               if (f != NULL)
+                       if (opt_verbosejni)
+                               printf("internal ]\n");
+       }
+
+#if defined(ENABLE_JVMTI)
+       /* fire Native Method Bind event */
+       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
+#endif
+
+       /* no symbol found? throw exception */
+
+       if (f == NULL) {
+               if (opt_verbosejni)
+                       printf("failed ]\n");
+
+               exceptions_throw_unsatisfiedlinkerror(m->name);
+       }
+
+       return f;
+}
+
+
 /* native_library_open *********************************************************
 
    Open a native library with the given utf8 name.
 
+   IN:
+       filename ... filename of the library to open
+
+   RETURN:
+       handle of the opened library
+
 *******************************************************************************/
 
 #if defined(ENABLE_LTDL)
@@ -533,9 +668,12 @@ lt_dlhandle native_library_open(utf *filename)
        handle = lt_dlopen(filename->text);
 
        if (handle == NULL) {
+               if (opt_verbosejni)
+                       printf("failed ]\n");
+
                if (opt_verbose) {
                        log_start();
-                       log_print("native_library_load: lt_dlopen failed: ");
+                       log_print("native_library_open: lt_dlopen failed: ");
                        log_print(lt_dlerror());
                        log_finish();
                }
@@ -543,11 +681,50 @@ lt_dlhandle native_library_open(utf *filename)
                return NULL;
        }
 
+       if (opt_verbosejni)
+               printf("OK ]\n");
+
        return handle;
 }
 #endif
 
 
+/* native_library_close ********************************************************
+
+   Close the native library of the given handle.
+
+   IN:
+       handle ... handle of the open library
+
+*******************************************************************************/
+
+#if defined(ENABLE_LTDL)
+void native_library_close(lt_dlhandle handle)
+{
+       int result;
+
+       if (opt_verbosejni) {
+               printf("[Unloading native library ");
+/*             utf_display_printable_ascii(filename); */
+               printf(" ... ");
+       }
+
+       /* Close the library. */
+
+       result = lt_dlclose(handle);
+
+       if (result != 0) {
+               if (opt_verbose) {
+                       log_start();
+                       log_print("native_library_close: lt_dlclose failed: ");
+                       log_print(lt_dlerror());
+                       log_finish();
+               }
+       }
+}
+#endif
+
+
 /* native_library_add **********************************************************
 
    Adds an entry to the native library hashtable.
@@ -555,7 +732,7 @@ lt_dlhandle native_library_open(utf *filename)
 *******************************************************************************/
 
 #if defined(ENABLE_LTDL)
-void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
+void native_library_add(utf *filename, classloader_t *loader, lt_dlhandle handle)
 {
        hashtable_library_loader_entry *le;
        hashtable_library_name_entry   *ne; /* library name                       */
@@ -638,7 +815,7 @@ void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
 
 #if defined(ENABLE_LTDL)
 hashtable_library_name_entry *native_library_find(utf *filename,
-                                                                                                 classloader *loader)
+                                                                                                 classloader_t *loader)
 {
        hashtable_library_loader_entry *le;
        hashtable_library_name_entry   *ne; /* library name                       */
@@ -680,206 +857,87 @@ hashtable_library_name_entry *native_library_find(utf *filename,
 
        return ne;
 }
-#endif /* !defined(WITH_STATIC_CLASSPATH) */
-
-
-/* native_findfunction *********************************************************
-
-   Looks up a method (must have the same class name, method name,
-   descriptor and 'static'ness) and returns a function pointer to it.
-   Returns: function pointer or NULL (if there is no such method)
-
-   Remark: For faster operation, the names/descriptors are converted
-   from C strings to Unicode the first time this function is called.
-
-*******************************************************************************/
-
-#if defined(WITH_STATIC_CLASSPATH)
-functionptr native_findfunction(utf *cname, utf *mname, utf *desc,
-                                                               bool isstatic)
-{
-       /* entry of table for fast string comparison */
-       struct nativecompref *n;
-       s4 i;
-
-       isstatic = isstatic ? true : false;
-       
-       if (!nativecompdone) {
-               for (i = 0; i < NATIVETABLESIZE; i++) {
-                       nativecomptable[i].classname  = 
-                               utf_new_char(nativetable[i].classname);
-
-                       nativecomptable[i].methodname = 
-                               utf_new_char(nativetable[i].methodname);
-
-                       nativecomptable[i].descriptor =
-                               utf_new_char(nativetable[i].descriptor);
-
-                       nativecomptable[i].isstatic   = nativetable[i].isstatic;
-                       nativecomptable[i].func       = nativetable[i].func;
-               }
-
-               nativecompdone = true;
-       }
-
-       for (i = 0; i < NATIVETABLESIZE; i++) {
-               n = &(nativecomptable[i]);
-
-               if (cname == n->classname && mname == n->methodname &&
-                   desc == n->descriptor && isstatic == n->isstatic)
-                       return n->func;
-       }
-
-       /* no function was found, throw exception */
+#endif
 
-       exceptions_throw_unsatisfiedlinkerror(mname);
 
-       return NULL;
-}
-#endif /* defined(WITH_STATIC_CLASSPATH) */
+/* native_library_load *********************************************************
 
+   Load a native library and initialize it, if possible.
 
-/* native_resolve_function *****************************************************
+   IN:
+       name ... name of the library
+          cl ..... classloader which loads this library
 
-   Resolves a native function, maybe from a dynamic library.
+   RETURN:
+       1 ... library loaded successfully
+       0 ... error
 
 *******************************************************************************/
 
-functionptr native_resolve_function(methodinfo *m)
+int native_library_load(JNIEnv *env, utf *name, classloader_t *cl)
 {
-       classloader                    *cl;
-       utf                            *name;
-       utf                            *newname;
-       functionptr                     f;
 #if defined(ENABLE_LTDL)
-       hashtable_library_loader_entry *le;
-       hashtable_library_name_entry   *ne;
-       u4                              key;    /* hashkey                        */
-       u4                              slot;   /* slot in hashtable              */
-#endif
-#if defined(WITH_CLASSPATH_SUN)
-       methodinfo                     *method_findNative;
-       java_handle_t                  *s;
-#endif
-
-       cl = m->class->classloader;
-
-       /* verbose output */
+       lt_dlhandle        handle;
+# if defined(ENABLE_JNI)
+       lt_ptr             onload;
+       int32_t            version;
+# endif
 
-       if (opt_verbosejni) {
-               printf("[Dynamic-linking native method ");
-               utf_display_printable_ascii_classname(m->class->name);
-               printf(".");
-               utf_display_printable_ascii(m->name);
-               printf(" ... ");
+       if (name == NULL) {
+               exceptions_throw_nullpointerexception();
+               return 0;
        }
 
-       /* generate method symbol string */
+       /* Is the library already loaded? */
 
-       name = native_method_symbol(m->class->name, m->name);
-
-       /* generate overloaded function (having the types in it's name)           */
-
-       newname = native_make_overloaded_function(name, m->descriptor);
-
-       /* check the library hash entries of the classloader of the
-          methods's class  */
-
-       f = NULL;
-
-#if defined(ENABLE_LTDL)
-       /* normally addresses are aligned to 4, 8 or 16 bytes */
-
-       key  = ((u4) (ptrint) cl) >> 4;                       /* align to 16-byte */
-       slot = key & (hashtable_library->size - 1);
-       le   = hashtable_library->ptr[slot];
-
-       /* iterate through loaders in this hash slot */
-
-       while ((le != NULL) && (f == NULL)) {
-               /* iterate through names in this loader */
-
-               ne = le->namelink;
-                       
-               while ((ne != NULL) && (f == NULL)) {
-                       f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text);
+       if (native_library_find(name, cl) != NULL)
+               return 1;
 
-                       if (f == NULL)
-                               f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text);
+       /* Open the library. */
 
-                       ne = ne->hashlink;
-               }
+       handle = native_library_open(name);
 
-               le = le->hashlink;
-       }
+       if (handle == NULL)
+               return 0;
 
-# if defined(WITH_CLASSPATH_SUN)
-       if (f == NULL) {
-               /* We can resolve the function directly from
-                  java.lang.ClassLoader as it's a static function. */
-               /* XXX should be done in native_init */
-
-               method_findNative =
-                       class_resolveclassmethod(class_java_lang_ClassLoader,
-                                                                        utf_findNative,
-                                                                        utf_java_lang_ClassLoader_java_lang_String__J,
-                                                                        class_java_lang_ClassLoader,
-                                                                        true);
+# if defined(ENABLE_JNI)
+       /* Resolve JNI_OnLoad function. */
 
-               if (method_findNative == NULL)
-                       return NULL;
+       onload = lt_dlsym(handle, "JNI_OnLoad");
 
-               /* try the normal name */
+       if (onload != NULL) {
+               JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
+               JavaVM *vm;
 
-               s = javastring_new(name);
+               JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
 
-               f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
-                                                                                                                NULL, cl, s);
+               (*env)->GetJavaVM(env, &vm);
 
-               /* if not found, try the mangled name */
+               version = JNI_OnLoad(vm, NULL);
 
-               if (f == NULL) {
-                       s = javastring_new(newname);
+               /* If the version is not 1.2 and not 1.4 the library cannot be
+                  loaded. */
 
-                       f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
-                                                                                                                        NULL, cl, s);
+               if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+                       lt_dlclose(handle);
+                       return 0;
                }
        }
 # endif
 
-       if (f != NULL)
-               if (opt_verbosejni)
-                       printf("JNI ]\n");
-#endif
+       /* Insert the library name into the library hash. */
 
-       /* If not found, try to find the native function symbol in the
-          main program. */
+       native_library_add(name, cl, handle);
 
-       if (f == NULL) {
-               f = native_method_find(m);
+       return 1;
+#else
+       vm_abort("native_library_load: not available");
 
-               if (f != NULL)
-                       if (opt_verbosejni)
-                               printf("internal ]\n");
-       }
+       /* Keep compiler happy. */
 
-#if defined(ENABLE_JVMTI)
-       /* fire Native Method Bind event */
-       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
+       return 0;
 #endif
-
-       /* no symbol found? throw exception */
-
-       if (f == NULL) {
-               if (opt_verbosejni)
-                       printf("failed ]\n");
-
-               exceptions_throw_unsatisfiedlinkerror(m->name);
-       }
-
-       return f;
 }
-#endif /* !defined(WITH_STATIC_CLASSPATH) */
 
 
 /* native_new_and_init *********************************************************
@@ -965,4 +1023,5 @@ java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */