PatchSet 6421 
Date: 2005/04/25 16:01:42
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
itable2dtable fix.

        * kaffe/kaffevm/classMethod.c
        (buildInterfaceDispatchTable): Put a strong reference on itable2dtable
        to prevent it being freed before the class is actually destroyed.

        * kaffe/kaffevm/gcFuncs.c
        (destroyClass): Remove strong reference on itable2dtable.

Members: 
        ChangeLog:1.3949->1.3950 
        kaffe/kaffevm/classMethod.c:INITIAL->1.140 
        kaffe/kaffevm/gcFuncs.c:1.70->1.71 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3949 kaffe/ChangeLog:1.3950
--- kaffe/ChangeLog:1.3949      Sun Apr 24 15:10:43 2005
+++ kaffe/ChangeLog     Mon Apr 25 16:01:42 2005
@@ -1,3 +1,12 @@
+2005-04-25  Guilhem Lavaux  <[EMAIL PROTECTED]>
+
+       * kaffe/kaffevm/classMethod.c
+       (buildInterfaceDispatchTable): Put a strong reference on itable2dtable
+       to prevent it being freed before the class is actually destroyed.
+
+       * kaffe/kaffevm/gcFuncs.c
+       (destroyClass): Remove strong reference on itable2dtable.
+
 2005-04-24  Eric Anholt <[EMAIL PROTECTED]>
 
        * kaffe/kaffevm/exception.c,
