diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 17 |
1 files changed, 8 insertions, 9 deletions
@@ -306,6 +306,8 @@ void luaD_hook (lua_State *L, int event, int line, | |||
306 | ci->u2.transferinfo.ftransfer = ftransfer; | 306 | ci->u2.transferinfo.ftransfer = ftransfer; |
307 | ci->u2.transferinfo.ntransfer = ntransfer; | 307 | ci->u2.transferinfo.ntransfer = ntransfer; |
308 | } | 308 | } |
309 | if (isLua(ci) && L->top < ci->top) | ||
310 | L->top = ci->top; /* protect entire activation register */ | ||
309 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 311 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
310 | if (ci->top < L->top + LUA_MINSTACK) | 312 | if (ci->top < L->top + LUA_MINSTACK) |
311 | ci->top = L->top + LUA_MINSTACK; | 313 | ci->top = L->top + LUA_MINSTACK; |
@@ -333,7 +335,6 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { | |||
333 | int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL | 335 | int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL |
334 | : LUA_HOOKCALL; | 336 | : LUA_HOOKCALL; |
335 | Proto *p = ci_func(ci)->p; | 337 | Proto *p = ci_func(ci)->p; |
336 | L->top = ci->top; /* prepare top */ | ||
337 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 338 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
338 | luaD_hook(L, event, -1, 1, p->numparams); | 339 | luaD_hook(L, event, -1, 1, p->numparams); |
339 | ci->u.l.savedpc--; /* correct 'pc' */ | 340 | ci->u.l.savedpc--; /* correct 'pc' */ |
@@ -349,21 +350,17 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { | |||
349 | static void rethook (lua_State *L, CallInfo *ci, int nres) { | 350 | static void rethook (lua_State *L, CallInfo *ci, int nres) { |
350 | if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ | 351 | if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ |
351 | StkId firstres = L->top - nres; /* index of first result */ | 352 | StkId firstres = L->top - nres; /* index of first result */ |
352 | ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */ | ||
353 | int delta = 0; /* correction for vararg functions */ | 353 | int delta = 0; /* correction for vararg functions */ |
354 | int ftransfer; | 354 | int ftransfer; |
355 | if (isLuacode(ci)) { | 355 | if (isLua(ci)) { |
356 | Proto *p = ci_func(ci)->p; | 356 | Proto *p = ci_func(ci)->p; |
357 | if (p->is_vararg) | 357 | if (p->is_vararg) |
358 | delta = ci->u.l.nextraargs + p->numparams + 1; | 358 | delta = ci->u.l.nextraargs + p->numparams + 1; |
359 | if (L->top < ci->top) | ||
360 | L->top = ci->top; /* correct top to run hook */ | ||
361 | } | 359 | } |
362 | ci->func += delta; /* if vararg, back to virtual 'func' */ | 360 | ci->func += delta; /* if vararg, back to virtual 'func' */ |
363 | ftransfer = cast(unsigned short, firstres - ci->func); | 361 | ftransfer = cast(unsigned short, firstres - ci->func); |
364 | luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ | 362 | luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ |
365 | ci->func -= delta; | 363 | ci->func -= delta; |
366 | L->top = restorestack(L, oldtop); | ||
367 | } | 364 | } |
368 | if (isLua(ci = ci->previous)) | 365 | if (isLua(ci = ci->previous)) |
369 | L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */ | 366 | L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */ |
@@ -707,8 +704,10 @@ static void resume (lua_State *L, void *ud) { | |||
707 | lua_assert(L->status == LUA_YIELD); | 704 | lua_assert(L->status == LUA_YIELD); |
708 | L->status = LUA_OK; /* mark that it is running (again) */ | 705 | L->status = LUA_OK; /* mark that it is running (again) */ |
709 | luaE_incCstack(L); /* control the C stack */ | 706 | luaE_incCstack(L); /* control the C stack */ |
710 | if (isLua(ci)) /* yielded inside a hook? */ | 707 | if (isLua(ci)) { /* yielded inside a hook? */ |
708 | L->top = firstArg; /* discard arguments */ | ||
711 | luaV_execute(L, ci); /* just continue running Lua code */ | 709 | luaV_execute(L, ci); /* just continue running Lua code */ |
710 | } | ||
712 | else { /* 'common' yield */ | 711 | else { /* 'common' yield */ |
713 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ | 712 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
714 | lua_unlock(L); | 713 | lua_unlock(L); |
@@ -793,15 +792,15 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
793 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 792 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
794 | } | 793 | } |
795 | L->status = LUA_YIELD; | 794 | L->status = LUA_YIELD; |
795 | ci->u2.nyield = nresults; /* save number of results */ | ||
796 | if (isLua(ci)) { /* inside a hook? */ | 796 | if (isLua(ci)) { /* inside a hook? */ |
797 | lua_assert(!isLuacode(ci)); | 797 | lua_assert(!isLuacode(ci)); |
798 | api_check(L, nresults == 0, "hooks cannot yield values"); | ||
798 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | 799 | api_check(L, k == NULL, "hooks cannot continue after yielding"); |
799 | ci->u2.nyield = 0; /* no results */ | ||
800 | } | 800 | } |
801 | else { | 801 | else { |
802 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ | 802 | if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ |
803 | ci->u.c.ctx = ctx; /* save context */ | 803 | ci->u.c.ctx = ctx; /* save context */ |
804 | ci->u2.nyield = nresults; /* save number of results */ | ||
805 | luaD_throw(L, LUA_YIELD); | 804 | luaD_throw(L, LUA_YIELD); |
806 | } | 805 | } |
807 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | 806 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ |