/* src/vm/jit/jit.h - code generation header
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
-
- Changes: Christian Thalinger
- Edwin Steiner
-
- $Id: jit.h 5780 2006-10-15 12:20:15Z edwin $
+ $Id: jit.h 8295 2007-08-11 17:57:24Z michi $
*/
typedef struct stackelement stackelement;
typedef stackelement *stackptr;
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"
#include "vm/types.h"
#include "toolbox/chain.h"
+
#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"
+#include "vm/jit/replace.h"
#if defined(ENABLE_INLINING)
# include "vm/jit/inline/inline.h"
#include "vm/jit/verify/typeinfo.h"
+#include "vmcore/method.h"
+#include "vmcore/references.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+
/* common jit/codegen macros **************************************************/
#if defined(ENABLE_STATISTICS)
# define COUNT(x) (x)++
-# define COUNT_SPILLS count_spills++
+# define COUNT_SPILLS /* use COUNT_(READ|WRITE)_SPILLS instead */
+# define COUNT_READ_SPILLS(var) \
+ switch(var->type) { \
+ case TYPE_FLT: count_spills_read_flt++; break; \
+ case TYPE_DBL: count_spills_read_dbl++; break; \
+ default: count_spills_read_ila++; break; \
+ }
+
+# define COUNT_WRITE_SPILLS(var) \
+ switch(var->type) { \
+ case TYPE_FLT: count_spills_write_flt++; break; \
+ case TYPE_DBL: count_spills_write_dbl++; break; \
+ default: count_spills_write_ila++; break; \
+ }
+
#else
-# define COUNT(x) /* nothing */
-# define COUNT_SPILLS /* nothing */
+# define COUNT(x) /* nothing */
+# define COUNT_SPILLS /* nothing */
+# define COUNT_READ_SPILLS(x) /* nothing */
+# define COUNT_WRITE_SPILLS(x) /* nothing */
#endif
typedef struct interface_info interface_info;
/* 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 */
+ 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) */
- s4 c_block_nr; /* counter for basic block number */
-
- varinfo *var; /* array of variables */
- s4 vartop; /* next free index in var array */
-
- 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 */
- interface_info *interface_map;
+
+ varinfo *var; /* array of variables */
+ s4 vartop; /* next free index in var array */
+
+ s4 varcount; /* number of variables in var array */
+ s4 localcount; /* number of locals at start of var ar. */
+ s4 *local_map; /* map for renaming (de-coallescing) */
+ /* locals and keeping the coalescing info for simplereg. */
+ /* local_map[javaindex * 5 + type] = */
+ /* >= 0......index into jd->var, or */
+ /* UNUSED....this (javaindex,type) pair is not used */
+
+ 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 UNUSED -1
#define JITDATA_FLAG_PARSE 0x00000001
#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)
#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 */
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 */
};
/* branch_target_t: used in TABLESWITCH tables */
typedef union {
- s4 insindex; /* used between parse and stack */
- basicblock *block; /* used from stack analysis onwards */
+ s4 insindex; /* used in parse */
+ basicblock *block; /* valid after parse */
} branch_target_t;
/* lookup_target_t: used in LOOKUPSWITCH tables */
typedef union {
s4 varindex;
- s4 *args;
+ 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 ***/
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;
float f;
double d;
void *anyptr;
- java_objectheader *stringconst; /* for ACONST with string */
+ java_handle_t *stringconst; /* for ACONST with string */
classref_or_classinfo c; /* for ACONST with class */
} val_operand_t;
typedef union {
s4 varindex;
- basicblock *block; /* valid after stack analysis */
+ basicblock *block; /* valid after parse */
branch_target_t *table; /* for TABLESWITCH */
lookup_target_t *lookup; /* for LOOKUPSWITCH */
- s4 insindex; /* used between parse and stack */
+ s4 insindex; /* used in parse */
} 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 */
+#define INS_FLAG_BASICBLOCK 0x01 /* marks a basic block start */
+#define INS_FLAG_UNRESOLVED 0x02 /* contains unresolved field/meth/class*/
+#define INS_FLAG_CLASS 0x04 /* for ACONST, PUT*CONST with class */
+#define INS_FLAG_ARRAY 0x08 /* for CHECKCAST/INSTANCEOF with array */
+#define INS_FLAG_CHECK 0x10 /* for *ALOAD|*ASTORE: check index */
/* for BUILTIN: check exception */
+#define INS_FLAG_KILL_PREV 0x04 /* for *STORE, invalidate prev local */
+#define INS_FLAG_KILL_NEXT 0x08 /* for *STORE, invalidate next local */
+#define INS_FLAG_RETADDR 0x10 /* for ASTORE: op is a returnAddress */
+
+#define INS_FLAG_ID_SHIFT 5
+#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 ***/
};
+#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
+ ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
+
#define INSTRUCTION_IS_RESOLVED(iptr) \
(!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
/* 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 ------------------------------*/
+#if defined(ENABLE_REPLACEMENT)
+ rplpoint *rp; /* replacement point at INLINE_START */
+#endif
+
+ /* fields set by the codegen ---------------------------------------------*/
+ s4 startmpc; /* machine code offset of start of inlining */
};
+
/* basicblock *****************************************************************/
-
+
/* flags */
#define BBDELETED -2
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 */
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 */
};
+/* [+]...the javalocals array: This array is indexed by the javaindex (the */
+/* local variable index ocurring in the original bytecode). An element */
+/* javalocals[javaindex] encodes where to find the contents of the */
+/* original variable at this point in the program. */
+/* There are three cases for javalocals[javaindex]: */
+/* >= 0.......it's an index into the jd->var array, where the */
+/* CACAO variable corresponding to the original local */
+/* can be found. */
+/* UNUSED.....the original variable is not live at this point */
+/* < UNUSED...the original variable contains a returnAddress at */
+/* this point. The number of the block to return to can */
+/* be calculated using RETADDR_FROM_JAVALOCAL: */
+/* */
+/* javalocals[javaindex] == JAVALOCAL_FROM_RETADDR(nr) */
+/* RETADDR_FROM_JAVALOCAL(javalocals[javaindex]) == nr */
+
+#define JAVALOCAL_FROM_RETADDR(nr) (UNUSED - (1 + (nr)))
+#define RETADDR_FROM_JAVALOCAL(jl) (UNUSED - (1 + (jl)))
+
/* Macro for initializing newly allocated basic block's. It does not
need to zero fields, as we zero out the whole basic block array. */
bptr->flags = -1; \
bptr->type = BBTYPE_STD; \
bptr->method = (m); \
- bptr->nr = (m)->c_block_nr++; \
} while (0)
-/* branchref *****************************************************************/
-
-struct branchref {
- s4 branchpos; /* patching position in code segment */
- branchref *next; /* next element in branchref list */
-};
-
-
/* data-flow constants for the ICMD table ************************************/
#define DF_0_TO_0 0
extern icmdtable_entry_t icmd_table[256];
-/********** op1 values for ACONST instructions ********************************/
-
-#define ACONST_LOAD 0 /* ACONST_NULL or LDC instruction */
-#define ACONST_BUILTIN 1 /* constant argument for a builtin function call */
-
-
/********** JavaVM operation codes (sorted) and instruction lengths ***********/
extern char *opcode_names[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 */
#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 */
/* 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);
void jit_check_basicblock_numbers(jitdata *jd);
#endif
-/* 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);
-#endif
-
-#if defined(ENABLE_INTRP)
-void intrp_md_init(void);
-#endif
-
#endif /* _JIT_H */