From 654eb3af12470c817c37f1a5c17f06115f05d3b8 Mon Sep 17 00:00:00 2001 From: edwin Date: Sat, 10 Jan 2004 22:49:32 +0000 Subject: [PATCH] added package access checking --- global.h | 7 +- jit/typecheck.c | 86 ++++++---------- loader.c | 6 +- src/vm/global.h | 7 +- src/vm/jit/verify/typecheck.c | 86 ++++++---------- src/vm/jit/verify/typeinfo.c | 189 ++++++++++++++++++++-------------- src/vm/jit/verify/typeinfo.h | 29 +++--- src/vm/loader.c | 6 +- src/vm/tables.c | 18 +++- tables.c | 18 +++- typeinfo.c | 189 ++++++++++++++++++++-------------- typeinfo.h | 29 +++--- 12 files changed, 376 insertions(+), 294 deletions(-) diff --git a/global.h b/global.h index a91db22b3..b454c2382 100644 --- a/global.h +++ b/global.h @@ -31,7 +31,7 @@ Philipp Tomsich Edwin Steiner - $Id: global.h 850 2004-01-05 23:58:39Z stefan $ + $Id: global.h 870 2004-01-10 22:49:32Z edwin $ */ @@ -597,7 +597,8 @@ struct classinfo { /* class structure */ struct gnu_classpath_RawData* vmData; /* gnu classpath */ s4 flags; /* ACC flags */ - utf *name; /* class name */ + utf *name; /* class name */ + utf *packagename; /* full name of the package */ s4 cpcount; /* number of entries in constant pool */ u1 *cptags; /* constant pool tags */ @@ -766,6 +767,8 @@ extern classinfo *pseudo_class_Null; extern classinfo *pseudo_class_New; extern vftbl *pseudo_class_Arraystub_vftbl; +extern utf *array_packagename; + /* instances of some system classes *******************************************/ diff --git a/jit/typecheck.c b/jit/typecheck.c index 1e7c1203c..ac3346387 100644 --- a/jit/typecheck.c +++ b/jit/typecheck.c @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typecheck.c 869 2004-01-10 21:30:06Z edwin $ + $Id: typecheck.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -496,16 +496,6 @@ typestate_ret(void *localbuf, return repeat; } -static bool -typestate_jsr(void *localbuf, - basicblock *current,basicblock *destblock, - stackptr ystack,typevector *yloc, - int locsize) -{ - typestack_put_retaddr(ystack,current+1,yloc); - return typestate_reach(localbuf,current,destblock,ystack,yloc,locsize); -} - /****************************************************************************/ /* HELPER FUNCTIONS */ /****************************************************************************/ @@ -524,10 +514,20 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, /* In the cases below, definingclass cannot be an interface */ case 0: - /* XXX check package access */ + if (definingclass->packagename != class->packagename) + return false; break; case ACC_PROTECTED: - /* XXX check package access and superclass access */ + if (definingclass->packagename != class->packagename) { + if (!builtin_isanysubclass(class,implementingclass)) + return false; + + /* For protected access of super class members in another + * package the instance must be a subclass of or the same + * as the current class. */ + LOG("protected access into other package"); + implementingclass = class; + } break; case ACC_PRIVATE: if (definingclass != class) { @@ -551,26 +551,12 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, && !TYPEINFO_IS_NULLTYPE(*instance) && !TYPEINFO_IS_NEWOBJECT(*instance)) { - typeinfo tempinfo; - - if (((flags & ACC_PROTECTED) != 0) - && builtin_isanysubclass(class,implementingclass)) + if (!typeinfo_is_assignable_to_classinfo(instance, + implementingclass)) { - /* For protected access of super class members - * the instance must be a subclass of or the same - * as the current class. */ - - /* XXX maybe we only are allowed to do this, if we - * don't have package access? */ - /* implementingclass = class; */ /* XXX does not work */ - } - - /* XXX use classinfo directly? */ - TYPEINFO_INIT_CLASSINFO(tempinfo,implementingclass); - if (!typeinfo_is_assignable(instance,&tempinfo)) { LOG("instance not assignable"); LOGINFO(instance); - LOGINFO(&tempinfo); + LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH; return false; } } @@ -600,11 +586,7 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, #endif /****************************************************************************/ -/* INTERNAL DATA STRUCTURES */ -/****************************************************************************/ - -/****************************************************************************/ -/* MACROS USED INTERNALLY IN typecheck() */ +/* MACROS FOR LOCAL VARIABLE CHECKING */ /****************************************************************************/ #define INDEX_ONEWORD(num) \ @@ -642,14 +624,11 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, panic("Variable type mismatch"); \ } while(0) -/* XXX maybe it's faster to copy always */ -#define COPYTYPE(source,dest) \ - {if ((source)->type == TYPE_ADR) \ - TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);} - -#define ISBUILTIN(v) (iptr->val.a == (functionptr)(v)) +/****************************************************************************/ +/* MACROS FOR STACK TYPE CHECKING */ +/****************************************************************************/ -/* Macros for basic typechecks which were not done in stack.c */ +/* These macros are for basic typechecks which were not done in stack.c */ #define TYPECHECK_STACK(sp,tp) \ do { if ((sp)->type != (tp)) \ @@ -670,6 +649,17 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, do {TYPECHECK_ARGS2(t1,t2); \ TYPECHECK_STACK(curstack->prev->prev,t3);} while (0) +/****************************************************************************/ +/* MISC MACROS */ +/****************************************************************************/ + +/* XXX maybe it's faster to copy always */ +#define COPYTYPE(source,dest) \ + {if ((source)->type == TYPE_ADR) \ + TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);} + +#define ISBUILTIN(v) (iptr->val.a == (functionptr)(v)) + /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local * variables to the local variables of the target block. * Input: @@ -1446,7 +1436,6 @@ typecheck() /* propagate stack and variables to the target block */ TYPECHECK_REACH; - /* XXX */ break; /****************************************/ @@ -1483,8 +1472,8 @@ typecheck() /* RETURNS AND THROW */ case ICMD_ATHROW: - TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable); - if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo)) + if (!typeinfo_is_assignable_to_classinfo( + &curstack->typeinfo,class_java_lang_Throwable)) panic("illegal instruction: ATHROW on non-Throwable"); superblockend = true; maythrow = true; @@ -1608,8 +1597,6 @@ typecheck() LOGINFO(pinfo + i); if (i==0 && callinginit) { - /* typeinfo tempinfo; */ - /* first argument to method */ if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) panic("Calling on initialized object"); @@ -1733,11 +1720,6 @@ typecheck() panic("illegal instruction: AASTORE to non-reference array"); /* XXX optimize */ - /* - typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo); - if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo)) - panic("illegal instruction: AASTORE to incompatible type"); - */ } else { /* XXX put these checks in a function */ diff --git a/loader.c b/loader.c index 8e3b18a6e..9ca75bf68 100644 --- a/loader.c +++ b/loader.c @@ -30,7 +30,7 @@ Mark Probst Edwin Steiner - $Id: loader.c 868 2004-01-10 20:12:10Z edwin $ + $Id: loader.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -135,6 +135,8 @@ static classinfo *class_java_lang_ArithmeticException; static classinfo *class_java_lang_ArrayStoreException; static classinfo *class_java_lang_ThreadDeath; +utf *array_packagename = NULL; + static int loader_inited = 0; @@ -3496,6 +3498,8 @@ void loader_init(u1 *stackbottom) utf_vmclass = utf_new_char("java/lang/VMClass"); utf_java_lang_Object= utf_new_char("java/lang/Object"); + array_packagename = utf_new_char(""); + /* create some important classes */ /* These classes have to be created now because the classinfo * pointers are used in the loading code. diff --git a/src/vm/global.h b/src/vm/global.h index a91db22b3..b454c2382 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -31,7 +31,7 @@ Philipp Tomsich Edwin Steiner - $Id: global.h 850 2004-01-05 23:58:39Z stefan $ + $Id: global.h 870 2004-01-10 22:49:32Z edwin $ */ @@ -597,7 +597,8 @@ struct classinfo { /* class structure */ struct gnu_classpath_RawData* vmData; /* gnu classpath */ s4 flags; /* ACC flags */ - utf *name; /* class name */ + utf *name; /* class name */ + utf *packagename; /* full name of the package */ s4 cpcount; /* number of entries in constant pool */ u1 *cptags; /* constant pool tags */ @@ -766,6 +767,8 @@ extern classinfo *pseudo_class_Null; extern classinfo *pseudo_class_New; extern vftbl *pseudo_class_Arraystub_vftbl; +extern utf *array_packagename; + /* instances of some system classes *******************************************/ diff --git a/src/vm/jit/verify/typecheck.c b/src/vm/jit/verify/typecheck.c index 1e7c1203c..ac3346387 100644 --- a/src/vm/jit/verify/typecheck.c +++ b/src/vm/jit/verify/typecheck.c @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typecheck.c 869 2004-01-10 21:30:06Z edwin $ + $Id: typecheck.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -496,16 +496,6 @@ typestate_ret(void *localbuf, return repeat; } -static bool -typestate_jsr(void *localbuf, - basicblock *current,basicblock *destblock, - stackptr ystack,typevector *yloc, - int locsize) -{ - typestack_put_retaddr(ystack,current+1,yloc); - return typestate_reach(localbuf,current,destblock,ystack,yloc,locsize); -} - /****************************************************************************/ /* HELPER FUNCTIONS */ /****************************************************************************/ @@ -524,10 +514,20 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, /* In the cases below, definingclass cannot be an interface */ case 0: - /* XXX check package access */ + if (definingclass->packagename != class->packagename) + return false; break; case ACC_PROTECTED: - /* XXX check package access and superclass access */ + if (definingclass->packagename != class->packagename) { + if (!builtin_isanysubclass(class,implementingclass)) + return false; + + /* For protected access of super class members in another + * package the instance must be a subclass of or the same + * as the current class. */ + LOG("protected access into other package"); + implementingclass = class; + } break; case ACC_PRIVATE: if (definingclass != class) { @@ -551,26 +551,12 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, && !TYPEINFO_IS_NULLTYPE(*instance) && !TYPEINFO_IS_NEWOBJECT(*instance)) { - typeinfo tempinfo; - - if (((flags & ACC_PROTECTED) != 0) - && builtin_isanysubclass(class,implementingclass)) + if (!typeinfo_is_assignable_to_classinfo(instance, + implementingclass)) { - /* For protected access of super class members - * the instance must be a subclass of or the same - * as the current class. */ - - /* XXX maybe we only are allowed to do this, if we - * don't have package access? */ - /* implementingclass = class; */ /* XXX does not work */ - } - - /* XXX use classinfo directly? */ - TYPEINFO_INIT_CLASSINFO(tempinfo,implementingclass); - if (!typeinfo_is_assignable(instance,&tempinfo)) { LOG("instance not assignable"); LOGINFO(instance); - LOGINFO(&tempinfo); + LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH; return false; } } @@ -600,11 +586,7 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, #endif /****************************************************************************/ -/* INTERNAL DATA STRUCTURES */ -/****************************************************************************/ - -/****************************************************************************/ -/* MACROS USED INTERNALLY IN typecheck() */ +/* MACROS FOR LOCAL VARIABLE CHECKING */ /****************************************************************************/ #define INDEX_ONEWORD(num) \ @@ -642,14 +624,11 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, panic("Variable type mismatch"); \ } while(0) -/* XXX maybe it's faster to copy always */ -#define COPYTYPE(source,dest) \ - {if ((source)->type == TYPE_ADR) \ - TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);} - -#define ISBUILTIN(v) (iptr->val.a == (functionptr)(v)) +/****************************************************************************/ +/* MACROS FOR STACK TYPE CHECKING */ +/****************************************************************************/ -/* Macros for basic typechecks which were not done in stack.c */ +/* These macros are for basic typechecks which were not done in stack.c */ #define TYPECHECK_STACK(sp,tp) \ do { if ((sp)->type != (tp)) \ @@ -670,6 +649,17 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, do {TYPECHECK_ARGS2(t1,t2); \ TYPECHECK_STACK(curstack->prev->prev,t3);} while (0) +/****************************************************************************/ +/* MISC MACROS */ +/****************************************************************************/ + +/* XXX maybe it's faster to copy always */ +#define COPYTYPE(source,dest) \ + {if ((source)->type == TYPE_ADR) \ + TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);} + +#define ISBUILTIN(v) (iptr->val.a == (functionptr)(v)) + /* TYPECHECK_COPYVARS: copy the types and typeinfos of the current local * variables to the local variables of the target block. * Input: @@ -1446,7 +1436,6 @@ typecheck() /* propagate stack and variables to the target block */ TYPECHECK_REACH; - /* XXX */ break; /****************************************/ @@ -1483,8 +1472,8 @@ typecheck() /* RETURNS AND THROW */ case ICMD_ATHROW: - TYPEINFO_INIT_CLASSINFO(tempinfo,class_java_lang_Throwable); - if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo)) + if (!typeinfo_is_assignable_to_classinfo( + &curstack->typeinfo,class_java_lang_Throwable)) panic("illegal instruction: ATHROW on non-Throwable"); superblockend = true; maythrow = true; @@ -1608,8 +1597,6 @@ typecheck() LOGINFO(pinfo + i); if (i==0 && callinginit) { - /* typeinfo tempinfo; */ - /* first argument to method */ if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)) panic("Calling on initialized object"); @@ -1733,11 +1720,6 @@ typecheck() panic("illegal instruction: AASTORE to non-reference array"); /* XXX optimize */ - /* - typeinfo_init_component(&curstack->prev->prev->typeinfo,&tempinfo); - if (!typeinfo_is_assignable(&curstack->typeinfo,&tempinfo)) - panic("illegal instruction: AASTORE to incompatible type"); - */ } else { /* XXX put these checks in a function */ diff --git a/src/vm/jit/verify/typeinfo.c b/src/vm/jit/verify/typeinfo.c index 9496b12cc..8f3d59288 100644 --- a/src/vm/jit/verify/typeinfo.c +++ b/src/vm/jit/verify/typeinfo.c @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typeinfo.c 868 2004-01-10 20:12:10Z edwin $ + $Id: typeinfo.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -61,45 +61,6 @@ typevectorset_copy(typevector *src,int k,int size) return dst; } -#if 0 -typevector * -typevectorset_copy_select(typevector *src, - int retindex,void *retaddr,int size) -{ - typevector *dst; - - for (;src; src=src->alt) { - if (TYPEINFO_RETURNADDRESS(src->td[retindex].info) != retaddr) - continue; - - dst = DNEW_TYPEVECTOR(size); - memcpy(dst,src,TYPEVECTOR_SIZE(size)); - if (src->alt) - dst->alt = typevectorset_copy_select(src->alt,retindex,retaddr,size); - return dst; - } - - return NULL; -} - -void -typevectorset_copy_select_to(typevector *src,typevector *dst, - int retindex,void *retaddr,int size) -{ - for (;src; src=src->alt) { - if (TYPEINFO_RETURNADDRESS(src->td[retindex].info) != retaddr) - continue; - - memcpy(dst,src,TYPEVECTOR_SIZE(size)); - if (src->alt) - dst->alt = typevectorset_copy_select(src->alt,retindex,retaddr,size); - return dst; - } - - return NULL; -} -#endif - bool typevectorset_checktype(typevector *vec,int index,int type) { @@ -304,16 +265,6 @@ typevectorset_add(typevector *dst,typevector *v,int size) dst->alt->k = dst->k + 1; } -#if 0 -void -typevectorset_union(typevector *dst,typevector *v,int size) -{ - while (dst->alt) - dst = dst->alt; - dst->alt = typevectorset_copy(v,size); -} -#endif - typevector * typevectorset_select(typevector **set,int retindex,void *retaddr) { @@ -332,29 +283,6 @@ typevectorset_select(typevector **set,int retindex,void *retaddr) return selected; } -/* XXX delete */ -#if 0 -bool -typevectorset_separable(typevector *vec,int size) -{ - int i; - typevector *v; - - for (i=0; itd[i])) - goto next_index; - - v = v->alt; - if (!v) return true; - } while (v); - next_index: - } - return false; -} -#endif - bool typevectorset_separable_with(typevector *set,typevector *add,int size) { @@ -502,16 +430,20 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged, bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest) { - classinfo *cls; - - cls = value->typeclass; - /* 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 - + + return typeinfo_is_assignable_to_classinfo(value,dest->typeclass); + + /* XXX delete */ +#if 0 + classinfo *cls; + + cls = value->typeclass; + /* assignments of primitive values are not checked here. */ if (!cls && !dest->typeclass) return true; @@ -592,6 +524,107 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) cls = class_java_lang_Object; return class_issubclass(cls,dest->typeclass); +#endif +} + +bool +typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) +{ + classinfo *cls; + + cls = value->typeclass; + + /* assignments of primitive values are not checked here. */ + if (!cls && !dest) + return true; + + /* primitive and reference types are not assignment compatible. */ + if (!cls || !dest) + return false; + +#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; + + /* uninitialized objects are not assignable */ + if (TYPEINFO_IS_NEWOBJECT(*value)) + return false; + + if (dest->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + return merged_implements_interface(cls,value->merged,dest); + } + + if (CLASS_IS_ARRAY(dest)) { + arraydescriptor *arraydesc = dest->vftbl->arraydesc; + int dimension = arraydesc->dimension; + classinfo *elementclass = (arraydesc->elementvftbl) + ? arraydesc->elementvftbl->class : NULL; + + /* We are assigning to an array type. */ + if (!TYPEINFO_IS_ARRAY(*value)) + return false; + + /* {Both value and dest are array types.} */ + + /* value must have at least the dimension of dest. */ + 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 */ + + if (!elementclass) return false; + + if (elementclass->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + return classinfo_implements_interface(pseudo_class_Arraystub, + elementclass); + } + + /* We are assigning to a class type. */ + return class_issubclass(pseudo_class_Arraystub,elementclass); + } + + /* {value and dest have the same dimension} */ + + if (value->elementtype != arraydesc->elementtype) + return false; + + if (value->elementclass) { + /* We are assigning an array of objects so we have to + * check if the elements are assignable. + */ + + if (elementclass->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + + return merged_implements_interface(value->elementclass, + value->merged, + elementclass); + } + + /* We are assigning to a class type. */ + return class_issubclass(value->elementclass,elementclass); + } + + return true; + } + + /* {dest is not an array} */ + + /* We are assigning to a class type */ + if (cls->flags & ACC_INTERFACE) + cls = class_java_lang_Object; + + return class_issubclass(cls,dest); } /**********************************************************************/ diff --git a/src/vm/jit/verify/typeinfo.h b/src/vm/jit/verify/typeinfo.h index e01ead892..b74cb46f5 100644 --- a/src/vm/jit/verify/typeinfo.h +++ b/src/vm/jit/verify/typeinfo.h @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typeinfo.h 868 2004-01-10 20:12:10Z edwin $ + $Id: typeinfo.h 870 2004-01-10 22:49:32Z edwin $ */ @@ -65,6 +65,11 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * * This pseudo class is used internally to represent the * null type. + * + * pseudo_class_New + * + * This pseudo class is used internally to represent the + * the uninitialized object type. */ /* data structures for the type system ****************************************/ @@ -73,6 +78,7 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * (stack elements, variables, etc. with type == TYPE_ADR.) * XXX: exclude ReturnAddresses? * + * XXX * For primitive types either there is no typeinfo allocated or the * typeclass pointer in the typeinfo struct is NULL. * @@ -87,13 +93,13 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * A) typeclass == NULL * * In this case the other fields of the structure - * are INVALID. + * are INVALID. XXX * * B) typeclass == pseudo_class_Null * * XXX * - * C) typeclass is an array class + * C) typeclass == pseudo_class_New * * XXX * @@ -101,17 +107,21 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * * XXX * - * E) typeclass is an interface + * E) typeclass is an array class + * + * XXX + * + * F) typeclass is an interface * * XXX * - * F) typeclass is a (non-pseudo-)class != java.lang.Object + * G) typeclass is a (non-pseudo-)class != java.lang.Object * * XXX * All classinfos in u.merged.list (if any) are * subclasses of typeclass. * - * G) typeclass is java.lang.Object + * H) typeclass is java.lang.Object * * XXX * In this case u.merged.count and u.merged.list @@ -406,15 +416,9 @@ bool typevector_merge(typevector *dst,typevector *y,int size); /* vector set functions */ typevector *typevectorset_copy(typevector *src,int k,int size); -/* typevector *typevectorset_copy_select(typevector *src, - int retindex,void *retaddr,int size); - void typevectorset_copy_select_to(typevector *src,typevector *dst, - int retindex,void *retaddr,int size); */ -/* bool typevectorset_separable(typevector *set,int size); */ bool typevectorset_separable_with(typevector *set,typevector *add,int size); bool typevectorset_collapse(typevector *dst,int size); void typevectorset_add(typevector *dst,typevector *v,int size); -/* void typevectorset_union(typevector *dst,typevector *v,int size); */ typevector *typevectorset_select(typevector **set,int retindex,void *retaddr); /* inquiry functions (read-only) ********************************************/ @@ -425,6 +429,7 @@ 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); /* initialization functions *************************************************/ diff --git a/src/vm/loader.c b/src/vm/loader.c index 8e3b18a6e..9ca75bf68 100644 --- a/src/vm/loader.c +++ b/src/vm/loader.c @@ -30,7 +30,7 @@ Mark Probst Edwin Steiner - $Id: loader.c 868 2004-01-10 20:12:10Z edwin $ + $Id: loader.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -135,6 +135,8 @@ static classinfo *class_java_lang_ArithmeticException; static classinfo *class_java_lang_ArrayStoreException; static classinfo *class_java_lang_ThreadDeath; +utf *array_packagename = NULL; + static int loader_inited = 0; @@ -3496,6 +3498,8 @@ void loader_init(u1 *stackbottom) utf_vmclass = utf_new_char("java/lang/VMClass"); utf_java_lang_Object= utf_new_char("java/lang/Object"); + array_packagename = utf_new_char(""); + /* create some important classes */ /* These classes have to be created now because the classinfo * pointers are used in the loading code. diff --git a/src/vm/tables.c b/src/vm/tables.c index 21456a718..385e513d4 100644 --- a/src/vm/tables.c +++ b/src/vm/tables.c @@ -35,7 +35,7 @@ - the heap - additional support functions - $Id: tables.c 868 2004-01-10 20:12:10Z edwin $ + $Id: tables.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -823,6 +823,7 @@ classinfo *class_new(utf *u) c->vmClass = 0; c->flags = 0; c->name = u; + c->packagename = NULL; c->cpcount = 0; c->cptags = NULL; c->cpinfos = NULL; @@ -891,8 +892,21 @@ classinfo *class_new(utf *u) } /* Array classes need further initialization. */ - if (u->text[0] == '[') + if (u->text[0] == '[') { class_new_array(c); + c->packagename = array_packagename; + } + else { + /* Find the package name */ + /* Classes in the unnamed package keep packagename == NULL. */ + char *p = utf_end(c->name) - 1; + char *start = c->name->text; + for (;p > start; --p) + if (*p == '.') { + c->packagename = utf_new(start,p-start); + break; + } + } return c; } diff --git a/tables.c b/tables.c index 21456a718..385e513d4 100644 --- a/tables.c +++ b/tables.c @@ -35,7 +35,7 @@ - the heap - additional support functions - $Id: tables.c 868 2004-01-10 20:12:10Z edwin $ + $Id: tables.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -823,6 +823,7 @@ classinfo *class_new(utf *u) c->vmClass = 0; c->flags = 0; c->name = u; + c->packagename = NULL; c->cpcount = 0; c->cptags = NULL; c->cpinfos = NULL; @@ -891,8 +892,21 @@ classinfo *class_new(utf *u) } /* Array classes need further initialization. */ - if (u->text[0] == '[') + if (u->text[0] == '[') { class_new_array(c); + c->packagename = array_packagename; + } + else { + /* Find the package name */ + /* Classes in the unnamed package keep packagename == NULL. */ + char *p = utf_end(c->name) - 1; + char *start = c->name->text; + for (;p > start; --p) + if (*p == '.') { + c->packagename = utf_new(start,p-start); + break; + } + } return c; } diff --git a/typeinfo.c b/typeinfo.c index 9496b12cc..8f3d59288 100644 --- a/typeinfo.c +++ b/typeinfo.c @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typeinfo.c 868 2004-01-10 20:12:10Z edwin $ + $Id: typeinfo.c 870 2004-01-10 22:49:32Z edwin $ */ @@ -61,45 +61,6 @@ typevectorset_copy(typevector *src,int k,int size) return dst; } -#if 0 -typevector * -typevectorset_copy_select(typevector *src, - int retindex,void *retaddr,int size) -{ - typevector *dst; - - for (;src; src=src->alt) { - if (TYPEINFO_RETURNADDRESS(src->td[retindex].info) != retaddr) - continue; - - dst = DNEW_TYPEVECTOR(size); - memcpy(dst,src,TYPEVECTOR_SIZE(size)); - if (src->alt) - dst->alt = typevectorset_copy_select(src->alt,retindex,retaddr,size); - return dst; - } - - return NULL; -} - -void -typevectorset_copy_select_to(typevector *src,typevector *dst, - int retindex,void *retaddr,int size) -{ - for (;src; src=src->alt) { - if (TYPEINFO_RETURNADDRESS(src->td[retindex].info) != retaddr) - continue; - - memcpy(dst,src,TYPEVECTOR_SIZE(size)); - if (src->alt) - dst->alt = typevectorset_copy_select(src->alt,retindex,retaddr,size); - return dst; - } - - return NULL; -} -#endif - bool typevectorset_checktype(typevector *vec,int index,int type) { @@ -304,16 +265,6 @@ typevectorset_add(typevector *dst,typevector *v,int size) dst->alt->k = dst->k + 1; } -#if 0 -void -typevectorset_union(typevector *dst,typevector *v,int size) -{ - while (dst->alt) - dst = dst->alt; - dst->alt = typevectorset_copy(v,size); -} -#endif - typevector * typevectorset_select(typevector **set,int retindex,void *retaddr) { @@ -332,29 +283,6 @@ typevectorset_select(typevector **set,int retindex,void *retaddr) return selected; } -/* XXX delete */ -#if 0 -bool -typevectorset_separable(typevector *vec,int size) -{ - int i; - typevector *v; - - for (i=0; itd[i])) - goto next_index; - - v = v->alt; - if (!v) return true; - } while (v); - next_index: - } - return false; -} -#endif - bool typevectorset_separable_with(typevector *set,typevector *add,int size) { @@ -502,16 +430,20 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged, bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest) { - classinfo *cls; - - cls = value->typeclass; - /* 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 - + + return typeinfo_is_assignable_to_classinfo(value,dest->typeclass); + + /* XXX delete */ +#if 0 + classinfo *cls; + + cls = value->typeclass; + /* assignments of primitive values are not checked here. */ if (!cls && !dest->typeclass) return true; @@ -592,6 +524,107 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest) cls = class_java_lang_Object; return class_issubclass(cls,dest->typeclass); +#endif +} + +bool +typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest) +{ + classinfo *cls; + + cls = value->typeclass; + + /* assignments of primitive values are not checked here. */ + if (!cls && !dest) + return true; + + /* primitive and reference types are not assignment compatible. */ + if (!cls || !dest) + return false; + +#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; + + /* uninitialized objects are not assignable */ + if (TYPEINFO_IS_NEWOBJECT(*value)) + return false; + + if (dest->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + return merged_implements_interface(cls,value->merged,dest); + } + + if (CLASS_IS_ARRAY(dest)) { + arraydescriptor *arraydesc = dest->vftbl->arraydesc; + int dimension = arraydesc->dimension; + classinfo *elementclass = (arraydesc->elementvftbl) + ? arraydesc->elementvftbl->class : NULL; + + /* We are assigning to an array type. */ + if (!TYPEINFO_IS_ARRAY(*value)) + return false; + + /* {Both value and dest are array types.} */ + + /* value must have at least the dimension of dest. */ + 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 */ + + if (!elementclass) return false; + + if (elementclass->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + return classinfo_implements_interface(pseudo_class_Arraystub, + elementclass); + } + + /* We are assigning to a class type. */ + return class_issubclass(pseudo_class_Arraystub,elementclass); + } + + /* {value and dest have the same dimension} */ + + if (value->elementtype != arraydesc->elementtype) + return false; + + if (value->elementclass) { + /* We are assigning an array of objects so we have to + * check if the elements are assignable. + */ + + if (elementclass->flags & ACC_INTERFACE) { + /* We are assigning to an interface type. */ + + return merged_implements_interface(value->elementclass, + value->merged, + elementclass); + } + + /* We are assigning to a class type. */ + return class_issubclass(value->elementclass,elementclass); + } + + return true; + } + + /* {dest is not an array} */ + + /* We are assigning to a class type */ + if (cls->flags & ACC_INTERFACE) + cls = class_java_lang_Object; + + return class_issubclass(cls,dest); } /**********************************************************************/ diff --git a/typeinfo.h b/typeinfo.h index e01ead892..b74cb46f5 100644 --- a/typeinfo.h +++ b/typeinfo.h @@ -26,7 +26,7 @@ Authors: Edwin Steiner - $Id: typeinfo.h 868 2004-01-10 20:12:10Z edwin $ + $Id: typeinfo.h 870 2004-01-10 22:49:32Z edwin $ */ @@ -65,6 +65,11 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * * This pseudo class is used internally to represent the * null type. + * + * pseudo_class_New + * + * This pseudo class is used internally to represent the + * the uninitialized object type. */ /* data structures for the type system ****************************************/ @@ -73,6 +78,7 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * (stack elements, variables, etc. with type == TYPE_ADR.) * XXX: exclude ReturnAddresses? * + * XXX * For primitive types either there is no typeinfo allocated or the * typeclass pointer in the typeinfo struct is NULL. * @@ -87,13 +93,13 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * A) typeclass == NULL * * In this case the other fields of the structure - * are INVALID. + * are INVALID. XXX * * B) typeclass == pseudo_class_Null * * XXX * - * C) typeclass is an array class + * C) typeclass == pseudo_class_New * * XXX * @@ -101,17 +107,21 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set; * * XXX * - * E) typeclass is an interface + * E) typeclass is an array class + * + * XXX + * + * F) typeclass is an interface * * XXX * - * F) typeclass is a (non-pseudo-)class != java.lang.Object + * G) typeclass is a (non-pseudo-)class != java.lang.Object * * XXX * All classinfos in u.merged.list (if any) are * subclasses of typeclass. * - * G) typeclass is java.lang.Object + * H) typeclass is java.lang.Object * * XXX * In this case u.merged.count and u.merged.list @@ -406,15 +416,9 @@ bool typevector_merge(typevector *dst,typevector *y,int size); /* vector set functions */ typevector *typevectorset_copy(typevector *src,int k,int size); -/* typevector *typevectorset_copy_select(typevector *src, - int retindex,void *retaddr,int size); - void typevectorset_copy_select_to(typevector *src,typevector *dst, - int retindex,void *retaddr,int size); */ -/* bool typevectorset_separable(typevector *set,int size); */ bool typevectorset_separable_with(typevector *set,typevector *add,int size); bool typevectorset_collapse(typevector *dst,int size); void typevectorset_add(typevector *dst,typevector *v,int size); -/* void typevectorset_union(typevector *dst,typevector *v,int size); */ typevector *typevectorset_select(typevector **set,int retindex,void *retaddr); /* inquiry functions (read-only) ********************************************/ @@ -425,6 +429,7 @@ 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); /* initialization functions *************************************************/ -- 2.25.1