x64: Use external unwinding for lua_yield().

This commit is contained in:
Mike Pall 2011-03-18 23:38:05 +01:00
parent 063182d79c
commit 642ae06916
2 changed files with 18 additions and 11 deletions

View File

@ -1107,9 +1107,13 @@ LUA_API int lua_yield(lua_State *L, int nresults)
top[2].fr.tp.ftsz = (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT;
L->top = L->base = top+3;
}
#if LJ_TARGET_X64
lj_err_throw(L, LUA_YIELD);
#else
L->cframe = NULL;
L->status = LUA_YIELD;
lj_vm_unwind_c(cf, LUA_YIELD);
#endif
}
lj_err_msg(L, LJ_ERR_CYIELD);
return 0; /* unreachable */

View File

@ -502,11 +502,14 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
frame = frame_prevd(frame);
break;
case FRAME_PCALL: /* FF pcall() frame. */
if (errcode)
hook_leave(G(L));
/* fallthrough */
case FRAME_PCALLH: /* FF pcall() frame inside hook. */
if (errcode) {
if (errcode == LUA_YIELD) {
frame = frame_prevd(frame);
break;
}
if (frame_typep(frame) == FRAME_PCALL)
hook_leave(G(L));
L->cframe = cf;
L->base = frame_prevd(frame) + 1;
unwindstack(L, L->base);
@ -660,28 +663,28 @@ LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
void *cf, CONTEXT *ctx, UndocumentedDispatcherContext *dispatch)
{
lua_State *L = cframe_L(cf);
int errcode = LJ_EXCODE_CHECK(rec->ExceptionCode) ?
LJ_EXCODE_ERRCODE(rec->ExceptionCode) : LUA_ERRRUN;
if ((rec->ExceptionFlags & 6)) { /* EH_UNWINDING|EH_EXIT_UNWIND */
err_unwind(L, cf, 1); /* Unwind internal frames. */
/* Unwind internal frames. */
err_unwind(L, cf, errcode);
} else {
void *cf2 = err_unwind(L, cf, 0);
if (cf2) { /* We catch it, so start unwinding the upper frames. */
int errcode;
if (LJ_EXCODE_CHECK(rec->ExceptionCode)) {
errcode = LJ_EXCODE_ERRCODE(rec->ExceptionCode);
} else if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
if (rec->ExceptionCode == LJ_MSVC_EXCODE) {
#ifdef _MSC_VER
__DestructExceptionObject(rec, 1);
#endif
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRCPP));
errcode = LUA_ERRRUN;
} else { /* Don't catch access violations etc. */
} else if (!LJ_EXCODE_CHECK(rec->ExceptionCode)) {
/* Don't catch access violations etc. */
return ExceptionContinueSearch;
}
/* Unwind the stack and call all handlers for all lower C frames
** (including ourselves) again with EH_UNWINDING set. Then set
** rsp = cf, rax = errcode and jump to the specified target.
*/
RtlUnwindEx(cf, (void *)(cframe_unwind_ff(cf2) ?
RtlUnwindEx(cf, (void *)((cframe_unwind_ff(cf2) && errcode != LUA_YIELD) ?
lj_vm_unwind_ff_eh :
lj_vm_unwind_c_eh),
rec, (void *)errcode, ctx, dispatch->HistoryTable);