Mercurial > vba-clojure
view src/lua/ldo.c @ 555:2d9bf762a073
tightened up control transfer waiting period.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 31 Aug 2012 00:52:33 -0500 |
parents | 27763b933818 |
children |
line wrap: on
line source
1 /*2 ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $3 ** Stack and Call structure of Lua4 ** See Copyright Notice in lua.h5 */8 #include <setjmp.h>9 #include <stdlib.h>10 #include <string.h>12 #define ldo_c13 #define LUA_CORE15 #include "lua.h"17 #include "ldebug.h"18 #include "ldo.h"19 #include "lfunc.h"20 #include "lgc.h"21 #include "lmem.h"22 #include "lobject.h"23 #include "lopcodes.h"24 #include "lparser.h"25 #include "lstate.h"26 #include "lstring.h"27 #include "ltable.h"28 #include "ltm.h"29 #include "lundump.h"30 #include "lvm.h"31 #include "lzio.h"36 /*37 ** {======================================================38 ** Error-recovery functions39 ** =======================================================40 */43 /* chain list of long jump buffers */44 struct lua_longjmp {45 struct lua_longjmp *previous;46 luai_jmpbuf b;47 volatile int status; /* error code */48 };51 void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {52 switch (errcode) {53 case LUA_ERRMEM: {54 setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));55 break;56 }57 case LUA_ERRERR: {58 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));59 break;60 }61 case LUA_ERRSYNTAX:62 case LUA_ERRRUN: {63 setobjs2s(L, oldtop, L->top - 1); /* error message on current top */64 break;65 }66 }67 L->top = oldtop + 1;68 }71 static void restore_stack_limit (lua_State *L) {72 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);73 if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */74 int inuse = cast_int(L->ci - L->base_ci);75 if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */76 luaD_reallocCI(L, LUAI_MAXCALLS);77 }78 }81 static void resetstack (lua_State *L, int status) {82 L->ci = L->base_ci;83 L->base = L->ci->base;84 luaF_close(L, L->base); /* close eventual pending closures */85 luaD_seterrorobj(L, status, L->base);86 L->nCcalls = L->baseCcalls;87 L->allowhook = 1;88 restore_stack_limit(L);89 L->errfunc = 0;90 L->errorJmp = NULL;91 }94 void luaD_throw (lua_State *L, int errcode) {95 if (L->errorJmp) {96 L->errorJmp->status = errcode;97 LUAI_THROW(L, L->errorJmp);98 }99 else {100 L->status = cast_byte(errcode);101 if (G(L)->panic) {102 resetstack(L, errcode);103 lua_unlock(L);104 G(L)->panic(L);105 }106 exit(EXIT_FAILURE);107 }108 }111 int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {112 struct lua_longjmp lj;113 lj.status = 0;114 lj.previous = L->errorJmp; /* chain new error handler */115 L->errorJmp = &lj;116 LUAI_TRY(L, &lj,117 (*f)(L, ud);118 );119 L->errorJmp = lj.previous; /* restore old error handler */120 return lj.status;121 }123 /* }====================================================== */126 static void correctstack (lua_State *L, TValue *oldstack) {127 CallInfo *ci;128 GCObject *up;129 L->top = (L->top - oldstack) + L->stack;130 for (up = L->openupval; up != NULL; up = up->gch.next)131 gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;132 for (ci = L->base_ci; ci <= L->ci; ci++) {133 ci->top = (ci->top - oldstack) + L->stack;134 ci->base = (ci->base - oldstack) + L->stack;135 ci->func = (ci->func - oldstack) + L->stack;136 }137 L->base = (L->base - oldstack) + L->stack;138 }141 void luaD_reallocstack (lua_State *L, int newsize) {142 TValue *oldstack = L->stack;143 int realsize = newsize + 1 + EXTRA_STACK;144 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);145 luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);146 L->stacksize = realsize;147 L->stack_last = L->stack+newsize;148 correctstack(L, oldstack);149 }152 void luaD_reallocCI (lua_State *L, int newsize) {153 CallInfo *oldci = L->base_ci;154 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);155 L->size_ci = newsize;156 L->ci = (L->ci - oldci) + L->base_ci;157 L->end_ci = L->base_ci + L->size_ci - 1;158 }161 void luaD_growstack (lua_State *L, int n) {162 if (n <= L->stacksize) /* double size is enough? */163 luaD_reallocstack(L, 2*L->stacksize);164 else165 luaD_reallocstack(L, L->stacksize + n);166 }169 static CallInfo *growCI (lua_State *L) {170 if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */171 luaD_throw(L, LUA_ERRERR);172 else {173 luaD_reallocCI(L, 2*L->size_ci);174 if (L->size_ci > LUAI_MAXCALLS)175 luaG_runerror(L, "stack overflow");176 }177 return ++L->ci;178 }181 void luaD_callhook (lua_State *L, int event, int line) {182 lua_Hook hook = L->hook;183 if (hook && L->allowhook) {184 ptrdiff_t top = savestack(L, L->top);185 ptrdiff_t ci_top = savestack(L, L->ci->top);186 lua_Debug ar;187 ar.event = event;188 ar.currentline = line;189 if (event == LUA_HOOKTAILRET)190 ar.i_ci = 0; /* tail call; no debug information about it */191 else192 ar.i_ci = cast_int(L->ci - L->base_ci);193 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */194 L->ci->top = L->top + LUA_MINSTACK;195 lua_assert(L->ci->top <= L->stack_last);196 L->allowhook = 0; /* cannot call hooks inside a hook */197 lua_unlock(L);198 (*hook)(L, &ar);199 lua_lock(L);200 lua_assert(!L->allowhook);201 L->allowhook = 1;202 L->ci->top = restorestack(L, ci_top);203 L->top = restorestack(L, top);204 }205 }208 static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {209 int i;210 int nfixargs = p->numparams;211 Table *htab = NULL;212 StkId base, fixed;213 for (; actual < nfixargs; ++actual)214 setnilvalue(L->top++);215 #if defined(LUA_COMPAT_VARARG)216 if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */217 int nvar = actual - nfixargs; /* number of extra arguments */218 lua_assert(p->is_vararg & VARARG_HASARG);219 luaC_checkGC(L);220 htab = luaH_new(L, nvar, 1); /* create `arg' table */221 for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */222 setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);223 /* store counter in field `n' */224 setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));225 }226 #endif227 /* move fixed parameters to final position */228 fixed = L->top - actual; /* first fixed argument */229 base = L->top; /* final position of first argument */230 for (i=0; i<nfixargs; i++) {231 setobjs2s(L, L->top++, fixed+i);232 setnilvalue(fixed+i);233 }234 /* add `arg' parameter */235 if (htab) {236 sethvalue(L, L->top++, htab);237 lua_assert(iswhite(obj2gco(htab)));238 }239 return base;240 }243 static StkId tryfuncTM (lua_State *L, StkId func) {244 const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);245 StkId p;246 ptrdiff_t funcr = savestack(L, func);247 if (!ttisfunction(tm))248 luaG_typeerror(L, func, "call");249 /* Open a hole inside the stack at `func' */250 for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);251 incr_top(L);252 func = restorestack(L, funcr); /* previous call may change stack */253 setobj2s(L, func, tm); /* tag method is the new function to be called */254 return func;255 }259 #define inc_ci(L) \260 ((L->ci == L->end_ci) ? growCI(L) : \261 (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))264 int luaD_precall (lua_State *L, StkId func, int nresults) {265 LClosure *cl;266 ptrdiff_t funcr;267 if (!ttisfunction(func)) /* `func' is not a function? */268 func = tryfuncTM(L, func); /* check the `function' tag method */269 funcr = savestack(L, func);270 cl = &clvalue(func)->l;271 L->ci->savedpc = L->savedpc;272 if (!cl->isC) { /* Lua function? prepare its call */273 CallInfo *ci;274 StkId st, base;275 Proto *p = cl->p;276 luaD_checkstack(L, p->maxstacksize);277 func = restorestack(L, funcr);278 if (!p->is_vararg) { /* no varargs? */279 base = func + 1;280 if (L->top > base + p->numparams)281 L->top = base + p->numparams;282 }283 else { /* vararg function */284 int nargs = cast_int(L->top - func) - 1;285 base = adjust_varargs(L, p, nargs);286 func = restorestack(L, funcr); /* previous call may change the stack */287 }288 ci = inc_ci(L); /* now `enter' new function */289 ci->func = func;290 L->base = ci->base = base;291 ci->top = L->base + p->maxstacksize;292 lua_assert(ci->top <= L->stack_last);293 L->savedpc = p->code; /* starting point */294 ci->tailcalls = 0;295 ci->nresults = nresults;296 for (st = L->top; st < ci->top; st++)297 setnilvalue(st);298 L->top = ci->top;299 if (L->hookmask & LUA_MASKCALL) {300 L->savedpc++; /* hooks assume 'pc' is already incremented */301 luaD_callhook(L, LUA_HOOKCALL, -1);302 L->savedpc--; /* correct 'pc' */303 }304 return PCRLUA;305 }306 else { /* if is a C function, call it */307 CallInfo *ci;308 int n;309 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */310 ci = inc_ci(L); /* now `enter' new function */311 ci->func = restorestack(L, funcr);312 L->base = ci->base = ci->func + 1;313 ci->top = L->top + LUA_MINSTACK;314 lua_assert(ci->top <= L->stack_last);315 ci->nresults = nresults;316 if (L->hookmask & LUA_MASKCALL)317 luaD_callhook(L, LUA_HOOKCALL, -1);318 lua_unlock(L);319 n = (*curr_func(L)->c.f)(L); /* do the actual call */320 lua_lock(L);321 if (n < 0) /* yielding? */322 return PCRYIELD;323 else {324 luaD_poscall(L, L->top - n);325 return PCRC;326 }327 }328 }331 static StkId callrethooks (lua_State *L, StkId firstResult) {332 ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */333 luaD_callhook(L, LUA_HOOKRET, -1);334 if (f_isLua(L->ci)) { /* Lua function? */335 while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */336 luaD_callhook(L, LUA_HOOKTAILRET, -1);337 }338 return restorestack(L, fr);339 }342 int luaD_poscall (lua_State *L, StkId firstResult) {343 StkId res;344 int wanted, i;345 CallInfo *ci;346 if (L->hookmask & LUA_MASKRET)347 firstResult = callrethooks(L, firstResult);348 ci = L->ci--;349 res = ci->func; /* res == final position of 1st result */350 wanted = ci->nresults;351 L->base = (ci - 1)->base; /* restore base */352 L->savedpc = (ci - 1)->savedpc; /* restore savedpc */353 /* move results to correct place */354 for (i = wanted; i != 0 && firstResult < L->top; i--)355 setobjs2s(L, res++, firstResult++);356 while (i-- > 0)357 setnilvalue(res++);358 L->top = res;359 return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */360 }363 /*364 ** Call a function (C or Lua). The function to be called is at *func.365 ** The arguments are on the stack, right after the function.366 ** When returns, all the results are on the stack, starting at the original367 ** function position.368 */369 void luaD_call (lua_State *L, StkId func, int nResults) {370 if (++L->nCcalls >= LUAI_MAXCCALLS) {371 if (L->nCcalls == LUAI_MAXCCALLS)372 luaG_runerror(L, "C stack overflow");373 else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))374 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */375 }376 if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */377 luaV_execute(L, 1); /* call it */378 L->nCcalls--;379 luaC_checkGC(L);380 }383 static void resume (lua_State *L, void *ud) {384 StkId firstArg = cast(StkId, ud);385 CallInfo *ci = L->ci;386 if (L->status == 0) { /* start coroutine? */387 lua_assert(ci == L->base_ci && firstArg > L->base);388 if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)389 return;390 }391 else { /* resuming from previous yield */392 lua_assert(L->status == LUA_YIELD);393 L->status = 0;394 if (!f_isLua(ci)) { /* `common' yield? */395 /* finish interrupted execution of `OP_CALL' */396 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||397 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);398 if (luaD_poscall(L, firstArg)) /* complete it... */399 L->top = L->ci->top; /* and correct top if not multiple results */400 }401 else /* yielded inside a hook: just continue its execution */402 L->base = L->ci->base;403 }404 luaV_execute(L, cast_int(L->ci - L->base_ci));405 }408 static int resume_error (lua_State *L, const char *msg) {409 L->top = L->ci->base;410 setsvalue2s(L, L->top, luaS_new(L, msg));411 incr_top(L);412 lua_unlock(L);413 return LUA_ERRRUN;414 }417 LUA_API int lua_resume (lua_State *L, int nargs) {418 int status;419 lua_lock(L);420 if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))421 return resume_error(L, "cannot resume non-suspended coroutine");422 if (L->nCcalls >= LUAI_MAXCCALLS)423 return resume_error(L, "C stack overflow");424 luai_userstateresume(L, nargs);425 lua_assert(L->errfunc == 0);426 L->baseCcalls = ++L->nCcalls;427 status = luaD_rawrunprotected(L, resume, L->top - nargs);428 if (status != 0) { /* error? */429 L->status = cast_byte(status); /* mark thread as `dead' */430 luaD_seterrorobj(L, status, L->top);431 L->ci->top = L->top;432 }433 else {434 lua_assert(L->nCcalls == L->baseCcalls);435 status = L->status;436 }437 --L->nCcalls;438 lua_unlock(L);439 return status;440 }443 LUA_API int lua_yield (lua_State *L, int nresults) {444 luai_userstateyield(L, nresults);445 lua_lock(L);446 if (L->nCcalls > L->baseCcalls)447 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");448 L->base = L->top - nresults; /* protect stack slots below */449 L->status = LUA_YIELD;450 lua_unlock(L);451 return -1;452 }455 int luaD_pcall (lua_State *L, Pfunc func, void *u,456 ptrdiff_t old_top, ptrdiff_t ef) {457 int status;458 unsigned short oldnCcalls = L->nCcalls;459 ptrdiff_t old_ci = saveci(L, L->ci);460 lu_byte old_allowhooks = L->allowhook;461 ptrdiff_t old_errfunc = L->errfunc;462 L->errfunc = ef;463 status = luaD_rawrunprotected(L, func, u);464 if (status != 0) { /* an error occurred? */465 StkId oldtop = restorestack(L, old_top);466 luaF_close(L, oldtop); /* close eventual pending closures */467 luaD_seterrorobj(L, status, oldtop);468 L->nCcalls = oldnCcalls;469 L->ci = restoreci(L, old_ci);470 L->base = L->ci->base;471 L->savedpc = L->ci->savedpc;472 L->allowhook = old_allowhooks;473 restore_stack_limit(L);474 }475 L->errfunc = old_errfunc;476 return status;477 }481 /*482 ** Execute a protected parser.483 */484 struct SParser { /* data to `f_parser' */485 ZIO *z;486 Mbuffer buff; /* buffer to be used by the scanner */487 const char *name;488 };490 static void f_parser (lua_State *L, void *ud) {491 int i;492 Proto *tf;493 Closure *cl;494 struct SParser *p = cast(struct SParser *, ud);495 int c = luaZ_lookahead(p->z);496 luaC_checkGC(L);497 tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,498 &p->buff, p->name);499 cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));500 cl->l.p = tf;501 for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */502 cl->l.upvals[i] = luaF_newupval(L);503 setclvalue(L, L->top, cl);504 incr_top(L);505 }508 int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {509 struct SParser p;510 int status;511 p.z = z; p.name = name;512 luaZ_initbuffer(L, &p.buff);513 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);514 luaZ_freebuffer(L, &p.buff);515 return status;516 }