X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fmips%2Fcodegen.c;h=5d323820121d98bcf922afe2e90416c52f141d0c;hb=86531c70a21a4616bdc6424a9cb906a9712bed32;hp=e81137a706df83df1b9f9581ae93a76d7d8efd1a;hpb=fd19b6bdd0d4941183c469bfad32dae65c8370b4;p=cacao.git diff --git a/src/vm/jit/mips/codegen.c b/src/vm/jit/mips/codegen.c index e81137a70..5d3238201 100644 --- a/src/vm/jit/mips/codegen.c +++ b/src/vm/jit/mips/codegen.c @@ -1,6 +1,6 @@ /* src/vm/jit/mips/codegen.c - machine code generator for MIPS - Copyright (C) 1996-2005, 2006, 2007, 2008 + Copyright (C) 1996-2005, 2006, 2007, 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -35,7 +35,7 @@ #include "vm/jit/mips/arch.h" #include "vm/jit/mips/codegen.h" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/localref.hpp" #include "native/native.hpp" @@ -55,109 +55,30 @@ #include "vm/jit/emit-common.hpp" #include "vm/jit/jit.hpp" #include "vm/jit/linenumbertable.hpp" +#include "vm/jit/parse.hpp" #include "vm/jit/patcher-common.hpp" #include "vm/jit/reg.h" -#include "vm/jit/replace.hpp" -#include "vm/jit/trap.h" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.hpp" -#if defined(ENABLE_LSRA) -# include "vm/jit/allocator/lsra.h" -#endif - - -/* codegen_emit **************************************************************** - - Generates machine code. -*******************************************************************************/ - -bool codegen_emit(jitdata *jd) +/** + * Generates machine code for the method prolog. + */ +void codegen_emit_prolog(jitdata* jd) { - methodinfo *m; - codeinfo *code; - codegendata *cd; - registerdata *rd; - s4 len, s1, s2, s3, d, disp; - varinfo *var; - basicblock *bptr; - instruction *iptr; - u2 currentline; - constant_classref *cr; - unresolved_class *uc; - methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ - unresolved_method *um; - builtintable_entry *bte; - methoddesc *md; - fieldinfo *fi; - unresolved_field *uf; - s4 fieldtype; - s4 varindex; - - /* get required compiler data */ - - m = jd->m; - code = jd->code; - cd = jd->cd; - rd = jd->rd; - - /* prevent compiler warnings */ - - s1 = 0; - d = 0; - fieldtype = 0; - lm = NULL; - um = NULL; - bte = NULL; - currentline = 0; - uf = NULL; - - { - s4 i, p, t, l; - s4 savedregs_num; - - savedregs_num = code_is_leafmethod(code) ? 0 : 1; /* space to save the RA */ - - /* space to save used callee saved registers */ - - savedregs_num += (INT_SAV_CNT - rd->savintreguse); - savedregs_num += (FLT_SAV_CNT - rd->savfltreguse); - - cd->stackframesize = rd->memuse + savedregs_num; - -#if defined(ENABLE_THREADS) - /* space to save argument of monitor_enter */ - - if (checksync && code_is_synchronized(code)) { -# if SIZEOF_VOID_P == 8 - cd->stackframesize++; -# else - rd->memuse++; - cd->stackframesize += 2; -# endif - } -#endif - - /* keep stack 16-byte aligned */ - - if (cd->stackframesize & 1) - cd->stackframesize++; - - /* create method header */ - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - - code->synchronizedoffset = rd->memuse * 8; - - /* REMOVEME: We still need it for exception handling in assembler. */ - - if (code_is_leafmethod(code)) - (void) dseg_add_unique_s4(cd, 1); - else - (void) dseg_add_unique_s4(cd, 0); - - (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ - (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ + varinfo* var; + methoddesc* md; + int32_t s1; + int32_t p, t, l; + int32_t varindex; + int i; + + // Get required compiler data. + methodinfo* m = jd->m; + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; /* create stack frame (if necessary) */ @@ -237,9 +158,9 @@ bool codegen_emit(jitdata *jd) if (!md->params[p].inmemory) { if (!(var->flags & INMEMORY)) { if (IS_2_WORD_TYPE(t)) - M_DBLMOVE(s1, var->vv.regoff); + emit_dmove(cd, s1, var->vv.regoff); else - M_FLTMOVE(s1, var->vv.regoff); + emit_fmove(cd, s1, var->vv.regoff); } else { if (IS_2_WORD_TYPE(t)) @@ -260,181 +181,88 @@ bool codegen_emit(jitdata *jd) } } } +} - /* call monitorenter function */ - -#if defined(ENABLE_THREADS) - if (checksync && code_is_synchronized(code)) { - /* stack offset for monitor argument */ - - s1 = rd->memuse; - -# if !defined(NDEBUG) - if (opt_verbosecall) { - M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8); - - for (p = 0; p < INT_ARG_CNT; p++) - M_AST(abi_registers_integer_argument[p], REG_SP, p * 8); - - for (p = 0; p < FLT_ARG_CNT; p++) - M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); - s1 += INT_ARG_CNT + FLT_ARG_CNT; - } -# endif +/** + * Generates machine code for the method epilog. + */ +void codegen_emit_epilog(jitdata* jd) +{ + int32_t p; + int i; - /* get correct lock object */ + // Get required compiler data. + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, &m->clazz->object.header); - M_ALD(REG_A0, REG_PV, disp); - disp = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD(REG_ITMP3, REG_PV, disp); - } - else { -/* emit_nullpointer_check(cd, iptr, REG_A0); */ - M_BNEZ(REG_A0, 2); - disp = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */ - M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException); - } - - M_JSR(REG_RA, REG_ITMP3); - M_AST(REG_A0, REG_SP, s1 * 8); /* branch delay */ + p = cd->stackframesize; -# if !defined(NDEBUG) - if (opt_verbosecall) { - for (p = 0; p < INT_ARG_CNT; p++) - M_ALD(abi_registers_integer_argument[p], REG_SP, p * 8); + /* restore return address */ - for (p = 0; p < FLT_ARG_CNT; p++) - M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); + if (!code_is_leafmethod(code)) { + p--; M_ALD(REG_RA, REG_SP, p * 8); + } + /* restore saved registers */ - M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8); - } -# endif + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_ALD(rd->savintregs[i], REG_SP, p * 8); } -#endif + for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { + p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); } -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#endif - - /* end of header generation */ - - /* create replacement points */ - - REPLACEMENT_POINTS_INIT(cd, jd); + /* deallocate stack and return */ - /* walk through all basic blocks */ + if (cd->stackframesize) { + int32_t lo, hi, disp; - for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) { + disp = cd->stackframesize * 8; + lo = (short) (disp); + hi = (short) (((disp) - lo) >> 16); - /* handle replacement points */ - - REPLACEMENT_POINT_BLOCK_START(cd, bptr); - - /* store relative start of block */ - - bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase); - - if (bptr->flags >= BBREACHED) { - /* branch resolving */ - - codegen_resolve_branchrefs(cd, bptr); - - /* copy interface registers to their destination */ - - len = bptr->indepth; - MCODECHECK(64+len); -#if defined(ENABLE_LSRA) - if (opt_lsra) { - while (len) { - len--; - src = bptr->invars[len]; - if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) { - /* d = reg_of_var(m, src, REG_ITMP1); */ - if (!(src->flags & INMEMORY)) - d = src->vv.regoff; - else - d = REG_ITMP1; - M_INTMOVE(REG_ITMP1, d); - emit_store(jd, NULL, src, d); - } - } + if (hi == 0) { + M_RET(REG_RA); + M_AADD_IMM(REG_SP, lo, REG_SP); /* delay slot */ } else { -#endif - while (len) { - len--; - var = VAR(bptr->invars[len]); - if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) { - d = codegen_reg_of_var(0, var, REG_ITMP1); - M_INTMOVE(REG_ITMP1, d); - emit_store(jd, NULL, var, d); - } - else { - assert((var->flags & INOUT)); - } - } -#if defined(ENABLE_LSRA) + M_LUI(REG_ITMP3,hi); + M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3); + M_RET(REG_RA); + M_AADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */ } -#endif - /* walk through all instructions */ - - len = bptr->icount; -/* currentline = 0; */ - - for (iptr = bptr->iinstr; len > 0; len--, iptr++) { - if (iptr->line != currentline) { - linenumbertable_list_entry_add(cd, iptr->line); - currentline = iptr->line; - } - - MCODECHECK(64); /* an instruction usually needs < 64 words */ - - switch (iptr->opc) { - - case ICMD_NOP: /* ... ==> ... */ - case ICMD_POP: /* ..., value ==> ... */ - case ICMD_POP2: /* ..., value, value ==> ... */ - break; - - case ICMD_INLINE_START: - - REPLACEMENT_POINT_INLINE_START(cd, iptr); - break; - - case ICMD_INLINE_BODY: - - REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - linenumbertable_list_entry_add_inline_start(cd, iptr); - linenumbertable_list_entry_add(cd, iptr->line); - break; - - case ICMD_INLINE_END: - linenumbertable_list_entry_add_inline_end(cd, iptr); - linenumbertable_list_entry_add(cd, iptr->line); - break; + } else { + M_RET(REG_RA); + M_NOP; + } +} - case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - emit_nullpointer_check(cd, iptr, s1); - break; +/** + * Generates machine code for one ICMD. + */ +void codegen_emit_instruction(jitdata* jd, instruction* iptr) +{ + varinfo* var; + builtintable_entry* bte; + methodinfo* lm; // Local methodinfo for ICMD_INVOKE*. + unresolved_method* um; + fieldinfo* fi; + unresolved_field* uf; + int32_t fieldtype; + int32_t s1, s2, s3, d; + int32_t disp; + + // Get required compiler data. + codeinfo* code = jd->code; + codegendata* cd = jd->cd; + + switch (iptr->opc) { /* constant operations ************************************************/ - case ICMD_ICONST: /* ... ==> ..., constant */ - - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - ICONST(d, iptr->sx.val.i); - emit_store_dst(jd, iptr, d); - break; - case ICMD_LCONST: /* ... ==> ..., constant */ #if SIZEOF_VOID_P == 8 @@ -467,7 +295,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - cr = iptr->sx.val.c.ref; + constant_classref *cr = iptr->sx.val.c.ref; disp = dseg_add_unique_address(cd, cr); patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, @@ -487,29 +315,6 @@ bool codegen_emit(jitdata *jd) break; - /* load/store/copy/move operations ************************************/ - - case ICMD_ILOAD: /* ... ==> ..., content of local variable */ - case ICMD_LLOAD: - case ICMD_ALOAD: - case ICMD_FLOAD: - case ICMD_DLOAD: - case ICMD_ISTORE: /* ..., value ==> ... */ - case ICMD_LSTORE: - case ICMD_FSTORE: - case ICMD_DSTORE: - case ICMD_COPY: - case ICMD_MOVE: - - emit_copy(jd, iptr); - break; - - case ICMD_ASTORE: - if (!(iptr->flags.bits & INS_FLAG_RETADDR)) - emit_copy(jd, iptr); - break; - - /* integer operations *************************************************/ case ICMD_INEG: /* ..., value ==> ..., - value */ @@ -672,19 +477,19 @@ bool codegen_emit(jitdata *jd) M_IADD(GET_HIGH_REG(s1), REG_ITMP3, GET_HIGH_REG(d)); } else if ((iptr->sx.val.l >= (-32768 + 1)) && (iptr->sx.val.l < 0)) { - s1 = emit_load_s1_low(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); M_ISUB_IMM(s1, -(iptr->sx.val.l), GET_LOW_REG(d)); M_CMPULT_IMM(GET_LOW_REG(d), iptr->sx.val.l, REG_ITMP3); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); M_ISUB_IMM(s1, 1, GET_HIGH_REG(d)); M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d)); } else { - ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff); + ICONST(REG_ITMP1, iptr->sx.val.l & 0xffffffff); s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); - M_IADD(s1, REG_ITMP2, GET_LOW_REG(d)); + M_IADD(s1, REG_ITMP1, GET_LOW_REG(d)); M_CMPULT(GET_LOW_REG(d), s1, REG_ITMP3); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); M_IADD(s1, REG_ITMP3, GET_HIGH_REG(d)); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d)); @@ -729,7 +534,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); M_ISUB(s1, s2, GET_HIGH_REG(d)); s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); - s2 = emit_load_s2_low(jd, iptr, REG_ITMP1); + s2 = emit_load_s2_low(jd, iptr, REG_ITMP2); M_CMPULT(s1, s2, REG_ITMP3); M_ISUB(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d)); /* if s1 is equal to REG_ITMP3 we have to reload it, since @@ -757,10 +562,10 @@ bool codegen_emit(jitdata *jd) #else d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 32768)) { - s1 = emit_load_s1_low(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_low(jd, iptr, REG_ITMP1); M_ISUB_IMM(s1, iptr->sx.val.l, GET_LOW_REG(d)); M_CMPULT_IMM(GET_LOW_REG(d), -(iptr->sx.val.l), REG_ITMP3); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); M_ISUB_IMM(s1, 1, GET_HIGH_REG(d)); M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d)); } @@ -771,11 +576,11 @@ bool codegen_emit(jitdata *jd) M_IADD(GET_HIGH_REG(s1), REG_ITMP3, GET_HIGH_REG(d)); } else { - ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff); + ICONST(REG_ITMP1, iptr->sx.val.l & 0xffffffff); s1 = emit_load_s1_low(jd, iptr, REG_ITMP3); - M_ISUB(s1, REG_ITMP2, GET_LOW_REG(d)); - M_CMPULT(s1, REG_ITMP2, REG_ITMP3); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + M_ISUB(s1, REG_ITMP1, GET_LOW_REG(d)); + M_CMPULT(s1, REG_ITMP1, REG_ITMP3); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); M_ISUB(s1, REG_ITMP3, GET_HIGH_REG(d)); ICONST(REG_ITMP3, iptr->sx.val.l >> 32); M_ISUB(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d)); @@ -975,12 +780,12 @@ bool codegen_emit(jitdata *jd) M_AND_IMM(d, iptr->sx.val.i, d); } else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_AND(s1, REG_ITMP2, d); + ICONST(REG_ITMP3, iptr->sx.val.i); + M_AND(s1, REG_ITMP3, d); M_BGEZ(s1, 4); M_NOP; M_ISUB(REG_ZERO, s1, d); - M_AND(d, REG_ITMP2, d); + M_AND(d, REG_ITMP3, d); } M_ISUB(REG_ZERO, d, d); emit_store_dst(jd, iptr, d); @@ -1205,7 +1010,7 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); M_AND(s1, s2, GET_LOW_REG(d)); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); M_AND(s1, s2, GET_HIGH_REG(d)); #endif @@ -1277,7 +1082,7 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); M_OR(s1, s2, GET_LOW_REG(d)); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); M_OR(s1, s2, GET_HIGH_REG(d)); #endif @@ -1349,7 +1154,7 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2_low(jd, iptr, REG_ITMP3); d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); M_XOR(s1, s2, GET_LOW_REG(d)); - s1 = emit_load_s1_high(jd, iptr, REG_ITMP2); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); s2 = emit_load_s2_high(jd, iptr, REG_ITMP3); M_XOR(s1, s2, GET_HIGH_REG(d)); #endif @@ -2245,134 +2050,80 @@ bool codegen_emit(jitdata *jd) case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, REG_ITMP1_XPTR); - -#ifdef ENABLE_VERIFIER - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uc = iptr->sx.s23.s2.uc; - - patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); - } -#endif /* ENABLE_VERIFIER */ - + // Some processor implementations seem to have a problem when using + // the JALR instruction with (reg_dest == reg_src), so avoid that. disp = dseg_add_functionptr(cd, asm_handle_exception); - M_ALD(REG_ITMP2, REG_PV, disp); - M_JSR(REG_ITMP2_XPC, REG_ITMP2); + M_ALD(REG_ITMP3, REG_PV, disp); + M_JSR(REG_ITMP2_XPC, REG_ITMP3); M_NOP; M_NOP; /* nop ensures that XPC is less than the end */ /* of basic block */ - ALIGNCODENOP; - break; - - case ICMD_GOTO: /* ... ==> ... */ - case ICMD_RET: /* ... ==> ... */ - - emit_br(cd, iptr->dst.block); - ALIGNCODENOP; - break; - - case ICMD_JSR: /* ... ==> ... */ - - emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); - ALIGNCODENOP; - break; - - case ICMD_IFNULL: /* ..., value ==> ... */ - case ICMD_IFNONNULL: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE); break; case ICMD_IFEQ: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_beqz(cd, iptr->dst.block, s1); - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - emit_beq(cd, iptr->dst.block, s1, REG_ITMP2); - } + ICONST(REG_ITMP2, iptr->sx.val.i); + emit_beq(cd, iptr->dst.block, s1, REG_ITMP2); break; case ICMD_IFLT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_bltz(cd, iptr->dst.block, s1); + if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) + M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1); else { - if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) - M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1); - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMPLT(s1, REG_ITMP2, REG_ITMP1); - } - emit_bnez(cd, iptr->dst.block, REG_ITMP1); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMPLT(s1, REG_ITMP2, REG_ITMP1); } + emit_bnez(cd, iptr->dst.block, REG_ITMP1); break; case ICMD_IFLE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_blez(cd, iptr->dst.block, s1); + if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) { + M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1); + emit_bnez(cd, iptr->dst.block, REG_ITMP1); + } else { - if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) { - M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1); - emit_bnez(cd, iptr->dst.block, REG_ITMP1); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMPGT(s1, REG_ITMP2, REG_ITMP1); - emit_beqz(cd, iptr->dst.block, REG_ITMP1); - } + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMPGT(s1, REG_ITMP2, REG_ITMP1); + emit_beqz(cd, iptr->dst.block, REG_ITMP1); } break; case ICMD_IFNE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_bnez(cd, iptr->dst.block, s1); - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - emit_bne(cd, iptr->dst.block, s1, REG_ITMP2); - } + ICONST(REG_ITMP2, iptr->sx.val.i); + emit_bne(cd, iptr->dst.block, s1, REG_ITMP2); break; case ICMD_IFGT: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_bgtz(cd, iptr->dst.block, s1); + if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) { + M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1); + emit_beqz(cd, iptr->dst.block, REG_ITMP1); + } else { - if ((iptr->sx.val.i >= -32769) && (iptr->sx.val.i <= 32766)) { - M_CMPLT_IMM(s1, iptr->sx.val.i + 1, REG_ITMP1); - emit_beqz(cd, iptr->dst.block, REG_ITMP1); - } - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMPGT(s1, REG_ITMP2, REG_ITMP1); - emit_bnez(cd, iptr->dst.block, REG_ITMP1); - } + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMPGT(s1, REG_ITMP2, REG_ITMP1); + emit_bnez(cd, iptr->dst.block, REG_ITMP1); } break; case ICMD_IFGE: /* ..., value ==> ... */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); - if (iptr->sx.val.i == 0) - emit_bgez(cd, iptr->dst.block, s1); + if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) + M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1); else { - if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) - M_CMPLT_IMM(s1, iptr->sx.val.i, REG_ITMP1); - else { - ICONST(REG_ITMP2, iptr->sx.val.i); - M_CMPLT(s1, REG_ITMP2, REG_ITMP1); - } - emit_beqz(cd, iptr->dst.block, REG_ITMP1); + ICONST(REG_ITMP2, iptr->sx.val.i); + M_CMPLT(s1, REG_ITMP2, REG_ITMP1); } + emit_beqz(cd, iptr->dst.block, REG_ITMP1); break; case ICMD_IF_LEQ: /* ..., value ==> ... */ @@ -2586,8 +2337,6 @@ bool codegen_emit(jitdata *jd) #endif break; - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */ #if SIZEOF_VOID_P == 8 case ICMD_IF_LCMPEQ: #endif @@ -2611,8 +2360,6 @@ bool codegen_emit(jitdata *jd) break; #endif - case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */ #if SIZEOF_VOID_P == 8 case ICMD_IF_LCMPNE: #endif @@ -2747,171 +2494,6 @@ bool codegen_emit(jitdata *jd) break; #endif - case ICMD_IRETURN: /* ..., retvalue ==> ... */ -#if SIZEOF_VOID_P == 8 - case ICMD_LRETURN: -#endif - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT); - M_INTMOVE(s1, REG_RESULT); - goto nowperformreturn; - - case ICMD_ARETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT); - M_INTMOVE(s1, REG_RESULT); - -#ifdef ENABLE_VERIFIER - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uc = iptr->sx.s23.s2.uc; - - patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); - } -#endif /* ENABLE_VERIFIER */ - goto nowperformreturn; - -#if SIZEOF_VOID_P == 4 - case ICMD_LRETURN: /* ..., retvalue ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED); - M_LNGMOVE(s1, REG_RESULT_PACKED); - goto nowperformreturn; -#endif - - case ICMD_FRETURN: /* ..., retvalue ==> ... */ - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_FRESULT); - M_FLTMOVE(s1, REG_FRESULT); - goto nowperformreturn; - - case ICMD_DRETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_FRESULT); - M_DBLMOVE(s1, REG_FRESULT); - goto nowperformreturn; - - case ICMD_RETURN: /* ... ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - -nowperformreturn: - { - s4 i, p; - - p = cd->stackframesize; - -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif - -#if defined(ENABLE_THREADS) - if (checksync && code_is_synchronized(code)) { - disp = dseg_add_functionptr(cd, LOCK_monitor_exit); - M_ALD(REG_ITMP3, REG_PV, disp); - - /* we need to save the proper return value */ - - switch (iptr->opc) { - case ICMD_IRETURN: - case ICMD_ARETURN: -#if SIZEOF_VOID_P == 8 - case ICMD_LRETURN: -#endif - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - M_JSR(REG_RA, REG_ITMP3); - M_AST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */ - break; -#if SIZEOF_VOID_P == 4 - case ICMD_LRETURN: - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - M_LST(REG_RESULT_PACKED, REG_SP, rd->memuse * 8); - M_JSR(REG_RA, REG_ITMP3); - M_NOP; - break; -#endif - case ICMD_FRETURN: - case ICMD_DRETURN: - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - M_JSR(REG_RA, REG_ITMP3); - M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */ - break; - case ICMD_RETURN: - M_JSR(REG_RA, REG_ITMP3); - M_ALD(REG_A0, REG_SP, rd->memuse * 8); /* delay*/ - break; - } - - /* and now restore the proper return value */ - - switch (iptr->opc) { - case ICMD_IRETURN: - case ICMD_ARETURN: -#if SIZEOF_VOID_P == 8 - case ICMD_LRETURN: -#endif - M_ALD(REG_RESULT, REG_SP, rd->memuse * 8); - break; -#if SIZEOF_VOID_P == 4 - case ICMD_LRETURN: - M_LLD(REG_RESULT_PACKED, REG_SP, rd->memuse * 8); - break; -#endif - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8); - break; - } - } -#endif - - /* restore return address */ - - if (!code_is_leafmethod(code)) { - p--; M_ALD(REG_RA, REG_SP, p * 8); - } - - /* restore saved registers */ - - for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_ALD(rd->savintregs[i], REG_SP, p * 8); - } - for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { - p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); - } - - /* deallocate stack and return */ - - if (cd->stackframesize) { - s4 lo, hi; - - disp = cd->stackframesize * 8; - lo = (short) (disp); - hi = (short) (((disp) - lo) >> 16); - - if (hi == 0) { - M_RET(REG_RA); - M_AADD_IMM(REG_SP, lo, REG_SP); /* delay slot */ - } else { - M_LUI(REG_ITMP3,hi); - M_AADD_IMM(REG_ITMP3,lo,REG_ITMP3); - M_RET(REG_RA); - M_AADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */ - } - - } else { - M_RET(REG_RA); - M_NOP; - } - - ALIGNCODENOP; - } - break; - - case ICMD_TABLESWITCH: /* ..., index ==> ... */ { s4 i, l; @@ -2961,261 +2543,112 @@ nowperformreturn: ALIGNCODENOP; break; + case ICMD_BUILTIN: + bte = iptr->sx.s23.s3.bte; + if (bte->stub == NULL) { + disp = dseg_add_functionptr(cd, bte->fp); + M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */ - case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ - { - s4 i; - lookup_target_t *lookup; + /* generate the actual call */ - lookup = iptr->dst.lookup; + /* TWISTI: i actually don't know the reason for using + REG_ITMP3 here instead of REG_PV. */ - i = iptr->sx.s23.s2.lookupcount; - - MCODECHECK((i<<2)+8); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - while (--i >= 0) { - ICONST(REG_ITMP2, lookup->value); - emit_beq(cd, lookup->target.block, s1, REG_ITMP2); - ++lookup; - } - - emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); - ALIGNCODENOP; - break; + M_JSR(REG_RA, REG_ITMP3); + M_NOP; } + else { + disp = dseg_add_functionptr(cd, bte->stub); + M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */ + /* generate the actual call */ - case ICMD_BUILTIN: /* ..., arg1 ==> ... */ - - bte = iptr->sx.s23.s3.bte; - md = bte->md; - goto gen_method; - - case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ - - case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */ - case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ - case ICMD_INVOKEINTERFACE: + M_JSR(REG_RA, REG_PV); + M_NOP; + } + break; - REPLACEMENT_POINT_INVOKE(cd, iptr); + case ICMD_INVOKESPECIAL: + emit_nullpointer_check(cd, iptr, REG_A0); + /* fall through */ + case ICMD_INVOKESTATIC: if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - lm = NULL; um = iptr->sx.s23.s3.um; - md = um->methodref->parseddesc.md; + disp = dseg_add_unique_address(cd, um); + + patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, + disp); } else { lm = iptr->sx.s23.s3.fmiref->p.method; - um = NULL; - md = lm->parseddesc; + disp = dseg_add_address(cd, lm->stubroutine); } -gen_method: - s3 = md->paramcount; - - MCODECHECK((s3 << 1) + 64); + M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */ - /* copy arguments to registers or stack location */ + /* generate the actual call */ - for (s3 = s3 - 1; s3 >= 0; s3--) { - var = VAR(iptr->sx.s23.s2.args[s3]); - d = md->params[s3].regoff; + M_JSR(REG_RA, REG_PV); + M_NOP; + break; - if (var->flags & PREALLOC) - continue; + case ICMD_INVOKEVIRTUAL: + emit_nullpointer_check(cd, iptr, REG_A0); - if (IS_INT_LNG_TYPE(var->type)) { -#if SIZEOF_VOID_P == 8 - if (!md->params[s3].inmemory) { - s1 = emit_load(jd, iptr, var, d); - M_INTMOVE(s1, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_ITMP1); - M_LST(s1, REG_SP, d); - } -#else - if (!md->params[s3].inmemory) { - s1 = emit_load(jd, iptr, var, d); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); - if (IS_2_WORD_TYPE(var->type)) - M_LNGMOVE(s1, d); - else - M_INTMOVE(s1, d); - } - else { - if (IS_2_WORD_TYPE(var->type)) { - s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED); - M_LST(s1, REG_SP, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_ITMP1); - M_IST(s1, REG_SP, d); - } - } -#endif - } - else { - if (!md->params[s3].inmemory) { - s1 = emit_load(jd, iptr, var, d); - if (IS_2_WORD_TYPE(var->type)) - M_DBLMOVE(s1, d); - else - M_FLTMOVE(s1, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_FTMP1); - if (IS_2_WORD_TYPE(var->type)) - M_DST(s1, REG_SP, d); - else - M_FST(s1, REG_SP, d); - } - } + s1 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, table[0]) + + sizeof(methodptr) * lm->vftblindex; } - switch (iptr->opc) { - case ICMD_BUILTIN: - if (bte->stub == NULL) { - disp = dseg_add_functionptr(cd, bte->fp); - M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */ - - /* generate the actual call */ - - /* TWISTI: i actually don't know the reason for using - REG_ITMP3 here instead of REG_PV. */ - - M_JSR(REG_RA, REG_ITMP3); - M_NOP; - } - else { - disp = dseg_add_functionptr(cd, bte->stub); - M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */ - - /* generate the actual call */ - - M_JSR(REG_RA, REG_PV); - M_NOP; - } - - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_RA, -disp); - break; - - case ICMD_INVOKESPECIAL: - emit_nullpointer_check(cd, iptr, REG_A0); - /* fall through */ - - case ICMD_INVOKESTATIC: - if (lm == NULL) { - disp = dseg_add_unique_address(cd, um); - - patcher_add_patch_ref(jd, PATCHER_invokestatic_special, um, - disp); - } - else - disp = dseg_add_address(cd, lm->stubroutine); - - M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */ - - /* generate the actual call */ - - M_JSR(REG_RA, REG_PV); - M_NOP; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_RA, -disp); - break; - - case ICMD_INVOKEVIRTUAL: - emit_nullpointer_check(cd, iptr, REG_A0); - - if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); - - s1 = 0; - } - else - s1 = OFFSET(vftbl_t, table[0]) + - sizeof(methodptr) * lm->vftblindex; - - /* implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - M_ALD(REG_PV, REG_METHODPTR, s1); - - /* generate the actual call */ - - M_JSR(REG_RA, REG_PV); - M_NOP; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_RA, -disp); - break; - - case ICMD_INVOKEINTERFACE: - emit_nullpointer_check(cd, iptr, REG_A0); + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD(REG_PV, REG_METHODPTR, s1); - if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); + /* generate the actual call */ - s1 = 0; - s2 = 0; - } - else { - s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr*) * lm->clazz->index; + M_JSR(REG_RA, REG_PV); + M_NOP; + break; - s2 = sizeof(methodptr) * (lm - lm->clazz->methods); - } + case ICMD_INVOKEINTERFACE: + emit_nullpointer_check(cd, iptr, REG_A0); - /* implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - M_ALD(REG_METHODPTR, REG_METHODPTR, s1); - M_ALD(REG_PV, REG_METHODPTR, s2); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); - /* generate the actual call */ + s1 = 0; + s2 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, interfacetable[0]) - + sizeof(methodptr*) * lm->clazz->index; - M_JSR(REG_RA, REG_PV); - M_NOP; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - disp = (s4) (cd->mcodeptr - cd->mcodebase); - M_LDA(REG_PV, REG_RA, -disp); - break; + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); } - /* store return value */ + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD(REG_METHODPTR, REG_METHODPTR, s1); + M_ALD(REG_PV, REG_METHODPTR, s2); - d = md->returntype.type; + /* generate the actual call */ - if (d != TYPE_VOID) { - if (IS_INT_LNG_TYPE(d)) { -#if SIZEOF_VOID_P == 8 - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); - M_INTMOVE(REG_RESULT, s1); -#else - if (IS_2_WORD_TYPE(d)) { - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED); - M_LNGMOVE(REG_RESULT_PACKED, s1); - } - else { - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); - M_INTMOVE(REG_RESULT, s1); - } -#endif - } - else { - s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT); - if (IS_2_WORD_TYPE(d)) - M_DMOV(REG_FRESULT, s1); - else - M_FMOV(REG_FRESULT, s1); - } - emit_store_dst(jd, iptr, s1); - } + M_JSR(REG_RA, REG_PV); + M_NOP; break; + case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ if (!(iptr->flags.bits & INS_FLAG_ARRAY)) { @@ -3238,7 +2671,7 @@ gen_method: if (super == NULL) { emit_label_beqz(cd, BRANCH_LABEL_1, s1); - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_s4(cd, 0); /* super->flags */ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, @@ -3253,7 +2686,7 @@ gen_method: if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; patcher_add_patch_ref(jd, PATCHER_checkcast_interface, cr, 0); @@ -3285,7 +2718,7 @@ gen_method: if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); patcher_add_patch_ref(jd, @@ -3298,26 +2731,75 @@ gen_method: emit_label_beqz(cd, BRANCH_LABEL_5, s1); } + // The following code checks whether object s is a subtype of class t. + // Represents the following semantic: + // if (!fast_subtype_check(s->vftbl, t->vftbl)) throw; + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); M_ALD(REG_ITMP3, REG_PV, disp); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); - /* if (s1 != REG_ITMP1) { */ - /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */ - /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */ - /* #if defined(ENABLE_THREADS) */ - /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */ - /* #endif */ - /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */ - /* } else { */ - M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); - M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2); - M_ALD(REG_ITMP3, REG_PV, disp); - M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + // Represents the following semantic: + // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good; + // Preconditions: + // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl; + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_AADD(REG_ITMP1, REG_ITMP2, REG_ITMP1); + M_ALD(REG_ITMP1, REG_ITMP1, 0); + emit_label_beq(cd, BRANCH_LABEL_6, REG_ITMP1, REG_ITMP3); /* good */ + + // Represents the following semantic: + // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw; + // Preconditions: + // REG_ITMP3==t->vftbl; + if (super == NULL) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_ISUB_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bnez(cd, BRANCH_LABEL_9, REG_ITMP1); /* throw */ + } - /* } */ - M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3); - emit_classcast_check(cd, iptr, ICMD_IFNE, REG_ITMP3, s1); + // Represents the following semantic: + // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw; + // Preconditions: + // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl; + M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth)); + M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_CMPULT(REG_ITMP1, REG_ITMP3, REG_ITMP1); + emit_label_bnez(cd, BRANCH_LABEL_8, REG_ITMP1); /* throw */ + + // Represents the following semantic: + // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw; + // Preconditions: + // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth; + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_ASLL_IMM(REG_ITMP3, POINTERSHIFT, REG_ITMP3); + M_AADD(REG_ITMP2, REG_ITMP3, REG_ITMP2); + M_ALD(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P); + M_ALD(REG_ITMP3, REG_PV, disp); /* reload REG_ITMP3, was destroyed */ + emit_label_beq(cd, BRANCH_LABEL_7, REG_ITMP2, REG_ITMP3); /* good */ + + // Throw case + emit_label(cd, BRANCH_LABEL_8); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_9); + emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */ + M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException); + + // Good case + emit_label(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_6); + emit_load_s1(jd, iptr, REG_ITMP1); /* reload s1, might have been destroyed */ + } + else { + // Represents the following semantic: + // if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw; + // Preconditions: + // REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl; + M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset); + M_BEQ(REG_ITMP2, REG_ITMP3, 2); + M_NOP; /* delay slot */ + M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -3335,7 +2817,7 @@ gen_method: M_INTMOVE(s1, REG_A0); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); patcher_add_patch_ref(jd, @@ -3394,7 +2876,7 @@ gen_method: if (super == NULL) { emit_label_beqz(cd, BRANCH_LABEL_1, s1); - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_s4(cd, 0); /* super->flags */ patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, @@ -3409,10 +2891,8 @@ gen_method: if ((super == NULL) || (super->flags & ACC_INTERFACE)) { if (super == NULL) { - cr = iptr->sx.s23.s3.c.ref; - patcher_add_patch_ref(jd, PATCHER_instanceof_interface, - cr, 0); + iptr->sx.s23.s3.c.ref, 0); } else { emit_label_beqz(cd, BRANCH_LABEL_3, s1); @@ -3441,7 +2921,7 @@ gen_method: if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl, @@ -3453,16 +2933,78 @@ gen_method: emit_label_beqz(cd, BRANCH_LABEL_5, s1); } + // The following code checks whether object s is a subtype of class t. + // Represents the following semantic: + // fast_subtype_check(s->vftbl, t->vftbl)); + M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); - M_ALD(REG_ITMP2, REG_PV, disp); + M_ALD(REG_ITMP3, REG_PV, disp); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + // Represents the following semantic: + // if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true; + // Preconditions: + // REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl; + M_ILD(REG_ITMP2, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_AADD(REG_ITMP2, REG_ITMP1, REG_ITMP2); + M_ALD(REG_ITMP2, REG_ITMP2, 0); + emit_label_beq(cd, BRANCH_LABEL_6, REG_ITMP2, REG_ITMP3); /* true */ + + // Represents the following semantic: + // if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false; + // Preconditions: + // REG_ITMP3==t->vftbl; + if (super == NULL) { + M_ILD(REG_ITMP2, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_ISUB_IMM(REG_ITMP2, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP2); + emit_label_bnez(cd, BRANCH_LABEL_9, REG_ITMP2); /* false */ + } - M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); + // Represents the following semantic: + // if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false; + // Preconditions: + // REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl; + M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, subtype_depth)); + M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_CMPULT(REG_ITMP2, REG_ITMP3, REG_ITMP2); + emit_label_bnez(cd, BRANCH_LABEL_8, REG_ITMP2); /* false */ + + // Represents the following semantic: + // if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false; + // Preconditions: + // REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth; + M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow)); + M_ASLL_IMM(REG_ITMP3, POINTERSHIFT, REG_ITMP3); + M_AADD(REG_ITMP1, REG_ITMP3, REG_ITMP1); + M_ALD(REG_ITMP1, REG_ITMP1, -DISPLAY_SIZE * SIZEOF_VOID_P); + M_ALD(REG_ITMP3, REG_PV, disp); /* reload REG_ITMP3, was destroyed */ + emit_label_bne(cd, BRANCH_LABEL_7, REG_ITMP1, REG_ITMP3); /* false */ + + // True case + emit_label(cd, BRANCH_LABEL_6); + M_MOV(1, d); + if (d == REG_ITMP2) { + M_BR(2); /* branch over M_CLR */ + M_NOP; /* delay slot */ + } - M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); - M_CMPULT(REG_ITMP2, REG_ITMP1, d); - M_XOR_IMM(d, 1, d); + // False (fall-through) case + emit_label(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_8); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_9); + if (d == REG_ITMP2) + M_CLR(d); /* if d == REG_ITMP2, it was destroyed */ + } + else { + // Represents the following semantic: + // *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl; + // Preconditions: + // REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl; + M_ALD(REG_ITMP1, REG_ITMP1, super->vftbl->subtype_offset); + M_XOR(REG_ITMP1, REG_ITMP3, d); + M_CMPULT_IMM(d, 1, d); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -3506,7 +3048,7 @@ gen_method: /* is patcher function set? */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - cr = iptr->sx.s23.s3.c.ref; + constant_classref *cr = iptr->sx.s23.s3.c.ref; disp = dseg_add_unique_address(cd, NULL); patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, @@ -3543,35 +3085,8 @@ gen_method: break; default: - exceptions_throw_internalerror("Unknown ICMD %d during code generation", - iptr->opc); - return false; + vm_abort("Unknown ICMD %d during code generation", iptr->opc); } /* switch */ - - } /* for instruction */ - - MCODECHECK(64); /* XXX require smaller number? */ - - /* At the end of a basic block we may have to append some nops, - because the patcher stub calling code might be longer than the - actual instruction. So codepatching does not change the - following block unintentionally. */ - - if (cd->mcodeptr < cd->lastmcodeptr) { - while (cd->mcodeptr < cd->lastmcodeptr) - M_NOP; - } - - } /* if (bptr -> flags >= BBREACHED) */ - } /* for basic block */ - - /* generate traps */ - - emit_patcher_traps(jd); - - /* everything's ok */ - - return true; } @@ -3633,11 +3148,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s M_LDA(REG_SP, REG_SP, -cd->stackframesize * 8); /* build up stackframe */ M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); /* store RA */ -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#endif - /* save integer and float argument registers */ #if SIZEOF_VOID_P == 8 @@ -3907,11 +3417,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s break; } -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif - /* remove native stackframe info */ M_MOV(REG_SP, REG_A0);