case ICMD_INVOKEVIRTUAL:
if (lm == NULL) {
- patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
+ int32_t disp = dseg_add_unique_s4(cd, 0);
+ patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, disp);
- s1 = 0;
- }
- else
- s1 = OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * lm->vftblindex;
+ // The following instruction MUST NOT change a0 because of the implicit NPE check.
+ M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
- /* implicit null-pointer check */
- M_LDR_INTERN(REG_METHODPTR, REG_A0,
- OFFSET(java_object_t, vftbl));
- M_LDR_INTERN(REG_PV, REG_METHODPTR, s1);
+ // Sanity check.
+ assert(REG_ITMP1 != REG_METHODPTR);
+ assert(REG_ITMP2 == REG_METHODPTR);
- /* generate the actual call */
+ M_DSEG_LOAD(REG_ITMP1, disp);
+ M_ADD(REG_METHODPTR, REG_METHODPTR, REG_ITMP1);
+ // This must be a load with displacement,
+ // otherwise the JIT method address patching does
+ // not work anymore (see md_jit_method_patch_address).
+ M_LDR_INTERN(REG_PV, REG_METHODPTR, 0);
+ }
+ else {
+ s1 = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex;
+
+ // The following instruction MUST NOT change a0 because of the implicit NPE check.
+ M_LDR_INTERN(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
+ M_LDR(REG_PV, REG_METHODPTR, s1);
+ }
+
+ // Generate the actual call.
M_MOV(REG_LR, REG_PC);
M_MOV(REG_PC, REG_PV);
s1 = (s4) (cd->mcodeptr - cd->mcodebase);
#include "vm/jit/patcher-common.hpp"
-#define gen_resolveload(inst,offset) \
- assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
- assert(!((inst) & 0x0fff)); \
- if ((offset) < 0) { \
- (inst) = ((inst) & 0xff7ff000) | ((-(offset)) & 0x0fff); \
- /*(inst) &= ~(1 << 23);*/ \
- } else { \
- (inst) = ((inst) & 0xfffff000) | ((offset) & 0x0fff); \
- /*(inst) |= (1 << 23);*/ \
- }
-
-
/* patcher_patch_code **********************************************************
Just patches back the original machine code.
bool patcher_invokevirtual(patchref_t *pr)
{
- uint32_t* pc = (uint32_t*) pr->mpc;
- unresolved_method* um = (unresolved_method *) pr->ref;
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
// Resolve the method.
methodinfo* m = resolve_method_eager(um);
return false;
// Patch vftbl index.
- gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
-
- // Synchronize instruction cache.
- md_icacheflush(pc + 1, 1 * 4);
+ int32_t disp = OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex;
+ *datap = disp;
// Patch back the original code.
patcher_patch_code(pr);
e1a0e00f mov lr, pc
e1a0f00c mov pc, ip
-
*******************************************************************************/
bool patcher_invokeinterface(patchref_t *pr)