-/* 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
"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 */
"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 */
{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"},
/* 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;
}
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 */
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 */
}
-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)
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);
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);
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);
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);
}
/* now generate the machine code */
- codegen(m);
+ codegen(m, cd, rd);
if (compileverbose)
log_message_method("Generating code done: ", m);
/* 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);