X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fs390%2Fcodegen.c;h=fc6c142d8ffd5fa94cc31baa7c17054a4401e35f;hb=e9865924b9bb241082f2b3878f893be3fc8b57c2;hp=5b083baa5a8f495ccab71d947607e7f38157ac99;hpb=33d335af24c942ce5a9062a7cc7b9b74e3b4209f;p=cacao.git diff --git a/src/vm/jit/s390/codegen.c b/src/vm/jit/s390/codegen.c index 5b083baa5..fc6c142d8 100644 --- a/src/vm/jit/s390/codegen.c +++ b/src/vm/jit/s390/codegen.c @@ -1,9 +1,7 @@ /* src/vm/jit/s390/codegen.c - machine code generator for s390 - 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. @@ -31,54 +29,51 @@ #include #include -#include "native/jni.h" -#include "native/localref.h" -#include "native/native.h" +#include "vm/jit/s390/arch.h" +#include "vm/jit/s390/codegen.h" +#include "vm/jit/s390/emit.h" +#include "vm/jit/s390/md-abi.h" -#include "mm/memory.h" +#include "native/localref.hpp" +#include "native/native.hpp" -#if defined(ENABLE_THREADS) -# include "threads/lock-common.h" -# include "threads/native/lock.h" -#endif +#include "mm/memory.hpp" + +#include "threads/lock.hpp" -#include "vmcore/loader.h" -#include "vmcore/options.h" -#include "vmcore/statistics.h" -#include "vm/builtin.h" -#include "vm/exceptions.h" +#include "vm/jit/builtin.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" +#include "vm/loader.hpp" +#include "vm/options.h" +#include "vm/statistics.h" +#include "vm/types.h" +#include "vm/vm.hpp" + #include "vm/jit/abi.h" -#if defined(ENABLE_LSRA) -# include "vm/jit/allocator/lsra.h" -#endif #include "vm/jit/asmpart.h" -#include "vm/jit/codegen-common.h" +#include "vm/jit/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-common.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/s390/arch.h" -#include "vm/jit/s390/codegen.h" -#include "vm/jit/s390/emit.h" -#include "vm/jit/s390/md-abi.h" -#include "vm/jit/stacktrace.h" -#include "vm/types.h" -#include "vm/stringlocal.h" -#include "vm/vm.h" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.hpp" + /* DO__LOG generates a call to do__log. No registers are destroyed, * so you may use it anywhere. regs is an array containing all general * purpose registers. */ +/* static void do__log(u4 *regs) { - /* insert stuff here */ } +*/ #define DO__LOG \ N_AHI(REG_SP, -200); \ @@ -89,13 +84,11 @@ static void do__log(u4 *regs) { N_LM(R0, R15, 96, REG_SP); \ N_AHI(REG_SP, 200); -#define SUPPORT_HERCULES 1 - -/* codegen ********************************************************************* - - Generates machine code. +/* If the following macro is defined, workaround code for hercules quirks + * is generated + */ -*******************************************************************************/ +/* #define SUPPORT_HERCULES 1 */ /* @@ -122,122 +115,29 @@ local[0] 0 * 8 */ -bool codegen_emit(jitdata *jd) -{ - methodinfo *m; - codeinfo *code; - codegendata *cd; - registerdata *rd; - s4 len, s1, s2, s3, d, dd, disp; - u2 currentline; - ptrint a; - varinfo *var, *var1, *var2, *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; -#if 0 - rplpoint *replacementpoint; -#endif - 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 + 1 /* space to save RA */; +/** + * Generates machine code for the method prolog. + */ +void codegen_emit_prolog(jitdata* jd) +{ + varinfo* var; + methoddesc* md; + int32_t s1, s2; + 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; /* CAUTION: * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved. */ -#if defined(ENABLE_THREADS) - /* Space to save argument of monitor_enter and Return Values to - survive monitor_exit. The stack position for the argument can - not be shared with place to save the return register - since both values reside in R2. */ - - if (checksync && code_is_synchronized(code)) { - /* 1 slot space to save argument of monitor_enter */ - /* 1 slot to temporary store return value before monitor_exit */ - cd->stackframesize += 2; - } -#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 (!code_is_leafmethod(code) || opt_verbosecall ) - /* TODO really 16 bytes ? */ - cd->stackframesize = (cd->stackframesize + 2) & ~2; - - /* create method header */ - - (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */ - (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */ - - /* 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. - */ - /* XXX Remove this "offset by one". */ - - code->synchronizedoffset = (rd->memuse + 1) * 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 */ - - (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); - } - /* Offset PV */ M_AADD_IMM(N_PV_OFFSET, REG_PV); @@ -252,20 +152,6 @@ bool codegen_emit(jitdata *jd) M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); - /* generate method profiling code */ - -#if defined(ENABLE_PROFILING) - if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { - /* count frequency */ - M_ALD_DSEG(REG_ITMP1, CodeinfoPointer); - ICONST(REG_ITMP2, 1); - N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1); - M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency)); - - PROFILE_CYCLE_START; - } -#endif - /* save used callee saved registers and return address */ p = cd->stackframesize - 1; @@ -337,7 +223,7 @@ bool codegen_emit(jitdata *jd) if (!md->params[p].inmemory) { /* register arguments */ s2 = s1; if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */ - M_FLTMOVE(s2, var->vv.regoff); + emit_fmove(cd, s2, var->vv.regoff); } else { /* reg arg -> spilled */ if (IS_2_WORD_TYPE(t)) @@ -361,212 +247,68 @@ bool codegen_emit(jitdata *jd) } } } /* end for */ +} - /* save monitorenter argument */ - -#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_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); - - for (p = 0; p < INT_ARG_CNT; p++) - M_IST(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 - - /* decide which monitor enter function to call */ - if (m->flags & ACC_STATIC) { - disp = dseg_add_address(cd, &m->class->object.header); - M_ALD_DSEG(REG_A0, disp); - } - else { - M_TEST(REG_A0); - M_BNE(SZ_BRC + SZ_ILL); - M_ILL(EXCEPTION_HARDWARE_NULLPOINTER); - } +/** + * Generates machine code for the method epilog. + */ +void codegen_emit_epilog(jitdata* jd) +{ + int32_t p; + int i; - disp = dseg_add_functionptr(cd, LOCK_monitor_enter); - M_ALD_DSEG(REG_ITMP2, disp); + // Get required compiler data. + codegendata* cd = jd->cd; + registerdata* rd = jd->rd; - M_AST(REG_A0, REG_SP, s1 * 8); + p = cd->stackframesize; - M_ASUB_IMM(96, REG_SP); - M_CALL(REG_ITMP2); - M_AADD_IMM(96, REG_SP); + /* restore return address */ -#if !defined(NDEBUG) - if (opt_verbosecall) { - for (p = 0; p < INT_ARG_CNT; p++) - M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8); + p--; M_ALD(REG_RA, REG_SP, p * 8); - 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_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP); - } -#endif + for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { + p--; M_ILD(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_ALD_DSEG(REG_ITMP1, CodeinfoPointer); - M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency)); - ICONST(REG_ITMP2, 1); - N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1); - M_IST(REG_ITMP2, REG_ITMP1, 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_ITMP3_XPTR; - M_INTMOVE(REG_ITMP3_XPTR, 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_ITMP3_XPTR); - M_INTMOVE(REG_ITMP3_XPTR, 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: + /* deallocate stack */ - REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - dseg_addlinenumber_inline_start(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; + if (cd->stackframesize) + M_AADD_IMM(cd->stackframesize * 8, REG_SP); - case ICMD_INLINE_END: + M_RET; +} - dseg_addlinenumber_inline_end(cd, iptr); - dseg_addlinenumber(cd, iptr->line); - break; - 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, dd; + 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 */ - - d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED); - 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); disp = dseg_add_float(cd, iptr->sx.val.f); @@ -585,16 +327,12 @@ 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; */ - patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo, cr, disp); -/* PROFILE_CYCLE_START; */ - M_ALD_DSEG(d, disp); } else { if (iptr->sx.val.anyptr == 0) { @@ -618,28 +356,6 @@ bool codegen_emit(jitdata *jd) 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 */ @@ -983,7 +699,6 @@ bool codegen_emit(jitdata *jd) case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */ bte = iptr->sx.s23.s3.bte; - md = bte->md; /* test s2 for zero */ @@ -1463,7 +1178,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); @@ -1476,7 +1191,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); @@ -1487,7 +1202,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FSUB(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1497,7 +1212,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DSUB(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1509,7 +1224,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); @@ -1522,7 +1237,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); @@ -1533,7 +1248,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_FDIV(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1543,7 +1258,7 @@ bool codegen_emit(jitdata *jd) d = codegen_reg_of_dst(jd, iptr, REG_FTMP1); s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d); - M_FLTMOVE(s1, d); + emit_fmove(cd, s1, d); M_DDIV(s2, d); emit_store_dst(jd, iptr, d); break; @@ -1638,7 +1353,9 @@ bool codegen_emit(jitdata *jd) case ICMD_F2D: /* ..., value ==> ..., (double) value */ { +#ifdef SUPPORT_HERCULES u1 *ref; +#endif s1 = emit_load_s1(jd, iptr, REG_FTMP1); d = codegen_reg_of_dst(jd, iptr, REG_FTMP2); #ifdef SUPPORT_HERCULES @@ -1717,17 +1434,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); - /* TODO softnull */ - /* 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); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -1810,13 +1516,13 @@ bool codegen_emit(jitdata *jd) N_L( GET_LOW_REG(d) /* maybe itmp3 */, - OFFSET(java_intarray_t, data[0]) + 4, + OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1 /* maybe itmp1 */ ); N_L( GET_HIGH_REG(d) /* maybe itmp1 */, - OFFSET(java_intarray_t, data[0]), + OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1 /* maybe itmp1 */ ); @@ -1852,7 +1558,7 @@ bool codegen_emit(jitdata *jd) M_INTMOVE(s2, REG_ITMP2); M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */ - N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1); + N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1); emit_store_dst(jd, iptr, d); break; @@ -1935,9 +1641,9 @@ bool codegen_emit(jitdata *jd) M_SLL_IMM(3, REG_ITMP2); s3 = emit_load_s3_high(jd, iptr, REG_ITMP3); - N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1); + N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1); s3 = emit_load_s3_low(jd, iptr, REG_ITMP3); - N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1); + N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1); break; case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */ @@ -1999,109 +1705,6 @@ bool codegen_emit(jitdata *jd) */ 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); - -/* PROFILE_CYCLE_STOP; */ - - patcher_add_patch_ref(jd, 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); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - PROFILE_CYCLE_STOP; - - patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0); - - PROFILE_CYCLE_START; - } - } - - M_ALD_DSEG(REG_ITMP1, 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: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED); - M_LLD(d, REG_ITMP1, 0); - break; - case TYPE_ADR: - d = codegen_reg_of_dst(jd, iptr, REG_ITMP2); - M_ALD(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, uf); - - patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); - } - else { - fi = iptr->sx.s23.s3.fmiref->p.field; - fieldtype = fi->type; - disp = dseg_add_address(cd, fi->value); - - if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) { - PROFILE_CYCLE_STOP; - patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp); - PROFILE_CYCLE_START; - } - } - - M_ALD_DSEG(REG_ITMP1, disp); - switch (fieldtype) { - case TYPE_INT: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_IST(s1, REG_ITMP1, 0); - break; - case TYPE_LNG: - s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED); - M_LST(s1, REG_ITMP1, 0); - break; - case TYPE_ADR: - s1 = emit_load_s1(jd, iptr, REG_ITMP2); - M_AST(s1, REG_ITMP1, 0); - break; - case TYPE_FLT: - s1 = emit_load_s1(jd, iptr, REG_FTMP2); - M_FST(s1, REG_ITMP1, 0); - break; - case TYPE_DBL: - s1 = emit_load_s1(jd, iptr, REG_FTMP2); - M_DST(s1, REG_ITMP1, 0); - break; - } - break; - case ICMD_GETFIELD: /* ... ==> ..., value */ s1 = emit_load_s1(jd, iptr, REG_ITMP1); @@ -2155,6 +1758,7 @@ bool codegen_emit(jitdata *jd) case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */ { u1 *ref; + patchref_t *pr; s1 = emit_load_s1(jd, iptr, REG_ITMP1); emit_nullpointer_check(cd, iptr, s1); @@ -2180,7 +1784,7 @@ bool codegen_emit(jitdata *jd) */ if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); + pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0); ref = cd->mcodeptr; } @@ -2195,7 +1799,7 @@ bool codegen_emit(jitdata *jd) } if (INSTRUCTION_IS_UNRESOLVED(iptr)) { - ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref); + pr->disp = (cd->mcodeptr - ref); } switch (fieldtype) { @@ -2224,109 +1828,25 @@ bool codegen_emit(jitdata *jd) case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */ - /* PROFILE_CYCLE_STOP; */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP3); - M_INTMOVE(s1, REG_ITMP3_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 */ - disp = dseg_add_functionptr(cd, asm_handle_exception); M_ALD_DSEG(REG_ITMP1, disp); - M_JMP(REG_ITMP1_XPC, REG_ITMP1); + M_JMP(REG_ITMP2_XPC, REG_ITMP1); M_NOP; break; - case ICMD_GOTO: /* ... ==> ... */ - case ICMD_RET: /* ... ==> ... */ - - emit_br(cd, iptr->dst.block); + case ICMD_IF_LLT: /* ..., value ==> ... */ + case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */ + case ICMD_IF_LGT: + case ICMD_IF_LGE: + case ICMD_IF_LEQ: + case ICMD_IF_LNE: - break; + /* ATTENTION: compare high words signed and low words unsigned */ - case ICMD_JSR: /* ... ==> ... */ +# define LABEL_OUT BRANCH_LABEL_1 - emit_br(cd, iptr->sx.s23.s3.jsrtarget.block); - - break; - - case ICMD_IFNULL: /* ..., value ==> ... */ - case ICMD_IFNONNULL: /* ..., value ==> ... */ - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - M_TEST(s1); - switch (iptr->opc) { - case ICMD_IFNULL: - emit_beq(cd, iptr->dst.block); - break; - case ICMD_IFNONNULL: - emit_bne(cd, iptr->dst.block); - break; - } - break; - - case ICMD_IFEQ: /* ..., value ==> ... */ - case ICMD_IFLT: /* ..., value ==> ... */ - case ICMD_IFLE: /* ..., value ==> ... */ - case ICMD_IFNE: /* ..., value ==> ... */ - case ICMD_IFGT: /* ..., value ==> ... */ - case ICMD_IFGE: /* ..., value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - - if (N_VALID_IMM(iptr->sx.val.i)) - M_ICMP_IMM(s1, iptr->sx.val.i); - else { - disp = dseg_add_s4(cd, iptr->sx.val.i); - if (N_VALID_DSEG_DISP(disp)) { - N_C(s1, N_DSEG_DISP(disp), RN, REG_PV); - } else { - ICONST(REG_ITMP2, disp); - N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV); - } - } - - switch (iptr->opc) { - case ICMD_IFLT: - emit_blt(cd, iptr->dst.block); - break; - case ICMD_IFLE: - emit_ble(cd, iptr->dst.block); - break; - case ICMD_IFNE: - emit_bne(cd, iptr->dst.block); - break; - case ICMD_IFGT: - emit_bgt(cd, iptr->dst.block); - break; - case ICMD_IFGE: - emit_bge(cd, iptr->dst.block); - break; - case ICMD_IFEQ: - emit_beq(cd, iptr->dst.block); - break; - } - - break; - - case ICMD_IF_LLT: /* ..., value ==> ... */ - case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */ - case ICMD_IF_LGT: - case ICMD_IF_LGE: - case ICMD_IF_LEQ: - case ICMD_IF_LNE: - - /* ATTENTION: compare high words signed and low words unsigned */ - -# define LABEL_OUT BRANCH_LABEL_1 - - s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); + s1 = emit_load_s1_high(jd, iptr, REG_ITMP1); if (N_VALID_IMM(iptr->sx.val.l >> 32)) M_ICMP_IMM(s1, iptr->sx.val.l >> 32); @@ -2430,39 +1950,6 @@ bool codegen_emit(jitdata *jd) break; - case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */ - case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */ - - s1 = emit_load_s1(jd, iptr, REG_ITMP1); - s2 = emit_load_s2(jd, iptr, REG_ITMP2); - M_CMP(s1, s2); - switch (iptr->opc) { - case ICMD_IF_ICMPEQ: - emit_beq(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPNE: - emit_bne(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPLT: - emit_blt(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPGT: - emit_bgt(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPLE: - emit_ble(cd, iptr->dst.block); - break; - case ICMD_IF_ICMPGE: - emit_bge(cd, iptr->dst.block); - break; - } - - break; - case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */ case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */ case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */ @@ -2543,137 +2030,6 @@ bool codegen_emit(jitdata *jd) } break; - case ICMD_IRETURN: /* ..., retvalue ==> ... */ - - 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)) { - unresolved_class *uc = iptr->sx.s23.s2.uc; - - PROFILE_CYCLE_STOP; - patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); - PROFILE_CYCLE_START; - } -#endif /* ENABLE_VERIFIER */ - goto nowperformreturn; - - case ICMD_LRETURN: /* ..., retvalue ==> ... */ - - REPLACEMENT_POINT_RETURN(cd, iptr); - s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED); - M_LNGMOVE(s1, REG_RESULT_PACKED); - 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; - - /* call trace function */ - -#if !defined(NDEBUG) - if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) - emit_verbosecall_exit(jd); -#endif /* !defined(NDEBUG) */ - -#if defined(ENABLE_THREADS) - if (checksync && code_is_synchronized(code)) { - /* we need to save the proper return value */ - - switch (iptr->opc) { - case ICMD_LRETURN: - M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4); - /* fall through */ - case ICMD_IRETURN: - case ICMD_ARETURN: - M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8); - break; - case ICMD_FRETURN: - M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); - break; - case ICMD_DRETURN: - M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); - break; - } - - M_ALD(REG_A0, REG_SP, rd->memuse * 8); - - disp = dseg_add_functionptr(cd, LOCK_monitor_exit); - M_ALD_DSEG(REG_ITMP2, disp); - - M_ASUB_IMM(96, REG_SP); - M_CALL(REG_ITMP2); - M_AADD_IMM(96, REG_SP); - - /* and now restore the proper return value */ - - switch (iptr->opc) { - case ICMD_LRETURN: - M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4); - /* fall through */ - case ICMD_IRETURN: - case ICMD_ARETURN: - M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8); - break; - case ICMD_FRETURN: - M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); - break; - case ICMD_DRETURN: - M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8); - break; - } - } -#endif - - /* restore return address */ - - p--; M_ALD(REG_RA, REG_SP, p * 8); - - /* restore saved registers */ - - for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) { - p--; M_ILD(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; @@ -2726,255 +2082,116 @@ nowperformreturn: break; - case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */ - { - s4 i; - lookup_target_t *lookup; - - lookup = iptr->dst.lookup; + case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + bte = iptr->sx.s23.s3.bte; + if (bte->stub == NULL) { + disp = dseg_add_functionptr(cd, bte->fp); + M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */ + } else { + disp = dseg_add_functionptr(cd, bte->stub); + } - i = iptr->sx.s23.s2.lookupcount; - - MCODECHECK(8 + ((7 + 6) * i) + 5); - s1 = emit_load_s1(jd, iptr, REG_ITMP1); + if (N_VALID_DSEG_DISP(disp)) { + N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); + } else { + N_LHI(REG_ITMP1, disp); + N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); + } - while (--i >= 0) { - if (N_VALID_IMM(lookup->value)) { - M_ICMP_IMM(s1, lookup->value); - } else { - ICONST(REG_ITMP2, lookup->value); - M_ICMP(REG_ITMP2, s1); - } - emit_beq(cd, lookup->target.block); - lookup++; - } + /* generate the actual call */ + M_CALL(REG_PV); - emit_br(cd, iptr->sx.s23.s3.lookupdefault.block); + /* post call finalization */ + if (bte->stub == NULL) { + M_AADD_IMM(96, REG_SP); /* remove C abi register save area */ } break; - - case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ - - 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); + /* TODO softnull */ + /* Implicit NULL pointer check */ + M_ILD(REG_ITMP1, REG_A0, 0); + /* fall through */ + case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */ 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); - - /* copy arguments to registers or stack location */ - - for (s3 = s3 - 1; s3 >= 0; s3--) { - var = VAR(iptr->sx.s23.s2.args[s3]); - - /* Already Preallocated? */ - if (var->flags & PREALLOC) - continue; - - if (IS_INT_LNG_TYPE(var->type)) { - if (!md->params[s3].inmemory) { - if (IS_2_WORD_TYPE(var->type)) { - s1 = PACK_REGS( - GET_LOW_REG(md->params[s3].regoff), - GET_HIGH_REG(md->params[s3].regoff) - ); - d = emit_load(jd, iptr, var, s1); - M_LNGMOVE(d, s1); - } - else { - s1 = md->params[s3].regoff; - d = emit_load(jd, iptr, var, s1); - M_INTMOVE(d, s1); - } - } - else { - if (IS_2_WORD_TYPE(var->type)) { - d = emit_load(jd, iptr, var, REG_ITMP12_PACKED); - M_LST(d, REG_SP, md->params[s3].regoff); - } - else { - d = emit_load(jd, iptr, var, REG_ITMP1); - M_IST(d, REG_SP, md->params[s3].regoff); - } - } - } - else { - if (!md->params[s3].inmemory) { - s1 = md->params[s3].regoff; - d = emit_load(jd, iptr, var, s1); - M_FLTMOVE(d, s1); - } - else { - d = emit_load(jd, iptr, var, REG_FTMP1); - if (IS_2_WORD_TYPE(var->type)) - M_DST(d, REG_SP, md->params[s3].regoff); - else - M_FST(d, REG_SP, md->params[s3].regoff); - } - } + if (N_VALID_DSEG_DISP(disp)) { + N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); + } else { + N_LHI(REG_ITMP1, disp); + N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); } - /* generate method profiling code */ - - PROFILE_CYCLE_STOP; - - switch (iptr->opc) { - case ICMD_BUILTIN: - if (bte->stub == NULL) { - disp = dseg_add_functionptr(cd, bte->fp); - M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */ - } else { - disp = dseg_add_functionptr(cd, bte->stub); - } - - if (N_VALID_DSEG_DISP(disp)) { - N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); - } else { - N_LHI(REG_ITMP1, disp); - N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); - } - break; - - case ICMD_INVOKESPECIAL: - /* TODO softnull */ - /* Implicit NULL pointer check */ - M_ILD(REG_ITMP1, REG_A0, 0); - - /* 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); - - if (N_VALID_DSEG_DISP(disp)) { - N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV); - } else { - N_LHI(REG_ITMP1, disp); - N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV); - } - break; - - case ICMD_INVOKEVIRTUAL: - /* TODO softnull 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); - break; - - case ICMD_INVOKEINTERFACE: - /* TODO softnull REG_A0 */ + /* generate the actual call */ + M_CALL(REG_PV); + break; - /* s1 will be negative here, so use (0xFFF + s1) as displacement - * and -0xFFF in index register (itmp1) - */ + case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */ + /* TODO softnull REG_A0 */ - if (lm == NULL) { - patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); - s1 = 0; - s2 = 0; - } - else { - s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr*) * lm->class->index; + s1 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, table[0]) + + sizeof(methodptr) * lm->vftblindex; + } - s2 = sizeof(methodptr) * (lm - lm->class->methods); - } + /* implicit null-pointer check */ - /* Implicit null-pointer check */ - M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); - N_LHI(REG_ITMP2, s1); - N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR); - M_ALD(REG_PV, REG_METHODPTR, s2); - break; - } + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + M_ALD(REG_PV, REG_METHODPTR, s1); /* generate the actual call */ - M_CALL(REG_PV); - emit_restore_pv(cd); - - /* post call finalization */ - - switch (iptr->opc) { - case ICMD_BUILTIN: - if (bte->stub == NULL) { - M_AADD_IMM(96, REG_SP); /* remove C abi register save area */ - } - break; - } - - /* generate method profiling code */ + break; - PROFILE_CYCLE_START; + case ICMD_INVOKEINTERFACE: + /* TODO softnull REG_A0 */ - /* store size of call code in replacement point */ + /* s1 will be negative here, so use (0xFFF + s1) as displacement + * and -0xFFF in index register (itmp1) + */ - REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); - - /* store return value */ + if (INSTRUCTION_IS_UNRESOLVED(iptr)) { + um = iptr->sx.s23.s3.um; + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); - d = md->returntype.type; + s1 = 0; + s2 = 0; + } + else { + lm = iptr->sx.s23.s3.fmiref->p.method; + s1 = OFFSET(vftbl_t, interfacetable[0]) - + sizeof(methodptr*) * lm->clazz->index; - if (d != TYPE_VOID) { - if (IS_INT_LNG_TYPE(d)) { - 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); - } - } - else { - s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT); - M_FLTMOVE(REG_FRESULT, s1); - } - emit_store_dst(jd, iptr, s1); + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); } - break; + /* Implicit null-pointer check */ + M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl)); + N_LHI(REG_ITMP2, s1); + N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR); + M_ALD(REG_PV, REG_METHODPTR, s2); + /* generate the actual call */ + M_CALL(REG_PV); + break; case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */ @@ -3017,9 +2234,6 @@ gen_method: 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 */ @@ -3097,8 +2311,6 @@ gen_method: } #if 1 - CODEGEN_CRITICAL_SECTION_START; - /* REG_ITMP3 := baseval(s1) */ M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval)); @@ -3114,8 +2326,6 @@ gen_method: M_ALD_DSEG(REG_ITMP2, disp); M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval)); - CODEGEN_CRITICAL_SECTION_END; - M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */ /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */ @@ -3125,16 +2335,12 @@ gen_method: M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl)); M_ALD_DSEG(REG_ITMP3, disp); - CODEGEN_CRITICAL_SECTION_START; - M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval)); M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval)); M_ISUB(REG_ITMP3, REG_ITMP2); M_ALD_DSEG(REG_ITMP3, disp); M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); - CODEGEN_CRITICAL_SECTION_END; - M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */ /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */ /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */ @@ -3237,9 +2443,6 @@ gen_method: # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6 - 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); if (s1 == d) { @@ -3341,14 +2544,10 @@ gen_method: M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl)); M_ALD_DSEG(REG_ITMP2, disp); - CODEGEN_CRITICAL_SECTION_START; - 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)); - CODEGEN_CRITICAL_SECTION_END; - M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */ M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */ @@ -3441,66 +2640,8 @@ gen_method: break; default: - exceptions_throw_internalerror("Unknown ICMD %d", 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_traps(jd); - - /* everything's ok */ - - return true; -} - - -/* codegen_emit_stub_compiler ************************************************** - - Emits 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 */ - - /* don't touch ITMP2 as it cointains the return address */ - - M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */ - - /* REG_METHODPTR (REG_ITMP1) already used */ - M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */ - M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */ - N_BR(REG_PV); } @@ -3536,10 +2677,10 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s codeinfo *code; codegendata *cd; methoddesc *md; - s4 i, j; /* count variables */ - s4 t; - s4 s1, s2, disp; - s4 funcdisp; + int i, j; + int t; + int s1, s2; + int disp; /* get required compiler data */ @@ -3569,12 +2710,9 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s (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 code */ @@ -3585,13 +2723,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8); - /* get function address (this must happen before the stackframeinfo) */ - - funcdisp = dseg_add_functionptr(cd, f); - - if (f == NULL) - patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp); - #if defined(ENABLE_GC_CACAO) /* Save callee saved integer registers in stackframeinfo (GC may need to recover them during a collection). */ @@ -3721,13 +2852,14 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s /* put env into first argument register */ - disp = dseg_add_address(cd, _Jv_env); + disp = dseg_add_address(cd, VM_get_jnienv()); M_ALD_DSEG(REG_A0, disp); } - /* generate the actual native call */ + /* Call native function. */ - M_ALD_DSEG(REG_ITMP2, funcdisp); + disp = dseg_add_functionptr(cd, f); + M_ALD_DSEG(REG_ITMP2, disp); M_CALL(REG_ITMP2); /* save return value */ @@ -3756,7 +2888,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s M_ALD_DSEG(REG_ITMP1, disp); M_CALL(REG_ITMP1); - M_MOV(REG_RESULT, REG_ITMP3_XPTR); + M_MOV(REG_RESULT, REG_ITMP1_XPTR); /* restore return value */ @@ -3797,22 +2929,19 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s /* check for exception */ - M_TEST(REG_ITMP3_XPTR); + M_TEST(REG_ITMP1_XPTR); M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */ M_RET; /* handle exception */ - M_MOV(REG_RA, REG_ITMP1_XPC); + M_MOV(REG_RA, REG_ITMP2_XPC); + M_ASUB_IMM(2, REG_ITMP2_XPC); disp = dseg_add_functionptr(cd, asm_handle_nat_exception); M_ALD_DSEG(REG_ITMP2, disp); M_JMP(RN, REG_ITMP2); - - /* generate patcher traps */ - - emit_patcher_traps(jd); } /*