Christian Ullrich
Edwin Steiner
- $Id: codegen.c 6036 2006-11-22 10:50:07Z twisti $
+ $Id: codegen.c 6264 2007-01-02 19:40:18Z edwin $
*/
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
builtintable_entry *bte;
methoddesc *md;
- rplpoint *replacementpoint;
s4 fieldtype;
s4 varindex;
#if defined(ENABLE_SSA)
#endif
#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
+ emit_verbosecall_enter(jd);
#endif
}
- /* create replacement points */
-
- if (!replace_create_replacement_points(jd))
- return false;
-
#if defined(ENABLE_SSA)
/* with SSA Header is Basic Block 0 - insert phi Moves if necessary */
if ( ls != NULL)
/* end of header generation */
- replacementpoint = jd->code->rplpoints;
+ /* create replacement points */
+
+ REPLACEMENT_POINTS_INIT(cd, jd);
/* walk through all basic blocks */
/* handle replacement points */
- if (bptr->bitflags & BBFLAG_REPLACEMENT) {
- replacementpoint->pc = (u1*)bptr->mpc; /* will be resolved later */
-
- replacementpoint++;
-
- assert(cd->lastmcodeptr <= cd->mcodeptr);
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
- }
+ REPLACEMENT_POINT_BLOCK_START(cd, bptr);
/* copy interface registers to their destination */
MCODECHECK(1024); /* 1kB should be enough */
switch (iptr->opc) {
+ case ICMD_NOP: /* ... ==> ... */
+ case ICMD_POP: /* ..., value ==> ... */
+ case ICMD_POP2: /* ..., value, value ==> ... */
+ break;
case ICMD_INLINE_START:
- /* handle replacement point */
+ REPLACEMENT_POINT_INLINE_START(cd, iptr);
+ break;
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+ case ICMD_INLINE_BODY:
+ REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
dseg_addlinenumber_inline_start(cd, iptr);
+ dseg_addlinenumber(cd, iptr->line);
break;
case ICMD_INLINE_END:
dseg_addlinenumber(cd, iptr->line);
break;
- case ICMD_NOP: /* ... ==> ... */
- break;
-
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- M_TEST(s1);
- M_BEQ(0);
- codegen_add_nullpointerexception_ref(cd);
+ emit_nullpointer_check(cd, iptr, s1);
break;
/* constant operations ************************************************/
case ICMD_FLOAD:
case ICMD_DLOAD:
case ICMD_ISTORE:
- case ICMD_ASTORE:
case ICMD_LSTORE:
case ICMD_FSTORE:
case ICMD_DSTORE:
emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
break;
-
- /* pop operations *****************************************************/
-
- /* attention: double and longs are only one entry in CACAO ICMDs */
-
- case ICMD_POP: /* ..., value ==> ... */
- case ICMD_POP2: /* ..., value, value ==> ... */
-
+ case ICMD_ASTORE:
+ if (!(iptr->flags.bits & INS_FLAG_RETADDR))
+ emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
break;
s1 = emit_load_s1(jd, iptr, EAX);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, EAX);
-
- if (checknull) {
- M_TEST(s2);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
- }
+ emit_arithmetic_check(cd, iptr, s2);
M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
s1 = emit_load_s1(jd, iptr, EAX);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, EDX);
-
- if (checknull) {
- M_TEST(s2);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
- }
+ emit_arithmetic_check(cd, iptr, s2);
M_INTMOVE(s1, EAX); /* we need the first operand in EAX */
M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
M_OR(GET_HIGH_REG(s2), REG_ITMP3);
- M_BEQ(0);
- codegen_add_arithmeticexception_ref(cd);
+ /* XXX could be optimized */
+ emit_arithmetic_check(cd, iptr, REG_ITMP3);
bte = iptr->sx.s23.s3.bte;
md = bte->md;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
M_ILD(d, s1, OFFSET(java_arrayheader, size));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movsbl_memindex_reg(cd, OFFSET(java_bytearray, data[0]),
s1, s2, 0, d);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movzwl_memindex_reg(cd, OFFSET(java_chararray, data[0]),
s1, s2, 1, d);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movswl_memindex_reg(cd, OFFSET(java_shortarray, data[0]),
s1, s2, 1, d);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_mov_memindex_reg(cd, OFFSET(java_intarray, data[0]),
s1, s2, 2, d);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
- var = VAROP(iptr->dst);
+ var = VAROP(iptr->dst);
assert(var->flags & INMEMORY);
emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]),
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_flds_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_fldl_memindex(cd, OFFSET(java_doublearray, data[0]), s1, s2,3);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]),
s1, s2, 2, d);
emit_store_dst(jd, iptr, d);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
if (s3 >= EBP) {
/* because EBP, ESI, EDI have no xH and xL nibbles */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]),
s1, s2, 1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]),
s1, s2, 1);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
emit_mov_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]),
s1, s2, 2);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
- var = VAROP(iptr->sx.s23.s3);
+ var = VAROP(iptr->sx.s23.s3);
assert(var->flags & INMEMORY);
emit_mov_membase_reg(cd, REG_SP, var->vv.regoff * 4, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
emit_fstps_memindex(cd, OFFSET(java_floatarray, data[0]), s1, s2,2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_FTMP1);
emit_fstpl_memindex(cd, OFFSET(java_doublearray, data[0]),
s1, s2, 3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
s3 = emit_load_s3(jd, iptr, REG_ITMP3);
M_AST(s1, REG_SP, 0 * 4);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval,
OFFSET(java_bytearray, data[0]), s1, s2, 0);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval,
OFFSET(java_chararray, data[0]), s1, s2, 1);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval,
OFFSET(java_shortarray, data[0]), s1, s2, 1);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_mov_imm_memindex(cd, iptr->sx.s23.s3.constval,
OFFSET(java_intarray, data[0]), s1, s2, 2);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_mov_imm_memindex(cd,
(u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff),
OFFSET(java_longarray, data[0]), s1, s2, 3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- gen_nullptr_check(s1);
- gen_bound_check;
- }
+ emit_array_checks(cd, iptr, s1, s2);
emit_mov_imm_memindex(cd, 0,
OFFSET(java_objectarray, data[0]), s1, s2, 2);
break;
case ICMD_GETFIELD: /* .., objectref. ==> ..., value */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_field *uf = iptr->sx.s23.s3.uf;
case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
/* must be done here because of code patching */
/* following NOP) */
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
- gen_nullptr_check(s1);
+ emit_nullpointer_check(cd, iptr, s1);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
unresolved_field *uf = iptr->sx.s23.s3.uf;
M_JMP(REG_ITMP3);
break;
- case ICMD_INLINE_GOTO:
-#if 0
- M_COPY(src, iptr->dst.var);
-#endif
- /* FALLTHROUGH! */
-
case ICMD_GOTO: /* ... ==> ... */
case ICMD_RET: /* ... ==> ... */
case ICMD_IRETURN: /* ..., retvalue ==> ... */
- /* handle replacement point */
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
-
+ REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_RESULT);
M_INTMOVE(s1, REG_RESULT);
goto nowperformreturn;
case ICMD_LRETURN: /* ..., retvalue ==> ... */
- /* handle replacement point */
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
-
+ REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
M_LNGMOVE(s1, REG_RESULT_PACKED);
goto nowperformreturn;
case ICMD_ARETURN: /* ..., retvalue ==> ... */
- /* handle replacement point */
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
-
+ REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_RESULT);
M_INTMOVE(s1, REG_RESULT);
case ICMD_FRETURN: /* ..., retvalue ==> ... */
case ICMD_DRETURN:
- /* handle replacement point */
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
-
+ REPLACEMENT_POINT_RETURN(cd, iptr);
s1 = emit_load_s1(jd, iptr, REG_FRESULT);
goto nowperformreturn;
case ICMD_RETURN: /* ... ==> ... */
- /* handle replacement point */
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+ REPLACEMENT_POINT_RETURN(cd, iptr);
nowperformreturn:
{
p = cd->stackframesize;
#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
+ emit_verbosecall_exit(jd);
#endif
#if defined(ENABLE_THREADS)
case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
case ICMD_INVOKEINTERFACE:
- /* handle replacement point */
-
- replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
- replacementpoint++;
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
- cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+ REPLACEMENT_POINT_INVOKE(cd, iptr);
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
case ICMD_INVOKEVIRTUAL:
M_ALD(REG_ITMP1, REG_SP, 0 * 4);
- gen_nullptr_check(REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
if (lm == NULL) {
unresolved_method *um = iptr->sx.s23.s3.um;
case ICMD_INVOKEINTERFACE:
M_ALD(REG_ITMP1, REG_SP, 0 * 4);
- gen_nullptr_check(REG_ITMP1);
+ emit_nullpointer_check(cd, iptr, s1);
if (lm == NULL) {
unresolved_method *um = iptr->sx.s23.s3.um;
/* store size of call code in replacement point */
- if (iptr->opc != ICMD_BUILTIN)
- replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)
- - (ptrint) replacementpoint[-1].pc;
+ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
/* d contains return type */
emit_exception_stubs(jd);
emit_patcher_stubs(jd);
- emit_replacement_stubs(jd);
+ REPLACEMENT_EMIT_STUBS(jd);
codegen_finish(jd);
{
u1 *s; /* memory to hold the stub */
ptrint *d;
- codeinfo *code;
codegendata *cd;
s4 dumpsize;
cd = DNEW(codegendata);
cd->mcodeptr = s;
- /* Store the codeinfo pointer in the same place as in the
- methodheader for compiled methods. */
-
- code = code_codeinfo_new(m);
+ /* The codeinfo pointer is actually a pointer to the
+ methodinfo. This fakes a codeinfo structure. */
d[0] = (ptrint) asm_call_jit_compiler;
d[1] = (ptrint) m;
- d[2] = (ptrint) code;
+ d[2] = (ptrint) &d[1]; /* fake code->m */
/* code for the stub */
M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_enter(jd);
+ emit_verbosecall_enter(jd);
#endif
/* get function address (this must happen before the stackframeinfo) */
}
#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
- emit_verbosecall_exit(jd);
+ emit_verbosecall_exit(jd);
#endif
/* remove native stackframe info */