X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fjit.c;h=f27f52ee99614c42d5920daf31440a0f0295205f;hb=d75b6037acf17c342166b9c9bd6e657dfdd12cd9;hp=a72d201a7c097c1f84f55f12e44de70dc113a3d8;hpb=06b6981a1f14ca367e1819de2dea14906b8848a1;p=cacao.git diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index a72d201a7..f27f52ee9 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -1,9 +1,9 @@ -/* 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. @@ -27,182 +27,60 @@ 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 -#include -#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] = { @@ -219,7 +97,6 @@ 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 */ @@ -230,7 +107,6 @@ int jcommandsize[256] = { #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 */ @@ -804,9 +680,27 @@ int jcommandsize[256] = { 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, @@ -819,15 +713,15 @@ char *icmd_names[256] = { "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 */ @@ -886,14 +780,14 @@ char *icmd_names[256] = { "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 */ @@ -1018,10 +912,16 @@ char *icmd_names[256] = { "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", @@ -1029,7 +929,9 @@ char *icmd_names[256] = { "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 */ @@ -1241,10 +1143,16 @@ char *opcode_names[256] = { "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", @@ -1252,8 +1160,9 @@ char *opcode_names[256] = { "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 */ @@ -1306,11 +1215,25 @@ stdopdescriptor builtintable[] = { }; #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 @@ -1320,12 +1243,13 @@ int builtintablelen; /* XXX make static again? */ 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"}, @@ -1368,18 +1292,26 @@ builtin_descriptor builtin_desc[] = { 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,""}, + {255,NULL,0,0,0,0,0,0,0,""}, /* 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"}, @@ -1407,10 +1339,6 @@ builtin_descriptor builtin_desc[] = { /* include compiler subsystems ************************************************/ -/* from codegen.inc */ -extern int dseglen; - - /* dummy function, used when there is no JavaVM code available */ static void* do_nothing_function() @@ -1421,206 +1349,318 @@ 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; @@ -1632,29 +1672,6 @@ static int stdopcompare(const void *a, const void *b) 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