* jit/patcher-common.h: Made declarations visible on s390.
* jit/s390/asmpart.S (asm_patcher_wrapper): removed.
* jit/s390/emit.c (emit_patcher_stubs): removed, (emit_patcher_traps): added.
* jit/s390/codegen.h (PATCHER_LONGBRANCHES_NOPS_SKIP, PATCHER_LONGBRANCHES_NOPS): removed, (PATCHER_CALL_SIZE, PATCHER_NOPS, PATCHER_NOPS_SKIP) adapted to patching via signals.
* jit/s390/codegen.c (codegen_emit, codegen_emit_stub_native): Adapted to paching via signals.
* jit/s390/md.c (md_signal_handler_sigill, md_signal_handler_sigsegv): added support for exceptions_new_hardware_exception returning NULL.
* jit/s390/patcher.c: Adapted to paching via signals.
/* patcher prototypes and macros **********************************************/
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__POWERPC__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__POWERPC__) || defined (__S390__)
/* new patcher functions */
bool patcher_invokeinterface(patchref_t *pr);
#define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
-#if defined(__ALPHA__) || defined(__POWERPC__)
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__S390__)
bool patcher_checkcast_interface(patchref_t *pr);
#define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
#endif /* defined(__ALPHA__) */
+#if defined(__S390__)
+bool patcher_clinit(patchref_t *pr);
+#define PATCHER_clinit (functionptr) patcher_clinit
+bool patcher_athrow_areturn(patchref_t *pr);
+#define PATCHER_athrow_areturn (functionptr) patcher_athrow_areturn
+
+bool patcher_checkcast_instanceof_interface(patchref_t *pr);
+#define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
+#endif /* defined (__S390__) */
#endif /* architecture list */
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: patcher.h 8216 2007-07-19 13:51:21Z michi $
+ $Id: patcher.h 8251 2007-08-01 15:26:59Z pm $
*/
#include "vm/global.h"
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__POWERPC__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__POWERPC__) || defined(__S390__)
# error "you should no longer include this file"
#else
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: asmpart.S 8123 2007-06-20 23:50:55Z michi $
+ $Id: asmpart.S 8251 2007-08-01 15:26:59Z pm $
*/
.globl asm_abstractmethoderror
- .globl asm_patcher_wrapper
-
.globl asm_replacement_out
.globl asm_replacement_in
#endif
-/* asm_patcher_wrapper *********************************************************
-
- XXX
-
- Stack layout:
- 20 return address into JIT code (patch position)
- 16 pointer to virtual java_objectheader
- 12 machine code (which is patched back later)
- 8 unresolved class/method/field reference
- 4 data segment displacement from load instructions
- 0 patcher function pointer to call (pv afterwards)
-
-*******************************************************************************/
-
-asm_patcher_wrapper:
-# define apw_sfs (96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE + VOLATILE_FLOAT_REGISTERS_SIZE)
-
- ahi sp, -apw_sfs /* create stack frame */
-
- /* store all volatile registers and a2, because we will touch it */
-
- st a2, 96(sp)
- STORE_VOLATILE_INTEGER_REGISTERS(96 + 4)
- STORE_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
-
- /* pass arguments */
-
- la a0, apw_sfs(sp) /* pass SP of patcher stub */
- la a1, 0xffc(pv) /* pass PV (if NULL, use findmethod) */
- lhi a2, 0 /* pass RA */
-
- /* call patcher_wrapper */
-
- bras itmp1, L_apw_bras /* call patcher_wrapper */
- .long patcher_wrapper
-L_apw_bras:
- l itmp1, 0(itmp1)
- basr %r14, itmp1
-
- /* store return value */
-
- st v0,0(sp) /* save return value */
-
- /* restore volatile registers */
-
- l a2, 96(sp)
- LOAD_VOLATILE_INTEGER_REGISTERS(96 + 4)
- LOAD_VOLATILE_FLOAT_REGISTERS(96 + 4 + VOLATILE_INTEGER_REGISTERS_SIZE)
-
- l itmp3, 0(sp) /* restore return value */
- ltr itmp3, itmp3 /* exception thrown ? */
- jne L_asm_patcher_wrapper_exception /* handle exception */
- l itmp3, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
- ahi sp, apw_sfs + (6 * 4) /* remove stack frame, and stack frame by patcher stub */
- br itmp3 /* return */
-
-L_asm_patcher_wrapper_exception:
- lr xptr,itmp3 /* get exception */
- l xpc, apw_sfs + (5 * 4)(sp) /* load return address to JIT from stack */
- ahi sp, apw_sfs + (6 * 4) /* remove stack frame, and stack frame by patcher stub */
- j L_asm_handle_exception
-
#if 0
/* asm_replacement_out *********************************************************
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: codegen.c 8240 2007-07-29 20:36:47Z pm $
+ $Id: codegen.c 8251 2007-08-01 15:26:59Z pm $
*/
#include <assert.h>
#include <stdio.h>
-#include "vm/types.h"
-
-#include "md-abi.h"
-#include "vm/jit/s390/arch.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-
-#include "mm/memory.h"
#include "native/jni.h"
#include "native/native.h"
+#include "mm/memory.h"
+
#if defined(ENABLE_THREADS)
+# include "threads/lock-common.h"
# include "threads/native/lock.h"
#endif
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/jit/abi.h"
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
+#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
+#include "vm/jit/s390/arch.h"
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
#include "vm/jit/stacktrace.h"
-#include "vm/jit/abi.h"
-#include "vm/jit/emit-common.h"
-
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
+#include "vm/types.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
#define OOPS() assert(0);
#define SUPPORT_HERCULES 1
/* PROFILE_CYCLE_STOP; */
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
cr, disp);
/* PROFILE_CYCLE_START; */
/* PROFILE_CYCLE_STOP; */
- codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
+ patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
/* PROFILE_CYCLE_START; */
}
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
PROFILE_CYCLE_STOP;
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
+ patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
PROFILE_CYCLE_START;
}
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = dseg_add_unique_address(cd, uf);
- codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
+ patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
PROFILE_CYCLE_STOP;
- codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
+ patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
PROFILE_CYCLE_START;
}
}
fieldtype = uf->fieldref->parseddesc.fd->type;
disp = 0;
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
* We pass in the disp parameter, how many bytes
* to skip to the to the actual store.
*
- * XXX this relies on codegen_add_patch_ref internals
+ * XXX this relies on patcher_add_patch_ref internals
*/
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
+ patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
ref = cd->mcodeptr;
}
}
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- cd->patchrefs->disp = (cd->mcodeptr - ref);
+ ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
}
switch (fieldtype) {
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uc = iptr->sx.s23.s2.uc;
- codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
}
#endif /* ENABLE_VERIFIER */
unresolved_class *uc = iptr->sx.s23.s2.uc;
PROFILE_CYCLE_STOP;
- codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
+ patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
PROFILE_CYCLE_START;
}
#endif /* ENABLE_VERIFIER */
if (lm == NULL) {
disp = dseg_add_unique_address(cd, um);
- codegen_addpatchref(cd, PATCHER_invokestatic_special,
+ patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
um, disp);
}
else
/* TODO softnull REG_A0 */
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
s1 = 0;
}
*/
if (lm == NULL) {
- codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
s1 = 0;
s2 = 0;
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
iptr->sx.s23.s3.c.ref,
disp);
if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
if (super == NULL) {
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_checkcast_instanceof_interface,
iptr->sx.s23.s3.c.ref,
0);
if (super == NULL) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_resolve_classref_to_vftbl,
iptr->sx.s23.s3.c.ref,
disp);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_resolve_classref_to_classinfo,
iptr->sx.s23.s3.c.ref,
disp);
disp = dseg_add_unique_s4(cd, 0); /* super->flags */
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
iptr->sx.s23.s3.c.ref, disp);
ICONST(REG_ITMP2, ACC_INTERFACE);
if (d == REG_ITMP2)
M_CLR(d);
- codegen_add_patch_ref(cd,
+ patcher_add_patch_ref(jd,
PATCHER_checkcast_instanceof_interface,
iptr->sx.s23.s3.c.ref, 0);
}
if (super == NULL) {
disp = dseg_add_unique_address(cd, NULL);
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
iptr->sx.s23.s3.c.ref,
disp);
}
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
disp = dseg_add_unique_address(cd, 0);
- codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
+ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
iptr->sx.s23.s3.c.ref,
disp);
}
/* generate stubs */
- emit_patcher_stubs(jd);
+ emit_patcher_traps(jd);
#if defined(ENABLE_REPLACEMENT)
REPLACEMENT_EMIT_STUBS(jd);
#endif
#if !defined(WITH_STATIC_CLASSPATH)
if (f == NULL)
- codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
+ patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
#endif
M_ILD_DSEG(REG_ITMP1, disp);
/* generate patcher stubs */
- emit_patcher_stubs(jd);
+ emit_patcher_traps(jd);
}
s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: codegen.h 8240 2007-07-29 20:36:47Z pm $
+ $Id: codegen.h 8251 2007-08-01 15:26:59Z pm $
*/
/* some patcher defines *******************************************************/
-#define PATCHER_CALL_SIZE 4 /* size in bytes of a patcher call */
-
-#define PATCHER_NOPS \
- do { \
- /* do not generate additonal nops for long patcher branches */ \
- if (! CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) { \
- M_NOP; \
- M_NOP; \
- M_NOP; \
- } \
- } while (0)
-
-#define PATCHER_LONGBRANCHES_NOPS \
- do { \
- M_BR(SZ_BRC + (10 * 2)); \
- M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; M_NOP2; /* ild */ \
- M_NOP2; /* aadd */ \
- M_NOP2; /* jmp */ \
- } while (0)
-
-#define PATCHER_NOPS_SKIP 12
-#define PATCHER_LONGBRANCHES_NOPS_SKIP 24
+#define PATCHER_CALL_SIZE 2 /* size in bytes of a patcher call */
+#define PATCHER_NOPS M_NOP3
+#define PATCHER_NOPS_SKIP 2
/* branch defines ************************************************************/
#define M_JMP(rs, rd) _IF(rs == RN, N_BCR(DD_ANY, rd), N_BASR(rs, rd))
#define M_NOP N_BC(0, 0, RN, RN)
#define M_NOP2 N_BCR(0, RN)
+#define M_NOP3 N_BCR(0, 1)
#define M_JSR(reg_ret, reg_addr) N_BASR(reg_ret, reg_addr)
#define M_ICMP(a, b) N_CR(a, b)
#define M_ICMPU(a, b) N_CLR(a, b)
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: emit.c 8240 2007-07-29 20:36:47Z pm $
+ $Id: emit.c 8251 2007-08-01 15:26:59Z pm $
*/
-
#include "config.h"
#include <assert.h>
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-
+#include "mm/memory.h"
#if defined(ENABLE_THREADS)
# include "threads/native/lock.h"
#endif
-
#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
+#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/abi.h"
-#include "vm/global.h"
-#include "mm/memory.h"
-#include "vm/exceptions.h"
-
-#define __PORTED__
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
+#include "vm/types.h"
+#include "vmcore/options.h"
/* emit_load *******************************************************************
*******************************************************************************/
-__PORTED__ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 disp;
*******************************************************************************/
-__PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
{
codegendata *cd;
*******************************************************************************/
-__PORTED__ void emit_copy(jitdata *jd, instruction *iptr)
+void emit_copy(jitdata *jd, instruction *iptr)
{
codegendata *cd;
varinfo *src;
}
}
+/* emit_patcher_traps **********************************************************
-/* emit_patcher_stubs **********************************************************
-
- Generates the code for the patcher stubs.
+ Generates the code for the patcher traps.
*******************************************************************************/
-__PORTED__ void emit_patcher_stubs(jitdata *jd)
+void emit_patcher_traps(jitdata *jd)
{
-
codegendata *cd;
- patchref *pref;
- u4 mcode;
+ codeinfo *code;
+ patchref_t *pr;
u1 *savedmcodeptr;
u1 *tmpmcodeptr;
- s4 targetdisp;
- s4 disp;
- u1 *ref;
/* get required compiler data */
- cd = jd->cd;
-
- /* generate code patching stub call code */
+ cd = jd->cd;
+ code = jd->code;
- targetdisp = 0;
+ /* generate patcher traps code */
- for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
- /* check code segment size */
-
- MCODECHECK(100);
+ for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
/* Get machine code which is patched back in later. The
- call is 1 instruction word long. */
-
- tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+ trap is 2 bytes long. */
- mcode = *((u4 *) tmpmcodeptr);
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
+ pr->mcode = *((u2 *) tmpmcodeptr);
- /* Patch in the call to call the following code (done at
+ /* Patch in the trap to call the signal handler (done at
compile time). */
savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
- disp = (savedmcodeptr) - (tmpmcodeptr);
-
- if (! N_VALID_BRANCH(disp)) {
- /* Displacement overflow */
-
- /* If LONGBRANCHES is not set, the flag and the error flag */
-
- if (! CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- cd->flags |= (CODEGENDATA_FLAG_ERROR |
- CODEGENDATA_FLAG_LONGBRANCHES);
- }
-
- /* If error flag is set, do nothing. The method has to be recompiled. */
-
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) && CODEGENDATA_HAS_FLAG_ERROR(cd)) {
- return;
- }
- }
-
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
-
- /* Generating long branches */
-
- disp = dseg_add_s4(cd, savedmcodeptr - cd->mcodebase - N_PV_OFFSET);
-
- M_ILD_DSEG(REG_ITMP3, disp);
- M_AADD(REG_PV, REG_ITMP3);
-
- /* Do the branch at the end of NOP sequence.
- * This way the patch position is at a *fixed* offset
- * (PATCHER_LONGBRANCHES_NOPS_SKIP) of the return address.
- */
-
- cd->mcodeptr = tmpmcodeptr + PATCHER_LONGBRANCHES_NOPS_SKIP - SZ_BASR;
- M_JMP(REG_ITMP3, REG_ITMP3);
- } else {
-
- /* Generating short branches */
-
- M_BSR(REG_ITMP3, disp);
- }
+ M_ILL(EXCEPTION_HARDWARE_PATCHER);
cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
-
- /* create stack frame */
-
- M_ASUB_IMM(6 * 4, REG_SP);
-
- /* move return address onto stack */
-
- M_AST(REG_ITMP3, REG_SP, 5 * 4);
-
- /* move pointer to java_objectheader onto stack */
-
-#if defined(ENABLE_THREADS)
- /* create a virtual java_objectheader */
-
- (void) dseg_add_unique_address(cd, NULL); /* flcword */
- (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
- disp = dseg_add_unique_address(cd, NULL); /* vftbl */
-
- M_LDA_DSEG(REG_ITMP3, disp);
- M_AST(REG_ITMP3, REG_SP, 4 * 4);
-#else
- /* nothing to do */
-#endif
-
- /* move machine code onto stack */
-
- disp = dseg_add_s4(cd, mcode);
- M_ILD_DSEG(REG_ITMP3, disp);
- M_IST(REG_ITMP3, REG_SP, 3 * 4);
-
- /* move class/method/field reference onto stack */
-
- disp = dseg_add_address(cd, pref->ref);
- M_ALD_DSEG(REG_ITMP3, disp);
- M_AST(REG_ITMP3, REG_SP, 2 * 4);
-
- /* move data segment displacement onto stack */
-
- disp = dseg_add_s4(cd, pref->disp);
- M_ILD_DSEG(REG_ITMP3, disp);
- M_IST(REG_ITMP3, REG_SP, 1 * 4);
-
- /* move patcher function pointer onto stack */
-
- disp = dseg_add_functionptr(cd, pref->patcher);
- M_ALD_DSEG(REG_ITMP3, disp);
- M_AST(REG_ITMP3, REG_SP, 0 * 4);
-
- if (targetdisp == 0) {
- targetdisp = (cd->mcodeptr) - (cd->mcodebase);
-
- disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
- M_ALD_DSEG(REG_ITMP3, disp);
- M_JMP(RN, REG_ITMP3);
- }
- else {
- disp = ((cd->mcodebase) + targetdisp) -
- (( cd->mcodeptr) );
-
- emit_branch(cd, disp, BRANCH_UNCONDITIONAL, RN, 0);
- }
}
}
-
/* emit_replacement_stubs ******************************************************
Generates the code for the replacement stubs.
*******************************************************************************/
-__PORTED__ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 disp;
*******************************************************************************/
-__PORTED__ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
{
codegendata *cd;
s4 disp;
Changes: Edwin Steiner
- $Id: md.c 8243 2007-07-31 08:57:54Z michi $
+ $Id: md.c 8251 2007-08-01 15:26:59Z pm $
*/
stacktrace_remove_stackframeinfo(&sfi);
- _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
- _mc->gregs[REG_ITMP1_XPTR] = (ptrint) e;
- _mc->psw.addr = (ptrint) asm_handle_exception;
+ if (e != NULL) {
+ _mc->gregs[REG_ITMP2_XPC] = (ptrint) xpc;
+ _mc->gregs[REG_ITMP1_XPTR] = (ptrint) e;
+ _mc->psw.addr = (ptrint) asm_handle_exception;
+ } else {
+ _mc->psw.addr = xpc;
+ }
}
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p) {
stacktrace_remove_stackframeinfo(&sfi);
- _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e;
- _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc;
- _mc->psw.addr = (ptrint) asm_handle_exception;
-
+ if (e != NULL) {
+ _mc->gregs[REG_ITMP1_XPTR] = (ptrint)e;
+ _mc->gregs[REG_ITMP2_XPC] = (ptrint)xpc;
+ _mc->psw.addr = (ptrint) asm_handle_exception;
+ } else {
+ _mc->psw.addr = xpc;
+ }
} else {
#if !defined(NDEBUG)
md_dump_context(xpc, _mc);
Authors: Christian Thalinger
- Changes:
+ Changes: Peter Molnar
- $Id: patcher.c 8195 2007-07-11 11:27:55Z pm $
-
- GENERATED PATCHER BRANCH AFTER PATCH
-
- Short patcher call:
-
- foo bras %r14, OFFSET foo
- bar ===> bar ===> bar
- baz baz baz
-
- Short patcher call with nops:
- PATCHER_NOPS_SKIP <-+
- |
- nop bras %r14, OFFSET nop --+
- nop ===> nop ===> nop |
- nop nop nop --+
- foo foo foo
-
- Long pacher call:
- PATCHER_LONGBRANCHES_NOPS_SKIP <-+
- |
- br exit: ild itmp3, disp(pv) br exit -+
- nop aadd pv, itmp3 aadd pv, itmp3 |
- nop ===> nop ===> nop |
- ..... .... .... |
- nop basr itmp3, itmp3 basr itmp3, itmp3 -+
- exit: exit:
+ $Id: patcher.c 8251 2007-08-01 15:26:59Z pm $
*/
#include "config.h"
-#include "vm/types.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/md-abi.h"
+#include <assert.h>
#include "mm/memory.h"
#include "native/native.h"
#include "vm/builtin.h"
-#include "vmcore/class.h"
#include "vm/exceptions.h"
-#include "vmcore/field.h"
#include "vm/initialize.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/md-abi.h"
+#include "vm/jit/stacktrace.h"
+#include "vm/resolve.h"
+#include "vm/types.h"
+#include "vmcore/class.h"
+#include "vmcore/field.h"
#include "vmcore/options.h"
#include "vmcore/references.h"
-#include "vm/resolve.h"
-#include "vm/jit/patcher.h"
-#include "vm/jit/stacktrace.h"
-
-#include <assert.h>
-#define OOPS() assert(0);
-#define __PORTED__
-
-/* A normal patcher branch done using BRAS */
-#define PATCHER_IS_SHORTBRANCH(brcode) ((brcode & 0xFF0F0000) == 0xA7050000)
-
-/* patcher_wrapper *************************************************************
-
- Wrapper for all patchers. It also creates the stackframe info
- structure.
-
- If the return value of the patcher function is false, it gets the
- exception object, clears the exception pointer and returns the
- exception.
-
-*******************************************************************************/
-
-java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
-{
- stackframeinfo sfi;
- u1 *xpc;
- java_objectheader *o;
- functionptr f;
- bool result;
- java_objectheader *e;
-
- /* define the patcher function */
-
- bool (*patcher_function)(u1 *);
-
- /* get stuff from the stack */
-
- xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
- o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
- f = (functionptr) *((ptrint *) (sp + 0 * 4));
-
- /* For a normal branch, the patch position is SZ_BRAS bytes before the RA.
- * For long branches it is PATCHER_LONGBRANCHES_NOPS_SKIP before the RA.
- */
-
- if (PATCHER_IS_SHORTBRANCH(*(u4 *)(xpc - SZ_BRAS))) {
- xpc = xpc - SZ_BRAS;
- } else {
- xpc = xpc - PATCHER_LONGBRANCHES_NOPS_SKIP;
- }
-
- *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
-
- /* store PV into the patcher function position */
-
- *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
-
- /* cast the passed function to a patcher function */
-
- patcher_function = (bool (*)(u1 *)) (ptrint) f;
-
- /* enter a monitor on the patching position */
-
- PATCHER_MONITORENTER;
-
- /* create the stackframeinfo */
-
- /* RA is passed as NULL, but the XPC is correct and can be used in
- stacktrace_create_extern_stackframeinfo for
- md_codegen_get_pv_from_pc. */
-
- stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
-
- /* call the proper patcher function */
-
- result = (patcher_function)(sp);
-
- /* remove the stackframeinfo */
-
- stacktrace_remove_stackframeinfo(&sfi);
- /* check for return value and exit accordingly */
-
- if (result == false) {
- e = exceptions_get_and_clear_exception();
-
- PATCHER_MONITOREXIT;
-
- return e;
- }
-
- PATCHER_MARK_PATCHED_MONITOREXIT;
-
- return NULL;
-}
+#define PATCH_BACK_ORIGINAL_MCODE \
+ *((u2 *) pr->mpc) = (u2) pr->mcode;
+#define PATCHER_TRACE
/* patcher_get_putstatic *******************************************************
*******************************************************************************/
-bool patcher_get_putstatic(u1 *sp)
+bool patcher_get_putstatic(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
unresolved_field *uf;
- s4 disp;
+ u1 *datap;
fieldinfo *fi;
- u1 *pv;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ uf = (unresolved_field *) pr->ref;
+ datap = (u1 *) pr->datap;
/* get the fieldinfo */
if (!initialize_class(fi->class))
return false;
- *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
+ PATCH_BACK_ORIGINAL_MCODE;
- /* patch back original code */
+ /* patch the field value's address */
- *((u4 *) ra) = mcode;
+ *((ptrint *) datap) = (ptrint) &(fi->value);
return true;
}
*******************************************************************************/
-bool patcher_get_putfield(u1 *sp)
+bool patcher_get_putfield(patchref_t *pr)
{
u1 *ra;
- u4 mcode, brcode;
unresolved_field *uf;
fieldinfo *fi;
- u1 byte;
s4 disp;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
+ ra = (u1 *) pr->mpc;
+ uf = (unresolved_field *) pr->ref;
+ disp = pr->disp;
/* get the fieldinfo */
if (!(fi = resolve_field_eager(uf)))
return false;
- /* patch back original code */
-
- brcode = *((u4 *) ra);
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
/* If NOPs are generated, skip them */
- if (! PATCHER_IS_SHORTBRANCH(brcode))
- ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
- else if (opt_shownops)
+ if (opt_shownops)
ra += PATCHER_NOPS_SKIP;
/* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
*******************************************************************************/
-__PORTED__ bool patcher_invokestatic_special(u1 *sp)
+bool patcher_invokestatic_special(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
unresolved_method *um;
- s4 disp;
- u1 *pv;
+ u1 *datap;
methodinfo *m;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ um = (unresolved_method *) pr->ref;
+ datap = (u1 *) pr->datap;
/* get the fieldinfo */
if (!(m = resolve_method_eager(um)))
return false;
- *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
-
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
/* patch stubroutine */
+ *((ptrint *) datap) = (ptrint) m->stubroutine;
+
return true;
}
-
/* patcher_invokevirtual *******************************************************
Machine code:
*******************************************************************************/
-bool patcher_invokevirtual(u1 *sp)
+bool patcher_invokevirtual(patchref_t *pr)
{
u1 *ra;
- u4 mcode, brcode;
unresolved_method *um;
methodinfo *m;
- s4 off;
+ s4 off;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
+ ra = (u1 *) pr->mpc;
+ um = (unresolved_method *) pr->ref;
/* get the fieldinfo */
/* patch back original code */
- brcode = *((u4 *) ra);
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
/* If NOPs are generated, skip them */
- if (! PATCHER_IS_SHORTBRANCH(brcode))
- ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
- else if (opt_shownops)
+ if (opt_shownops)
ra += PATCHER_NOPS_SKIP;
/* patch vftbl index */
*******************************************************************************/
-bool patcher_invokeinterface(u1 *sp)
+bool patcher_invokeinterface(patchref_t *pr)
{
u1 *ra;
- u4 mcode, brcode;
unresolved_method *um;
methodinfo *m;
s4 idx, off;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
+ ra = (u1 *) pr->mpc;
+ um = (unresolved_method *) pr->ref;
/* get the fieldinfo */
/* patch back original code */
- brcode = *((u4 *) ra);
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
/* If NOPs are generated, skip them */
- if (! PATCHER_IS_SHORTBRANCH(brcode))
- ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
- else if (opt_shownops)
+ if (opt_shownops)
ra += PATCHER_NOPS_SKIP;
/* get interfacetable index */
*******************************************************************************/
-__PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
+bool patcher_resolve_classref_to_flags(patchref_t *pr)
{
constant_classref *cr;
- s4 disp;
- u1 *pv;
+ u1 *datap;
classinfo *c;
- u4 mcode;
- u1 *ra;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ cr = (constant_classref *) pr->ref;
+ datap = (u1 *) pr->datap;
/* get the fieldinfo */
if (!(c = resolve_classref_eager(cr)))
return false;
- /* patch class flags */
-
- *((s4 *) (pv + disp)) = (s4) c->flags;
+ PATCH_BACK_ORIGINAL_MCODE;
- /* patch back original code */
+ /* patch class flags */
- *((u4 *) ra) = mcode;
+ *((s4 *) datap) = (s4) c->flags;
return true;
}
*******************************************************************************/
-__PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
{
constant_classref *cr;
- s4 disp;
- u1 *pv;
+ u1 *datap;
classinfo *c;
- u4 mcode;
- u1 *ra;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ cr = (constant_classref *) pr->ref;
+ datap = (u1 *) pr->datap;
/* get the classinfo */
if (!(c = resolve_classref_eager(cr)))
return false;
- /* patch the classinfo pointer */
-
- *((ptrint *) (pv + disp)) = (ptrint) c;
+ PATCH_BACK_ORIGINAL_MCODE;
- /* patch back original code */
+ /* patch the classinfo pointer */
- *((u4 *) ra) = mcode;
+ *((ptrint *) datap) = (ptrint) c;
return true;
}
*******************************************************************************/
-bool patcher_resolve_classref_to_vftbl(u1 *sp)
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
{
constant_classref *cr;
- s4 disp;
- u1 *pv;
+ u1 *datap;
classinfo *c;
- u4 mcode;
- u1 *ra;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ cr = (constant_classref *) pr->ref;
+ datap = (u1 *) pr->datap;
/* get the fieldinfo */
if (!(c = resolve_classref_eager(cr)))
return false;
- /* patch super class' vftbl */
-
- *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
+ PATCH_BACK_ORIGINAL_MCODE;
- /* patch back original code */
+ /* patch super class' vftbl */
- *((u4 *) ra) = mcode;
+ *((ptrint *) datap) = (ptrint) c->vftbl;
return true;
}
*******************************************************************************/
-bool patcher_checkcast_instanceof_interface(u1 *sp)
+bool patcher_checkcast_instanceof_interface(patchref_t *pr)
{
+
u1 *ra;
- u4 mcode, brcode;
constant_classref *cr;
classinfo *c;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
+ ra = (u1 *) pr->mpc;
+ cr = (constant_classref *) pr->ref;
/* get the fieldinfo */
/* patch back original code */
- brcode = *((u4 *) ra);
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
/* If NOPs are generated, skip them */
- if (! PATCHER_IS_SHORTBRANCH(brcode))
- ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
- else if (opt_shownops)
+ if (opt_shownops)
ra += PATCHER_NOPS_SKIP;
/* patch super class index */
*******************************************************************************/
-__PORTED__ bool patcher_clinit(u1 *sp)
+bool patcher_clinit(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
classinfo *c;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- c = (classinfo *) *((ptrint *) (sp + 2 * 4));
+ c = (classinfo *)pr->ref;
/* check if the class is initialized */
/* patch back original code */
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
return true;
}
*******************************************************************************/
#ifdef ENABLE_VERIFIER
-__PORTED__ bool patcher_athrow_areturn(u1 *sp)
+bool patcher_athrow_areturn(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
unresolved_class *uc;
+ PATCHER_TRACE;
+
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
+ uc = (unresolved_class *) pr->ref;
/* resolve the class and check subtype constraints */
/* patch back original code */
- *((u4 *) ra) = mcode;
+ PATCH_BACK_ORIGINAL_MCODE;
return true;
}
*******************************************************************************/
#if !defined(WITH_STATIC_CLASSPATH)
-__PORTED__ bool patcher_resolve_native(u1 *sp)
+bool patcher_resolve_native_function(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
methodinfo *m;
+ u1 *datap;
functionptr f;
- s4 disp;
- u1 *pv;
+
+ PATCHER_TRACE;
/* get stuff from the stack */
- ra = (u1 *) *((ptrint *) (sp + 5 * 4));
- mcode = *((u4 *) (sp + 3 * 4));
- disp = *((s4 *) (sp + 1 * 4));
- m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
- pv = (u1 *) *((ptrint *) (sp + 0 * 4));
+ m = (methodinfo *) pr->ref;
+ datap = (u1 *) pr->datap;
/* resolve native function */
if (!(f = native_resolve_function(m)))
return false;
- /* patch native function pointer */
-
- *((ptrint *) (pv + disp)) = (ptrint) f;
+ PATCH_BACK_ORIGINAL_MCODE;
- /* patch back original code */
+ /* patch native function pointer */
- *((u4 *) ra) = mcode;
+ *((ptrint *) datap) = (ptrint) f;
return true;
}
#endif /* !defined(WITH_STATIC_CLASSPATH) */
-
/*
* 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