##
## 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
method.h \
options.c \
options.h \
+ references.h \
resolve.c \
resolve.h \
$(STATISTICS_OBJ) \
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 *********************************************************************/
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 <assert.h>
#include <string.h>
-#include "config.h"
-#include "types.h"
-
+#include "vm/global.h"
#include "mm/memory.h"
#if defined(USE_THREADS)
#include "vm/statistics.h"
#include "vm/tables.h"
#include "vm/utf8.h"
+#include "vm/loader.h"
/******************************************************************************/
Changes:
- $Id: class.h 2153 2005-03-30 19:30:05Z twisti $
+ $Id: class.h 2181 2005-04-01 16:53:33Z edwin $
*/
/* 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 */
};
-/* 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
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);
Changes:
- $Id: classcache.c 2083 2005-03-25 14:25:15Z edwin $
+ $Id: classcache.c 2181 2005-04-01 16:53:33Z edwin $
*/
#include <assert.h>
#include "vm/classcache.h"
-#include "vm/tables.h"
#include "vm/utf8.h"
+#include "vm/tables.h"
#include "vm/exceptions.h"
#include "mm/memory.h"
#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 */
/*============================================================================*/
/* classcache_init *************************************************************
Initialize the loaded class cache
+
+ Note: NOT synchronized!
*******************************************************************************/
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
*******************************************************************************/
classcache_name_entry *en;
classcache_class_entry *clsen;
classcache_loader_entry *lden;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
en = classcache_lookup_name(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 ************************************************************
the cache if necessary,
false............an exception has been thrown.
+ Note: synchronized with global tablelock
+
*******************************************************************************/
bool
CLASSCACHE_ASSERT(cls);
- /* XXX lock table */
+ CLASSCACHE_LOCK();
en = classcache_new_name(cls->name);
/* 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 */
clsen->classobj = cls;
/* done */
- return true;
+ goto return_success;
}
}
clsen->next = en->classes;
en->classes = clsen;
- /* done */
+return_success:
+ CLASSCACHE_UNLOCK();
return true;
+
+return_exception:
+ CLASSCACHE_UNLOCK();
+ return false; /* exception */
}
/* classcache_find_loader ******************************************************
The class cache may not be used any more after this call, except
when it is reinitialized with classcache_init.
+ Note: NOT synchronized!
+
*******************************************************************************/
void
true.............everything ok, the constraint has been added,
false............an exception has been thrown.
+ Note: synchronized with global tablelock
+
*******************************************************************************/
bool
if (a == b)
return true;
- /* XXX lock table */
+ CLASSCACHE_LOCK();
en = classcache_new_name(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 */
}
}
- /* done */
+return_success:
+ CLASSCACHE_UNLOCK();
return true;
+
+return_exception:
+ CLASSCACHE_UNLOCK();
+ return false; /* exception */
}
/*============================================================================*/
IN:
file.............output stream
+ Note: synchronized with global tablelock
+
*******************************************************************************/
void
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);
}
}
fprintf(file,"\n==============================================================\n\n");
+
+ CLASSCACHE_UNLOCK();
}
/*
Changes:
- $Id: classcache.h 2111 2005-03-29 21:28:24Z twisti $
+ $Id: classcache.h 2181 2005-04-01 16:53:33Z edwin $
*/
#include <stdio.h> /* for FILE */
-#include "vm/class.h"
-#include "vm/utf8.h"
+#include "vm/references.h"
/* forward declarations *******************************************************/
Changes:
- $Id: descriptor.c 2111 2005-03-29 21:28:24Z twisti $
+ $Id: descriptor.c 2181 2005-04-01 16:53:33Z edwin $
*/
*exceptionptr = new_classformaterror(pool->referer,"Invalid class name");
return false; /* exception */
}
+
+ /* XXX check maximum array dimension */
c = DNEW(classref_hash_entry);
c->name = name;
Changes:
- $Id: descriptor.h 2112 2005-03-29 21:29:08Z twisti $
+ $Id: descriptor.h 2181 2005-04-01 16:53:33Z edwin $
*/
/* 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 ************************************************************/
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 ********************************************************/
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 */
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 $
*/
#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)
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 $
*/
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"
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 $
*/
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)
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 $
*/
#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"
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 $
*/
typedef struct xtafldinfo xtafldinfo;
+#include "toolbox/list.h"
#include "vm/global.h"
#include "vm/jit/inline/sets.h"
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 $
*/
#include "vm/linker.h"
#include "vm/loader.h"
#include "vm/tables.h"
+#include "vm/class.h"
#include "vm/jit/inline/sets.h"
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 $
*/
typedef struct classSetNode classSetNode;
-#include "types.h"
#include "vm/global.h"
#include "vm/method.h"
+#include "vm/field.h"
/*------------ Method /Class Used Markers -------------------------------*/
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 $
*/
#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"
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 $
*/
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:
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:
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");
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 {
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);
}
}
}
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 $
*/
#ifndef _STACK_H
#define _STACK_H
-#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/exceptions.h"
#include "vm/jit/reg.h"
Changes:
- $Id: genoffsets.c 2122 2005-03-29 22:12:06Z twisti $
+ $Id: genoffsets.c 2181 2005-04-01 16:53:33Z edwin $
*/
#include <stdio.h>
-#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"
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 <assert.h>
#include <string.h>
#include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
#ifdef CACAO_TYPECHECK
#include "types.h"
-/* #include "main.h" */
#include "mm/memory.h"
#include "toolbox/logging.h"
#include "native/native.h"
#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)
#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)
#define LOGSTR2(str,a,b)
#define LOGSTR3(str,a,b,c)
#define LOGSTRu(utf)
+#define LOGNAME(c)
#endif
#ifdef TYPECHECK_VERBOSE_IMPORTANT
{
#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," ");
}
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) {
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);
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;
}
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);
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;
}
/* 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;
&& !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);
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 */
#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);
{
/*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) {
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);
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;
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");
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");
{
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;
}
if (dst->type == TYPE_ADR) {
- TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
+ typeinfo_init_from_typedesc(fi->parseddesc,NULL,&(dst->typeinfo));
}
}
maythrow = true;
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;
/* 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;
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");
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;
/* 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 <init> 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))
TYPESTACK_COPY(sp,copy);
}
- TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
+ TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(srcstack->typeinfo,initclass);
}
srcstack = srcstack->prev;
}
/* initializing the 'this' reference? */
if (!ins) {
-#ifdef TYPECHECK_DEBUG
- if (!initmethod)
- panic("Internal error: calling <init> on this in non-<init> method.");
-#endif
+ TYPECHECK_ASSERT(initmethod);
/* must be <init> of current class or direct superclass */
if (mi->class != m->class && mi->class != m->class->super)
panic("<init> calling <init> of the wrong class");
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 <init> method of the wrong class");
}
}
!= 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);
}
!= 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);
}
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");
!= 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);
}
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
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,
}
}
+ LOG("next instruction");
iptr++;
} /* while instructions */
} 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
{
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
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/
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 <assert.h>
#include <string.h>
#include "mm/memory.h"
#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 */
/**********************************************************************/
}
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;
&& 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);
}
}
}
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; i<cls->interfacescount; ++i) {
if (cls->interfaces[i] == 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) {
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;
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)
{
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;
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;
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;
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.
*/
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);
}
/**********************************************************************/
/* 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; i<desc->paramcount; ++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; i<desc->paramcount; ++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;
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;
}
/* 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;
newlist = newmerged->list;
mlist = m->list;
while (count) {
- if (*mlist > cls)
+ if (mlist->any > cls.any)
break;
*newlist++ = *mlist++;
count--;
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.) */
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--;
}
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--;
}
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))
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;
* 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 */
/* {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) {
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. */
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);
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;
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;
/* 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;
if (x->dimension < y->dimension) {
dimension = x->dimension;
elementtype = ARRAYTYPE_OBJECT;
- elementclass = pseudo_class_Arraystub;
+ elementclass.cls = pseudo_class_Arraystub;
}
else {
dimension = y->dimension;
/* 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 {
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 {
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) {
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;
}
#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)
{
for (i=0; i<num; ++i) {
if (typebuf[i] != TYPE_ADDRESS)
panic("non-reference type in mergedlist");
- info->merged->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 {
&returntype,info);
}
}
+#endif
#define TYPEINFO_TEST_BUFLEN 4000
{
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;
}
if (!(x->merged && y->merged)) return false;
if (x->merged->count != y->merged->count) return false;
for (i=0; i<x->merged->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;
}
}
+#if 0
static void
typeinfo_inc_dimension(typeinfo *info)
{
}
info->typeclass = class_array_of(info->typeclass);
}
+#endif
#define TYPEINFO_TEST_MAXDIM 10
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 */
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);
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,"<class %p>",c.any);*/
+
+ if (!c.any) {
+ fprintf(file,"<null>");
+ }
+ else {
+ if (IS_CLASSREF(c)) {
+ fprintf(file,"<ref>");
+ utf_fprint(file,c.ref->name);
+ }
+ else {
+ utf_fprint(file,c.cls->name);
+ }
+ }
+}
+
void
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 {
}
fprintf(file,"%sClass: ",ind);
- utf_fprint(file,info->typeclass->name);
+ typeinfo_print_class(file,info->typeclass);
fprintf(file,"\n");
if (TYPEINFO_IS_ARRAY(*info)) {
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;
}
if (info->merged) {
- fprintf(file,"%sMerged: ",ind);
+ fprintf(file,"%sMerged: ",ind);
for (i=0; i<info->merged->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");
}
int i;
instruction *ins;
basicblock *bptr;
+ classref_or_classinfo c;
+
+ /*fprintf(file,"<typeinfo %p>",info);*/
+
+ if (!info) {
+ fprintf(file,"(typeinfo*)NULL");
+ return;
+ }
if (TYPEINFO_IS_PRIMITIVE(*info)) {
bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*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 %p>",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; i<info->merged->count; ++i) {
if (i) fprintf(file,",");
- utf_fprint(file,info->merged->list[i]->name);
+ typeinfo_print_class(file,info->merged->list[i]);
}
fprintf(file,"}");
}
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);
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 *****************************************************/
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.
* 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".
* 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! */
};
/*-----------------------------------------------------------------------*/
/* 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 ********************************************/
#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) \
/* 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)
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)
#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) ***********/
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);
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 ********************************************************/
#include <stdio.h>
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);
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 $
*/
}
+/***************** Function: print_arraydescriptor ****************************
+
+ Debugging helper for displaying an arraydescriptor
+
+*******************************************************************************/
+
+void print_arraydescriptor(FILE *file, arraydescriptor *desc)
+{
+ if (!desc) {
+ fprintf(file, "<NULL>");
+ return;
+ }
+
+ fprintf(file, "{");
+ if (desc->componentvftbl) {
+ if (desc->componentvftbl->class)
+ utf_fprint(file, desc->componentvftbl->class->name);
+ else
+ fprintf(file, "<no classinfo>");
+ }
+ else
+ fprintf(file, "0");
+
+ fprintf(file, ",");
+ if (desc->elementvftbl) {
+ if (desc->elementvftbl->class)
+ utf_fprint(file, desc->elementvftbl->class->name);
+ else
+ fprintf(file, "<no classinfo>");
+ }
+ 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
Changes:
- $Id: linker.h 2148 2005-03-30 16:49:40Z twisti $
+ $Id: linker.h 2181 2005-04-01 16:53:33Z edwin $
*/
typedef struct primitivetypeinfo primitivetypeinfo;
-#include "vm/class.h"
+#include "vm/references.h"
/* virtual function table ******************************************************
bool linker_init(void);
classinfo *link_class(classinfo *c);
+/* debug print arraydescriptor */
+void print_arraydescriptor(FILE *file, arraydescriptor *desc);
+
#endif /* _LINKER_H */
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 $
*/
*******************************************************************************/
-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
} /* 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 */
#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;
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 */
*******************************************************************************/
-static bool load_method(classbuffer *cb, methodinfo *m)
+static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
{
classinfo *c;
s4 argcount;
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))
}
-/***************** Function: print_arraydescriptor ****************************
-
- Debugging helper for displaying an arraydescriptor
-
-*******************************************************************************/
-
-void print_arraydescriptor(FILE *file, arraydescriptor *desc)
-{
- if (!desc) {
- fprintf(file, "<NULL>");
- return;
- }
-
- fprintf(file, "{");
- if (desc->componentvftbl) {
- if (desc->componentvftbl->class)
- utf_fprint(file, desc->componentvftbl->class->name);
- else
- fprintf(file, "<no classinfo>");
- }
- else
- fprintf(file, "0");
-
- fprintf(file, ",");
- if (desc->elementvftbl) {
- if (desc->elementvftbl->class)
- utf_fprint(file, desc->elementvftbl->class->name);
- else
- fprintf(file, "<no classinfo>");
- }
- else
- fprintf(file, "0");
- fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
- desc->dataoffset, desc->componentsize);
-}
-
-
/* load_class_from_classloader *************************************************
XXX
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;
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 */
"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;
/* 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*/
new_classformaterror(c,
"Illegal class modifiers: 0x%X", c->flags);
- return NULL;
+ goto return_exception;
}
if (c->flags & ACC_SUPER) {
*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);
*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) {
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. */
new_exception_message(string_java_lang_ClassFormatError,
"Interfaces must have java.lang.Object as superclass");
- return NULL;
+ goto return_exception;
}
} else {
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; i<c->cpcount; ++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
new_classformaterror(c,
"Repetitive field name/signature");
- return NULL;
+ goto return_exception;
}
} while ((old = next[old]));
}
new_classformaterror(c,
"Repetitive method name/signature");
- return NULL;
+ goto return_exception;
}
} while ((old = next[old]));
}
/* 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
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;
}
{
classinfo *comp = NULL;
methodinfo *clone;
+ methoddesc *clonedesc;
+ constant_classref *classrefs;
int namelen;
/* Check array class name */
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;
/* 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 */
}
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 $
*/
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"
*******************************************************************************/
-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;
/* 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);
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"
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 $
*/
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"
--- /dev/null
+/* 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:
+ */
+
Changes:
- $Id: resolve.c 2148 2005-03-30 16:49:40Z twisti $
+ $Id: resolve.c 2181 2005-04-01 16:53:33Z edwin $
*/
/* DEBUG HELPERS */
/******************************************************************************/
+/*#define RESOLVE_VERBOSE*/
+
#ifndef NDEBUG
#define RESOLVE_DEBUG
#endif
classinfo **result)
{
classinfo *cls = NULL;
+ char *utf_ptr;
+ int len;
RESOLVE_ASSERT(result);
RESOLVE_ASSERT(referer);
*result = NULL;
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
fprintf(stderr,"resolve_class(");
utf_fprint(stderr,referer->name);
fprintf(stderr,",");
/* 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
}
/* resolution succeeds */
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
fprintf(stderr," success.\n");
#endif
*result = cls;
if (link) {
if (!c->linked)
- if (!class_link(c))
+ if (!link_class(c))
return false; /* exception */
RESOLVE_ASSERT(c->linked);
}
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)) {
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");
/* 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;
*result = NULL;
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
unresolved_field_debug_dump(ref,stderr);
#endif
/* 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
RESOLVE_ASSERT(declarer);
RESOLVE_ASSERT(declarer->loaded && declarer->linked);
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
fprintf(stderr," checking static...\n");
#endif
/* 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
/* 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,
/* 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 */
RESOLVE_ASSERT(result);
RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
unresolved_method_debug_dump(ref,stderr);
#endif
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);
count = tinfo->merged->count;
stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
for (i=0; i<count; ++i) {
- stset->subtyperefs[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 */
}
}
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);
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);
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);
Changes:
- $Id: resolve.h 2112 2005-03-29 21:29:08Z twisti $
+ $Id: resolve.h 2181 2005-04-01 16:53:33Z edwin $
*/
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/references.h"
#include "vm/jit/jit.h"
} 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 {
#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 ***************************************************************
Changes:
- $Id: stringlocal.h 1926 2005-02-10 10:47:29Z twisti $
+ $Id: stringlocal.h 2181 2005-04-01 16:53:33Z edwin $
*/
#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 **********/
Changes:
- $Id: utf8.h 2158 2005-03-30 20:06:37Z twisti $
+ $Id: utf8.h 2181 2005-04-01 16:53:33Z edwin $
*/
typedef struct utf utf;
-#include "types.h"
#include "vm/global.h"