(asm_call_jit_compiler): Added #ifdef.
* src/vm/jit/codegen-common.c (codegen_generate_stub_compiler)
[JIT_COMPILER_VIA_SIGNAL]: Added new code.
* src/vm/jit/codegen-common.h [!JIT_COMPILER_VIA_SIGNAL]
(codegen_emit_stub_compiler): Added #ifdef.
* src/vm/jit/emit-common.h (emit_trap_compiler): Added.
* src/vm/jit/jit.c [!JIT_COMPILER_VIA_SIGNAL] (jit_asm_compile): Added
#ifdef.
(jit_compile_handle): New function.
* src/vm/jit/jit.h (vm/jit/stacktrace.h): Added.
[!JIT_COMPILER_VIA_SIGNAL] (jit_asm_compile): Added #ifdef.
* src/vm/jit/x86_64/arch.h (JIT_COMPILER_VIA_SIGNAL): Added
temporarily.
* src/vm/jit/x86_64/asmpart.S (asm_call_jit_compiler): Removed.
* src/vm/jit/x86_64/codegen.c (codegen_emit_stub_compiler): Removed.
* src/vm/jit/x86_64/codegen.h (COMPILERSTUB_CODESIZE): Adapted.
* src/vm/jit/x86_64/emit.c (emit_trap_compiler): New function.
* src/vm/jit/x86_64/linux/md-os.c (md_signal_handler_sigsegv): Added
JIT compiler handling code.
* src/vm/signal.c (signal_handle): Likewise.
/* machine dependent initialization */
s4 asm_md_init(void);
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
/*
invokes the compiler for untranslated JavaVM methods.
Register R0 contains a pointer to the method info structure
(prepared by createcompilerstub).
*/
void asm_call_jit_compiler(void);
+#endif
#if defined(ENABLE_JIT)
java_object_t *asm_vm_call_method(void *pv, uint64_t *array, int32_t stackargs);
cd = jd->cd;
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
/* allocate code memory */
c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
/* flush caches */
md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
+#else
+ /* Allocate code memory. */
+
+ c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
+
+ /* Set pointers correctly. */
+
+ d = (ptrint *) c;
+
+ cd->mcodebase = c;
+
+ c = c + 2 * SIZEOF_VOID_P;
+ cd->mcodeptr = c;
+
+ /* NOTE: The codeinfo pointer is actually a pointer to the
+ methodinfo (this fakes a codeinfo structure). */
+
+ d[0] = (ptrint) m;
+ d[1] = (ptrint) &d[0]; /* fake code->m */
+
+ /* Emit the trap instruction. */
+
+ emit_trap_compiler(cd);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
+#endif
+
+ /* Flush caches. */
+
+ md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
+#endif
/* release dump memory */
void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte);
codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
void codegen_emit_stub_compiler(jitdata *jd);
+#endif
void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams);
#if defined(ENABLE_INTRP)
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
void emit_exception_check(codegendata *cd, instruction *iptr);
+void emit_trap_compiler(codegendata *cd);
uint32_t emit_trap(codegendata *cd);
void emit_patcher_stubs(jitdata *jd);
*******************************************************************************/
#if defined(ENABLE_JIT)
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra)
{
stackframeinfo sfi;
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(void *pc, void *pv, void *ra, void *mptr)
+{
+ methodinfo *m;
+ void *newpv; /* new compiled method PV */
+ void *pa; /* patch address */
+ uintptr_t *p; /* convenience pointer */
+
+ /* Get methodinfo pointer. */
+
+ m = *((methodinfo **) (((intptr_t) pc) - 2 * SIZEOF_VOID_P));
+
+ /* 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 the instruction cache. */
+
+ md_icacheflush(p, SIZEOF_VOID_P);
+
+ return newpv;
+}
#endif /* defined(ENABLE_JIT) */
#include "vm/jit/codegen-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
#if defined(ENABLE_INLINING)
# include "vm/jit/inline/inline.h"
void jit_request_optimization(methodinfo *m);
/* patch the method entrypoint */
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra);
+#endif
+void *jit_compile_handle(void *pc, void *pv, void *ra, void *mptr);
s4 jit_complement_condition(s4 opcode);
#ifndef _ARCH_H
#define _ARCH_H
+#define JIT_COMPILER_VIA_SIGNAL
+
#include "config.h"
.globl asm_vm_call_method_exception_handler
.globl asm_vm_call_method_end
- .globl asm_call_jit_compiler
-
.globl asm_handle_exception
.globl asm_handle_nat_exception
nop
-/****************** function asm_call_jit_compiler *****************************
-* *
-* invokes the compiler for untranslated JavaVM methods. *
-* *
-* Register R0 contains a pointer to the method info structure (prepared *
-* by createcompilerstub). Using the return address in R26 and the *
-* offset in the LDA instruction or using the value in methodptr R28 the *
-* patching address for storing the method address can be computed: *
-* *
-* method address was either loaded using *
-* *
-* i386_mov_imm_reg(a, REG_ITMP2) ; invokestatic/special *
-* i386_call_reg(REG_ITMP2) *
-* *
-* or *
-* *
-* i386_mov_membase_reg(REG_SP, 0, REG_ITMP2) ; invokevirtual/interface *
-* i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3) *
-* i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \ *
-* sizeof(methodptr) * m->vftblindex, REG_ITMP1) *
-* i386_call_reg(REG_ITMP1) *
-* *
-* in the static case the method pointer can be computed using the *
-* return address and the lda function following the jmp instruction *
-* *
-*******************************************************************************/
-
-asm_call_jit_compiler:
-L_asm_call_jit_compiler: /* required for PIC code */
- sub $(ARG_CNT+1)*8,sp /* +1: keep stack 16-byte aligned */
-
- SAVE_ARGUMENT_REGISTERS(0)
-
- mov itmp1,a0 /* pass methodinfo pointer */
- mov mptr,a1 /* pass method pointer */
- mov sp,a2 /* pass java sp */
- add $(1+ARG_CNT+1)*8,a2
- mov (ARG_CNT+1)*8(sp),a3 /* pass ra to java function */
- call jit_asm_compile@PLT
-
- RESTORE_ARGUMENT_REGISTERS(0)
-
- add $(ARG_CNT+1)*8,sp /* remove stack frame */
-
- test v0,v0 /* check for exception */
- je L_asm_call_jit_compiler_exception
-
- jmp *v0 /* ...and now call the new method */
-
-L_asm_call_jit_compiler_exception:
- call exceptions_get_and_clear_exception@PLT
- pop xpc /* delete return address */
- sub $3,xpc /* faulting address is ra - 3 */
- jmp L_asm_handle_exception
-
-
/* asm_handle_exception ********************************************************
* *
* This function handles an exception. It does not use the usual calling *
}
-/* codegen_emit_stub_compiler **************************************************
-
- Emit a stub routine which calls the compiler.
-
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* code for the stub */
-
- M_LLD(REG_ITMP1, RIP, -(7 * 1 + 2 * SIZEOF_VOID_P)); /* methodinfo */
-/* M_ALD(REG_ITMP1, RIP, -(2 * SIZEOF_VOID_P)); /\* methodinfo *\/ */
- M_LLD(REG_ITMP3, RIP, -(7 * 2 + 3 * SIZEOF_VOID_P)); /* compiler pointer */
-/* M_ALD(REG_ITMP3, RIP, -(3 * SIZEOF_VOID_P)); /\* compiler pointer *\/ */
- M_JMP(REG_ITMP3);
-}
-
-
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
/* stub defines ***************************************************************/
-#define COMPILERSTUB_CODESIZE 7 + 7 + 3
+#define COMPILERSTUB_CODESIZE 8
/* macros to create code ******************************************************/
}
+/* emit_trap *******************************************************************
+
+ Emit a JIT compiler trap instruction.
+
+*******************************************************************************/
+
+void emit_trap_compiler(codegendata *cd)
+{
+ M_ALD_MEM(REG_METHODPTR, EXCEPTION_HARDWARE_COMPILER);
+}
+
+
/* emit_trap *******************************************************************
Emit a trap instruction and return the original machine code.
int type;
intptr_t val;
void *p;
+ java_handle_t *o;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
}
val = _mc->gregs[d];
+
+ if (type == EXCEPTION_HARDWARE_COMPILER) {
+ /* We use a framesize of zero here because the call pushed
+ the return addres onto the stack. */
+
+ ra = md_stacktrace_get_returnaddress(sp, 0);
+
+ /* And remove the RA from the stack. */
+
+ sp = sp + 1 * SIZEOF_VOID_P;
+ }
}
else {
/* this was a normal NPE */
p = signal_handle(type, val, NULL, sp, ra, xpc, _p);
- /* set registers */
+ /* Set registers. */
- _mc->gregs[REG_RAX] = (intptr_t) p;
- _mc->gregs[REG_R10] = (intptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_RIP] = (intptr_t) asm_handle_exception;
+ if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (p == NULL) {
+ o = exceptions_get_and_clear_exception();
+
+ log_println("compiler exception");
+ ra = ra - 3; /* XPC is before the actual call */
+
+ _mc->gregs[REG_RSP] = (uintptr_t) sp; /* Remove RA from stack. */
+
+ _mc->gregs[REG_RAX] = (uintptr_t) o;
+ _mc->gregs[REG_R10] = (uintptr_t) ra; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
+ }
+ else {
+ _mc->gregs[REG_RIP] = (uintptr_t) p;
+ }
+ }
+ else {
+ _mc->gregs[REG_RAX] = (uintptr_t) p;
+ _mc->gregs[REG_R10] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
+ }
}
p = patcher_handler(xpc);
break;
+ case EXCEPTION_HARDWARE_COMPILER:
+ p = jit_compile_handle(xpc, pv, ra, (void *) val);
+ break;
+
default:
/* Let's try to get a backtrace. */
/* unwrap and return the exception object */
/* AFTER: removing stackframeinfo */
- return LLNI_UNWRAP(p);
+ if (type == EXCEPTION_HARDWARE_COMPILER)
+ return p;
+ else
+ return LLNI_UNWRAP(p);
}