/* src/vm/jit/verify/typecheck-common.h - internal header for the type checker Copyright (C) 1996-2005, 2006, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _TYPECHECK_COMMON_H #define _TYPECHECK_COMMON_H #include "config.h" #include "vm/types.h" #include "vm/global.h" #include #include "vm/jit/jit.hpp" #if defined(__cplusplus) extern "C" { #endif /****************************************************************************/ /* DEBUG HELPERS */ /****************************************************************************/ #ifdef TYPECHECK_DEBUG #define TYPECHECK_ASSERT(cond) assert(cond) #else #define TYPECHECK_ASSERT(cond) #endif #ifdef TYPECHECK_VERBOSE_OPT extern bool opt_typecheckverbose; #define DOLOG(action) do { if (opt_typecheckverbose) {action;} } while(0) #else #define DOLOG(action) #endif #ifdef TYPECHECK_VERBOSE #define TYPECHECK_VERBOSE_IMPORTANT #define LOGNL DOLOG(puts("")) #define LOG(str) DOLOG(puts(str);) #define LOG1(str,a) DOLOG(printf(str,a); LOGNL) #define LOG2(str,a,b) DOLOG(printf(str,a,b); LOGNL) #define LOG3(str,a,b,c) DOLOG(printf(str,a,b,c); LOGNL) #define LOGIF(cond,str) DOLOG(do {if (cond) { puts(str); }} while(0)) #ifdef TYPEINFO_DEBUG #define LOGINFO(info) DOLOG(do {typeinfo_print_short(stdout,(info)); LOGNL;} while(0)) #else #define LOGINFO(info) #define typevector_print(x,y,z) #endif #define LOGFLUSH DOLOG(fflush(stdout)) #define LOGSTR(str) DOLOG(printf("%s", str)) #define LOGSTR1(str,a) DOLOG(printf(str,a)) #define LOGSTR2(str,a,b) DOLOG(printf(str,a,b)) #define LOGSTR3(str,a,b,c) DOLOG(printf(str,a,b,c)) #define LOGNAME(c) DOLOG(class_classref_or_classinfo_print(c)) #define LOGMETHOD(str,m) DOLOG(printf("%s", str); method_println(m);) #else #define LOG(str) #define LOG1(str,a) #define LOG2(str,a,b) #define LOG3(str,a,b,c) #define LOGIF(cond,str) #define LOGINFO(info) #define LOGFLUSH #define LOGNL #define LOGSTR(str) #define LOGSTR1(str,a) #define LOGSTR2(str,a,b) #define LOGSTR3(str,a,b,c) #define LOGNAME(c) #define LOGMETHOD(str,m) #endif #ifdef TYPECHECK_VERBOSE_IMPORTANT #define LOGimp(str) DOLOG(puts(str);LOGNL) #define LOGimpSTR(str) DOLOG(puts(str)) #else #define LOGimp(str) #define LOGimpSTR(str) #endif #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT) #include void typecheck_print_var(FILE *file, jitdata *jd, s4 index); void typecheck_print_vararray(FILE *file, jitdata *jd, s4 *vars, int len); #endif /****************************************************************************/ /* STATISTICS */ /****************************************************************************/ #if defined(TYPECHECK_DEBUG) && !defined(TYPECHECK_NO_STATISTICS) /*#define TYPECHECK_STATISTICS*/ #endif #ifdef TYPECHECK_STATISTICS #define STAT_ITERATIONS 10 #define STAT_BLOCKS 10 #define STAT_LOCALS 16 extern int stat_typechecked; extern int stat_methods_with_handlers; extern int stat_methods_maythrow; extern int stat_iterations[STAT_ITERATIONS+1]; extern int stat_reached; extern int stat_copied; extern int stat_merged; extern int stat_merging_changed; extern int stat_blocks[STAT_BLOCKS+1]; extern int stat_locals[STAT_LOCALS+1]; extern int stat_ins; extern int stat_ins_maythrow; extern int stat_ins_stack; extern int stat_ins_field; extern int stat_ins_field_unresolved; extern int stat_ins_field_uninitialized; extern int stat_ins_invoke; extern int stat_ins_invoke_unresolved; extern int stat_ins_primload; extern int stat_ins_aload; extern int stat_ins_builtin; extern int stat_ins_builtin_gen; extern int stat_ins_branch; extern int stat_ins_switch; extern int stat_ins_primitive_return; extern int stat_ins_areturn; extern int stat_ins_areturn_unresolved; extern int stat_ins_athrow; extern int stat_ins_athrow_unresolved; extern int stat_ins_unchecked; extern int stat_handlers_reached; extern int stat_savedstack; #define TYPECHECK_MARK(var) ((var) = true) #define TYPECHECK_COUNT(cnt) (cnt)++ #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0) #define TYPECHECK_COUNT_FREQ(array,val,limit) \ do { \ if ((val) < (limit)) (array)[val]++; \ else (array)[limit]++; \ } while (0) void typecheck_print_statistics(FILE *file); #else /* !defined(TYPECHECK_STATISTICS) */ #define TYPECHECK_COUNT(cnt) #define TYPECHECK_MARK(var) #define TYPECHECK_COUNTIF(cond,cnt) #define TYPECHECK_COUNT_FREQ(array,val,limit) #endif /* defined(TYPECHECK_STATISTICS) */ /****************************************************************************/ /* MACROS FOR THROWING EXCEPTIONS */ /****************************************************************************/ #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \ do { \ exceptions_throw_verifyerror((m), (msg)); \ return (retval); \ } while (0) #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL) #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false) /****************************************************************************/ /* MISC MACROS */ /****************************************************************************/ #define COPYTYPE(source,dest) \ {if (VAROP(source)->type == TYPE_ADR) \ TYPEINFO_COPY(VAROP(source)->typeinfo,VAROP(dest)->typeinfo);} /****************************************************************************/ /* JSR VERIFICATION (stack-based verifier) */ /****************************************************************************/ typedef struct typecheck_jsr_t typecheck_jsr_t; typedef struct typecheck_jsr_caller_t typecheck_jsr_caller_t; struct typecheck_jsr_caller_t { typecheck_jsr_caller_t *next; /* next in linked list */ basicblock *callblock; /* block containing the calling JSR */ }; struct typecheck_jsr_t { typecheck_jsr_t *next; /* next (lower) in the call chain */ basicblock *start; /* for debugging */ typecheck_jsr_caller_t *callers; /* list of callers (blocks with JSR) */ basicblock *retblock; /* block with the RET for this sub */ bool active; /* true if this sub is currently active */ char *blockflags; /* saved block flags when JSR was traversed */ char *usedlocals; /* != 0 for each local used in this sub */ typedescriptor_t *retlocals; /* locals on the RET edge */ typedescriptor_t *retstack; /* stack on the RET edge */ s4 retdepth; /* stack depth on the RET edge */ }; /****************************************************************************/ /* VERIFIER STATE STRUCT */ /****************************************************************************/ /* verifier_state - This structure keeps the current state of the */ /* bytecode verifier for passing it between verifier functions. */ typedef struct verifier_state { instruction *iptr; /* pointer to current instruction */ basicblock *bptr; /* pointer to current basic block */ methodinfo *m; /* the current method */ jitdata *jd; /* jitdata for current method */ codegendata *cd; /* codegendata for current method */ basicblock *basicblocks; s4 basicblockcount; s4 numlocals; /* number of local variables */ s4 validlocals; /* number of Java-accessible locals */ typedescriptor_t returntype; /* return type of the current method */ s4 *savedindices; s4 *savedinvars; /* saved invar pointer */ s4 exinvars; exception_entry **handlers; /* active exception handlers */ bool repeat; /* if true, blocks are iterated over again */ bool initmethod; /* true if this is an "" method */ #ifdef TYPECHECK_STATISTICS bool stat_maythrow; /* at least one instruction may throw */ #endif /* the following fields are used by the stackbased verifier only: */ typedescriptor_t *locals; /* current local variables */ typedescriptor_t *startlocals;/* locals at the start of each block */ typedescriptor_t *startstack; /* stack at the start of each block */ s4 *indepth; /* stack depth at --''-- */ typedescriptor_t *stackceiling; /* upper edge of verifier stack */ typecheck_jsr_t *topjsr; /* most recently called subroutine */ typecheck_jsr_t **jsrinfos; /* subroutine info for each block */ } verifier_state; void typecheck_init_flags(verifier_state *state, s4 minflags); void typecheck_reset_flags(verifier_state *state); bool typecheck_copy_types(verifier_state *state, s4 *srcvars, s4 *dstvars, s4 n); typecheck_result typecheck_merge_types(verifier_state *state, s4 *srcvars, s4 *dstvars, s4 n); typecheck_result typestate_merge(verifier_state *state, s4 *srcvars, varinfo *srclocals, s4 *dstvars, varinfo *dstlocals, s4 n); bool typestate_reach(verifier_state *state, basicblock *destblock, s4 *srcvars, varinfo *srclocals, s4 n); bool typecheck_init_locals(verifier_state *state, bool newthis); #if defined(__cplusplus) } #endif #endif /* _TYPECHECK_COMMON_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: */