X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fjit.h;h=9418bbca53f94cfc4daf78d95845fd3ef6a27ee1;hb=add35c29eddac8e51219ba6410234e89e23fa796;hp=9e431bfbdcc68652db4a020f063be096ea771c8b;hpb=f459ec29a0e8d92bc5156fcef01cab012b4049fc;p=cacao.git diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index 9e431bfbd..9418bbca5 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -30,7 +30,7 @@ Changes: Christian Thalinger Edwin Steiner - $Id: jit.h 4737 2006-04-05 12:56:43Z edwin $ + $Id: jit.h 5404 2006-09-07 13:29:05Z christian $ */ @@ -38,6 +38,8 @@ #ifndef _JIT_H #define _JIT_H +#define NEW_VAR + /* forward typedefs ***********************************************************/ typedef struct jitdata jitdata; @@ -46,7 +48,6 @@ typedef stackelement *stackptr; typedef struct basicblock basicblock; typedef struct branchref branchref; typedef struct instruction instruction; -typedef struct subroutineinfo subroutineinfo; typedef struct insinfo_inline insinfo_inline; @@ -57,9 +58,11 @@ typedef struct insinfo_inline insinfo_inline; #include "vm/global.h" #include "vm/method.h" #include "vm/references.h" +#include "vm/resolve.h" #include "vm/statistics.h" #include "vm/jit/codegen-common.h" #include "vm/jit/reg.h" +#include "vm/jit/stacktrace.h" #if defined(ENABLE_INLINING) # include "vm/jit/inline/inline.h" @@ -68,10 +71,15 @@ typedef struct insinfo_inline insinfo_inline; #if defined(ENABLE_LOOP) # include "vm/jit/loop/loop.h" #endif +#if defined(ENABLE_SSA) +# include "vm/jit/optimizing/lsra.h" +#endif +#if defined(ENABLE_LSRA) +# include "vm/jit/allocator/lsra.h" +#endif #include "vm/jit/verify/typeinfo.h" - /* common jit/codegen macros **************************************************/ #if defined(ENABLE_STATISTICS) @@ -85,38 +93,85 @@ typedef struct insinfo_inline insinfo_inline; /* jitdata ********************************************************************/ -#define JITDATA_FLAG_IFCONV 0x00000001 - struct jitdata { - methodinfo *m; /* methodinfo of the method compiled */ - codeinfo *code; - codegendata *cd; - registerdata *rd; + methodinfo *m; /* methodinfo of the method compiled */ + codeinfo *code; + codegendata *cd; + registerdata *rd; #if defined(ENABLE_LOOP) - loopdata *ld; + loopdata *ld; +#endif +#if defined(ENABLE_SSA) || defined(ENABLE_LSRA) + 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; + s4 vartop; + + s4 varcount; + s4 localcount; + 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 LOCAL_UNUSED */ + s4 *interface_map; /* like local_map for interfaces */ #endif - u4 flags; /* contains JIT compiler flags */ }; +#define UNUSED -1 -/************************** stack element structure ***************************/ +#define JITDATA_FLAG_PARSE 0x00000001 +#define JITDATA_FLAG_VERIFY 0x00000002 -/* slot types */ +#define JITDATA_FLAG_INSTRUMENT 0x00000004 + +#define JITDATA_FLAG_IFCONV 0x00000008 +#define JITDATA_FLAG_REORDER 0x00000010 + +#define JITDATA_FLAG_SHOWINTERMEDIATE 0x20000000 +#define JITDATA_FLAG_SHOWDISASSEMBLE 0x40000000 +#define JITDATA_FLAG_VERBOSECALL 0x80000000 -/* Unified these with longer names. Maybe someday use only - * one set of names? -Edwin - */ -/*#define TYPE_INT 0*/ /* the stack slot types must numbered in the */ -#define TYPE_LNG TYPE_LONG /*1*/ /* same order as the ICMD_Ixxx to ICMD_Axxx */ -#define TYPE_FLT TYPE_FLOAT /*2*/ /* instructions (LOAD and STORE) */ -#define TYPE_DBL TYPE_DOUBLE /*3*/ /* integer, long, float, double, address */ -#define TYPE_ADR TYPE_ADDRESS /*4*/ -#define IS_INT_LNG_TYPE(a) (!((a) & TYPE_FLT)) -#define IS_FLT_DBL_TYPE(a) ((a) & TYPE_FLT) -#define IS_2_WORD_TYPE(a) ((a) & TYPE_LNG) -#define IS_ADR_TYPE(a) ((a) & TYPE_ADR) +#define JITDATA_HAS_FLAG_PARSE(jd) \ + ((jd)->flags & JITDATA_FLAG_PARSE) +#define JITDATA_HAS_FLAG_VERIFY(jd) \ + ((jd)->flags & JITDATA_FLAG_VERIFY) + +#define JITDATA_HAS_FLAG_INSTRUMENT(jd) \ + ((jd)->flags & JITDATA_FLAG_INSTRUMENT) + +#define JITDATA_HAS_FLAG_IFCONV(jd) \ + ((jd)->flags & JITDATA_FLAG_IFCONV) + +#define JITDATA_HAS_FLAG_REORDER(jd) \ + ((jd)->flags & JITDATA_FLAG_REORDER) + +#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \ + ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE) + +#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \ + ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE) + +#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \ + ((jd)->flags & JITDATA_FLAG_VERBOSECALL) + + +/* stack element structure ****************************************************/ /* flags */ @@ -128,6 +183,13 @@ struct jitdata { /* using the same register/memory location */ #define STKEEP 32 /* to prevent reg_mark_copy to free this */ /* stackslot */ +#define PREALLOC 64 /* preallocated var like for ARGVARS. Used */ + /* with the new var system */ +#define OUTVAR 128 /* STACKVR flag for new var system */ + +#define IS_SAVEDVAR(x) ((x) & SAVEDVAR) +#define IS_INMEMORY(x) ((x) & INMEMORY) + /* variable kinds */ @@ -153,31 +215,193 @@ struct stackelement { /**************************** instruction structure ***************************/ +/* branch_target_t: used in TABLESWITCH tables */ + +typedef union { + s4 insindex; /* used between parse and stack */ + basicblock *block; /* used from stack analysis onwards */ +} branch_target_t; + +/* lookup_target_t: used in LOOKUPSWITCH tables */ + +typedef struct { + s4 value; /* case value */ + branch_target_t target; /* branch target, see above */ +} lookup_target_t; + +/*** s1 operand ***/ + +typedef union { +#if defined(NEW_VAR) + s4 varindex; +#else + stackptr var; + s4 localindex; +#endif + s4 argcount; +} s1_operand_t; + +/*** s2 operand ***/ + +typedef union { +#if defined(NEW_VAR) + s4 varindex; + s4 *args; +#else + stackptr var; + stackptr *args; +#endif + classref_or_classinfo c; + unresolved_class *uc; + ptrint constval; /* for PUT*CONST */ + s4 tablelow; /* for TABLESWITCH */ + u4 lookupcount; /* for LOOKUPSWITCH */ +} s2_operand_t; + +/*** s3 operand ***/ + +typedef union { +#if defined(NEW_VAR) + s4 varindex; +#else + stackptr var; +#endif + ptrint constval; + classref_or_classinfo c; + constant_FMIref *fmiref; + unresolved_method *um; + unresolved_field *uf; + insinfo_inline *inlineinfo; /* for INLINE_START/END */ + s4 tablehigh; /* for TABLESWITCH */ + branch_target_t lookupdefault; /* for LOOKUPSWITCH */ + branch_target_t jsrtarget; /* for JSR */ + struct builtintable_entry *bte; +} s3_operand_t; + +/*** val operand ***/ + +typedef union { + s4 i; + s8 l; + float f; + double d; + void *anyptr; + java_objectheader *stringconst; /* for ACONST with string */ + classref_or_classinfo c; /* for ACONST with class */ +} val_operand_t; + +/*** dst operand ***/ + +typedef union { +#if defined(NEW_VAR) + s4 varindex; +#else + stackptr var; + s4 localindex; +#endif + 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 */ +#if defined(NEW_VAR) + s4 *dupslots; /* for SWAP, DUP* except DUP */ +#else + stackptr *dupslots; /* for SWAP, DUP* except DUP */ +#endif +} 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_ARRAY 0x04 /* for CHECKCAST/INSTANCEOF with array */ +#define INS_FLAG_CHECK 0x08 /* for *ALOAD|*ASTORE: check index */ + /* for BUILTIN: check exception */ + +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 ***/ + +/* The instruction format for the intermediate representation: */ + struct instruction { - stackptr dst; /* stack index of destination operand stack */ - u2 opc; /* opcode of intermediate code command */ - s4 op1; /* first operand, usually variable number */ - imm_union val; /* immediate constant */ - void *target; /* used for targets of branches and jumps */ - /* and as address for list of targets for */ - /* statements */ - u2 line; /* line number in source file */ + u2 opc; /* opcode */ + u2 line; /* line number */ +#if SIZEOF_VOID_P == 8 + flags_operand_t flags; /* 4 bytes */ +#endif + s1_operand_t s1; /* pointer-size */ + union { + struct { + s2_operand_t s2; /* pointer-size */ + s3_operand_t s3; /* pointer-size */ + } s23; /* XOR */ + val_operand_t val; /* long-size */ + } sx; + dst_operand_t dst; /* pointer-size */ +#if SIZEOF_VOID_P == 4 + flags_operand_t flags; /* 4 bytes */ +#endif }; -#define INSTRUCTION_PUTCONST_TYPE(iptr) \ - ((iptr)[0].op1) -#define INSTRUCTION_PUTCONST_VALUE_ADR(iptr) \ - ((iptr)[0].val.a) +#define INSTRUCTION_IS_RESOLVED(iptr) \ + (!((iptr)->flags.bits & INS_FLAG_UNRESOLVED)) + +#define INSTRUCTION_IS_UNRESOLVED(iptr) \ + ((iptr)->flags.bits & INS_FLAG_UNRESOLVED) + +#define INSTRUCTION_MUST_CHECK(iptr) \ + ((iptr)->flags.bits & INS_FLAG_CHECK) -#define INSTRUCTION_PUTCONST_FIELDINFO(iptr) \ - ((fieldinfo *)((iptr)[1].val.a)) +#define INSTRUCTION_GET_FIELDREF(iptr,fref) \ + do { \ + if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \ + fref = iptr->sx.s23.s3.uf->fieldref; \ + else \ + fref = iptr->sx.s23.s3.fmiref; \ + } while (0) -#define INSTRUCTION_PUTCONST_FIELDINFO_PTR(iptr) \ - ((fieldinfo **) &((iptr)[1].val.a)) +#define INSTRUCTION_GET_METHODREF(iptr,mref) \ + do { \ + if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \ + mref = iptr->sx.s23.s3.um->methodref; \ + else \ + mref = iptr->sx.s23.s3.fmiref; \ + } while (0) -#define INSTRUCTION_PUTCONST_FIELDREF(iptr) \ - ((unresolved_field *)((iptr)[1].target)) +#define INSTRUCTION_GET_METHODDESC(iptr, md) \ + do { \ + if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \ + md = iptr->sx.s23.s3.um->methodref->parseddesc.md; \ + else \ + md = iptr->sx.s23.s3.fmiref->parseddesc.md; \ + } while (0) /* additional info structs for special instructions ***************************/ @@ -216,43 +440,53 @@ struct insinfo_inline { /* the others by using bitfields. */ struct basicblock { - s4 debug_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 icount; /* number of intermediate code instructions */ - s4 mpc; /* machine code pc at start of block */ - stackptr instack; /* stack at begin of basic block */ - stackptr outstack; /* stack at end of basic block */ - s4 indepth; /* stack depth at begin of basic block */ - s4 outdepth; /* stack depth end of basic block */ - s4 pre_count; /* count of predecessor basic blocks */ - 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 */ + 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 icount; /* number of intermediate code instructions */ + s4 mpc; /* machine code pc at start of block */ + stackptr instack; /* stack at begin of basic block */ + stackptr outstack; /* stack at end of basic block */ +#if defined(NEW_VAR) + s4 *invars; /* array of in-variables at begin of block */ + s4 *outvars; /* array of out-variables at end of block */ +#else + stackptr *invars; /* array of in-variables at begin of block */ + stackptr *outvars; /* array of out-variables at end of block */ +#endif + s4 indepth; /* stack depth at begin of basic block */ + s4 outdepth; /* stack depth end of basic block */ + + s4 predecessorcount; + s4 successorcount; + basicblock **predecessors; /* array of predecessor basic blocks */ + basicblock **successors; /* array of successor basic blocks */ + + 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 */ + stackptr stack; /* start of stack array for this block */ /* (see doc/stack.txt) */ - methodinfo *method; /* method this block belongs to */ + methodinfo *method; /* method this block belongs to */ }; -/* macro for initializing newly allocated basicblock:s */ - -#define BASICBLOCK_INIT(bptr,m) \ - do { \ - bptr->mpc = -1; \ - bptr->flags = -1; \ - bptr->bitflags = 0; \ - bptr->lflags = 0; \ - bptr->type = BBTYPE_STD; \ - bptr->branchrefs = NULL; \ - bptr->pre_count = 0; \ - bptr->method = (m); \ - bptr->debug_nr = (m)->c_debug_nr++; \ - } while (0) + +/* Macro for initializing newly allocated basic block's. It does not + need to zero fields, as we zero out the whole basic block array. */ + +#define BASICBLOCK_INIT(bptr,m) \ + do { \ + bptr->mpc = -1; \ + bptr->flags = -1; \ + bptr->type = BBTYPE_STD; \ + bptr->method = (m); \ + bptr->nr = (m)->c_debug_nr++; \ + } while (0) /* branchref *****************************************************************/ @@ -288,6 +522,7 @@ 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 */ @@ -311,31 +546,24 @@ extern int jcommandsize[256]; #define JAVA_FCONST_1 12 #define JAVA_FCONST_2 13 -#define ICMD_ELSE_ICONST 13 #define JAVA_DCONST_0 14 #define ICMD_DCONST 14 /* val.d = constant */ #define JAVA_DCONST_1 15 -#define ICMD_IFEQ_ICONST 15 #define JAVA_BIPUSH 16 -#define ICMD_IFNE_ICONST 16 #define JAVA_SIPUSH 17 -#define ICMD_IFLT_ICONST 17 #define JAVA_LDC1 18 -#define ICMD_IFGE_ICONST 18 #define JAVA_LDC2 19 -#define ICMD_IFGT_ICONST 19 #define JAVA_LDC2W 20 -#define ICMD_IFLE_ICONST 20 /* order of LOAD instructions must be */ - /* equal to order of TYPE_XXX defines */ + /* equal to order of TYPE_* defines */ #define JAVA_ILOAD 21 #define ICMD_ILOAD 21 /* op1 = local variable */ @@ -436,7 +664,7 @@ extern int jcommandsize[256]; #define ICMD_SALOAD 53 /* order of STORE instructions must be*/ - /* equal to order of TYPE_XXX defines */ + /* equal to order of TYPE_* defines */ #define JAVA_ISTORE 54 #define ICMD_ISTORE 54 /* op1 = local variable */ @@ -874,40 +1102,52 @@ extern int jcommandsize[256]; /* UNDEF203 */ #define ICMD_IASTORECONST 204 - #define ICMD_LASTORECONST 205 - #define ICMD_FASTORECONST 206 - #define ICMD_DASTORECONST 207 - #define ICMD_AASTORECONST 208 - #define ICMD_BASTORECONST 209 - #define ICMD_CASTORECONST 210 - #define ICMD_SASTORECONST 211 #define ICMD_PUTSTATICCONST 212 - #define ICMD_PUTFIELDCONST 213 #define ICMD_IMULPOW2 214 - #define ICMD_LMULPOW2 215 +#define ICMD_IF_FCMPEQ 216 +#define ICMD_IF_FCMPNE 217 + +#define ICMD_IF_FCMPL_LT 218 +#define ICMD_IF_FCMPL_GE 219 +#define ICMD_IF_FCMPL_GT 220 +#define ICMD_IF_FCMPL_LE 221 + +#define ICMD_IF_FCMPG_LT 222 +#define ICMD_IF_FCMPG_GE 223 +#define ICMD_IF_FCMPG_GT 224 +#define ICMD_IF_FCMPG_LE 225 + +#define ICMD_IF_DCMPEQ 226 +#define ICMD_IF_DCMPNE 227 + +#define ICMD_IF_DCMPL_LT 228 +#define ICMD_IF_DCMPL_GE 229 +#define ICMD_IF_DCMPL_GT 230 +#define ICMD_IF_DCMPL_LE 231 + +#define ICMD_IF_DCMPG_LT 232 +#define ICMD_IF_DCMPG_GE 233 +#define ICMD_IF_DCMPG_GT 234 +#define ICMD_IF_DCMPG_LE 235 + #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_BUILTIN 255 /* internal opcode */ -/* define some ICMD masks *****************************************************/ - -#define ICMD_OPCODE_MASK 0x00ff /* mask to get the opcode */ -#define ICMD_CONDITION_MASK 0xff00 /* mask to get the condition */ - /******************* description of JavaVM instructions ***********************/ @@ -931,7 +1171,14 @@ extern int jcommandsize[256]; /***************************** 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 ********************************************************/ @@ -943,11 +1190,19 @@ void jit_close(void); /* compile a method with jit compiler */ u1 *jit_compile(methodinfo *m); +u1 *jit_recompile(methodinfo *m); + +/* patch the method entrypoint */ +u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); + +s4 jit_complement_condition(s4 opcode); /* machine dependent functions */ #if defined(ENABLE_JIT) void md_init(void); +u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr); + void md_cacheflush(u1 *addr, s4 nbytes); void md_icacheflush(u1 *addr, s4 nbytes); void md_dcacheflush(u1 *addr, s4 nbytes); @@ -957,10 +1212,6 @@ void md_dcacheflush(u1 *addr, s4 nbytes); void intrp_md_init(void); #endif -#if defined(ENABLE_RT_TIMING) -void jit_print_time_stats(FILE *file); -#endif - #endif /* _JIT_H */