From 9f9da4d8a07992b384d14a41f441e95aea050a71 Mon Sep 17 00:00:00 2001 From: twisti Date: Fri, 21 Apr 2006 10:54:24 +0000 Subject: [PATCH] * src/vm/jit/jit.c (jit_asm_compile): New method. * src/vm/jit/jit.h (jit_asm_compile): Added. (md_get_method_patch_address): Likewise. * src/vm/jit/x86_64/asmpart.S (asm_vm_call_method): Store asm_call_jit_compiler on stack as for the other architectures. (asm_call_jit_compiler): Use new jit_asm_compile. * src/vm/jit/x86_64/codegen.c (codegen): Use REG_ITMP3 for calling methods. This is required for asm_vm_call_method to work. * src/vm/jit/x86_64/md.c (md_get_method_patch_address): New method. (md_icacheflush): Added. (md_dcacheflush): Added. * src/vm/jit/x86_64/md-asm.h (mptr): Defined. --- src/vm/jit/jit.c | 53 +++++++++++++++++++- src/vm/jit/jit.h | 8 ++- src/vm/jit/x86_64/asmpart.S | 78 +++++++---------------------- src/vm/jit/x86_64/codegen.c | 19 ++++--- src/vm/jit/x86_64/md-asm.h | 3 +- src/vm/jit/x86_64/md.c | 98 ++++++++++++++++++++++++++++++++++++- 6 files changed, 186 insertions(+), 73 deletions(-) diff --git a/src/vm/jit/jit.c b/src/vm/jit/jit.c index 40688c373..2ffb10269 100644 --- a/src/vm/jit/jit.c +++ b/src/vm/jit/jit.c @@ -31,7 +31,7 @@ Christian Thalinger Christian Ullrich - $Id: jit.c 4768 2006-04-13 16:58:05Z edwin $ + $Id: jit.c 4805 2006-04-21 10:54:24Z twisti $ */ @@ -1722,6 +1722,57 @@ static u1 *jit_compile_intern(jitdata *jd) } +/* jit_asm_compile ************************************************************* + + This method is called from asm_vm_call_method and does things like: + create stackframe info for exceptions, compile the method, patch + the entrypoint of the method into the calculated address in the JIT + code, and flushes the instruction cache. + +*******************************************************************************/ + +u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra) +{ + stackframeinfo sfi; + u1 *entrypoint; + u1 *pa; + ptrint *p; + + /* create the stackframeinfo (XPC is equal to RA) */ + + stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra); + + /* actually compile the method */ + + entrypoint = jit_compile(m); + + /* remove the stackframeinfo */ + + stacktrace_remove_stackframeinfo(&sfi); + + /* there was a problem during compilation */ + + if (entrypoint == NULL) + return NULL; + + /* get the method patch address */ + + pa = md_get_method_patch_address(ra, &sfi, mptr); + + /* patch the method entry point */ + + p = (ptrint *) pa; + + *p = (ptrint) entrypoint; + + /* flush the instruction cache */ + + md_icacheflush(pa, SIZEOF_VOID_P); + + return entrypoint; +} + + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where diff --git a/src/vm/jit/jit.h b/src/vm/jit/jit.h index ee6e5200b..f34d9e6f5 100644 --- a/src/vm/jit/jit.h +++ b/src/vm/jit/jit.h @@ -30,7 +30,7 @@ Changes: Christian Thalinger Edwin Steiner - $Id: jit.h 4790 2006-04-18 20:36:40Z twisti $ + $Id: jit.h 4805 2006-04-21 10:54:24Z twisti $ */ @@ -60,6 +60,7 @@ typedef struct insinfo_inline insinfo_inline; #include "vm/statistics.h" #include "vm/jit/codegen-common.h" #include "vm/jit/reg.h" +#include "vm/jit/stacktrace.h" #if defined(ENABLE_INLINING) # include "vm/jit/inline/inline.h" @@ -1000,10 +1001,15 @@ void jit_close(void); /* compile a method with jit compiler */ u1 *jit_compile(methodinfo *m); +/* patch the method entrypoint */ +u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra); + /* machine dependent functions */ #if defined(ENABLE_JIT) void md_init(void); +u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr); + void md_cacheflush(u1 *addr, s4 nbytes); void md_icacheflush(u1 *addr, s4 nbytes); void md_dcacheflush(u1 *addr, s4 nbytes); diff --git a/src/vm/jit/x86_64/asmpart.S b/src/vm/jit/x86_64/asmpart.S index a502aaaa8..c246b932a 100644 --- a/src/vm/jit/x86_64/asmpart.S +++ b/src/vm/jit/x86_64/asmpart.S @@ -30,7 +30,7 @@ Changes: Edwin Steiner - $Id: asmpart.S 4749 2006-04-11 10:20:18Z twisti $ + $Id: asmpart.S 4805 2006-04-21 10:54:24Z twisti $ */ @@ -202,7 +202,15 @@ L_stack_copy: L_copy_done: /* itmp1 still contains method pointer*/ - lea L_asm_call_jit_compiler(%rip),itmp3 + lea L_asm_call_jit_compiler(%rip),mptr + mov sp,itmp3 /* calculate the old stack pointer */ + add bp,itmp3 + mov mptr,6*8(itmp3) + lea (6*8-256)(itmp3),mptr /* We subtract 256 to force the next */ + /* move instruction to have a 32-bit */ + /* offset. */ + + mov (0*8+256)(mptr),itmp3 /* method call as in Java */ call *itmp3 /* call JIT compiler */ add bp,sp /* remove argument stack frame if any */ @@ -316,72 +324,24 @@ handle_fa7: asm_call_jit_compiler: L_asm_call_jit_compiler: /* required for PIC code */ - /* keep stack 16-byte aligned */ - sub $((3+ARG_CNT)*8+sizestackframeinfo),sp + sub $(ARG_CNT+1)*8,sp /* +1: keep stack 16-byte aligned */ - mov t0,0*8(sp) /* save register */ - - mov (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address */ - mov -1(itmp3),%bl /* get function code */ - cmp $0xd2,%bl /* called with `call *REG_ITMP2'? */ - jne L_not_static_special - - sub $11,itmp3 /* calculate address of immediate */ - jmp L_call_jit_compile - -L_not_static_special: - cmp $0xd0,%bl /* called with `call *REG_ITMP1' */ - jne L_not_virtual_interface - - sub $7,itmp3 /* calculate address of offset */ - mov (itmp3),itmp3l /* get offset (32-bit) */ - add itmp2,itmp3 /* add base address to get method addr*/ - jmp L_call_jit_compile - -L_not_virtual_interface: /* a call from asm_calljavamethod */ - xor itmp3,itmp3 - -L_call_jit_compile: - mov 0*8(sp),t0 /* restore register */ - mov itmp3,0*8(sp) /* save address for method pointer */ - mov itmp1,1*8(sp) /* save method pointer */ - - SAVE_ARGUMENT_REGISTERS(3) + SAVE_ARGUMENT_REGISTERS(0) - mov sp,a0 /* create stackframe info */ - add $((3+ARG_CNT)*8),a0 /* pass sfi */ - xor a1,a1 /* if pv is NULL, use findmethod */ + mov itmp1,a0 /* pass methodinfo pointer */ + mov mptr,a1 /* pass method pointer */ mov sp,a2 /* pass java sp */ - add $((1+3+ARG_CNT)*8+sizestackframeinfo),a2 - /* pass ra to java function */ - mov ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3 - mov a3,a4 /* xpc is equal to ra */ - call stacktrace_create_extern_stackframeinfo@PLT - - mov 1*8(sp),a0 /* pass method pointer */ - call jit_compile@PLT - mov v0,1*8(sp) /* save return value */ - - mov sp,a0 /* remove stackframe info */ - add $((3+ARG_CNT)*8),a0 /* pass sfi */ - call stacktrace_remove_stackframeinfo@PLT + add $(1+ARG_CNT+1)*8,a2 + mov (ARG_CNT+1)*8(sp),a3 /* pass ra to java function */ + call jit_asm_compile@PLT - mov 0*8(sp),itmp3 /* restore address for method pointer */ - mov 1*8(sp),v0 /* restore return value */ - - RESTORE_ARGUMENT_REGISTERS(3) + RESTORE_ARGUMENT_REGISTERS(0) - add $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame */ + add $(ARG_CNT+1)*8,sp /* remove stack frame */ test v0,v0 /* check for exception */ je L_asm_call_jit_compiler_exception - test itmp3,itmp3 /* is address == 0 (asm_calljavamethod*/ - je L_call_method - - mov v0,(itmp3) /* and now save the new pointer */ - -L_call_method: jmp *v0 /* ...and now call the new method */ L_asm_call_jit_compiler_exception: diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index abe863d8c..0f39dc038 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -30,7 +30,7 @@ Changes: Christian Ullrich Edwin Steiner - $Id: codegen.c 4791 2006-04-18 21:16:36Z twisti $ + $Id: codegen.c 4805 2006-04-21 10:54:24Z twisti $ */ @@ -3241,11 +3241,10 @@ gen_method: d = lm->parseddesc->returntype.type; } - x86_64_mov_membase_reg(cd, rd->argintregs[0], - OFFSET(java_objectheader, vftbl), - REG_ITMP2); - x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1); - M_CALL(REG_ITMP1); + M_ALD(REG_METHODPTR, rd->argintregs[0], + OFFSET(java_objectheader, vftbl)); + M_ALD32(REG_ITMP3, REG_METHODPTR, s1); + M_CALL(REG_ITMP3); break; case ICMD_INVOKEINTERFACE: @@ -3274,11 +3273,11 @@ gen_method: d = lm->parseddesc->returntype.type; } - M_ALD(REG_ITMP2, rd->argintregs[0], + M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl)); - x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP2); - x86_64_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1); - M_CALL(REG_ITMP1); + M_ALD32(REG_METHODPTR, REG_METHODPTR, s1); + M_ALD32(REG_ITMP3, REG_METHODPTR, s2); + M_CALL(REG_ITMP3); break; } diff --git a/src/vm/jit/x86_64/md-asm.h b/src/vm/jit/x86_64/md-asm.h index def285594..e624dcac1 100644 --- a/src/vm/jit/x86_64/md-asm.h +++ b/src/vm/jit/x86_64/md-asm.h @@ -28,7 +28,7 @@ Changes: - $Id: md-asm.h 4357 2006-01-22 23:33:38Z twisti $ + $Id: md-asm.h 4805 2006-04-21 10:54:24Z twisti $ */ @@ -75,6 +75,7 @@ #define xptr itmp1 #define xpc itmp2 +#define mptr itmp2 #define fa0 %xmm0 diff --git a/src/vm/jit/x86_64/md.c b/src/vm/jit/x86_64/md.c index b5ed97d49..9b946a4ce 100644 --- a/src/vm/jit/x86_64/md.c +++ b/src/vm/jit/x86_64/md.c @@ -28,7 +28,7 @@ Changes: Edwin Steiner - $Id: md.c 4698 2006-03-28 14:31:53Z twisti $ + $Id: md.c 4805 2006-04-21 10:54:24Z twisti $ */ @@ -37,6 +37,7 @@ #include "config.h" +#include #include #include @@ -163,6 +164,77 @@ u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize) } +/* md_get_method_patch_address ************************************************* + + Gets the patch address of the currently compiled method. The offset + is extracted from the load instruction(s) before the jump and added + to the right base address (PV or REG_METHODPTR). + + INVOKESTATIC/SPECIAL: + + 49 ba 98 3a ed ab aa 2a 00 00 mov $0x2aaaabed3a98,%r10 + 49 ff d2 rex64Z callq *%r10 + + INVOKEVIRTUAL: + + 4c 8b 17 mov (%rdi),%r10 + 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax + 48 ff d3 rex64 callq *%rax + + INVOKEINTERFACE: + + 4c 8b 17 mov (%rdi),%r10 + 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10 + 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax + 48 ff d3 rex64 callq *%r11 + +*******************************************************************************/ + +u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr) +{ + u1 mcode; + s4 offset; + u1 *pa; /* patch address */ + + /* go back to the actual call instruction (3-bytes) */ + + ra = ra - 3; + + /* get the last byte of the call */ + + mcode = ra[2]; + + /* check for the different calls */ + + /* INVOKESTATIC/SPECIAL */ + + if (mcode == 0xd2) { + /* patch address is 8-bytes before the call instruction */ + + pa = ra - 8; + + } else if (mcode == 0xd3) { + /* INVOKEVIRTUAL/INTERFACE */ + + /* Get the offset from the instruction (the offset address is + 4-bytes before the call instruction). */ + + offset = *((s4 *) (ra - 4)); + + /* add the offset to the method pointer */ + + pa = mptr + offset; + + } else { + /* catch any problems */ + + assert(0); + } + + return pa; +} + + /* md_codegen_findmethod ******************************************************* On this architecture just a wrapper function to codegen_findmethod. @@ -195,6 +267,30 @@ void md_cacheflush(u1 *addr, s4 nbytes) } +/* md_icacheflush ************************************************************** + + Calls the system's function to flush the instruction cache. + +*******************************************************************************/ + +void md_icacheflush(u1 *addr, s4 nbytes) +{ + /* do nothing */ +} + + +/* md_dcacheflush ************************************************************** + + Calls the system's function to flush the data cache. + +*******************************************************************************/ + +void md_dcacheflush(u1 *addr, s4 nbytes) +{ + /* do nothing */ +} + + /* md_patch_replacement_point ************************************************** Patch the given replacement point. -- 2.25.1