* implemented the library hash: each loaded library with it's classloader
authortwisti <none@none>
Tue, 14 Jun 2005 22:31:37 +0000 (22:31 +0000)
committertwisti <none@none>
Tue, 14 Jun 2005 22:31:37 +0000 (22:31 +0000)
  is stored in the hash, TODO: reference count and unloading

src/native/native.c
src/native/native.h
src/native/vm/VMRuntime.c

index 070cf8b9a7b1e0dc779705746955d5ece23418ff..4d25a6df55fb32a82fc6b4e62d3399f2f6963167 100644 (file)
@@ -30,7 +30,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: native.c 2690 2005-06-14 17:48:49Z twisti $
+   $Id: native.c 2696 2005-06-14 22:31:37Z twisti $
 
 */
 
@@ -279,6 +279,12 @@ static struct nativeCall nativeCalls[] =
 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
 
 
+/* global variables ***********************************************************/
+
+static hashtable library_hash;
+static lt_dlhandle mainhandle;
+
+
 /* native_loadclasses **********************************************************
 
    Load classes required for native methods.
@@ -304,6 +310,16 @@ bool native_init(void)
 
                return false;
        }
+
+       /* get the handle for the main program */
+
+       if (!(mainhandle = lt_dlopen(NULL)))
+               return false;
+
+       /* initialize library hashtable, 10 entries should be enough */
+
+       init_hashtable(&library_hash, 10);
+
 #endif
 
        /* everything's ok */
@@ -312,6 +328,126 @@ bool native_init(void)
 }
 
 
+/* native_library_hash_add *****************************************************
+
+   Adds an entry to the native library hashtable.
+
+*******************************************************************************/
+
+void native_library_hash_add(utf *filename, java_objectheader *loader,
+                                                        lt_dlhandle handle)
+{
+       library_hash_loader_entry *le;
+       library_hash_name_entry   *ne;      /* library name                       */
+       u4   key;                           /* hashkey                            */
+       u4   slot;                          /* slot in hashtable                  */
+       u4   i;
+
+       key = (u4) (ptrint) loader;         /* we use the classinfo pointer       */
+       slot = key & (library_hash.size - 1);
+       le = library_hash.ptr[slot];
+
+       /* search external hash chain for the entry */
+
+       while (le) {
+               if (le->loader == loader)
+                       break;
+
+               le = le->hashlink;                  /* next element in external chain */
+       }
+
+       /* no loader found? create a new entry */
+
+       if (!le) {
+               le = NEW(library_hash_loader_entry);
+
+               le->loader = loader;
+               le->namelink = NULL;
+
+               /* insert entry into hashtable */
+
+               le->hashlink = (library_hash_loader_entry *) library_hash.ptr[slot];
+               library_hash.ptr[slot] = le;
+
+               /* update number of hashtable-entries */
+
+               library_hash.entries++;
+       }
+
+
+       /* search for library name */
+
+       ne = le->namelink;
+
+       while (ne) {
+               if (ne->name->blength == filename->blength) {
+                       for (i = 0; i < (u4) filename->blength; i++)
+                               if (ne->name->text[i] != filename->text[i])
+                                       goto nomatch;
+
+                       /* entry found in hashtable */
+
+                       return;
+               }
+
+       nomatch:
+               ne = ne->hashlink;                  /* next element in external chain */
+       }
+
+       /* not found? add the library name to the classloader */
+
+       ne = NEW(library_hash_name_entry);
+
+       ne->name = filename;
+       ne->handle = handle;
+
+       /* insert entry into external chain */
+
+       ne->hashlink = le->namelink;
+       le->namelink = ne;
+
+
+       /* check for hashtable size */
+
+       if (library_hash.entries > (library_hash.size * 2)) {
+
+               /* reorganization of hashtable, average length of 
+                  the external chains is approx. 2                */
+
+               hashtable           newhash;                     /* the new hashtable */
+
+               /* create new hashtable, double the size */
+
+               init_hashtable(&newhash, library_hash.size * 2);
+               newhash.entries = library_hash.entries;
+
+               /* transfer elements to new hashtable */
+
+               for (i = 0; i < library_hash.size; i++) {
+                       le = (library_hash_loader_entry *) library_hash.ptr[i];
+
+                       while (le) {
+                               library_hash_loader_entry *nextl = le->hashlink;
+                               u4 newslot = ((u4) (ptrint) le) & (newhash.size - 1);
+
+                               le->hashlink =
+                                       (library_hash_loader_entry *) newhash.ptr[newslot];
+
+                               newhash.ptr[newslot] = le;
+
+                               le = nextl;
+                       }
+               }
+
+               /* dispose old table */
+
+               MFREE(library_hash.ptr, void *, library_hash.size);
+
+               library_hash = newhash;
+       }
+}
+
+
 /*********************** Function: native_findfunction *************************
 
        Looks up a method (must have the same class name, method name, descriptor
@@ -541,24 +677,18 @@ static char *native_make_overloaded_function(char *name, utf *desc)
 
 functionptr native_resolve_function(methodinfo *m)
 {
-       lt_dlhandle  handle;
-       lt_ptr       sym;
-       char        *name;
-       s4           namelen;
-       char        *utf_ptr;
-       char        *utf_endptr;
-       s4           dumpsize;
-       s4           i;
-
-       /* get the handle for the main program */
+       lt_ptr                     sym;
+       char                      *name;
+       s4                         namelen;
+       char                      *utf_ptr;
+       char                      *utf_endptr;
+       s4                         dumpsize;
+       library_hash_loader_entry *le;
+       library_hash_name_entry   *ne;
+       u4                         key;     /* hashkey                            */
+       u4                         slot;    /* slot in hashtable                  */
+       u4                         i;
 
