Merged with tip.
[cacao.git] / src / vm / initialize.c
index e3493ebd3682df73ef74a4f5eb37a0598cf736f1..2c6ff024ddad81c18b4997484c477006380cbfe5 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/initialize.c - static class initializer functions
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Reinhard Grafl
+*/
 
-   Changes: Mark Probst
-            Andreas Krall
-            Christian Thalinger
 
-   $Id: initialize.c 2424 2005-04-30 13:45:06Z jowenn $
+#include "config.h"
 
-*/
+#include <string.h>
 
+#include "vm/types.h"
 
-#include <string.h>
+#include "threads/lock-common.h"
 
 #include "vm/global.h"
 #include "vm/initialize.h"
 #include "vm/builtin.h"
-#include "vm/class.h"
-#include "vm/loader.h"
 #include "vm/exceptions.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
+#include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
-#undef JWDEBUG
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
 
 /* private functions **********************************************************/
 
 static bool initialize_class_intern(classinfo *c);
 
 
+/* initialize_init *************************************************************
+
+   Initialize important system classes.
+
+*******************************************************************************/
+
+void initialize_init(void)
+{
+       TRACESUBSYSTEMINITIALIZATION("initialize_init");
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_GNU)
+
+       /* Nothing. */
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+       if (!initialize_class(class_java_lang_String))
+               vm_abort("initialize_init: Initialization failed: java.lang.String");
+
+       if (!initialize_class(class_java_lang_System))
+               vm_abort("initialize_init: Initialization failed: java.lang.System");
+
+       if (!initialize_class(class_java_lang_ThreadGroup))
+               vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
+
+       if (!initialize_class(class_java_lang_Thread))
+               vm_abort("initialize_init: Initialization failed: java.lang.Thread");
+
+# else
+#  error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+       /* Nothing. */
+
+#else
+# error unknown Java configuration
+#endif
+}
+
 /* initialize_class ************************************************************
 
    In Java, every class can have a static initialization
@@ -70,54 +111,49 @@ bool initialize_class(classinfo *c)
        if (!makeinitializations)
                return true;
 
-#if defined(USE_THREADS)
-       /* enter a monitor on the class */
-
-       builtin_monitorenter((java_objectheader *) c);
-#endif
+       LOCK_MONITOR_ENTER(c);
 
        /* maybe the class is already initalized or the current thread, which can
           pass the monitor, is currently initalizing this class */
 
-       /* JOWENN: In future we need an additinal flag: initializationfailed,
-               since further access to the class should cause a NoClassDefFound,
-               if the static initializer failed once
-        */
+       if (CLASS_IS_OR_ALMOST_INITIALIZED(c)) {
+               LOCK_MONITOR_EXIT(c);
 
-       if (c->initialized || c->initializing) {
-#if defined(USE_THREADS)
-               builtin_monitorexit((java_objectheader *) c);
-#endif
+               return true;
+       }
+
+       /* if <clinit> throw an Error before, the class was marked with an
+       error and we have to throw a NoClassDefFoundError */
+
+       if (c->state & CLASS_ERROR) {
+               exceptions_throw_noclassdeffounderror(c->name);
+
+               LOCK_MONITOR_EXIT(c);
+
+               /* ...but return true, this is ok (mauve test) */
 
                return true;
        }
 
-#ifdef JWDEBUG
-       printf("preparing to call initialize_class_intern for %s\n",c->name->text);
-#endif
        /* this initalizing run begins NOW */
-       c->initializing = true;
+
+       c->state |= CLASS_INITIALIZING;
 
        /* call the internal function */
+
        r = initialize_class_intern(c);
 
        /* if return value is not NULL everything was ok and the class is
           initialized */
-       if (r)
-               c->initialized = true;
 
-#ifdef JWDEBUG
-       printf("finished to call initialize_class_intern for %s\n",c->name->text);
-#endif
+       if (r)
+               c->state |= CLASS_INITIALIZED;
 
        /* this initalizing run is done */
-       c->initializing = false;
 
-#if defined(USE_THREADS)
-       /* leave the monitor */
+       c->state &= ~CLASS_INITIALIZING;
 
-       builtin_monitorexit((java_objectheader *) c);
-#endif
+       LOCK_MONITOR_EXIT(c);
 
        return r;
 }
