* src/native/vm/openjdk/jvm.cpp (JVM_CurrentClassLoader): Implemented.
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 15 Apr 2009 09:39:14 +0000 (11:39 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 15 Apr 2009 09:39:14 +0000 (11:39 +0200)
* src/vm/javaobjects.hpp [ENABLE_JAVASE] (java_lang_ClassLoader): Added.
* src/vm/javaobjects.cpp (java_lang_ClassLoader::invoke_getSystemClassLoader):
Implemented new invocation wrapper method.
* src/vm/loader.cpp (load_class_from_sysloader): Use above invocation wrapper.
* src/vm/jit/stacktrace.cpp (stacktrace_first_nonsystem_classloader): Added.
* src/vm/jit/stacktrace.hpp: Likewise.
* src/vm/vm.cpp (vm_get_mainclass_from_jar): Added workaround to make it
compile with CLDC. We have to look into this at some point.

src/native/vm/openjdk/jvm.cpp
src/vm/javaobjects.cpp
src/vm/javaobjects.hpp
src/vm/jit/stacktrace.cpp
src/vm/jit/stacktrace.hpp
src/vm/loader.cpp
src/vm/vm.cpp

index f356686358642efa01c9008f83f1dfed5fb1628d..596b3df83a79471947865036e66b7c0727768683 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
         }                                                                              \
     } while (0)
 
-# define PRINTJVMWARNINGS(x)
-/*     do { \ */
-/*         if (opt_PrintJVMWarnings) { \ */
-/*             log_println x; \ */
-/*         } \ */
-/*     } while (0) */
+# define PRINTJVMWARNINGS(x)                                   \
+    do {                                                                               \
+        if (opt_PrintWarnings) {                               \
+            log_println x;                                             \
+        }                                                                              \
+    } while (0)
 
 #else
 
@@ -2316,12 +2317,10 @@ jclass JVM_CurrentLoadedClass(JNIEnv *env)
 
 jobject JVM_CurrentClassLoader(JNIEnv *env)
 {
-    /* XXX if a method in a class in a trusted loader is in a
-          doPrivileged, return NULL */
-
-       log_println("JVM_CurrentClassLoader: IMPLEMENT ME!");
+       TRACEJVMCALLS(("JVM_CurrentClassLoader(env=%p)", env));
+       PRINTJVMWARNINGS(("JVM_CurrentClassLoader is deprecated, do not use it."));
 
-       return NULL;
+       return stacktrace_first_nonsystem_classloader();
 }
 
 
@@ -2413,13 +2412,9 @@ jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint le
 
 jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
 {
-       classloader_t *cl;
-
        TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env));
 
-       cl = stacktrace_first_nonnull_classloader();
-
-       return (jobject) cl;
+       return stacktrace_first_nonnull_classloader();
 }
 
 
index b8a0d601326b5b830b68e14a474d44ca009341df..901756534cd4441f25d5f03a5e2b7e706f402e52 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/javaobjects.cpp - functions to create and access Java objects
 
-   Copyright (C) 2008 Theobroma Systems Ltd.
+   Copyright (C) 2008, 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #if defined(ENABLE_JAVASE)
 