-       handle = lt_dlopen(NULL);
-
-       if (!handle) {
-               *exceptionptr =
-                       new_internalerror("lt_dlopen: can't get handle for the main program");
-               return NULL;
-       }
 
        /* calculate length of native function name */
 
@@ -633,11 +763,9 @@ functionptr native_resolve_function(methodinfo *m)
        name[i] = '\0';
 
 
-       /* try to find the native function symbol */
-
-       sym = lt_dlsym(handle, name);
+       /* try to find the native function symbol in the main program */
 
-       if (!sym) {
+       if (!(sym = lt_dlsym(mainhandle, name))) {
                /* we didn't find the symbol yet, try to resolve an overloaded        */
                /* function (having the types in it's name)                           */
 
@@ -645,16 +773,38 @@ functionptr native_resolve_function(methodinfo *m)
 
                /* try to find the overloaded symbol */
 
-               sym = lt_dlsym(handle, name);
+               sym = lt_dlsym(mainhandle, name);
+       }
 
-               if (!sym) {
-                       *exceptionptr =
-                               new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
-                                                                                m->name);
-                       return NULL;
+       /* if symbol not found, check the library hash entries of the classloader */
+       /* of the methods's class                                                 */
+
+       if (!sym) {
+               key = (u4) (ptrint) m->class->classloader;
+               slot = key & (library_hash.size - 1);
+               le = library_hash.ptr[slot];
+
+               ne = le->namelink;
+
+               while (ne && !sym) {
+                       sym = lt_dlsym(ne->handle, name);
+
+                       if (!sym) {
+                               name = native_make_overloaded_function(name, m->descriptor);
+                               sym = lt_dlsym(ne->handle, name);
+                       }
+
+                       ne = ne->hashlink;
                }
        }
 
+       /* no symbol found? throw exception */
+
+       if (!sym)
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError,
+                                                                        m->name);
+
        /* release memory */
 
        dump_release(dumpsize);
index ab5aecddeac8ca2b45c3c00a17f165dfee4a59c3..e712b3e0ce5947fedcc6a0bb751cb09f63482e15 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: native.h 2690 2005-06-14 17:48:49Z twisti $
+   $Id: native.h 2696 2005-06-14 22:31:37Z twisti $
 
 */
 
 #ifndef _NATIVE_H
 #define _NATIVE_H
 
+#if !defined(STATIC_CLASSPATH)
+# include "src/libltdl/ltdl.h"
+#endif
+
 #include "vm/class.h"
 #include "vm/global.h"
 #include "vm/method.h"
 
 /* table for locating native methods */
 
+typedef struct library_hash_loader_entry library_hash_loader_entry;
+typedef struct library_hash_name_entry library_hash_name_entry;
 typedef struct nativeref nativeref;
 typedef struct nativecompref nativecompref;
 
+
+/* library_hash_loader_entry **************************************************/
+
+struct library_hash_loader_entry {
+       java_objectheader         *loader;  /* class loader                       */
+       library_hash_name_entry   *namelink;/* libraries loaded by this loader    */
+       library_hash_loader_entry *hashlink;/* link for external chaining         */
+};
+
+
+/* library_hash_name_entry ****************************************************/
+
+struct library_hash_name_entry {
+       utf                     *name;      /* library name                       */
+       lt_dlhandle              handle;    /* libtool library handle             */
+       library_hash_name_entry *hashlink;  /* link for external chaining         */
+};
+
+
 struct nativeref {
        char       *classname;
        char       *methodname;
@@ -72,9 +97,13 @@ struct nativecompref {
 
 void use_class_as_object(classinfo *c);
 
-/* load classes required for native methods */
+/* initialize native subsystem */
 bool native_init(void);
 
+/* add a library to the library hash */
+void native_library_hash_add(utf *filename, java_objectheader *loader,
+                                                        lt_dlhandle handle);
+
 /* find native function */
 functionptr native_findfunction(utf *cname, utf *mname, 
                                                                utf *desc, bool isstatic);
index 3af4ec0a1ea1c181790eb22a75b2a057209310df..24333ba470a1e0349a34bb7d706da834876a3c83 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Joseph Wenninger
             Christian Thalinger
 
-   $Id: VMRuntime.c 2647 2005-06-13 13:56:42Z twisti $
+   $Id: VMRuntime.c 2696 2005-06-14 22:31:37Z twisti $
 
 */
 
@@ -255,7 +255,8 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_availableProcessors(JNIEnv *env, j
  */
 JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, java_lang_String *filename, java_lang_ClassLoader *loader)
 {
-       utf *name;
+       utf         *name;
+       lt_dlhandle  handle;
 
        if (!filename) {
                *exceptionptr = new_nullpointerexception();
@@ -270,10 +271,14 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass cla
        /* here it could be interesting to store the references in a list eg for  */
        /* nicely cleaning up or for certain platforms */
 
-       if (lt_dlopenext(name->text))
-               return 1;
+       if (!(handle = lt_dlopenext(name->text)))
+               return 0;
+
+       /* insert the library name into the library hash */
 
-       return 0;
+       native_library_hash_add(name, loader, handle);
+
+       return 1;
 #endif
 }