From fd47d5e80136db91d3b2374c6236dd9e4c667740 Mon Sep 17 00:00:00 2001 From: edwin Date: Fri, 1 Apr 2005 16:53:33 +0000 Subject: [PATCH] extended type system to use symbolic references introduce pre-parsed descriptors cleaned up headers made classcache thread-safe --- src/vm/Makefile.am | 3 +- src/vm/access.h | 5 +- src/vm/class.c | 7 +- src/vm/class.h | 29 +- src/vm/classcache.c | 75 ++- src/vm/classcache.h | 5 +- src/vm/descriptor.c | 4 +- src/vm/descriptor.h | 59 ++- src/vm/exceptions.h | 7 +- src/vm/field.h | 7 +- src/vm/global.h | 42 +- src/vm/jit/codegen.inc.h | 4 +- src/vm/jit/inline/parseXTA.h | 3 +- src/vm/jit/inline/sets.c | 3 +- src/vm/jit/inline/sets.h | 4 +- src/vm/jit/jit.h | 4 +- src/vm/jit/stack.c | 12 +- src/vm/jit/stack.h | 4 +- src/vm/jit/tools/genoffsets.c | 7 +- src/vm/jit/verify/typecheck.c | 137 +++--- src/vm/jit/verify/typeinfo.c | 863 ++++++++++++++++++++-------------- src/vm/jit/verify/typeinfo.h | 172 ++++--- src/vm/linker.c | 39 +- src/vm/linker.h | 7 +- src/vm/loader.c | 215 ++++++--- src/vm/loader.h | 20 +- src/vm/method.c | 4 +- src/vm/method.h | 6 +- src/vm/references.h | 135 ++++++ src/vm/resolve.c | 110 +++-- src/vm/resolve.h | 26 +- src/vm/stringlocal.h | 4 +- src/vm/utf8.h | 3 +- 33 files changed, 1258 insertions(+), 767 deletions(-) create mode 100644 src/vm/references.h diff --git a/src/vm/Makefile.am b/src/vm/Makefile.am index 3c400fb7d..58ef7b482 100644 --- a/src/vm/Makefile.am +++ b/src/vm/Makefile.am @@ -28,7 +28,7 @@ ## ## Changes: ## -## $Id: Makefile.am 2130 2005-03-29 22:30:51Z twisti $ +## $Id: Makefile.am 2181 2005-04-01 16:53:33Z edwin $ ## Process this file with automake to produce Makefile.in @@ -75,6 +75,7 @@ libvmcore_la_SOURCES = \ method.h \ options.c \ options.h \ + references.h \ resolve.c \ resolve.h \ $(STATISTICS_OBJ) \ diff --git a/src/vm/access.h b/src/vm/access.h index fb66db99b..7eadfc231 100644 --- a/src/vm/access.h +++ b/src/vm/access.h @@ -28,15 +28,14 @@ Changes: - $Id: access.h 2111 2005-03-29 21:28:24Z twisti $ + $Id: access.h 2181 2005-04-01 16:53:33Z edwin $ */ #ifndef _ACCESS_H #define _ACCESS_H -#include "types.h" -#include "vm/class.h" +#include "vm/references.h" /* macros *********************************************************************/ diff --git a/src/vm/class.c b/src/vm/class.c index 5995c1ec9..23193e2d6 100644 --- a/src/vm/class.c +++ b/src/vm/class.c @@ -30,16 +30,14 @@ Andreas Krall Christian Thalinger - $Id: class.c 2153 2005-03-30 19:30:05Z twisti $ + $Id: class.c 2181 2005-04-01 16:53:33Z edwin $ */ #include #include -#include "config.h" -#include "types.h" - +#include "vm/global.h" #include "mm/memory.h" #if defined(USE_THREADS) @@ -58,6 +56,7 @@ #include "vm/statistics.h" #include "vm/tables.h" #include "vm/utf8.h" +#include "vm/loader.h" /******************************************************************************/ diff --git a/src/vm/class.h b/src/vm/class.h index ddc104f7a..cdd22692e 100644 --- a/src/vm/class.h +++ b/src/vm/class.h @@ -28,7 +28,7 @@ Changes: - $Id: class.h 2153 2005-03-30 19:30:05Z twisti $ + $Id: class.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -38,22 +38,19 @@ /* forward typedefs ***********************************************************/ -typedef struct classinfo classinfo; typedef struct innerclassinfo innerclassinfo; -typedef struct constant_classref constant_classref; typedef struct extra_classref extra_classref; - #include "config.h" #include "toolbox/list.h" -#include "vm/field.h" #include "vm/global.h" +#include "vm/utf8.h" +#include "vm/references.h" +#include "vm/field.h" #include "vm/linker.h" #include "vm/tables.h" -#include "vm/utf8.h" #include "vm/jit/inline/sets.h" - /* classinfo ******************************************************************/ struct classinfo { /* class structure */ @@ -135,15 +132,6 @@ struct innerclassinfo { }; -/* constant_classref **********************************************************/ - -struct constant_classref { - vftbl_t *pseudo_vftbl; /* for distinguishing it from classinfo */ - classinfo *referer; /* class containing the reference */ - utf *name; /* name of the class refered to */ -}; - - /* extra_classref ************************************************************** for classrefs not occurring within descriptors @@ -231,15 +219,6 @@ extern classinfo *pseudo_class_Null; extern classinfo *pseudo_class_New; -/* macros *********************************************************************/ - -/* initialize a constant_classref with referer `ref` and name `classname` */ -#define CLASSREF_INIT(c,ref,classname) \ - do { (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \ - (c).referer = (ref); \ - (c).name = (classname); } while (0) - - /* function prototypes ********************************************************/ void class_init_foo(void); diff --git a/src/vm/classcache.c b/src/vm/classcache.c index 9737b7e1f..401ccb745 100644 --- a/src/vm/classcache.c +++ b/src/vm/classcache.c @@ -28,14 +28,14 @@ Changes: - $Id: classcache.c 2083 2005-03-25 14:25:15Z edwin $ + $Id: classcache.c 2181 2005-04-01 16:53:33Z edwin $ */ #include #include "vm/classcache.h" -#include "vm/tables.h" #include "vm/utf8.h" +#include "vm/tables.h" #include "vm/exceptions.h" #include "mm/memory.h" @@ -56,6 +56,23 @@ #define CLASSCACHE_ASSERT(cond) #endif +/*============================================================================*/ +/* THREAD-SAFE LOCKING */ +/*============================================================================*/ + + /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + /* CAUTION: The static functions below are */ + /* NOT synchronized! */ + /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +#if defined(USE_THREADS) && defined(NATIVE_THREADS) +# define CLASSCACHE_LOCK() tables_lock() +# define CLASSCACHE_UNLOCK() tables_unlock() +#else +# define CLASSCACHE_LOCK() +# define CLASSCACHE_UNLOCK() +#endif + /*============================================================================*/ /* GLOBAL VARIABLES */ /*============================================================================*/ @@ -69,6 +86,8 @@ static hashtable classcache_hash; /* classcache_init ************************************************************* Initialize the loaded class cache + + Note: NOT synchronized! *******************************************************************************/ @@ -303,6 +322,8 @@ classcache_new_name(utf *name) RETURN VALUE: The return value is a pointer to the cached class object, or NULL, if the class is not in the cache. + + Note: synchronized with global tablelock *******************************************************************************/ @@ -312,6 +333,9 @@ classcache_lookup(classloader *initloader,utf *classname) classcache_name_entry *en; classcache_class_entry *clsen; classcache_loader_entry *lden; + classinfo *cls = NULL; + + CLASSCACHE_LOCK(); en = classcache_lookup_name(classname); @@ -323,14 +347,15 @@ classcache_lookup(classloader *initloader,utf *classname) if (lden->loader == initloader) { /* found the loaded class entry */ CLASSCACHE_ASSERT(clsen->classobj); - return clsen->classobj; + cls = clsen->classobj; + goto found; } } } } - - /* not found */ - return NULL; +found: + CLASSCACHE_UNLOCK(); + return cls; } /* classcache_store ************************************************************ @@ -346,6 +371,8 @@ classcache_lookup(classloader *initloader,utf *classname) the cache if necessary, false............an exception has been thrown. + Note: synchronized with global tablelock + *******************************************************************************/ bool @@ -357,7 +384,7 @@ classcache_store(classloader *initloader,classinfo *cls) CLASSCACHE_ASSERT(cls); - /* XXX lock table */ + CLASSCACHE_LOCK(); en = classcache_new_name(cls->name); @@ -384,7 +411,7 @@ classcache_store(classloader *initloader,classinfo *cls) /* a loading constraint is violated */ *exceptionptr = new_exception_message(string_java_lang_LinkageError, "loading constraint violated XXX add message"); - return false; /* exception */ + goto return_exception; } /* record initloader as initiating loader */ @@ -394,7 +421,7 @@ classcache_store(classloader *initloader,classinfo *cls) clsen->classobj = cls; /* done */ - return true; + goto return_success; } } @@ -411,8 +438,13 @@ classcache_store(classloader *initloader,classinfo *cls) clsen->next = en->classes; en->classes = clsen; - /* done */ +return_success: + CLASSCACHE_UNLOCK(); return true; + +return_exception: + CLASSCACHE_UNLOCK(); + return false; /* exception */ } /* classcache_find_loader ****************************************************** @@ -552,6 +584,8 @@ classcache_free_name_entry(classcache_name_entry *entry) The class cache may not be used any more after this call, except when it is reinitialized with classcache_init. + Note: NOT synchronized! + *******************************************************************************/ void @@ -590,6 +624,8 @@ classcache_free() true.............everything ok, the constraint has been added, false............an exception has been thrown. + Note: synchronized with global tablelock + *******************************************************************************/ bool @@ -611,7 +647,7 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname) if (a == b) return true; - /* XXX lock table */ + CLASSCACHE_LOCK(); en = classcache_new_name(classname); @@ -626,14 +662,14 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname) /* if the entries are the same, the constraint is already recorded */ if (clsenA == clsenB) - return true; + goto return_success; /* check if the entries can be merged */ if (clsenA->classobj && clsenB->classobj && clsenA->classobj != clsenB->classobj) { /* no, the constraint is violated */ *exceptionptr = new_exception_message(string_java_lang_LinkageError, "loading constraint violated XXX add message"); - return false; /* exception */ + goto return_exception; } /* yes, merge the entries */ @@ -680,8 +716,13 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname) } } - /* done */ +return_success: + CLASSCACHE_UNLOCK(); return true; + +return_exception: + CLASSCACHE_UNLOCK(); + return false; /* exception */ } /*============================================================================*/ @@ -695,6 +736,8 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname) IN: file.............output stream + Note: synchronized with global tablelock + *******************************************************************************/ void @@ -705,6 +748,8 @@ classcache_debug_dump(FILE *file) classcache_loader_entry *lden; u4 slot; + CLASSCACHE_LOCK(); + fprintf(file,"\n=== [loaded class cache] =====================================\n\n"); fprintf(file,"hash size : %d\n",classcache_hash.size); fprintf(file,"hash entries: %d\n",classcache_hash.entries); @@ -733,6 +778,8 @@ classcache_debug_dump(FILE *file) } } fprintf(file,"\n==============================================================\n\n"); + + CLASSCACHE_UNLOCK(); } /* diff --git a/src/vm/classcache.h b/src/vm/classcache.h index 2323e9632..127e85bd8 100644 --- a/src/vm/classcache.h +++ b/src/vm/classcache.h @@ -28,7 +28,7 @@ Changes: - $Id: classcache.h 2111 2005-03-29 21:28:24Z twisti $ + $Id: classcache.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -38,8 +38,7 @@ #include /* for FILE */ -#include "vm/class.h" -#include "vm/utf8.h" +#include "vm/references.h" /* forward declarations *******************************************************/ diff --git a/src/vm/descriptor.c b/src/vm/descriptor.c index fdc5bc9aa..adabb6287 100644 --- a/src/vm/descriptor.c +++ b/src/vm/descriptor.c @@ -28,7 +28,7 @@ Changes: - $Id: descriptor.c 2111 2005-03-29 21:28:24Z twisti $ + $Id: descriptor.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -348,6 +348,8 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name) *exceptionptr = new_classformaterror(pool->referer,"Invalid class name"); return false; /* exception */ } + + /* XXX check maximum array dimension */ c = DNEW(classref_hash_entry); c->name = name; diff --git a/src/vm/descriptor.h b/src/vm/descriptor.h index c62d72e65..092b59fa7 100644 --- a/src/vm/descriptor.h +++ b/src/vm/descriptor.h @@ -28,7 +28,7 @@ Changes: - $Id: descriptor.h 2112 2005-03-29 21:29:08Z twisti $ + $Id: descriptor.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -39,17 +39,10 @@ /* forward typedefs ***********************************************************/ typedef struct descriptor_pool descriptor_pool; -typedef struct typedesc typedesc; -typedef struct methoddesc methoddesc; -typedef union parseddesc parseddesc; - -#include "types.h" -#include "vm/class.h" #include "vm/global.h" +#include "vm/references.h" #include "vm/tables.h" -#include "vm/utf8.h" - /* data structures ************************************************************/ @@ -110,12 +103,6 @@ struct methoddesc { typedesc paramtypes[1]; /* parameter types, variable length! */ }; -union parseddesc { - typedesc *fd; /* parsed field descriptor */ - methoddesc *md; /* parsed method descriptor */ - void *any; /* used for simple test against NULL */ -}; - /* function prototypes ********************************************************/ @@ -361,6 +348,48 @@ void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d); void descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file); +/* macros for descriptor parsing **********************************************/ + +/* XXX These should be moved to descriptor.c */ + +/* SKIP_FIELDDESCRIPTOR: + * utf_ptr must point to the first character of a field descriptor. + * After the macro call utf_ptr points to the first character after + * the field descriptor. + * + * CAUTION: This macro does not check for an unexpected end of the + * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE. + */ +#define SKIP_FIELDDESCRIPTOR(utf_ptr) \ + do { while (*(utf_ptr)=='[') (utf_ptr)++; \ + if (*(utf_ptr)++=='L') \ + while(*(utf_ptr)++ != ';') /* skip */; } while(0) + +/* SKIP_FIELDDESCRIPTOR_SAFE: + * utf_ptr must point to the first character of a field descriptor. + * After the macro call utf_ptr points to the first character after + * the field descriptor. + * + * Input: + * utf_ptr....points to first char of descriptor + * end_ptr....points to first char after the end of the string + * errorflag..must be initialized (to false) by the caller! + * Output: + * utf_ptr....points to first char after the descriptor + * errorflag..set to true if the string ended unexpectedly + */ +#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \ + do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \ + if ((utf_ptr) == (end_ptr)) \ + (errorflag) = true; \ + else \ + if (*(utf_ptr)++=='L') { \ + while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \ + /* skip */; \ + if ((utf_ptr)[-1] != ';') \ + (errorflag) = true; }} while(0) + + #endif /* _DESCRIPTOR_H */ diff --git a/src/vm/exceptions.h b/src/vm/exceptions.h index 8bb3ab5f5..73d183947 100644 --- a/src/vm/exceptions.h +++ b/src/vm/exceptions.h @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: exceptions.h 2147 2005-03-30 16:47:35Z twisti $ + $Id: exceptions.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -35,13 +35,12 @@ #define _EXCEPTIONS_H -#include "config.h" - #include "vm/global.h" #include "native/include/java_lang_String.h" #include "native/include/java_lang_Throwable.h" #include "vm/builtin.h" -#include "vm/class.h" +#include "vm/references.h" +#include "vm/method.h" #if defined(USE_THREADS) && defined(NATIVE_THREADS) diff --git a/src/vm/field.h b/src/vm/field.h index a871456da..e5759e4d8 100644 --- a/src/vm/field.h +++ b/src/vm/field.h @@ -28,7 +28,7 @@ Changes: Christian Thalinger - $Id: field.h 2113 2005-03-29 21:36:28Z twisti $ + $Id: field.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -40,11 +40,10 @@ typedef struct fieldinfo fieldinfo; -#include "types.h" -#include "vm/class.h" -#include "vm/descriptor.h" #include "vm/global.h" #include "vm/utf8.h" +#include "vm/references.h" +#include "vm/descriptor.h" #include "vm/jit/inline/parseXTA.h" diff --git a/src/vm/global.h b/src/vm/global.h index 6ab163b96..e0b530758 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -33,7 +33,7 @@ Joseph Wenninger Christian Thalinger - $Id: global.h 2157 2005-03-30 20:05:55Z twisti $ + $Id: global.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -293,46 +293,6 @@ struct java_objectarray { extern bool cacao_initializing; -/* macros for descriptor parsing **********************************************/ - -/* SKIP_FIELDDESCRIPTOR: - * utf_ptr must point to the first character of a field descriptor. - * After the macro call utf_ptr points to the first character after - * the field descriptor. - * - * CAUTION: This macro does not check for an unexpected end of the - * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE. - */ -#define SKIP_FIELDDESCRIPTOR(utf_ptr) \ - do { while (*(utf_ptr)=='[') (utf_ptr)++; \ - if (*(utf_ptr)++=='L') \ - while(*(utf_ptr)++ != ';') /* skip */; } while(0) - -/* SKIP_FIELDDESCRIPTOR_SAFE: - * utf_ptr must point to the first character of a field descriptor. - * After the macro call utf_ptr points to the first character after - * the field descriptor. - * - * Input: - * utf_ptr....points to first char of descriptor - * end_ptr....points to first char after the end of the string - * errorflag..must be initialized (to false) by the caller! - * Output: - * utf_ptr....points to first char after the descriptor - * errorflag..set to true if the string ended unexpectedly - */ -#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \ - do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \ - if ((utf_ptr) == (end_ptr)) \ - (errorflag) = true; \ - else \ - if (*(utf_ptr)++=='L') { \ - while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \ - /* skip */; \ - if ((utf_ptr)[-1] != ';') \ - (errorflag) = true; }} while(0) - - /* Synchronization ************************************************************/ #if defined(USE_THREADS) && defined(NATIVE_THREADS) diff --git a/src/vm/jit/codegen.inc.h b/src/vm/jit/codegen.inc.h index f31e75410..f78723162 100644 --- a/src/vm/jit/codegen.inc.h +++ b/src/vm/jit/codegen.inc.h @@ -28,7 +28,7 @@ Changes: - $Id: codegen.inc.h 2125 2005-03-29 22:20:49Z twisti $ + $Id: codegen.inc.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -50,7 +50,7 @@ typedef struct threadcritnodetemp threadcritnodetemp; #include "types.h" #include "vm/global.h" -#include "vm/class.h" +#include "vm/references.h" #include "vm/method.h" #include "vm/jit/jit.h" #include "vm/jit/reg.h" diff --git a/src/vm/jit/inline/parseXTA.h b/src/vm/jit/inline/parseXTA.h index 421539d91..a13c8362c 100644 --- a/src/vm/jit/inline/parseXTA.h +++ b/src/vm/jit/inline/parseXTA.h @@ -26,7 +26,7 @@ Authors: Carolyn Oates - $Id: parseXTA.h 2160 2005-03-30 20:08:29Z twisti $ + $Id: parseXTA.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -39,6 +39,7 @@ typedef struct xtainfo xtainfo; typedef struct xtafldinfo xtafldinfo; +#include "toolbox/list.h" #include "vm/global.h" #include "vm/jit/inline/sets.h" diff --git a/src/vm/jit/inline/sets.c b/src/vm/jit/inline/sets.c index b1c3cbfe6..7ece8d111 100644 --- a/src/vm/jit/inline/sets.c +++ b/src/vm/jit/inline/sets.c @@ -26,7 +26,7 @@ Authors: Carolyn Oates - $Id: sets.c 2107 2005-03-28 22:44:28Z twisti $ + $Id: sets.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -39,6 +39,7 @@ #include "vm/linker.h" #include "vm/loader.h" #include "vm/tables.h" +#include "vm/class.h" #include "vm/jit/inline/sets.h" diff --git a/src/vm/jit/inline/sets.h b/src/vm/jit/inline/sets.h index 2c3ed3afd..fe9acf08f 100644 --- a/src/vm/jit/inline/sets.h +++ b/src/vm/jit/inline/sets.h @@ -26,7 +26,7 @@ Authors: Carolyn Oates - $Id: sets.h 2107 2005-03-28 22:44:28Z twisti $ + $Id: sets.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -42,9 +42,9 @@ typedef struct classSet classSet; typedef struct classSetNode classSetNode; -#include "types.h" #include "vm/global.h" #include "vm/method.h" +#include "vm/field.h" /*------------ Method /Class Used Markers -------------------------------*/ diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index 38887504f..e6f0bd7b5 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -29,7 +29,7 @@ Changes: Christian Thalinger - $Id: jit.h 2135 2005-03-30 09:55:26Z twisti $ + $Id: jit.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -47,8 +47,8 @@ typedef struct subroutineinfo subroutineinfo; #include "toolbox/chain.h" -#include "vm/class.h" #include "vm/global.h" +#include "vm/references.h" #include "vm/method.h" #include "vm/jit/codegen.inc.h" #include "vm/jit/verify/typeinfo.h" diff --git a/src/vm/jit/stack.c b/src/vm/jit/stack.c index d205b990c..1e00f4478 100644 --- a/src/vm/jit/stack.c +++ b/src/vm/jit/stack.c @@ -29,7 +29,7 @@ Changes: Edwin Steiner Christian Thalinger - $Id: stack.c 2163 2005-03-30 20:18:18Z twisti $ + $Id: stack.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -2140,7 +2140,7 @@ void icmd_print_stack(codegendata *cd, stackptr s) else if (IS_FLT_DBL_TYPE(s->type)) printf(" F%02d", s->regoff); else { - printf(" %3s", regs[s->regoff]); + printf(" R%02d", s->regoff); } break; case STACKVAR: @@ -2163,7 +2163,7 @@ void icmd_print_stack(codegendata *cd, stackptr s) else if (IS_FLT_DBL_TYPE(s->type)) printf(" f%02d", s->regoff); else { - printf(" %3s", regs[s->regoff]); + printf(" r%02d", s->regoff); } break; case STACKVAR: @@ -2286,7 +2286,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd) else if ((j == TYPE_FLT) || (j == TYPE_DBL)) printf("f%02d", rd->locals[i][j].regoff); else { - printf("%3s", regs[rd->locals[i][j].regoff]); + printf("r%02d", rd->locals[i][j].regoff); } } printf("\n"); @@ -2312,7 +2312,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd) else if ((j == TYPE_FLT) || (j == TYPE_DBL)) printf("F%02d", rd->interfaces[i][j].regoff); else { - printf("%3s", regs[rd->interfaces[i][j].regoff]); + printf("R%02d", rd->interfaces[i][j].regoff); } } else { @@ -2321,7 +2321,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd) else if ((j == TYPE_FLT) || (j == TYPE_DBL)) printf("f%02d", rd->interfaces[i][j].regoff); else { - printf("%3s", regs[rd->interfaces[i][j].regoff]); + printf("r%02d", rd->interfaces[i][j].regoff); } } } diff --git a/src/vm/jit/stack.h b/src/vm/jit/stack.h index fd68a0083..a382de3c2 100644 --- a/src/vm/jit/stack.h +++ b/src/vm/jit/stack.h @@ -26,7 +26,7 @@ Authors: Christian Thalinger - $Id: stack.h 1735 2004-12-07 14:33:27Z twisti $ + $Id: stack.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -34,8 +34,8 @@ #ifndef _STACK_H #define _STACK_H -#include "vm/exceptions.h" #include "vm/global.h" +#include "vm/exceptions.h" #include "vm/jit/reg.h" diff --git a/src/vm/jit/tools/genoffsets.c b/src/vm/jit/tools/genoffsets.c index 6e9cc9e80..db8baa00f 100644 --- a/src/vm/jit/tools/genoffsets.c +++ b/src/vm/jit/tools/genoffsets.c @@ -28,19 +28,18 @@ Changes: - $Id: genoffsets.c 2122 2005-03-29 22:12:06Z twisti $ + $Id: genoffsets.c 2181 2005-04-01 16:53:33Z edwin $ */ #include -#include "config.h" -#include "types.h" +#include "vm/global.h" #include "mm/memory.h" #include "vm/linker.h" #include "vm/method.h" -#include "vm/global.h" +#include "vm/class.h" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/verify/typecheck.c b/src/vm/jit/verify/typecheck.c index 548b71ae0..b2dedc939 100644 --- a/src/vm/jit/verify/typecheck.c +++ b/src/vm/jit/verify/typecheck.c @@ -26,10 +26,11 @@ Authors: Edwin Steiner - $Id: typecheck.c 2081 2005-03-25 13:45:26Z edwin $ + $Id: typecheck.c 2181 2005-04-01 16:53:33Z edwin $ */ +#include #include #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */ @@ -37,7 +38,6 @@ #ifdef CACAO_TYPECHECK #include "types.h" -/* #include "main.h" */ #include "mm/memory.h" #include "toolbox/logging.h" #include "native/native.h" @@ -47,12 +47,20 @@ #include "vm/tables.h" #include "vm/jit/jit.h" #include "vm/jit/stack.h" +#include "vm/access.h" +#include "vm/resolve.h" /****************************************************************************/ /* DEBUG HELPERS */ /****************************************************************************/ +#ifdef TYPECHECK_DEBUG +#define TYPECHECK_ASSERT(cond) assert(cond) +#else +#define TYPECHECK_ASSERT(cond) +#endif + #ifdef TYPECHECK_VERBOSE_OPT bool typecheckverbose = false; #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0) @@ -80,6 +88,7 @@ bool typecheckverbose = false; #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b)) #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c)) #define LOGSTRu(utf) DOLOG(log_plain_utf(utf)) +#define LOGNAME(c) DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0)) #else #define LOG(str) #define LOG1(str,a) @@ -94,6 +103,7 @@ bool typecheckverbose = false; #define LOGSTR2(str,a,b) #define LOGSTR3(str,a,b,c) #define LOGSTRu(utf) +#define LOGNAME(c) #endif #ifdef TYPECHECK_VERBOSE_IMPORTANT @@ -116,7 +126,8 @@ typestack_print(FILE *file,stackptr stack) { #ifdef TYPEINFO_DEBUG while (stack) { - typeinfo_print_stacktype(file,stack->type,&stack->typeinfo); + /*fprintf(file,"<%p>",stack);*/ + typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo)); stack = stack->prev; if (stack) fprintf(file," "); } @@ -290,10 +301,7 @@ typestack_copy(stackptr dst,stackptr y,typevector *selected) static void typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc) { -#ifdef TYPECHECK_DEBUG - if (dst->type != TYPE_ADDRESS) - panic("Internal error: Storing returnAddress in non-address slot"); -#endif + TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS); TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL); for (;loc; loc=loc->alt) { @@ -367,14 +375,9 @@ typestack_separable_with(stackptr a,stackptr b,int kb) typeinfo_retaddr_set *setb; for (; a; a = a->prev, b = b->prev) { -#ifdef TYPECHECK_DEBUG - if (!b) panic("Internal error: typestack_separable_from: different depth"); -#endif + TYPECHECK_ASSERT(b); if (TYPESTACK_IS_RETURNADDRESS(a)) { -#ifdef TYPECHECK_DEBUG - if (!TYPESTACK_IS_RETURNADDRESS(b)) - panic("Internal error: typestack_separable_from: unmergable stacks"); -#endif + TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b)); seta = TYPESTACK_RETURNADDRESSSET(a); setb = TYPESTACK_RETURNADDRESSSET(b); RETURNADDRESSSET_SEEK(setb,kb); @@ -383,9 +386,7 @@ typestack_separable_with(stackptr a,stackptr b,int kb) if (seta->addr != setb->addr) return true; } } -#ifdef TYPECHECK_DEBUG - if (b) panic("Internal error: typestack_separable_from: different depth"); -#endif + TYPECHECK_ASSERT(!b); return false; } @@ -397,14 +398,9 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb) typeinfo_retaddr_set *setb; for (; a; a = a->prev, b = b->prev) { -#ifdef TYPECHECK_DEBUG - if (!b) panic("Internal error: typestack_separable_from: different depth"); -#endif + TYPECHECK_ASSERT(b); if (TYPESTACK_IS_RETURNADDRESS(a)) { -#ifdef TYPECHECK_DEBUG - if (!TYPESTACK_IS_RETURNADDRESS(b)) - panic("Internal error: typestack_separable_from: unmergable stacks"); -#endif + TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b)); seta = TYPESTACK_RETURNADDRESSSET(a); setb = TYPESTACK_RETURNADDRESSSET(b); RETURNADDRESSSET_SEEK(seta,ka); @@ -413,9 +409,7 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb) if (seta->addr != setb->addr) return true; } } -#ifdef TYPECHECK_DEBUG - if (b) panic("Internal error: typestack_separable_from: different depth"); -#endif + TYPECHECK_ASSERT(!b); return false; } @@ -622,11 +616,11 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, c /* In the cases below, definingclass cannot be an interface */ case 0: - if (definingclass->packagename != methodclass->packagename) + if (!SAME_PACKAGE(definingclass,methodclass)) return false; break; case ACC_PROTECTED: - if (definingclass->packagename != methodclass->packagename) { + if (!SAME_PACKAGE(definingclass,methodclass)) { if (!builtin_isanysubclass(methodclass,implementingclass)) return false; @@ -660,8 +654,8 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, c && !TYPEINFO_IS_NULLTYPE(*instance) && !TYPEINFO_IS_NEWOBJECT(*instance)) { - if (!typeinfo_is_assignable_to_classinfo(instance, - implementingclass)) + if (!typeinfo_is_assignable_to_class(instance, + CLASSREF_OR_CLASSINFO(implementingclass))) { LOG("instance not assignable"); LOGINFO(instance); @@ -845,7 +839,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) typedescriptor returntype; /* return type of current method */ u1 *ptype; /* parameter types of called method */ typeinfo *pinfo; /* parameter typeinfos of called method */ - int rtype; /* return type of called method */ + u1 rtype; /* return type of called method */ typeinfo rinfo; /* typeinfo for return type of called method */ stackptr dst; /* output stack of current instruction */ @@ -868,7 +862,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) #endif LOGSTR("\n==============================================================================\n"); - /*DOLOG( show_icmd_method(cd->method,cd,rd));*/ + DOLOG( show_icmd_method(cd->method,cd,rd)); LOGSTR("\n==============================================================================\n"); LOGimpSTR("Entering typecheck: "); LOGimpSTRu(cd->method->name); @@ -900,7 +894,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) { /*show_icmd_method(cd->method,cd,rd);*/ LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH; - panic("Internal error: Unexpected block flags in typecheck()"); + TYPECHECK_ASSERT(false); } #endif if (bptr->flags >= BBFINISHED) { @@ -956,7 +950,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) LOG("'this' argument set.\n"); /* the rest of the arguments and the return type */ - i = typedescriptors_init_from_method_args(td, m->descriptor, + i = typedescriptors_init_from_methoddesc(td, m->parseddesc, i, true, /* two word types use two slots */ &returntype); @@ -1038,6 +1032,10 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) iptr = bptr->iinstr; while (--len >= 0) { TYPECHECK_COUNT(stat_ins); + + DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals)); + LOGNL; LOGFLUSH; + DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH; opcode = iptr->opc; @@ -1233,7 +1231,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) if (type != fi->type) panic("PUTFIELD(CONST) type mismatch"); if (type == TYPE_ADR) { - TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi); + typeinfo_init_from_typedesc(fi->parseddesc,NULL,&rinfo); if (!typeinfo_is_assignable(temptip, &rinfo)) panic("PUTFIELD(CONST) reference type not assignable"); @@ -1278,7 +1276,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) if (type != fi->type) panic("PUTSTATIC(CONST) type mismatch"); if (type == TYPE_ADR) { - TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi); + typeinfo_init_from_typedesc(fi->parseddesc,NULL,&rinfo); if (!typeinfo_is_assignable(temptip, &rinfo)) panic("PUTSTATIC(CONST) reference type not assignable"); @@ -1296,13 +1294,13 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) { fieldinfo *fi = (fieldinfo *)(iptr->val.a); - + if (!is_accessible(fi->flags,fi->class,fi->class,myclass, &(curstack->typeinfo))) panic("GETFIELD: field is not accessible"); if (dst->type == TYPE_ADR) { - TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi); + typeinfo_init_from_typedesc(fi->parseddesc,NULL,&(dst->typeinfo)); } } maythrow = true; @@ -1325,7 +1323,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) } if (dst->type == TYPE_ADR) { - TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi); + typeinfo_init_from_typedesc(fi->parseddesc,NULL,&(dst->typeinfo)); } } maythrow = true; @@ -1336,7 +1334,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) case ICMD_ARRAYLENGTH: if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo) - && curstack->typeinfo.typeclass != pseudo_class_Arraystub) + && curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub) panic("illegal instruction: ARRAYLENGTH on non-array"); maythrow = true; break; @@ -1555,8 +1553,8 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) /* RETURNS AND THROW */ case ICMD_ATHROW: - if (!typeinfo_is_assignable_to_classinfo( - &curstack->typeinfo,class_java_lang_Throwable)) + if (!typeinfo_is_assignable_to_class( + &curstack->typeinfo,CLASSREF_OR_CLASSINFO(class_java_lang_Throwable))) panic("illegal instruction: ATHROW on non-Throwable"); superblockend = true; maythrow = true; @@ -1642,7 +1640,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) bool specialmethod = (mi->name->text[0] == '<'); bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init); instruction *ins; - classinfo *initclass; + classref_or_classinfo initclass; if (specialmethod && !callinginit) panic("Invalid invocation of special method"); @@ -1664,9 +1662,9 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class); i++; } - typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i, - MAXPARAMS-i,false, - &rtype,&rinfo); + typeinfo_init_from_methoddesc(mi->parseddesc,ptype+i,pinfo+i, + MAXPARAMS-i,false, + &rtype,&rinfo); /* check parameter types */ srcstack = curstack; @@ -1687,14 +1685,11 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) /* get the address of the NEW instruction */ LOGINFO(&(srcstack->typeinfo)); ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo); - initclass = (ins) ? (classinfo*)ins[-1].val.a : m->class; - LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL; - - /* check type */ - /* (This is checked below.) */ -/* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */ -/* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */ -/* panic("Parameter reference type mismatch in invocation"); */ + if (ins) + initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a); + else + initclass.cls = m->class; + LOGSTR("class: "); LOGNAME(initclass); LOGNL; } else { if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i)) @@ -1753,7 +1748,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) TYPESTACK_COPY(sp,copy); } - TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass); + TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(srcstack->typeinfo,initclass); } srcstack = srcstack->prev; } @@ -1762,10 +1757,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) /* initializing the 'this' reference? */ if (!ins) { -#ifdef TYPECHECK_DEBUG - if (!initmethod) - panic("Internal error: calling on this in non- method."); -#endif + TYPECHECK_ASSERT(initmethod); /* must be of current class or direct superclass */ if (mi->class != m->class && mi->class != m->class->super) panic(" calling of the wrong class"); @@ -1777,7 +1769,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) else { /* initializing an instance created with NEW */ /* XXX is this strictness ok? */ - if (mi->class != initclass) + if (mi->class != initclass.cls) /* XXX change to classref */ panic("Calling method of the wrong class"); } } @@ -1834,7 +1826,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) != iptr->val.fp) builtindesc++; if (!builtindesc->opcode) { dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp)); - panic("Internal error: builtin not found in table"); + TYPECHECK_ASSERT(false); } TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1); } @@ -1887,7 +1879,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) != iptr->val.fp) builtindesc++; if (!builtindesc->opcode) { dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp)); - panic("Internal error: builtin not found in table"); + TYPECHECK_ASSERT(false); } TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1); } @@ -1901,8 +1893,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) if (iptr[-1].opc != ICMD_ACONST) panic("illegal instruction: builtin_new without classinfo"); cls = (classinfo *) iptr[-1].val.a; - if (!cls->linked) - panic("Internal error: NEW with unlinked class"); + TYPECHECK_ASSERT(cls->linked); /* The following check also forbids array classes and interfaces: */ if ((cls->flags & ACC_ABSTRACT) != 0) panic("Invalid instruction: NEW creating instance of abstract class"); @@ -1947,7 +1938,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) != iptr->val.fp) builtindesc++; if (!builtindesc->opcode) { dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp)); - panic("Internal error: builtin not found in table"); + TYPECHECK_ASSERT(false); } TYPECHECK_ARGS1(builtindesc->type_s1); } @@ -1982,14 +1973,14 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) case ICMD_AASTORE: LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr)); LOG("Should have been converted to builtin function call."); - panic("Internal error: unexpected instruction encountered"); + TYPECHECK_ASSERT(false); break; case ICMD_READONLY_ARG: case ICMD_CLEAR_ARGREN: LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr)); LOG("Should have been replaced in stack.c."); - panic("Internal error: unexpected pseudo instruction encountered"); + TYPECHECK_ASSERT(false); break; #endif @@ -2142,8 +2133,8 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) i = 0; while (handlers[i]) { TYPECHECK_COUNT(stat_handlers_reached); - cls = handlers[i]->catchtype; - excstack.typeinfo.typeclass = (cls) ? cls + cls = handlers[i]->catchtype; /* XXX change to classref */ + excstack.typeinfo.typeclass.cls = (cls) ? cls : class_java_lang_Throwable; repeat |= typestate_reach(cd,rd, localbuf,bptr, handlers[i]->handler, @@ -2154,6 +2145,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) } } + LOG("next instruction"); iptr++; } /* while instructions */ @@ -2198,7 +2190,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) } while (repeat); #ifdef TYPECHECK_STATISTICS - dolog("Typechecker did %4d iterations",count_iterations); + LOG1("Typechecker did %4d iterations",count_iterations); TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS); TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr); #endif @@ -2214,7 +2206,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) { LOG2("block L%03d has invalid flags after typecheck: %d", m->basicblocks[i].debug_nr,m->basicblocks[i].flags); - panic("Invalid block flags after typecheck"); + TYPECHECK_ASSERT(false); } } #endif @@ -2247,4 +2239,5 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */ diff --git a/src/vm/jit/verify/typeinfo.c b/src/vm/jit/verify/typeinfo.c index 0f6e8fde0..4b943bf9d 100644 --- a/src/vm/jit/verify/typeinfo.c +++ b/src/vm/jit/verify/typeinfo.c @@ -26,11 +26,11 @@ Authors: Edwin Steiner - $Id: typeinfo.c 2161 2005-03-30 20:08:53Z twisti $ + $Id: typeinfo.c 2181 2005-04-01 16:53:33Z edwin $ */ - +#include #include #include "mm/memory.h" @@ -40,14 +40,27 @@ #include "vm/tables.h" #include "vm/jit/jit.h" #include "vm/jit/verify/typeinfo.h" +#include "vm/descriptor.h" +#include "vm/resolve.h" + -#define CLASS_IS_ARRAY(cls) \ - ((cls)->vftbl->arraydesc != NULL) +/* check if a linked class is an array class. Only use for linked classes! */ +#define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL) -#define CLASS_IMPLEMENTS_INTERFACE(cls,index) \ +#define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index) \ ( ((index) < (cls)->vftbl->interfacetablelength) \ && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) ) +/******************************************************************************/ +/* DEBUG HELPERS */ +/******************************************************************************/ + +#ifdef TYPEINFO_DEBUG +#define TYPEINFO_ASSERT(cond) assert(cond) +#else +#define TYPEINFO_ASSERT(cond) +#endif + /**********************************************************************/ /* TYPEVECTOR FUNCTIONS */ /**********************************************************************/ @@ -183,7 +196,8 @@ typevectorset_store_twoword(typevector *vec,int index,int type) } void -typevectorset_init_object(typevector *set,void *ins,classinfo *initclass, +typevectorset_init_object(typevector *set,void *ins, + classref_or_classinfo initclass, int size) { int i; @@ -194,7 +208,7 @@ typevectorset_init_object(typevector *set,void *ins,classinfo *initclass, && TYPEINFO_IS_NEWOBJECT(set->td[i].info) && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins) { - TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass); + TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(set->td[i].info,initclass); } } } @@ -334,27 +348,34 @@ typevectorset_collapse(typevector *dst,int size) bool typeinfo_is_array(typeinfo *info) { + TYPEINFO_ASSERT(info); return TYPEINFO_IS_ARRAY(*info); } bool typeinfo_is_primitive_array(typeinfo *info,int arraytype) { + TYPEINFO_ASSERT(info); return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype); } bool typeinfo_is_array_of_refs(typeinfo *info) { + TYPEINFO_ASSERT(info); return TYPEINFO_IS_ARRAY_OF_REFS(*info); } -static -bool +static bool interface_extends_interface(classinfo *cls,classinfo *interf) { int i; + TYPEINFO_ASSERT(cls); + TYPEINFO_ASSERT(interf); + TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0); + TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0); + /* first check direct superinterfaces */ for (i=0; iinterfacescount; ++i) { if (cls->interfaces[i] == interf) @@ -370,16 +391,19 @@ interface_extends_interface(classinfo *cls,classinfo *interf) return false; } -static -bool +static bool classinfo_implements_interface(classinfo *cls,classinfo *interf) { + TYPEINFO_ASSERT(cls); + TYPEINFO_ASSERT(interf); + TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0); + if (!cls->loaded) - if (!load_class_bootstrap(cls)) + if (!load_class_bootstrap(cls)) /* XXX */ return false; if (!cls->linked) - if (!link_class(cls)) + if (!link_class(cls)) /* XXX */ return false; if (cls->flags & ACC_INTERFACE) { @@ -391,15 +415,19 @@ classinfo_implements_interface(classinfo *cls,classinfo *interf) return interface_extends_interface(cls,interf); } - return CLASS_IMPLEMENTS_INTERFACE(cls,interf->index); + return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index); } -bool mergedlist_implements_interface(typeinfo_mergedlist *merged, - classinfo *interf) +tristate_t +mergedlist_implements_interface(typeinfo_mergedlist *merged, + classinfo *interf) { int i; - classinfo **mlist; + classref_or_classinfo *mlist; + TYPEINFO_ASSERT(interf); + TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0); + /* Check if there is an non-empty mergedlist. */ if (!merged) return false; @@ -410,13 +438,16 @@ bool mergedlist_implements_interface(typeinfo_mergedlist *merged, mlist = merged->list; i = merged->count; while (i--) { - if (!classinfo_implements_interface(*mlist++,interf)) + if (IS_CLASSREF(*mlist)) { + return MAYBE; + } + if (!classinfo_implements_interface((mlist++)->cls,interf)) return false; } return true; } -bool +tristate_t merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged, classinfo *interf) { @@ -436,45 +467,35 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged, return (merged && mergedlist_implements_interface(merged,interf)); } -bool +tristate_t typeinfo_is_assignable(typeinfo *value,typeinfo *dest) { - /* DEBUG CHECK: dest must not have a merged list. */ -#ifdef TYPEINFO_DEBUG - if (dest->merged) - panic("Internal error: typeinfo_is_assignable on merged destination."); -#endif + TYPEINFO_ASSERT(value); + TYPEINFO_ASSERT(dest); + TYPEINFO_ASSERT(dest->merged == NULL); - return typeinfo_is_assignable_to_classinfo(value,dest->typeclass); + return typeinfo_is_assignable_to_class(value,dest->typeclass); } -bool -typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) +tristate_t +typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest) { + classref_or_classinfo c; classinfo *cls; + utf *classname; + + TYPEINFO_ASSERT(value); - cls = value->typeclass; + c = value->typeclass; /* assignments of primitive values are not checked here. */ - if (!cls && !dest) + if (!c.any && !dest.any) return true; /* primitive and reference types are not assignment compatible. */ - if (!cls || !dest) + if (!c.any || !dest.any) return false; - /* maybe we need to load and link the class */ - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); - -#ifdef TYPEINFO_DEBUG - if (!dest->linked) - panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class."); -#endif - /* the null type can be assigned to any type */ if (TYPEINFO_IS_NULLTYPE(*value)) return true; @@ -483,13 +504,70 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) if (TYPEINFO_IS_NEWOBJECT(*value)) return false; - if (dest->flags & ACC_INTERFACE) { + if (IS_CLASSREF(c)) { + /* The value type is an unresolved class reference. */ + classname = c.ref->name; + } + else { + classname = c.cls->name; + } + + if (IS_CLASSREF(dest)) { + /* the destination type is an unresolved class reference */ + /* In this case we cannot tell a lot about assignability. */ + + /* the common case of value and dest type having the same classname */ + if (dest.ref->name == classname && !value->merged) + return true; + + /* we cannot tell if value is assignable to dest, so we */ + /* leave it up to the resolving code to check this */ + return MAYBE; + } + + /* { we know that dest is a loaded class } */ + + if (IS_CLASSREF(c)) { + /* the value type is an unresolved class reference */ + + /* the common case of value and dest type having the same classname */ + if (dest.cls->name == classname) + return true; + + /* we cannot tell if value is assignable to dest, so we */ + /* leave it up to the resolving code to check this */ + return MAYBE; + } + + /* { we know that both c and dest are loaded classes } */ + + cls = c.cls; + + if (!cls->loaded) + load_class_bootstrap(cls); /* XXX */ + if (!dest.cls->loaded) + load_class_bootstrap(dest.cls); /* XXX */ + + TYPEINFO_ASSERT(cls->loaded); + TYPEINFO_ASSERT(dest.cls->loaded); + + /* maybe we need to link the classes */ + if (!cls->linked) + link_class(cls); /* XXX */ + if (!dest.cls->linked) + link_class(dest.cls); /* XXX */ + + /* { we know that both c and dest are linked classes } */ + TYPEINFO_ASSERT(cls->linked); + TYPEINFO_ASSERT(dest.cls->linked); + + if (dest.cls->flags & ACC_INTERFACE) { /* We are assigning to an interface type. */ - return merged_implements_interface(cls,value->merged,dest); + return merged_implements_interface(cls,value->merged,dest.cls); } - if (CLASS_IS_ARRAY(dest)) { - arraydescriptor *arraydesc = dest->vftbl->arraydesc; + if (CLASSINFO_IS_ARRAY(dest.cls)) { + arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc; int dimension = arraydesc->dimension; classinfo *elementclass = (arraydesc->elementvftbl) ? arraydesc->elementvftbl->class : NULL; @@ -498,16 +576,16 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) if (!TYPEINFO_IS_ARRAY(*value)) return false; - /* {Both value and dest are array types.} */ + /* {Both value and dest.cls are array types.} */ - /* value must have at least the dimension of dest. */ + /* value must have at least the dimension of dest.cls. */ if (value->dimension < dimension) return false; if (value->dimension > dimension) { /* value has higher dimension so we need to check * if its component array can be assigned to the - * element type of dest */ + * element type of dest.cls */ if (!elementclass) return false; @@ -521,12 +599,12 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) return class_issubclass(pseudo_class_Arraystub,elementclass); } - /* {value and dest have the same dimension} */ + /* {value and dest.cls have the same dimension} */ if (value->elementtype != arraydesc->elementtype) return false; - if (value->elementclass) { + if (value->elementclass.any) { /* We are assigning an array of objects so we have to * check if the elements are assignable. */ @@ -534,25 +612,37 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) if (elementclass->flags & ACC_INTERFACE) { /* We are assigning to an interface type. */ - return merged_implements_interface(value->elementclass, + return merged_implements_interface(value->elementclass.cls, value->merged, elementclass); } /* We are assigning to a class type. */ - return class_issubclass(value->elementclass,elementclass); + return class_issubclass(value->elementclass.cls,elementclass); } return true; } - /* {dest is not an array} */ + /* {dest.cls is not an array} */ + /* {dest.cls is a loaded class} */ + + /* If there are any unresolved references in the merged list, we cannot */ + /* tell if the assignment will be ok. */ + /* This can only happen when cls is java.lang.Object */ + if (cls == class_java_lang_Object && value->merged) { + classref_or_classinfo *mlist = value->merged->list; + int i = value->merged->count; + while (i--) + if (IS_CLASSREF(*mlist++)) + return MAYBE; + } /* We are assigning to a class type */ if (cls->flags & ACC_INTERFACE) cls = class_java_lang_Object; - return class_issubclass(cls,dest); + return class_issubclass(cls,dest.cls); } /**********************************************************************/ @@ -560,229 +650,214 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) /* The following functions fill in uninitialized typeinfo structures. */ /**********************************************************************/ -void -typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr) +bool +typeinfo_init_class(typeinfo *info,classref_or_classinfo c) { - classinfo *cls; - char *end; - - cls = class_from_descriptor(utf_ptr,end_ptr,&end, - CLASSLOAD_NULLPRIMITIVE - | CLASSLOAD_NEW - | CLASSLOAD_NOVOID - | CLASSLOAD_CHECKEND); - + char *utf_ptr; + int len; + classinfo *cls; + + TYPEINFO_ASSERT(c.any); + TYPEINFO_ASSERT(info); + + /* if necessary, try to resolve lazily */ + if (!resolve_classref_or_classinfo(NULL /* XXX should now method */, + c,resolveLazy,true,&cls)) + { + panic("XXX could not resolve class reference"); /* XXX */ + return false; + } + if (cls) { - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); - - /* a class, interface or array descriptor */ TYPEINFO_INIT_CLASSINFO(*info,cls); - } else { - /* a primitive type */ - TYPEINFO_INIT_PRIMITIVE(*info); + return true; + } + + /* {the type could no be resolved lazily} */ + + info->typeclass.ref = c.ref; + info->elementclass.any = NULL; + info->dimension = 0; + info->merged = NULL; + + /* handle array type references */ + utf_ptr = c.ref->name->text; + len = c.ref->name->blength; + if (*utf_ptr == '[') { + /* count dimensions */ + while (*utf_ptr == '[') { + utf_ptr++; + info->dimension++; + len--; + } + if (*utf_ptr == 'L') { + utf_ptr++; + len -= 2; + info->elementtype = ARRAYTYPE_OBJECT; + info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len)); + } + else { + /* an array with primitive element type */ + /* should have been resolved above */ + TYPEINFO_ASSERT(false); + } } + return true; } -int -typeinfo_count_method_args(utf *d,bool twoword) +void +typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info) { - int args = 0; - char *utf_ptr = d->text; - char *end_pos = utf_end(d); - char c; + TYPEINFO_ASSERT(desc); - /* method descriptor must start with parenthesis */ - if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); +#ifdef TYPEINFO_VERBOSE + fprintf(stderr,"typeinfo_init_from_typedesc("); + descriptor_debug_print_typedesc(stderr,desc); + fprintf(stderr,")\n"); +#endif - - /* check arguments */ - while ((c = *utf_ptr) != ')') { - class_from_descriptor(utf_ptr,end_pos,&utf_ptr, - CLASSLOAD_SKIP | CLASSLOAD_NOVOID - | CLASSLOAD_NULLPRIMITIVE); - args++; - if (twoword && (c == 'J' || c == 'D')) - /* primitive two-word type */ - args++; - } + if (type) + *type = desc->type; - return args; + if (info) { + if (desc->type == TYPE_ADR) { + TYPEINFO_ASSERT(desc->classref); + TYPEINFO_INIT_CLASSREF(*info,desc->classref); + } + else { + TYPEINFO_INIT_PRIMITIVE(*info); + } + } } void -typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf, - int buflen,bool twoword, - int *returntype,typeinfo *returntypeinfo) +typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf, + int buflen,bool twoword, + u1 *returntype,typeinfo *returntypeinfo) { - char *utf_ptr = desc->text; /* current position in utf text */ - char *end_pos = utf_end(desc); /* points behind utf string */ + int i; int args = 0; - classinfo *cls; - /* method descriptor must start with parenthesis */ - if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); + TYPEINFO_ASSERT(desc); + TYPEINFO_ASSERT(typebuf); + TYPEINFO_ASSERT(infobuf); + +#ifdef TYPEINFO_VERBOSE + fprintf(stderr,"typeinfo_init_from_methoddesc("); + descriptor_debug_print_methoddesc(stderr,desc); + fprintf(stderr,")\n"); +#endif /* check arguments */ - while (utf_ptr != end_pos && *utf_ptr != ')') { + for (i=0; iparamcount; ++i) { if (++args > buflen) - panic("Buffer too small for method arguments."); - - *typebuf++ = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, - CLASSLOAD_NEW - | CLASSLOAD_NULLPRIMITIVE - | CLASSLOAD_NOVOID); - - if (cls) { - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); - - TYPEINFO_INIT_CLASSINFO(*infobuf, cls); - - } else { - TYPEINFO_INIT_PRIMITIVE(*infobuf); - } - infobuf++; + panic("Buffer too small for method arguments."); /* XXX */ + typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++); + if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) { if (++args > buflen) - panic("Buffer too small for method arguments."); + panic("Buffer too small for method arguments."); /* XXX */ *typebuf++ = TYPE_VOID; TYPEINFO_INIT_PRIMITIVE(*infobuf); infobuf++; } } - utf_ptr++; /* skip ')' */ /* check returntype */ if (returntype) { - *returntype = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, - CLASSLOAD_NULLPRIMITIVE - | CLASSLOAD_NEW - | CLASSLOAD_CHECKEND); - - if (returntypeinfo) { - if (cls) { - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); - - TYPEINFO_INIT_CLASSINFO(*returntypeinfo, cls); + typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo); + } +} - } else { - TYPEINFO_INIT_PRIMITIVE(*returntypeinfo); - } - } +void +typedescriptor_init_from_typedesc(typedescriptor *td, + typedesc *desc) +{ + td->type = desc->type; + if (td->type == TYPE_ADR) { + TYPEINFO_INIT_CLASSREF(td->info,desc->classref); + } + else { + TYPEINFO_INIT_PRIMITIVE(td->info); } } int -typedescriptors_init_from_method_args(typedescriptor *td, - utf *desc, - int buflen,bool twoword, - typedescriptor *returntype) +typedescriptors_init_from_methoddesc(typedescriptor *td, + methoddesc *desc, + int buflen,bool twoword, + typedescriptor *returntype) { - char *utf_ptr = desc->text; /* current position in utf text */ - char *end_pos = utf_end(desc); /* points behind utf string */ + int i; int args = 0; - classinfo *cls; - - /* method descriptor must start with parenthesis */ - if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor"); /* check arguments */ - while (utf_ptr != end_pos && *utf_ptr != ')') { + for (i=0; iparamcount; ++i) { if (++args > buflen) - panic("Buffer too small for method arguments."); - - td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, - CLASSLOAD_NEW - | CLASSLOAD_NULLPRIMITIVE - | CLASSLOAD_NOVOID); - - if (cls) { - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); + panic("Buffer too small for method arguments."); /* XXX */ - TYPEINFO_INIT_CLASSINFO(td->info, cls); - - } else { - TYPEINFO_INIT_PRIMITIVE(td->info); - } + typedescriptor_init_from_typedesc(td,desc->paramtypes + i); td++; if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) { if (++args > buflen) - panic("Buffer too small for method arguments."); + panic("Buffer too small for method arguments."); /* XXX */ td->type = TYPE_VOID; TYPEINFO_INIT_PRIMITIVE(td->info); td++; } } - utf_ptr++; /* skip ')' */ /* check returntype */ if (returntype) { - returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr, - CLASSLOAD_NULLPRIMITIVE - | CLASSLOAD_NEW - | CLASSLOAD_CHECKEND); - if (cls) { - if (!cls->loaded) - load_class_bootstrap(cls); - - if (!cls->linked) - link_class(cls); - - TYPEINFO_INIT_CLASSINFO(returntype->info,cls); - - } else { - TYPEINFO_INIT_PRIMITIVE(returntype->info); - } + typedescriptor_init_from_typedesc(returntype,&(desc->returntype)); } + return args; } void typeinfo_init_component(typeinfo *srcarray,typeinfo *dst) { - vftbl_t *comp = NULL; - if (TYPEINFO_IS_NULLTYPE(*srcarray)) { TYPEINFO_INIT_NULLTYPE(*dst); return; } if (!TYPEINFO_IS_ARRAY(*srcarray)) - panic("Trying to access component of non-array"); + panic("Trying to access component of non-array"); /* XXX throw exception */ - comp = srcarray->typeclass->vftbl->arraydesc->componentvftbl; - if (comp) { - TYPEINFO_INIT_CLASSINFO(*dst,comp->class); - } - else { - TYPEINFO_INIT_PRIMITIVE(*dst); - } + if (IS_CLASSREF(srcarray->typeclass)) { + constant_classref *comp; + comp = class_get_classref_component_of(srcarray->typeclass.ref); + + if (comp) + TYPEINFO_INIT_CLASSREF(*dst,comp); + else + TYPEINFO_INIT_PRIMITIVE(*dst); + } + else { + vftbl_t *comp; + + TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl); + TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc); + + comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl; + if (comp) + TYPEINFO_INIT_CLASSINFO(*dst,comp->class); + else + TYPEINFO_INIT_PRIMITIVE(*dst); + } - dst->merged = srcarray->merged; + dst->merged = srcarray->merged; /* XXX should we do a deep copy? */ } void typeinfo_clone(typeinfo *src,typeinfo *dest) { int count; - classinfo **srclist,**destlist; + classref_or_classinfo *srclist,*destlist; if (src == dest) return; @@ -821,32 +896,29 @@ typeinfo_free(typeinfo *info) static void typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) { -#ifdef TYPEINFO_DEBUG +#ifdef TYPEINFO_VERBOSE fprintf(stderr,"Error in typeinfo_merge: %s\n",str); fprintf(stderr,"Typeinfo x:\n"); typeinfo_print(stderr,x,1); fprintf(stderr,"Typeinfo y:\n"); typeinfo_print(stderr,y,1); #endif - panic(str); + panic(str); /* XXX throw an exception */ } /* Condition: clsx != clsy. */ -/* Returns: true if dest was changed (always true). */ +/* Returns: true if dest was changed (currently always true). */ static bool -typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy) +typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy) { TYPEINFO_FREEMERGED_IF_ANY(dest->merged); TYPEINFO_ALLOCMERGED(dest->merged,2); dest->merged->count = 2; -#ifdef TYPEINFO_DEBUG - if (clsx == clsy) - panic("Internal error: typeinfo_merge_two called with clsx==clsy."); -#endif + TYPEINFO_ASSERT(clsx.any != clsy.any); - if (clsx < clsy) { + if (clsx.any < clsy.any) { dest->merged->list[0] = clsx; dest->merged->list[1] = clsy; } @@ -861,18 +933,18 @@ typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy) /* Returns: true if dest was changed. */ static bool -typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls) +typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls) { int count; typeinfo_mergedlist *newmerged; - classinfo **mlist,**newlist; + classref_or_classinfo *mlist,*newlist; count = m->count; mlist = m->list; /* Check if cls is already in the mergedlist m. */ while (count--) { - if (*mlist++ == cls) { + if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */ /* cls is in the list, so m is the resulting mergedlist */ if (dest->merged == m) return false; @@ -898,7 +970,7 @@ typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls) newlist = newmerged->list; mlist = m->list; while (count) { - if (*mlist > cls) + if (mlist->any > cls.any) break; *newlist++ = *mlist++; count--; @@ -924,7 +996,7 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x, int count = 0; int countx,county; typeinfo_mergedlist *temp,*result; - classinfo **clsx,**clsy,**newlist; + classref_or_classinfo *clsx,*clsy,*newlist; /* count the elements that will be in the resulting list */ /* (Both lists are sorted, equal elements are counted only once.) */ @@ -933,13 +1005,13 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x, countx = x->count; county = y->count; while (countx && county) { - if (*clsx == *clsy) { + if (clsx->any == clsy->any) { clsx++; clsy++; countx--; county--; } - else if (*clsx < *clsy) { + else if (clsx->any < clsy->any) { clsx++; countx--; } @@ -989,13 +1061,13 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x, countx = x->count; county = y->count; while (countx && county) { - if (*clsx == *clsy) { + if (clsx->any == clsy->any) { *newlist++ = *clsx++; clsy++; countx--; county--; } - else if (*clsx < *clsy) { + else if (clsx->any < clsy->any) { *newlist++ = *clsx++; countx--; } @@ -1019,30 +1091,25 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x, static bool typeinfo_merge_nonarrays(typeinfo *dest, - classinfo **result, - classinfo *clsx,classinfo *clsy, + classref_or_classinfo *result, + classref_or_classinfo x,classref_or_classinfo y, typeinfo_mergedlist *mergedx, typeinfo_mergedlist *mergedy) { + classref_or_classinfo t; classinfo *tcls,*common; typeinfo_mergedlist *tmerged; bool changed; + utf *xname; + utf *yname; - /* DEBUG */ - /* -#ifdef TYPEINFO_DEBUG - typeinfo dbgx,dbgy; - printf("typeinfo_merge_nonarrays:\n"); - TYPEINFO_INIT_CLASSINFO(dbgx,clsx); - dbgx.merged = mergedx; - TYPEINFO_INIT_CLASSINFO(dbgy,clsy); - dbgy.merged = mergedy; - typeinfo_print(stdout,&dbgx,4); - printf(" with:\n"); - typeinfo_print(stdout,&dbgy,4); -#endif - */ + TYPEINFO_ASSERT(dest && result && x.any && y.any); + TYPEINFO_ASSERT(x.cls != pseudo_class_Null); + TYPEINFO_ASSERT(y.cls != pseudo_class_Null); + TYPEINFO_ASSERT(x.cls != pseudo_class_New); + TYPEINFO_ASSERT(y.cls != pseudo_class_New); +#ifdef XXX /* check clsx */ if (!clsx->loaded) if (!load_class_bootstrap(clsx)) @@ -1060,57 +1127,111 @@ typeinfo_merge_nonarrays(typeinfo *dest, if (!clsy->linked) if (!link_class(clsy)) return false; +#endif + + /*--------------------------------------------------*/ + /* common cases */ + /*--------------------------------------------------*/ - /* Common case: clsx == clsy */ + /* Common case 1: x and y are the same class or class reference */ /* (This case is very simple unless *both* x and y really represent * merges of subclasses of clsx==clsy.) */ - if ((clsx == clsy) && (!mergedx || !mergedy)) { + if ( (x.any == y.any) && (!mergedx || !mergedy) ) { return_simple_x: /* DEBUG */ /* log_text("return simple x"); */ changed = (dest->merged != NULL); TYPEINFO_FREEMERGED_IF_ANY(dest->merged); dest->merged = NULL; - *result = clsx; + *result = x; /* DEBUG */ /* log_text("returning"); */ return changed; } - - /* If clsy is an interface, swap x and y. */ - if (clsy->flags & ACC_INTERFACE) { - tcls = clsx; clsx = clsy; clsy = tcls; + + xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name; + yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name; + + /* Common case 2: xname == yname, at least one unresolved */ + if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname)) + { + /* use the loaded one if any */ + if (!IS_CLASSREF(y)) + x = y; + goto return_simple_x; + } + + /*--------------------------------------------------*/ + /* non-trivial cases */ + /*--------------------------------------------------*/ + +#ifdef TYPEINFO_VERBOSE + { + typeinfo dbgx,dbgy; + fprintf(stderr,"merge_nonarrays:\n"); + TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgx,x); + dbgx.merged = mergedx; + TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgy,y); + dbgy.merged = mergedy; + typeinfo_print(stderr,&dbgx,4); + fprintf(stderr," with:\n"); + typeinfo_print(stderr,&dbgy,4); + } +#endif + + /* If y is unresolved or an interface, swap x and y. */ + if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE)) + { + t = x; x = y; y = t; tmerged = mergedx; mergedx = mergedy; mergedy = tmerged; } + + /* {We know: If only one of x,y is unresolved it is x,} */ + /* { If both x,y are resolved and only one of x,y is an interface it is x.} */ + + if (IS_CLASSREF(x)) { + /* {We know: x and y have different class names} */ + + /* Check if we are merging an unresolved type with java.lang.Object */ + if (y.cls == class_java_lang_Object && !mergedy) { + x = y; + goto return_simple_x; + } + + common = class_java_lang_Object; + goto merge_with_simple_x; + } + + /* {We know: both x and y are resolved} */ /* {We know: If only one of x,y is an interface it is x.} */ /* Handle merging of interfaces: */ - if (clsx->flags & ACC_INTERFACE) { - /* {clsx is an interface and mergedx == NULL.} */ + if (x.cls->flags & ACC_INTERFACE) { + /* {x.cls is an interface and mergedx == NULL.} */ - if (clsy->flags & ACC_INTERFACE) { + if (y.cls->flags & ACC_INTERFACE) { /* We are merging two interfaces. */ /* {mergedy == NULL} */ - /* {We know that clsx!=clsy (see common case at beginning.)} */ - *result = class_java_lang_Object; - return typeinfo_merge_two(dest,clsx,clsy); + /* {We know that x.cls!=y.cls (see common case at beginning.)} */ + result->cls = class_java_lang_Object; + return typeinfo_merge_two(dest,x,y); } - /* {We know: x is an interface, clsy is a class.} */ + /* {We know: x is an interface, y is a class.} */ /* Check if we are merging an interface with java.lang.Object */ - if (clsy == class_java_lang_Object && !mergedy) { - clsx = clsy; + if (y.cls == class_java_lang_Object && !mergedy) { + x = y; goto return_simple_x; } - /* If the type y implements clsx then the result of the merge - * is clsx regardless of mergedy. + /* If the type y implements x then the result of the merge + * is x regardless of mergedy. */ - if (CLASS_IMPLEMENTS_INTERFACE(clsy,clsx->index) - || mergedlist_implements_interface(mergedy,clsx)) + if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index) + || mergedlist_implements_interface(mergedy,x.cls)) { /* y implements x, so the result of the merge is x. */ goto return_simple_x; @@ -1120,7 +1241,7 @@ typeinfo_merge_nonarrays(typeinfo *dest, * of subclasses and does not implement x.} */ /* There may still be superinterfaces of x which are implemented - * by y, too, so we have to add clsx to the mergedlist. + * by y, too, so we have to add x.cls to the mergedlist. */ /* if x has no superinterfaces we could return a simple java.lang.Object */ @@ -1132,16 +1253,16 @@ typeinfo_merge_nonarrays(typeinfo *dest, /* {We know: x and y are classes (not interfaces).} */ /* If *x is deeper in the inheritance hierarchy swap x and y. */ - if (clsx->index > clsy->index) { - tcls = clsx; clsx = clsy; clsy = tcls; + if (x.cls->index > y.cls->index) { + t = x; x = y; y = t; tmerged = mergedx; mergedx = mergedy; mergedy = tmerged; } /* {We know: y is at least as deep in the hierarchy as x.} */ /* Find nearest common anchestor for the classes. */ - common = clsx; - tcls = clsy; + common = x.cls; + tcls = y.cls; while (tcls->index > common->index) tcls = tcls->super; while (common != tcls) { @@ -1149,29 +1270,29 @@ typeinfo_merge_nonarrays(typeinfo *dest, tcls = tcls->super; } - /* {common == nearest common anchestor of clsx and clsy.} */ + /* {common == nearest common anchestor of x and y.} */ - /* If clsx==common and x is a whole class (not a merge of subclasses) - * then the result of the merge is clsx. + /* If x.cls==common and x is a whole class (not a merge of subclasses) + * then the result of the merge is x. */ - if (clsx == common && !mergedx) { + if (x.cls == common && !mergedx) { goto return_simple_x; } if (mergedx) { - *result = common; + result->cls = common; if (mergedy) return typeinfo_merge_mergedlists(dest,mergedx,mergedy); else - return typeinfo_merge_add(dest,mergedx,clsy); + return typeinfo_merge_add(dest,mergedx,y); } - merge_with_simple_x: - *result = common; +merge_with_simple_x: + result->cls = common; if (mergedy) - return typeinfo_merge_add(dest,mergedy,clsx); + return typeinfo_merge_add(dest,mergedy,x); else - return typeinfo_merge_two(dest,clsx,clsy); + return typeinfo_merge_two(dest,x,y); } /* Condition: *dest must be a valid initialized typeinfo. */ @@ -1181,41 +1302,36 @@ bool typeinfo_merge(typeinfo *dest,typeinfo* y) { typeinfo *x; - typeinfo *tmp; /* used for swapping */ - classinfo *common; - classinfo *elementclass; + typeinfo *tmp; + classref_or_classinfo common; + classref_or_classinfo elementclass; int dimension; int elementtype; bool changed; - /* DEBUG */ - /* -#ifdef TYPEINFO_DEBUG - typeinfo_print(stdout,dest,4); - typeinfo_print(stdout,y,4); -#endif - */ + /*--------------------------------------------------*/ + /* fast checks */ + /*--------------------------------------------------*/ /* Merging something with itself is a nop */ if (dest == y) return false; /* Merging two returnAddress types is ok. */ - if (!dest->typeclass && !y->typeclass) { -#ifdef TYPEINFO_DEBUG - if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y)) - panic("Internal error: typeinfo_merge merges different returnAddresses"); -#endif + /* Merging two different returnAddresses never happens, as the verifier */ + /* keeps them separate in order to check all the possible return paths */ + /* from JSR subroutines. */ + if (!dest->typeclass.any && !y->typeclass.any) { + TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) == TYPEINFO_RETURNADDRESS(*y)); return false; } /* Primitive types cannot be merged with reference types */ /* XXX only check this in debug mode? */ - if (!dest->typeclass || !y->typeclass) + if (!dest->typeclass.any || !y->typeclass.any) typeinfo_merge_error("Trying to merge primitive types.",dest,y); /* handle uninitialized object types */ - /* XXX is there a way we could put this after the common case? */ if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) { if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) typeinfo_merge_error("Trying to merge uninitialized object type.",dest,y); @@ -1225,28 +1341,22 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) return false; } - /* DEBUG */ /* log_text("Testing common case"); */ + /*--------------------------------------------------*/ + /* common cases */ + /*--------------------------------------------------*/ - /* Common case: class dest == class y */ + /* Common case: dest and y are the same class or class reference */ /* (This case is very simple unless *both* dest and y really represent * merges of subclasses of class dest==class y.) */ - if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) { + if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) { +return_simple: changed = (dest->merged != NULL); - TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */ + TYPEINFO_FREEMERGED_IF_ANY(dest->merged); dest->merged = NULL; - /* DEBUG */ /* log_text("common case handled"); */ return changed; } -#ifdef TYPEINFO_DEBUG - /* check that no unlinked classes are merged. */ - if (!dest->typeclass->linked || !y->typeclass->linked) - typeinfo_merge_error("Trying to merge unlinked class(es).",dest,y); -#endif - - /* DEBUG */ /* log_text("Handling null types"); */ - /* Handle null types: */ if (TYPEINFO_IS_NULLTYPE(*y)) { return false; @@ -1257,6 +1367,36 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) return true; } + /* Common case: two types with the same name, at least one unresolved */ + if (IS_CLASSREF(dest->typeclass)) { + if (IS_CLASSREF(y->typeclass)) { + if (dest->typeclass.ref->name == y->typeclass.ref->name) + goto return_simple; + } + else { + /* XXX should we take y instead of dest here? */ + if (dest->typeclass.ref->name == y->typeclass.cls->name) + goto return_simple; + } + } + else { + if (IS_CLASSREF(y->typeclass) + && (dest->typeclass.cls->name == y->typeclass.ref->name)) + { + goto return_simple; + } + } + + /*--------------------------------------------------*/ + /* non-trivial cases */ + /*--------------------------------------------------*/ + +#ifdef TYPEINFO_VERBOSE + fprintf(stderr,"merge:\n"); + typeinfo_print(stderr,dest,4); + typeinfo_print(stderr,y,4); +#endif + /* This function uses x internally, so x and y can be swapped * without changing dest. */ x = dest; @@ -1265,8 +1405,6 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) /* Handle merging of arrays: */ if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) { - /* DEBUG */ /* log_text("Handling arrays"); */ - /* Make x the one with lesser dimension */ if (x->dimension > y->dimension) { tmp = x; x = y; y = tmp; @@ -1277,7 +1415,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) if (x->dimension < y->dimension) { dimension = x->dimension; elementtype = ARRAYTYPE_OBJECT; - elementclass = pseudo_class_Arraystub; + elementclass.cls = pseudo_class_Arraystub; } else { dimension = y->dimension; @@ -1291,14 +1429,14 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) /* Different element types are merged, so the resulting array * type has one accessible dimension less. */ if (--dimension == 0) { - common = pseudo_class_Arraystub; + common.cls = pseudo_class_Arraystub; elementtype = 0; - elementclass = NULL; + elementclass.any = NULL; } else { - common = class_multiarray_of(dimension,pseudo_class_Arraystub); + common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub); elementtype = ARRAYTYPE_OBJECT; - elementclass = pseudo_class_Arraystub; + elementclass.cls = pseudo_class_Arraystub; } } else { @@ -1315,9 +1453,15 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) x->merged,y->merged); /* DEBUG */ /* log_text("finding resulting array class: "); */ - common = class_multiarray_of(dimension,elementclass); + if (IS_CLASSREF(elementclass)) + common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref); + else + common.cls = class_multiarray_of(dimension,elementclass.cls); /* DEBUG */ /* utf_display(common->name); printf("\n"); */ } + else { + common.any = y->typeclass.any; + } } } else { @@ -1331,13 +1475,13 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) dimension = 0; elementtype = 0; - elementclass = NULL; + elementclass.any = NULL; } /* Put the new values into dest if neccessary. */ - if (dest->typeclass != common) { - dest->typeclass = common; + if (dest->typeclass.any != common.any) { + dest->typeclass.any = common.any; changed = true; } if (dest->dimension != dimension) { @@ -1348,13 +1492,11 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) dest->elementtype = elementtype; changed = true; } - if (dest->elementclass != elementclass) { - dest->elementclass = elementclass; + if (dest->elementclass.any != elementclass.any) { + dest->elementclass.any = elementclass.any; changed = true; } - /* DEBUG */ /* log_text("returning from merge"); */ - return changed; } @@ -1365,17 +1507,15 @@ typeinfo_merge(typeinfo *dest,typeinfo* y) #ifdef TYPEINFO_DEBUG - -/*extern instruction *instr;*/ - static int -typeinfo_test_compare(classinfo **a,classinfo **b) +typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b) { - if (*a == *b) return 0; - if (*a < *b) return -1; + if (a->any == b->any) return 0; + if (a->any < b->any) return -1; return +1; } +#if 0 static void typeinfo_test_parse(typeinfo *info,char *str) { @@ -1400,9 +1540,9 @@ typeinfo_test_parse(typeinfo *info,char *str) for (i=0; imerged->list[i] = infobuf[i].typeclass; + info->merged->list[i].any = infobuf[i].typeclass.any; } - qsort(info->merged->list,num,sizeof(classinfo*), + qsort(info->merged->list,num,sizeof(classref_or_classinfo), (int(*)(const void *,const void *))&typeinfo_test_compare); } else { @@ -1410,6 +1550,7 @@ typeinfo_test_parse(typeinfo *info,char *str) &returntype,info); } } +#endif #define TYPEINFO_TEST_BUFLEN 4000 @@ -1418,10 +1559,10 @@ typeinfo_equal(typeinfo *x,typeinfo *y) { int i; - if (x->typeclass != y->typeclass) return false; + if (x->typeclass.any != y->typeclass.any) return false; if (x->dimension != y->dimension) return false; if (x->dimension) { - if (x->elementclass != y->elementclass) return false; + if (x->elementclass.any != y->elementclass.any) return false; if (x->elementtype != y->elementtype) return false; } @@ -1434,7 +1575,7 @@ typeinfo_equal(typeinfo *x,typeinfo *y) if (!(x->merged && y->merged)) return false; if (x->merged->count != y->merged->count) return false; for (i=0; imerged->count; ++i) - if (x->merged->list[i] != y->merged->list[i]) + if (x->merged->list[i].any != y->merged->list[i].any) return false; } return true; @@ -1479,6 +1620,7 @@ typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed) } } +#if 0 static void typeinfo_inc_dimension(typeinfo *info) { @@ -1488,6 +1630,7 @@ typeinfo_inc_dimension(typeinfo *info) } info->typeclass = class_array_of(info->typeclass); } +#endif #define TYPEINFO_TEST_MAXDIM 10 @@ -1514,11 +1657,14 @@ typeinfo_testrun(char *filename) res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc); if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) panic("Invalid line in typeinfo test file (none of empty, comment or test)"); - +#if 0 typeinfo_test_parse(&a,bufa); typeinfo_test_parse(&b,bufb); typeinfo_test_parse(&c,bufc); +#endif +#if 0 do { +#endif typeinfo_testmerge(&a,&b,&c,&failed); /* check result */ typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */ @@ -1530,12 +1676,14 @@ typeinfo_testrun(char *filename) if (b.dimension > maxdim) maxdim = b.dimension; if (c.dimension > maxdim) maxdim = c.dimension; +#if 0 if (maxdim < TYPEINFO_TEST_MAXDIM) { typeinfo_inc_dimension(&a); typeinfo_inc_dimension(&b); typeinfo_inc_dimension(&c); } } while (maxdim < TYPEINFO_TEST_MAXDIM); +#endif } fclose(file); @@ -1554,14 +1702,35 @@ typeinfo_test() log_text("Finished typeinfo test file."); } +#if 0 void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc) { typeinfo_init_from_descriptor(info,desc,desc+strlen(desc)); } +#endif #define TYPEINFO_MAXINDENT 80 +void +typeinfo_print_class(FILE *file,classref_or_classinfo c) +{ + /*fprintf(file,"",c.any);*/ + + if (!c.any) { + fprintf(file,""); + } + else { + if (IS_CLASSREF(c)) { + fprintf(file,""); + utf_fprint(file,c.ref->name); + } + else { + utf_fprint(file,c.cls->name); + } + } +} + void typeinfo_print(FILE *file,typeinfo *info,int indent) { @@ -1593,8 +1762,8 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) if (TYPEINFO_IS_NEWOBJECT(*info)) { ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info); if (ins) { - fprintf(file,"%sNEW(%d):",ind,ins-bptr->iinstr); - utf_fprint(file,((classinfo *)ins[-1].val.a)->name); + fprintf(file,"%sNEW(%p):",ind,ins); + typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a)); fprintf(file,"\n"); } else { @@ -1604,7 +1773,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) } fprintf(file,"%sClass: ",ind); - utf_fprint(file,info->typeclass->name); + typeinfo_print_class(file,info->typeclass); fprintf(file,"\n"); if (TYPEINFO_IS_ARRAY(*info)) { @@ -1621,8 +1790,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break; case ARRAYTYPE_OBJECT: - fprintf(file,"reference: "); - utf_fprint(file,info->elementclass->name); + typeinfo_print_class(file,info->elementclass); fprintf(file,"\n"); break; @@ -1632,10 +1800,10 @@ typeinfo_print(FILE *file,typeinfo *info,int indent) } if (info->merged) { - fprintf(file,"%sMerged: ",ind); + fprintf(file,"%sMerged: ",ind); for (i=0; imerged->count; ++i) { if (i) fprintf(file,", "); - utf_fprint(file,info->merged->list[i]->name); + typeinfo_print_class(file,info->merged->list[i]); } fprintf(file,"\n"); } @@ -1647,6 +1815,14 @@ typeinfo_print_short(FILE *file,typeinfo *info) int i; instruction *ins; basicblock *bptr; + classref_or_classinfo c; + + /*fprintf(file,"",info);*/ + + if (!info) { + fprintf(file,"(typeinfo*)NULL"); + return; + } if (TYPEINFO_IS_PRIMITIVE(*info)) { bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info); @@ -1665,21 +1841,22 @@ typeinfo_print_short(FILE *file,typeinfo *info) if (TYPEINFO_IS_NEWOBJECT(*info)) { ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info); if (ins) { - fprintf(file,"NEW(%d):",ins-bptr->iinstr); - utf_fprint(file,((classinfo *)ins[-1].val.a)->name); + /*fprintf(file,"",ins);*/ + fprintf(file,"NEW(%p):",ins); + typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a)); } else fprintf(file,"NEW(this)"); return; } - utf_fprint(file,info->typeclass->name); + typeinfo_print_class(file,info->typeclass); if (info->merged) { fprintf(file,"{"); for (i=0; imerged->count; ++i) { if (i) fprintf(file,","); - utf_fprint(file,info->merged->list[i]->name); + typeinfo_print_class(file,info->merged->list[i]); } fprintf(file,"}"); } @@ -1706,6 +1883,8 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info) void typeinfo_print_stacktype(FILE *file,int type,typeinfo *info) { + TYPEINFO_ASSERT(file); + TYPEINFO_ASSERT(type != TYPE_ADDRESS || info != NULL); if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) { typeinfo_retaddr_set *set = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info); diff --git a/src/vm/jit/verify/typeinfo.h b/src/vm/jit/verify/typeinfo.h index 3e69cbe3c..4601b56db 100644 --- a/src/vm/jit/verify/typeinfo.h +++ b/src/vm/jit/verify/typeinfo.h @@ -26,15 +26,43 @@ Authors: Edwin Steiner - $Id: typeinfo.h 2087 2005-03-25 20:14:29Z edwin $ + $Id: typeinfo.h 2181 2005-04-01 16:53:33Z edwin $ */ - #ifndef _TYPEINFO_H #define _TYPEINFO_H #include "vm/global.h" +#include "vm/references.h" + +/* configuration **************************************************************/ + +/* + * TYPECHECK_STATISTICS activates gathering statistical information. + * TYPEINFO_DEBUG activates debug checks and debug helpers in typeinfo.c + * TYPECHECK_DEBUG activates debug checks in typecheck.c + * TYPEINFO_DEBUG_TEST activates the typeinfo test at startup. + * TYPECHECK_VERBOSE_IMPORTANT activates important debug messages + * TYPECHECK_VERBOSE activates all debug messages + * TYPEINFO_VERBOSE activates debug prints in typeinfo.c + */ +#ifdef CACAO_TYPECHECK +/*#define TYPECHECK_STATISTICS*/ +#define TYPEINFO_DEBUG +/*#define TYPEINFO_VERBOSE*/ +#define TYPECHECK_DEBUG +/*#define TYPEINFO_DEBUG_TEST +#define TYPECHECK_VERBOSE +#define TYPECHECK_VERBOSE_IMPORTANT*/ +#if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT) +#define TYPECHECK_VERBOSE_OPT +#endif +#endif + +#ifdef TYPECHECK_VERBOSE_OPT +extern bool typecheckverbose; +#endif /* resolve typedef cycles *****************************************************/ @@ -44,6 +72,22 @@ typedef struct typedescriptor typedescriptor; typedef struct typevector typevector; typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; +/* constants ******************************************************************/ + +#define MAYBE 2 + +#if MAYBE == true +#error "`MAYBE` must not be the same as `true`" +#endif +#if MAYBE == false +#error "`MAYBE` must not be the same as `false`" +#endif + +/* types **********************************************************************/ + +/* a tristate_t is one of {true,false,MAYBE} */ +typedef int tristate_t; + /* data structures for the type system ****************************************/ /* The typeinfo structure stores detailed information on address types. @@ -132,45 +176,45 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * 1) pseudo_class_Arraystub * 2) an unresolved type * 3) a loaded interface - * 4) a loaded (non-pseudo-,non-array-)class != java.lang.Object + * 4) a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object * Note: `merged` may be used - * 5) java.lang.Object + * 5) (BOOTSTRAP)java.lang.Object * Note: `merged` may be used * * For the semantics of the merged field in cases 4) and 5) consult the * corresponding descriptions with `elementclass` replaced by `typeclass`. * - * X) typeclass is an unresolved type (a symbolic class/interface reference) + * F) typeclass is an unresolved type (a symbolic class/interface reference) * * The type has not been resolved yet. (Meaning it corresponds to an * unloaded class or interface). * Don't access other fields of the struct. * - * F) typeclass is a loaded interface + * G) typeclass is a loaded interface * * An interface reference type. * Don't access other fields of the struct. * - * G) typeclass is a loaded (non-pseudo-,non-array-)class != java.lang.Object + * H) typeclass is a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object * * A loaded class type. - * All classinfos in u.merged.list (if any) are + * All classref_or_classinfos in u.merged.list (if any) are * loaded subclasses of typeclass (no interfaces, array classes, or * unresolved types). * Don't access other fields of the struct. * - * H) typeclass is (BOOTSTRAP)java.lang.Object + * I) typeclass is (BOOTSTRAP)java.lang.Object * * The most general kind of reference type. * In this case u.merged.count and u.merged.list * are valid and may be non-zero. - * The classinfos in u.merged.list (if any) may be + * The classref_or_classinfos in u.merged.list (if any) may be * classes, interfaces, pseudo classes or unresolved types. * Don't access other fields of the struct. */ /* The following algorithm is used to determine if the type described - * by this typeinfo struct supports the interface X: + * by this typeinfo struct supports the interface X: * XXX add MAYBE * * * 1) If typeclass is X or a subinterface of X the answer is "yes". * 2) If typeclass is a (pseudo) class implementing X the answer is "yes". @@ -186,16 +230,16 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * access typeinfo structures! */ struct typeinfo { - classinfo *typeclass; - classinfo *elementclass; /* valid if dimension>0 */ /* various uses! */ - typeinfo_mergedlist *merged; - u1 dimension; - u1 elementtype; /* valid if dimension>0 */ + classref_or_classinfo typeclass; + classref_or_classinfo elementclass; /* valid if dimension>0 */ /* various uses! */ + typeinfo_mergedlist *merged; + u1 dimension; + u1 elementtype; /* valid if dimension>0 */ }; struct typeinfo_mergedlist { - s4 count; - classinfo *list[1]; /* variable length! */ + s4 count; + classref_or_classinfo list[1]; /* variable length! */ }; /*-----------------------------------------------------------------------*/ @@ -287,24 +331,24 @@ struct typevector { /* macros for type queries **************************************************/ #define TYPEINFO_IS_PRIMITIVE(info) \ - ((info).typeclass == NULL) + ((info).typeclass.any == NULL) #define TYPEINFO_IS_REFERENCE(info) \ - ((info).typeclass != NULL) + ((info).typeclass.any != NULL) #define TYPEINFO_IS_NULLTYPE(info) \ - ((info).typeclass == pseudo_class_Null) + ((info).typeclass.cls == pseudo_class_Null) #define TYPEINFO_IS_NEWOBJECT(info) \ - ((info).typeclass == pseudo_class_New) + ((info).typeclass.cls == pseudo_class_New) /* only use this if TYPEINFO_IS_PRIMITIVE returned true! */ #define TYPEINFO_RETURNADDRESS(info) \ - ((void *)(info).elementclass) + ((void *)(info).elementclass.any) /* only use this if TYPEINFO_IS_NEWOBJECT returned true! */ #define TYPEINFO_NEWOBJECT_INSTRUCTION(info) \ - ((void *)(info).elementclass) + ((void *)(info).elementclass.any) /* macros for array type queries ********************************************/ @@ -324,11 +368,11 @@ struct typevector { #define TYPEINFO_IS_OBJECT_ARRAY(info) \ ( TYPEINFO_IS_SIMPLE_ARRAY(info) \ - && ((info).elementclass != NULL) ) + && ((info).elementclass.any != NULL) ) /* assumes that info describes an array type */ #define TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) \ - ( ((info).elementclass != NULL) \ + ( ((info).elementclass.any != NULL) \ || ((info).dimension >= 2) ) #define TYPEINFO_IS_ARRAY_OF_REFS(info) \ @@ -363,22 +407,22 @@ struct typevector { /* macros for initializing typeinfo structures ******************************/ #define TYPEINFO_INIT_PRIMITIVE(info) \ - do {(info).typeclass = NULL; \ - (info).elementclass = NULL; \ + do {(info).typeclass.any = NULL; \ + (info).elementclass.any = NULL; \ (info).merged = NULL; \ (info).dimension = 0; \ (info).elementtype = 0;} while(0) #define TYPEINFO_INIT_RETURNADDRESS(info,adr) \ - do {(info).typeclass = NULL; \ - (info).elementclass = (classinfo*) (adr); \ + do {(info).typeclass.any = NULL; \ + (info).elementclass.any = (adr); \ (info).merged = NULL; \ (info).dimension = 0; \ (info).elementtype = 0;} while(0) #define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo) \ - do {(info).typeclass = (cinfo); \ - (info).elementclass = NULL; \ + do {(info).typeclass.cls = (cinfo); \ + (info).elementclass.any = NULL; \ (info).merged = NULL; \ (info).dimension = 0; \ (info).elementtype = 0;} while(0) @@ -387,8 +431,8 @@ struct typevector { TYPEINFO_INIT_CLASSINFO(info,pseudo_class_Null) #define TYPEINFO_INIT_NEWOBJECT(info,instr) \ - do {(info).typeclass = pseudo_class_New; \ - (info).elementclass = (classinfo*) (instr);\ + do {(info).typeclass.cls = pseudo_class_New; \ + (info).elementclass.any = (instr); \ (info).merged = NULL; \ (info).dimension = 0; \ (info).elementtype = 0;} while(0) @@ -396,25 +440,27 @@ struct typevector { #define TYPEINFO_INIT_PRIMITIVE_ARRAY(info,arraytype) \ TYPEINFO_INIT_CLASSINFO(info,primitivetype_table[arraytype].arrayclass); -#define TYPEINFO_INIT_CLASSINFO(info,cls) \ - do {if (((info).typeclass = (cls))->vftbl->arraydesc) { \ - if ((cls)->vftbl->arraydesc->elementvftbl) \ - (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \ +#define TYPEINFO_INIT_CLASSINFO(info,c) \ + do {if (((info).typeclass.cls = (c))->vftbl->arraydesc) { \ + if ((c)->vftbl->arraydesc->elementvftbl) \ + (info).elementclass.cls = (c)->vftbl->arraydesc->elementvftbl->class; \ else \ - (info).elementclass = NULL; \ - (info).dimension = (cls)->vftbl->arraydesc->dimension; \ - (info).elementtype = (cls)->vftbl->arraydesc->elementtype; \ + (info).elementclass.any = NULL; \ + (info).dimension = (c)->vftbl->arraydesc->dimension; \ + (info).elementtype = (c)->vftbl->arraydesc->elementtype;\ } \ else { \ - (info).elementclass = NULL; \ + (info).elementclass.any = NULL; \ (info).dimension = 0; \ (info).elementtype = 0; \ } \ (info).merged = NULL;} while(0) -#define TYPEINFO_INIT_FROM_FIELDINFO(info,fi) \ - typeinfo_init_from_descriptor(&(info), \ - (fi)->descriptor->text,utf_end((fi)->descriptor)); +#define TYPEINFO_INIT_CLASSREF(info,c) \ + typeinfo_init_class(&(info),CLASSREF_OR_CLASSINFO(c)) + +#define TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(info,c) \ + typeinfo_init_class(&(info),c) /* macros for copying types (destinition is not checked or freed) ***********/ @@ -447,7 +493,7 @@ int typevectorset_mergedtype(typevector *set,int index,typeinfo *temp,typeinfo * void typevectorset_store(typevector *set,int index,int type,typeinfo *info); void typevectorset_store_retaddr(typevector *set,int index,typeinfo *info); void typevectorset_store_twoword(typevector *set,int index,int type); -void typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,int size); +void typevectorset_init_object(typevector *set,void *ins,classref_or_classinfo initclass,int size); /* vector functions */ bool typevector_separable_from(typevector *a,typevector *b,int size); @@ -466,31 +512,35 @@ bool typeinfo_is_array(typeinfo *info); bool typeinfo_is_primitive_array(typeinfo *info,int arraytype); bool typeinfo_is_array_of_refs(typeinfo *info); -bool typeinfo_implements_interface(typeinfo *info,classinfo *interf); -bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest); -bool typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest); +tristate_t typeinfo_implements_interface(typeinfo *info,classinfo *interf); +tristate_t typeinfo_is_assignable(typeinfo *value,typeinfo *dest); +tristate_t typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest); /* initialization functions *************************************************/ -void typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr); +bool typeinfo_init_class(typeinfo *info,classref_or_classinfo c); void typeinfo_init_component(typeinfo *srcarray,typeinfo *dst); -int typeinfo_count_method_args(utf *d,bool twoword); /* this not included */ -void typeinfo_init_from_method_args(utf *desc,u1 *typebuf, - typeinfo *infobuf, - int buflen,bool twoword, - int *returntype,typeinfo *returntypeinfo); -int typedescriptors_init_from_method_args(typedescriptor *td, - utf *desc, - int buflen,bool twoword, - typedescriptor *returntype); +void typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info); +void typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf, + typeinfo *infobuf, + int buflen,bool twoword, + u1 *returntype,typeinfo *returntypeinfo); +void typedescriptor_init_from_typedesc(typedescriptor *td, + typedesc *desc); +int typedescriptors_init_from_methoddesc(typedescriptor *td, + methoddesc *desc, + int buflen,bool twoword, + typedescriptor *returntype); void typeinfo_clone(typeinfo *src,typeinfo *dest); -/* functions for the type system ********************************************/ +/* freeing memory ***********************************************************/ void typeinfo_free(typeinfo *info); +/* functions for merging types **********************************************/ + bool typeinfo_merge(typeinfo *dest,typeinfo* y); /* debugging helpers ********************************************************/ @@ -500,7 +550,7 @@ bool typeinfo_merge(typeinfo *dest,typeinfo* y); #include void typeinfo_test(); -void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc); +void typeinfo_print_class(FILE *file,classref_or_classinfo c); void typeinfo_print(FILE *file,typeinfo *info,int indent); void typeinfo_print_short(FILE *file,typeinfo *info); void typeinfo_print_type(FILE *file,int type,typeinfo *info); diff --git a/src/vm/linker.c b/src/vm/linker.c index 4ff12a5ac..cb89bcf35 100644 --- a/src/vm/linker.c +++ b/src/vm/linker.c @@ -32,7 +32,7 @@ Edwin Steiner Christian Thalinger - $Id: linker.c 2169 2005-03-31 15:50:57Z twisti $ + $Id: linker.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -975,6 +975,43 @@ static s4 class_highestinterface(classinfo *c) } +/***************** Function: print_arraydescriptor **************************** + + Debugging helper for displaying an arraydescriptor + +*******************************************************************************/ + +void print_arraydescriptor(FILE *file, arraydescriptor *desc) +{ + if (!desc) { + fprintf(file, ""); + return; + } + + fprintf(file, "{"); + if (desc->componentvftbl) { + if (desc->componentvftbl->class) + utf_fprint(file, desc->componentvftbl->class->name); + else + fprintf(file, ""); + } + else + fprintf(file, "0"); + + fprintf(file, ","); + if (desc->elementvftbl) { + if (desc->elementvftbl->class) + utf_fprint(file, desc->elementvftbl->class->name); + else + fprintf(file, ""); + } + else + fprintf(file, "0"); + fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension, + desc->dataoffset, desc->componentsize); +} + + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/src/vm/linker.h b/src/vm/linker.h index cd77fcec4..44e10dc54 100644 --- a/src/vm/linker.h +++ b/src/vm/linker.h @@ -28,7 +28,7 @@ Changes: - $Id: linker.h 2148 2005-03-30 16:49:40Z twisti $ + $Id: linker.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -42,7 +42,7 @@ typedef struct arraydescriptor arraydescriptor; typedef struct primitivetypeinfo primitivetypeinfo; -#include "vm/class.h" +#include "vm/references.h" /* virtual function table ****************************************************** @@ -163,6 +163,9 @@ extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT]; bool linker_init(void); classinfo *link_class(classinfo *c); +/* debug print arraydescriptor */ +void print_arraydescriptor(FILE *file, arraydescriptor *desc); + #endif /* _LINKER_H */ diff --git a/src/vm/loader.c b/src/vm/loader.c index aad9a25a9..fb7233f75 100644 --- a/src/vm/loader.c +++ b/src/vm/loader.c @@ -32,7 +32,7 @@ Edwin Steiner Christian Thalinger - $Id: loader.c 2155 2005-03-30 20:04:42Z twisti $ + $Id: loader.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -927,7 +927,7 @@ u4 class_constanttype(classinfo *c, u4 pos) *******************************************************************************/ -static bool load_constantpool(classbuffer *cb) +static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool) { /* The following structures are used to save information which cannot be @@ -1227,6 +1227,18 @@ static bool load_constantpool(classbuffer *cb) } /* end switch */ } /* end while */ + /* add all class references to the descriptor_pool */ + for (nfc=forward_classes; nfc; nfc=nfc->next) { + utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8); + if (!descriptor_pool_add_class(descpool,name)) + return false; + } + /* add all descriptors in NameAndTypes to the descriptor_pool */ + for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) { + utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8); + if (!descriptor_pool_add(descpool,desc)) + return false; + } /* resolve entries in temporary structures */ @@ -1373,7 +1385,7 @@ static bool load_constantpool(classbuffer *cb) #define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */ -static bool load_field(classbuffer *cb, fieldinfo *f) +static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool) { classinfo *c; u4 attrnum, i; @@ -1395,6 +1407,9 @@ static bool load_field(classbuffer *cb, fieldinfo *f) if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) return false; f->descriptor = u; + f->parseddesc = NULL; + if (!descriptor_pool_add(descpool,u)) + return false; if (opt_verify) { /* check name */ @@ -1561,7 +1576,7 @@ static bool load_field(classbuffer *cb, fieldinfo *f) *******************************************************************************/ -static bool load_method(classbuffer *cb, methodinfo *m) +static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool) { classinfo *c; s4 argcount; @@ -1599,6 +1614,9 @@ static bool load_method(classbuffer *cb, methodinfo *m) if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8))) return false; m->descriptor = u; + m->parseddesc = NULL; + if (!descriptor_pool_add(descpool,u)) + return false; if (opt_verify) { if (!is_valid_name_utf(m->name)) @@ -1966,43 +1984,6 @@ static bool load_attributes(classbuffer *cb, u4 num) } -/***************** Function: print_arraydescriptor **************************** - - Debugging helper for displaying an arraydescriptor - -*******************************************************************************/ - -void print_arraydescriptor(FILE *file, arraydescriptor *desc) -{ - if (!desc) { - fprintf(file, ""); - return; - } - - fprintf(file, "{"); - if (desc->componentvftbl) { - if (desc->componentvftbl->class) - utf_fprint(file, desc->componentvftbl->class->name); - else - fprintf(file, ""); - } - else - fprintf(file, "0"); - - fprintf(file, ","); - if (desc->elementvftbl) { - if (desc->elementvftbl->class) - utf_fprint(file, desc->elementvftbl->class->name); - else - fprintf(file, ""); - } - else - fprintf(file, "0"); - fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension, - desc->dataoffset, desc->componentsize); -} - - /* load_class_from_classloader ************************************************* XXX @@ -2150,7 +2131,13 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) classinfo *tc; u4 i; u4 ma, mi; + s4 dumpsize; + descriptor_pool *descpool; char msg[MAXLOGTEXT]; /* maybe we get an exception */ +#if defined(STATISTICS) + u4 classrefsize; + u4 descsize; +#endif /* get the classbuffer's class */ c = cb->class; @@ -2168,17 +2155,20 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (loadverbose) log_message_class("Loading class: ", c); + /* mark start of dump memory area */ + dumpsize = dump_size(); + /* class is somewhat loaded */ c->loaded = true; if (!check_classbuffer_size(cb, 4 + 2 + 2)) - return NULL; + goto return_exception; /* check signature */ if (suck_u4(cb) != MAGIC) { *exceptionptr = new_classformaterror(c, "Bad magic number"); - return NULL; + goto return_exception; } /* check version */ @@ -2191,12 +2181,15 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) "Unsupported major.minor version %d.%d", ma, mi); - return NULL; + goto return_exception; } + /* create a new descriptor pool */ + descpool = descriptor_pool_new(c); + /* load the constant pool */ - if (!load_constantpool(cb)) - return NULL; + if (!load_constantpool(cb,descpool)) + goto return_exception; /*JOWENN*/ c->erroneous_state = 0; @@ -2207,7 +2200,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) /* ACC flags */ if (!check_classbuffer_size(cb, 2)) - return NULL; + goto return_exception; c->flags = suck_u2(cb); /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/ @@ -2227,7 +2220,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags); - return NULL; + goto return_exception; } if (c->flags & ACC_SUPER) { @@ -2239,16 +2232,16 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) *exceptionptr = new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags); - return NULL; + goto return_exception; } if (!check_classbuffer_size(cb, 2 + 2)) - return NULL; + goto return_exception; /* this class */ i = suck_u2(cb); if (!(tc = class_getconstant(c, i, CONSTANT_Class))) - return NULL; + goto return_exception; if (tc != c) { utf_sprint(msg, c->name); @@ -2259,13 +2252,13 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) *exceptionptr = new_exception_message(string_java_lang_NoClassDefFoundError, msg); - return NULL; + goto return_exception; } /* retrieve superclass */ if ((i = suck_u2(cb))) { if (!(c->super = class_getconstant(c, i, CONSTANT_Class))) - return NULL; + goto return_exception; /* java.lang.Object may not have a super class. */ if (c->name == utf_java_lang_Object) { @@ -2273,7 +2266,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) new_exception_message(string_java_lang_ClassFormatError, "java.lang.Object with superclass"); - return NULL; + goto return_exception; } /* Interfaces must have java.lang.Object as super class. */ @@ -2283,7 +2276,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) new_exception_message(string_java_lang_ClassFormatError, "Interfaces must have java.lang.Object as superclass"); - return NULL; + goto return_exception; } } else { @@ -2293,47 +2286,100 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (c->name != utf_java_lang_Object) { *exceptionptr = new_classformaterror(c, "Bad superclass index"); - return NULL; + goto return_exception; } } /* retrieve interfaces */ if (!check_classbuffer_size(cb, 2)) - return NULL; + goto return_exception; c->interfacescount = suck_u2(cb); if (!check_classbuffer_size(cb, 2 * c->interfacescount)) - return NULL; + goto return_exception; c->interfaces = MNEW(classinfo*, c->interfacescount); for (i = 0; i < c->interfacescount; i++) { if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class))) - return NULL; + goto return_exception; } /* load fields */ if (!check_classbuffer_size(cb, 2)) - return NULL; + goto return_exception; c->fieldscount = suck_u2(cb); c->fields = GCNEW(fieldinfo, c->fieldscount); /* c->fields = MNEW(fieldinfo, c->fieldscount); */ for (i = 0; i < c->fieldscount; i++) { - if (!load_field(cb, &(c->fields[i]))) - return NULL; + if (!load_field(cb, &(c->fields[i]),descpool)) + goto return_exception; } /* load methods */ if (!check_classbuffer_size(cb, 2)) - return NULL; + goto return_exception; c->methodscount = suck_u2(cb); /* c->methods = GCNEW(methodinfo, c->methodscount); */ c->methods = MNEW(methodinfo, c->methodscount); for (i = 0; i < c->methodscount; i++) { - if (!load_method(cb, &(c->methods[i]))) - return NULL; + if (!load_method(cb, &(c->methods[i]),descpool)) + goto return_exception; + } + + /* create the class reference table */ + c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount)); + + /* allocate space for the parsed descriptors */ + descriptor_pool_alloc_parsed_descriptors(descpool); + c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize)); + +#if defined(STATISTICS) + if (opt_stat) { + descriptor_pool_get_sizes(descpool,&classrefsize,&descsize); + count_classref_len += classrefsize; + count_parsed_desc_len += descsize; + } +#endif + + /* parse the loaded descriptors */ + for (i=0; icpcount; ++i) { + constant_FMIref *fmi; + + switch (c->cptags[i]) { + case CONSTANT_Class: + /* XXX set classref */ + break; + case CONSTANT_Fieldref: + fmi = (constant_FMIref *)c->cpinfos[i]; + fmi->parseddesc.fd = + descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor); + if (!fmi->parseddesc.fd) + goto return_exception; + fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name); + break; + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + fmi = (constant_FMIref *)c->cpinfos[i]; + fmi->parseddesc.md = + descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor); + if (!fmi->parseddesc.md) + goto return_exception; + fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name); + break; + } + } + for (i = 0; i < c->fieldscount; i++) { + c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor); + if (!c->fields[i].parseddesc) + goto return_exception; + } + for (i = 0; i < c->methodscount; i++) { + c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor); + if (!c->methods[i].parseddesc) + goto return_exception; } /* Check if all fields and methods can be uniquely @@ -2386,7 +2432,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) new_classformaterror(c, "Repetitive field name/signature"); - return NULL; + goto return_exception; } } while ((old = next[old])); } @@ -2420,7 +2466,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) new_classformaterror(c, "Repetitive method name/signature"); - return NULL; + goto return_exception; } } while ((old = next[old])); } @@ -2440,10 +2486,10 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) /* load attribute structures */ if (!check_classbuffer_size(cb, 2)) - return NULL; + goto return_exception; if (!load_attributes(cb, suck_u2(cb))) - return NULL; + goto return_exception; #if 0 /* Pre java 1.5 version don't check this. This implementation is like @@ -2457,15 +2503,25 @@ classinfo *load_class_from_classbuffer(classbuffer *cb) if (classdata_left > 0) { *exceptionptr = new_classformaterror(c, "Extra bytes at the end of class file"); - return NULL; + goto return_exception; } } #endif + /* release dump area */ + dump_release(dumpsize); + if (loadverbose) log_message_class("Loading done class: ", c); return c; + +return_exception: + /* release dump area */ + dump_release(dumpsize); + + /* an exception has been thrown */ + return NULL; } @@ -2480,6 +2536,8 @@ void class_new_array(classinfo *c) { classinfo *comp = NULL; methodinfo *clone; + methoddesc *clonedesc; + constant_classref *classrefs; int namelen; /* Check array class name */ @@ -2547,11 +2605,22 @@ void class_new_array(classinfo *c) c->methodscount = 1; c->methods = MNEW(methodinfo, c->methodscount); + classrefs = MNEW(constant_classref,1); + CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object); + + clonedesc = NEW(methoddesc); + clonedesc->returntype.type = TYPE_ADDRESS; + clonedesc->returntype.classref = classrefs; + clonedesc->returntype.arraydim = 0; + clonedesc->paramcount = 0; + clonedesc->paramslots = 0; + clone = c->methods; MSET(clone, 0, methodinfo, 1); clone->flags = ACC_PUBLIC; clone->name = utf_new_char("clone"); clone->descriptor = utf_void__java_lang_Object; + clone->parseddesc = clonedesc; clone->class = c; clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone); clone->monoPoly = MONO; @@ -2560,6 +2629,12 @@ void class_new_array(classinfo *c) /* array classes are not loaded from class files */ c->loaded = true; + c->parseddescs = (u1*) clonedesc; + c->parseddescsize = sizeof(methodinfo); + c->classrefs = classrefs; + c->classrefcount = 1; + + /* XXX insert class into the loaded class cache */ } diff --git a/src/vm/loader.h b/src/vm/loader.h index 52dd1f53f..569c8255e 100644 --- a/src/vm/loader.h +++ b/src/vm/loader.h @@ -26,7 +26,7 @@ Authors: Reinhard Grafl - $Id: loader.h 2154 2005-03-30 20:03:06Z twisti $ + $Id: loader.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -42,13 +42,11 @@ typedef struct classbuffer classbuffer; typedef struct classpath_info classpath_info; -#include "config.h" -#include "types.h" -#include "vm/class.h" -#include "vm/descriptor.h" #include "vm/global.h" -#include "vm/method.h" #include "vm/utf8.h" +#include "vm/references.h" +#include "vm/descriptor.h" +#include "vm/method.h" #if defined(USE_ZLIB) # include "vm/unzip.h" @@ -86,15 +84,6 @@ typedef struct classpath_info classpath_info; *******************************************************************************/ -typedef struct { /* Fieldref, Methodref and InterfaceMethodref */ - classinfo *class; /* class containing this field/method/intfmeth. */ /* XXX remove */ - constant_classref *classref; /* class containing this field/meth./intfm. */ - utf *name; /* field/method/interfacemethod name */ - utf *descriptor; /* field/method/intfmeth. type descriptor string */ - parseddesc parseddesc; /* parsed descriptor */ -} constant_FMIref; - - typedef struct { /* Integer */ s4 value; } constant_integer; @@ -213,7 +202,6 @@ classinfo *class_init(classinfo *c); /* debug purposes */ void class_showmethods(classinfo *c); void class_showconstantpool(classinfo *c); -void print_arraydescriptor(FILE *file, arraydescriptor *desc); /* return the primitive class inidicated by the given signature character */ classinfo *class_primitive_from_sig(char sig); diff --git a/src/vm/method.c b/src/vm/method.c index 1012c6870..7012c6873 100644 --- a/src/vm/method.c +++ b/src/vm/method.c @@ -32,13 +32,15 @@ Edwin Steiner Christian Thalinger - $Id: method.c 2100 2005-03-28 21:57:23Z twisti $ + $Id: method.c 2181 2005-04-01 16:53:33Z edwin $ */ +#include "vm/global.h" #include "mm/memory.h" #include "vm/method.h" +#include "vm/class.h" #include "vm/jit/codegen.inc.h" diff --git a/src/vm/method.h b/src/vm/method.h index 06553ea9d..eb653f320 100644 --- a/src/vm/method.h +++ b/src/vm/method.h @@ -28,7 +28,7 @@ Changes: Christian Thalinger - $Id: method.h 2114 2005-03-29 21:42:33Z twisti $ + $Id: method.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -42,10 +42,10 @@ typedef struct exceptiontable exceptiontable; typedef struct lineinfo lineinfo; -#include "vm/class.h" -#include "vm/descriptor.h" #include "vm/global.h" #include "vm/utf8.h" +#include "vm/references.h" +#include "vm/descriptor.h" #include "vm/jit/jit.h" #include "vm/jit/inline/parseXTA.h" diff --git a/src/vm/references.h b/src/vm/references.h new file mode 100644 index 000000000..0810af4c5 --- /dev/null +++ b/src/vm/references.h @@ -0,0 +1,135 @@ +/* vm/references.h - references to classes/fields/methods + + Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, + R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, + C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, + Institut f. Computersprachen - TU Wien + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + Contact: cacao@complang.tuwien.ac.at + + Authors: Edwin Steiner + + Changes: + + $Id: references.h 2181 2005-04-01 16:53:33Z edwin $ + +*/ + +#ifndef _REFERENCES_H_ +#define _REFERENCES_H_ + +#include "vm/global.h" +#include "vm/utf8.h" + +/*----------------------------------------------------------------------------*/ +/* References */ +/* */ +/* This header files defines the following types used for references to */ +/* classes/methods/fields and descriptors: */ +/* */ +/* classinfo * a loaded class */ +/* constant_classref a symbolic reference */ +/* classref_or_classinfo a loaded class or a symbolic reference */ +/* */ +/* constant_FMIref a symb. ref. to a field/method/intf.method */ +/* */ +/* typedesc * describes a field type */ +/* methoddesc * descrives a method type */ +/* parseddesc describes a field type or a method type */ +/*----------------------------------------------------------------------------*/ + +/* forward declarations *******************************************************/ + +typedef struct classinfo classinfo; +typedef struct typedesc typedesc; +typedef struct methoddesc methoddesc; + +/* structs ********************************************************************/ + +/* constant_classref **********************************************************/ + +typedef struct constant_classref { + void *pseudo_vftbl; /* for distinguishing it from classinfo */ + classinfo *referer; /* class containing the reference */ + utf *name; /* name of the class refered to */ +} constant_classref; + +/* classref_or_classinfo ******************************************************/ + +typedef union { + constant_classref *ref; /* a symbolic class reference */ + classinfo *cls; /* an already loaded class */ + void *any; /* used for general access (x != NULL,...) */ +} classref_or_classinfo; + +/* parseddesc *****************************************************************/ + +typedef union parseddesc { + typedesc *fd; /* parsed field descriptor */ + methoddesc *md; /* parsed method descriptor */ + void *any; /* used for simple test against NULL */ +} parseddesc; + +/* constant_FMIref ************************************************************/ + +typedef struct { /* Fieldref, Methodref and InterfaceMethodref */ + classinfo *class; /* class containing this field/method/intfmeth. */ /* XXX remove */ + constant_classref *classref; /* class containing this field/meth./intfm. */ + utf *name; /* field/method/interfacemethod name */ + utf *descriptor; /* field/method/intfmeth. type descriptor string */ + parseddesc parseddesc; /* parsed descriptor */ +} constant_FMIref; + +/* macros *********************************************************************/ + +/* a value that never occurrs in classinfo.header.vftbl */ +#define CLASSREF_PSEUDO_VFTBL ((void *) 1) + +/* macro for testing if a classref_or_classinfo is a classref */ +/* `reforinfo` is only evaluated once */ +#define IS_CLASSREF(reforinfo) \ + ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL) + +/* macro for casting a classref/classinfo * to a classref_or_classinfo */ +#define CLASSREF_OR_CLASSINFO(value) \ + (*((classref_or_classinfo *)(&(value)))) + +/* initialize a constant_classref with referer `ref` and name `classname` */ +#define CLASSREF_INIT(c,ref,classname) \ + do { (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \ + (c).referer = (ref); \ + (c).name = (classname); } while (0) + +#endif /* _REFERENCES_H_ */ + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + * vim:noexpandtab:sw=4:ts=4: + */ + diff --git a/src/vm/resolve.c b/src/vm/resolve.c index 3d59f36e7..79a1affa3 100644 --- a/src/vm/resolve.c +++ b/src/vm/resolve.c @@ -28,7 +28,7 @@ Changes: - $Id: resolve.c 2148 2005-03-30 16:49:40Z twisti $ + $Id: resolve.c 2181 2005-04-01 16:53:33Z edwin $ */ @@ -48,6 +48,8 @@ /* DEBUG HELPERS */ /******************************************************************************/ +/*#define RESOLVE_VERBOSE*/ + #ifndef NDEBUG #define RESOLVE_DEBUG #endif @@ -70,6 +72,8 @@ resolve_class(classinfo *referer,methodinfo *refmethod, classinfo **result) { classinfo *cls = NULL; + char *utf_ptr; + int len; RESOLVE_ASSERT(result); RESOLVE_ASSERT(referer); @@ -78,7 +82,7 @@ resolve_class(classinfo *referer,methodinfo *refmethod, *result = NULL; -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"resolve_class("); utf_fprint(stderr,referer->name); fprintf(stderr,","); @@ -89,35 +93,62 @@ resolve_class(classinfo *referer,methodinfo *refmethod, /* lookup if this class has already been loaded */ cls = classcache_lookup(referer->classloader,classname); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," lookup result: %p\n",(void*)cls); #endif if (!cls) { - /* the class has not been loaded, yet */ - if (mode == resolveLazy) - return true; /* be lazy */ + /* resolve array types */ + if (classname->text[0] == '[') { + utf_ptr = classname->text + 1; + len = classname->blength - 1; + /* classname is an array type name */ + switch (*utf_ptr) { + case 'L': + utf_ptr++; + len -= 2; + /* FALLTHROUGH */ + case '[': + /* the component type is a reference type */ + /* resolve the component type */ + if (!resolve_class(referer,refmethod, + utf_new(utf_ptr,len), + mode,&cls)) + return false; /* exception */ + if (!cls) { + RESOLVE_ASSERT(mode == resolveLazy); + return true; /* be lazy */ + } + /* create the array class */ + cls = class_array_of(cls); + } + } + else { + /* the class has not been loaded, yet */ + if (mode == resolveLazy) + return true; /* be lazy */ + } -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," loading...\n"); #endif /* load the class */ -#ifdef XXX - if (!load_class(referer->classloader,classname,&cls)) - return false; /* exception */ -#else - cls = class_new(classname); - if (!cls->loaded) - load_class_from_classloader(cls, referer->classloader); -#endif + if (!cls) { + classinfo *c = class_new(classname); + cls = load_class_from_classloader(c,referer->classloader); + if (!cls) { + class_free(c); + return false; /* exception */ + } + } } /* the class is now loaded */ RESOLVE_ASSERT(cls); RESOLVE_ASSERT(cls->loaded); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," checking access rights...\n"); #endif @@ -129,7 +160,7 @@ resolve_class(classinfo *referer,methodinfo *refmethod, } /* resolution succeeds */ -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," success.\n"); #endif *result = cls; @@ -174,7 +205,7 @@ resolve_classref_or_classinfo(methodinfo *refmethod, if (link) { if (!c->linked) - if (!class_link(c)) + if (!link_class(c)) return false; /* exception */ RESOLVE_ASSERT(c->linked); } @@ -210,7 +241,7 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod, RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager); RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"resolve_and_check_subtype_set\n"); unresolved_subtype_set_debug_dump(ref,stderr); if (IS_CLASSREF(typeref)) { @@ -256,7 +287,7 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod, RESOLVE_ASSERT(result->loaded); RESOLVE_ASSERT(result->linked); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"performing subclass test:\n"); fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr); fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass"); @@ -266,16 +297,18 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod, /* now check the subtype relationship */ TYPEINFO_INIT_CLASSINFO(resultti,result); if (reversed) { - if (!typeinfo_is_assignable_to_classinfo(&typeti,result)) { -#ifdef RESOLVE_DEBUG + /* we must test against `true` because `MAYBE` is also != 0 */ + if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) { +#ifdef RESOLVE_VERBOSE fprintf(stderr,"reversed subclass test failed\n"); #endif goto throw_error; } } else { - if (!typeinfo_is_assignable_to_classinfo(&resultti,type)) { -#ifdef RESOLVE_DEBUG + /* we must test against `true` because `MAYBE` is also != 0 */ + if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) { +#ifdef RESOLVE_VERBOSE fprintf(stderr,"subclass test failed\n"); #endif goto throw_error; @@ -321,7 +354,7 @@ resolve_field(unresolved_field *ref, *result = NULL; -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE unresolved_field_debug_dump(ref,stderr); #endif @@ -345,7 +378,7 @@ resolve_field(unresolved_field *ref, /* now we must find the declaration of the field in `container` * or one of its superclasses */ -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," resolving field in class...\n"); #endif @@ -360,7 +393,7 @@ resolve_field(unresolved_field *ref, RESOLVE_ASSERT(declarer); RESOLVE_ASSERT(declarer->loaded && declarer->linked); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," checking static...\n"); #endif @@ -375,7 +408,7 @@ resolve_field(unresolved_field *ref, /* for non-static accesses we have to check the constraints on the instance type */ if ((ref->flags & RESOLVE_STATIC) == 0) { -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," checking instance types...\n"); #endif @@ -396,6 +429,7 @@ resolve_field(unresolved_field *ref, /* for PUT* instructions we have to check the constraints on the value type */ if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) { + RESOLVE_ASSERT(fieldtyperef); if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) { /* check subtype constraints */ if (!resolve_and_check_subtype_set(referer,ref->referermethod, @@ -436,6 +470,7 @@ resolve_field(unresolved_field *ref, /* impose loading constraint on field type */ if (fi->type == TYPE_ADR) { + RESOLVE_ASSERT(fieldtyperef); if (!classcache_add_constraint(declarer->classloader,referer->classloader, fieldtyperef->name)) return false; /* exception */ @@ -469,7 +504,7 @@ resolve_method(unresolved_method *ref, RESOLVE_ASSERT(result); RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE unresolved_method_debug_dump(ref,stderr); #endif @@ -628,7 +663,7 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod, RESOLVE_ASSERT(stset); RESOLVE_ASSERT(tinfo); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n"); #ifdef TYPEINFO_DEBUG typeinfo_print(stderr,tinfo,4); @@ -665,17 +700,20 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod, count = tinfo->merged->count; stset->subtyperefs = MNEW(classref_or_classinfo,count + 1); for (i=0; isubtyperefs[i].cls = tinfo->merged->list[i]; + stset->subtyperefs[i] = tinfo->merged->list[i]; } stset->subtyperefs[count].any = NULL; /* terminate */ } else { - if (tinfo->typeclass->name == declaredtype->name) { + if ((IS_CLASSREF(tinfo->typeclass) + ? tinfo->typeclass.ref->name + : tinfo->typeclass.cls->name) == declaredtype->name) + { goto empty_set; } else { stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1); - stset->subtyperefs[0].cls = tinfo->typeclass; + stset->subtyperefs[0] = tinfo->typeclass; stset->subtyperefs[1].any = NULL; /* terminate */ } } @@ -700,7 +738,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod, typeinfo *tip = NULL; typedesc *fd; -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"create_unresolved_field\n"); fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr); fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr); @@ -752,7 +790,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod, fd = fieldref->parseddesc.fd; RESOLVE_ASSERT(fd); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr); fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr); fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr); @@ -831,7 +869,7 @@ create_unresolved_method(classinfo *referer,methodinfo *refmethod, md = methodref->parseddesc.md; RESOLVE_ASSERT(md); -#ifdef RESOLVE_DEBUG +#ifdef RESOLVE_VERBOSE fprintf(stderr,"create_unresolved_method\n"); fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr); fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr); diff --git a/src/vm/resolve.h b/src/vm/resolve.h index b3b20faa9..3145d28e5 100644 --- a/src/vm/resolve.h +++ b/src/vm/resolve.h @@ -28,7 +28,7 @@ Changes: - $Id: resolve.h 2112 2005-03-29 21:29:08Z twisti $ + $Id: resolve.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -44,7 +44,7 @@ typedef struct unresolved_subtype_set unresolved_subtype_set; #include "vm/global.h" -#include "vm/loader.h" +#include "vm/references.h" #include "vm/jit/jit.h" @@ -68,15 +68,6 @@ typedef enum { } resolve_err_t; -/* classref_or_classinfo ******************************************************/ - -typedef union { - constant_classref *ref; /* a symbolic class reference */ - classinfo *cls; /* an already loaded class */ - void *any; /* used for general access (x != NULL,...) */ -} classref_or_classinfo; - - /* structs ********************************************************************/ struct unresolved_subtype_set { @@ -110,19 +101,6 @@ struct unresolved_method { #define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \ do { (stset).subtyperefs = NULL; } while(0) -/* a value that never occurrs in classinfo.header.vftbl */ -#define CLASSREF_PSEUDO_VFTBL ((vftbl_t *) 1) - -/* macro for testing if a classref_or_classinfo is a classref */ -/* `reforinfo` is only evaluated once */ -#define IS_CLASSREF(reforinfo) \ - ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL) - -/* macro for casting a classref/classinfo * to a classref_or_classinfo */ -#define CLASSREF_OR_CLASSINFO(value) \ - (*((classref_or_classinfo *)(&(value)))) - - /* function prototypes ********************************************************/ /* resolve_class *************************************************************** diff --git a/src/vm/stringlocal.h b/src/vm/stringlocal.h index 099861060..30a09dcbe 100644 --- a/src/vm/stringlocal.h +++ b/src/vm/stringlocal.h @@ -28,7 +28,7 @@ Changes: - $Id: stringlocal.h 1926 2005-02-10 10:47:29Z twisti $ + $Id: stringlocal.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -41,8 +41,8 @@ typedef struct literalstring literalstring; #include "native/include/java_lang_String.h" #include "vm/global.h" -#include "vm/tables.h" #include "vm/utf8.h" +#include "vm/tables.h" /* data structure of internal javastrings stored in global hashtable **********/ diff --git a/src/vm/utf8.h b/src/vm/utf8.h index d5b648a56..991314fcc 100644 --- a/src/vm/utf8.h +++ b/src/vm/utf8.h @@ -28,7 +28,7 @@ Changes: - $Id: utf8.h 2158 2005-03-30 20:06:37Z twisti $ + $Id: utf8.h 2181 2005-04-01 16:53:33Z edwin $ */ @@ -44,7 +44,6 @@ typedef struct utf utf; -#include "types.h" #include "vm/global.h" -- 2.25.1