]>
git.saurik.com Git - redis.git/blob - deps/lua/src/ldo.c
2 ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
3 ** Stack and Call structure of Lua
4 ** See Copyright Notice in lua.h
37 ** {======================================================
38 ** Error-recovery functions
39 ** =======================================================
43 /* chain list of long jump buffers */
45 struct lua_longjmp
*previous
;
47 volatile int status
; /* error code */
51 void luaD_seterrorobj (lua_State
*L
, int errcode
, StkId oldtop
) {
54 setsvalue2s(L
, oldtop
, luaS_newliteral(L
, MEMERRMSG
));
58 setsvalue2s(L
, oldtop
, luaS_newliteral(L
, "error in error handling"));
63 setobjs2s(L
, oldtop
, L
->top
- 1); /* error message on current top */
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
);
81 static void resetstack (lua_State
*L
, int status
) {
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
;
88 restore_stack_limit(L
);
94 void luaD_throw (lua_State
*L
, int errcode
) {
96 L
->errorJmp
->status
= errcode
;
97 LUAI_THROW(L
, L
->errorJmp
);
100 L
->status
= cast_byte(errcode
);
102 resetstack(L
, errcode
);
111 int luaD_rawrunprotected (lua_State
*L
, Pfunc f
, void *ud
) {
112 struct lua_longjmp lj
;
114 lj
.previous
= L
->errorJmp
; /* chain new error handler */
119 L
->errorJmp
= lj
.previous
; /* restore old error handler */
123 /* }====================================================== */
126 static void correctstack (lua_State
*L
, TValue
*oldstack
) {
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
;
137 L
->base
= (L
->base
- oldstack
) + L
->stack
;
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
);
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;
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
);
165 luaD_reallocstack(L
, L
->stacksize
+ n
);
169 static CallInfo
*growCI (lua_State
*L
) {
170 if (L
->size_ci
> LUAI_MAXCALLS
) /* overflow while handling overflow? */
171 luaD_throw(L
, LUA_ERRERR
);
173 luaD_reallocCI(L
, 2*L
->size_ci
);
174 if (L
->size_ci
> LUAI_MAXCALLS
)
175 luaG_runerror(L
, "stack overflow");
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
);
188 ar
.currentline
= line
;
189 if (event
== LUA_HOOKTAILRET
)
190 ar
.i_ci
= 0; /* tail call; no debug information about it */
192 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 */
200 lua_assert(!L
->allowhook
);
202 L
->ci
->top
= restorestack(L
, ci_top
);
203 L
->top
= restorestack(L
, top
);
208 static StkId
adjust_varargs (lua_State
*L
, Proto
*p
, int actual
) {
210 int nfixargs
= p
->numparams
;
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
);
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
));
227 /* 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
);
234 /* add `arg' parameter */
236 sethvalue(L
, L
->top
++, htab
);
237 lua_assert(iswhite(obj2gco(htab
)));
243 static StkId
tryfuncTM (lua_State
*L
, StkId func
) {
244 const TValue
*tm
= luaT_gettmbyobj(L
, func
, TM_CALL
);
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);
252 func
= restorestack(L
, funcr
); /* previous call may change stack */
253 setobj2s(L
, func
, tm
); /* tag method is the new function to be called */
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
) {
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 */
276 luaD_checkstack(L
, p
->maxstacksize
);
277 func
= restorestack(L
, funcr
);
278 if (!p
->is_vararg
) { /* no varargs? */
280 if (L
->top
> base
+ p
->numparams
)
281 L
->top
= base
+ p
->numparams
;
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 */
288 ci
= inc_ci(L
); /* now `enter' new function */
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 */
295 ci
->nresults
= nresults
;
296 for (st
= L
->top
; st
< ci
->top
; st
++)
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' */
306 else { /* if is a C function, call it */
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);
319 n
= (*curr_func(L
)->c
.f
)(L
); /* do the actual call */
321 if (n
< 0) /* yielding? */
324 luaD_poscall(L
, L
->top
- n
);
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);
338 return restorestack(L
, fr
);
342 int luaD_poscall (lua_State
*L
, StkId firstResult
) {
346 if (L
->hookmask
& LUA_MASKRET
)
347 firstResult
= callrethooks(L
, firstResult
);
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
++);
359 return (wanted
- LUA_MULTRET
); /* 0 iff wanted == LUA_MULTRET */
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 original
367 ** function position.
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 */
376 if (luaD_precall(L
, func
, nResults
) == PCRLUA
) /* is a Lua function? */
377 luaV_execute(L
, 1); /* call it */
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
)
391 else { /* resuming from previous yield */
392 lua_assert(L
->status
== LUA_YIELD
);
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 */
401 else /* yielded inside a hook: just continue its execution */
402 L
->base
= L
->ci
->base
;
404 luaV_execute(L
, cast_int(L
->ci
- L
->base_ci
));
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
));
417 LUA_API
int lua_resume (lua_State
*L
, int nargs
) {
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
);
434 lua_assert(L
->nCcalls
== L
->baseCcalls
);
443 LUA_API
int lua_yield (lua_State
*L
, int nresults
) {
444 luai_userstateyield(L
, nresults
);
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
;
455 int luaD_pcall (lua_State
*L
, Pfunc func
, void *u
,
456 ptrdiff_t old_top
, ptrdiff_t ef
) {
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
;
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
);
475 L
->errfunc
= old_errfunc
;
482 ** Execute a protected parser.
484 struct SParser
{ /* data to `f_parser' */
486 Mbuffer buff
; /* buffer to be used by the scanner */
490 static void f_parser (lua_State
*L
, void *ud
) {
494 struct SParser
*p
= cast(struct SParser
*, ud
);
495 int c
= luaZ_lookahead(p
->z
);
497 tf
= ((c
== LUA_SIGNATURE
[0]) ? luaU_undump
: luaY_parser
)(L
, p
->z
,
499 cl
= luaF_newLclosure(L
, tf
->nups
, hvalue(gt(L
)));
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
);
508 int luaD_protectedparser (lua_State
*L
, ZIO
*z
, const char *name
) {
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
);