X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fjit.h;h=de45e2d222e0dfd9bc6412fc91291e66660c45c5;hb=63429f68692b49b4c18e739e96918bc010c33ca5;hp=f6c63a8271268c79efa734e0ce09d07448cc55a0;hpb=cfef9f2e80f715dede980020e6040932c190c8cc;p=cacao.git diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index f6c63a827..de45e2d22 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -26,11 +26,10 @@ Authors: Andreas Krall Reinhard Grafl + Christian Thalinger + Edwin Steiner - Changes: Christian Thalinger - Edwin Steiner - - $Id: jit.h 5352 2006-09-05 22:51:48Z christian $ + $Id: jit.h 6211 2006-12-16 22:53:24Z edwin $ */ @@ -47,6 +46,7 @@ typedef struct basicblock basicblock; typedef struct branchref branchref; typedef struct instruction instruction; typedef struct insinfo_inline insinfo_inline; +typedef struct exception_entry exception_entry; #include "config.h" @@ -61,6 +61,7 @@ typedef struct insinfo_inline insinfo_inline; #include "vm/jit/codegen-common.h" #include "vm/jit/reg.h" #include "vm/jit/stacktrace.h" +#include "vm/jit/replace.h" #if defined(ENABLE_INLINING) # include "vm/jit/inline/inline.h" @@ -88,11 +89,18 @@ typedef struct insinfo_inline insinfo_inline; # define COUNT_SPILLS /* nothing */ #endif +typedef struct interface_info interface_info; + +struct interface_info { + s4 flags; + s4 regoff; +}; + /* jitdata ********************************************************************/ struct jitdata { - methodinfo *m; /* methodinfo of the method compiled */ + methodinfo *m; /* methodinfo of the method compiled */ codeinfo *code; codegendata *cd; registerdata *rd; @@ -100,33 +108,48 @@ struct jitdata { loopdata *ld; #endif #if defined(ENABLE_SSA) || defined(ENABLE_LSRA) - lsradata *ls; + lsradata *ls; #endif - u4 flags; /* contains JIT compiler flags */ - bool isleafmethod; /* does method call subroutines */ - - instruction *new_instructions; - basicblock *new_basicblocks; - s4 *new_basicblockindex; - stackelement *new_stack; - s4 new_instructioncount; - s4 new_basicblockcount; - s4 new_stackcount; - s4 new_c_debug_nr; - -/* #if defined(NEW_VAR) */ -/* varinfo **var; */ -/* int var_top; */ + u4 flags; /* contains JIT compiler flags */ + bool isleafmethod; /* true, if no subroutines are called */ + + instruction *instructions; /* ICMDs, valid between parse and stack */ + basicblock *basicblocks; /* start of basic block list */ + s4 *basicblockindex; /* block index for each JavaPC */ + /* valid between parse and stack */ + stackelement *stack; /* XXX should become stack.c internal */ + s4 instructioncount;/* XXX remove this? */ + s4 basicblockcount; /* number of basic blocks */ + s4 stackcount; /* number of stackelements to allocate */ + /* (passed from parse to stack) */ + + varinfo *var; /* array of variables */ + s4 vartop; /* next free index in var array */ - int *local_map; /* internal structure to rename(de-coallesc) locals */ - /* and keep the coalescing info for simplereg. */ - /* local_map[local_index * 5 + local_type] = new_index in */ - /* rd->var or LOCAL_UNUSED */ -/* #endif */ + s4 varcount; /* number of variables in var array */ + s4 localcount; /* number of locals at start of var ar. */ + s4 *local_map; /* internal structure to rename(de-coallesc) */ + /* locals and keep the coalescing info for simplereg. */ + /* local_map[local_index * 5 + local_type] = */ + /* new_index in rd->var or UNUSED */ + s4 maxlocals; /* max. number of javalocals */ + + interface_info *interface_map; /* interface variables (for simplereg) */ + s4 maxinterfaces; /* max. number of interface variables */ + + s4 exceptiontablelength; /* exceptiontable length */ + exception_entry *exceptiontable; /* the exceptiontable */ + + basicblock *returnblock; /* block containing the *RETURN */ + /* (only use if returncount==1) */ + s4 returncount; /* number of return instructions */ + bool branchtoentry; /* true if first block is a target */ + bool branchtoend; /* true if end dummy is a target */ }; -#define LOCAL_UNUSED -1 + +#define UNUSED -1 #define JITDATA_FLAG_PARSE 0x00000001 #define JITDATA_FLAG_VERIFY 0x00000002 @@ -135,6 +158,9 @@ struct jitdata { #define JITDATA_FLAG_IFCONV 0x00000008 #define JITDATA_FLAG_REORDER 0x00000010 +#define JITDATA_FLAG_INLINE 0x00000020 + +#define JITDATA_FLAG_COUNTDOWN 0x00000100 #define JITDATA_FLAG_SHOWINTERMEDIATE 0x20000000 #define JITDATA_FLAG_SHOWDISASSEMBLE 0x40000000 @@ -156,6 +182,12 @@ struct jitdata { #define JITDATA_HAS_FLAG_REORDER(jd) \ ((jd)->flags & JITDATA_FLAG_REORDER) +#define JITDATA_HAS_FLAG_INLINE(jd) \ + ((jd)->flags & JITDATA_FLAG_INLINE) + +#define JITDATA_HAS_FLAG_COUNTDOWN(jd) \ + ((jd)->flags & JITDATA_FLAG_COUNTDOWN) + #define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \ ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE) @@ -166,18 +198,46 @@ struct jitdata { ((jd)->flags & JITDATA_FLAG_VERBOSECALL) -/************************** stack element structure ***************************/ +/* macros for accessing variables ********************************************* + + Use VAROP for s1, s2, s3 and dst operands (eg. VAROP(iptr->s1)), + use VAR if you have the variable index (eg. VAR(iptr->sx.s23.s2.args[0])). + +******************************************************************************/ + +#define VAROP(v) (jd->var + (v).varindex) +#define VAR(i) (jd->var + (i)) + + +/* exception_entry ************************************************************/ + +struct exception_entry { + basicblock *start; + basicblock *end; + basicblock *handler; + classref_or_classinfo catchtype; /* catchtype of exc. (NULL == catchall) */ + exception_entry *next; /* next in list of exceptions when */ + /* loops are copied */ + exception_entry *down; /* next exception_entry */ +}; + + +/* stack element structure ****************************************************/ /* flags */ -#define SAVEDVAR 1 /* variable has to survive method invocations */ -#define INMEMORY 2 /* variable stored in memory */ -#define SAVEDTMP 4 /* temporary variable using a saved register */ -#define TMPARG 8 /* temporary variable using a arg register */ -#define STCOPY 16 /* there is another stackslot alive "below" */ - /* using the same register/memory location */ -#define STKEEP 32 /* to prevent reg_mark_copy to free this */ - /* stackslot */ +#define SAVEDVAR 1 /* variable has to survive method invocations */ +#define INMEMORY 2 /* variable stored in memory */ +#define SAVREG 4 /* allocated to a saved register */ +#define ARGREG 8 /* allocated to an arg register */ +#define PASSTHROUGH 32 /* stackslot was passed-through by an ICMD */ +#define PREALLOC 64 /* preallocated var like for ARGVARS. Used */ + /* with the new var system */ +#define INOUT 128 /* variable is an invar or/and an outvar */ + +#define IS_SAVEDVAR(x) ((x) & SAVEDVAR) +#define IS_INMEMORY(x) ((x) & INMEMORY) + /* variable kinds */ @@ -190,14 +250,11 @@ struct jitdata { struct stackelement { stackptr prev; /* pointer to next element towards bottom */ + instruction *creator; /* instruction that created this element */ s4 type; /* slot type of stack element */ -#ifdef ENABLE_VERIFIER - typeinfo typeinfo; /* info on reference types */ -#endif s4 flags; /* flags (SAVED, INMEMORY) */ s4 varkind; /* kind of variable or register */ s4 varnum; /* number of variable */ - s4 regoff; /* register number or memory offset */ }; @@ -220,27 +277,27 @@ typedef struct { /*** s1 operand ***/ typedef union { - stackptr var; - s4 localindex; + s4 varindex; s4 argcount; } s1_operand_t; /*** s2 operand ***/ typedef union { - stackptr var; - stackptr *args; + s4 varindex; + s4 *args; classref_or_classinfo c; unresolved_class *uc; ptrint constval; /* for PUT*CONST */ s4 tablelow; /* for TABLESWITCH */ u4 lookupcount; /* for LOOKUPSWITCH */ + s4 retaddrnr; /* for ASTORE */ } s2_operand_t; /*** s3 operand ***/ typedef union { - stackptr var; + s4 varindex; ptrint constval; classref_or_classinfo c; constant_FMIref *fmiref; @@ -250,6 +307,7 @@ typedef union { s4 tablehigh; /* for TABLESWITCH */ branch_target_t lookupdefault; /* for LOOKUPSWITCH */ branch_target_t jsrtarget; /* for JSR */ + s4 javaindex; /* for *STORE */ struct builtintable_entry *bte; } s3_operand_t; @@ -268,47 +326,29 @@ typedef union { /*** dst operand ***/ typedef union { - stackptr var; - s4 localindex; + s4 varindex; basicblock *block; /* valid after stack analysis */ branch_target_t *table; /* for TABLESWITCH */ lookup_target_t *lookup; /* for LOOKUPSWITCH */ s4 insindex; /* used between parse and stack */ - stackptr *dupslots; /* for SWAP, DUP* except DUP */ } dst_operand_t; /*** flags (32 bits) ***/ #define INS_FLAG_UNRESOLVED 0x01 /* contains unresolved field/meth/class*/ -#define INS_FLAG_CLASS 0x02 /* for ACONST with class */ +#define INS_FLAG_CLASS 0x02 /* for ACONST, PUT*CONST with class */ #define INS_FLAG_ARRAY 0x04 /* for CHECKCAST/INSTANCEOF with array */ -#define INS_FLAG_NOCHECK 0x08 +#define INS_FLAG_CHECK 0x08 /* for *ALOAD|*ASTORE: check index */ + /* for BUILTIN: check exception */ +#define INS_FLAG_KILL_PREV 0x02 /* for *STORE, invalidate prev local */ +#define INS_FLAG_KILL_NEXT 0x04 /* for *STORE, invalidate next local */ +#define INS_FLAG_RETADDR 0x08 /* for ASTORE: op is a returnAddress */ + +#define INS_FLAG_ID_SHIFT 4 +#define INS_FLAG_ID_MASK (~0 << INS_FLAG_ID_SHIFT) typedef union { u4 bits; - struct { /* fields: */ - - union { - u1 type; /* TYPE_* constant for fields */ - u1 argcount; /* XXX does u1 suffice? */ - /* for MULTIANEWARRAY and */ - /* INVOKE* */ - } f; /* XXX these could be made smaller */ - /* only MULTIANEWARRAY needs the argcount */ - - bool predicated:1; - int condition :3; - bool unresolved:1; /* field/method is unresolved */ - bool nocheck :1; /* don't check array access */ - bool branch :1; /* branch to dst.target */ - - int tmpreg1 :5; - int tmpreg2 :5; - int tmpreg3 :5; - - int unused :2; - - } fields; } flags_operand_t; /*** instruction ***/ @@ -343,7 +383,7 @@ struct instruction { ((iptr)->flags.bits & INS_FLAG_UNRESOLVED) #define INSTRUCTION_MUST_CHECK(iptr) \ - (!((iptr)->flags.bits & INS_FLAG_NOCHECK)) + ((iptr)->flags.bits & INS_FLAG_CHECK) #define INSTRUCTION_GET_FIELDREF(iptr,fref) \ do { \ @@ -375,15 +415,31 @@ struct instruction { /* for ICMD_INLINE_START and ICMD_INLINE_END */ struct insinfo_inline { - methodinfo *method; /* the inlined method starting/ending here */ - methodinfo *outer; /* the outer method suspended/resumed here */ - s4 startmpc; /* machine code offset of start of inlining */ - s4 synclocal; /* local index used for synchronization */ - bool synchronize; /* true if synchronization is needed */ + /* fields copied from the inlining tree ----------------------------------*/ + insinfo_inline *parent; /* insinfo of the surrounding inlining, if any*/ + methodinfo *method; /* the inlined method starting/ending here */ + methodinfo *outer; /* the outer method suspended/resumed here */ + s4 synclocal; /* local index used for synchronization */ + bool synchronize; /* true if synchronization is needed */ + s4 throughcount; /* total # of pass-through variables */ + s4 paramcount; /* number of parameters of original call */ + s4 stackvarscount; /* source stackdepth at INLINE_START */ + s4 *stackvars; /* stack vars at INLINE_START */ + + /* fields set by inlining ------------------------------------------------*/ + s4 *javalocals_start; /* javalocals at start of inlined body */ + s4 *javalocals_end; /* javalocals after inlined body */ + + /* fields set by replacement point creation ------------------------------*/ + rplpoint *rp; /* replacement point at INLINE_START */ + + /* fields set by the codegen ---------------------------------------------*/ + s4 startmpc; /* machine code offset of start of inlining */ }; + /* basicblock *****************************************************************/ - + /* flags */ #define BBDELETED -2 @@ -405,20 +461,26 @@ struct insinfo_inline { /* combined without loss of efficiency. The first one could be combined with */ /* the others by using bitfields. */ +/* XXX "flags" should probably be called "state", as it is an integer state */ + struct basicblock { s4 nr; /* basic block number */ s4 flags; /* used during stack analysis, init with -1 */ s4 bitflags; /* OR of BBFLAG_... constants, init with 0 */ s4 type; /* basic block type (std, xhandler, subroutine*/ - instruction *iinstr; /* pointer to intermediate code instructions */ + s4 lflags; /* used during loop copying, init with 0 */ + s4 icount; /* number of intermediate code instructions */ - s4 mpc; /* machine code pc at start of block */ - stackptr instack; /* stack at begin of basic block */ - stackptr *invars; /* array of in-variables at begin of block */ - stackptr outstack; /* stack at end of basic block */ - stackptr *outvars; /* array of out-variables at end of block */ + instruction *iinstr; /* pointer to intermediate code instructions */ + + varinfo *inlocals; /* copy of locals on block entry */ + s4 *javalocals; /* map from java locals to cacao variables */ + s4 *invars; /* array of in-variables at begin of block */ + s4 *outvars; /* array of out-variables at end of block */ s4 indepth; /* stack depth at begin of basic block */ s4 outdepth; /* stack depth end of basic block */ + s4 varstart; /* index of first non-invar block variable */ + s4 varcount; /* number of non-invar block variables */ s4 predecessorcount; s4 successorcount; @@ -428,12 +490,14 @@ struct basicblock { branchref *branchrefs; /* list of branches to be patched */ basicblock *next; /* used to build a BB list (instead of array) */ - s4 lflags; /* used during loop copying, init with 0 */ basicblock *copied_to; /* points to the copy of this basic block */ /* when loop nodes are copied */ - stackptr stack; /* start of stack array for this block */ - /* (see doc/stack.txt) */ + basicblock *original; /* block of which this block is a clone */ + /* NULL for the original block itself */ methodinfo *method; /* method this block belongs to */ + insinfo_inline *inlineinfo; /* inlineinfo for the start of this block */ + + s4 mpc; /* machine code pc at start of block */ }; @@ -446,7 +510,6 @@ struct basicblock { bptr->flags = -1; \ bptr->type = BBTYPE_STD; \ bptr->method = (m); \ - bptr->nr = (m)->c_debug_nr++; \ } while (0) @@ -458,17 +521,88 @@ struct branchref { }; -/********** op1 values for ACONST instructions ********************************/ +/* data-flow constants for the ICMD table ************************************/ + +#define DF_0_TO_0 0 +#define DF_1_TO_0 1 +#define DF_2_TO_0 2 +#define DF_3_TO_0 3 + +#define DF_DST_BASE 4 /* from this value on, iptr->dst is a variable */ + +#define DF_0_TO_1 (DF_DST_BASE + 0) +#define DF_1_TO_1 (DF_DST_BASE + 1) +#define DF_2_TO_1 (DF_DST_BASE + 2) +#define DF_3_TO_1 (DF_DST_BASE + 3) +#define DF_N_TO_1 (DF_DST_BASE + 4) + +#define DF_INVOKE (DF_DST_BASE + 5) +#define DF_BUILTIN (DF_DST_BASE + 6) + +#define DF_COPY (DF_DST_BASE + 7) +#define DF_MOVE (DF_DST_BASE + 8) + +#define DF_DUP -1 +#define DF_DUP_X1 -1 +#define DF_DUP_X2 -1 +#define DF_DUP2 -1 +#define DF_DUP2_X1 -1 +#define DF_DUP2_X2 -1 +#define DF_SWAP -1 + +/* special data-flow recognized by verify/generate.pl: */ +#define DF_LOAD DF_COPY +#define DF_STORE DF_MOVE +#define DF_IINC DF_1_TO_1 +#define DF_POP DF_1_TO_0 +#define DF_POP2 DF_2_TO_0 + + +/* control-flow constants for the ICMD table *********************************/ + +#define CF_NORMAL 0 +#define CF_IF 1 + +#define CF_END_BASE 2 /* from here on, they mark the end of a superblock */ + +#define CF_END (CF_END_BASE + 0) +#define CF_GOTO (CF_END_BASE + 1) +#define CF_TABLE (CF_END_BASE + 2) +#define CF_LOOKUP (CF_END_BASE + 3) +#define CF_JSR (CF_END_BASE + 4) +#define CF_RET (CF_END_BASE + 5) + + +/* flag constants for the ICMD table *****************************************/ + +#define ICMDTABLE_PEI 0x0001 /* ICMD may throw an exception */ +#define ICMDTABLE_CALLS 0x0002 /* needs registers to be saved, may call */ + + +/* ICMD table entry **********************************************************/ + +typedef struct icmdtable_entry_t icmdtable_entry_t; + +struct icmdtable_entry_t { +#if !defined(NDEBUG) + char *name; /* name, without ICMD_ prefix */ +#endif + s4 dataflow; /* a DF_ constant, see above */ + s4 controlflow; /* a CF_ constant, see above */ + s4 flags; /* a combination of ICMDTABLE_ flags */ +}; + + +/* the ICMD table ************************************************************/ -#define ACONST_LOAD 0 /* ACONST_NULL or LDC instruction */ -#define ACONST_BUILTIN 1 /* constant argument for a builtin function call */ +extern icmdtable_entry_t icmd_table[256]; /********** JavaVM operation codes (sorted) and instruction lengths ***********/ -extern char *icmd_names[256]; extern char *opcode_names[256]; extern int jcommandsize[256]; +extern int stackreq[256]; #define JAVA_NOP 0 #define ICMD_NOP 0 @@ -483,7 +617,6 @@ extern int jcommandsize[256]; #define ICMD_ICONST 3 /* val.i = constant */ #define JAVA_ICONST_1 4 -#define ICMD_CHECKNULL_POP 4 #define JAVA_ICONST_2 5 #define ICMD_IDIVPOW2 5 /* val.i = constant */ @@ -512,8 +645,10 @@ extern int jcommandsize[256]; #define ICMD_DCONST 14 /* val.d = constant */ #define JAVA_DCONST_1 15 +#define ICMD_COPY 15 #define JAVA_BIPUSH 16 +#define ICMD_MOVE 16 #define JAVA_SIPUSH 17 @@ -1105,15 +1240,11 @@ extern int jcommandsize[256]; #define ICMD_INLINE_START 251 /* instruction before inlined method */ #define ICMD_INLINE_END 252 /* instruction after inlined method */ -#define ICMD_INLINE_GOTO 253 /* jump to caller of inlined method */ +#define ICMD_INLINE_BODY 253 /* start of inlined body */ #define ICMD_BUILTIN 255 /* internal opcode */ -/******************* description of JavaVM instructions ***********************/ - - - /***************************** register types *********************************/ #define REG_RES 0 /* reserved register for OS or code generator */ @@ -1129,18 +1260,6 @@ extern int jcommandsize[256]; #define PARAMMODE_STUFFED 1 -/***************************** register info block ****************************/ - -extern int stackreq[256]; -/* extern int op_needs_saved[256]; */ -/* extern int op_is_pei[256]; */ -#define NEEDS_SAVED 0 -#define PEI 1 -#define OP_DATA_SIZE 2 -extern int op_data[256][OP_DATA_SIZE]; -/* [0..255][NEEDS_SAVED] ... if ICMD needs a SAVEDVAR */ -/* [0..255][PEI] ... if ICMD could throw an exception */ - /* function prototypes ********************************************************/ /* compiler initialisation */ @@ -1149,15 +1268,27 @@ void jit_init(void); /* compiler finalisation */ void jit_close(void); +/* create a new jitdata */ +jitdata *jit_jitdata_new(methodinfo *m); + /* compile a method with jit compiler */ u1 *jit_compile(methodinfo *m); u1 *jit_recompile(methodinfo *m); +void jit_invalidate_code(methodinfo *m); +codeinfo *jit_get_current_code(methodinfo *m); +void jit_request_optimization(methodinfo *m); + /* patch the method entrypoint */ u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); s4 jit_complement_condition(s4 opcode); +void jit_renumber_basicblocks(jitdata *jd); +#if !defined(NDEBUG) +void jit_check_basicblock_numbers(jitdata *jd); +#endif + /* machine dependent functions */ #if defined(ENABLE_JIT) void md_init(void);