* gen_inst: Use lastmcodeptr instead of last_compiled.
[cacao.git] / src / vm / loader.c
index acbf1ea60cd8c3e147a92e98f9867e158db5a33f..92d8c0fa395bda9fd3d6888de431d3c57d7e7038 100644 (file)
@@ -32,7 +32,7 @@
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 3082 2005-07-20 15:28:51Z twisti $
+   $Id: loader.c 3684 2005-11-16 13:28:33Z twisti $
 
 */
 
@@ -126,7 +126,7 @@ bool loader_init(u1 *stackbottom)
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        classpath_info *cpi;
 
-       /* Initialize the monitor pointer for zip/jar file locking.               */
+       /* Initialize the monitor pointer for zip/jar file locking. */
 
        for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
                if (cpi->type == CLASSPATH_ARCHIVE)
@@ -200,10 +200,18 @@ bool loader_init(u1 *stackbottom)
        if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
                return false;
 
+       if (!(class_java_lang_Thread =
+                 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
+               return false;
+
        if (!(class_java_lang_ThreadGroup =
                  load_class_bootstrap(utf_java_lang_ThreadGroup)))
                return false;
 
+       if (!(class_java_lang_VMThread =
+                 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
+               return false;
+
 
        /* some classes which may be used more often */
 
@@ -354,8 +362,7 @@ static float suck_float(classbuffer *cb)
 #endif
 
        if (sizeof(float) != 4) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible float-format");
+               *exceptionptr = new_internalerror("Incompatible float-format");
 
                /* XXX should we exit in such a case? */
                throw_exception_exit();
@@ -374,8 +381,21 @@ static double suck_double(classbuffer *cb)
        u1 buffer[8];
        u2 i;   
 
+#if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
+       /*
+        * On little endian ARM processors when using FPA, word order
+        * of doubles is still big endian. So take that into account
+        * here. When using VFP, word order of doubles follows byte
+        * order. (michi 2005/07/24)
+        */
+       for (i = 0; i < 4; i++)
+               buffer[3 - i] = suck_u1(cb);
+       for (i = 0; i < 4; i++)
+               buffer[7 - i] = suck_u1(cb);
+#else
        for (i = 0; i < 8; i++)
                buffer[7 - i] = suck_u1(cb);
+#endif /* defined(__ARM__) && ... */
 
        memcpy((u1*) (&d), buffer, 8);
 #else 
@@ -383,8 +403,7 @@ static double suck_double(classbuffer *cb)
 #endif
 
        if (sizeof(double) != 8) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible double-format");
+               *exceptionptr = new_internalerror("Incompatible double-format");
 
                /* XXX should we exit in such a case? */
                throw_exception_exit();
@@ -476,6 +495,11 @@ void suck_init(char *classpath)
                                        cpi->next = NULL;
                                        cpi->path = filename;
                                        cpi->pathlen = filenamelen;
+
+                                       /* SUN compatible -verbose:class output */
+
+                                       if (opt_verboseclass)
+                                               printf("[Opened %s]\n", filename);
                                }
 
 #else
@@ -543,10 +567,11 @@ void loader_load_all_classes(void)
                        ce = s->cacao_dir_list;
                                
                        while (ce) {
-                               /* skip all entries in META-INF and .properties files */
+                               /* skip all entries in META-INF and .properties, .png files */
 
                                if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
-                                       !strstr(ce->name->text, ".properties"))
+                                       !strstr(ce->name->text, ".properties") &&
+                                       !strstr(ce->name->text, ".png"))
                                        c = load_class_bootstrap(ce->name);
 
                                ce = ce->next;
@@ -613,9 +638,10 @@ classbuffer *suck_start(classinfo *c)
                                        if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
                                                cb = NEW(classbuffer);
                                                cb->class = c;
-                                               cb->size = file_info.uncompressed_size;
-                                               cb->data = MNEW(u1, cb->size);
-                                               cb->pos = cb->data - 1;
+                                               cb->size  = file_info.uncompressed_size;
+                                               cb->data  = MNEW(u1, cb->size);
+                                               cb->pos   = cb->data - 1;
+                                               cb->path  = cpi->path;
 
                                                len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
 
@@ -656,9 +682,10 @@ classbuffer *suck_start(classinfo *c)
                                if (!stat(path, &buffer)) {            /* read classfile data */
                                        cb = NEW(classbuffer);
                                        cb->class = c;
-                                       cb->size = buffer.st_size;
-                                       cb->data = MNEW(u1, cb->size);
-                                       cb->pos = cb->data - 1;
+                                       cb->size  = buffer.st_size;
+                                       cb->data  = MNEW(u1, cb->size);
+                                       cb->pos   = cb->data - 1;
+                                       cb->path  = cpi->path;
 
                                        /* read class data */
                                        len = fread(cb->data, 1, cb->size, classfile);
@@ -1085,11 +1112,11 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        if (opt_verify &&
                                !is_valid_utf((char *) (cb->pos + 1),
                                                          (char *) (cb->pos + 1 + length))) {
-                               dolog("Invalid UTF-8 string (constant pool index %d)",idx);
-                               assert(0);
+                               *exceptionptr = new_classformaterror(c,"Invalid UTF-8 string");
+                               return false;
                        }
                        /* insert utf-string into the utf-symboltable */
-                       cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
+                       cpinfos[idx] = utf_new((char *) (cb->pos + 1), length);
 
                        /* skip bytes of the string (buffer size check above) */
                        skip_nbytes(cb, length);
@@ -1110,6 +1137,8 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        while (forward_classes) {
                utf *name =
                        class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+               if (!name)
+                       return false;
 
                if (opt_verify && !is_valid_name_utf(name)) {
                        *exceptionptr = 
@@ -1145,6 +1174,8 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        while (forward_strings) {
                utf *text =
                        class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+               if (!text)
+                       return false;
 
                /* resolve utf-string */
                cptags[forward_strings->thisindex] = CONSTANT_String;
@@ -1166,10 +1197,14 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                cn->name = class_getconstant(c,
                                                                         forward_nameandtypes->name_index,
                                                                         CONSTANT_Utf8);
+               if (!cn->name)
+                       return false;
 
                cn->descriptor = class_getconstant(c,
                                                                                   forward_nameandtypes->sig_index,
                                                                                   CONSTANT_Utf8);
+               if (!cn->descriptor)
+                       return false;
 
                if (opt_verify) {
                        /* check name */
@@ -1185,8 +1220,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                        /* disallow referencing <clinit> among others */
                        if (cn->name->text[0] == '<' && cn->name != utf_init) {
                                *exceptionptr =
-                                       new_exception_utfmessage(string_java_lang_InternalError,
-                                                                                        cn->name);
+                                       new_classformaterror(c,"Illegal reference to special method");
                                return false;
                        }
                }
@@ -1211,6 +1245,8 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
                nat = class_getconstant(c,
                                                                forward_fieldmethints->nameandtype_index,
                                                                CONSTANT_NameAndType);
+               if (!nat)
+                       return false;
 
                /* add all descriptors in {Field,Method}ref to the descriptor_pool */
 
@@ -1275,6 +1311,13 @@ static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
        if (!descriptor_pool_add(descpool, u, NULL))
                return false;
 
+       /* descriptor_pool_add accepts method descriptors, so we have to check */
+       /* against them here before the call of desc_to_type below.            */
+       if (u->text[0] == '(') {
+               *exceptionptr = new_classformaterror(c,"Method descriptor used for field");
+               return false;
+       }
+
        if (opt_verify) {
                /* check name */
                if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
@@ -1484,14 +1527,14 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 
        if (opt_verify) {
                if (!is_valid_name_utf(m->name)) {
-                       log_text("Method with invalid name");
-                       assert(0);
+                       *exceptionptr = new_classformaterror(c,"Method with invalid name");
+                       return false;
                }
 
                if (m->name->text[0] == '<' &&
                        m->name != utf_init && m->name != utf_clinit) {
-                       log_text("Method with invalid special name");
-                       assert(0);
+                       *exceptionptr = new_classformaterror(c,"Method with invalid special name");
+                       return false;
                }
        }
        
@@ -1541,8 +1584,9 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
                        if (m->name == utf_init) {
                                if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
                                                                ACC_NATIVE | ACC_ABSTRACT)) {
-                                       log_text("Instance initialization method has invalid flags set");
-                                       assert(0);
+                                       *exceptionptr = new_classformaterror(c,
+                                                       "Instance initialization method has invalid flags set");
+                                       return false;
                                }
                        }
                }
@@ -1648,7 +1692,8 @@ static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpoo
 #if defined(STATISTICS)
                        if (opt_stat) {
                                count_vmcode_len += m->jcodelength + 18;
-                               count_extable_len += 8 * m->exceptiontablelength;
+                               count_extable_len +=
+                                       m->exceptiontablelength * sizeof(exceptiontable);
                        }
 #endif
 
@@ -1953,41 +1998,47 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 
        if (cl) {
                methodinfo *lc;
+               char       *text;
+               s4          namelen;
+
+               text = name->text;
+               namelen = name->blength;
 
                /* handle array classes */
-               if (name->text[0] == '[') {
-                       char      *utf_ptr;
-                       s4         len;
+               if (text[0] == '[') {
                        classinfo *comp;
                        utf       *u;
 
-                       utf_ptr = name->text + 1;
-                       len = name->blength - 1;
-
-                       switch (*utf_ptr) {
+                       switch (text[1]) {
                        case 'L':
-                               utf_ptr++;
-                               len -= 2;
-                               /* FALLTHROUGH */
+                               /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+                               if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+                                       *exceptionptr = new_noclassdeffounderror(name);
+                                       return false;
+                               }
+
+                               u = utf_new(text + 2, namelen - 3);
+
+                               if (!(comp = load_class_from_classloader(u, cl)))
+                                       return false;
+
+                               /* create the array class */
+                               return class_array_of(comp, false);
+
                        case '[':
                                /* load the component class */
-                               u = utf_new(utf_ptr, len);
-                               LOADER_INC();
-                               if (!(comp = load_class_from_classloader(u, cl))) {
-                                       LOADER_DEC();
+
+                               u = utf_new(text + 1, namelen - 1);
+
+                               if (!(comp = load_class_from_classloader(u, cl)))
                                        return false;
-                               }
-                               LOADER_DEC();
+
                                /* create the array class */
-                               r = class_array_of(comp, false);
-                               return r;
-                               break;
+                               return class_array_of(comp, false);
+
                        default:
                                /* primitive array classes are loaded by the bootstrap loader */
-                               LOADER_INC();
-                               r = load_class_bootstrap(name);
-                               LOADER_DEC();
-                               return r;
+                               return load_class_bootstrap(name);
                        }
                }
                
@@ -2010,20 +2061,39 @@ classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
                LOADER_DEC();
 
                if (r) {
-                       /* store this class in the loaded class cache */
-                       /* If another class with the same (initloader,name) pair has been */
-                       /* stored earlier it will be returned by classcache_store         */
-                       /* In this case classcache_store may not free the class because it*/
-                       /* has already been exposed to Java code which may have kept      */
-                       /* references to that class.                                      */
+                       /* Store this class in the loaded class cache. If another
+                          class with the same (initloader,name) pair has been
+                          stored earlier it will be returned by classcache_store
+                          In this case classcache_store may not free the class
+                          because it has already been exposed to Java code which
+                          may have kept references to that class. */
+
                    classinfo *c = classcache_store(cl,r,false);
+
                        if (c == NULL) {
                                /* exception, free the loaded class */
                                r->loaded = false;
                                class_free(r);
                        }
+
                        r = c;
                }
+               else {
+                       /* loadClass has thrown an exception */
+                       /* we must convert ClassNotFoundException into NoClassDefFoundException */
+                       /* XXX maybe we should have a flag that avoids this conversion */
+                       /* for calling load_class_from_classloader from Class.forName  */
+                       /* Currently we do a double conversion in these cases          */
+                       classnotfoundexception_to_noclassdeffounderror();
+               }
+
+               /* SUN compatible -verbose:class output */
+
+               if (opt_verboseclass && (r != NULL) && (r->classloader == cl)) {
+                       printf("[Loaded ");
+                       utf_display_classname(name);
+                       printf("]\n");
+               }
 
                return r;
        } 
@@ -2123,6 +2193,34 @@ classinfo *load_class_bootstrap(utf *name)
 
        r = load_class_from_classbuffer(cb);
 
+       if (!r) {
+               /* the class could not be loaded, free the classinfo struct */
+
+               class_free(c);
+
+       } else {
+               /* Store this class in the loaded class cache this step also
+               checks the loading constraints. If the class has been loaded
+               before, the earlier loaded class is returned. */
+
+               classinfo *res = classcache_store(NULL, c, true);
+
+               if (!res) {
+                       /* exception */
+                       class_free(c);
+               }
+
+               r = res;
+       }
+
+       /* SUN compatible -verbose:class output */
+
+       if (opt_verboseclass && r) {
+               printf("[Loaded ");
+               utf_display_classname(name);
+               printf(" from %s]\n", cb->path);
+       }
+
        /* free memory */
 
        suck_stop(cb);
@@ -2137,24 +2235,6 @@ classinfo *load_class_bootstrap(utf *name)
                compilingtime_start();
 #endif
 
-       if (!r) {
-               /* the class could not be loaded, free the classinfo struct */
-
-               class_free(c);
-       }
-       else {
-               /* store this class in the loaded class cache    */
-               /* this step also checks the loading constraints */
-               /* If the class has been loaded before, the      */
-               /* earlier loaded class is returned.             */
-               classinfo *res = classcache_store(NULL,c,true);
-               if (!res) {
-                       /* exception */
-                       class_free(c);
-               }
-               r = res;
-       }
-
        if (!r)
                goto return_exception;
 
@@ -2414,7 +2494,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                goto return_exception;
 
        c->fieldscount = suck_u2(cb);
-       c->fields = GCNEW(fieldinfo, c->fieldscount);
+       c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
 /*     c->fields = MNEW(fieldinfo, c->fieldscount); */
        for (i = 0; i < c->fieldscount; i++) {
                if (!load_field(cb, &(c->fields[i]),descpool))
@@ -2731,8 +2811,8 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
        methodinfo        *clone;
        methoddesc        *clonedesc;
        constant_classref *classrefs;
+       char              *text;
        s4                 namelen;
-       java_objectheader *definingloader = NULL;
        utf               *u;
 
 #ifdef LOADER_VERBOSE
@@ -2743,21 +2823,23 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
        log_text(logtext);
 #endif
 
+       text = c->name->text;
+       namelen = c->name->blength;
+
        /* Check array class name */
 
-       namelen = c->name->blength;
-       if (namelen < 2 || c->name->text[0] != '[') {
-               *exceptionptr = new_internalerror("Invalid array class name");
+       if (namelen < 2 || text[0] != '[') {
+               *exceptionptr = new_noclassdeffounderror(c->name);
                return NULL;
        }
 
-       /* Check the component type */
+       /* Check the element type */
 
-       switch (c->name->text[1]) {
+       switch (text[1]) {
        case '[':
                /* c is an array of arrays. We have to create the component class. */
 
-               u = utf_new_intern(c->name->text + 1, namelen - 1);
+               u = utf_new(text + 1, namelen - 1);
                LOADER_INC();
                if (!(comp = load_class_from_classloader(u, loader))) {
                        LOADER_DEC();
@@ -2768,17 +2850,22 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
                if (opt_eager)
                        if (!link_class(c))
                                return NULL;
-               definingloader = comp->classloader;
+
+               /* the array's flags are that of the component class */
+               c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = comp->classloader;
                break;
 
        case 'L':
                /* c is an array of objects. */
-               if (namelen < 4 || c->name->text[namelen - 1] != ';') {
-                       *exceptionptr = new_internalerror("Invalid array class name");
+
+               /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+               if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+                       *exceptionptr = new_noclassdeffounderror(c->name);
                        return NULL;
                }
 
-               u = utf_new_intern(c->name->text + 2, namelen - 3);
+               u = utf_new(text + 2, namelen - 3);
 
                LOADER_INC();
                if (!(comp = load_class_from_classloader(u, loader))) {
@@ -2790,18 +2877,33 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
                if (opt_eager)
                        if (!link_class(c))
                                return NULL;
-               definingloader = comp->classloader;
+
+               /* the array's flags are that of the component class */
+               c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = comp->classloader;
                break;
+
+       default:
+               /* c is an array of a primitive type */
+
+               /* check for cases like `[II' */
+               if (namelen > 2) {
+                       *exceptionptr = new_noclassdeffounderror(c->name);
+                       return NULL;
+               }
+
+               /* the accessibility of the array class is public (VM Spec 5.3.3) */
+               c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = NULL;
        }
 
        LOADER_ASSERT(class_java_lang_Object);
        LOADER_ASSERT(class_java_lang_Cloneable);
        LOADER_ASSERT(class_java_io_Serializable);
 
-       /* Setup the array class */
+       /* setup the array class */
 
        c->super.cls = class_java_lang_Object;
-       c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
 
     c->interfacescount = 2;
     c->interfaces = MNEW(classref_or_classinfo, 2);
@@ -2837,14 +2939,13 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
        clonedesc->returntype.type = TYPE_ADDRESS;
        clonedesc->returntype.classref = classrefs + 1;
        clonedesc->returntype.arraydim = 0;
+       /* initialize params to "empty", add real params below in
+          descriptor_params_from_paramtypes */
        clonedesc->paramcount = 0;
        clonedesc->paramslots = 0;
        clonedesc->paramtypes[0].classref = classrefs + 0;
 
-       /* parse the descriptor to get the register allocation */
-
-       if (!descriptor_params_from_paramtypes(clonedesc, ACC_NONE))
-               return false;
+       /* create methodinfo */
 
        clone = c->methods;
        MSET(clone, 0, methodinfo, 1);
@@ -2853,17 +2954,23 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
        initObjectLock(&clone->header);
 #endif
 
-       clone->flags = ACC_PUBLIC;
+       /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter 
+          related) */
+       clone->flags = ACC_PUBLIC | ACC_NATIVE;
        clone->name = utf_clone;
        clone->descriptor = utf_void__java_lang_Object;
        clone->parseddesc = clonedesc;
        clone->class = c;
        clone->monoPoly = MONO;
 
+       /* parse the descriptor to get the register allocation */
+
+       if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
+               return false;
+
        clone->entrypoint =
                codegen_createnativestub((functionptr) &builtin_clone_array, clone);
 
-
        /* XXX: field: length? */
 
        /* array classes are not loaded from class files */
@@ -2873,7 +2980,6 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
        c->parseddescsize = sizeof(methodinfo);
        c->classrefs = classrefs;
        c->classrefcount = 1;
-       c->classloader = definingloader;
 
        /* insert class into the loaded class cache */
        /* XXX free classinfo if NULL returned? */
@@ -2882,628 +2988,6 @@ classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
 }
 
 
-/************************* Function: class_findfield ***************************
-       
-       Searches a 'classinfo' structure for a field having the given name and
-       type.
-
-*******************************************************************************/
-
-fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
-
-       for (i = 0; i < c->fieldscount; i++) { 
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
-                       return &(c->fields[i]);                                                         
-    }
-
-       log_text("Can not find field given in CONSTANT_Fieldref");
-       assert(0);
-
-       /* keep compiler happy */
-
-       return NULL;
-}
-
-
-/****************** Function: class_resolvefield_int ***************************
-
-    This is an internally used helper function. Do not use this directly.
-
-       Tries to resolve a field having the given name and type.
-    If the field cannot be resolved, NULL is returned.
-
-*******************************************************************************/
-
-static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
-{
-       fieldinfo *fi;
-       s4         i;
-
-       /* search for field in class c */
-
-       for (i = 0; i < c->fieldscount; i++) { 
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
-                       return &(c->fields[i]);
-               }
-    }
-
-       /* try superinterfaces recursively */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
-               if (fi)
-                       return fi;
-       }
-
-       /* try superclass */
-
-       if (c->super.cls)
-               return class_resolvefield_int(c->super.cls, name, desc);
-
-       /* not found */
-
-       return NULL;
-}
-
-
-/********************* Function: class_resolvefield ***************************
-       
-       Resolves a reference from REFERER to a field with NAME and DESC in class C.
-
-    If the field cannot be resolved the return value is NULL. If EXCEPT is
-    true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
-                                                         classinfo *referer, bool except)
-{
-       fieldinfo *fi;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-       fi = class_resolvefield_int(c, name, desc);
-
-       if (!fi) {
-               if (except)
-                       *exceptionptr =
-                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
-                                                                                name);
-
-               return NULL;
-       }
-
-       /* XXX check access rights */
-
-       return fi;
-}
-
-
-/* class_findmethod ************************************************************
-       
-   Searches a 'classinfo' structure for a method having the given name
-   and descriptor. If descriptor is NULL, it is ignored.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *m;
-       s4          i;
-
-       for (i = 0; i < c->methodscount; i++) {
-               m = &(c->methods[i]);
-
-               if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
-                       return m;
-       }
-
-       return NULL;
-}
-
-
-/*********************** Function: class_fetchmethod **************************
-       
-    like class_findmethod, but aborts with an error if the method is not found
-
-*******************************************************************************/
-
-methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *mi;
-
-       mi = class_findmethod(c, name, desc);
-
-       if (!mi) {
-               log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
-               log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
-               log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
-
-               log_text("Method not found");
-               assert(0);
-       }
-
-       return mi;
-}
-
-
-/************************* Function: class_findmethod_approx ******************
-       
-       like class_findmethod but ignores the return value when comparing the
-       descriptor.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
-
-       for (i = 0; i < c->methodscount; i++) {
-               if (c->methods[i].name == name) {
-                       utf *meth_descr = c->methods[i].descriptor;
-                       
-                       if (desc == NULL) 
-                               /* ignore type */
-                               return &(c->methods[i]);
-
-                       if (desc->blength <= meth_descr->blength) {
-                               /* current position in utf text   */
-                               char *desc_utf_ptr = desc->text;      
-                               char *meth_utf_ptr = meth_descr->text;                                    
-                               /* points behind utf strings */
-                               char *desc_end = UTF_END(desc);         
-                               char *meth_end = UTF_END(meth_descr);   
-                               char ch;
-
-                               /* compare argument types */
-                               while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
-
-                                       if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
-                                               break; /* no match */
-
-                                       if (ch == ')')
-                                               return &(c->methods[i]); /* all parameter types equal */
-                               }
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-
-/***************** Function: class_resolvemethod_approx ***********************
-       
-       Searches a class and every super class for a method (without paying
-       attention to the return value)
-
-*******************************************************************************/
-
-methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
-{
-       while (c) {
-               /* search for method (ignore returntype) */
-               methodinfo *m = class_findmethod_approx(c, name, desc);
-               /* method found */
-               if (m) return m;
-               /* search superclass */
-               c = c->super.cls;
-       }
-
-       return NULL;
-}
-
-
-/* class_resolvemethod *********************************************************
-       
-   Searches a class and it's super classes for a method.
-
-*******************************************************************************/
-
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *m;
-
-       while (c) {
-               m = class_findmethod(c, name, desc);
-
-               if (m)
-                       return m;
-
-               c = c->super.cls;
-       }
-
-       return NULL;
-}
-
-
-/* class_resolveinterfacemethod_intern *****************************************
-
-   Internally used helper function. Do not use this directly.
-
-*******************************************************************************/
-
-static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
-                                                                                                          utf *name, utf *desc)
-{
-       methodinfo *m;
-       s4          i;
-       
-       m = class_findmethod(c, name, desc);
-
-       if (m)
-               return m;
-
-       /* try the superinterfaces */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
-                                                                                               name, desc);
-
-               if (m)
-                       return m;
-       }
-       
-       return NULL;
-}
-
-/* class_resolveinterfacemethod ************************************************
-
-   Resolves a reference from REFERER to a method with NAME and DESC in
-   interface C.
-
-   If the method cannot be resolved the return value is NULL. If
-   EXCEPT is true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
-                                                                                classinfo *referer, bool except)
-{
-       methodinfo *mi;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-       if (!(c->flags & ACC_INTERFACE)) {
-               if (except)
-                       *exceptionptr =
-                               new_exception(string_java_lang_IncompatibleClassChangeError);
-
-               return NULL;
-       }
-
-       mi = class_resolveinterfacemethod_intern(c, name, desc);
-
-       if (mi)
-               return mi;
-
-       /* try class java.lang.Object */
-
-       mi = class_findmethod(class_java_lang_Object, name, desc);
-
-       if (mi)
-               return mi;
-
-       if (except)
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
-
-       return NULL;
-}
-
-
-/* class_resolveclassmethod ****************************************************
-       
-   Resolves a reference from REFERER to a method with NAME and DESC in
-   class C.
-
-   If the method cannot be resolved the return value is NULL. If
-   EXCEPT is true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
-                                                                        classinfo *referer, bool except)
-{
-       classinfo  *cls;
-       methodinfo *mi;
-       s4          i;
-       char       *msg;
-       s4          msglen;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-/*     if (c->flags & ACC_INTERFACE) { */
-/*             if (except) */
-/*                     *exceptionptr = */
-/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
-/*             return NULL; */
-/*     } */
-
-       /* try class c and its superclasses */
-
-       cls = c;
-
-       while (cls) {
-               mi = class_findmethod(cls, name, desc);
-
-               if (mi)
-                       goto found;
-
-               cls = cls->super.cls;
-       }
-
-       /* try the superinterfaces */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
-                                                                                                name, desc);
-
-               if (mi)
-                       goto found;
-       }
-       
-       if (except) {
-               msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
-                       utf_strlen(desc) + strlen("0");
-
-               msg = MNEW(char, msglen);
-
-               utf_sprint(msg, c->name);
-               strcat(msg, ".");
-               utf_sprint(msg + strlen(msg), name);
-               utf_sprint(msg + strlen(msg), desc);
-
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodError, msg);
-
-               MFREE(msg, char, msglen);
-       }
-
-       return NULL;
-
- found:
-       if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
-               if (except)
-                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
-
-               return NULL;
-       }
-
-       /* XXX check access rights */
-
-       return mi;
-}
-
-
-/************************* Function: class_issubclass **************************
-
-       Checks if sub is a descendant of super.
-       
-*******************************************************************************/
-
-bool class_issubclass(classinfo *sub, classinfo *super)
-{
-       for (;;) {
-               if (!sub) return false;
-               if (sub == super) return true;
-               sub = sub->super.cls;
-       }
-}
-
-
-void class_showconstanti(classinfo *c, int ii) 
-{
-       u4 i = ii;
-       voidptr e;
-               
-       e = c->cpinfos [i];
-       printf ("#%d:  ", (int) i);
-       if (e) {
-               switch (c->cptags [i]) {
-               case CONSTANT_Class:
-                       printf("Classreference -> ");
-                       utf_display(((constant_classref*)e)->name);
-                       break;
-                               
-               case CONSTANT_Fieldref:
-                       printf("Fieldref -> "); goto displayFMIi;
-               case CONSTANT_Methodref:
-                       printf("Methodref -> "); goto displayFMIi;
-               case CONSTANT_InterfaceMethodref:
-                       printf("InterfaceMethod -> "); goto displayFMIi;
-               displayFMIi:
-                       {
-                               constant_FMIref *fmi = e;
-                               utf_display(fmi->classref->name);
-                               printf(".");
-                               utf_display(fmi->name);
-                               printf(" ");
-                               utf_display(fmi->descriptor);
-                       }
-                       break;
-
-               case CONSTANT_String:
-                       printf("String -> ");
-                       utf_display(e);
-                       break;
-               case CONSTANT_Integer:
-                       printf("Integer -> %d", (int) (((constant_integer*)e)->value));
-                       break;
-               case CONSTANT_Float:
-                       printf("Float -> %f", ((constant_float*)e)->value);
-                       break;
-               case CONSTANT_Double:
-                       printf("Double -> %f", ((constant_double*)e)->value);
-                       break;
-               case CONSTANT_Long:
-                       {
-                               u8 v = ((constant_long*)e)->value;
-#if U8_AVAILABLE
-                               printf("Long -> %ld", (long int) v);
-#else
-                               printf("Long -> HI: %ld, LO: %ld\n", 
-                                           (long int) v.high, (long int) v.low);
-#endif 
-                       }
-                       break;
-               case CONSTANT_NameAndType:
-                       { 
-                               constant_nameandtype *cnt = e;
-                               printf("NameAndType: ");
-                               utf_display(cnt->name);
-                               printf(" ");
-                               utf_display(cnt->descriptor);
-                       }
-                       break;
-               case CONSTANT_Utf8:
-                       printf("Utf8 -> ");
-                       utf_display(e);
-                       break;
-               default: 
-                       log_text("Invalid type of ConstantPool-Entry");
-                       assert(0);
-               }
-       }
-       printf("\n");
-}
-
-
-void class_showconstantpool (classinfo *c) 
-{
-       u4 i;
-       voidptr e;
-
-       printf ("---- dump of constant pool ----\n");
-
-       for (i=0; i<c->cpcount; i++) {
-               printf ("#%d:  ", (int) i);
-               
-               e = c -> cpinfos [i];
-               if (e) {
-                       
-                       switch (c -> cptags [i]) {
-                       case CONSTANT_Class:
-                               printf ("Classreference -> ");
-                               utf_display ( ((constant_classref*)e) -> name );
-                               break;
-                               
-                       case CONSTANT_Fieldref:
-                               printf ("Fieldref -> "); goto displayFMI;
-                       case CONSTANT_Methodref:
-                               printf ("Methodref -> "); goto displayFMI;
-                       case CONSTANT_InterfaceMethodref:
-                               printf ("InterfaceMethod -> "); goto displayFMI;
-                       displayFMI:
-                               {
-                                       constant_FMIref *fmi = e;
-                                       utf_display ( fmi->classref->name );
-                                       printf (".");
-                                       utf_display ( fmi->name);
-                                       printf (" ");
-                                       utf_display ( fmi->descriptor );
-                               }
-                               break;
-
-                       case CONSTANT_String:
-                               printf ("String -> ");
-                               utf_display (e);
-                               break;
-                       case CONSTANT_Integer:
-                               printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
-                               break;
-                       case CONSTANT_Float:
-                               printf ("Float -> %f", ((constant_float*)e) -> value);
-                               break;
-                       case CONSTANT_Double:
-                               printf ("Double -> %f", ((constant_double*)e) -> value);
-                               break;
-                       case CONSTANT_Long:
-                               {
-                                       u8 v = ((constant_long*)e) -> value;
-#if U8_AVAILABLE
-                                       printf ("Long -> %ld", (long int) v);
-#else
-                                       printf ("Long -> HI: %ld, LO: %ld\n", 
-                                                       (long int) v.high, (long int) v.low);
-#endif 
-                               }
-                               break;
-                       case CONSTANT_NameAndType:
-                               {
-                                       constant_nameandtype *cnt = e;
-                                       printf ("NameAndType: ");
-                                       utf_display (cnt->name);
-                                       printf (" ");
-                                       utf_display (cnt->descriptor);
-                               }
-                               break;
-                       case CONSTANT_Utf8:
-                               printf ("Utf8 -> ");
-                               utf_display (e);
-                               break;
-                       default: 
-                               log_text("Invalid type of ConstantPool-Entry");
-                               assert(0);
-                       }
-               }
-
-               printf ("\n");
-       }
-}
-
-
-
-/********** Function: class_showmethods   (debugging only) *************/
-
-void class_showmethods (classinfo *c)
-{
-       s4 i;
-       
-       printf ("--------- Fields and Methods ----------------\n");
-       printf ("Flags: ");     printflags (c->flags);  printf ("\n");
-
-       printf ("This: "); utf_display (c->name); printf ("\n");
-       if (c->super.cls) {
-               printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
-               }
-       printf ("Index: %d\n", c->index);
-       
-       printf ("interfaces:\n");       
-       for (i=0; i < c-> interfacescount; i++) {
-               printf ("   ");
-               utf_display (c -> interfaces[i].cls -> name);
-               printf (" (%d)\n", c->interfaces[i].cls -> index);
-               }
-
-       printf ("fields:\n");           
-       for (i=0; i < c -> fieldscount; i++) {
-               field_display (&(c -> fields[i]));
-               }
-
-       printf ("methods:\n");
-       for (i=0; i < c -> methodscount; i++) {
-               methodinfo *m = &(c->methods[i]);
-               if ( !(m->flags & ACC_STATIC)) 
-                       printf ("vftblindex: %d   ", m->vftblindex);
-
-               method_display ( m );
-
-               }
-
-       printf ("Virtual function table:\n");
-       for (i=0; i<c->vftbl->vftbllength; i++) {
-               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
-               }
-
-}
-
-
 /* loader_close ****************************************************************
 
    Frees all resources.