-/* jit/typecheck.c - typechecking (part of bytecode verification)
+/* vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ 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.
Authors: Edwin Steiner
- $Id: typecheck.c 1348 2004-07-22 09:57:51Z twisti $
+ $Id: typecheck.c 1735 2004-12-07 14:33:27Z twisti $
*/
-#include "global.h" /* must be here because of CACAO_TYPECHECK */
+#include <string.h>
+
+#include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
#ifdef CACAO_TYPECHECK
-#include <string.h>
-#include "main.h"
-#include "builtin.h"
-#include "tables.h"
-#include "loader.h"
-#include "native.h"
#include "types.h"
-#include "jit/jit.h"
-#include "jit/stack.h"
+/* #include "main.h" */
+#include "mm/memory.h"
#include "toolbox/logging.h"
-#include "toolbox/memory.h"
+#include "native/native.h"
+#include "vm/builtin.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/tables.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/stack.h"
+
/****************************************************************************/
/* DEBUG HELPERS */
static bool
-typestate_reach(methodinfo *m, void *localbuf,
+typestate_reach(codegendata *cd, registerdata *rd,void *localbuf,
basicblock *current,
basicblock *destblock,
stackptr ystack,typevector *yloc,
LOG1("reaching block L%03d",destblock->debug_nr);
TYPECHECK_COUNT(stat_reached);
- destidx = destblock - m->basicblocks;
+ destidx = destblock - cd->method->basicblocks;
destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
/* When branching backwards we have to check for uninitialized objects */
if (destblock <= current) {
stackptr sp;
int i;
-
- TYPECHECK_COUNT(stat_backwards);
- LOG("BACKWARDS!");
- for (sp = ystack; sp; sp=sp->prev)
- if (sp->type == TYPE_ADR &&
- TYPEINFO_IS_NEWOBJECT(sp->typeinfo))
- panic("Branching backwards with uninitialized object on stack");
-
- for (i=0; i<locsize; ++i)
- if (yloc->td[i].type == TYPE_ADR &&
- TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
- panic("Branching backwards with uninitialized object in local variable");
- }
+#if defined(__GNUC__)
+#warning FIXME FOR INLINING
+#endif
+ if (!useinlining) {
+ TYPECHECK_COUNT(stat_backwards);
+ LOG("BACKWARDS!");
+ for (sp = ystack; sp; sp=sp->prev)
+ if (sp->type == TYPE_ADR &&
+ TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
+ show_icmd_method(cd->method,cd,rd);
+ printf("current: %ld, dest: %ld\n",current->debug_nr,destblock->debug_nr);
+ panic("Branching backwards with uninitialized object on stack");
+ }
+
+ for (i=0; i<locsize; ++i)
+ if (yloc->td[i].type == TYPE_ADR &&
+ TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
+ panic("Branching backwards with uninitialized object in local variable");
+ }
+ }
if (destblock->flags == BBTYPECHECK_UNDEF) {
/* The destblock has never been reached before */
static bool
-typestate_ret(methodinfo *m, void *localbuf,
+typestate_ret(codegendata *cd,registerdata *rd, void *localbuf,
basicblock *current,
stackptr ystack,typevector *yloc,
int retindex,int locsize)
selected = typevectorset_select(&yvec,retindex,destblock);
- repeat |= typestate_reach(m, localbuf,current,destblock,
+ repeat |= typestate_reach(cd, rd, localbuf,current,destblock,
ystack,selected,locsize,true);
}
return repeat;
#define STORE_TWOWORD(num,type) \
do {typevectorset_store_twoword(localset,num,type);} while(0)
+
+#define WORDCHECKFAULT \
+ do { \
+ show_icmd_method(m, cd, rd); \
+ dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
+ iptr->op1,iptr->method->class->name->text, \
+ iptr->method->name->text,m->class->name->text,m->name->text); \
+ show_icmd(iptr++, false); \
+ show_icmd(iptr, false); \
+ } while (0)
+
+
#define CHECK_ONEWORD(num,tp) \
do {TYPECHECK_COUNT(stat_ins_primload); \
if (jsrencountered) { \
- if (!typevectorset_checktype(localset,num,tp)) \
+ if (!typevectorset_checktype(localset,num,tp)) { \
+ WORDCHECKFAULT; \
panic("Variable type mismatch"); \
+ } \
} \
else { \
- if (localset->td[num].type != tp) \
+ if (localset->td[num].type != tp) { \
panic("Variable type mismatch"); \
+ WORDCHECKFAULT; \
+ } \
} \
} while(0)
#define CHECK_TWOWORD(num,type) \
do {TYPECHECK_COUNT(stat_ins_primload); \
- if (!typevectorset_checktype(localset,num,type)) \
- panic("Variable type mismatch"); \
- } while(0)
+ if (!typevectorset_checktype(localset,num,type)) { \
+ WORDCHECKFAULT; \
+ panic("Variable type mismatch"); \
+ } \
+ } while(0)
/****************************************************************************/
/* MACROS FOR STACK TYPE CHECKING */
{if ((source)->type == TYPE_ADR) \
TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
-#define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
+#define ISBUILTIN(v) (iptr->val.fp == (functionptr) (v))
/* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
* from the current block (bptr). The types of local variables and
*/
#define TYPECHECK_REACH \
do { \
- repeat |= typestate_reach(m, localbuf,bptr,tbptr,dst, \
+ repeat |= typestate_reach(cd,rd, localbuf,bptr,tbptr,dst, \
localset,numlocals,jsrencountered); \
LOG("done."); \
} while (0)
/* typecheck is called directly after analyse_stack */
-methodinfo *typecheck(methodinfo *m)
+methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
{
int b_count, b_index;
stackptr curstack; /* input stack top for current instruction */
#ifdef TYPECHECK_STATISTICS
int count_iterations = 0;
TYPECHECK_COUNT(stat_typechecked);
- TYPECHECK_COUNT_FREQ(stat_locals,m->maxlocals,STAT_LOCALS);
+ TYPECHECK_COUNT_FREQ(stat_locals,m->codegendata->maxlocals,STAT_LOCALS);
TYPECHECK_COUNT_FREQ(stat_blocks,m->basicblockcount/10,STAT_BLOCKS);
#endif
/* In <init> methods we use an extra local variable to signal if
* the 'this' reference has been initialized. */
- numlocals = m->maxlocals;
+ numlocals = cd->maxlocals;
validlocals = numlocals;
if (initmethod) numlocals++;
LOG("Variable buffer allocated.\n");
/* allocate the buffer of active exception handlers */
- handlers = DMNEW(exceptiontable*, m->exceptiontablelength + 1);
+ handlers = DMNEW(exceptiontable*, cd->exceptiontablelength + 1);
/* initialize the variable types of the first block */
/* to the types of the arguments */
/* XXX could use a faster algorithm with sorted lists or
* something? */
len = 0;
- for (i = 0; i < m->exceptiontablelength; ++i) {
- if ((m->exceptiontable[i].start <= bptr) && (m->exceptiontable[i].end > bptr)) {
- LOG1("active handler L%03d", m->exceptiontable[i].handler->debug_nr);
- handlers[len++] = m->exceptiontable + i;
+ for (i = 0; i < cd->exceptiontablelength; ++i) {
+ if ((cd->exceptiontable[i].start <= bptr) && (cd->exceptiontable[i].end > bptr)) {
+ LOG1("active handler L%03d", cd->exceptiontable[i].handler->debug_nr);
+ handlers[len++] = cd->exceptiontable + i;
}
}
handlers[len] = NULL;
/* init variable types at the start of this block */
COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
localset,numlocals);
+#if defined(__GNUC__)
+#warning FIXME FOR INLINING
+#endif
+ if(!useinlining) {
if (handlers[0])
for (i=0; i<numlocals; ++i)
if (localset->td[i].type == TYPE_ADR
- && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
- panic("Uninitialized object in local variable inside try block");
-
+ && TYPEINFO_IS_NEWOBJECT(localset->td[i].info)) {
+ show_icmd_method(m, cd, rd);
+ printf("Uninitialized variale:%ld, block:%ld\n",i,bptr->debug_nr);
+ panic("Uninitialized object in local variable inside try block");
+ }
+ }
DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
LOGNL; LOGFLUSH;
typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
}
else {
- if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1]))
+ if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1])) {
+ show_icmd_method(m, cd, rd);
+ dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n",
+ iptr->op1,iptr->method->class->name->text,
+ iptr->method->name->text,m->class->name->text,m->name->text);
+ show_icmd(iptr, false);
panic("illegal instruction: ALOAD loading non-reference");
+ }
TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
}
break;
if (bptr + 1 == (m->basicblocks + m->basicblockcount + 1))
panic("Illegal instruction: JSR at end of bytecode");
typestack_put_retaddr(dst,bptr+1,localset);
- repeat |= typestate_reach(m, localbuf,bptr,tbptr,dst,
+ repeat |= typestate_reach(cd, rd,localbuf,bptr,tbptr,dst,
localset,numlocals,true);
superblockend = true;
if (!typevectorset_checkretaddr(localset,iptr->op1))
panic("illegal instruction: RET using non-returnAddress variable");
- repeat |= typestate_ret(m, localbuf,bptr,curstack,
+ repeat |= typestate_ret(cd,rd, localbuf,bptr,curstack,
localset,iptr->op1,numlocals);
superblockend = true;
LOG("saving input stack types");
if (!savedstackbuf) {
LOG("allocating savedstack buffer");
- savedstackbuf = DMNEW(stackelement,m->maxstack);
+ savedstackbuf = DMNEW(stackelement, cd->maxstack);
savedstackbuf->prev = NULL;
- for (i=1; i<m->maxstack; ++i)
+ for (i = 1; i < cd->maxstack; ++i)
savedstackbuf[i].prev = savedstackbuf+(i-1);
}
sp = savedstack = bptr->instack;
TYPECHECK_COUNT(stat_ins_builtin_gen);
builtindesc = builtin_desc;
while (builtindesc->opcode && builtindesc->builtin
- != (functionptr) iptr->val.a) builtindesc++;
+ != iptr->val.fp) builtindesc++;
if (!builtindesc->opcode) {
- dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
+ dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
panic("Internal error: builtin not found in table");
}
TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
TYPECHECK_COUNT(stat_ins_builtin_gen);
builtindesc = builtin_desc;
while (builtindesc->opcode && builtindesc->builtin
- != (functionptr) iptr->val.a) builtindesc++;
+ != iptr->val.fp) builtindesc++;
if (!builtindesc->opcode) {
- dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
+ dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
panic("Internal error: builtin not found in table");
}
TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
TYPECHECK_COUNT(stat_ins_builtin_gen);
builtindesc = builtin_desc;
while (builtindesc->opcode && builtindesc->builtin
- != (functionptr) iptr->val.a) builtindesc++;
+ != iptr->val.fp) builtindesc++;
if (!builtindesc->opcode) {
- dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
+ dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
panic("Internal error: builtin not found in table");
}
TYPECHECK_ARGS1(builtindesc->type_s1);
cls = handlers[i]->catchtype;
excstack.typeinfo.typeclass = (cls) ? cls
: class_java_lang_Throwable;
- repeat |= typestate_reach(m, localbuf,bptr,
+ repeat |= typestate_reach(cd,rd, localbuf,bptr,
handlers[i]->handler,
&excstack,localset,
numlocals,