diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-07-16 17:49:02 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-07-16 17:49:02 -0300 |
commit | fa26d294aef136aa4ec48c23b4b87b853df0e3da (patch) | |
tree | f8ccce58fe28fbc116f082766eecf3a50812c82d /ldo.c | |
parent | 5a761e3a1519eae7264209db8257b040c77556aa (diff) | |
download | lua-fa26d294aef136aa4ec48c23b4b87b853df0e3da.tar.gz lua-fa26d294aef136aa4ec48c23b4b87b853df0e3da.tar.bz2 lua-fa26d294aef136aa4ec48c23b4b87b853df0e3da.zip |
new way to control `pc' of running functions
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 47 |
1 files changed, 21 insertions, 26 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.218 2003/05/13 19:22:19 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.219 2003/05/14 21:02:39 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 | */ |
@@ -243,6 +243,7 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
243 | cl = &clvalue(func)->l; | 243 | cl = &clvalue(func)->l; |
244 | if (!cl->isC) { /* Lua function? prepare its call */ | 244 | if (!cl->isC) { /* Lua function? prepare its call */ |
245 | CallInfo *ci; | 245 | CallInfo *ci; |
246 | StkId st; | ||
246 | Proto *p = cl->p; | 247 | Proto *p = cl->p; |
247 | if (p->is_vararg) /* varargs? */ | 248 | if (p->is_vararg) /* varargs? */ |
248 | adjust_varargs(L, p->numparams, func+1); | 249 | adjust_varargs(L, p->numparams, func+1); |
@@ -252,9 +253,8 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
252 | ci->top = L->base + p->maxstacksize; | 253 | ci->top = L->base + p->maxstacksize; |
253 | ci->u.l.savedpc = p->code; /* starting point */ | 254 | ci->u.l.savedpc = p->code; /* starting point */ |
254 | ci->u.l.tailcalls = 0; | 255 | ci->u.l.tailcalls = 0; |
255 | ci->state = CI_SAVEDPC; | 256 | for (st = L->top; st < ci->top; st++) |
256 | while (L->top < ci->top) | 257 | setnilvalue(st); |
257 | setnilvalue(L->top++); | ||
258 | L->top = ci->top; | 258 | L->top = ci->top; |
259 | return NULL; | 259 | return NULL; |
260 | } | 260 | } |
@@ -265,7 +265,6 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
265 | ci = ++L->ci; /* now `enter' new function */ | 265 | ci = ++L->ci; /* now `enter' new function */ |
266 | L->base = L->ci->base = restorestack(L, funcr) + 1; | 266 | L->base = L->ci->base = restorestack(L, funcr) + 1; |
267 | ci->top = L->top + LUA_MINSTACK; | 267 | ci->top = L->top + LUA_MINSTACK; |
268 | ci->state = CI_C; /* a C function */ | ||
269 | if (L->hookmask & LUA_MASKCALL) | 268 | if (L->hookmask & LUA_MASKCALL) |
270 | luaD_callhook(L, LUA_HOOKCALL, -1); | 269 | luaD_callhook(L, LUA_HOOKCALL, -1); |
271 | lua_unlock(L); | 270 | lua_unlock(L); |
@@ -279,7 +278,7 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
279 | static StkId callrethooks (lua_State *L, StkId firstResult) { | 278 | static StkId callrethooks (lua_State *L, StkId firstResult) { |
280 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | 279 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ |
281 | luaD_callhook(L, LUA_HOOKRET, -1); | 280 | luaD_callhook(L, LUA_HOOKRET, -1); |
282 | if (!(L->ci->state & CI_C)) { /* Lua function? */ | 281 | if (f_isLua(L->ci)) { /* Lua function? */ |
283 | while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ | 282 | while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ |
284 | luaD_callhook(L, LUA_HOOKTAILRET, -1); | 283 | luaD_callhook(L, LUA_HOOKTAILRET, -1); |
285 | } | 284 | } |
@@ -313,7 +312,6 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | |||
313 | */ | 312 | */ |
314 | void luaD_call (lua_State *L, StkId func, int nResults) { | 313 | void luaD_call (lua_State *L, StkId func, int nResults) { |
315 | StkId firstResult; | 314 | StkId firstResult; |
316 | lua_assert(!(L->ci->state & CI_CALLING)); | ||
317 | if (++L->nCcalls >= LUA_MAXCCALLS) { | 315 | if (++L->nCcalls >= LUA_MAXCCALLS) { |
318 | if (L->nCcalls == LUA_MAXCCALLS) | 316 | if (L->nCcalls == LUA_MAXCCALLS) |
319 | luaG_runerror(L, "C stack overflow"); | 317 | luaG_runerror(L, "C stack overflow"); |
@@ -322,7 +320,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
322 | } | 320 | } |
323 | firstResult = luaD_precall(L, func); | 321 | firstResult = luaD_precall(L, func); |
324 | if (firstResult == NULL) /* is a Lua function? */ | 322 | if (firstResult == NULL) /* is a Lua function? */ |
325 | firstResult = luaV_execute(L); /* call it */ | 323 | firstResult = luaV_execute(L, 1); /* call it */ |
326 | luaD_poscall(L, nResults, firstResult); | 324 | luaD_poscall(L, nResults, firstResult); |
327 | L->nCcalls--; | 325 | L->nCcalls--; |
328 | luaC_checkGC(L); | 326 | luaC_checkGC(L); |
@@ -333,29 +331,28 @@ static void resume (lua_State *L, void *ud) { | |||
333 | StkId firstResult; | 331 | StkId firstResult; |
334 | int nargs = *cast(int *, ud); | 332 | int nargs = *cast(int *, ud); |
335 | CallInfo *ci = L->ci; | 333 | CallInfo *ci = L->ci; |
336 | if (ci == L->base_ci) { /* no activation record? */ | 334 | if (!L->isSuspended) { |
337 | if (nargs >= L->top - L->base) | 335 | if (ci == L->base_ci) { /* no activation record? */ |
338 | luaG_runerror(L, "cannot resume dead coroutine"); | 336 | if (nargs >= L->top - L->base) |
339 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | 337 | luaG_runerror(L, "cannot resume dead coroutine"); |
338 | luaD_precall(L, L->top - (nargs + 1)); /* start coroutine */ | ||
339 | } | ||
340 | else | ||
341 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | ||
340 | } | 342 | } |
341 | else if (ci->state & CI_YIELD) { /* inside a yield? */ | 343 | else { /* resumming from previous yield */ |
342 | if (ci->state & CI_C) { /* `common' yield? */ | 344 | if (!f_isLua(ci)) { /* `common' yield? */ |
343 | /* finish interrupted execution of `OP_CALL' */ | 345 | /* finish interrupted execution of `OP_CALL' */ |
344 | int nresults; | 346 | int nresults; |
345 | lua_assert((ci-1)->state & CI_SAVEDPC); | ||
346 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || | 347 | lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL || |
347 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); | 348 | GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL); |
348 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; | 349 | nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1; |
349 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ | 350 | luaD_poscall(L, nresults, L->top - nargs); /* complete it */ |
350 | if (nresults >= 0) L->top = L->ci->top; | 351 | if (nresults >= 0) L->top = L->ci->top; |
351 | } | 352 | } /* else yielded inside a hook: just continue its execution */ |
352 | else { /* yielded inside a hook: just continue its execution */ | ||
353 | ci->state &= ~CI_YIELD; | ||
354 | } | ||
355 | } | 353 | } |
356 | else | 354 | L->isSuspended = 0; |
357 | luaG_runerror(L, "cannot resume non-suspended coroutine"); | 355 | firstResult = luaV_execute(L, L->ci - L->base_ci); |
358 | firstResult = luaV_execute(L); | ||
359 | if (firstResult != NULL) /* return? */ | 356 | if (firstResult != NULL) /* return? */ |
360 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | 357 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ |
361 | } | 358 | } |
@@ -388,9 +385,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
388 | ci = L->ci; | 385 | ci = L->ci; |
389 | if (L->nCcalls > 0) | 386 | if (L->nCcalls > 0) |
390 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); | 387 | luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); |
391 | if (ci->state & CI_C) { /* usual yield */ | 388 | if (!f_isLua(ci)) { /* usual yield */ |
392 | if ((ci-1)->state & CI_C) | ||
393 | luaG_runerror(L, "cannot yield a C function"); | ||
394 | if (L->top - nresults > L->base) { /* is there garbage in the stack? */ | 389 | if (L->top - nresults > L->base) { /* is there garbage in the stack? */ |
395 | int i; | 390 | int i; |
396 | for (i=0; i<nresults; i++) /* move down results */ | 391 | for (i=0; i<nresults; i++) /* move down results */ |
@@ -398,7 +393,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
398 | L->top = L->base + nresults; | 393 | L->top = L->base + nresults; |
399 | } | 394 | } |
400 | } /* else it's an yield inside a hook: nothing to do */ | 395 | } /* else it's an yield inside a hook: nothing to do */ |
401 | ci->state |= CI_YIELD; | 396 | L->isSuspended = 1; |
402 | lua_unlock(L); | 397 | lua_unlock(L); |
403 | return -1; | 398 | return -1; |
404 | } | 399 | } |