Use monitorenter/exit only with threads.
[cacao.git] / src / vm / jit / jit.c
index b5e423bcfb4fd0f8cbc4b5305b9e2786275658c0..38679ad03580f74dd3c59e36c0026660ec5e8c87 100644 (file)
@@ -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.
 
 
    Changes: Edwin Steiner
 
-   $Id: jit.c 1420 2004-10-27 16:05:14Z twisti $
+   $Id: jit.c 1807 2004-12-22 10:47:13Z twisti $
 
 */
 
 
-#include <stdlib.h>
-#include <string.h>
-#include "global.h"
-#include "tables.h"
-#include "loader.h"
-#include "builtin.h"
-#include "native.h"
-#include "asmpart.h"
 #include "codegen.h"
-#include "types.h"
-#include "options.h"
-#include "statistics.h"
-#include "jit/codegen.inc.h"
-#include "jit/inline.h"
-#include "jit/jit.h"
-#include "jit/parseRT.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/logging.h"
-#include "toolbox/memory.h"
 #include "types.h"
-#include <stdio.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
+
+
 
 /* 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 JAVA_NOP               0
@@ -923,7 +922,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 */
@@ -1152,8 +1153,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 */
@@ -1311,8 +1313,10 @@ builtin_descriptor builtin_desc[] = {
        {255,BUILTIN_newarray_short  ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_short"},
        {255,BUILTIN_newarray_int    ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_int"},
        {255,BUILTIN_newarray_long   ,ICMD_BUILTIN1,TYPE_INT   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_ADR   ,0,0,"newarray_long"},
+#if defined(USE_THREADS)
        {255,BUILTIN_monitorenter    ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorenter"},
        {255,BUILTIN_monitorexit     ,ICMD_BUILTIN1,TYPE_ADR   ,TYPE_VOID  ,TYPE_VOID  ,TYPE_VOID  ,0,0,"monitorexit"},
+#endif
 #if !SUPPORT_DIVISION
        {255,BUILTIN_idiv            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"idiv"},
        {255,BUILTIN_irem            ,ICMD_BUILTIN2,TYPE_INT   ,TYPE_INT   ,TYPE_VOID  ,TYPE_INT   ,0,0,"irem"},
@@ -1340,29 +1344,45 @@ 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
 
 *******************************************************************************/
 
-static methodptr jit_compile_intern(methodinfo *m);
+static functionptr jit_compile_intern(methodinfo *m, codegendata *cd,
+                                                                         registerdata *rd, loopdata *ld,
+                                                                         t_inlining_globals *id);
 
-methodptr jit_compile(methodinfo *m)
+functionptr jit_compile(methodinfo *m)
 {
        static bool jitrunning;
-       methodptr r;
+       functionptr r;
        s4 dumpsize;
+       codegendata *cd;
+       registerdata *rd;
+       loopdata *ld;
+       t_inlining_globals *id;
+
+
+       if (m->flags & ACC_NATIVE) {
+               /*this is the case if a native function is called by using jni*/
+               return m->stubroutine;
+       }
 
        if (opt_stat)
                count_jit_calls++;
 
+#if defined(USE_THREADS)
        /* enter a monitor on the method */
 
        builtin_monitorenter((java_objectheader *) m);
+#endif
 
        /* if method has been already compiled return immediately */
 
        if (m->entrypoint) {
-               builtin_monitorexit((java_objectheader *) m );
+#if defined(USE_THREADS)
+               builtin_monitorexit((java_objectheader *) m);
+#endif
 
                return m->entrypoint;
        }
@@ -1370,32 +1390,69 @@ methodptr jit_compile(methodinfo *m)
        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 */
 
        jitrunning = true;
+#endif
+
+       /* measure time */
+
+       if (getcompilingtime)
+               compilingtime_start();
 
        /* mark start of dump memory area */
 
        dumpsize = dump_size();
 
-       /* measure time */
+       /* allocate memory */
 
-       if (getcompilingtime)
-               compilingtime_start();
+       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);
+       r = jit_compile_intern(m, cd, rd, ld, id);
 
-       if (r) {
-               if (compileverbose)
-                       log_message_method("Running: ", m);
-       }
+       /* free some memory */
+
+       reg_free(m, rd);
+       codegen_free(m, cd);
 
        /* clear pointers to dump memory area */
 
@@ -1416,9 +1473,22 @@ methodptr jit_compile(methodinfo *m)
 
        jitrunning = false;
 
+        /* 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
+
+#if defined(USE_THREADS)
        /* leave the monitor */
 
        builtin_monitorexit((java_objectheader *) m );
+#endif
+
+       if (r) {
+               if (compileverbose)
+                       log_message_method("Running: ", m);
+       }
 
        /* return pointer to the methods entry point */
 
@@ -1426,18 +1496,16 @@ methodptr jit_compile(methodinfo *m)
 }
 
 
-static methodptr jit_compile_intern(methodinfo *m)
-{
-t_inlining_globals *inline_env = NULL;
-       /* if there is no javacode, print error message and return empty method   */
+/* jit_compile_intern **********************************************************
 
-       if (!m->jcode) {
-               if (compileverbose)
-                       log_message_method("No code given for: ", m);
+   Static internal function which does the actual compilation.
 
-               return (methodptr) do_nothing_function;    /* return empty method     */
-       }
+*******************************************************************************/
 
+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)
@@ -1469,49 +1537,13 @@ t_inlining_globals *inline_env = NULL;
 
        descriptor2types(m);
 
-#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
-
        /* call the compiler passes ***********************************************/
 
-       EXTABLEN
-       /* first of all initialize the register allocator */
-       reg_init(m);
-
-       /* 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 */
-       inline_env = inlining_init(m);
-
-       EXTABLEN
-
-       reg_setup(m);
-
-       /* setup the codegendata memory */
-       codegen_setup(m,inline_env);
-
-       EXTABLEN
-
        if (compileverbose)
                log_message_method("Parsing: ", m);
 
-       if (!parse(m, inline_env)) {
+       /* call parse pass */
+       if (!parse(m, cd, id)) {
                if (compileverbose)
                        log_message_method("Exception while parsing: ", m);
 
@@ -1523,8 +1555,8 @@ t_inlining_globals *inline_env = NULL;
                log_message_method("Analysing: ", m);
        }
 
-
-       if (!analyse_stack(m->codegendata)) {
+       /* call stack analysis pass */
+       if (!analyse_stack(m, cd, rd)) {
                if (compileverbose)
                        log_message_method("Exception while analysing: ", m);
 
@@ -1539,7 +1571,8 @@ t_inlining_globals *inline_env = NULL;
                if (compileverbose)
                        log_message_method("Typechecking: ", m);
 
-               if (!typecheck(m->codegendata)) {
+               /* call typecheck pass */
+               if (!typecheck(m, cd, rd)) {
                        if (compileverbose)
                                log_message_method("Exception while typechecking: ", m);
 
@@ -1550,20 +1583,27 @@ t_inlining_globals *inline_env = NULL;
                        log_message_method("Typechecking done: ", m);
        }
 #endif
+
        if (opt_loops) {
-               depthFirst(m);
-               analyseGraph(m);
-               optimize_loops(m);
+               depthFirst(m, ld);
+               analyseGraph(m, ld);
+               optimize_loops(m, cd, ld);
        }
    
 #ifdef SPECIALMEMUSE
-       preregpass(m);
+       preregpass(m, rd);
 #endif
 
        if (compileverbose)
                log_message_method("Allocating registers: ", m);
 
-       regalloc(m);
+       /* allocate registers */
+#ifdef LSRA
+       if (opt_lsra)
+               lsra(m, cd, rd, ld, id);
+       else
+#endif
+               regalloc(m, cd, rd);
 
        if (compileverbose) {
                log_message_method("Allocating registers done: ", m);
@@ -1571,7 +1611,7 @@ t_inlining_globals *inline_env = NULL;
        }
 
        /* now generate the machine code */
-       codegen(m);
+       codegen(m, cd, rd);
 
        if (compileverbose)
                log_message_method("Generating code done: ", m);
@@ -1579,20 +1619,15 @@ t_inlining_globals *inline_env = NULL;
        /* intermediate and assembly code listings */
                
        if (showintermediate) {
-               show_icmd_method(m);
+               show_icmd_method(m, cd, rd);
 
        } else if (showdisassemble) {
-               disassemble((void *) (m->mcode + m->codegendata->dseglen),
-                                       m->mcodelength - m->codegendata->dseglen);
+               disassemble((void *) ((long) m->mcode + cd->dseglen), 
+                                       m->mcodelength - cd->dseglen);
        }
 
        if (showddatasegment)
-               dseg_display(m);
-
-       /* free some memory */
-
-       reg_close(m);
-       codegen_close(m);
+               dseg_display(m, cd);
 
        if (compileverbose)
                log_message_method("Compiling done: ", m);