X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fx86_64%2Fcodegen.c;h=dc42a9a966075f1b9cb7a297edadb8102c9785d2;hb=219e4a46e3d127d3c0883ee2e8635b4fe3c94d60;hp=de2ceaed1f96ddeeeee41eb17cfb0b33a074e51f;hpb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;p=cacao.git diff --git a/src/vm/jit/x86_64/codegen.c b/src/vm/jit/x86_64/codegen.c index de2ceaed1..dc42a9a96 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 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -29,6 +27,7 @@ #include #include +#include #include "vm/types.h" @@ -40,39 +39,41 @@ #include "mm/memory.h" -#include "native/jni.h" #include "native/localref.h" #include "native/native.h" #include "threads/lock-common.h" -#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.h" #include "vm/jit/methodheader.h" #include "vm/jit/parse.h" -#include "vm/jit/patcher.h" +#include "vm/jit/patcher-common.hpp" #include "vm/jit/reg.h" -#include "vm/jit/replace.h" -#include "vm/jit/stacktrace.h" +#include "vm/jit/replace.hpp" +#include "vm/jit/stacktrace.hpp" +#include "vm/jit/trap.h" #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 **************************************************************** @@ -92,7 +93,6 @@ bool codegen_emit(jitdata *jd) varinfo *var, *dst; basicblock *bptr; instruction *iptr; - exception_entry *ex; constant_classref *cr; unresolved_class *uc; methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */ @@ -134,7 +134,7 @@ bool codegen_emit(jitdata *jd) #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */ - if (checksync && (m->flags & ACC_SYNCHRONIZED)) + if (checksync && code_is_synchronized(code)) cd->stackframesize++; #endif @@ -142,7 +142,7 @@ bool codegen_emit(jitdata *jd) native code e.g. libc or jni (alignment problems with movaps). */ - if (!jd->isleafmethod || opt_verbosecall) + if (!code_is_leafmethod(code) || opt_verbosecall) cd->stackframesize |= 0x1; /* create method header */ @@ -150,36 +150,16 @@ bool codegen_emit(jitdata *jd) (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 */ + code->synchronizedoffset = rd->memuse * 8; + + if (code_is_leafmethod(code)) + (void) dseg_add_unique_s4(cd, 1); /* IsLeaf */ 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, 0); /* 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 */ @@ -262,7 +242,7 @@ bool codegen_emit(jitdata *jd) /* save monitorenter argument */ #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { /* stack offset for monitor argument */ s1 = rd->memuse; @@ -282,12 +262,12 @@ bool codegen_emit(jitdata *jd) /* decide which monitor enter function to call */ if (m->flags & ACC_STATIC) { - M_MOV_IMM(&m->class->object.header, REG_A0); + M_MOV_IMM(&m->clazz->object.header, REG_A0); } else { M_TEST(REG_A0); M_BNE(8); - M_ALD_MEM(REG_A0, EXCEPTION_HARDWARE_NULLPOINTER); + M_ALD_MEM(REG_A0, TRAP_NullPointerException); } M_AST(REG_A0, REG_SP, s1 * 8); @@ -401,7 +381,7 @@ bool codegen_emit(jitdata *jd) for (iptr = bptr->iinstr; len > 0; len--, iptr++) { if (iptr->line != currentline) { - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add(cd, iptr->line); currentline = iptr->line; } @@ -421,14 +401,14 @@ bool codegen_emit(jitdata *jd) case ICMD_INLINE_BODY: REPLACEMENT_POINT_INLINE_BODY(cd, iptr); - dseg_addlinenumber_inline_start(cd, iptr); - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add_inline_start(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); break; case ICMD_INLINE_END: - dseg_addlinenumber_inline_end(cd, iptr); - dseg_addlinenumber(cd, iptr->line); + linenumbertable_list_entry_add_inline_end(cd, iptr); + linenumbertable_list_entry_add(cd, iptr->line); break; case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */ @@ -474,21 +454,26 @@ 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; + 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; @@ -1672,9 +1657,9 @@ bool codegen_emit(jitdata *jd) M_MOV(s1, REG_A0); M_MOV(s3, REG_A1); - M_MOV_IMM(BUILTIN_canstore, REG_ITMP1); + M_MOV_IMM(BUILTIN_FAST_canstore, REG_ITMP1); M_CALL(REG_ITMP1); - emit_exception_check(cd, iptr); + emit_arraystore_check(cd, iptr); s1 = emit_load_s1(jd, iptr, REG_ITMP1); s2 = emit_load_s2(jd, iptr, REG_ITMP2); @@ -1750,17 +1735,11 @@ 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); + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); /* PROFILE_CYCLE_START; */ } @@ -1768,17 +1747,14 @@ bool codegen_emit(jitdata *jd) 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)) { + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, 0); PROFILE_CYCLE_START; - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; } } @@ -1814,17 +1790,11 @@ 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); + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); /* PROFILE_CYCLE_START; */ } @@ -1832,17 +1802,14 @@ bool codegen_emit(jitdata *jd) 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)) { + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, 0); PROFILE_CYCLE_START; - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; } } @@ -1879,17 +1846,11 @@ 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); + patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp); /* PROFILE_CYCLE_START; */ } @@ -1897,17 +1858,14 @@ bool codegen_emit(jitdata *jd) 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)) { + if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) { PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0); + patcher_add_patch_ref(jd, PATCHER_initialize_class, + fi->clazz, 0); PROFILE_CYCLE_START; - - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; } } @@ -1927,8 +1885,8 @@ 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; } @@ -1945,7 +1903,7 @@ 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; */ } @@ -1990,7 +1948,7 @@ 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; */ } @@ -2031,7 +1989,7 @@ bool codegen_emit(jitdata *jd) /* PROFILE_CYCLE_STOP; */ - codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0); + patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0); /* PROFILE_CYCLE_START; */ } @@ -2050,9 +2008,12 @@ 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; } break; @@ -2071,7 +2032,7 @@ bool codegen_emit(jitdata *jd) if (INSTRUCTION_IS_UNRESOLVED(iptr)) { uc = iptr->sx.s23.s2.uc; - codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); } #endif /* ENABLE_VERIFIER */ @@ -2187,7 +2148,7 @@ bool codegen_emit(jitdata *jd) PROFILE_CYCLE_STOP; - codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0); + patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0); PROFILE_CYCLE_START; } @@ -2218,7 +2179,7 @@ nowperformreturn: #endif /* !defined(NDEBUG) */ #if defined(ENABLE_THREADS) - if (checksync && (m->flags & ACC_SYNCHRONIZED)) { + if (checksync && code_is_synchronized(code)) { M_ALD(REG_A0, REG_SP, rd->memuse * 8); /* we need to save the proper return value */ @@ -2345,6 +2306,8 @@ nowperformreturn: case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */ + REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr); + bte = iptr->sx.s23.s3.bte; md = bte->md; goto gen_method; @@ -2416,10 +2379,13 @@ gen_method: switch (iptr->opc) { case ICMD_BUILTIN: - M_MOV_IMM(bte->fp, REG_ITMP1); + 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: @@ -2428,34 +2394,22 @@ gen_method: 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 */ + disp = dseg_add_unique_address(cd, um); - if (opt_shownops) - disp -= PATCHER_CALL_SIZE; - - codegen_add_patch_ref(cd, PATCHER_invokestatic_special, + patcher_add_patch_ref(jd, 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); + patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0); s1 = 0; } @@ -2472,16 +2426,16 @@ gen_method: case ICMD_INVOKEINTERFACE: if (lm == NULL) { - codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0); + patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0); s1 = 0; s2 = 0; } else { s1 = OFFSET(vftbl_t, interfacetable[0]) - - sizeof(methodptr) * lm->class->index; + sizeof(methodptr) * lm->clazz->index; - s2 = sizeof(methodptr) * (lm - lm->class->methods); + s2 = sizeof(methodptr) * (lm - lm->clazz->methods); } /* implicit null-pointer check */ @@ -2499,6 +2453,7 @@ gen_method: /* store size of call code in replacement point */ REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr); + REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr); /* store return value */ @@ -2529,23 +2484,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 */ @@ -2554,7 +2503,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 */ @@ -2573,7 +2522,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); } @@ -2600,50 +2549,59 @@ gen_method: if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); + + 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); @@ -2663,11 +2621,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); + 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); @@ -2687,23 +2652,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); @@ -2720,7 +2679,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 */ @@ -2739,7 +2698,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); } @@ -2767,33 +2726,70 @@ gen_method: if ((super == NULL) || !(super->flags & ACC_INTERFACE)) { if (super == NULL) { emit_label(cd, BRANCH_LABEL_2); + + 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); @@ -2826,20 +2822,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 */ + 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 */ @@ -2881,11 +2883,9 @@ gen_method: } /* if (bptr -> flags >= BBREACHED) */ } /* for basic block */ - dseg_createlinenumbertable(cd); - - /* generate stubs */ + /* Generate patcher traps. */ - emit_patcher_stubs(jd); + emit_patcher_traps(jd); /* everything's ok */ @@ -2893,48 +2893,27 @@ gen_method: } -/* 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_native **************************************************** Emits a stub routine which calls a native method. *******************************************************************************/ -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; + int i, j; + int s1, s2; + int disp; - /* get required compiler data */ + /* Sanity check. */ + + assert(f != NULL); + + /* Get required compiler data. */ m = jd->m; code = jd->code; @@ -2943,29 +2922,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 */ @@ -2982,20 +2957,17 @@ 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 +#if defined(ENABLE_GC_CACAO) + /* Save callee saved integer registers in stackframeinfo (GC may + need to recover them during a collection). */ - /* get function address (this must happen before the stackframeinfo) */ + disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) + + OFFSET(stackframeinfo_t, intregs); -#if !defined(WITH_STATIC_CLASSPATH) - if (f == NULL) - codegen_add_patch_ref(cd, PATCHER_resolve_native, m, 0); + for (i = 0; i < INT_SAV_CNT; i++) + M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8); #endif - M_MOV_IMM(f, REG_ITMP3); - /* save integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { @@ -3016,17 +2988,18 @@ 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_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_ALEA(REG_SP, cd->stackframesize * 8 + SIZEOF_VOID_P, REG_A2); - M_ALD(REG_A3, REG_SP, cd->stackframesize * 8); M_MOV_IMM(codegen_start_native_call, REG_ITMP1); M_CALL(REG_ITMP1); + /* remember class argument */ + + if (m->flags & ACC_STATIC) + M_MOV(REG_RESULT, REG_ITMP2); + /* restore integer and float argument registers */ for (i = 0; i < md->paramcount; i++) { @@ -3047,15 +3020,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; @@ -3069,38 +3042,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_IMM(m->class, 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); + } + + /* Call the native function. */ - M_CALL(REG_ITMP3); + disp = dseg_add_functionptr(cd, f); + M_ALD(REG_ITMP1, RIP, disp); + M_CALL(REG_ITMP1); /* save return value */ @@ -3108,6 +3089,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: @@ -3118,14 +3113,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); @@ -3146,6 +3137,17 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f) 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_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); +#endif + /* remove stackframe */ M_AADD_IMM(cd->stackframesize * 8, REG_SP); @@ -3164,10 +3166,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); }