Pass MULTRES or negated error code in RD to lj_vm_exit_interp.

Fixes overwrite of saved r12 after trace exit.
This commit is contained in:
Mike Pall 2010-03-23 18:31:17 +01:00
parent 097db7317b
commit 6038866f7d
6 changed files with 1867 additions and 1884 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2623,7 +2623,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|.endif |.endif
| lea FCARG1, [DISPATCH+GG_DISP2J] | lea FCARG1, [DISPATCH+GG_DISP2J]
| call extern lj_trace_exit@8 // (jit_State *J, ExitState *ex) | call extern lj_trace_exit@8 // (jit_State *J, ExitState *ex)
| // Error code returned in eax (RD). | // MULTRES or negated error code returned in eax (RD).
| mov RAa, L:RB->cframe | mov RAa, L:RB->cframe
| and RAa, CFRAME_RAWMASK | and RAa, CFRAME_RAWMASK
|.if X64WIN |.if X64WIN
@ -2638,14 +2638,12 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
| mov PC, [RAa+CFRAME_OFS_PC] // Get SAVE_PC. | mov PC, [RAa+CFRAME_OFS_PC] // Get SAVE_PC.
|.if X64 |.if X64
| jmp >1 | jmp >1
|.else
| test RD, RD; jnz >2 // Check for error from exit.
|.endif |.endif
#endif #endif
|->vm_exit_interp: |->vm_exit_interp:
| // RD = MULTRES or negated error code, BASE, PC and DISPATCH set.
#if LJ_HASJIT #if LJ_HASJIT
|.if X64 |.if X64
| xor RD, RD
| // Restore additional callee-save registers only used in compiled code. | // Restore additional callee-save registers only used in compiled code.
|.if X64WIN |.if X64WIN
| lea RAa, [rsp+9*16+4*8] | lea RAa, [rsp+9*16+4*8]
@ -2669,8 +2667,9 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
|.endif |.endif
| mov r13, TMPa | mov r13, TMPa
| mov r12, TMPQ | mov r12, TMPQ
| test RD, RD; jnz >2 // Check for error from exit.
|.endif |.endif
| test RD, RD; js >2 // Check for error from exit.
| mov MULTRES, RD
| mov LFUNC:KBASE, [BASE-8] | mov LFUNC:KBASE, [BASE-8]
| mov KBASE, LFUNC:KBASE->pc | mov KBASE, LFUNC:KBASE->pc
| mov KBASE, [KBASE+PC2PROTO(k)] | mov KBASE, [KBASE+PC2PROTO(k)]
@ -2679,6 +2678,7 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
| ins_next | ins_next
| |
|2: // Rethrow error from the right C frame. |2: // Rethrow error from the right C frame.
| neg RD
| mov FCARG1, L:RB | mov FCARG1, L:RB
| mov FCARG2, RD | mov FCARG2, RD
| call extern lj_err_throw@8 // (lua_State *L, int errcode) | call extern lj_err_throw@8 // (lua_State *L, int errcode)

File diff suppressed because it is too large Load Diff

View File

