#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include "vm/types.h"
+#include "md.h"
+
#include "mm/memory.h"
#include "native/native.h"
#include "vm/jit/disass.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
-#include "vm/jit/md.h"
#include "vm/jit/parse.h"
#include "vm/jit/reg.h"
/* debug macros ***************************************************************/
#if !defined(NDEBUG)
-#define DEBUG_JIT_COMPILEVERBOSE(x) \
- do { \
- if (compileverbose) { \
- log_message_method(x, m); \
- } \
+#define DEBUG_JIT_COMPILEVERBOSE(x) \
+ do { \
+ if (compileverbose) { \
+ log_message_method(x, m); \
+ } \
} while (0)
#else
#define DEBUG_JIT_COMPILEVERBOSE(x) /* nothing */
#endif
-
+#if !defined(NDEBUG)
+# define TRACECOMPILERCALLS() \
+ do { \
+ if (opt_TraceCompilerCalls) { \
+ log_start(); \
+ log_print("[JIT compiler started: method="); \
+ method_print(m); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
+#else
+# define TRACECOMPILERCALLS()
+#endif
+
+
/* the ICMD table ************************************************************/
#if !defined(NDEBUG)
/* initialize code subsystem */
(void) code_init();
+
+ /* Machine dependent initialization. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ intrp_md_init();
+ else
+# endif
+ md_init();
+#else
+ intrp_md_init();
+#endif
}
jitdata *jit_jitdata_new(methodinfo *m)
{
- jitdata *jd;
+ jitdata *jd;
+ codeinfo *code;
/* allocate jitdata structure and fill it */
/* Allocate codeinfo memory from the heap as we need to keep them. */
- jd->code = code_codeinfo_new(m);
+ code = code_codeinfo_new(m);
+
+ /* Set codeinfo flags. */
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ code_flag_synchronized(code);
+
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ code_unflag_leafmethod(code);
+ else
+#endif
+ code_flag_leafmethod(code);
/* initialize variables */
+ jd->code = code;
jd->flags = 0;
jd->exceptiontable = NULL;
jd->exceptiontablelength = 0;
jd->returnblock = NULL;
jd->maxlocals = m->maxlocals;
-#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- jd->isleafmethod = false;
- else
-#endif
- jd->isleafmethod = true;
-
return jd;
}
return m->code->entrypoint;
}
+ TRACECOMPILERCALLS();
+
STATISTICS(count_methods++);
#if defined(ENABLE_STATISTICS)
code = jd->code;
cd = jd->cd;
- /* print log message for compiled method */
-
- DEBUG_JIT_COMPILEVERBOSE("Compiling: ");
-
#if defined(ENABLE_DEBUG_FILTER)
show_filters_apply(jd->m);
#endif
if (m->flags & ACC_NATIVE) {
functionptr f;
- f = NULL;
+ f = native_method_resolve(m);
+
+ if (f == NULL)
+ return NULL;
code = codegen_generate_stub_native(m, f);
- assert(!m->code); /* native methods are never recompiled */
+ /* Native methods are never recompiled. */
+
+ assert(!m->code);
+
m->code = code;
return code->entrypoint;
RT_TIMING_GET_TIME(time_checks);
+#if defined(WITH_CLASSPATH_SUN)
+ /* Code for Sun's OpenJDK (see
+ hotspot/src/share/vm/classfile/verifier.cpp
+ (Verifier::is_eligible_for_verification)): Don't verify
+ dynamically-generated bytecodes. */
+
+# if defined(ENABLE_VERIFIER)
+ if (class_issubclass(m->class, class_sun_reflect_MagicAccessorImpl))
+ jd->flags &= ~JITDATA_FLAG_VERIFY;
+# endif
+#endif
+
/* call the compiler passes ***********************************************/
DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
+#if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
+ /* activate replacement points inside newly created code */
+
+ if (opt_TestReplacement)
+ replace_activate_replacement_points(code, false);
+#endif
+
#if !defined(NDEBUG)
#if defined(ENABLE_DEBUG_FILTER)
if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
}
#endif
- DEBUG_JIT_COMPILEVERBOSE("Compiling done: ");
-
/* switch to the newly generated code */
assert(code);
codeinfo *code;
code = m->code;
- if (code == NULL || CODE_IS_INVALID(code))
+
+ if (code == NULL || code_is_invalid(code))
return;
- CODE_SETFLAG_INVALID(code);
+ code_flag_invalid(code);
/* activate mappable replacement points */
/* if we have valid code, return it */
- if (m->code && CODE_IS_VALID(m->code))
+ if (m->code && !code_is_invalid(m->code))
return m->code;
/* otherwise: recompile */
*******************************************************************************/
#if defined(ENABLE_JIT)
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra)
{
- stackframeinfo sfi;
- u1 *entrypoint;
- u1 *pa;
- ptrint *p;
+ stackframeinfo_t sfi;
+ u1 *entrypoint;
+ u1 *pa;
+ ptrint *p;
/* create the stackframeinfo (subtract 1 from RA as it points to the */
/* instruction after the call) */
- stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra-1);
+ stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra-1);
/* actually compile the method */
/* remove the stackframeinfo */
- stacktrace_remove_stackframeinfo(&sfi);
+ stacktrace_stackframeinfo_remove(&sfi);
/* there was a problem during compilation */
/* get the method patch address */
- pa = md_get_method_patch_address(ra, &sfi, mptr);
+ pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
/* patch the method entry point */
return entrypoint;
}
+#endif
+
+/* jit_compile_handle **********************************************************
+
+ This method is called from the appropriate signal handler which
+ handles compiler-traps and does the following:
+
+ - compile the method
+ - patch the entrypoint of the method into the calculated address in
+ the JIT code
+ - flush the instruction cache
+
+*******************************************************************************/
+
+void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
+{
+ void *newpv; /* new compiled method PV */
+ void *pa; /* patch address */
+ uintptr_t *p; /* convenience pointer */
+
+ /* Compile the method. */
+
+ newpv = jit_compile(m);
+
+ /* There was a problem during compilation. */
+
+ if (newpv == NULL)
+ return NULL;
+
+ /* Get the method patch address. */
+
+ pa = md_jit_method_patch_address(pv, ra, mptr);
+
+ /* Patch the method entry point. */
+
+ p = (uintptr_t *) pa;
+
+ *p = (uintptr_t) newpv;
+
+ /* Flush both caches. */
+
+ md_cacheflush(pa, SIZEOF_VOID_P);
+
+ return newpv;
+}
#endif /* defined(ENABLE_JIT) */