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 $
*/
typedef struct branchref branchref;
typedef struct instruction instruction;
typedef struct insinfo_inline insinfo_inline;
+typedef struct exception_entry exception_entry;
#include "config.h"
#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"
# 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;
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
#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
#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)
((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 */
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 */
};
/*** 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;
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;
/*** 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 ***/
((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 { \
/* 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
/* 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;
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 */
};
bptr->flags = -1; \
bptr->type = BBTYPE_STD; \
bptr->method = (m); \
- bptr->nr = (m)->c_debug_nr++; \
} while (0)
};
-/********** 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
#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 */
#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
#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 */
#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 */
/* 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);