* 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.
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 $
*/
}
+/* 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
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 $
*/
#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"
/* 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);
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 $
*/
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 */
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:
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 $
*/
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:
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;
}
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 $
*/
#define xptr itmp1
#define xpc itmp2
+#define mptr itmp2
#define fa0 %xmm0
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 $
*/
#include "config.h"
+#include <assert.h>
#include <stdlib.h>
#include <ucontext.h>
}
+/* 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.
}
+/* 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.