/* 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 2500 2005-05-23 08:18:46Z twisti $
+#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
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;
}
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 */
+ /* Initialize super class. */
- if (c->super.cls) {
- if (!c->super.cls->initialized) {
+ 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.cls,
+ c->super,
" from ",
c);
-
-#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 */
- 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);
-#endif
- if (initverbose)
- log_message_class_message_class("Initialize interface class ",
- c->interfaces[i].cls,
- " from ",
- c);
-
- 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 (m == NULL) {
+#if !defined(NDEBUG)
if (initverbose)
log_message_class("Class has no static class initializer: ", c);
+#endif
return true;
}
/* if (!(m->flags & ACC_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;
}