+/**
+ * Invokes the static Java method getSystemClassLoader().
+ *
+ * @return Return value of the invocation or NULL in
+ * case of an exception.
+ */
+java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader()
+{
+       methodinfo    *m;
+       java_handle_t *clo;
+       classloader_t *cl;
+
+       assert(class_java_lang_Object);
+       assert(class_java_lang_ClassLoader);
+       assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
+
+       m = class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                utf_getSystemClassLoader,
+                                                                utf_void__java_lang_ClassLoader,
+                                                                class_java_lang_Object,
+                                                                false);
+
+       if (m == NULL)
+               return NULL;
+
+       clo = vm_call_method(m, NULL);
+
+       if (clo == NULL)
+               return NULL;
+
+       cl = loader_hashtable_classloader_add(clo);
+
+       return cl;
+}
+
+
 /**
  * Constructs a Java object with the given
  * java.lang.reflect.Constructor.
@@ -67,7 +103,7 @@ java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarr
 
        if (h == NULL)
                return NULL;
-        
+
        // Call initializer.
        (void) Reflection::invoke(m, h, args);
 
index b8ee1215a26280226c6296bd90cfcfb2a268d55c..71f58abb11147bfe1de4996a6df396331f529237 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/javaobjects.hpp - functions to create and access Java objects
 
-   Copyright (C) 2008 Theobroma Systems Ltd.
+   Copyright (C) 2008, 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -590,6 +590,39 @@ inline void java_lang_Class::set_pd(java_handle_t* value)
 }
 
 
+/**
+ * GNU Classpath java/lang/ClassLoader
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.util.HashMap     definedPackages
+ * 2. java.lang.ClassLoader parent
+ * [other fields are not used]
+ */
+class java_lang_ClassLoader : public java_lang_Object, private FieldAccess {
+private:
+       // Static offsets of the object's instance fields.
+       // TODO These offsets need to be checked on VM startup.
+       static const off_t offset_definedPackages = MEMORY_ALIGN(sizeof(java_object_t),                  SIZEOF_VOID_P);
+       static const off_t offset_parent          = MEMORY_ALIGN(offset_definedPackages + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+       java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {}
+
+       // Getters.
+       java_handle_t* get_parent() const;
+
+       // Invocation wrappers for static methods.
+       static java_handle_t* invoke_getSystemClassLoader();
+};
+
+inline java_handle_t* java_lang_ClassLoader::get_parent() const
+{
+       return get<java_handle_t*>(_handle, offset_parent);
+}
+
+
 /**
  * GNU Classpath java/lang/StackTraceElement
  *
@@ -1715,7 +1748,7 @@ public:
        gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {}
        gnu_classpath_Pointer(java_handle_t* h, void* data);
 
-       // Setters.
+       // Getters.
        void* get_data() const;
 
        // Setters.
@@ -1788,6 +1821,39 @@ inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives(
 }
 
 
+/**
+ * OpenJDK java/lang/ClassLoader
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean               initialized
+ * 2. java.lang.ClassLoader parent
+ * [other fields are not used]
+ */
+class java_lang_ClassLoader : public java_lang_Object, private FieldAccess {
+private:
+       // Static offsets of the object's instance fields.
+       // TODO These offsets need to be checked on VM startup.
+       static const off_t offset_initialized = MEMORY_ALIGN(sizeof(java_object_t),                sizeof(int32_t));
+       static const off_t offset_parent      = MEMORY_ALIGN(offset_initialized + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+       java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {}
+
+       // Getters.
+       java_handle_t* get_parent() const;
+
+       // Invocation wrappers for static methods.
+       static java_handle_t* invoke_getSystemClassLoader();
+};
+
+inline java_handle_t* java_lang_ClassLoader::get_parent() const
+{
+       return get<java_handle_t*>(_handle, offset_parent);
+}
+
+
 /**
  * OpenJDK java/lang/StackTraceElement
  *
index e3389e4ac49a33cc210d7b3963a255058bb1fb4e..b51154ed2578fdb94b3068f88660ece7eb2bffa1 100644 (file)
@@ -2,6 +2,7 @@
 
    Copyright (C) 1996-2005, 2006, 2007, 2008
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
@@ -872,17 +873,12 @@ classinfo *stacktrace_get_caller_class(int depth)
 #endif
 
 
-/* stacktrace_first_nonnull_classloader ****************************************
-
-   Returns the first non-null (user-defined) classloader on the stack.
-   If none is found NULL is returned.
-
-   RETURN:
-       classloader
-
-*******************************************************************************/
-
-classloader_t *stacktrace_first_nonnull_classloader(void)
+/**
+ * Returns the first non-null (user-defined) classloader on the stack.
+ *
+ * @return The first non-null classloader or NULL if none is found.
+ */
+classloader_t* stacktrace_first_nonnull_classloader(void)
 {
        stackframeinfo_t *sfi;
        stackframeinfo_t  tmpsfi;
@@ -915,6 +911,82 @@ classloader_t *stacktrace_first_nonnull_classloader(void)
 }
 
 
+/**
+ * Checks if a given classloader is equal to the the second classloader
+ * or one of its ancestors (parents).
+ *
+ * XXX: This helper method should be moved to java_lang_Classloader.
+ */
+#if defined(ENABLE_JAVASE)
+static bool is_ancestor_of(classloader_t* loader, classloader_t* parent)
+{
+       // Iterate over chain of possible parents.
+       while (parent != NULL) {
+
+               // Check if given loader is parent.
+               if (loader == parent)
+                       return true;
+
+               // Jump to next parent.
+               java_lang_ClassLoader jlcl(parent);
+               parent = jlcl.get_parent();
+       }
+
+       return false;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/**
+ * Returns the first non-system (user-defined) classloader on the stack.
+ * A non-system classloader is a non-null classloader being not equal to
+ * the system classloader (or one of its ancestors).
+ *
+ * @return The first non-system classloader or NULL if none is found.
+ */
+#if defined(ENABLE_JAVASE)
+classloader_t* stacktrace_first_nonsystem_classloader(void)
+{
+       stackframeinfo_t *sfi;
+       stackframeinfo_t  tmpsfi;
+       methodinfo       *m;
+       classloader_t    *cl;
+       classloader_t    *syscl;
+
+#if !defined(NDEBUG)
+       if (opt_DebugStackTrace)
+               log_println("[stacktrace_first_nonsystem_classloader]");
+#endif
+
+       // Get the stackframeinfo of the current thread.
+       sfi = threads_get_current_stackframeinfo();
+
+       // Get the system class class loader.
+       syscl = java_lang_ClassLoader::invoke_getSystemClassLoader();
+
+       // Iterate over the whole stack.
+       for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+                stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+                stacktrace_stackframeinfo_next(&tmpsfi)) {
+
+               m  = tmpsfi.code->m;
+               cl = class_get_classloader(m->clazz);
+
+               if (cl == NULL)
+                       continue;
+
+               // XXX if a method in a class in a trusted loader is in a
+               // doPrivileged, return NULL (or break) here.
+
+               if (!is_ancestor_of(cl, syscl))
+                       return cl;
+       }
+
+       return NULL;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
 /* stacktrace_getClassContext **************************************************
 
    Creates a Class context array.
index 2c2920c826b55de4d14e1b517dd824f176b06fce..ee032b2a2107606662dc0bb1faba4cb1637e3f78 100644 (file)
@@ -110,6 +110,7 @@ java_handle_t*             stacktrace_get_StackTraceElement(stacktrace_t *st, in
 java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t *st);
 classinfo                 *stacktrace_get_caller_class(int depth);
 classloader_t             *stacktrace_first_nonnull_classloader(void);
+classloader_t             *stacktrace_first_nonsystem_classloader(void);
 java_handle_objectarray_t *stacktrace_getClassContext(void);
 classinfo                 *stacktrace_get_current_class(void);
 java_handle_objectarray_t *stacktrace_get_stack(void);
index 2dd8dac9feeabf7c6ced20ea9e317c696b8fc6ce..e697a97ddbc5e693724a63f986815218170467cb 100644 (file)
@@ -48,6 +48,7 @@
 #include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
 #include "vm/linker.hpp"
 #include "vm/loader.hpp"
 #include "vm/method.hpp"
@@ -992,37 +993,22 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
 
 *******************************************************************************/
 
+#if defined(ENABLE_JAVASE)
 classinfo *load_class_from_sysloader(utf *name)
 {
-       methodinfo    *m;
-       java_handle_t *clo;
        classloader_t *cl;
        classinfo     *c;
 
-       assert(class_java_lang_Object);
-       assert(class_java_lang_ClassLoader);
-       assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
-       
-       m = class_resolveclassmethod(class_java_lang_ClassLoader,
-                                                                utf_getSystemClassLoader,
-                                                                utf_void__java_lang_ClassLoader,
-                                                                class_java_lang_Object,
-                                                                false);
-
-       if (!m)
-               return false;
+       cl = java_lang_ClassLoader::invoke_getSystemClassLoader();
 
-       clo = vm_call_method(m, NULL);
-
-       if (!clo)
+       if (cl == NULL)
                return false;
 
-       cl = loader_hashtable_classloader_add(clo);
-
        c = load_class_from_classloader(name, cl);
 
        return c;
 }
+#endif /* defined(ENABLE_JAVASE) */
 
 
 /* load_class_from_classloader *************************************************
index 23518fd85435b4100e6971781c716dd0c7f632b0..1239da685cfc3c129b10ff7f81576d1a2ee68b83 100644 (file)
@@ -2011,7 +2011,11 @@ static char *vm_get_mainclass_from_jar(char *mainname)
        methodinfo    *m;
        java_handle_t *s;
 
+#if defined(ENABLE_JAVAME_CLDC1_1)
+       c = load_class_bootstrap(utf_new_char("java/util/jar/JarFile"));
+#else
        c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+#endif
 
        if (c == NULL) {
                exceptions_print_stacktrace();