- moved statistic variables into statistics.*
[cacao.git] / jit / jit.c
index a0fbfd00771665dcd09eb53a2be278df0cb9cc77..ec6e1cc3713b17e340e341e48c3c420c4a640a08 100644 (file)
--- a/jit/jit.c
+++ b/jit/jit.c
 
    Changes: Edwin Steiner
 
-   $Id: jit.c 854 2004-01-06 15:37:05Z twisti $
+   $Id: jit.c 1229 2004-06-30 19:39:04Z twisti $
 
 */
 
 
 #include <stdlib.h>
 #include <string.h>
-#include "global.h"    /* we define _GNU_SOURCE there */
-#include "main.h"
+#include "global.h"
 #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 "options.h"
+#include "statistics.h"
+#include "jit/inline.h"
+#include "jit/jit.h"
+#include "jit/parse.h"
+#include "jit/stack.h"
+#include "jit/reg.h"
+#include "jit/typecheck.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/logging.h"
 #include "toolbox/memory.h"
 
 
 /* global switches ************************************************************/
 
-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  */
-
-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;
-
 int stackreq[256];
 
                                 
@@ -789,9 +673,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,
@@ -1003,10 +905,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",
@@ -1226,10 +1134,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",
@@ -1420,43 +1334,71 @@ static void* do_nothing_function()
 
 *******************************************************************************/
 
-#if 0
-#define LOG_STEP(step)                                                                                 \
-       if (compileverbose) {                                                                           \
-               char logtext[MAXLOGTEXT];                                                               \
-               sprintf(logtext, "%s: ",step);                                                  \
-               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);             \
-               log_text(logtext);                                                                              \
-       }
-#else
-#define LOG_STEP(step)
-#endif
+static methodptr jit_compile_intern(methodinfo *m);
 
 methodptr jit_compile(methodinfo *m)
 {
-       int dumpsize;
-       long starttime = 0;
-       long stoptime  = 0;
+       static bool jitrunning;
+       methodptr r;
+       s4 dumpsize;
+       s8 starttime = 0;
+       s8 stoptime  = 0;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+#else
+       intsDisable();      /* disable interrupts */
+#endif
+#endif
 
-       count_jit_calls++;
+       if (opt_stat)
+               count_jit_calls++;
 
        /* if method has been already compiled return immediately */
 
-       if (m->entrypoint)
+       if (m->entrypoint) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+               compiler_unlock();
+#else
+               intsRestore();                             /* enable interrupts again */
+#endif
+#endif
+
                return m->entrypoint;
+       }
+
+       if (opt_stat)
+               count_methods++;
 
-       count_methods++;
+       /* initialize the static function's class */
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_lock(&compiler_mutex);
+       if (m->flags & ACC_STATIC && !m->class->initialized) {
+               if (initverbose)
+                       log_message_class("Initialize class ", m->class);
+
+               if (!class_init(m->class)) {
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+                       compiler_unlock();
+#else
+                       intsRestore();
 #endif
+#endif
+                       return NULL;
+               }
+       }
 
-       intsDisable();      /* disable interrupts */
+       if (jitrunning) {
+               printf("JITRUNNING!!! new method=");
+               utf_display_classname(m->class->name);printf(".");utf_display(m->name);
+               printf("\n");
+       }
 
-       regs_ok = false;
+       /* now the jit is running */
+
+       jitrunning = true;
 
        /* mark start of dump memory area */
 
@@ -1467,143 +1409,211 @@ methodptr jit_compile(methodinfo *m)
        if (getcompilingtime)
                starttime = getcputime();
 
-       /* if there is no javacode print error message and return empty method    */
+       /* now call internal compile function */
+
+       r = jit_compile_intern(m);
+
+       if (r) {
+               if (compileverbose)
+                       log_message_method("Running: ", m);
+       }
+
+       /* clear pointers to dump memory area */
+
+       m->basicblocks = NULL;
+       m->basicblockindex = NULL;
+       m->instructions = NULL;
+       m->stack = NULL;
+       m->exceptiontable = NULL;
+       m->registerdata = NULL;
+
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       /* measure time */
+
+       if (getcompilingtime) {
+               stoptime = getcputime();
+               compilingtime += (stoptime - starttime);
+       }
+
+       jitrunning = false;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_unlock();
+#else
+       intsRestore();
+#endif
+#endif
+
+       /* return pointer to the methods entry point */
+
+       return r;
+}
+
+
+static methodptr jit_compile_intern(methodinfo *m)
+{
+       /* if there is no javacode, print error message and return empty method   */
 
        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);
