diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 33 |
1 files changed, 19 insertions, 14 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.45 2007/03/27 14:11:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.46 2008/01/18 22:36:50 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -193,6 +193,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
193 | ar.i_ci = cast_int(L->ci - L->base_ci); | 193 | ar.i_ci = cast_int(L->ci - L->base_ci); |
194 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 194 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
195 | L->ci->top = L->top + LUA_MINSTACK; | 195 | L->ci->top = L->top + LUA_MINSTACK; |
196 | L->ci->status |= 1; /* this level is running a hook */ | ||
196 | lua_assert(L->ci->top <= L->stack_last); | 197 | lua_assert(L->ci->top <= L->stack_last); |
197 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 198 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
198 | lua_unlock(L); | 199 | lua_unlock(L); |
@@ -202,6 +203,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
202 | L->allowhook = 1; | 203 | L->allowhook = 1; |
203 | L->ci->top = restorestack(L, ci_top); | 204 | L->ci->top = restorestack(L, ci_top); |
204 | L->top = restorestack(L, top); | 205 | L->top = restorestack(L, top); |
206 | L->ci->status &= ~1; /* this level is not running a hook anymore */ | ||
205 | } | 207 | } |
206 | } | 208 | } |
207 | 209 | ||
@@ -264,6 +266,9 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
264 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) | 266 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) |
265 | 267 | ||
266 | 268 | ||
269 | /* | ||
270 | ** returns true if function has been executed (C function) | ||
271 | */ | ||
267 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 272 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
268 | LClosure *cl; | 273 | LClosure *cl; |
269 | ptrdiff_t funcr; | 274 | ptrdiff_t funcr; |
@@ -292,6 +297,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
292 | lua_assert(ci->top <= L->stack_last); | 297 | lua_assert(ci->top <= L->stack_last); |
293 | L->savedpc = p->code; /* starting point */ | 298 | L->savedpc = p->code; /* starting point */ |
294 | ci->tailcalls = 0; | 299 | ci->tailcalls = 0; |
300 | ci->status = 0; | ||
295 | ci->nresults = nresults; | 301 | ci->nresults = nresults; |
296 | for (st = L->top; st < ci->top; st++) | 302 | for (st = L->top; st < ci->top; st++) |
297 | setnilvalue(st); | 303 | setnilvalue(st); |
@@ -301,7 +307,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
301 | luaD_callhook(L, LUA_HOOKCALL, -1); | 307 | luaD_callhook(L, LUA_HOOKCALL, -1); |
302 | L->savedpc--; /* correct 'pc' */ | 308 | L->savedpc--; /* correct 'pc' */ |
303 | } | 309 | } |
304 | return PCRLUA; | 310 | return 0; |
305 | } | 311 | } |
306 | else { /* if is a C function, call it */ | 312 | else { /* if is a C function, call it */ |
307 | CallInfo *ci; | 313 | CallInfo *ci; |
@@ -318,12 +324,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
318 | lua_unlock(L); | 324 | lua_unlock(L); |
319 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | 325 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ |
320 | lua_lock(L); | 326 | lua_lock(L); |
321 | if (n < 0) /* yielding? */ | 327 | luaD_poscall(L, L->top - n); |
322 | return PCRYIELD; | 328 | return 1; |
323 | else { | ||
324 | luaD_poscall(L, L->top - n); | ||
325 | return PCRC; | ||
326 | } | ||
327 | } | 329 | } |
328 | } | 330 | } |
329 | 331 | ||
@@ -378,7 +380,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
378 | else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) | 380 | else if (g->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) |
379 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | 381 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ |
380 | } | 382 | } |
381 | if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ | 383 | if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ |
382 | luaV_execute(L, 1); /* call it */ | 384 | luaV_execute(L, 1); /* call it */ |
383 | g->nCcalls--; | 385 | g->nCcalls--; |
384 | luaC_checkGC(L); | 386 | luaC_checkGC(L); |
@@ -390,8 +392,8 @@ static void resume (lua_State *L, void *ud) { | |||
390 | CallInfo *ci = L->ci; | 392 | CallInfo *ci = L->ci; |
391 | if (L->status == LUA_OK) { /* start coroutine? */ | 393 | if (L->status == LUA_OK) { /* start coroutine? */ |
392 | lua_assert(ci == L->base_ci && firstArg > L->base); | 394 | lua_assert(ci == L->base_ci && firstArg > L->base); |
393 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) | 395 | if (luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* C function? */ |
394 | return; | 396 | return; /* done */ |
395 | } | 397 | } |
396 | else { /* resuming from previous yield */ | 398 | else { /* resuming from previous yield */ |
397 | lua_assert(L->status == LUA_YIELD); | 399 | lua_assert(L->status == LUA_YIELD); |
@@ -434,14 +436,14 @@ LUA_API int lua_resume (lua_State *L, int nargs) { | |||
434 | return resume_error(L, "C stack overflow"); | 436 | return resume_error(L, "C stack overflow"); |
435 | L->baseCcalls = ++G(L)->nCcalls; | 437 | L->baseCcalls = ++G(L)->nCcalls; |
436 | status = luaD_rawrunprotected(L, resume, L->top - nargs); | 438 | status = luaD_rawrunprotected(L, resume, L->top - nargs); |
437 | if (status != LUA_OK) { /* error? */ | 439 | if (status != LUA_OK && status != LUA_YIELD) { /* error? */ |
438 | L->status = cast_byte(status); /* mark thread as `dead' */ | 440 | L->status = cast_byte(status); /* mark thread as `dead' */ |
439 | luaD_seterrorobj(L, status, L->top); | 441 | luaD_seterrorobj(L, status, L->top); |
440 | L->ci->top = L->top; | 442 | L->ci->top = L->top; |
441 | } | 443 | } |
442 | else { | 444 | else { |
443 | lua_assert(L->baseCcalls == G(L)->nCcalls); | 445 | lua_assert(L->baseCcalls == G(L)->nCcalls); |
444 | status = L->status; | 446 | lua_assert(status == L->status); |
445 | } | 447 | } |
446 | --G(L)->nCcalls; | 448 | --G(L)->nCcalls; |
447 | L->baseCcalls = 0; | 449 | L->baseCcalls = 0; |
@@ -457,8 +459,11 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
457 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | 459 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); |
458 | L->base = L->top - nresults; /* protect stack slots below */ | 460 | L->base = L->top - nresults; /* protect stack slots below */ |
459 | L->status = LUA_YIELD; | 461 | L->status = LUA_YIELD; |
462 | if (!isLua(L->ci)) /* not inside a hook? */ | ||
463 | luaD_throw(L, LUA_YIELD); | ||
464 | lua_assert(L->ci->status & 1); /* must be inside a hook */ | ||
460 | lua_unlock(L); | 465 | lua_unlock(L); |
461 | return -1; | 466 | return 0; /* otherwise, return to 'luaD_callhook' */ |
462 | } | 467 | } |
463 | 468 | ||
464 | 469 | ||