aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-04-18 13:41:30 +0200
committerMike Pall <mike>2010-04-19 00:43:35 +0200
commit932cda0fe3cbd34e60aa68479935c946f69b756f (patch)
tree9e46aa620a75b5ac5bc95413b8b7b57e507d82a1 /src/lj_asm.c
parentff82df797a5ddf6ed2610ff1808b1fdc53686ea1 (diff)
downloadluajit-932cda0fe3cbd34e60aa68479935c946f69b756f.tar.gz
luajit-932cda0fe3cbd34e60aa68479935c946f69b756f.tar.bz2
luajit-932cda0fe3cbd34e60aa68479935c946f69b756f.zip
Replace on-trace GC frame syncing with interpreter exit.
Need to sync GC objects to stack only during atomic GC phase. Need to setup a proper frame structure only for calling finalizers. Force an exit to the interpreter and let it handle the uncommon cases. Finally solves the "NYI: gcstep sync with frames" issue.
Diffstat (limited to 'src/lj_asm.c')
-rw-r--r--src/lj_asm.c66
1 files changed, 17 insertions, 49 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 75a0cd53..73416768 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -2752,67 +2752,32 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
2752 2752
2753/* -- GC handling --------------------------------------------------------- */ 2753/* -- GC handling --------------------------------------------------------- */
2754 2754
2755/* Sync all live GC values to Lua stack slots. */
2756static void asm_gc_sync(ASMState *as, SnapShot *snap, Reg base)
2757{
2758 /* Some care must be taken when allocating registers here, since this is
2759 ** not part of the fast path. All scratch registers are evicted in the
2760 ** fast path, so it's easiest to force allocation from scratch registers
2761 ** only. This avoids register allocation state unification.
2762 */
2763 RegSet allow = rset_exclude(RSET_SCRATCH & RSET_GPR, base);
2764 SnapEntry *map = &as->T->snapmap[snap->mapofs];
2765 MSize n, nent = snap->nent;
2766 for (n = 0; n < nent; n++) {
2767 SnapEntry sn = map[n];
2768 IRRef ref = snap_ref(sn);
2769 /* NYI: sync the frame, bump base, set topslot, clear new slots. */
2770 if ((sn & (SNAP_CONT|SNAP_FRAME)))
2771 lj_trace_err(as->J, LJ_TRERR_NYIGCF);
2772 if (!irref_isk(ref)) {
2773 IRIns *ir = IR(ref);
2774 if (irt_isgcv(ir->t)) {
2775 int32_t ofs = 8*(int32_t)(snap_slot(sn)-1);
2776 Reg src = ra_alloc1(as, ref, allow);
2777 emit_movtomro(as, src, base, ofs);
2778 emit_movmroi(as, base, ofs+4, irt_toitype(ir->t));
2779 checkmclim(as);
2780 }
2781 }
2782 }
2783}
2784
2785/* Check GC threshold and do one or more GC steps. */ 2755/* Check GC threshold and do one or more GC steps. */
2786static void asm_gc_check(ASMState *as, SnapShot *snap) 2756static void asm_gc_check(ASMState *as)
2787{ 2757{
2788 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit]; 2758 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
2789 IRRef args[2]; 2759 IRRef args[2];
2790 MCLabel l_end; 2760 MCLabel l_end;
2791 Reg base, lstate, tmp; 2761 Reg base, lstate, tmp;
2792 RegSet drop = RSET_SCRATCH; 2762 ra_evictset(as, RSET_SCRATCH);
2793 if (ra_hasreg(IR(REF_BASE)->r)) /* Stack may be reallocated by the GC. */
2794 drop |= RID2RSET(IR(REF_BASE)->r); /* Need to evict BASE, too. */
2795 ra_evictset(as, drop);
2796 l_end = emit_label(as); 2763 l_end = emit_label(as);
2764 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
2765 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
2766 emit_rr(as, XO_TEST, RID_RET, RID_RET);
2797 args[0] = ASMREF_L; 2767 args[0] = ASMREF_L;
2798 args[1] = ASMREF_TMP1; 2768 args[1] = ASMREF_TMP1;
2799 asm_gencall(as, ci, args); 2769 asm_gencall(as, ci, args);
2800 tmp = ra_releasetmp(as, ASMREF_TMP1); 2770 tmp = ra_releasetmp(as, ASMREF_TMP1);
2801 emit_loadi(as, tmp, (int32_t)as->gcsteps); 2771 emit_loadi(as, tmp, (int32_t)as->gcsteps);
2802 /* We don't know spadj yet, so get the C frame from L->cframe. */
2803 emit_movmroi(as, tmp, CFRAME_OFS_PC,
2804 (int32_t)as->T->snapmap[snap->mapofs+snap->nent]);
2805 emit_gri(as, XG_ARITHi(XOg_AND), tmp|REX_64, CFRAME_RAWMASK);
2806 lstate = IR(ASMREF_L)->r;
2807 emit_rmro(as, XO_MOV, tmp|REX_64, lstate, offsetof(lua_State, cframe));
2808 /* It's ok if lstate is already in a non-scratch reg. But all allocations 2772 /* It's ok if lstate is already in a non-scratch reg. But all allocations
2809 ** in the non-fast path must use a scratch reg. See comment above. 2773 ** in the non-fast path must use a scratch reg (avoids unification).
2810 */ 2774 */
2775 lstate = IR(ASMREF_L)->r;
2811 base = ra_alloc1(as, REF_BASE, rset_exclude(RSET_SCRATCH & RSET_GPR, lstate)); 2776 base = ra_alloc1(as, REF_BASE, rset_exclude(RSET_SCRATCH & RSET_GPR, lstate));
2812 emit_movtomro(as, base|REX_64, lstate, offsetof(lua_State, base)); 2777 emit_movtomro(as, base|REX_64, lstate, offsetof(lua_State, base));
2813 asm_gc_sync(as, snap, base);
2814 /* BASE/L get restored anyway, better do it inside the slow path. */ 2778 /* BASE/L get restored anyway, better do it inside the slow path. */
2815 if (as->parent || as->curins == as->loopref) ra_restore(as, REF_BASE); 2779 if (rset_test(RSET_SCRATCH, base) && (as->parent || as->snapno != 0))
2780 ra_restore(as, REF_BASE);
2816 if (rset_test(RSET_SCRATCH, lstate) && ra_hasreg(IR(ASMREF_L)->r)) 2781 if (rset_test(RSET_SCRATCH, lstate) && ra_hasreg(IR(ASMREF_L)->r))
2817 ra_restore(as, ASMREF_L); 2782 ra_restore(as, ASMREF_L);
2818 /* Jump around GC step if GC total < GC threshold. */ 2783 /* Jump around GC step if GC total < GC threshold. */
@@ -3034,7 +2999,7 @@ static void asm_loop(ASMState *as)
3034 /* LOOP is a guard, so the snapno is up to date. */ 2999 /* LOOP is a guard, so the snapno is up to date. */
3035 as->loopsnapno = as->snapno; 3000 as->loopsnapno = as->snapno;
3036 if (as->gcsteps) 3001 if (as->gcsteps)
3037 asm_gc_check(as, &as->T->snap[as->loopsnapno]); 3002 asm_gc_check(as);
3038 /* LOOP marks the transition from the variant to the invariant part. */ 3003 /* LOOP marks the transition from the variant to the invariant part. */
3039 as->testmcp = as->invmcp = NULL; 3004 as->testmcp = as->invmcp = NULL;
3040 as->sectref = 0; 3005 as->sectref = 0;
@@ -3126,7 +3091,7 @@ static void asm_head_side(ASMState *as)
3126 allow = asm_head_side_base(as, pbase, allow); 3091 allow = asm_head_side_base(as, pbase, allow);
3127 3092
3128 /* Scan all parent SLOADs and collect register dependencies. */ 3093 /* Scan all parent SLOADs and collect register dependencies. */
3129 for (i = as->curins; i > REF_BASE; i--) { 3094 for (i = as->stopins; i > REF_BASE; i--) {
3130 IRIns *ir = IR(i); 3095 IRIns *ir = IR(i);
3131 RegSP rs; 3096 RegSP rs;
3132 lua_assert(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT)); 3097 lua_assert(ir->o == IR_SLOAD && (ir->op2 & IRSLOAD_PARENT));
@@ -3161,7 +3126,7 @@ static void asm_head_side(ASMState *as)
3161 3126
3162 /* Reload spilled target registers. */ 3127 /* Reload spilled target registers. */
3163 if (pass2) { 3128 if (pass2) {
3164 for (i = as->curins; i > REF_BASE; i--) { 3129 for (i = as->stopins; i > REF_BASE; i--) {
3165 IRIns *ir = IR(i); 3130 IRIns *ir = IR(i);
3166 if (irt_ismarked(ir->t)) { 3131 if (irt_ismarked(ir->t)) {
3167 RegSet mask; 3132 RegSet mask;
@@ -3686,8 +3651,11 @@ void lj_asm_trace(jit_State *J, Trace *T)
3686 3651
3687 RA_DBG_REF(); 3652 RA_DBG_REF();
3688 checkmclim(as); 3653 checkmclim(as);
3689 if (as->gcsteps) 3654 if (as->gcsteps) {
3690 asm_gc_check(as, &as->T->snap[0]); 3655 as->curins = as->T->snap[0].ref;
3656 asm_snap_prep(as); /* The GC check is a guard. */
3657 asm_gc_check(as);
3658 }
3691 ra_evictk(as); 3659 ra_evictk(as);
3692 if (as->parent) 3660 if (as->parent)
3693 asm_head_side(as); 3661 asm_head_side(as);