- 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();
- panic("Method not found");
- }
-
- 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;
- }
-
- 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;
- }
-
- 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], 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;
- }
-
- /* try the superinterfaces */
-
- for (i = 0; i < c->interfacescount; i++) {
- mi = class_resolveinterfacemethod_intern(c->interfaces[i], 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;
- }
-}
-
-
-/****************** Initialization function for classes ******************
-
- In Java, every class can have a static initialization function. This
- function has to be called BEFORE calling other methods or accessing static
- variables.
-
-*******************************************************************************/
-
-static classinfo *class_init_intern(classinfo *c);
-
-classinfo *class_init(classinfo *c)
-{
- classinfo *r;
-
- if (!makeinitializations)
- return c;
-
-#if defined(USE_THREADS)
- /* enter a monitor on the class */
-
- builtin_monitorenter((java_objectheader *) c);
-#endif
-
- /* 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 (c->initialized || c->initializing) {
-#if defined(USE_THREADS)
- builtin_monitorexit((java_objectheader *) c);
-#endif
-
- return c;
- }
-
- /* this initalizing run begins NOW */
- c->initializing = true;
-
- /* call the internal function */
- r = class_init_intern(c);
-
- /* if return value is not NULL everything was ok and the class is
- initialized */
- if (r)
- c->initialized = true;
-
- /* this initalizing run is done */
- c->initializing = false;
-
-#if defined(USE_THREADS)
- /* leave the monitor */
-
- builtin_monitorexit((java_objectheader *) c);
-#endif
-
- return r;
-}
-
-
-/* this function MUST NOT be called directly, because of thread <clinit>
- race conditions */
-
-static classinfo *class_init_intern(classinfo *c)
-{
- methodinfo *m;
- s4 i;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- int b;
-#endif
-
- /* maybe the class is not already loaded */
- if (!c->loaded)
- if (!class_load(c))
- return NULL;
-
- /* maybe the class is not already linked */
- if (!c->linked)
- if (!class_link(c))
- return NULL;
-
-#if defined(STATISTICS)
- if (opt_stat)
- count_class_inits++;
-#endif
-
- /* initialize super class */
-
- if (c->super) {
- if (!c->super->initialized) {
- if (initverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Initialize super class ");
- utf_sprint_classname(logtext + strlen(logtext), c->super->name);
- sprintf(logtext + strlen(logtext), " from ");
- utf_sprint_classname(logtext + strlen(logtext), c->name);
- log_text(logtext);
- }
-
- if (!class_init(c->super))
- return NULL;
- }
- }
-
- /* initialize interface classes */
-
- for (i = 0; i < c->interfacescount; i++) {
- if (!c->interfaces[i]->initialized) {
- if (initverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Initialize interface class ");
- utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
- sprintf(logtext + strlen(logtext), " from ");
- utf_sprint_classname(logtext + strlen(logtext), c->name);
- log_text(logtext);
- }
-
- if (!class_init(c->interfaces[i]))
- return NULL;
- }
- }
-
- m = class_findmethod(c, utf_clinit, utf_void__void);
-
- if (!m) {
- if (initverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Class ");
- utf_sprint_classname(logtext + strlen(logtext), c->name);
- sprintf(logtext + strlen(logtext), " has no static class initializer");
- log_text(logtext);
- }
-
- return c;
- }
-
- /* Sun's and IBM's JVM don't care about the static flag */
-/* if (!(m->flags & ACC_STATIC)) { */
-/* panic("Class initializer is not static!"); */
-
- 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
-
- /* we have an exception or error */
- if (*exceptionptr) {
- /* class is NOT initialized */
- c->initialized = false;
-
- /* is this an exception, than wrap it */
- if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
- java_objectheader *xptr;
- java_objectheader *cause;
-
- /* get the cause */
- cause = *exceptionptr;
-
- /* clear exception, because we are calling jit code again */
- *exceptionptr = NULL;
-
- /* 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;
- }
-
- return NULL;
- }
-
- if (initverbose)
- log_message_class("Finished static class initializer for class: ", c);
-
- return c;
-}
-
-
-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(((classinfo*)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->class->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:
- panic("Invalid type of ConstantPool-Entry");
- }
- }
- 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 ( ((classinfo*)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->class->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:
- panic ("Invalid type of ConstantPool-Entry");
- }
- }
-
- 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) {
- printf ("Super: "); utf_display (c->super->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] -> name);
- printf (" (%d)\n", c->interfaces[i] -> 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]) );
- }
-
-}
-
-
-/******************************************************************************/
-/******************* General functions for the class loader *******************/
-/******************************************************************************/
-
-/**************** function: class_primitive_from_sig ***************************
-
- return the primitive class indicated by the given signature character
-
- If the descriptor does not indicate a valid primitive type the
- return value is NULL.
-
-********************************************************************************/
-
-classinfo *class_primitive_from_sig(char sig)
-{
- switch (sig) {
- case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
- case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
- case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
- case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
- case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
- case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
- case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
- case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
- case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
- }
- return NULL;
-}
-
-/****************** function: class_from_descriptor ****************************
-
- return the class indicated by the given descriptor
-
- utf_ptr....first character of descriptor
- end_ptr....first character after the end of the string
- next.......if non-NULL, *next is set to the first character after
- the descriptor. (Undefined if an error occurs.)
-
- mode.......a combination (binary or) of the following flags:
-
- (Flags marked with * are the default settings.)
-
- What to do if a reference type descriptor is parsed successfully:
-
- CLASSLOAD_SKIP...skip it and return something != NULL
- * CLASSLOAD_NEW....get classinfo * via class_new
- CLASSLOAD_LOAD...get classinfo * via loader_load
-
- How to handle primitive types:
-
- * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
- CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
-
- How to handle "V" descriptors:
-
- * CLASSLOAD_VOID.....handle it like other primitive types
- CLASSLOAD_NOVOID...treat it as an error
-
- How to deal with extra characters after the end of the
- descriptor:
-
- * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
- CLASSLOAD_CHECKEND.....treat them as an error
-
- How to deal with errors:
-
- * CLASSLOAD_PANIC....abort execution with an error message
- CLASSLOAD_NOPANIC..return NULL on error
-
-*******************************************************************************/
-
-classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
- char **next, int mode)
-{
- char *start = utf_ptr;
- bool error = false;
- utf *name;
-
- SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
-
- if (mode & CLASSLOAD_CHECKEND)
- error |= (utf_ptr != end_ptr);
-
- if (!error) {
- if (next) *next = utf_ptr;
-
- switch (*start) {
- case 'V':
- if (mode & CLASSLOAD_NOVOID)
- break;
- /* FALLTHROUGH! */
- case 'I':
- case 'J':
- case 'F':
- case 'D':
- case 'B':
- case 'C':
- case 'S':
- case 'Z':
- return (mode & CLASSLOAD_NULLPRIMITIVE)
- ? NULL
- : class_primitive_from_sig(*start);
-
- case 'L':
- start++;
- utf_ptr--;
- /* FALLTHROUGH! */
- case '[':
- if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
- name = utf_new(start, utf_ptr - start);
- if (opt_eager) {
- classinfo *tc;
-
- tc = class_new_intern(name);
- class_load(tc);
- list_addfirst(&unlinkedclasses, tc);
-
- return tc;
-
- } else {
- return (mode & CLASSLOAD_LOAD)
- ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
- }
- }
- }
-
- /* An error occurred */
- if (mode & CLASSLOAD_NOPANIC)
- return NULL;
-
- log_plain("Invalid descriptor at beginning of '");
- log_plain_utf(utf_new(start, end_ptr - start));
- log_plain("'");
- log_nl();
-
- panic("Invalid descriptor");
-
- /* keep compiler happy */
- return NULL;
-}
-
-
-/******************* function: type_from_descriptor ****************************
-
- return the basic type indicated by the given descriptor
-
- This function parses a descriptor and returns its basic type as
- TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
-
- cls...if non-NULL the referenced variable is set to the classinfo *
- returned by class_from_descriptor.
-
- For documentation of the arguments utf_ptr, end_ptr, next and mode
- see class_from_descriptor. The only difference is that
- type_from_descriptor always uses CLASSLOAD_PANIC.
-
-********************************************************************************/
-
-int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
- char **next, int mode)
-{
- classinfo *mycls;
- if (!cls) cls = &mycls;
- *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
- switch (*utf_ptr) {
- case 'B':
- case 'C':
- case 'I':
- case 'S':
- case 'Z':
- return TYPE_INT;
- case 'D':
- return TYPE_DOUBLE;
- case 'F':
- return TYPE_FLOAT;
- case 'J':
- return TYPE_LONG;
- case 'V':
- return TYPE_VOID;
- }
- return TYPE_ADDRESS;
-}
-
-
-/******************** Function: loader_close ***********************************
-
- Frees all resources
-
-*******************************************************************************/
-
-void loader_close()
-{
- classinfo *c;
- s4 slot;
-
- for (slot = 0; slot < class_hash.size; slot++) {
- c = class_hash.ptr[slot];
-
- while (c) {
- class_free(c);
- c = c->hashlink;
- }
- }