Changes: Edwin Steiner
- $Id: jit.c 789 2003-12-16 14:46:55Z edwin $
+ $Id: jit.c 1067 2004-05-18 10:25:51Z stefan $
*/
#include <stdlib.h>
#include <string.h>
#include "global.h" /* we define _GNU_SOURCE there */
+#include "main.h"
#include "tables.h"
#include "loader.h"
#include "jit.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 ************************************************************/
-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;
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 */
+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 maxlocals; /* maximal number of local JavaVM variables */
int jcodelength; /* length of JavaVM-codes */
u1 *jcode; /* pointer to start of JavaVM-code */
+lineinfo *jlinenumbers; /* line information array */
+u2 jlinenumbercount; /* number of entries in the linenumber array */
int exceptiontablelength; /* length of exception table */
xtable *extable; /* pointer to start of exception table */
exceptiontable *raw_extable;
5,
#define JAVA_BREAKPOINT 202
1,
+#define ICMD_CHECKOOM 203
+ 1, /* unused */
- 1,1,1,1,1,1,1,1, /* unused */
+ 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,
"UNDEF200 ", /* GOTO_W 200 */
"UNDEF201 ", /* JSR_W 201 */
"UNDEF202 ", /* BREAKPOINT 202 */
+ "CHECKOOM ", /* UNDEF204 203 */
- "UNDEF203","UNDEF204","UNDEF205",
+ "UNDEF204","UNDEF205",
"UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
"GOTO_W ", /* GOTO_W 200 */
"JSR_W ", /* JSR_W 201 */
"BREAKPOINT ", /* BREAKPOINT 202 */
+ "CHECKOOM ", /* UNDEF203 203 */
- "UNDEF203","UNDEF204","UNDEF205",
+ "UNDEF204","UNDEF205",
"UNDEF206","UNDEF207","UNDEF208","UNDEF209","UNDEF210",
"UNDEF","UNDEF","UNDEF","UNDEF","UNDEF",
"UNDEF216","UNDEF217","UNDEF218","UNDEF219","UNDEF220",
#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_d2i ,ICMD_BUILTIN1,TYPE_DOUBLE,TYPE_VOID ,TYPE_VOID ,TYPE_INT ,0,0,"d2i"},
#endif
- /* the following functions are not replaced automatically */
{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"},
*******************************************************************************/
+#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
+
methodptr jit_compile(methodinfo *m)
{
- int dumpsize;
- long starttime = 0;
- long stoptime = 0;
+ static bool jitrunning;
+ s4 dumpsize;
+ s8 starttime = 0;
+ s8 stoptime = 0;
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ compiler_lock();
+#endif
+
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+ intsDisable(); /* disable interrupts */
+#endif
count_jit_calls++;
/* if method has been already compiled return immediately */
- if (m->entrypoint)
- return m->entrypoint;
-
- count_methods++;
+ if (m->entrypoint) {
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+ intsRestore(); /* enable interrupts again */
+#endif
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- pthread_mutex_lock(&compiler_mutex);
+ compiler_unlock();
#endif
- intsDisable(); /* disable interrupts */
+ return m->entrypoint;
+ }
- regs_ok = false;
+ count_methods++;
/* mark start of dump memory area */
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);
+ utf_sprint_classname(logtext + strlen(logtext), m->class->name);
+ strcpy(logtext + strlen(logtext), ".");
+ utf_sprint(logtext + strlen(logtext), m->name);
+ utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
log_text(logtext);
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
intsRestore(); /* enable interrupts again */
+#endif
+ jitrunning = false;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ compiler_unlock();
+#endif
return (methodptr) do_nothing_function; /* return empty 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);
+ utf_sprint_classname(logtext + strlen(logtext), m->class->name);
+ sprintf(logtext + strlen(logtext), ".");
+ utf_sprint(logtext + strlen(logtext), m->name);
+ utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
log_text(logtext);
}
+ if (!m->class->loaded)
+ class_load(m->class);
+
+ if (!m->class->linked)
+ class_link(m->class);
+
+ /* initialize the static function's class */
+ if (m->flags & ACC_STATIC && !m->class->initialized) {
+ if (initverbose) {
+ char logtext[MAXLOGTEXT];
+ sprintf(logtext, "Initialize class ");
+ utf_sprint_classname(logtext + strlen(logtext), m->class->name);
+ log_text(logtext);
+ }
+ class_init(m->class);
+ }
+
+ if (jitrunning) {
+ printf("m=");
+ utf_display_classname(m->class->name);printf(".");utf_display(m->name);
+ printf(", method=");
+ utf_display_classname(method->class->name);printf(".");utf_display(method->name);
+ printf("\n");
+ panic("Compiler lock recursion");
+ }
+ jitrunning = true;
/* initialisation of variables and subsystems */
maxlocals = m->maxlocals;
jcodelength = m->jcodelength;
jcode = m->jcode;
+ jlinenumbers = m->linenumbers;
+ jlinenumbercount = m->linenumbercount;
exceptiontablelength = m->exceptiontablelength;
raw_extable = m->exceptiontable;
+ regs_ok = false;
#ifdef STATISTICS
count_tryblocks += exceptiontablelength;
mparamcount = m->paramcount;
mparamtypes = m->paramtypes;
- /* initialize class list with class the compiled method belongs to */
-
- uninitializedclasses = chain_new();
- compiler_addinitclass(m->class);
-
-
#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 {
+ method_uses_ecx = false;
+ method_uses_edx = false;
+ }
#endif
/* call the compiler passes ***********************************************/
analyse_stack();
#ifdef CACAO_TYPECHECK
- /* print log message for compiled method */
-
- 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);
- log_text(logtext);
- }
-
- typecheck();
-
- if (compileverbose) {
- dolog("Typechecking done.");
+ if (opt_verify) {
+ LOG_STEP("Typechecking");
+ typecheck();
+ LOG_STEP("Done typechecking");
}
#endif
preregpass();
#endif
+ LOG_STEP("Regalloc");
regalloc();
regs_ok = true;
+
+ LOG_STEP("Codegen");
codegen();
/* intermediate and assembly code listings ********************************/
compilingtime += (stoptime - starttime);
}
- /* 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 (compileverbose) {
+ char logtext[MAXLOGTEXT];
+ sprintf(logtext, "Running: ");
+ utf_sprint_classname(logtext + strlen(logtext), m->class->name);
+ sprintf(logtext + strlen(logtext), ".");
+ utf_sprint(logtext + strlen(logtext), m->name);
+ utf_sprint_classname(logtext + strlen(logtext), m->descriptor);
+ log_text(logtext);
}
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
intsRestore(); /* enable interrupts again */
-
+#endif
+ jitrunning = false;
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- pthread_mutex_unlock(&compiler_mutex);
+ compiler_unlock();
#endif
/* return pointer to the methods entry point */
-
+
return m->entrypoint;
}
#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;