===================================================================
Checking out kaffe/kaffe/kaffevm/classMethod.c
RCS:  /home/cvs/kaffe/kaffe/kaffe/kaffevm/classMethod.c,v
VERS: 1.140
***************
--- /dev/null   Sun Aug  4 19:57:58 2002
+++ kaffe/kaffe/kaffevm/classMethod.c   Mon Apr 25 16:05:52 2005
@@ -0,0 +1,2907 @@
+/*
+ * classMethod.c
+ * Dictionary of classes, methods and fields.
+ *
+ * Copyright (c) 1996, 1997, 2004
+ *     Transvirtual Technologies, Inc.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#include "config.h"
+#include "debug.h"
+#include "config-std.h"
+#include "config-mem.h"
+#include "config-hacks.h"
+#include "defs.h"
+#include "gtypes.h"
+#include "slots.h"
+#include "access.h"
+#include "object.h"
+#include "errors.h"
+#include "code.h"
+#include "file.h"
+#include "readClass.h"
+#include "baseClasses.h"
+#include "stringSupport.h"
+#include "stackTrace.h"
+#include "thread.h"
+#include "jthread.h"
+#include "itypes.h"
+#include "bytecode.h"
+#include "exception.h"
+#include "classMethod.h"
+#include "md.h"
+#include "external.h"
+#include "lookup.h"
+#include "support.h"
+#include "stats.h"
+#include "gc.h"
+#include "locks.h"
+#include "md.h"
+#include "jni.h"
+#include "soft.h"
+#include "methodCache.h"
+#include "gcj/gcj.h"
+#include "xprofiler.h"
+#include "debugFile.h"
+#include "jvmpi_kaffe.h"
+#include "kaffe/jmalloc.h"
+#include "methodcalls.h"
+
+#if 0
+#define        METHOD_TRUE_NCODE(METH)                 
(METH)->c.ncode.ncode_start
+#define        METHOD_PRE_COMPILED(METH)               ((int16)(METH)->localsz 
< 0)
+#define        SET_METHOD_PRE_COMPILED(METH, VAL)      ((METH)->localsz = 
-(VAL))
+#endif
+
+
+/* interfaces supported by arrays */
+static Hjava_lang_Class* arr_interfaces[2];
+
+extern bool verify2(Hjava_lang_Class*, errorInfo*);
+extern bool verify3(Hjava_lang_Class*, errorInfo*);
+
+static int internalSetupClass(Hjava_lang_Class*, Utf8Const*, int, int, int, 
Hjava_lang_ClassLoader*, errorInfo *einfo);
+
+static bool buildDispatchTable(Hjava_lang_Class*, errorInfo *info);
+static bool buildInterfaceDispatchTable(Hjava_lang_Class*, errorInfo *);
+static bool checkForAbstractMethods(Hjava_lang_Class* class, errorInfo *einfo);
+static bool prepareInterface(Hjava_lang_Class*, errorInfo*);
+static bool computeInterfaceImplementationIndex(Hjava_lang_Class*, errorInfo*);
+static bool allocStaticFields(Hjava_lang_Class*, errorInfo *einfo);
+static bool resolveObjectFields(Hjava_lang_Class*, errorInfo *einfo);
+static bool resolveStaticFields(Hjava_lang_Class*, errorInfo *einfo);
+static bool resolveConstants(Hjava_lang_Class*, errorInfo *einfo);
+static bool resolveInterfaces(Hjava_lang_Class *class, errorInfo *einfo);
+
+
+
+#if !defined(ALIGNMENT_OF_SIZE)
+#define        ALIGNMENT_OF_SIZE(S)    (S)
+#endif
+
+/* set a class's alloc_type field */
+static void
+determineAllocType(Hjava_lang_Class *class)
+{
+  if (StringClass != 0 && StringClass == class)
+    class->alloc_type = KGC_ALLOC_JAVASTRING;
+  else
+    if (ClassLoaderClass != 0 && instanceof(ClassLoaderClass, class))
+      class->alloc_type = KGC_ALLOC_JAVALOADER;
+    else
+      class->alloc_type = KGC_ALLOC_FINALIZEOBJECT;
+}
+
+/*
+ * Process all the stage of a classes initialisation.  We can provide
+ * a state to aim for (so we don't have to do this all at once).  This
+ * is called by various parts of the machine in order to load, link
+ * and initialise the class.  Putting it all together here makes it a damn
+ * sight easier to understand what's happening.
+ *
+ * Returns true if processing was successful, false otherwise.
+ */
+bool
+processClass(Hjava_lang_Class* class, int tostate, errorInfo *einfo)
+{
+       Method* meth;
+       classEntry *ce;
+       Hjava_lang_Class* nclass;
+       bool success = true;    /* optimistic */
+#if !(defined(NDEBUG) || !defined(KAFFE_VMDEBUG))
+       int i;
+       static int depth;
+#endif /* !(defined(NDEBUG) || !defined(KAFFE_VMDEBUG)) */
+       static Method *object_fin;
+
+       /* If this class is initialised to the required point, quit now */
+       if (class->state >= tostate) {
+               return (true);
+       }
+
+#define        SET_CLASS_STATE(S)      class->state = (S)
+#define        DO_CLASS_STATE(S)       if ((S) > class->state && (S) <= 
tostate)
+
+       /* For the moment we only allow one thread to initialise any classes
+        * at once.  This is because we've got circular class dependencies
+        * we've got to work out.
+        */
+
+       /*
+        * Get the entry for this class, we'll need to update its state along
+        * the way.
+        */
+       ce = lookupClassEntryInternal(class->name, class->loader);
+
+       lockClass(class);
+
+DBG(RESERROR,
+       /* show calls to processClass when debugging resolution errors */
+       depth++;
+       for (i = 0; i < depth; dprintf("  "), i++);
+       dprintf("%p entering process class %s %d->%d\n",
+               KTHREAD(current)(), class->name->data,
+               class->state, tostate);
+    );
+
+retry:
+       /* If the initialization of that class failed once before, don't
+        * bother and report that no definition for this class exists.
+        * We must do that after the retry label so that threads waiting
+        * on other threads performing a particular initialization step
+        * can learn that things went wrong.
+        */
+       if (class->state == CSTATE_FAILED) {
+               postExceptionMessage(einfo,
+                                    JAVA_LANG(NoClassDefFoundError),
+                                    "%s",
+                                    class->name->data);
+               einfo->type |= KERR_NO_CLASS_FOUND; /* for the verifier */
+               success = false;
+               goto done;
+       }
+
+       DO_CLASS_STATE(CSTATE_LOADED_SUPER) {
+
+               setClassMappingState(ce, NMS_LOADING);
+               
+               class->processingThread = THREAD_NATIVE();
+               
+               /* Load and link the super class */
+               if( class->superclass )
+               {
+                       /*
+                        * propagate failures in super class loading and
+                        * processing.  Since getClass might involve an
+                        * upcall to a classloader, we must release the
+                        * classLock here.
+                        */
+                       unlockClass(class);
+                       
+#if defined(HAVE_GCJ_SUPPORT)
+                       if( CLASS_GCJ(class) )
+                       {
+                               class->superclass
+                                       = gcjGetClass((void*)class->superclass,
+                                                     einfo);
+                       }
+                       else
+#endif
+                       {
+                               class->superclass =
+                                       
getClass((constIndex)(uintp)class->superclass,
+                                                class,
+                                                einfo);
+                       }
+                       
+                       lockClass(class);
+                       if( class->superclass == 0 )
+                       {
+                               success = false;
+                               goto done;
+                       }
+                       KGC_addWeakRef(main_collector, class->superclass, 
&(class->superclass));
+                       if( !(class->accflags & ACC_INTERFACE) &&
+                           (class->superclass->accflags & ACC_INTERFACE)) {
+                               postExceptionMessage(
+                                       einfo,
+                                       JAVA_LANG(
+                                               IncompatibleClassChangeError),
+                                       "Super class, %s, is an interface.",
+                                       class->superclass->name->data);
+                               success = false;
+                               goto done;
+                       }
+                       /* that's pretty much obsolete. */
+                       assert(class->superclass->state >= CSTATE_DOING_LINK);
+                       classMappingLoaded(ce, class);
+                       /* Copy initial field size and gc layout.
+                        * Later, as this class's fields are resolved, they
+                        * are added to the superclass's layout.
+                        */
+                       CLASS_FSIZE(class) = CLASS_FSIZE(class->superclass);
+                       class->gc_layout = class->superclass->gc_layout;
+               }
+               if( class->superclass )
+               {
+                       assert(class->superclass->state >= CSTATE_DOING_LINK);
+               }
+               
+       }
+       
+       DO_CLASS_STATE(CSTATE_VERIFIED) {
+               /*
+                * Second stage verification - check the class format is okay
+                */
+               success =  verify2(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               SET_CLASS_STATE(CSTATE_VERIFIED);
+       }
+       
+       DO_CLASS_STATE(CSTATE_PREPARED) {
+
+               if( (class->loader == 0) && !gc_add_ref(class) )
+               {
+                       postOutOfMemory(einfo);
+                       success = false;
+                       goto done;
+               }
+
+               /* Allocate any static space required by class and initialise
+                * the space with any constant values.  This isn't necessary
+                * for pre-loaded classes.
+                */
+               if (class->state != CSTATE_PRELOADED
+                   && !allocStaticFields(class, einfo)) {
+                       success = false;
+                       goto done;
+               }
+
+               SET_CLASS_STATE(CSTATE_DOING_PREPARE);
+               class->processingThread = THREAD_NATIVE();
+
+#if defined(HAVE_GCJ_SUPPORT)
+               if (CLASS_GCJ(class)) {
+                       success = gcjProcessClass(class, class->gcjPeer, einfo);
+                       if (success == false) {
+                               goto done;
+                       }
+               }
+#else
+/* #warning No GCJ Support */
+#endif
+               success = resolveObjectFields(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               success = resolveStaticFields(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               success = resolveInterfaces(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               /* Build dispatch table.  We must handle interfaces a little
+                * differently since they only have a <clinit> method.
+                */
+               if (!CLASS_IS_INTERFACE(class)) {
+
+                       success = buildDispatchTable(class, einfo);
+                       if (success == false) {
+                               goto done;
+                       }
+
+                       success = buildInterfaceDispatchTable(class, einfo);
+                       if (success == false) {
+                               goto done;
+                       }
+
+                       success = checkForAbstractMethods(class, einfo);
+                       if (success == false) {
+                               goto done;
+                       }
+
+                       success = computeInterfaceImplementationIndex(class,
+                                                                     einfo);
+               } else {
+                       success = prepareInterface(class, einfo);
+               }
+
+               if (success == false) {
+                       goto done;
+               }
+
+               SET_CLASS_STATE(CSTATE_PREPARED);
+               
+               setClassMappingState(ce, NMS_DONE);
+               
+#if defined(ENABLE_JVMPI)
+               if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_CLASS_LOAD) )
+               {
+                       JVMPI_Method *jvmpi_methods;
+                       JVMPI_Field *jvmpi_fields;
+                       JVMPI_Event ev;
+                       
+                       jvmpi_methods = alloca(sizeof(JVMPI_Method) *
+                                              CLASS_NMETHODS(class));
+                       jvmpi_fields = alloca(sizeof(JVMPI_Field) *
+                                             (class->nsfields +
+                                              CLASS_NFIELDS(class)));
+                       ev.u.class_load.methods = jvmpi_methods;
+                       ev.u.class_load.statics = &jvmpi_fields[0];
+                       ev.u.class_load.instances =
+                               &jvmpi_fields[class->nsfields];
+                       jvmpiFillClassLoad(&ev, class);
+                       jvmpiPostEvent(&ev);
+               }
+#endif
+       }
+
+       assert((class == ObjectClass) || (class->superclass != NULL));
+
+       DO_CLASS_STATE(CSTATE_LINKED) {
+               
+               if (class->state == CSTATE_DOING_LINK) {
+                       if (THREAD_NATIVE() == class->processingThread) {
+                               goto done;
+                       } else {
+                               while (class->state == CSTATE_DOING_LINK) {
+                                       waitOnClass(class);
+                                       goto retry;
+                               }
+                       }
+               }
+               
+               SET_CLASS_STATE(CSTATE_DOING_LINK);
+               
+               /* Third stage verification - check the bytecode is okay */
+               success = verify3(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               SET_CLASS_STATE(CSTATE_LINKED);
+       }
+
+       /* NB: the reason that CONSTINIT is a separate state is that
+        * CONSTINIT depends on StringClass, which isn't available during
+        * initialization when we bring the base classes to the LINKED state.
+        */
+       DO_CLASS_STATE(CSTATE_CONSTINIT) {
+#if defined(HAVE_GCJ_SUPPORT)
+               int i;
+                Field *fld;
+
+               if (CLASS_GCJ(class)) {
+                       success = gcjProcessClassConstants(class,
+                                                          class->gcjPeer,
+                                                          einfo);
+                       if (success == false) {
+                               goto done;
+                       }
+               }
+
+               /* We must resolve field types eagerly so that class gc
+                * will mark static fields of gcj classes.  That walking
+                * depends on whether the UNRESOLVED_FLAG is clear.
+                */
+               fld = CLASS_FIELDS(class);
+               for (i = 0; i < CLASS_NFIELDS(class); fld++, i++) {
+                       if (resolveFieldType(fld, class, einfo) == 0) {
+                               success = false;
+                               goto done;
+                       }
+               }
+
+#endif /* defined(HAVE_GCJ_SUPPORT) */
+
+               /* Initialise the constants */
+               success = resolveConstants(class, einfo);
+               if (success == false) {
+                       goto done;
+               }
+
+               /* And note that it's done */
+               SET_CLASS_STATE(CSTATE_CONSTINIT);
+       }
+
+       DO_CLASS_STATE(CSTATE_USABLE) {
+
+               /* If somebody's already processing the super class,
+                * check whether it's us.  If so, return.
+                * Else, wait for the other thread to complete and
+                * start over to reevaluate the situation.
+                */
+               if (class->state == CSTATE_DOING_SUPER) {
+                       if (THREAD_NATIVE() == class->processingThread) {
+                               goto done;
+                       } else {
+                               while (class->state == CSTATE_DOING_SUPER) {
+                                       waitOnClass(class);
+                                       goto retry;
+                               }
+                       }
+               }
+
+               SET_CLASS_STATE(CSTATE_DOING_SUPER);
+
+               /* Now determine the method used to finalize this object.
+                * If the finalizer is empty, we set class->finalizer to null.
+                * Find finalizer first without calling findMethod.
+                */
+               meth = NULL;
+               for (nclass = class; nclass != 0; nclass = nclass->superclass) {
+                       meth = findMethodLocal(nclass, final_name, 
void_signature);
+                       if (meth != NULL) {
+                               break;
+                       }
+               }
+
+               /* every class must have one since java.lang.Object has one */
+               if (meth == NULL) {
+                       postException(einfo, JAVA_LANG(InternalError));
+                       success = false;
+                       goto done;
+               }
+
+               /* is it empty?  This test should work even if an
+                * object has been finalized before this class is
+                * loaded. If Object.finalize() is empty, save a pointer
+                * to the method itself, and check meth against it in
+                * the future.
+                */
+               if ((meth->c.bcode.codelen == 1
+                    && meth->c.bcode.code[0] == RETURN)) {
+                       if (!object_fin && meth->class == ObjectClass) {
+                               object_fin = meth;
+                       }
+                       class->finalizer = NULL;
+               } else if (meth == object_fin) {
+                       class->finalizer = NULL;
+               } else {
+                       class->finalizer = meth;
+               }
+
+               determineAllocType(class);
+
+               if (class->superclass != NULL) {
+                       class->processingThread = THREAD_NATIVE();
+
+                       /* We must not hold the class lock here because we
+                        * might call out into the superclass's initializer
+                        * here!
+                        */
+                       unlockClass(class);
+                       success = processClass(class->superclass,
+                                              CSTATE_COMPLETE,
+                                              einfo);
+                       lockClass(class);
+                       if (success == false) {
+                               if (class->superclass->state == CSTATE_FAILED)
+                                       SET_CLASS_STATE(CSTATE_FAILED);
+                               goto done;
+                       }
+               }
+
+#if defined(KAFFE_XDEBUGGING)
+               if( machine_debug_file )
+               {
+                       addDebugInfo(machine_debug_file,
+                                    DIA_Class, class,
+                                    DIA_DONE);
+               }
+#endif
+               
+               SET_CLASS_STATE(CSTATE_USABLE);
+       }
+
+       DO_CLASS_STATE(CSTATE_COMPLETE) {
+               jthrowable exc = NULL;
+               jthrowable excpending;
+
+               /* If we need a successfully initialized class here, but its
+                * initializer failed, return false as well
+                */
+               if (class->state == CSTATE_FAILED) {
+                       postExceptionMessage(einfo,
+                               JAVA_LANG(NoClassDefFoundError),
+                               "%s", class->name->data);
+                       success = false;
+                       goto done;
+               }
+
+DBG(STATICINIT, dprintf("Initialising %s static %d\n", class->name->data,
+                       CLASS_FSIZE(class));    );
+               meth = findMethodLocal(class, init_name, void_signature);
+               if (meth == NULL) {
+                       SET_CLASS_STATE(CSTATE_COMPLETE);
+                       goto done;
+               }
+
+               if (class->state == CSTATE_DOING_INIT) {
+                       if (THREAD_NATIVE() == class->processingThread) {
+                               goto done;
+                       } else {
+                               while (class->state == CSTATE_DOING_INIT) {
+                                       waitOnClass(class);
+                                       goto retry;
+                               }
+                       }
+               }
+
+               SET_CLASS_STATE(CSTATE_DOING_INIT);
+               class->processingThread = THREAD_NATIVE();
+
+               /* give classLock up for the duration of this call */
+               unlockClass(class);
+
+               /* We use here an exception safe call method to be able
+                * to catch possible exceptions which may occur.
+                */
+               excpending = THREAD_DATA()->exceptObj;
+               THREAD_DATA()->exceptObj = NULL;
+
+               KaffeVM_safeCallMethodA(meth, METHOD_NATIVECODE(meth), NULL, 
NULL, NULL, 0);
+               exc = THREAD_DATA()->exceptObj;
+               THREAD_DATA()->exceptObj = excpending;
+
+               lockClass(class);
+
+               class->processingThread = NULL;
+               
+               if (exc != 0) {
+                       if( soft_instanceof(javaLangException, exc) )
+                       {
+                               /* this is special-cased in throwError */
+                               einfo->type = (KERR_INITIALIZER_ERROR |
+                                              KERR_NO_CLASS_FOUND);
+                               einfo->throwable = exc;
+                       }
+                       else
+                       {
+                               /* Should be an error... */
+                               einfo->type = (KERR_RETHROW |
+                                              KERR_NO_CLASS_FOUND);
+                               einfo->throwable = exc;
+                       }
+                       
+                       /*
+                        * we return false here because COMPLETE fails
+                        */
+                       success = false;
+                       SET_CLASS_STATE(CSTATE_FAILED);
+               } else {
+                       SET_CLASS_STATE(CSTATE_COMPLETE);
+               }
+
+               /* Since we'll never run this again we might as well
+                * lose it now. However, if there was an exception, keep
+                * it so the stack trace doesn't lose the <clinit> frame.
+                */
+#if defined(TRANSLATOR) && (defined (MD_UNREGISTER_JIT_EXCEPTION_INFO) || 
defined (JIT3))
+#if defined(MD_UNREGISTER_JIT_EXCEPTION_INFO)
+               if (exc == 0) {
+                       MD_UNREGISTER_JIT_EXCEPTION_INFO 
(meth->c.ncode.ncode_start,
+                                                         
METHOD_NATIVECODE(meth),
+                                                         
meth->c.ncode.ncode_end);
+               }
+#endif
+#endif
+               if (
+#if defined(JIT3)
+                   (exc == 0) &&
+#endif
+#if defined(KAFFE_XPROFILER)
+                   !xProfFlag &&
+#endif
+                   1) {
+                       _SET_METHOD_NATIVECODE(meth, NULL);
+                       meth->c.ncode.ncode_start = NULL;
+                       meth->c.ncode.ncode_end = NULL;
+               }
+       }
+
+done:
+       /* If anything ever goes wrong with this class, we declare it dead
+        * and will respond with NoClassDefFoundErrors to any future attempts
+        * to access that class.
+        * NB: this does not include when a static initializer failed.
+        */
+       if (success == false && class->state != CSTATE_FAILED) {
+               SET_CLASS_STATE(CSTATE_FAILED);
+
+               if( ce->state != NMS_DONE )
+               {
+                       setClassMappingState(ce, NMS_EMPTY);
+               }
+       }
+
+       /* wake up any waiting threads */
+       broadcastOnClass(class);
+       unlockClass(class);
+
+DBG(RESERROR,
+       for (i = 0; i < depth; dprintf("  "), i++);
+       depth--;
+       dprintf("%p leaving process class %s -> %s\n",
+               KTHREAD(current)(), class->name->data,
+               success ? "success" : "failure");
+    );
+       return (success);
+}
+
+static int
+expandMethods(Hjava_lang_Class *cl, Method *imeth, errorInfo *einfo)
+{
+       Method *new_methods = NULL;
+       int retval = 0;
+       
+       /*
+       if( !CLASS_IS_ABSTRACT(cl) )
+       {
+               postExceptionMessage(einfo,
+                                    JAVA_LANG(ClassFormatError),
+                                    "(class: %s, method: %s signature: %s) "
+                                    "Abstract method in non-abstract class",
+                                    cl->name->data,
+                                    imeth->name->data,
+                                    imeth->parsed_sig->signature->data);
+       }
+       else
+       */
+       if( (new_methods = gc_realloc(CLASS_METHODS(cl),
+                                     sizeof(Method) *
+                                     (CLASS_NMETHODS(cl) + 1), 
KGC_ALLOC_METHOD)) )
+       {
+               int i;
+               
+               i = CLASS_NMETHODS(cl);
+               CLASS_NMETHODS(cl) = i + 1;
+               CLASS_METHODS(cl) = new_methods;
+               utf8ConstAddRef(imeth->name);
+               utf8ConstAddRef(imeth->parsed_sig->signature);
+               new_methods[i] = *imeth;
+               new_methods[i].ndeclared_exceptions = -1;
+               new_methods[i].declared_exceptions_u.remote_exceptions =
+                       imeth;
+               new_methods[i].class = cl;
+               retval = 1;
+       }
+       else
+       {
+               gc_free(new_methods);
+               postOutOfMemory(einfo);
+       }
+       return( retval );
+}
+
+static int
+expandInterfaces(Hjava_lang_Class *root_class,
+                Hjava_lang_Class *class,
+                errorInfo *einfo)
+{
+       int i, j, k, success = 1;
+       
+       /*
+        * Check to make sure all the interface methods are implemented,
+        * otherwise, we'll need to add a slot.
+        */
+       for( i = 0; (i < class->interface_len) && success; i++ )
+       {
+               Hjava_lang_Class *iface;
+               
+               iface = class->interfaces[i];
+               if( !expandInterfaces(root_class, iface, einfo) )
+               {
+                       success = 0;
+                       break;
+               }
+               for( j = 0; (j < CLASS_NMETHODS(iface)) && success; j++ )
+               {
+                       Hjava_lang_Class *cl;
+                       int foundit = 0;
+                       Method *imeth;
+                       
+                       imeth = &CLASS_METHODS(iface)[j];
+                       /* Igore statics */
+                       if( imeth->accflags & ACC_STATIC )
+                               continue;
+                       /* Search for the corresponding slot. */
+                       for( cl = root_class;
+                            cl && !foundit;
+                            cl = cl->superclass )
+                       {
+                               for( k = 0; k < CLASS_NMETHODS(cl); k++ )
+                               {
+                                       Method *cmeth;
+                                       
+                                       cmeth = &CLASS_METHODS(cl)[k];
+                                       if( (cmeth->name == imeth->name) &&
+                                           (cmeth->parsed_sig->signature ==
+                                            imeth->parsed_sig->signature) )
+                                       {
+                                               foundit = 1;
+                                               break;
+                                       }
+                               }
+                       }
+                       if( !foundit )
+                       {
+                               /* No impl, add a slot */
+                               success = expandMethods(root_class,
+                                                       imeth,
+                                                       einfo);
+                       }
+               }
+       }
+       return( success );
+}
+
+static bool
+resolveInterfaces(Hjava_lang_Class *class, errorInfo *einfo)
+{
+       int i, j, k;
+       int totalilen;
+       Hjava_lang_Class** newifaces;
+       Hjava_lang_Class* nclass;
+       bool success = true;    /* optimistic */
+
+       /* Load all the implemented interfaces. */
+       j = class->interface_len;
+       nclass = class->superclass;
+       if (nclass != 0 && nclass != ObjectClass) {
+               /* If class is an interface, its superclass must
+                * be java.lang.Object or the class file is broken.
+                */
+               if (CLASS_IS_INTERFACE(class)) {
+                       postException(einfo, JAVA_LANG(VerifyError));
+                       success = false;
+                       goto done;
+               }
+               j += class->superclass->total_interface_len;
+       }
+       for (i = 0; i < class->interface_len; i++) {
+               uintp iface = (uintp)class->interfaces[i];
+               unlockClass(class);
+
+#if defined(HAVE_GCJ_SUPPORT)
+               if (CLASS_GCJ(class)) {
+                       nclass = gcjGetClass((void*)iface, einfo);
+               } else {
+                       nclass = getClass(iface, class, einfo);
+               }
+#else
+               nclass = getClass(iface, class, einfo);
+#endif /* HAVE_GCJ_SUPPORT */
+
+               class->interfaces[i] = nclass;
+
+               lockClass(class);
+               if (class->interfaces[i] == 0) {
+                       success = false;
+                       goto done;
+               }
+               if (!(class->interfaces[i]->accflags & ACC_INTERFACE)) {
+                       postExceptionMessage(
+                               einfo,
+                               JAVA_LANG(IncompatibleClassChangeError),
+                               "Class, %s, used as interface by %s",
+                               class->interfaces[i]->name->data,
+                               class->name->data);
+                       success = false;
+                       goto done;
+               }
+               if (instanceof(class, class->interfaces[i])) {
+                       postExceptionMessage(
+                               einfo,
+                               JAVA_LANG(ClassCircularityError),
+                               "%s",
+                               class->name->data);
+                       success = false;
+                       goto done;
+               }
+               j += class->interfaces[i]->total_interface_len;
+       }
+       totalilen = j;
+
+       /* We build a list of *all* interfaces this class can use */
+       if (class->interface_len != j) {
+               newifaces = 
(Hjava_lang_Class**)gc_malloc(sizeof(Hjava_lang_Class**) * j, 
KGC_ALLOC_INTERFACE);
+               if (newifaces == 0) {
+                       postOutOfMemory(einfo);
+                       success = false;
+                       goto done;
+               }
+               for (i = 0; i < class->interface_len; i++) {
+                       newifaces[i] = class->interfaces[i];
+               }
+               nclass = class->superclass;
+               if (nclass != 0 && nclass != ObjectClass) {
+                       for (j = 0; j < nclass->total_interface_len; j++, i++) {
+                               newifaces[i] = nclass->interfaces[j];
+                       }
+               }
+               for (k = 0; k < class->interface_len; k++) {
+                       nclass = class->interfaces[k];
+                       for (j = 0; j < nclass->total_interface_len; j++, i++) {
+                               newifaces[i] = nclass->interfaces[j];
+                       }
+               }
+               class->interfaces = newifaces;
+       }
+
+       /* don't set total_interface_len before interfaces to avoid
+        * having walkClass attempting to walk interfaces
+        */
+       class->total_interface_len = totalilen;
+       
+       if( !CLASS_IS_INTERFACE(class) )
+       {
+               success = expandInterfaces(class, class, einfo);
+       }
+
+done:
+       return (success);
+}
+
+/**
+ * Check if a class name is in a set of packages.
+ *
+ * XXX Move somewhere else...
+ *
+ * @param plist The null terminated list of packages to check against.
+ * @param name The class name to check.
+ * @return True if the class name is in one of the packages, false otherwise.
+ */
+static int
+inPackageSet(const char **plist, Utf8Const *name)
+{
+       unsigned int name_len, lpc, retval = 0;
+       
+       name_len = strlen(name->data);
+       for( lpc = 0; plist[lpc] && !retval; lpc++ )
+       {
+               unsigned int len;
+
+               len = strlen(plist[lpc]);
+               if( (name_len > len) &&
+                   strncmp(name->data, plist[lpc], len) == 0 )
+               {
+                       retval = 1;
+               }
+       }
+       return( retval );
+}
+
+/**
+ * The set of restricted packages that a user defined class loader can't add
+ * classes to.
+ */
+static const char *restrictedPackages[] = {
+       "java/",
+       "kaffe/",
+       NULL
+};
+
+static int
+internalSetupClass(Hjava_lang_Class* cl, Utf8Const* name, int flags,
+                  int this_index, int su, Hjava_lang_ClassLoader* loader,
+                  struct _errorInfo *einfo)
+{
+       if( (loader != NULL) &&
+           inPackageSet(restrictedPackages, name) ) {
+               /*
+                * Can't allow users to add classes to the bootstrap
+                * packages.
+                */
+               postExceptionMessage(einfo,
+                                    JAVA_LANG(SecurityException),
+                                    "Prohibited package: %s",
+                                    name->data);
+               return 0;
+       }
+       if( cl->name == NULL ) {
+               utf8ConstAssign(cl->name, name);
+       }
+       else if( !utf8ConstEqual(cl->name, name) ) {
+               postExceptionMessage(einfo,
+                                    JAVA_LANG(ClassFormatError),
+                                    "%s (wrong name: %s)",
+                                    name->data,
+                                    cl->name->data);
+               return 0;
+       }
+       cl->packageLength = findPackageLength(name->data);
+       CLASS_METHODS(cl) = NULL;
+       CLASS_NMETHODS(cl) = 0;
+       assert(cl->superclass == 0);
+       cl->superclass = (Hjava_lang_Class*)(uintp)su;
+       cl->msize = 0;
+       CLASS_FIELDS(cl) = NULL;
+       CLASS_FSIZE(cl) = 0;
+       cl->accflags = flags;
+       cl->vtable = NULL;
+        cl->interfaces = NULL;
+       cl->interface_len = 0;
+       assert(cl->state < CSTATE_LOADED);
+       cl->state = CSTATE_LOADED;
+       cl->loader = loader;
+       cl->this_index = this_index;
+       cl->inner_classes = NULL;
+       cl->nr_inner_classes = 0;
+       cl->this_inner_index = -1;
+       return 1;
+}
+
+Hjava_lang_Class*
+setupClass(Hjava_lang_Class* cl, constIndex c, constIndex s,
+          u2 flags, Hjava_lang_ClassLoader* loader,
+          errorInfo* einfo)
+{
+       constants* pool;
+
+       pool = CLASS_CONSTANTS(cl);
+
+       /* Find the name of the class */

*** Patch too long, truncated ***

_______________________________________________
kaffe mailing list
[email protected]
http://kaffe.org/cgi-bin/mailman/listinfo/kaffe

Reply via email to