@@ -132,141 +168,99 @@ bool initialize_class(classinfo *c)
 
 static bool initialize_class_intern(classinfo *c)
 {
-       methodinfo *m;
-       s4 i;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       int b;
-#endif
+       methodinfo    *m;
+       java_handle_t *cause;
+       classinfo     *class;
 
        /* maybe the class is not already linked */
 
-       if (!c->linked)
+       if (!(c->state & CLASS_LINKED))
                if (!link_class(c))
                        return false;
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_class_inits++;
 #endif
 
-       /* initialize super class */
-
-       if (c->super.cls) {
-               if (!c->super.cls->initialized) {
-                       if (initverbose) {
-                               char logtext[MAXLOGTEXT];
-                               strcpy(logtext, "Initialize super class ");
-                               utf_strcat_classname(logtext, c->super.cls->name);
-                               strcat(logtext, " from ");
-                               utf_strcat_classname(logtext, c->name);
-                               log_text(logtext);
-                       }
-#ifdef JWDEBUG
-                       printf("preparing to call initialize_class for super  %s\n",c->super.cls->name->text);
-#endif
-                       if (!initialize_class(c->super.cls))
-                               return false;
-               }
-       }
-
-       /* initialize interface classes */
+       /* Initialize super class. */
 
-       for (i = 0; i < c->interfacescount; i++) {
-               if (!c->interfaces[i].cls->initialized) {
-#ifdef JWDEBUG
-                       printf("preparing to call initialize_class for interface  %s\n",c->interfaces[i].cls->name->text);
+       if (c->super != NULL) {
+               if (!(c->super->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+                       if (initverbose)
+                               log_message_class_message_class("Initialize super class ",
+                                                                                               c->super,
+                                                                                               " from ",
+                                                                                               c);
 #endif
-                       if (initverbose) {
-                               char logtext[MAXLOGTEXT];
-                               strcpy(logtext, "Initialize interface class ");
-                               utf_strcat_classname(logtext, c->interfaces[i].cls->name);
-                               strcat(logtext, " from ");
-                               utf_strcat_classname(logtext, c->name);
-                               log_text(logtext);
-                       }
-                       
-                       if (!initialize_class(c->interfaces[i].cls))
+
+                       if (!initialize_class(c->super))
                                return false;
                }
        }
 
+       /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
+
        m = class_findmethod(c, utf_clinit, utf_void__void);
 
-       if (!m) {
-               if (initverbose) {
-                       char logtext[MAXLOGTEXT];
-                       strcpy(logtext, "Class ");
-                       utf_strcat_classname(logtext, c->name);
-                       strcat(logtext, " has no static class initializer");
-                       log_text(logtext);
-               }
+       if (m == NULL) {
+#if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Class has no static class initializer: ", c);
+#endif
 
                return true;
        }
 
        /* Sun's and IBM's JVM don't care about the static flag */
 /*     if (!(m->flags & ACC_STATIC)) { */
-/*             panic("Class initializer is not static!"); */
+/*             log_text("Class initializer is not static!"); */
 
+#if !defined(NDEBUG)
        if (initverbose)
                log_message_class("Starting static class initializer for class: ", c);
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       b = blockInts;
-       blockInts = 0;
 #endif
 
        /* now call the initializer */
 
-       asm_calljavafunction(m, NULL, NULL, NULL, NULL);
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       assert(blockInts == 0);
-       blockInts = b;
-#endif
+       (void) vm_call_method(m, NULL);
 
        /* we have an exception or error */
 
-       if (*exceptionptr) {
-               /* class is NOT initialized */
+       cause = exceptions_get_exception();
+
+       if (cause != NULL) {
+               /* class is NOT initialized and is marked with error */
 
-               c->initialized = false;
+               c->state |= CLASS_ERROR;
 
-               /* is this an exception, than wrap it */
+               /* Load java/lang/Exception for the instanceof check. */
 
-               if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
-                       java_objectheader *xptr;
-                       java_objectheader *cause;
+               class = load_class_bootstrap(utf_java_lang_Exception);
 
-                       /* get the cause */
+               if (class == NULL)
+                       return false;
 
-                       cause = *exceptionptr;
+               /* Is this an exception?  Yes, than wrap it. */
 
+               if (builtin_instanceof(cause, class)) {
                        /* clear exception, because we are calling jit code again */
 
-                       *exceptionptr = NULL;
+                       exceptions_clear_exception();
 
                        /* wrap the exception */
 
-                       xptr =
-                               new_exception_throwable(string_java_lang_ExceptionInInitializerError,
-                                                                               (java_lang_Throwable *) cause);
-
-                       /* XXX should we exit here? */
-
-                       if (*exceptionptr)
-                               throw_exception();
-
-                       /* set new exception */
-
-                       *exceptionptr = xptr;
+                       exceptions_throw_exceptionininitializererror(cause);
                }
 
                return false;
        }
 
+#if !defined(NDEBUG)
        if (initverbose)
                log_message_class("Finished static class initializer for class: ", c);
+#endif
 
        return true;
 }