From adfe8e5aaeadd20f5caffab078e8e3f8f07423b1 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Sat, 29 Sep 2007 20:09:34 +0200 Subject: [PATCH] * src/vm/jit/asmpart.h [!JIT_COMPILER_VIA_SIGNAL] (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. --- src/vm/jit/asmpart.h | 2 ++ src/vm/jit/codegen-common.c | 34 +++++++++++++++++++ src/vm/jit/codegen-common.h | 2 ++ src/vm/jit/emit-common.h | 1 + src/vm/jit/jit.c | 51 +++++++++++++++++++++++++++++ src/vm/jit/jit.h | 4 +++ src/vm/jit/x86_64/arch.h | 2 ++ src/vm/jit/x86_64/asmpart.S | 58 --------------------------------- src/vm/jit/x86_64/codegen.c | 26 --------------- src/vm/jit/x86_64/codegen.h | 2 +- src/vm/jit/x86_64/emit.c | 12 +++++++ src/vm/jit/x86_64/linux/md-os.c | 39 +++++++++++++++++++--- src/vm/signal.c | 9 ++++- 13 files changed, 152 insertions(+), 90 deletions(-) diff --git a/src/vm/jit/asmpart.h b/src/vm/jit/asmpart.h index e1ad04807..cb549c55f 100644 --- a/src/vm/jit/asmpart.h +++ b/src/vm/jit/asmpart.h @@ -49,12 +49,14 @@ /* 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); diff --git a/src/vm/jit/codegen-common.c b/src/vm/jit/codegen-common.c index 4bcf87bff..e02a579ef 100644 --- a/src/vm/jit/codegen-common.c +++ b/src/vm/jit/codegen-common.c @@ -1160,6 +1160,7 @@ u1 *codegen_generate_stub_compiler(methodinfo *m) cd = jd->cd; +#if !defined(JIT_COMPILER_VIA_SIGNAL) /* allocate code memory */ c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE); @@ -1192,6 +1193,39 @@ u1 *codegen_generate_stub_compiler(methodinfo *m) /* 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 */ diff --git a/src/vm/jit/codegen-common.h b/src/vm/jit/codegen-common.h index c545e151e..24365494b 100644 --- a/src/vm/jit/codegen-common.h +++ b/src/vm/jit/codegen-common.h @@ -313,7 +313,9 @@ u1 *codegen_generate_stub_compiler(methodinfo *m); 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) diff --git a/src/vm/jit/emit-common.h b/src/vm/jit/emit-common.h index baad4d1c3..11ba8f330 100644 --- a/src/vm/jit/emit-common.h +++ b/src/vm/jit/emit-common.h @@ -177,6 +177,7 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r 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); diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index 0838ce2b4..d45f71fc5 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -1669,6 +1669,7 @@ codeinfo *jit_get_current_code(methodinfo *m) *******************************************************************************/ #if defined(ENABLE_JIT) +#if !defined(JIT_COMPILER_VIA_SIGNAL) u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra) { stackframeinfo sfi; @@ -1710,6 +1711,56 @@ u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra) 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) */ diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index c1ea4bf3b..e0a49df7a 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -50,6 +50,7 @@ typedef struct exception_entry exception_entry; #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" @@ -1309,7 +1310,10 @@ codeinfo *jit_get_current_code(methodinfo *m); 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); diff --git a/src/vm/jit/x86_64/arch.h b/src/vm/jit/x86_64/arch.h index c7c4c0fc9..331e3afc7 100644 --- a/src/vm/jit/x86_64/arch.h +++ b/src/vm/jit/x86_64/arch.h @@ -28,6 +28,8 @@ #ifndef _ARCH_H #define _ARCH_H +#define JIT_COMPILER_VIA_SIGNAL + #include "config.h" diff --git a/src/vm/jit/x86_64/asmpart.S b/src/vm/jit/x86_64/asmpart.S index 6ddd7dde6..af15de533 100644 --- a/src/vm/jit/x86_64/asmpart.S +++ b/src/vm/jit/x86_64/asmpart.S @@ -48,8 +48,6 @@ .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 @@ -182,62 +180,6 @@ asm_vm_call_method_end: 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 * diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index dff6060f7..6824bf532 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -2877,32 +2877,6 @@ gen_method: } -/* 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. diff --git a/src/vm/jit/x86_64/codegen.h b/src/vm/jit/x86_64/codegen.h index 6b0fb88fc..add6b306a 100644 --- a/src/vm/jit/x86_64/codegen.h +++ b/src/vm/jit/x86_64/codegen.h @@ -133,7 +133,7 @@ /* stub defines ***************************************************************/ -#define COMPILERSTUB_CODESIZE 7 + 7 + 3 +#define COMPILERSTUB_CODESIZE 8 /* macros to create code ******************************************************/ diff --git a/src/vm/jit/x86_64/emit.c b/src/vm/jit/x86_64/emit.c index 4693e218c..fe08a7f41 100644 --- a/src/vm/jit/x86_64/emit.c +++ b/src/vm/jit/x86_64/emit.c @@ -435,6 +435,18 @@ void emit_exception_check(codegendata *cd, instruction *iptr) } +/* 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. diff --git a/src/vm/jit/x86_64/linux/md-os.c b/src/vm/jit/x86_64/linux/md-os.c index 146dba3bf..da050b8da 100644 --- a/src/vm/jit/x86_64/linux/md-os.c +++ b/src/vm/jit/x86_64/linux/md-os.c @@ -70,6 +70,7 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) int type; intptr_t val; void *p; + java_handle_t *o; _uc = (ucontext_t *) _p; _mc = &_uc->uc_mcontext; @@ -149,6 +150,17 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) } 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 */ @@ -161,11 +173,30 @@ void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) 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; + } } diff --git a/src/vm/signal.c b/src/vm/signal.c index f20196d82..979b0f521 100644 --- a/src/vm/signal.c +++ b/src/vm/signal.c @@ -288,6 +288,10 @@ void *signal_handle(int type, intptr_t val, 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. */ @@ -322,7 +326,10 @@ void *signal_handle(int type, intptr_t val, /* 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); } -- 2.25.1