@ -3253,16 +3253,6 @@ static void asm_head_side(ASMState *as)
/* -- Tail of trace ------------------------------------------------------- */ /* -- Tail of trace ------------------------------------------------------- */
/* Set MULTRES in C frame. */
static void asm_tail_multres(ASMState *as, BCReg mres)
{
/* We don't know spadj yet, so get the C frame from L->cframe. */
emit_movmroi(as, RID_RET, CFRAME_OFS_MULTRES, mres);
emit_gri(as, XG_ARITHi(XOg_AND), RID_RET|REX_64, CFRAME_RAWMASK);
emit_rmro(as, XO_MOV, RID_RET|REX_64, RID_RET, offsetof(lua_State, cframe));
emit_getgl(as, RID_RET, jit_L);
}
/* Link to another trace. */ /* Link to another trace. */
static void asm_tail_link(ASMState *as) static void asm_tail_link(ASMState *as)
{ {
@ -3276,6 +3266,7 @@ static void asm_tail_link(ASMState *as)
if (as->T->link == TRACE_INTERP) { if (as->T->link == TRACE_INTERP) {
/* Setup fixed registers for exit to interpreter. */ /* Setup fixed registers for exit to interpreter. */
const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]); const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]);
int32_t mres;
if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */ if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */
BCIns *retpc = &as->J->trace[bc_d(*pc)]->startins; BCIns *retpc = &as->J->trace[bc_d(*pc)]->startins;
if (bc_isret(bc_op(*retpc))) if (bc_isret(bc_op(*retpc)))
@ -3283,19 +3274,14 @@ static void asm_tail_link(ASMState *as)
} }
emit_loada(as, RID_DISPATCH, J2GG(as->J)->dispatch); emit_loada(as, RID_DISPATCH, J2GG(as->J)->dispatch);
emit_loada(as, RID_PC, pc); emit_loada(as, RID_PC, pc);
mres = (int32_t)(snap->nslots - baseslot - bc_a(*pc));
switch (bc_op(*pc)) { switch (bc_op(*pc)) {
case BC_CALLM: case BC_CALLMT: case BC_CALLM: case BC_CALLMT: mres -= (int32_t)(1 + bc_c(*pc)); break;
asm_tail_multres(as, snap->nslots - baseslot - 1 - bc_a(*pc) - bc_c(*pc)); case BC_RETM: mres -= (int32_t)bc_d(*pc); break;
break; case BC_TSETM: break;
case BC_RETM: default: mres = 0; break;
asm_tail_multres(as, snap->nslots - baseslot - bc_a(*pc) - bc_d(*pc));
break;
case BC_TSETM:
asm_tail_multres(as, snap->nslots - baseslot - bc_a(*pc));
break;
default:
break;
} }
emit_loadi(as, RID_RET, mres); /* Return MULTRES or 0. */
} else if (baseslot) { } else if (baseslot) {
/* Save modified BASE for linking to trace with higher start frame. */ /* Save modified BASE for linking to trace with higher start frame. */
emit_setgl(as, RID_BASE, jit_base); emit_setgl(as, RID_BASE, jit_base);

View File

@ -671,7 +671,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
exd.exptr = exptr; exd.exptr = exptr;
errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp); errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp);
if (errcode) if (errcode)
return errcode; return -errcode; /* Return negated error code. */
lj_vmevent_send(L, TEXIT, lj_vmevent_send(L, TEXIT,
ExitState *ex = (ExitState *)exptr; ExitState *ex = (ExitState *)exptr;
@ -694,8 +694,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
pc = exd.pc; pc = exd.pc;
trace_hotside(J, pc); trace_hotside(J, pc);
cf = cframe_raw(L->cframe); cf = cframe_raw(L->cframe);
switch (bc_op(*pc)) { if (bc_op(*pc) == BC_JLOOP) {
case BC_JLOOP: {
BCIns *retpc = &J->trace[bc_d(*pc)]->startins; BCIns *retpc = &J->trace[bc_d(*pc)]->startins;
if (bc_isret(bc_op(*retpc))) { if (bc_isret(bc_op(*retpc))) {
if (J->state == LJ_TRACE_RECORD) { if (J->state == LJ_TRACE_RECORD) {
@ -706,22 +705,19 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
pc = retpc; pc = retpc;
} }
} }
break;
}
case BC_CALLM: case BC_CALLMT:
cframe_multres(cf) = (BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc);
break;
case BC_RETM:
cframe_multres(cf) = (BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc);
break;
case BC_TSETM:
cframe_multres(cf) = (BCReg)(L->top - L->base) + 1 - bc_a(*pc);
break;
default:
break;
} }
setcframe_pc(cf, pc); setcframe_pc(cf, pc);
return 0; /* Return MULTRES or 0. */
switch (bc_op(*pc)) {
case BC_CALLM: case BC_CALLMT:
return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc));
case BC_RETM:
return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc) - bc_d(*pc));
case BC_TSETM:
return (int)((BCReg)(L->top - L->base) + 1 - bc_a(*pc));
default:
return 0;
}
} }
#endif #endif