-/* jit/jit.c - calls the code generation functions
+/* vm/jit/jit.c - calls the code generation functions
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ Copyright (C) 1996-2005 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
This file is part of CACAO.
Authors: Andreas Krall
Reinhard Grafl
- $Id: jit.c 727 2003-12-11 10:52:40Z edwin $
+ Changes: Edwin Steiner
+
+ $Id: jit.c 1735 2004-12-07 14:33:27Z twisti $
*/
-#include <stdlib.h>
-#include <string.h>
-#include "global.h" /* we define _GNU_SOURCE there */
-#include "tables.h"
-#include "loader.h"
-#include "jit.h"
-#include "parse.h"
-#include "stack.h"
-#include "reg.h"
-#include "inline.h"
-#include "builtin.h"
-#include "native.h"
-#include "asmpart.h"
#include "codegen.h"
-#include "types.h"
-#include "threads/thread.h"
#include "disass.h"
-#include "loop/loop.h"
-#include "loop/graph.h"
-#include "loop/analyze.h"
-#include "toolbox/loging.h"
-#include "toolbox/memory.h"
-
-
-/* global switches ************************************************************/
-bool compileverbose = false;
-bool showstack = false;
-bool showdisassemble = false;
-bool showddatasegment = false;
-bool showintermediate = false;
-int optimizelevel = 0;
-
-bool useinlining = false;
-bool inlinevirtuals = false;
-bool inlineexceptions = false;
-bool inlineparamopt = false;
-bool inlineoutsiders = false;
-
-bool checkbounds = true;
-bool checknull = true;
-bool opt_noieee = false;
-bool checksync = true;
-bool opt_loops = false;
-
-bool getcompilingtime = false;
-long compilingtime = 0;
-
-int has_ext_instr_set = 0;
-
-bool statistics = false;
-
-int count_jit_calls = 0;
-int count_methods = 0;
-int count_spills = 0;
-int count_pcmd_activ = 0;
-int count_pcmd_drop = 0;
-int count_pcmd_zero = 0;
-int count_pcmd_const_store = 0;
-int count_pcmd_const_alu = 0;
-int count_pcmd_const_bra = 0;
-int count_pcmd_load = 0;
-int count_pcmd_move = 0;
-int count_load_instruction = 0;
-int count_pcmd_store = 0;
-int count_pcmd_store_comb = 0;
-int count_dup_instruction = 0;
-int count_pcmd_op = 0;
-int count_pcmd_mem = 0;
-int count_pcmd_met = 0;
-int count_pcmd_bra = 0;
-int count_pcmd_table = 0;
-int count_pcmd_return = 0;
-int count_pcmd_returnx = 0;
-int count_check_null = 0;
-int count_check_bound = 0;
-int count_max_basic_blocks = 0;
-int count_basic_blocks = 0;
-int count_javainstr = 0;
-int count_max_javainstr = 0;
-int count_javacodesize = 0;
-int count_javaexcsize = 0;
-int count_calls = 0;
-int count_tryblocks = 0;
-int count_code_len = 0;
-int count_data_len = 0;
-int count_cstub_len = 0;
-int count_nstub_len = 0;
-int count_max_new_stack = 0;
-int count_upper_bound_new_stack = 0;
-static int count_block_stack_init[11] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_block_stack = count_block_stack_init;
-static int count_analyse_iterations_init[5] = {
- 0, 0, 0, 0, 0
-};
-int *count_analyse_iterations = count_analyse_iterations_init;
-static int count_method_bb_distribution_init[9] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0
-};
-int *count_method_bb_distribution = count_method_bb_distribution_init;
-static int count_block_size_distribution_init[18] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0
-};
-int *count_block_size_distribution = count_block_size_distribution_init;
-static int count_store_length_init[21] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_store_length = count_store_length_init;
-static int count_store_depth_init[11] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_store_depth = count_store_depth_init;
-
-
-
-/* global compiler variables **************************************************/
-
- /* data about the currently compiled method */
-
-classinfo *class; /* class the compiled method belongs to */
-methodinfo *method; /* pointer to method info of compiled method */
-static utf *descriptor; /* type descriptor of compiled method */
-int mparamcount; /* number of parameters (incl. this) */
-u1 *mparamtypes; /* types of all parameters (TYPE_INT, ...) */
-static int mreturntype; /* return type of method */
-
-int maxstack; /* maximal JavaVM stack size */
-int maxlocals; /* maximal number of local JavaVM variables */
-int jcodelength; /* length of JavaVM-codes */
-u1 *jcode; /* pointer to start of JavaVM-code */
-int exceptiontablelength; /* length of exception table */
-xtable *extable; /* pointer to start of exception table */
-exceptiontable *raw_extable;
-
-int block_count; /* number of basic blocks */
-basicblock *block; /* points to basic block array */
-int *block_index; /* a table which contains for every byte of */
- /* JavaVM code a basic block index if at this */
- /* byte there is the start of a basic block */
-
-int instr_count; /* number of JavaVM instructions */
-instruction *instr; /* points to intermediate code instructions */
-
-int stack_count; /* number of stack elements */
-stackelement *stack; /* points to intermediate code instructions */
-
-bool isleafmethod; /* true if a method doesn't call subroutines */
+#include "types.h"
+#include "mm/memory.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
+#include "vm/jit/codegen.inc.h"
+#include "vm/jit/jit.h"
+#ifdef LSRA
+#include "vm/jit/lsra.h"
+#endif
+#include "vm/jit/parse.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/inline/inline.h"
+#include "vm/jit/inline/parseRT.h"
+#include "vm/jit/loop/analyze.h"
+#include "vm/jit/loop/graph.h"
+#include "vm/jit/loop/loop.h"
+#include "vm/jit/verify/typecheck.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+# include "threads/native/threads.h"
+# else
+# include "threads/green/threads.h"
+# endif
+#endif
-basicblock *last_block; /* points to the end of the BB list */
-bool regs_ok; /* true if registers have been allocated */
-/* list of all classes used by the compiled method which have to be */
-/* initialised (if not already done) before execution of this method */
-chain *uninitializedclasses;
+/* global switches ************************************************************/
int stackreq[256];
+
+#if defined(__I386__)
+/* these define if a method has ICMDs which use %edx or %ecx */
+bool method_uses_ecx;
+bool method_uses_edx;
+#endif
+
int jcommandsize[256] = {
#define ICMD_ICONST 3 /* val.i = constant */
1,
#define JAVA_ICONST_1 4
-#define ICMD_IREM0X10001 4
1,
#define JAVA_ICONST_2 5
#define ICMD_IDIVPOW2 5 /* val.i = constant */
#define JAVA_ICONST_4 7
1,
#define JAVA_ICONST_5 8
-#define ICMD_LREM0X10001 8
1,
#define JAVA_LCONST_0 9
#define ICMD_LCONST 9 /* val.l = constant */
5,
#define JAVA_BREAKPOINT 202
1,
+#define ICMD_CHECKEXCEPTION 203
+ 1,
+#define ICMD_IASTORECONST 204
+ 1,
+#define ICMD_LASTORECONST 205
+ 1,
+#define ICMD_FASTORECONST 206
+ 1,
+#define ICMD_DASTORECONST 207
+ 1,
+#define ICMD_AASTORECONST 208
+ 1,
+#define ICMD_BASTORECONST 209
+ 1,
+#define ICMD_CASTORECONST 210
+ 1,
+#define ICMD_SASTORECONST 211
+ 1,
- 1,1,1,1,1,1,1,1, /* unused */
- 1,1,1,1,1,1,1,1,1,1,
+ /* unused */
+ 1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
"ACONST ", /* 1 */
"NULLCHECKPOP ", /* ICONST_M1 2 */
"ICONST ", /* 3 */
- "IREM0X10001 ", /* ICONST_1 4 */
+ "UNDEF4 ", /* ICONST_1 4 */
"IDIVPOW2 ", /* ICONST_2 5 */
"LDIVPOW2 ", /* ICONST_3 6 */
- "UNDEF__7 ", /* ICONST_4 7 */
- "LREM0X10001 ", /* ICONST_5 8 */
+ "UNDEF7 ", /* ICONST_4 7 */
+ "UNDEF8 ", /* ICONST_5 8 */
"LCONST ", /* 9 */
"LCMPCONST ", /* LCONST_1 10 */
"FCONST ", /* 11 */
- "UNDEF_12 ", /* FCONST_1 12 */
+ "UNDEF12 ", /* FCONST_1 12 */
"ELSE_ICONST ", /* FCONST_2 13 */
"DCONST ", /* 14 */
"IFEQ_ICONST ", /* DCONST_1 15 */
"IF_LCMPGE ", /* FSTORE_1 68 */
"IF_LCMPGT ", /* FSTORE_2 69 */
"IF_LCMPLE ", /* FSTORE_3 70 */
- "UNDEF_71 ", /* DSTORE_0 71 */
- "UNDEF_72 ", /* DSTORE_1 72 */
- "UNDEF_73 ", /* DSTORE_2 73 */
- "UNDEF_74 ", /* DSTORE_3 74 */
- "UNDEF_75 ", /* ASTORE_0 75 */
- "UNDEF_76 ", /* ASTORE_1 76 */
- "UNDEF_77 ", /* ASTORE_2 77 */
- "UNDEF_78 ", /* ASTORE_3 78 */
+ "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 */
"UNDEF200 ", /* GOTO_W 200 */
"UNDEF201 ", /* JSR_W 201 */
"UNDEF202 ", /* BREAKPOINT 202 */
-
- "UNDEF203","UNDEF204","UNDEF205",
- "UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
- "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "CHECKEXCEPTION", /* UNDEF203 203 */
+ "IASTORECONST ", /* 204 */
+ "LASTORECONST ", /* 205 */
+ "FASTORECONST ", /* 206 */
+ "DASTORECONST ", /* 207 */
+ "AASTORECONST ", /* 208 */
+ "BASTORECONST ", /* 209 */
+ "CASTORECONST ", /* 210 */
+ "SASTORECONST ", /* 211 */
+ "UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF226","UNDEF227","UNDEF228","UNDEF229","UNDEF230",
"UNDEF236","UNDEF237","UNDEF238","UNDEF239","UNDEF240",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF246","UNDEF247","UNDEF248","UNDEF249","UNDEF250",
- "UNDEF251","UNDEF252",
+
+ "INLINE_START", /* 251 */
+ "INLINE_END", /* 252"*/
"BUILTIN3 ", /* 253 */
"BUILTIN2 ", /* 254 */
"GOTO_W ", /* GOTO_W 200 */
"JSR_W ", /* JSR_W 201 */
"BREAKPOINT ", /* BREAKPOINT 202 */
-
- "UNDEF203","UNDEF204","UNDEF205",
- "UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
- "UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
+ "CHECKEXCEPTION", /* UNDEF203 203 */
+ "IASTORECONST ", /* 204 */
+ "LASTORECONST ", /* 205 */
+ "FASTORECONST ", /* 206 */
+ "DASTORECONST ", /* 207 */
+ "AASTORECONST ", /* 208 */
+ "BASTORECONST ", /* 209 */
+ "CASTORECONST ", /* 210 */
+ "SASTORECONST ", /* 211 */
+ "UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF226","UNDEF227","UNDEF228","UNDEF229","UNDEF230",
"UNDEF236","UNDEF237","UNDEF238","UNDEF239","UNDEF240",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF246","UNDEF247","UNDEF248","UNDEF249","UNDEF250",
- "UNDEF251","UNDEF252",
+ "INLINE_START", /* 251 */
+ "INLINE_END", /* 252 */
"BUILTIN3 ", /* 253 */
"BUILTIN2 ", /* 254 */
"BUILTIN1 " /* 255 */
};
#endif
-int builtintablelen; /* XXX make static again? */
+
+static int builtintablelen;
#endif /* USEBUILTINTABLE */
+
+#define EXTABLEN
+/* \
+ { \
+ printf("PARSE method name ="); \
+ utf_display(m->class->name); \
+ printf("."); \
+ method_display(m); \
+ printf(" exceptiontablelength %d\n",m->exceptiontablelength); \
+ fflush(stdout); \
+ }
+*/
+
/*****************************************************************************
TABLE OF BUILTIN FUNCTIONS
The first part of the table (up to the 255-marker) lists the
opcodes which are automatically replaced in stack.c.
- The second part lists the builtin functions which are used for
- BUILTIN* opcodes in parse.c and stack.c.
+ The second part lists the builtin functions which are "manually"
+ used for BUILTIN* opcodes in parse.c and stack.c.
*****************************************************************************/
builtin_descriptor builtin_desc[] = {
+#if defined(USEBUILTINTABLE)
{ICMD_LCMP , BUILTIN_lcmp ,ICMD_BUILTIN2,TYPE_LONG ,TYPE_LONG ,TYPE_VOID ,TYPE_INT ,
SUPPORT_LONG && SUPPORT_LONG_CMP,false,"lcmp"},
SUPPORT_FLOAT && SUPPORT_FICVT,true ,"f2i"},
{ICMD_D2I , BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,
SUPPORT_DOUBLE && SUPPORT_FICVT,true ,"d2i"},
+#endif
/* this record marks the end of the automatically replaced opcodes */
- {255 , NULL ,0 ,0 ,0 ,0 ,0 ,
- true ,false,"<INVALID>"},
+ {255,NULL,0,0,0,0,0,0,0,"<INVALID>"},
/* the following functions are not replaced automatically */
+
+#if defined(__ALPHA__)
+ {255, BUILTIN_f2l ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"f2l"},
+ {255, BUILTIN_d2l ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_LONG ,0,0,"d2l"},
+ {255, BUILTIN_f2i ,ICMD_BUILTIN1,TYPE_FLOAT ,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"f2i"},
+ {255, BUILTIN_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
+#endif
+
{255,BUILTIN_instanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"instanceof"},
{255,BUILTIN_arrayinstanceof ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_INT ,0,0,"arrayinstanceof"},
{255,BUILTIN_checkarraycast ,ICMD_BUILTIN2,TYPE_ADR ,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,0,0,"checkarraycast"},
{255,BUILTIN_aastore ,ICMD_BUILTIN3,TYPE_ADR ,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,0,0,"aastore"},
{255,BUILTIN_new ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"new"},
- {255,BUILTIN_newarray ,ICMD_BUILTIN1,TYPE_ADR ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
+ {255,BUILTIN_newarray ,ICMD_BUILTIN2,TYPE_INT ,TYPE_ADR ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray"},
{255,BUILTIN_newarray_boolean,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_boolean"},
{255,BUILTIN_newarray_char ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_char"},
{255,BUILTIN_newarray_float ,ICMD_BUILTIN1,TYPE_INT ,TYPE_VOID ,TYPE_VOID ,TYPE_ADR ,0,0,"newarray_float"},
/* include compiler subsystems ************************************************/
-/* from codegen.inc */
-extern int dseglen;
-
-
/* dummy function, used when there is no JavaVM code available */
static void* do_nothing_function()
/* jit_compile *****************************************************************
- jit_compile, new version of compiler, translates one method to machine code
+ jit_compile, new version of compiler, translates one method to machine code
*******************************************************************************/
-methodptr jit_compile(methodinfo *m)
+static functionptr jit_compile_intern(methodinfo *m, codegendata *cd,
+ registerdata *rd, loopdata *ld,
+ t_inlining_globals *id);
+
+functionptr jit_compile(methodinfo *m)
{
- int dumpsize;
- long starttime = 0;
- long stoptime = 0;
+ static bool jitrunning;
+ functionptr r;
+ s4 dumpsize;
+ codegendata *cd;
+ registerdata *rd;
+ loopdata *ld;
+ t_inlining_globals *id;
+
+ if (opt_stat)
+ count_jit_calls++;
+
+ /* enter a monitor on the method */
- count_jit_calls++;
+ builtin_monitorenter((java_objectheader *) m);
/* if method has been already compiled return immediately */
- if (m->entrypoint)
+ if (m->entrypoint) {
+ builtin_monitorexit((java_objectheader *) m);
+
return m->entrypoint;
+ }
+
+ if (opt_stat)
+ count_methods++;
+
+ /* if there is no javacode, print error message and return empty method */
+
+ if (!m->jcode) {
+ if (compileverbose)
+ log_message_method("No code given for: ", m);
+
+ /*m->entrypoint = (methodptr) do_nothing_function;*/
+ m->entrypoint = (functionptr) do_nothing_function;
+
+ return m->entrypoint; /* return empty method */
+ }
+
+#if 0
+ if (jitrunning) {
+ printf("JITRUNNING!!! new method=");
+ utf_display_classname(m->class->name);printf(".");utf_display(m->name);
+ printf("\n");
+ }
+
+ /* now the jit is running */
- count_methods++;
+ jitrunning = true;
+#endif
- intsDisable(); /* disable interrupts */
+ /* measure time */
- regs_ok = false;
+ if (getcompilingtime)
+ compilingtime_start();
/* mark start of dump memory area */
dumpsize = dump_size();
+ /* allocate memory */
+
+ cd = DNEW(codegendata);
+ rd = DNEW(registerdata);
+ ld = DNEW(loopdata);
+ id = DNEW(t_inlining_globals);
+
+ /* RTA static analysis must be called before inlining */
+ if (opt_rt)
+ RT_jit_parse(m); /* will be called just once */
+ /* return value ignored for now */
+
+ /* must be called before reg_setup, because it can change maxlocals */
+ /* init reqd to initialize for parse even in no inlining */
+ inlining_setup(m, id);
+
+ /* initialize the register allocator */
+ reg_setup(m, rd, id);
+
+ /* setup the codegendata memory */
+ codegen_setup(m, cd, id);
+
+ /* now call internal compile function */
+
+ r = jit_compile_intern(m, cd, rd, ld, id);
+
+ /* free some memory */
+
+ reg_free(m, rd);
+ codegen_free(m, cd);
+
+ /* clear pointers to dump memory area */
+
+ m->basicblocks = NULL;
+ m->basicblockindex = NULL;
+ m->instructions = NULL;
+ m->stack = NULL;
+ /* NO !!! m->exceptiontable = NULL; */
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
/* measure time */
if (getcompilingtime)
- starttime = getcputime();
+ compilingtime_stop();
- /* if there is no javacode print error message and return empty method */
+ jitrunning = false;
- if (!m->jcode) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "No code given for: ");
- utf_sprint(logtext+strlen(logtext), m->class->name);
- strcpy(logtext+strlen(logtext), ".");
- utf_sprint(logtext+strlen(logtext), m->name);
- utf_sprint(logtext+strlen(logtext), m->descriptor);
- dolog(logtext);
- intsRestore(); /* enable interrupts again */
- return (methodptr) do_nothing_function; /* return empty method */
+ /* define in options.h; Used in main.c, jit.c & inline.c */
+ #ifdef INAFTERMAIN
+ if ((utf_new_char("main") == m->name) && (useinliningm))
+ useinlining = false;
+ #endif
+
+ /* leave the monitor */
+
+ builtin_monitorexit((java_objectheader *) m );
+
+ if (r) {
+ if (compileverbose)
+ log_message_method("Running: ", m);
}
+ /* return pointer to the methods entry point */
+
+ return r;
+}
+
+
+/* jit_compile_intern **********************************************************
+
+ Static internal function which does the actual compilation.
+
+*******************************************************************************/
+
+static functionptr jit_compile_intern(methodinfo *m, codegendata *cd,
+ registerdata *rd, loopdata *ld,
+ t_inlining_globals *id)
+{
/* print log message for compiled method */
- if (compileverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Compiling: ");
- utf_sprint(logtext+strlen(logtext), m->class->name);
- strcpy(logtext+strlen(logtext), ".");
- utf_sprint(logtext+strlen(logtext), m->name);
- utf_sprint(logtext+strlen(logtext), m->descriptor);
- dolog(logtext);
- }
+ if (compileverbose)
+ log_message_method("Compiling: ", m);
+
+ /* initialize the static function's class */
+ if (m->flags & ACC_STATIC && !m->class->initialized) {
+ if (initverbose)
+ log_message_class("Initialize class ", m->class);
+
+ if (!class_init(m->class))
+ return NULL;
+ }
/* initialisation of variables and subsystems */
- isleafmethod = true;
-
- method = m;
- class = m->class;
- descriptor = m->descriptor;
- maxstack = m->maxstack;
- maxlocals = m->maxlocals;
- jcodelength = m->jcodelength;
- jcode = m->jcode;
- exceptiontablelength = m->exceptiontablelength;
- raw_extable = m->exceptiontable;
-
-#ifdef STATISTICS
- count_tryblocks += exceptiontablelength;
- count_javacodesize += jcodelength + 18;
- count_javaexcsize += exceptiontablelength * POINTERSIZE;
+ m->isleafmethod = true;
+
+#if defined(STATISTICS)
+ if (opt_stat) {
+ count_tryblocks += m->exceptiontablelength;
+ count_javacodesize += m->jcodelength + 18;
+ count_javaexcsize += m->exceptiontablelength * POINTERSIZE;
+ }
#endif
/* initialise parameter type descriptor */
descriptor2types(m);
- mreturntype = m->returntype;
- mparamcount = m->paramcount;
- mparamtypes = m->paramtypes;
- /* initialize class list with class the compiled method belongs to */
+#if defined(__I386__)
+ /* we try to use these registers as scratch registers */
+ if (m->exceptiontablelength > 0) {
+ method_uses_ecx = true;
+ method_uses_edx = true;
+
+ } else {
+ /* XXX when we use this, we have to save used registers in asm_
+ functions (see asm_check_clinit */
+/* method_uses_ecx = false; */
+/* method_uses_edx = false; */
+ method_uses_ecx = true;
+ method_uses_edx = true;
+ }
+#endif
- uninitializedclasses = chain_new();
- compiler_addinitclass(m->class);
+ /* call the compiler passes ***********************************************/
+ if (compileverbose)
+ log_message_method("Parsing: ", m);
- /* call the compiler passes ***********************************************/
+ /* call parse pass */
+ if (!parse(m, cd, id)) {
+ if (compileverbose)
+ log_message_method("Exception while parsing: ", m);
- /* must be call before reg_init, because it can change maxlocals */
- if (useinlining)
- inlining_init(m);
+ return NULL;
+ }
- reg_init(m);
+ if (compileverbose) {
+ log_message_method("Parsing done: ", m);
+ log_message_method("Analysing: ", m);
+ }
- codegen_init();
+ /* call stack analysis pass */
+ if (!analyse_stack(m, cd, rd)) {
+ if (compileverbose)
+ log_message_method("Exception while analysing: ", m);
+
+ return NULL;
+ }
+
+ if (compileverbose)
+ log_message_method("Analysing done: ", m);
- parse();
- analyse_stack();
-
#ifdef CACAO_TYPECHECK
- /* print log message for compiled method */
+ if (opt_verify) {
+ if (compileverbose)
+ log_message_method("Typechecking: ", m);
- if (compileverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Typechecking: ");
- utf_sprint(logtext+strlen(logtext), m->class->name);
- strcpy(logtext+strlen(logtext), ".");
- utf_sprint(logtext+strlen(logtext), m->name);
- utf_sprint(logtext+strlen(logtext), m->descriptor);
- dolog(logtext);
- }
+ /* call typecheck pass */
+ if (!typecheck(m, cd, rd)) {
+ if (compileverbose)
+ log_message_method("Exception while typechecking: ", m);
- typecheck();
-
- if (compileverbose) {
- dolog("Typechecking done.");
+ return NULL;
+ }
+
+ if (compileverbose)
+ log_message_method("Typechecking done: ", m);
}
#endif
-
+
if (opt_loops) {
- depthFirst();
- analyseGraph();
- optimize_loops();
+ depthFirst(m, ld);
+ analyseGraph(m, ld);
+ optimize_loops(m, cd, ld);
}
#ifdef SPECIALMEMUSE
- preregpass();
+ preregpass(m, rd);
#endif
- regalloc();
- regs_ok = true;
- codegen();
+ if (compileverbose)
+ log_message_method("Allocating registers: ", m);
- /* intermediate and assembly code listings ********************************/
-
- if (showintermediate)
- show_icmd_method();
- else if (showdisassemble)
- disassemble((void*) (m->mcode + dseglen), m->mcodelength - dseglen);
+ /* allocate registers */
+#ifdef LSRA
+ if (opt_lsra)
+ lsra(m, cd, rd, ld, id);
+ else
+#endif
+ regalloc(m, cd, rd);
- if (showddatasegment)
- dseg_display((void*) (m->mcode));
+ if (compileverbose) {
+ log_message_method("Allocating registers done: ", m);
+ log_message_method("Generating code: ", m);
+ }
- /* release dump area */
+ /* now generate the machine code */
+ codegen(m, cd, rd);
- dump_release(dumpsize);
+ if (compileverbose)
+ log_message_method("Generating code done: ", m);
- /* measure time */
+ /* intermediate and assembly code listings */
+
+ if (showintermediate) {
+ show_icmd_method(m, cd, rd);
- if (getcompilingtime) {
- stoptime = getcputime();
- compilingtime += (stoptime-starttime);
+ } else if (showdisassemble) {
+ disassemble((void *) ((long) m->mcode + cd->dseglen),
+ m->mcodelength - cd->dseglen);
}
- /* initialize all used classes */
- /* because of reentrant code global variables are not allowed here */
-
- {
- chain *ul = uninitializedclasses; /* list of uninitialized classes */
- classinfo *c; /* single class */
-
- while ((c = chain_first(ul)) != NULL) {
- chain_remove(ul);
- class_init(c); /* may again call the compiler */
- }
- chain_free(ul);
- }
+ if (showddatasegment)
+ dseg_display(m, cd);
- intsRestore(); /* enable interrupts again */
+ if (compileverbose)
+ log_message_method("Compiling done: ", m);
/* return pointer to the methods entry point */
-
+
return m->entrypoint;
}
+void compile_all_class_methods(classinfo *c)
+{
+ s4 i;
+
+ for (i = 0; i < c->methodscount; i++) {
+ (void) jit_compile(&(c->methods[i]));
+ }
+}
+
/* functions for compiler initialisation and finalisation *********************/
#ifdef USEBUILTINTABLE
-/* XXX delete */
-#if 0
-static int stdopcompare(const void *a, const void *b)
-{
- stdopdescriptor *o1 = (stdopdescriptor *) a;
- stdopdescriptor *o2 = (stdopdescriptor *) b;
- if (!o1->supported && o2->supported)
- return -1;
- if (o1->supported && !o2->supported)
- return 1;
- return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
-}
-#endif
static int stdopcompare(const void *a, const void *b)
{
builtin_descriptor *o1 = (builtin_descriptor *) a;
return (o1->opcode < o2->opcode) ? -1 : (o1->opcode > o2->opcode);
}
-/* XXX delete */
-#if 0
-static inline void sort_builtintable()
-{
- int len;
-
- len = sizeof(builtintable) / sizeof(stdopdescriptor);
- qsort(builtintable, len, sizeof(builtin_descriptor), stdopcompare);
-
- for (--len; len>=0 && builtintable[len].supported; len--);
- builtintablelen = ++len;
-
-#if 0
- {
- int i;
- for (i=0; i<len; i++)
- if (!builtintable[i].supported)
- printf("%s\n", icmd_names[builtintable[i].opcode]);
- }
-#endif
-}
-#endif
-
static inline void sort_builtintable()
{
int len;
}
-#if 0
-stdopdescriptor *find_builtin(int icmd)
-{
- builtin_descriptor *first = builtintable;
- builtin_descriptor *last = builtintable + builtintablelen;
-#endif
builtin_descriptor *find_builtin(int icmd)
{
builtin_descriptor *first = builtin_desc;
void jit_init()
{
- int i;
+ s4 i;
#ifdef USEBUILTINTABLE
sort_builtintable();
stackreq[JAVA_DUP_X2] = 4;
stackreq[JAVA_DUP2_X1] = 3;
stackreq[JAVA_DUP2_X2] = 4;
-
- init_exceptions();
-}
+ /* initialize the codegen stuff */
+ codegen_init();
+}
void jit_close()
{
- codegen_close();
- reg_close();
}