-               log_text(logtext);
-               intsRestore();                             /* enable interrupts again */
+               if (compileverbose)
+                       log_message_method("No code given for: ", m);
+
                return (methodptr) do_nothing_function;    /* return empty method     */
        }
 
        /* 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);
-               log_text(logtext);
-       }
+       if (compileverbose)
+               log_message_method("Compiling: ", m);
 
-       /* initialize the function's class */
-       if (!m->class->initialized) {
-               if (initverbose) {
-                       char logtext[MAXLOGTEXT];
-                       sprintf(logtext, "Initialize class ");
-                       utf_sprint(logtext + strlen(logtext), m->class->name);
-                       log_text(logtext);
-               }
-               class_init(m->class);
+#if 0
+       /* 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;
        }
+#endif
 
        /* 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;
 
 #if defined(__I386__)
-       method_uses_ecx = true;
-       method_uses_edx = false;
+       /* 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
 
        /* call the compiler passes ***********************************************/
 
-       /* must be called before reg_init, because it can change maxlocals */
+       /* first of all initialize the register allocator */
+       reg_init(m);
+
+       /* must be called before reg_setup, because it can change maxlocals */
        if (useinlining)
                inlining_init(m);
 
-       reg_setup();
+       reg_setup(m);
 
        codegen_init();
 
-       parse();
-       analyse_stack();
-   
+       if (compileverbose)
+               log_message_method("Parsing: ", m);
+
+       if (!parse(m)) {
+               if (compileverbose)
+                       log_message_method("Exception while parsing: ", m);
+
+               return NULL;
+       }
+
+       if (compileverbose) {
+               log_message_method("Parsing done: ", m);
+               log_message_method("Analysing: ", m);
+       }
+
+       if (!analyse_stack(m)) {
+               if (compileverbose)
+                       log_message_method("Exception while analysing: ", m);
+
+               return NULL;
+       }
+
+       if (compileverbose)
+               log_message_method("Analysing done: ", m);
+
 #ifdef CACAO_TYPECHECK
        if (opt_verify) {
-               LOG_STEP("Typechecking");
-               typecheck();
-               LOG_STEP("Done typechecking");
+               if (compileverbose)
+                       log_message_method("Typechecking: ", m);
+
+               if (!typecheck(m)) {
+                       if (compileverbose)
+                               log_message_method("Exception while typechecking: ", m);
+
+                       return NULL;
+               }
+
+               if (compileverbose)
+                       log_message_method("Typechecking done: ", m);
        }
 #endif
        
        if (opt_loops) {
-               depthFirst();
-               analyseGraph();
-               optimize_loops();
+               depthFirst(m);
+               analyseGraph(m);
+               optimize_loops(m);
        }
    
 #ifdef SPECIALMEMUSE
        preregpass();
 #endif
 
-       LOG_STEP("Regalloc");
-       regalloc();
-       regs_ok = true;
+       if (compileverbose)
+               log_message_method("Allocating registers: ", m);
 
-       LOG_STEP("Codegen");
-       codegen();
-
-       /* intermediate and assembly code listings ********************************/
-               
-       if (showintermediate)
-               show_icmd_method();
-       else if (showdisassemble)
-               disassemble((void*) (m->mcode + dseglen), m->mcodelength - dseglen);
+       regalloc(m);
 
-       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);
 
-       dump_release(dumpsize);
+       if (compileverbose) {
+               log_message_method("Generating code done: ", m);
+               log_message_method("Compiling done: ", m);
+       }
 
-       /* measure time */
+       /* intermediate and assembly code listings */
+               
+       if (showintermediate) {
+               show_icmd_method(m);
 
-       if (getcompilingtime) {
-               stoptime = getcputime();
-               compilingtime += (stoptime - starttime);
+       } else if (showdisassemble) {
+               disassemble((void *) (m->mcode + dseglen), m->mcodelength - dseglen);
        }
 
-       intsRestore();    /* enable interrupts again */
+       if (showddatasegment)
+               dseg_display((void *) (m->mcode));
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
-#endif
+       /* close register allocator */
+       reg_close(m);
 
        /* return pointer to the methods entry point */
-       
-       LOG_STEP("Done compiling");
+
        return m->entrypoint;
 } 
 
@@ -1613,19 +1623,6 @@ methodptr jit_compile(methodinfo *m)
 
 #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;
@@ -1637,29 +1634,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<len; i++)
-                       if (!builtintable[i].supported)
-                               printf("%s\n", icmd_names[builtintable[i].opcode]);
-       }
-#endif
-}
-#endif
-
 static inline void sort_builtintable()
 {
        int len;
@@ -1673,12 +1647,6 @@ static inline void sort_builtintable()
 }
 
 
-#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;
@@ -1705,7 +1673,7 @@ builtin_descriptor *find_builtin(int icmd)
 
 void jit_init()
 {
-       int i;
+       s4 i;
 
 #ifdef USEBUILTINTABLE
        sort_builtintable();
@@ -1796,8 +1764,11 @@ void jit_init()
        stackreq[JAVA_DUP2_X1] = 3;
        stackreq[JAVA_DUP2_X2] = 4;
 
-       reg_init();
        init_exceptions();
+
+       /* initialize exceptions used in the system */
+
+       init_system_exceptions();
 }
 
 
@@ -1805,7 +1776,7 @@ void jit_init()
 void jit_close()
 {
        codegen_close();
-       reg_close();
+/*     reg_close(); */
 }