X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fx86_64%2Fcodegen.c;h=3a4acd2ea61482646c34b3a4593e19de345d75de;hb=67702ed5605e84f33724aeee9ccf5f82ea774084;hp=f896c417df4e537592e538147c34be5d9b9d008f;hpb=2dfe2e695bdbfa04476815285f46eca4add5d327;p=cacao.git diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index f896c417d..3a4acd2ea 100644 --- a/src/vm/jit/x86_64/codegen.c +++ b/src/vm/jit/x86_64/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64 - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -29,8 +27,10 @@ #include #include +#include #include "vm/types.h" +#include "vm/os.hpp" #include "md-abi.h" @@ -38,160 +38,55 @@ #include "vm/jit/x86_64/codegen.h" #include "vm/jit/x86_64/emit.h" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "native/jni.h" -#include "native/localref.h" -#include "native/native.h" +#include "native/localref.hpp" +#include "native/native.hpp" -#include "threads/lock-common.h" +#include "threads/lock.hpp" -#include "vm/builtin.h" -#include "vm/exceptions.h" +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" -#include "vm/stringlocal.h" -#include "vm/vm.h" +#include "vm/loader.hpp" +#include "vm/options.h" +#include "vm/primitive.hpp" +#include "vm/statistics.h" +#include "vm/string.hpp" +#include "vm/vm.hpp" #include "vm/jit/abi.h" #include "vm/jit/asmpart.h" -#include "vm/jit/codegen-common.h" +#include "vm/jit/code.hpp" +#include "vm/jit/codegen-common.hpp" #include "vm/jit/dseg.h" -#include "vm/jit/emit-common.h" -#include "vm/jit/jit.h" +#include "vm/jit/emit-common.hpp" +#include "vm/jit/jit.hpp" +#include "vm/jit/linenumbertable.hpp" #include "vm/jit/methodheader.h" -#include "vm/jit/parse.h" -#include "vm/jit/patcher.h" +#include "vm/jit/parse.hpp" +#include "vm/jit/patcher-common.hpp" #include "vm/jit/reg.h" -#include "vm/jit/replace.h" -#include "vm/jit/stacktrace.h" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.hpp" -#if defined(ENABLE_LSRA) -# include "vm/jit/allocator/lsra.h" -#endif - -#include "vmcore/loader.h" -#include "vmcore/options.h" -#include "vmcore/statistics.h" - - -/* 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; - u2 currentline; - ptrint a; - varinfo *var, *dst; - basicblock *bptr; - instruction *iptr; - exception_entry *ex; - 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 */ - - d = 0; - lm = NULL; - um = NULL; - bte = NULL; - - { - s4 i, p, t, l; - s4 savedregs_num; - - savedregs_num = 0; - - /* 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 && (m->flags & ACC_SYNCHRONIZED)) - cd->stackframesize++; -#endif - - /* Keep stack of non-leaf functions 16-byte aligned for calls into - native code e.g. libc or jni (alignment problems with - movaps). */ - - if (!jd->isleafmethod || opt_verbosecall) - cd->stackframesize |= 0x1; - - /* create method header */ - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - -#if defined(ENABLE_THREADS) - /* IsSync contains the offset relative to the stack pointer for the - argument of monitor_exit used in the exception handler. Since the - offset could be zero and give a wrong meaning of the flag it is - offset by one. - */ - - if (checksync && (m->flags & ACC_SYNCHRONIZED)) - (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */ - else -#endif - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ - - (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */ - (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */ - (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */ - - (void) dseg_addlinenumbertablesize(cd); - - (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */ - - /* create exception table */ - - for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) { - dseg_add_target(cd, ex->start); - dseg_add_target(cd, ex->end); - dseg_add_target(cd, ex->handler); - (void) dseg_add_unique_address(cd, ex->catchtype.any); - } - -#if defined(ENABLE_PROFILING) - /* generate method profiling code */ - - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - - M_MOV_IMM(code, REG_ITMP3); - M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency)); - - PROFILE_CYCLE_START; - } -#endif + 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; + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; /* create stack frame (if necessary) */ @@ -246,7 +141,7 @@ bool codegen_emit(jitdata *jd) else { /* floating args */ if (!md->params[p].inmemory) { /* register arguments */ if (!IS_INMEMORY(var->flags)) - M_FLTMOVE(s1, var->vv.regoff); + emit_fmove(cd, s1, var->vv.regoff); else M_DST(s1, REG_SP, var->vv.regoff); } @@ -258,201 +153,81 @@ bool codegen_emit(jitdata *jd) } } } +} - /* save monitorenter argument */ - -#if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - /* stack offset for monitor argument */ - - s1 = rd->memuse; - - if (opt_verbosecall) { - M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); - - for (p = 0; p < INT_ARG_CNT; p++) - M_LST(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; - } - - /* decide which monitor enter function to call */ - if (m->flags & ACC_STATIC) { - M_MOV_IMM(&m->class->object.header, REG_A0); - } - else { - M_TEST(REG_A0); - M_BNE(8); - M_ALD_MEM(REG_A0, EXCEPTION_HARDWARE_NULLPOINTER); - } +/** + * Generates machine code for the method epilog. + */ +void codegen_emit_epilog(jitdata* jd) +{ + int32_t p; + int i; - M_AST(REG_A0, REG_SP, s1 * 8); - M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1); - M_CALL(REG_ITMP1); + // Get required compiler data. + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; - if (opt_verbosecall) { - for (p = 0; p < INT_ARG_CNT; p++) - M_LLD(abi_registers_integer_argument[p], REG_SP, p * 8); + p = cd->stackframesize; - for (p = 0; p < FLT_ARG_CNT; p++) - M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8); + /* restore saved registers */ - M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); - } + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_LLD(rd->savintregs[i], REG_SP, p * 8); } -#endif - -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#endif /* !defined(NDEBUG) */ - + for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) { + p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8); } - /* end of header generation */ - - /* create replacement points */ - - REPLACEMENT_POINTS_INIT(cd, jd); - - /* walk through all basic blocks */ - - for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) { - - bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase); - - if (bptr->flags >= BBREACHED) { - - /* branch resolving */ - - codegen_resolve_branchrefs(cd, bptr); - - /* handle replacement points */ - - REPLACEMENT_POINT_BLOCK_START(cd, bptr); - - /* copy interface registers to their destination */ - - len = bptr->indepth; - MCODECHECK(512); - -#if defined(ENABLE_PROFILING) - /* generate basicblock profiling code */ - - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - - M_MOV_IMM(code->bbfrequency, REG_ITMP3); - M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4); - - /* if this is an exception handler, start profiling again */ - - if (bptr->type == BBTYPE_EXH) - PROFILE_CYCLE_START; - } -#endif - -#if defined(ENABLE_LSRA) - if (opt_lsra) { - while (len) { - len--; - src = bptr->invars[len]; - if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) { - if (bptr->type == BBTYPE_EXH) { -/* d = reg_of_var(rd, src, REG_ITMP1); */ - if (!IS_INMEMORY(src->flags)) - d= src->vv.regoff; - else - d=REG_ITMP1; - M_INTMOVE(REG_ITMP1, d); - emit_store(jd, NULL, src, d); - } - } - } - - } else { -#endif - - while (len) { - len--; - var = VAR(bptr->invars[len]); - if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) { - if (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) - } -#endif - /* walk through all instructions */ - - len = bptr->icount; - currentline = 0; - - for (iptr = bptr->iinstr; len > 0; len--, iptr++) { - if (iptr->line != currentline) { - dseg_addlinenumber(cd, iptr->line); - currentline = iptr->line; - } - - 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: - - REPLACEMENT_POINT_INLINE_START(cd, iptr); - break; - - case ICMD_INLINE_BODY: - - REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - dseg_addlinenumber_inline_start(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; + /* deallocate stack */ - case ICMD_INLINE_END: + if (cd->stackframesize) + M_AADD_IMM(cd->stackframesize * 8, REG_SP); - dseg_addlinenumber_inline_end(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; + M_RET; +} - case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ +/** + * Generates a memory barrier to be used after volatile writes. It can be + * patched out later if the field turns out not to be volatile. + */ +void codegen_emit_patchable_barrier(instruction *iptr, codegendata *cd, patchref_t *pr, fieldinfo *fi) +{ + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + /* Align on word boundary */ + if ((((intptr_t) cd->mcodeptr) & 3) >= 2) + emit_nop(cd, 4 - (((intptr_t) cd->mcodeptr) & 3)); + /* Displacement for patching out MFENCE */ + pr->disp_mb = (cd->mcodeptr - cd->mcodebase - pr->mpc); + } + if (INSTRUCTION_IS_UNRESOLVED(iptr) || fi->flags & ACC_VOLATILE) + M_MFENCE; +} - 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; + varinfo* dst; + builtintable_entry* bte; + methodinfo* lm; // Local methodinfo for ICMD_INVOKE*. + unresolved_method* um; + fieldinfo* fi; + unresolved_field* uf; + patchref_t* pr; + int32_t fieldtype; + int32_t s1, s2, s3, d; + int32_t disp; + + // Get required compiler data. + 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 */ - - d = codegen_reg_of_dst(jd, iptr, REG_ITMP1); - LCONST(d, iptr->sx.val.l); - emit_store_dst(jd, iptr, d); - break; - case ICMD_FCONST: /* ... ==> ..., constant */ d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); @@ -474,48 +249,31 @@ 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); /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_aconst, cr, 0); + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, + cr, disp); /* PROFILE_CYCLE_START; */ - M_MOV_IMM(NULL, d); - - } else { - if (iptr->sx.val.anyptr == 0) + M_ALD(d, RIP, disp); + } + else { + if (iptr->sx.val.anyptr == 0) { M_CLR(d); - else - M_MOV_IMM(iptr->sx.val.anyptr, d); + } + else { + disp = dseg_add_address(cd, iptr->sx.val.anyptr); + M_ALD(d, RIP, disp); + } } emit_store_dst(jd, iptr, d); break; - /* load/store/copy/move operations ************************************/ - - case ICMD_ILOAD: /* ... ==> ..., content of local variable */ - case ICMD_ALOAD: /* s1 = local variable */ - case ICMD_LLOAD: - 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 */ @@ -1184,7 +942,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); disp = dseg_add_s4(cd, 0x80000000); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2); emit_xorps_reg_reg(cd, REG_FTMP2, d); emit_store_dst(jd, iptr, d); @@ -1195,7 +953,7 @@ bool codegen_emit(jitdata *jd) s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); disp = dseg_add_s8(cd, 0x8000000000000000); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2); emit_xorpd_reg_reg(cd, REG_FTMP2, d); emit_store_dst(jd, iptr, d); @@ -1209,7 +967,7 @@ bool codegen_emit(jitdata *jd) if (s2 == d) M_FADD(s1, d); else { - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FADD(s2, d); } emit_store_dst(jd, iptr, d); @@ -1223,7 +981,7 @@ bool codegen_emit(jitdata *jd) if (s2 == d) M_DADD(s1, d); else { - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DADD(s2, d); } emit_store_dst(jd, iptr, d); @@ -1235,10 +993,10 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); + emit_fmove(cd, s2, REG_FTMP2); s2 = REG_FTMP2; } - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FSUB(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1249,10 +1007,10 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); + emit_fmove(cd, s2, REG_FTMP2); s2 = REG_FTMP2; } - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DSUB(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1265,7 +1023,7 @@ bool codegen_emit(jitdata *jd) if (s2 == d) M_FMUL(s1, d); else { - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FMUL(s2, d); } emit_store_dst(jd, iptr, d); @@ -1279,7 +1037,7 @@ bool codegen_emit(jitdata *jd) if (s2 == d) M_DMUL(s1, d); else { - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DMUL(s2, d); } emit_store_dst(jd, iptr, d); @@ -1291,10 +1049,10 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); + emit_fmove(cd, s2, REG_FTMP2); s2 = REG_FTMP2; } - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FDIV(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1305,10 +1063,10 @@ bool codegen_emit(jitdata *jd) s2 = emit_load_s2(jd, iptr, REG_FTMP2); d = codegen_reg_of_dst(jd, iptr, REG_FTMP3); if (s2 == d) { - M_FLTMOVE(s2, REG_FTMP2); + emit_fmove(cd, s2, REG_FTMP2); s2 = REG_FTMP2; } - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DDIV(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1354,7 +1112,7 @@ bool codegen_emit(jitdata *jd) disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3); M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); + emit_fmove(cd, s1, REG_FTMP1); M_MOV_IMM(asm_builtin_f2i, REG_ITMP2); M_CALL(REG_ITMP2); M_INTMOVE(REG_RESULT, d); @@ -1370,7 +1128,7 @@ bool codegen_emit(jitdata *jd) disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3); M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); + emit_fmove(cd, s1, REG_FTMP1); M_MOV_IMM(asm_builtin_d2i, REG_ITMP2); M_CALL(REG_ITMP2); M_INTMOVE(REG_RESULT, d); @@ -1387,7 +1145,7 @@ bool codegen_emit(jitdata *jd) disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3); M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); + emit_fmove(cd, s1, REG_FTMP1); M_MOV_IMM(asm_builtin_f2l, REG_ITMP2); M_CALL(REG_ITMP2); M_INTMOVE(REG_RESULT, d); @@ -1404,7 +1162,7 @@ bool codegen_emit(jitdata *jd) disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3); M_BNE(disp); - M_FLTMOVE(s1, REG_FTMP1); + emit_fmove(cd, s1, REG_FTMP1); M_MOV_IMM(asm_builtin_d2l, REG_ITMP2); M_CALL(REG_ITMP2); M_INTMOVE(REG_RESULT, d); @@ -1494,15 +1252,6 @@ bool codegen_emit(jitdata *jd) /* memory operations **************************************************/ - case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - d = codegen_reg_of_dst(jd, iptr, REG_ITMP3); - /* implicit null-pointer check */ - M_ILD(d, s1, OFFSET(java_array_t, size)); - emit_store_dst(jd, iptr, d); - break; - case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -1744,134 +1493,6 @@ bool codegen_emit(jitdata *jd) emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray_t, data[0]), s1, s2, 3); break; - - case ICMD_GETSTATIC: /* ... ==> ..., value */ - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, NULL); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - /* must be calculated before codegen_add_patch_ref */ - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - -/* PROFILE_CYCLE_STOP; */ - - codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); - -/* PROFILE_CYCLE_START; */ - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = dseg_add_address(cd, fi->value); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - PROFILE_CYCLE_STOP; - - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); - - PROFILE_CYCLE_START; - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - } - } - - /* This approach is much faster than moving the field - address inline into a register. */ - - M_ALD(REG_ITMP1, RIP, disp); - - switch (fieldtype) { - case TYPE_INT: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ILD(d, REG_ITMP1, 0); - break; - case TYPE_LNG: - case TYPE_ADR: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_LLD(d, REG_ITMP1, 0); - break; - case TYPE_FLT: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_FLD(d, REG_ITMP1, 0); - break; - case TYPE_DBL: - d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); - M_DLD(d, REG_ITMP1, 0); - break; - } - emit_store_dst(jd, iptr, d); - break; - - case ICMD_PUTSTATIC: /* ..., value ==> ... */ - - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uf = iptr->sx.s23.s3.uf; - fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, NULL); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - /* must be calculated before codegen_add_patch_ref */ - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - -/* PROFILE_CYCLE_STOP; */ - - codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); - -/* PROFILE_CYCLE_START; */ - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = dseg_add_address(cd, fi->value); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - PROFILE_CYCLE_STOP; - - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); - - PROFILE_CYCLE_START; - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - } - } - - /* This approach is much faster than moving the field - address inline into a register. */ - - M_ALD(REG_ITMP1, RIP, disp); - - switch (fieldtype) { - case TYPE_INT: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_IST(s1, REG_ITMP1, 0); - break; - case TYPE_LNG: - case TYPE_ADR: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_LST(s1, REG_ITMP1, 0); - break; - case TYPE_FLT: - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - M_FST(s1, REG_ITMP1, 0); - break; - case TYPE_DBL: - s1 = emit_load_s1(jd, iptr, REG_FTMP1); - M_DST(s1, REG_ITMP1, 0); - break; - } - break; - case ICMD_PUTSTATICCONST: /* ... ==> ... */ /* val = value (in current instruction) */ /* following NOP) */ @@ -1879,36 +1500,31 @@ bool codegen_emit(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uf = iptr->sx.s23.s3.uf; fieldtype = uf->fieldref->parseddesc.fd->type; - disp = dseg_add_unique_address(cd, NULL); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - /* must be calculated before codegen_add_patch_ref */ - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; + disp = dseg_add_unique_address(cd, uf); /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp); + pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); /* PROFILE_CYCLE_START; */ + + fi = NULL; /* Silence compiler warning */ } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; disp = dseg_add_address(cd, fi->value); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { + //PROFILE_CYCLE_STOP; - PROFILE_CYCLE_START; + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, 0); - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; + //PROFILE_CYCLE_START; } + + pr = NULL; /* Silence compiler warning */ } /* This approach is much faster than moving the field @@ -1927,11 +1543,12 @@ bool codegen_emit(jitdata *jd) if (IS_IMM32(iptr->sx.s23.s2.constval)) M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0); else { - M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0); - M_IST_IMM(iptr->sx.s23.s2.constval >> 32, REG_ITMP1, 4); + M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2); + M_LST(REG_ITMP2, REG_ITMP1, 0); } break; } + codegen_emit_patchable_barrier(iptr, cd, pr, fi); break; case ICMD_GETFIELD: /* ... ==> ..., value */ @@ -1945,9 +1562,11 @@ bool codegen_emit(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0); + patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); /* PROFILE_CYCLE_START; */ + + fi = NULL; /* Silence compiler warning */ } else { fi = iptr->sx.s23.s3.fmiref->p.field; @@ -1974,6 +1593,9 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); M_DLD32(d, s1, disp); break; + default: + // Silence compiler warning. + d = 0; } emit_store_dst(jd, iptr, d); break; @@ -1990,14 +1612,18 @@ bool codegen_emit(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0); + pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); /* PROFILE_CYCLE_START; */ + + fi = NULL; /* Silence compiler warning */ } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; disp = fi->offset; + + pr = NULL; /* Silence compiler warning */ } /* implicit null-pointer check */ @@ -2016,6 +1642,7 @@ bool codegen_emit(jitdata *jd) M_DST32(s2, s1, disp); break; } + codegen_emit_patchable_barrier(iptr, cd, pr, fi); break; case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */ @@ -2031,14 +1658,18 @@ bool codegen_emit(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0); + pr = patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0); /* PROFILE_CYCLE_START; */ + + fi = NULL; /* Silence compiler warning */ } else { fi = iptr->sx.s23.s3.fmiref->p.field; fieldtype = fi->type; disp = fi->offset; + + pr = NULL; /* Silence compiler warning */ } /* implicit null-pointer check */ @@ -2050,11 +1681,15 @@ bool codegen_emit(jitdata *jd) case TYPE_LNG: case TYPE_ADR: case TYPE_DBL: - /* XXX why no check for IS_IMM32? */ - M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp); - M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4); + /* XXX why no check for IS_IMM32? -- probably because of the patcher */ + M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2); + if (disp) /* resolved, disp can never be 0 */ + M_LST(REG_ITMP2, s1, disp); + else /* unresolved */ + M_LST32(REG_ITMP2, s1, disp); break; } + codegen_emit_patchable_barrier(iptr, cd, pr, fi); break; @@ -2062,19 +1697,6 @@ bool codegen_emit(jitdata *jd) case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_INTMOVE(s1, REG_ITMP1_XPTR); - - PROFILE_CYCLE_STOP; - -#ifdef ENABLE_VERIFIER - if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - uc = iptr->sx.s23.s2.uc; - - codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); - } -#endif /* ENABLE_VERIFIER */ - M_CALL_IMM(0); /* passing exception pc */ M_POP(REG_ITMP2_XPC); @@ -2082,39 +1704,6 @@ bool codegen_emit(jitdata *jd) M_JMP(REG_ITMP3); 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); - M_TEST(s1); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, BRANCH_OPT_NONE); - break; - - case ICMD_IFEQ: /* ..., value ==> ... */ - case ICMD_IFLT: - case ICMD_IFLE: - case ICMD_IFNE: - case ICMD_IFGT: - case ICMD_IFGE: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_ICMP_IMM(iptr->sx.val.i, s1); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IFEQ, BRANCH_OPT_NONE); - break; - case ICMD_IF_LEQ: /* ..., value ==> ... */ case ICMD_IF_LNE: case ICMD_IF_LLT: @@ -2132,28 +1721,6 @@ bool codegen_emit(jitdata *jd) emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE); break; - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPNE: - case ICMD_IF_ICMPLT: - case ICMD_IF_ICMPGE: - case ICMD_IF_ICMPGT: - case ICMD_IF_ICMPLE: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_ICMP(s2, s1); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ICMPEQ, BRANCH_OPT_NONE); - break; - - case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ACMPNE: - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_LCMP(s2, s1); - emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_ACMPEQ, BRANCH_OPT_NONE); - break; - case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */ case ICMD_IF_LCMPNE: case ICMD_IF_LCMPLT: @@ -2167,114 +1734,6 @@ bool codegen_emit(jitdata *jd) emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE); break; - case ICMD_IRETURN: /* ..., retvalue ==> ... */ - case ICMD_LRETURN: - - 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; - - PROFILE_CYCLE_STOP; - - codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); - - PROFILE_CYCLE_START; - } -#endif /* ENABLE_VERIFIER */ - goto nowperformreturn; - - case ICMD_FRETURN: /* ..., retvalue ==> ... */ - case ICMD_DRETURN: - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_FRESULT); - M_FLTMOVE(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 /* !defined(NDEBUG) */ - -#if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - - /* we need to save the proper return value */ - switch (iptr->opc) { - case ICMD_IRETURN: - case ICMD_ARETURN: - case ICMD_LRETURN: - M_LST(REG_RESULT, REG_SP, rd->memuse * 8); - break; - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); - break; - } - - M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1); - M_CALL(REG_ITMP1); - - /* and now restore the proper return value */ - switch (iptr->opc) { - case ICMD_IRETURN: - case ICMD_ARETURN: - case ICMD_LRETURN: - M_LLD(REG_RESULT, REG_SP, rd->memuse * 8); - break; - case ICMD_FRETURN: - case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8); - break; - } - } -#endif - - /* restore saved registers */ - - for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_LLD(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 */ - - if (cd->stackframesize) - M_AADD_IMM(cd->stackframesize * 8, REG_SP); - - /* generate method profiling code */ - - PROFILE_CYCLE_STOP; - - M_RET; - } - break; - - case ICMD_TABLESWITCH: /* ..., index ==> ... */ { s4 i, l; @@ -2318,217 +1777,79 @@ nowperformreturn: } break; - - case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ - { - s4 i; - lookup_target_t *lookup; - - lookup = iptr->dst.lookup; - - i = iptr->sx.s23.s2.lookupcount; - - MCODECHECK(8 + ((7 + 6) * i) + 5); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - while (--i >= 0) { - M_ICMP_IMM(lookup->value, s1); - emit_beq(cd, lookup->target.block); - lookup++; - } - - emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); - ALIGNCODENOP; + case ICMD_BUILTIN: + bte = iptr->sx.s23.s3.bte; + if (bte->stub == NULL) { + M_MOV_IMM(bte->fp, REG_ITMP1); + } + else { + M_MOV_IMM(bte->stub, REG_ITMP1); } + M_CALL(REG_ITMP1); break; + case ICMD_INVOKESPECIAL: + emit_nullpointer_check(cd, iptr, REG_A0); + /* fall through */ - case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ - - REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr); - - 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: - - REPLACEMENT_POINT_INVOKE(cd, iptr); - + 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_functionptr(cd, lm->stubroutine); } -gen_method: - s3 = md->paramcount; - - MCODECHECK((20 * s3) + 128); - - /* copy arguments to registers or stack location */ - - for (s3 = s3 - 1; s3 >= 0; s3--) { - var = VAR(iptr->sx.s23.s2.args[s3]); - d = md->params[s3].regoff; - - /* already preallocated (ARGVAR)? */ - - if (var->flags & PREALLOC) - continue; + M_ALD(REG_ITMP2, RIP, disp); + M_CALL(REG_ITMP2); + break; - if (IS_INT_LNG_TYPE(var->type)) { - 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); - M_FLTMOVE(s1, d); - } - else { - s1 = emit_load(jd, iptr, var, REG_FTMP1); + case ICMD_INVOKEVIRTUAL: + 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_DST(s1, REG_SP, d); - else - M_FST(s1, REG_SP, d); - } - } + s1 = 0; } - - /* generate method profiling code */ - - PROFILE_CYCLE_STOP; - - switch (iptr->opc) { - case ICMD_BUILTIN: - if (bte->stub == NULL) { - M_MOV_IMM(bte->fp, REG_ITMP1); - } else { - M_MOV_IMM(bte->stub, REG_ITMP1); - } - M_CALL(REG_ITMP1); - - emit_exception_check(cd, iptr); - 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, NULL); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - - /* must be calculated before codegen_add_patch_ref */ - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - - codegen_add_patch_ref(cd, PATCHER_invokestatic_special, - um, disp); - -/* a = 0; */ - } - else { - disp = dseg_add_functionptr(cd, lm->stubroutine); - disp = disp + -((cd->mcodeptr + 7) - cd->mcodebase); - -/* a = (ptrint) lm->stubroutine; */ - } - -/* M_MOV_IMM(a, REG_ITMP2); */ - M_ALD(REG_ITMP2, RIP, disp); - M_CALL(REG_ITMP2); - break; - - case ICMD_INVOKEVIRTUAL: - if (lm == NULL) { - codegen_add_patch_ref(cd, 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_ALD32(REG_ITMP3, REG_METHODPTR, s1); - M_CALL(REG_ITMP3); - break; - - case ICMD_INVOKEINTERFACE: - if (lm == NULL) { - codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0); - - s1 = 0; - s2 = 0; - } - else { - s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr) * lm->class->index; - - s2 = sizeof(methodptr) * (lm - lm->class->methods); - } - - /* implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - M_ALD32(REG_METHODPTR, REG_METHODPTR, s1); - M_ALD32(REG_ITMP3, REG_METHODPTR, s2); - M_CALL(REG_ITMP3); - break; + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, table[0]) + + sizeof(methodptr) * lm->vftblindex; } - /* generate method profiling code */ - - PROFILE_CYCLE_START; - - /* store size of call code in replacement point */ + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD32(REG_ITMP3, REG_METHODPTR, s1); + M_CALL(REG_ITMP3); + break; - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr); + case ICMD_INVOKEINTERFACE: + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); - /* store return value */ + s1 = 0; + s2 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, interfacetable[0]) - + sizeof(methodptr) * lm->clazz->index; - switch (md->returntype.type) { - case TYPE_INT: - case TYPE_LNG: - case TYPE_ADR: - s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT); - M_INTMOVE(REG_RESULT, s1); - emit_store_dst(jd, iptr, s1); - break; - case TYPE_FLT: - case TYPE_DBL: - s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT); - M_FLTMOVE(REG_FRESULT, s1); - emit_store_dst(jd, iptr, s1); - break; - default: - /* TYPE_VOID */ - break; + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); } - break; + /* implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD32(REG_METHODPTR, REG_METHODPTR, s1); + M_ALD32(REG_ITMP3, REG_METHODPTR, s2); + M_CALL(REG_ITMP3); + break; case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ @@ -2536,23 +1857,17 @@ gen_method: /* object type cast-check */ classinfo *super; - vftbl_t *supervftbl; s4 superindex; if (INSTRUCTION_IS_UNRESOLVED(iptr)) { super = NULL; superindex = 0; - supervftbl = NULL; } else { super = iptr->sx.s23.s3.c.cls; superindex = super->index; - supervftbl = super->vftbl; } - if ((super == NULL) || !(super->flags & ACC_INTERFACE)) - CODEGEN_CRITICAL_SECTION_NEW; - s1 = emit_load_s1(jd, iptr, REG_ITMP1); /* if class is not resolved, check which code to call */ @@ -2561,7 +1876,7 @@ gen_method: M_TEST(s1); emit_label_beq(cd, BRANCH_LABEL_1); - codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0); M_IMOV_IMM(0, REG_ITMP2); /* super->flags */ @@ -2580,7 +1895,7 @@ gen_method: M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); if (super == NULL) { - codegen_add_patch_ref(cd, PATCHER_checkcast_interface, + patcher_add_patch_ref(jd, PATCHER_checkcast_interface, iptr->sx.s23.s3.c.ref, 0); } @@ -2607,50 +1922,59 @@ gen_method: if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); + + constant_classref *cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, cr); + + patcher_add_patch_ref(jd, + PATCHER_resolve_classref_to_vftbl, + cr, disp); } else { M_TEST(s1); emit_label_beq(cd, BRANCH_LABEL_5); + + disp = dseg_add_address(cd, super->vftbl); } M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); - - if (super == NULL) { - codegen_add_patch_ref(cd, PATCHER_checkcast_class, - iptr->sx.s23.s3.c.ref, - 0); + M_ALD(REG_ITMP3, RIP, disp); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_6); /* good */ + + if (super == NULL) { + M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bne(cd, BRANCH_LABEL_10); /* throw */ + } + + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1); + emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */ + + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3); + emit_label_beq(cd, BRANCH_LABEL_7); /* good */ + + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); + M_ALD_MEM(s1, TRAP_ClassCastException); + + emit_label(cd, BRANCH_LABEL_7); + emit_label(cd, BRANCH_LABEL_6); + /* reload s1, might have been destroyed */ + emit_load_s1(jd, iptr, REG_ITMP1); + } + else { + M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3); + emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1); } - - M_MOV_IMM(supervftbl, REG_ITMP3); - - CODEGEN_CRITICAL_SECTION_START; - - M_ILD32(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); - - /* if (s1 != REG_ITMP1) { */ - /* emit_movl_membase_reg(cd, REG_ITMP3, */ - /* OFFSET(vftbl_t, baseval), */ - /* REG_ITMP1); */ - /* emit_movl_membase_reg(cd, REG_ITMP3, */ - /* OFFSET(vftbl_t, diffval), */ - /* REG_ITMP3); */ - /* #if defined(ENABLE_THREADS) */ - /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */ - /* #endif */ - /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */ - - /* } else { */ - - M_ILD32(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); - M_ISUB(REG_ITMP3, REG_ITMP2); - M_MOV_IMM(supervftbl, REG_ITMP3); - M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); - /* } */ - - CODEGEN_CRITICAL_SECTION_END; - - M_ICMP(REG_ITMP3, REG_ITMP2); - emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1); if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -2670,11 +1994,18 @@ gen_method: M_INTMOVE(s1, REG_A0); if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast, - iptr->sx.s23.s3.c.ref, 0); + constant_classref *cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, cr); + + patcher_add_patch_ref(jd, + PATCHER_resolve_classref_to_classinfo, + cr, disp); + } + else { + disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); } - M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1); + M_ALD(REG_A1, RIP, disp); M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1); M_CALL(REG_ITMP1); @@ -2694,23 +2025,17 @@ gen_method: { classinfo *super; - vftbl_t *supervftbl; s4 superindex; if (INSTRUCTION_IS_UNRESOLVED(iptr)) { super = NULL; superindex = 0; - supervftbl = NULL; } else { super = iptr->sx.s23.s3.c.cls; superindex = super->index; - supervftbl = super->vftbl; } - if ((super == NULL) || !(super->flags & ACC_INTERFACE)) - CODEGEN_CRITICAL_SECTION_NEW; - s1 = emit_load_s1(jd, iptr, REG_ITMP1); d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); @@ -2727,7 +2052,7 @@ gen_method: M_TEST(s1); emit_label_beq(cd, BRANCH_LABEL_1); - codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags, + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags, iptr->sx.s23.s3.c.ref, 0); M_IMOV_IMM(0, REG_ITMP3); /* super->flags */ @@ -2746,7 +2071,7 @@ gen_method: M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); if (super == NULL) { - codegen_add_patch_ref(cd, PATCHER_instanceof_interface, + patcher_add_patch_ref(jd, PATCHER_instanceof_interface, iptr->sx.s23.s3.c.ref, 0); } @@ -2754,7 +2079,7 @@ gen_method: REG_ITMP1, OFFSET(vftbl_t, interfacetablelength)); M_ICMP_IMM32(superindex, REG_ITMP3); - a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */; + int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */; M_BLE(a); M_ALD32(REG_ITMP1, REG_ITMP1, @@ -2774,33 +2099,70 @@ gen_method: if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); + + constant_classref *cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, cr); + + patcher_add_patch_ref(jd, + PATCHER_resolve_classref_to_vftbl, + cr, disp); } else { M_TEST(s1); emit_label_beq(cd, BRANCH_LABEL_5); + + disp = dseg_add_address(cd, super->vftbl); } - M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); + M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); + M_ALD(REG_ITMP3, RIP, disp); + + if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) { + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset)); + M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3); + emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */ + if (d == REG_ITMP2) { + M_SETE(d); + M_BSEXT(d, d); + } else + M_LINC(d); + emit_label_br(cd, BRANCH_LABEL_6); /* true */ + emit_label(cd, BRANCH_LABEL_8); - if (super == NULL) { - codegen_add_patch_ref(cd, PATCHER_instanceof_class, - iptr->sx.s23.s3.c.ref, 0); - } + if (super == NULL) { + M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1); + emit_label_bne(cd, BRANCH_LABEL_10); /* false */ + } - M_MOV_IMM(supervftbl, REG_ITMP2); + M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth)); + M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1); + emit_label_bgt(cd, BRANCH_LABEL_9); /* false */ - CODEGEN_CRITICAL_SECTION_START; + M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow)); + M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3); + M_SETE(d); + if (d == REG_ITMP2) { + M_BSEXT(d, d); - M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval)); - M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, diffval)); - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); + emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */ + } - CODEGEN_CRITICAL_SECTION_END; + emit_label(cd, BRANCH_LABEL_9); + if (super == NULL) + emit_label(cd, BRANCH_LABEL_10); + if (d == REG_ITMP2) { + M_CLR(d); - M_ISUB(REG_ITMP2, REG_ITMP1); - M_CLR(d); /* may be REG_ITMP2 */ - M_ICMP(REG_ITMP3, REG_ITMP1); - M_SETULE(d); + emit_label(cd, BRANCH_LABEL_7); + } + emit_label(cd, BRANCH_LABEL_6); + } + else { + M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3); + M_SETE(d); + if (d == REG_ITMP2) + M_BSEXT(d, d); + } if (super != NULL) emit_label(cd, BRANCH_LABEL_5); @@ -2833,20 +2195,26 @@ gen_method: } } + /* a0 = dimension count */ + + M_MOV_IMM(iptr->s1.argcount, REG_A0); + /* is a patcher function set? */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray, - iptr->sx.s23.s3.c.ref, 0); - } - - /* a0 = dimension count */ + constant_classref *cr = iptr->sx.s23.s3.c.ref; + disp = dseg_add_unique_address(cd, cr); - M_MOV_IMM(iptr->s1.argcount, REG_A0); + patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, + cr, disp); + } + else { + disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls); + } /* a1 = classinfo */ - M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1); + M_ALD(REG_A1, RIP, disp); /* a2 = pointer to dimensions = stack pointer */ @@ -2865,232 +2233,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(512); /* XXX require a lower 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 */ - - dseg_createlinenumbertable(cd); - - /* generate stubs */ - - emit_patcher_stubs(jd); - - /* everything's ok */ - - return true; -} - - -/* codegen_emit_stub_compiler ************************************************** - - Emit a stub routine which calls the compiler. - -*******************************************************************************/ - -void codegen_emit_stub_compiler(jitdata *jd) -{ - methodinfo *m; - codegendata *cd; - - /* get required compiler data */ - - m = jd->m; - cd = jd->cd; - - /* code for the stub */ - - M_ALD(REG_ITMP1, RIP, -(7 * 1 + 2 * SIZEOF_VOID_P)); /* methodinfo */ - M_ALD(REG_ITMP3, RIP, -(7 * 2 + 3 * SIZEOF_VOID_P)); /* compiler pointer */ - M_JMP(REG_ITMP3); -} - - -/* codegen_emit_stub_builtin *************************************************** - - Creates a stub routine which calls a builtin function. - -*******************************************************************************/ - -void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte) -{ - codeinfo *code; - codegendata *cd; - methoddesc *md; - s4 i, j; - s4 s1, disp; - - /* get required compiler data */ - - code = jd->code; - cd = jd->cd; - - md = bte->md; - - /* calculate stack frame size */ - - cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + - md->paramcount + /* saved argument registers */ - 1; /* return value */ - - cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */ - - /* create method header */ - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ - (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ - (void) dseg_add_unique_s4(cd, 0); /* IntSave */ - (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ - - /* generate stub code */ - - M_ASUB_IMM(cd->stackframesize * 8, REG_SP); - -#if defined(ENABLE_GC_CACAO) - /* Save callee saved integer registers in stackframeinfo (GC may - need to recover them during a collection). */ - - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); - - for (i = 0; i < INT_SAV_CNT; i++) - M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8); -#endif - - /* save integer and float argument registers */ - - for (i = 0, j = 0; i < md->paramcount; i++) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - switch (md->paramtypes[i].type) { - case TYPE_INT: - case TYPE_LNG: - case TYPE_ADR: - M_LST(s1, REG_SP, j * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DST(s1, REG_SP, j * 8); - break; - } - - j++; - } - } - - /* create dynamic stack info */ - - M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0); - emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1); - M_ALEA(REG_SP, cd->stackframesize * 8 + SIZEOF_VOID_P, REG_A2); - M_ALD(REG_A3, REG_SP, cd->stackframesize * 8); - M_MOV_IMM(codegen_stub_builtin_enter, REG_ITMP1); - M_CALL(REG_ITMP1); - - /* restore integer and float argument registers */ - - for (i = 0, j = 0; i < md->paramcount; i++) { - if (!md->params[i].inmemory) { - s1 = md->params[i].regoff; - - switch (md->paramtypes[i].type) { - case TYPE_INT: - case TYPE_LNG: - case TYPE_ADR: - M_LLD(s1, REG_SP, j * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DLD(s1, REG_SP, j * 8); - break; - } - - j++; - } - } - - /* call the builtin function */ - - M_MOV_IMM(bte->fp, REG_ITMP3); - M_CALL(REG_ITMP3); - - /* save return value */ - - switch (md->returntype.type) { - case TYPE_INT: - case TYPE_LNG: - case TYPE_ADR: - M_LST(REG_RESULT, REG_SP, 0 * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DST(REG_FRESULT, REG_SP, 0 * 8); - break; - case TYPE_VOID: - break; - } - - /* remove native stackframe info */ - - M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0); - M_MOV_IMM(codegen_stub_builtin_exit, REG_ITMP1); - M_CALL(REG_ITMP1); - - /* restore return value */ - - switch (md->returntype.type) { - case TYPE_INT: - case TYPE_LNG: - case TYPE_ADR: - M_LLD(REG_RESULT, REG_SP, 0 * 8); - break; - case TYPE_FLT: - case TYPE_DBL: - M_DLD(REG_FRESULT, REG_SP, 0 * 8); - break; - case TYPE_VOID: - break; - } - -#if defined(ENABLE_GC_CACAO) - /* Restore callee saved integer registers from stackframeinfo (GC - might have modified them during a collection). */ - - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); - - for (i = 0; i < INT_SAV_CNT; i++) - M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8); -#endif - - /* remove stackframe */ - - M_AADD_IMM(cd->stackframesize * 8, REG_SP); - M_RET; } @@ -3100,18 +2244,21 @@ void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte) *******************************************************************************/ -void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) +void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams) { methodinfo *m; codeinfo *code; codegendata *cd; methoddesc *md; - s4 nativeparams; - s4 i, j; - s4 t; - s4 s1, s2, disp; + int i, j; + int s1, s2; + int disp; + + /* Sanity check. */ - /* get required compiler data */ + assert(f != NULL); + + /* Get required compiler data. */ m = jd->m; code = jd->code; @@ -3120,29 +2267,25 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* initialize variables */ md = m->parseddesc; - nativeparams = (m->flags & ACC_STATIC) ? 2 : 1; /* calculate stack frame size */ cd->stackframesize = - sizeof(stackframeinfo) / SIZEOF_VOID_P + + sizeof(stackframeinfo_t) / SIZEOF_VOID_P + sizeof(localref_table) / SIZEOF_VOID_P + md->paramcount + - 1 + /* functionptr, TODO: store in data segment */ + (md->returntype.type == TYPE_VOID ? 0 : 1) + nmd->memuse; - cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */ + ALIGN_ODD(cd->stackframesize); /* keep stack 16-byte aligned */ /* create method header */ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - (void) dseg_add_unique_s4(cd, 0); /* IsSync */ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */ (void) dseg_add_unique_s4(cd, 0); /* IntSave */ (void) dseg_add_unique_s4(cd, 0); /* FltSave */ - (void) dseg_addlinenumbertablesize(cd); - (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */ #if defined(ENABLE_PROFILING) /* generate native method profiling code */ @@ -3159,26 +2302,12 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) M_ASUB_IMM(cd->stackframesize * 8, REG_SP); -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_enter(jd); -#endif - - /* get function address (this must happen before the stackframeinfo) */ - -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) - codegen_add_patch_ref(cd, PATCHER_resolve_native, m, 0); -#endif - - M_MOV_IMM(f, REG_ITMP3); - #if defined(ENABLE_GC_CACAO) /* Save callee saved integer registers in stackframeinfo (GC may need to recover them during a collection). */ - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); for (i = 0; i < INT_SAV_CNT; i++) M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8); @@ -3204,8 +2333,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) } } - M_AST(REG_ITMP3, REG_SP, md->paramcount * 8); - /* create dynamic stack info */ M_MOV(REG_SP, REG_A0); @@ -3238,15 +2365,15 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) } } - M_ALD(REG_ITMP3, REG_SP, md->paramcount * 8); - - /* copy or spill arguments to new locations */ + /* Copy or spill arguments to new locations. */ - for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) { - t = md->paramtypes[i].type; + for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) { s2 = nmd->params[j].regoff; - if (IS_INT_LNG_TYPE(t)) { + switch (md->paramtypes[i].type) { + case TYPE_INT: + case TYPE_LNG: + case TYPE_ADR: if (!md->params[i].inmemory) { s1 = md->params[i].regoff; @@ -3260,38 +2387,46 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) M_LLD(REG_ITMP1, REG_SP, s1); M_LST(REG_ITMP1, REG_SP, s2); } - } - else { + break; + case TYPE_FLT: /* We only copy spilled float arguments, as the float argument registers keep unchanged. */ if (md->params[i].inmemory) { s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */ - if (IS_2_WORD_TYPE(t)) { - M_DLD(REG_FTMP1, REG_SP, s1); - M_DST(REG_FTMP1, REG_SP, s2); - } - else { - M_FLD(REG_FTMP1, REG_SP, s1); - M_FST(REG_FTMP1, REG_SP, s2); - } + M_FLD(REG_FTMP1, REG_SP, s1); + M_FST(REG_FTMP1, REG_SP, s2); } + break; + case TYPE_DBL: + if (md->params[i].inmemory) { + s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */ + M_DLD(REG_FTMP1, REG_SP, s1); + M_DST(REG_FTMP1, REG_SP, s2); + } + break; } } - /* put class into second argument register */ + /* Handle native Java methods. */ - if (m->flags & ACC_STATIC) - M_MOV(REG_ITMP2, REG_A1); + if (m->flags & ACC_NATIVE) { + /* put class into second argument register */ - /* put env into first argument register */ + if (m->flags & ACC_STATIC) + M_MOV(REG_ITMP2, REG_A1); - M_MOV_IMM(_Jv_env, REG_A0); + /* put env into first argument register */ - /* do the native function call */ + M_MOV_IMM(VM_get_jnienv(), REG_A0); + } - M_CALL(REG_ITMP3); + /* Call the native function. */ + + disp = dseg_add_functionptr(cd, f); + M_ALD(REG_ITMP1, RIP, disp); + M_CALL(REG_ITMP1); /* save return value */ @@ -3299,6 +2434,20 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) case TYPE_INT: case TYPE_LNG: case TYPE_ADR: + switch (md->returntype.primitivetype) { + case PRIMITIVETYPE_BOOLEAN: + M_BZEXT(REG_RESULT, REG_RESULT); + break; + case PRIMITIVETYPE_BYTE: + M_BSEXT(REG_RESULT, REG_RESULT); + break; + case PRIMITIVETYPE_CHAR: + M_CZEXT(REG_RESULT, REG_RESULT); + break; + case PRIMITIVETYPE_SHORT: + M_SSEXT(REG_RESULT, REG_RESULT); + break; + } M_LST(REG_RESULT, REG_SP, 0 * 8); break; case TYPE_FLT: @@ -3309,14 +2458,10 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) break; } -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif - /* remove native stackframe info */ - M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0); + M_MOV(REG_SP, REG_A0); + emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1); M_MOV_IMM(codegen_finish_native_call, REG_ITMP1); M_CALL(REG_ITMP1); M_MOV(REG_RESULT, REG_ITMP3); @@ -3341,8 +2486,8 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) /* Restore callee saved integer registers from stackframeinfo (GC might have modified them during a collection). */ - disp = cd->stackframesize * 8 - sizeof(stackframeinfo) + - OFFSET(stackframeinfo, intregs); + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); for (i = 0; i < INT_SAV_CNT; i++) M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8); @@ -3366,10 +2511,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3); M_JMP(REG_ITMP3); - - /* generate patcher stubs */ - - emit_patcher_stubs(jd); }