/* src/vm/jit/jit.c - calls the code generation functions
- 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: Edwin Steiner
- Christian Thalinger
- Christian Ullrich
-
- $Id: jit.c 5234 2006-08-14 17:50:12Z christian $
-
*/
#include "config.h"
-#include "vm/types.h"
#include <assert.h>
+#include "vm/types.h"
+
#include "mm/memory.h"
+
#include "native/native.h"
+
#include "toolbox/logging.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#else
-# include "threads/none/lock.h"
-#endif
+#include "threads/lock-common.h"
+#include "threads/threads-common.h"
-#include "vm/class.h"
#include "vm/global.h"
#include "vm/initialize.h"
-#include "vm/loader.h"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
+
#include "vm/jit/asmpart.h"
# include "vm/jit/cfg.h"
#include "vm/jit/disass.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
+#include "vm/jit/md.h"
#include "vm/jit/parse.h"
#include "vm/jit/reg.h"
-# include "vm/jit/reorder.h"
-
#include "vm/jit/show.h"
#include "vm/jit/stack.h"
# include "vm/jit/optimizing/ssa.h"
#endif
-
-#if defined(ENABLE_IFCONV)
-# include "vm/jit/ifconv/ifconv.h"
+#if defined(ENABLE_INLINING)
+# include "vm/jit/inline/inline.h"
#endif
#include "vm/jit/loop/analyze.h"
#include "vm/jit/loop/graph.h"
#include "vm/jit/loop/loop.h"
-#include "vm/jit/verify/typecheck.h"
-#include "vm/rt-timing.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
+#if defined(ENABLE_IFCONV)
+# include "vm/jit/optimizing/ifconv.h"
#endif
+#include "vm/jit/optimizing/reorder.h"
+
+#include "vm/jit/verify/typecheck.h"
+
+#include "vmcore/class.h"
+#include "vmcore/loader.h"
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+#include "vmcore/rt-timing.h"
+#include "vmcore/statistics.h"
+
/* debug macros ***************************************************************/
#endif
-/* global switches ************************************************************/
+/* the ICMD table ************************************************************/
+
+#if !defined(NDEBUG)
+#define N(name) name,
+#else
+#define N(name)
+#endif
+
+/* abbreviations for flags */
+
+#define PEI ICMDTABLE_PEI
+#define CALLS ICMDTABLE_CALLS
+
+/* some machine dependent values */
+
+#if SUPPORT_DIVISION
+#define IDIV_CALLS 0
+#else
+#define IDIV_CALLS ICMDTABLE_CALLS
+#endif
+
+#if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+#define LDIV_CALLS 0
+#else
+#define LDIV_CALLS ICMDTABLE_CALLS
+#endif
+
+/* include the actual table */
+
+icmdtable_entry_t icmd_table[256] = {
+#include <vm/jit/icmdtable.inc>
+};
+
+#undef N
+#undef PEI
+#undef CALLS
+
+/* XXX hack until the old "PEI" definition is removed */
+#define PEI 1
+
+
+/* stackelement requirements of Java opcodes **********************************/
int stackreq[256] = {
0, /* JAVA_NOP 0 */
0, /* JAVA_POP 87 */
0, /* JAVA_POP2 88 */
1, /* JAVA_DUP 89 */
- 3, /* JAVA_DUP_X1 90 */
- 4, /* JAVA_DUP_X2 91 */
+ 1+3, /* JAVA_DUP_X1 90 */
+ 2+4, /* JAVA_DUP_X2 91 */
2, /* JAVA_DUP2 92 */
- 3, /* JAVA_DUP2_X1 93 */
- 4, /* JAVA_DUP2_X2 94 */
- 2, /* JAVA_SWAP 95 */
+ 2+5, /* JAVA_DUP2_X1 93 */
+ 3+6, /* JAVA_DUP2_X2 94 */
+ 1+2, /* JAVA_SWAP 95 */
1, /* JAVA_IADD 96 */
1, /* JAVA_LADD 97 */
1, /* JAVA_FADD 98 */
1, /* JAVA_UNDEF255 255 */
};
+
+/* size in bytes of Java opcodes **********************************************/
int jcommandsize[256] = {
};
-char *icmd_names[256] = {
- "NOP ", /* 0 */
- "ACONST ", /* 1 */
- "CHECKNULL ", /* ICONST_M1 2 */
- "ICONST ", /* 3 */
- "CHECKNULL_POP ", /* ICONST_1 4 */
- "IDIVPOW2 ", /* ICONST_2 5 */
- "LDIVPOW2 ", /* ICONST_3 6 */
- "UNDEF7 ", /* ICONST_4 7 */
- "UNDEF8 ", /* ICONST_5 8 */
- "LCONST ", /* 9 */
- "LCMPCONST ", /* LCONST_1 10 */
- "FCONST ", /* 11 */
- "UNDEF12 ", /* FCONST_1 12 */
- "UNDEF13 ", /* FCONST_2 13 */
- "DCONST ", /* 14 */
- "UNDEF15 ", /* DCONST_1 15 */
- "UNDEF16 ", /* BIPUSH 16 */
- "UNDEF17 ", /* SIPUSH 17 */
- "UNDEF18 ", /* LDC1 18 */
- "UNDEF19 ", /* LDC2 19 */
- "UNDEF20 ", /* LDC2W 20 */
- "ILOAD ", /* 21 */
- "LLOAD ", /* 22 */
- "FLOAD ", /* 23 */
- "DLOAD ", /* 24 */
- "ALOAD ", /* 25 */
- "IADDCONST ", /* ILOAD_0 26 */
- "ISUBCONST ", /* ILOAD_1 27 */
- "IMULCONST ", /* ILOAD_2 28 */
- "IANDCONST ", /* ILOAD_3 29 */
- "IORCONST ", /* LLOAD_0 30 */
- "IXORCONST ", /* LLOAD_1 31 */
- "ISHLCONST ", /* LLOAD_2 32 */
- "ISHRCONST ", /* LLOAD_3 33 */
- "IUSHRCONST ", /* FLOAD_0 34 */
- "IREMPOW2 ", /* FLOAD_1 35 */
- "LADDCONST ", /* FLOAD_2 36 */
- "LSUBCONST ", /* FLOAD_3 37 */
- "LMULCONST ", /* DLOAD_0 38 */
- "LANDCONST ", /* DLOAD_1 39 */
- "LORCONST ", /* DLOAD_2 40 */
- "LXORCONST ", /* DLOAD_3 41 */
- "LSHLCONST ", /* ALOAD_0 42 */
- "LSHRCONST ", /* ALOAD_1 43 */
- "LUSHRCONST ", /* ALOAD_2 44 */
- "LREMPOW2 ", /* ALOAD_3 45 */
- "IALOAD ", /* 46 */
- "LALOAD ", /* 47 */
- "FALOAD ", /* 48 */
- "DALOAD ", /* 49 */
- "AALOAD ", /* 50 */
- "BALOAD ", /* 51 */
- "CALOAD ", /* 52 */
- "SALOAD ", /* 53 */
- "ISTORE ", /* 54 */
- "LSTORE ", /* 55 */
- "FSTORE ", /* 56 */
- "DSTORE ", /* 57 */
- "ASTORE ", /* 58 */
- "IF_LEQ ", /* ISTORE_0 59 */
- "IF_LNE ", /* ISTORE_1 60 */
- "IF_LLT ", /* ISTORE_2 61 */
- "IF_LGE ", /* ISTORE_3 62 */
- "IF_LGT ", /* LSTORE_0 63 */
- "IF_LLE ", /* LSTORE_1 64 */
- "IF_LCMPEQ ", /* LSTORE_2 65 */
- "IF_LCMPNE ", /* LSTORE_3 66 */
- "IF_LCMPLT ", /* FSTORE_0 67 */
- "IF_LCMPGE ", /* FSTORE_1 68 */
- "IF_LCMPGT ", /* FSTORE_2 69 */
- "IF_LCMPLE ", /* FSTORE_3 70 */
- "UNDEF71 ", /* DSTORE_0 71 */
- "UNDEF72 ", /* DSTORE_1 72 */
- "UNDEF73 ", /* DSTORE_2 73 */
- "UNDEF74 ", /* DSTORE_3 74 */
- "UNDEF75 ", /* ASTORE_0 75 */
- "UNDEF76 ", /* ASTORE_1 76 */
- "UNDEF77 ", /* ASTORE_2 77 */
- "UNDEF78 ", /* ASTORE_3 78 */
- "IASTORE ", /* 79 */
- "LASTORE ", /* 80 */
- "FASTORE ", /* 81 */
- "DASTORE ", /* 82 */
- "AASTORE ", /* 83 */
- "BASTORE ", /* 84 */
- "CASTORE ", /* 85 */
- "SASTORE ", /* 86 */
- "POP ", /* 87 */
- "POP2 ", /* 88 */
- "DUP ", /* 89 */
- "DUP_X1 ", /* 90 */
- "DUP_X2 ", /* 91 */
- "DUP2 ", /* 92 */
- "DUP2_X1 ", /* 93 */
- "DUP2_X2 ", /* 94 */
- "SWAP ", /* 95 */
- "IADD ", /* 96 */
- "LADD ", /* 97 */
- "FADD ", /* 98 */
- "DADD ", /* 99 */
- "ISUB ", /* 100 */
- "LSUB ", /* 101 */
- "FSUB ", /* 102 */
- "DSUB ", /* 103 */
- "IMUL ", /* 104 */
- "LMUL ", /* 105 */
- "FMUL ", /* 106 */
- "DMUL ", /* 107 */
- "IDIV ", /* 108 */
- "LDIV ", /* 109 */
- "FDIV ", /* 110 */
- "DDIV ", /* 111 */
- "IREM ", /* 112 */
- "LREM ", /* 113 */
- "FREM ", /* 114 */
- "DREM ", /* 115 */
- "INEG ", /* 116 */
- "LNEG ", /* 117 */
- "FNEG ", /* 118 */
- "DNEG ", /* 119 */
- "ISHL ", /* 120 */
- "LSHL ", /* 121 */
- "ISHR ", /* 122 */
- "LSHR ", /* 123 */
- "IUSHR ", /* 124 */
- "LUSHR ", /* 125 */
- "IAND ", /* 126 */
- "LAND ", /* 127 */
- "IOR ", /* 128 */
- "LOR ", /* 129 */
- "IXOR ", /* 130 */
- "LXOR ", /* 131 */
- "IINC ", /* 132 */
- "I2L ", /* 133 */
- "I2F ", /* 134 */
- "I2D ", /* 135 */
- "L2I ", /* 136 */
- "L2F ", /* 137 */
- "L2D ", /* 138 */
- "F2I ", /* 139 */
- "F2L ", /* 140 */
- "F2D ", /* 141 */
- "D2I ", /* 142 */
- "D2L ", /* 143 */
- "D2F ", /* 144 */
- "INT2BYTE ", /* 145 */
- "INT2CHAR ", /* 146 */
- "INT2SHORT ", /* 147 */
- "LCMP ", /* 148 */
- "FCMPL ", /* 149 */
- "FCMPG ", /* 150 */
- "DCMPL ", /* 151 */
- "DCMPG ", /* 152 */
- "IFEQ ", /* 153 */
- "IFNE ", /* 154 */
- "IFLT ", /* 155 */
- "IFGE ", /* 156 */
- "IFGT ", /* 157 */
- "IFLE ", /* 158 */
- "IF_ICMPEQ ", /* 159 */
- "IF_ICMPNE ", /* 160 */
- "IF_ICMPLT ", /* 161 */
- "IF_ICMPGE ", /* 162 */
- "IF_ICMPGT ", /* 163 */
- "IF_ICMPLE ", /* 164 */
- "IF_ACMPEQ ", /* 165 */
- "IF_ACMPNE ", /* 166 */
- "GOTO ", /* 167 */
- "JSR ", /* 168 */
- "RET ", /* 169 */
- "TABLESWITCH ", /* 170 */
- "LOOKUPSWITCH ", /* 171 */
- "IRETURN ", /* 172 */
- "LRETURN ", /* 173 */
- "FRETURN ", /* 174 */
- "DRETURN ", /* 175 */
- "ARETURN ", /* 176 */
- "RETURN ", /* 177 */
- "GETSTATIC ", /* 178 */
- "PUTSTATIC ", /* 179 */
- "GETFIELD ", /* 180 */
- "PUTFIELD ", /* 181 */
- "INVOKEVIRTUAL ", /* 182 */
- "INVOKESPECIAL ", /* 183 */
- "INVOKESTATIC ", /* 184 */
- "INVOKEINTERFACE", /* 185 */
- "UNDEF186 ", /* UNDEF186 186 */
- "NEW ", /* 187 */
- "NEWARRAY ", /* 188 */
- "ANEWARRAY ", /* 189 */
- "ARRAYLENGTH ", /* 190 */
- "ATHROW ", /* 191 */
- "CHECKCAST ", /* 192 */
- "INSTANCEOF ", /* 193 */
- "MONITORENTER ", /* 194 */
- "MONITOREXIT ", /* 195 */
- "UNDEF196 ", /* WIDE 196 */
- "MULTIANEWARRAY ", /* 197 */
- "IFNULL ", /* 198 */
- "IFNONNULL ", /* 199 */
- "UNDEF200 ", /* GOTO_W 200 */
- "UNDEF201 ", /* JSR_W 201 */
- "UNDEF202 ", /* BREAKPOINT 202 */
- "UNDEF203 ", /* UNDEF203 203 */
- "IASTORECONST ", /* 204 */
- "LASTORECONST ", /* 205 */
- "FASTORECONST ", /* 206 */
- "DASTORECONST ", /* 207 */
- "AASTORECONST ", /* 208 */
- "BASTORECONST ", /* 209 */
- "CASTORECONST ", /* 210 */
- "SASTORECONST ", /* 211 */
- "PUTSTATICCONST ", /* 212 */
- "PUTFIELDCONST ", /* 213 */
- "IMULPOW2 ", /* 214 */
- "LMULPOW2 ", /* 215 */
-
- "IF_FCMPEQ ", /* 216 */
- "IF_FCMPNE ", /* 217 */
-
- "IF_FCMPL_LT ", /* 218 */
- "IF_FCMPL_GE ", /* 219 */
- "IF_FCMPL_GT ", /* 220 */
- "IF_FCMPL_LE ", /* 221 */
-
- "IF_FCMPG_LT ", /* 222 */
- "IF_FCMPG_GE ", /* 223 */
- "IF_FCMPG_GT ", /* 224 */
- "IF_FCMPG_LE ", /* 225 */
-
- "IF_DCMPEQ ", /* 226 */
- "IF_DCMPNE ", /* 227 */
-
- "IF_DCMPL_LT ", /* 228 */
- "IF_DCMPL_GE ", /* 229 */
- "IF_DCMPL_GT ", /* 230 */
- "IF_DCMPL_LE ", /* 231 */
-
- "IF_DCMPG_LT ", /* 232 */
- "IF_DCMPG_GE ", /* 233 */
- "IF_DCMPG_GT ", /* 234 */
- "IF_DCMPG_LE ", /* 235 */
-
- "UNDEF236", "UNDEF237", "UNDEF238", "UNDEF239", "UNDEF240",
- "UNDEF241", "UNDEF242", "UNDEF243", "UNDEF244", "UNDEF245",
- "UNDEF246", "UNDEF247", "UNDEF248", "UNDEF249", "UNDEF250",
-
- "INLINE_START ", /* 251 */
- "INLINE_END ", /* 252 */
- "INLINE_GOTO ", /* 253 */
-
- "UNDEF254",
-
- "BUILTIN " /* 255 */
-};
-
+/* Java opcode names *********************************************************/
char *opcode_names[256] = {
"NOP ", /* 0 */
"UNDEF251", "UNDEF252", "UNDEF253", "UNDEF254", "UNDEF255"
};
-int op_needs_saved[256];
/* jit_init ********************************************************************
void jit_init(void)
{
- s4 i;
- for( i = 0; i < 256; i++) {
- op_needs_saved[i] = 0;
- }
-
- op_needs_saved[ICMD_AASTORE ] = 1;
-#if !SUPPORT_DIVISION
- op_needs_saved[ICMD_IDIV ] = 1;
- op_needs_saved[ICMD_IREM ] = 1;
-#endif
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
- op_needs_saved[ICMD_LDIV ] = 1;
- op_needs_saved[ICMD_LREM ] = 1;
-#endif
- op_needs_saved[ICMD_CHECKCAST] = 1;
-
- op_needs_saved[ICMD_BUILTIN ] = 1;
- op_needs_saved[ICMD_INVOKESTATIC ] = 1;
- op_needs_saved[ICMD_INVOKESPECIAL ] = 1;
- op_needs_saved[ICMD_INVOKEVIRTUAL ] = 1;
- op_needs_saved[ICMD_INVOKEINTERFACE] = 1;
- op_needs_saved[ICMD_MULTIANEWARRAY ] = 1;
-
+#if defined(ENABLE_JIT)
/* initialize stack analysis subsystem */
(void) stack_init();
+#endif
/* initialize show subsystem */
/* initialize codegen subsystem */
codegen_init();
+
+ /* initialize code subsystem */
+
+ (void) code_init();
}
*******************************************************************************/
-static jitdata *jit_jitdata_new(methodinfo *m)
+jitdata *jit_jitdata_new(methodinfo *m)
{
jitdata *jd;
/* initialize variables */
- jd->flags = 0;
- jd->isleafmethod = true;
+ jd->flags = 0;
+ jd->exceptiontable = NULL;
+ jd->exceptiontablelength = 0;
+ jd->returncount = 0;
+ jd->branchtoentry = false;
+ jd->branchtoend = false;
+ jd->returncount = 0;
+ jd->returnblock = NULL;
+ jd->maxlocals = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ jd->isleafmethod = false;
+ else
+#endif
+ jd->isleafmethod = true;
return jd;
}
jd->flags = JITDATA_FLAG_PARSE;
+#if defined(ENABLE_VERIFIER)
if (opt_verify)
jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+#if defined(ENABLE_PROFILING)
if (opt_prof)
jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+#if defined(ENABLE_IFCONV)
if (opt_ifconv)
jd->flags |= JITDATA_FLAG_IFCONV;
+#endif
+
+#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
+ if (opt_inlining && opt_inline_debug_all)
+ jd->flags |= JITDATA_FLAG_INLINE;
+#endif
if (opt_showintermediate)
jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
if (opt_verbosecall)
jd->flags |= JITDATA_FLAG_VERBOSECALL;
+#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
+ if (opt_inlining)
+ jd->flags |= JITDATA_FLAG_COUNTDOWN;
+#endif
+
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
if (!opt_intrp)
# endif
/* initialize the register allocator */
-
+ {
reg_setup(jd);
+ }
#endif
/* setup the codegendata memory */
r = jit_compile_intern(jd);
- /* clear pointers to dump memory area */
-
- m->basicblocks = NULL;
- m->basicblockindex = NULL;
- m->instructions = NULL;
- m->stack = NULL;
-
if (r == NULL) {
/* We had an exception! Finish stuff here if necessary. */
code_codeinfo_free(jd->code);
+#if defined(ENABLE_PROFILING)
/* Release memory for basic block profiling information. */
if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
if (jd->code->bbfrequency != NULL)
MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
+#endif
}
else {
DEBUG_JIT_COMPILEVERBOSE("Running: ");
/* check for max. optimization level */
- optlevel = m->code->optlevel;
+ optlevel = (m->code) ? m->code->optlevel : 0;
+#if 0
if (optlevel == 1) {
/* log_message_method("not recompiling: ", m); */
return NULL;
}
+#endif
- log_message_method("Recompiling start: ", m);
+ DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
STATISTICS(count_jit_calls++);
/* get the optimization flags for the current JIT run */
- jd->flags |= JITDATA_FLAG_REORDER;
- jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
- jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
-/* jd->flags |= JITDATA_FLAG_VERBOSECALL; */
+#if defined(ENABLE_VERIFIER)
+ jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+
+ /* jd->flags |= JITDATA_FLAG_REORDER; */
+ if (opt_showintermediate)
+ jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+ if (opt_showdisassemble)
+ jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+ if (opt_verbosecall)
+ jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+#if defined(ENABLE_INLINING)
+ if (opt_inlining)
+ jd->flags |= JITDATA_FLAG_INLINE;
+#endif
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
r = jit_compile_intern(jd);
- /* clear pointers to dump memory area */
-
- m->basicblocks = NULL;
- m->basicblockindex = NULL;
- m->instructions = NULL;
- m->stack = NULL;
-
if (r == NULL) {
/* We had an exception! Finish stuff here if necessary. */
compilingtime_stop();
#endif
- log_message_method("Recompiling done: ", m);
+ DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
/* return pointer to the methods entry point */
#if defined(ENABLE_RT_TIMING)
struct timespec time_start,time_checks,time_parse,time_stack,
time_typecheck,time_loop,time_ifconv,time_alloc,
- time_rplpoints,time_codegen;
+ time_codegen;
#endif
RT_TIMING_GET_TIME(time_start);
DEBUG_JIT_COMPILEVERBOSE("Compiling: ");
+#if defined(ENABLE_DEBUG_FILTER)
+ show_filters_apply(jd->m);
+#endif
+
/* handle native methods and create a native stub */
if (m->flags & ACC_NATIVE) {
f = NULL;
#endif
- code = codegen_createnativestub(f, m);
+ code = codegen_generate_stub_native(m, f);
assert(!m->code); /* native methods are never recompiled */
m->code = code;
#if defined(ENABLE_STATISTICS)
if (opt_stat) {
- count_tryblocks += m->exceptiontablelength;
count_javacodesize += m->jcodelength + 18;
- count_javaexcsize += m->exceptiontablelength * SIZEOF_VOID_P;
+ count_tryblocks += jd->exceptiontablelength;
+ count_javaexcsize += jd->exceptiontablelength * SIZEOF_VOID_P;
}
#endif
RT_TIMING_GET_TIME(time_parse);
DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+# endif
+ DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
- /* build the CFG */
-
- if (!cfg_build(jd))
- return NULL;
+ /* call stack analysis pass */
- DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
+ if (!stack_analyse(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
- /* call stack analysis pass */
+ return NULL;
+ }
+ RT_TIMING_GET_TIME(time_stack);
- if (!stack_analyse(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
+ DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
- return NULL;
- }
- RT_TIMING_GET_TIME(time_stack);
+ /* Build the CFG. This has to be done after stack_analyse, as
+ there happens the JSR elimination. */
- DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
+ if (!cfg_build(jd))
+ return NULL;
#ifdef ENABLE_VERIFIER
- if (jd->flags & JITDATA_FLAG_VERIFY) {
- DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
+ if (JITDATA_HAS_FLAG_VERIFY(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
- /* call typecheck pass */
- if (!typecheck(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
+ /* call typecheck pass */
+ if (!typecheck(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
- return NULL;
- }
+ return NULL;
+ }
- DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
- }
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
+ }
#endif
- RT_TIMING_GET_TIME(time_typecheck);
+ RT_TIMING_GET_TIME(time_typecheck);
#if defined(ENABLE_LOOP)
- if (opt_loops) {
- depthFirst(jd);
- analyseGraph(jd);
- optimize_loops(jd);
- }
+ if (opt_loops) {
+ depthFirst(jd);
+ analyseGraph(jd);
+ optimize_loops(jd);
+ jit_renumber_basicblocks(jd);
+ }
#endif
- RT_TIMING_GET_TIME(time_loop);
+ RT_TIMING_GET_TIME(time_loop);
#if defined(ENABLE_IFCONV)
- if (JITDATA_HAS_FLAG_IFCONV(jd))
- if (!ifconv_static(jd))
- return NULL;
+ if (JITDATA_HAS_FLAG_IFCONV(jd)) {
+ if (!ifconv_static(jd))
+ return NULL;
+ jit_renumber_basicblocks(jd);
+ }
#endif
- RT_TIMING_GET_TIME(time_ifconv);
+ RT_TIMING_GET_TIME(time_ifconv);
- /* Basic block reordering. I think this should be done after
- if-conversion, as we could lose the ability to do the
- if-conversion. */
+ /* inlining */
- if (JITDATA_HAS_FLAG_REORDER(jd))
- if (!reorder(jd))
- return NULL;
+#if defined(ENABLE_INLINING)
+ if (JITDATA_HAS_FLAG_INLINE(jd)) {
+ if (!inline_inline(jd))
+ return NULL;
+ }
+#endif
+
+#if defined(ENABLE_PROFILING)
+ /* Basic block reordering. I think this should be done after
+ if-conversion, as we could lose the ability to do the
+ if-conversion. */
+
+ if (JITDATA_HAS_FLAG_REORDER(jd)) {
+ if (!reorder(jd))
+ return NULL;
+ jit_renumber_basicblocks(jd);
+ }
+#endif
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
#if defined(ENABLE_SSA)
/* allocate registers */
- if ((opt_lsra) && (cd->exceptiontablelength == 0)) {
+ if ((opt_lsra) && (jd->exceptiontablelength == 0)) {
jd->ls = DNEW(lsradata);
lsra(jd);
} else
# endif /* defined(ENABLE_SSA) */
{
- STATISTICS(count_locals_conflicts += (cd->maxlocals - 1) * (cd->maxlocals));
+ STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
regalloc(jd);
}
- STATISTICS(reg_make_statistics(jd));
+ STATISTICS(simplereg_make_statistics(jd));
DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
# if defined(ENABLE_INTRP)
#endif /* defined(ENABLE_JIT) */
RT_TIMING_GET_TIME(time_alloc);
+#if defined(ENABLE_PROFILING)
/* Allocate memory for basic block profiling information. This
_must_ be done after loop optimization and register allocation,
since they can change the basic block count. */
if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
- code->bbfrequency = MNEW(u4, m->basicblockcount);
+ code->bbfrequency = MNEW(u4, jd->basicblockcount);
+#endif
DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
- /* create the replacement points */
-
- if (!replace_create_replacement_points(jd))
- return NULL;
- RT_TIMING_GET_TIME(time_rplpoints);
-
/* now generate the machine code */
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
if (opt_intrp) {
+#if defined(ENABLE_VERIFIER)
+ if (opt_verify) {
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
+
+ if (!typecheck_stackbased(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
+ return NULL;
+ }
+ }
+#endif
if (!intrp_codegen(jd)) {
DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
} else
# endif
{
- if (!codegen(jd)) {
+ if (!codegen_generate(jd)) {
DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
return NULL;
DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
#if !defined(NDEBUG)
- /* intermediate and assembly code listings */
+#if defined(ENABLE_DEBUG_FILTER)
+ if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+#endif
+ {
+ /* intermediate and assembly code listings */
- if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
- show_method(jd);
- }
- else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+ if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
+ show_method(jd, SHOW_CODE);
+ }
+ else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
# if defined(ENABLE_DISASSEMBLER)
- DISASSEMBLE(code->entrypoint,
- code->entrypoint + (code->mcodelength - cd->dseglen));
+ DISASSEMBLE(code->entrypoint,
+ code->entrypoint + (code->mcodelength - cd->dseglen));
# endif
- }
+ }
- if (opt_showddatasegment)
- dseg_display(jd);
+ if (opt_showddatasegment)
+ dseg_display(jd);
+ }
#endif
DEBUG_JIT_COMPILEVERBOSE("Compiling done: ");
RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
- RT_TIMING_TIME_DIFF(time_alloc,time_rplpoints,RT_TIMING_JIT_RPLPOINTS);
- RT_TIMING_TIME_DIFF(time_rplpoints,time_codegen,RT_TIMING_JIT_CODEGEN);
+ RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
/* return pointer to the methods entry point */
}
+/* jit_invalidate_code *********************************************************
+
+ Mark the compiled code of the given method as invalid and take care that
+ it is replaced if necessary.
+
+ XXX Not fully implemented, yet.
+
+*******************************************************************************/
+
+void jit_invalidate_code(methodinfo *m)
+{
+ codeinfo *code;
+
+ code = m->code;
+ if (code == NULL || CODE_IS_INVALID(code))
+ return;
+
+ CODE_SETFLAG_INVALID(code);
+
+ /* activate mappable replacement points */
+
+#if defined(ENABLE_REPLACEMENT)
+ replace_activate_replacement_points(code, true);
+#else
+ vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
+#endif
+}
+
+
+/* jit_request_optimization ****************************************************
+
+ Request optimization of the given method. If the code of the method is
+ unoptimized, it will be invalidated, so the next jit_get_current_code(m)
+ triggers an optimized recompilation.
+ If the method is already optimized, this function does nothing.
+
+ IN:
+ m................the method
+
+*******************************************************************************/
+
+void jit_request_optimization(methodinfo *m)
+{
+ codeinfo *code;
+
+ code = m->code;
+
+ if (code && code->optlevel == 0)
+ jit_invalidate_code(m);
+}
+
+
+/* jit_get_current_code ********************************************************
+
+ Get the currently valid code for the given method. If there is no valid
+ code, (re)compile the method.
+
+ IN:
+ m................the method
+
+ RETURN VALUE:
+ the codeinfo* for the current code, or
+ NULL if an exception has been thrown during recompilation.
+
+*******************************************************************************/
+
+codeinfo *jit_get_current_code(methodinfo *m)
+{
+ assert(m);
+
+ /* if we have valid code, return it */
+
+ if (m->code && CODE_IS_VALID(m->code))
+ return m->code;
+
+ /* otherwise: recompile */
+
+ if (!jit_recompile(m))
+ return NULL;
+
+ assert(m->code);
+
+ return m->code;
+}
+
+
/* jit_asm_compile *************************************************************
This method is called from asm_vm_call_method and does:
*******************************************************************************/
+#if defined(ENABLE_JIT)
u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra)
{
stackframeinfo sfi;
u1 *pa;
ptrint *p;
- /* create the stackframeinfo (XPC is equal to RA) */
+ /* create the stackframeinfo (subtract 1 from RA as it points to the */
+ /* instruction after the call) */
- stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
+ stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra-1);
/* actually compile the method */
return entrypoint;
}
+#endif /* defined(ENABLE_JIT) */
/* jit_complement_condition ****************************************************
}
+/* jit_renumber_basicblocks ****************************************************
+
+ Set the ->nr of all blocks so it increases when traversing ->next.
+
+ IN:
+ jitdata..........the current jitdata
+
+*******************************************************************************/
+
+void jit_renumber_basicblocks(jitdata *jd)
+{
+ s4 nr;
+ basicblock *bptr;
+
+ nr = 0;
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+ bptr->nr = nr++;
+ }
+
+ /* we have one block more than jd->basicblockcount (the end marker) */
+
+ assert(nr == jd->basicblockcount + 1);
+}
+
+
+/* jit_check_basicblock_numbers ************************************************
+
+ Assert that the ->nr of the first block is zero and increases by 1 each
+ time ->next is traversed.
+ This function should be called before any analysis that relies on
+ the basicblock numbers.
+
+ IN:
+ jitdata..........the current jitdata
+
+ NOTE: Aborts with an assertion if the condition is not met!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void jit_check_basicblock_numbers(jitdata *jd)
+{
+ s4 nr;
+ basicblock *bptr;
+
+ nr = 0;
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+ assert(bptr->nr == nr);
+ nr++;
+ }
+
+ /* we have one block more than jd->basicblockcount (the end marker) */
+
+ assert(nr == jd->basicblockcount + 1);
+}
+#endif /* !defined(NDEBUG) */
+
+
/*
* 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