Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/vm/classloader.h |    1 +
 vm/classloader.c         |  107 ++++++++++++++++-----------------------------
 vm/jato.c                |    2 +
 3 files changed, 41 insertions(+), 69 deletions(-)

diff --git a/include/vm/classloader.h b/include/vm/classloader.h
index 6cd728f..505b3db 100644
--- a/include/vm/classloader.h
+++ b/include/vm/classloader.h
@@ -11,6 +11,7 @@ int classloader_add_to_classpath(const char *classpath);
 int try_to_add_zip_to_classpath(const char *zip);
 char *get_classpath(void);
 
+void classloader_init(void);
 struct vm_class *classloader_load(const char *class_name);
 struct vm_class *classloader_load_primitive(const char *class_name);
 struct vm_class *classloader_find_class(const char *name);
diff --git a/vm/classloader.c b/vm/classloader.c
index 1c3e7f3..4aaf7fc 100644
--- a/vm/classloader.c
+++ b/vm/classloader.c
@@ -16,6 +16,7 @@
 #include "vm/trace.h"
 
 #include "lib/string.h"
+#include "lib/hash-map.h"
 
 bool opt_trace_classloader;
 static __thread int trace_classloader_level = 0;
@@ -184,39 +185,27 @@ int classloader_add_to_classpath(const char *classpath)
 }
 
 struct classloader_class {
-       /* If false then the class loading is in progress. */
        bool loaded;
-
-       union {
-               /* When @loaded is false this holds the class's name. It
-                * should not be referenced when class is loaded. */
-               const char *class_name;
-
-               struct vm_class *class;
-       };
+       struct vm_class *class;
 };
 
-static struct classloader_class *classes;
-static unsigned long max_classes;
-static unsigned long nr_classes;
+static struct hash_map *classes;
 
-static int lookup_class(const char *class_name)
+void classloader_init(void)
 {
-       unsigned long i;
+       classes = alloc_hash_map(10000, string_hash, string_compare);
+       if (!classes)
+               error("failed to initialize class loader");
+}
 
-       for (i = 0; i < nr_classes; ++i) {
-               struct classloader_class *class = &classes[i];
+static struct classloader_class *lookup_class(const char *class_name)
+{
+       void *class;
 
-               if (!class->loaded) {
-                       if (!strcmp(class->class_name, class_name))
-                               return i;
-               } else {
-                       if (!strcmp(class->class->name, class_name))
-                               return i;
-               }
-       }
+       if (hash_map_get(classes, class_name, &class))
+               return NULL;
 
-       return -1;
+       return class;
 }
 
 static char *dots_to_slash(const char *name)
@@ -482,9 +471,7 @@ out_filename:
 struct vm_class *classloader_load(const char *class_name)
 {
        struct vm_class *vmc;
-       struct classloader_class *new_array;
-       unsigned long new_max_classes;
-       int class_index;
+       struct classloader_class *class;
 
        trace_push(class_name);
 
@@ -496,47 +483,26 @@ struct vm_class *classloader_load(const char *class_name)
 
        pthread_mutex_lock(&classloader_mutex);
 
-       /*
-        * XXX: we must use index here not the entry pointer because
-        * while we're loading a class or waiting for a class to get
-        * loaded the classes array might get relocated.
-        */
-       class_index = lookup_class(slash_class_name);
-       if (class_index >= 0) {
+       class = lookup_class(slash_class_name);
+       if (class) {
                /* If class is being loaded by another thread then wait
                 * until loading is completed. */
-               while (!classes[class_index].loaded)
-                       pthread_cond_wait(&classloader_cond,
-                                         &classloader_mutex);
+               while (!class->loaded)
+                       pthread_cond_wait(&classloader_cond, 
&classloader_mutex);
 
-               vmc = classes[class_index].class;
+               vmc = class->class;
                goto out_unlock;
        }
 
-       /*
-        * We allocate cache space before loading to indicate that we
-        * are loading this class and other threads wanting to load
-        * that class in the same time should wait for us.
-        */
-       if (nr_classes == max_classes) {
-               new_max_classes = 1 + max_classes * 2;
-               new_array = realloc(classes,
-                       new_max_classes * sizeof(struct classloader_class));
-               if (!new_array) {
-                       NOT_IMPLEMENTED;
-                       vmc = NULL;
-                       goto out_unlock;
-               }
+       class = malloc(sizeof(*class));
+       class->loaded = false;
 
-               max_classes = new_max_classes;
-               classes = new_array;
+       if (hash_map_put(classes, strdup(slash_class_name), class)) {
+               NOT_IMPLEMENTED;
+               vmc = NULL;
+               goto out_unlock;
        }
 
-       class_index = nr_classes++;
-
-       classes[class_index].loaded = false;
-       classes[class_index].class_name = slash_class_name;
-
        pthread_mutex_unlock(&classloader_mutex);
 
        /*
@@ -546,6 +512,10 @@ struct vm_class *classloader_load(const char *class_name)
         */
        vmc = load_class(slash_class_name);
        if (!vmc) {
+               /*
+                * We should remove the entry from map but other threads
+                * might be waiting on it.
+                */
                NOT_IMPLEMENTED;
                vmc = NULL;
                goto out;
@@ -555,8 +525,8 @@ struct vm_class *classloader_load(const char *class_name)
 
        vmc->classloader = NULL;
 
-       classes[class_index].loaded = true;
-       classes[class_index].class = vmc;
+       class->class = vmc;
+       class->loaded = true;
 
        /* Tell other threads that the class has been loaded. Would it
         * be worth to use a per-class condition variable for that? */
@@ -579,7 +549,7 @@ struct vm_class *classloader_find_class(const char *name)
 {
        struct vm_class *vmc;
        char *slash_class_name;
-       int class_index;
+       struct classloader_class *class;
 
        slash_class_name = dots_to_slash(name);
        if (!slash_class_name) {
@@ -591,15 +561,14 @@ struct vm_class *classloader_find_class(const char *name)
 
        pthread_mutex_lock(&classloader_mutex);
 
-       class_index = lookup_class(slash_class_name);
-       if (class_index >= 0) {
+       class = lookup_class(slash_class_name);
+       if (class) {
                /* If class is being loaded by another thread then wait
                 * until loading is completed. */
-               while (!classes[class_index].loaded)
-                       pthread_cond_wait(&classloader_cond,
-                                         &classloader_mutex);
+               while (!class->loaded)
+                       pthread_cond_wait(&classloader_cond, 
&classloader_mutex);
 
-               vmc = classes[class_index].class;
+               vmc = class->class;
        }
 
        free(slash_class_name);
diff --git a/vm/jato.c b/vm/jato.c
index 6b0f7c3..f6744d7 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -1241,6 +1241,8 @@ main(int argc, char *argv[])
 
        init_configurable_system_properties();
 
+       classloader_init();
+
        init_vm_objects();
 
        jit_text_init();
-- 
1.6.0.6


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to