aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c275
1 files changed, 135 insertions, 140 deletions
diff --git a/ldo.c b/ldo.c
index 55f7958f..e6307b0c 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.187 2002/07/09 18:19:19 roberto Exp roberto $ 2** $Id: ldo.c,v 1.188 2002/07/16 14:26:56 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*/
@@ -29,40 +29,113 @@
29 29
30 30
31 31
32/*
33** {======================================================
34** Error-recovery functions (based on long jumps)
35** =======================================================
36*/
37
38
32/* chain list of long jump buffers */ 39/* chain list of long jump buffers */
33struct lua_longjmp { 40struct lua_longjmp {
34 struct lua_longjmp *previous; 41 struct lua_longjmp *previous;
35 CallInfo *ci; /* index of call info of active function that set protection */
36 StkId top; /* top stack when protection was set */
37 jmp_buf b; 42 jmp_buf b;
38 int allowhooks; /* `allowhook' state when protection was set */
39 volatile int status; /* error code */ 43 volatile int status; /* error code */
40 TObject *err; /* error messages (start of `ud') */
41}; 44};
42 45
43 46
44static void pusherrormsg (lua_State *L, int status, TObject *err) { 47static void seterrorobj (lua_State *L, int errcode) {
45 setobj(L->top++, &err[0]); 48 switch (errcode) {
46 if (status == LUA_ERRRUN) 49 case LUA_ERRMEM: {
47 setobj(L->top++, &err[1]); 50 setsvalue(L->top, luaS_new(L, MEMERRMSG));
51 break;
52 }
53 case LUA_ERRERR: {
54 setsvalue(L->top, luaS_new(L, "error in error handling"));
55 break;
56 }
57 case LUA_ERRSYNTAX:
58 case LUA_ERRRUN: {
59 return; /* error message already on top */
60 }
61 }
62 L->top++;
63}
64
65
66void luaD_throw (lua_State *L, int errcode) {
67 if (errcode == LUA_ERRRUN)
68 luaD_checkstack(L, LUA_MINSTACK); /* ensure stack space to handle error */
69 luaG_saveallpcs(L); /* C stack will disapear */
70 if (L->errorJmp) {
71 L->errorJmp->status = errcode;
72 longjmp(L->errorJmp->b, 1);
73 }
74 else {
75 G(L)->panic(L);
76 exit(EXIT_FAILURE);
77 }
78}
79
80
81int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
82 struct lua_longjmp lj;
83 lj.status = 0;
84 lj.previous = L->errorJmp; /* chain new error handler */
85 L->errorJmp = &lj;
86 if (setjmp(lj.b) == 0)
87 (*f)(L, ud);
88 L->errorJmp = lj.previous; /* restore old error handler */
89 return lj.status;
90}
91
92
93static void restore_stack_limit (lua_State *L) {
94 L->stack_last = L->stack+L->stacksize-1;
95 if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
96 int inuse = (L->ci - L->base_ci);
97 if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
98 luaD_reallocCI(L, LUA_MAXCALLS);
99 }
48} 100}
49 101
50 102
103void luaD_resetprotection (lua_State *L) {
104 Protection *p;
105 StkId err = L->top - 1; /* error msg. position (if there is one) */
106 lua_assert(L->number_toreset > 0);
107 p = &L->toreset[--L->number_toreset];
108 L->ci = restoreci(L, p->ci);
109 L->top = restorestack(L, p->top);
110 L->ci->top = L->top + LUA_MINSTACK;
111 setallowhook(L, p->allowhooks);
112 restore_stack_limit(L);
113 setobj(L->top++, err); /* copy error message to corrected top */
114}
115
116
117/*
118** invalidate all pc pointers from stack part that becomes inactive
119*/
120static void deactivateinfo (lua_State *L, CallInfo *p_ci) {
121 CallInfo *ci;
122 for (ci = L->ci; ci > p_ci; ci--)
123 ci->pc = NULL;
124}
125
126/* }====================================================== */
127
128
51static void correctstack (lua_State *L, TObject *oldstack) { 129static void correctstack (lua_State *L, TObject *oldstack) {
52 struct lua_longjmp *lj;
53 CallInfo *ci; 130 CallInfo *ci;
54 UpVal *up; 131 UpVal *up;
55 L->top = (L->top - oldstack) + L->stack; 132 L->top = (L->top - oldstack) + L->stack;
56 for (lj = L->errorJmp; lj != NULL; lj = lj->previous)
57 lj->top = (lj->top - oldstack) + L->stack;
58 for (up = L->openupval; up != NULL; up = up->next) 133 for (up = L->openupval; up != NULL; up = up->next)
59 up->v = (up->v - oldstack) + L->stack; 134 up->v = (up->v - oldstack) + L->stack;
60 for (ci = L->base_ci; ci <= L->ci; ci++) { 135 for (ci = L->base_ci; ci <= L->ci; ci++) {
61 ci->base = (ci->base - oldstack) + L->stack; 136 ci->base = (ci->base - oldstack) + L->stack;
62 ci->top = (ci->top - oldstack) + L->stack; 137 ci->top = (ci->top - oldstack) + L->stack;
63 if (isLua(ci) && /* is a Lua function... */ 138 if (ci->pc && ci->pc != &luaV_callingmark) /* function has a frame? */
64 !(isLua(ci-1) && /* and next is not a Lua function... */
65 ci->u.l.pc == (ci-1)->u.l.pc)) /* sharing the same C frame? */
66 *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ 139 *ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
67 } 140 }
68} 141}
@@ -72,35 +145,17 @@ void luaD_reallocstack (lua_State *L, int newsize) {
72 TObject *oldstack = L->stack; 145 TObject *oldstack = L->stack;
73 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject); 146 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
74 L->stacksize = newsize; 147 L->stacksize = newsize;
75 L->stack_last = L->stack+(newsize-EXTRA_STACK)-1; 148 L->stack_last = L->stack+newsize-1-EXTRA_STACK;
76 correctstack(L, oldstack); 149 correctstack(L, oldstack);
77} 150}
78 151
79 152
80static void correctCI (lua_State *L, CallInfo *oldci) {
81 struct lua_longjmp *lj;
82 for (lj = L->errorJmp; lj != NULL; lj = lj->previous) {
83 lj->ci = (lj->ci - oldci) + L->base_ci;
84 }
85}
86
87
88void luaD_reallocCI (lua_State *L, int newsize) { 153void luaD_reallocCI (lua_State *L, int newsize) {
89 CallInfo *oldci = L->base_ci; 154 CallInfo *oldci = L->base_ci;
90 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); 155 luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
91 L->size_ci = newsize; 156 L->size_ci = newsize;
92 L->ci = (L->ci - oldci) + L->base_ci; 157 L->ci = (L->ci - oldci) + L->base_ci;
93 L->end_ci = L->base_ci + L->size_ci; 158 L->end_ci = L->base_ci + L->size_ci;
94 correctCI(L, oldci);
95}
96
97
98static void restore_stack_limit (lua_State *L) {
99 if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
100 int inuse = (L->ci - L->base_ci);
101 if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
102 luaD_reallocCI(L, LUA_MAXCALLS);
103 }
104} 159}
105 160
106 161
@@ -175,7 +230,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
175 const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); 230 const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
176 StkId p; 231 StkId p;
177 ptrdiff_t funcr = savestack(L, func); 232 ptrdiff_t funcr = savestack(L, func);
178 if (ttype(tm) != LUA_TFUNCTION) 233 if (!ttisfunction(tm))
179 luaG_typeerror(L, func, "call"); 234 luaG_typeerror(L, func, "call");
180 /* Open a hole inside the stack at `func' */ 235 /* Open a hole inside the stack at `func' */
181 for (p = L->top; p > func; p--) setobj(p, p-1); 236 for (p = L->top; p > func; p--) setobj(p, p-1);
@@ -189,7 +244,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
189StkId luaD_precall (lua_State *L, StkId func) { 244StkId luaD_precall (lua_State *L, StkId func) {
190 LClosure *cl; 245 LClosure *cl;
191 ptrdiff_t funcr = savestack(L, func); 246 ptrdiff_t funcr = savestack(L, func);
192 if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */ 247 if (!ttisfunction(func)) /* `func' is not a function? */
193 func = tryfuncTM(L, func); /* check the `function' tag method */ 248 func = tryfuncTM(L, func); /* check the `function' tag method */
194 if (L->ci + 1 == L->end_ci) luaD_growCI(L); 249 if (L->ci + 1 == L->end_ci) luaD_growCI(L);
195 cl = &clvalue(func)->l; 250 cl = &clvalue(func)->l;
@@ -202,7 +257,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
202 ci = ++L->ci; /* now `enter' new function */ 257 ci = ++L->ci; /* now `enter' new function */
203 ci->base = restorestack(L, funcr) + 1; 258 ci->base = restorestack(L, funcr) + 1;
204 ci->top = ci->base + p->maxstacksize; 259 ci->top = ci->base + p->maxstacksize;
205 ci->savedpc = p->code; /* starting point */ 260 ci->u.l.savedpc = p->code; /* starting point */
206 while (L->top < ci->top) 261 while (L->top < ci->top)
207 setnilvalue(L->top++); 262 setnilvalue(L->top++);
208 L->top = ci->top; 263 L->top = ci->top;
@@ -215,7 +270,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
215 ci = ++L->ci; /* now `enter' new function */ 270 ci = ++L->ci; /* now `enter' new function */
216 ci->base = restorestack(L, funcr) + 1; 271 ci->base = restorestack(L, funcr) + 1;
217 ci->top = L->top + LUA_MINSTACK; 272 ci->top = L->top + LUA_MINSTACK;
218 ci->savedpc = NULL; /* not a Lua function */ 273 ci->pc = NULL; /* not a Lua function */
219 if (L->hookmask & LUA_MASKCALL) { 274 if (L->hookmask & LUA_MASKCALL) {
220 luaD_callhook(L, LUA_HOOKCALL, -1); 275 luaD_callhook(L, LUA_HOOKCALL, -1);
221 ci = L->ci; /* previous call may realocate `ci' */ 276 ci = L->ci; /* previous call may realocate `ci' */
@@ -274,6 +329,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
274LUA_API void lua_cobegin (lua_State *L, int nargs) { 329LUA_API void lua_cobegin (lua_State *L, int nargs) {
275 lua_lock(L); 330 lua_lock(L);
276 luaD_precall(L, L->top - (nargs+1)); 331 luaD_precall(L, L->top - (nargs+1));
332 L->ci->pc = &luaV_callingmark; /* function is not active (yet) */
277 lua_unlock(L); 333 lua_unlock(L);
278} 334}
279 335
@@ -287,28 +343,24 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
287} 343}
288 344
289 345
290struct ResS {
291 TObject err[2];
292 int numres;
293};
294
295static void resume (lua_State *L, void *ud) { 346static void resume (lua_State *L, void *ud) {
296 StkId firstResult; 347 StkId firstResult;
297 CallInfo *ci = L->ci; 348 CallInfo *ci = L->ci;
298 if (!isLua(ci)) { /* not first time? */ 349 if (ci->pc == NULL) { /* not first time? */
299 /* finish interrupted execution of `OP_CALL' */ 350 /* finish interrupted execution of `OP_CALL' */
300 int nresults; 351 int nresults;
301 lua_assert(isLua(ci - 1)); 352 lua_assert((ci - 1)->pc == &luaV_callingmark);
302 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL); 353 lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
303 nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1; 354 GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
355 nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
304 luaD_poscall(L, nresults, L->top); /* complete it */ 356 luaD_poscall(L, nresults, L->top); /* complete it */
305 if (nresults >= 0) L->top = L->ci->top; 357 if (nresults >= 0) L->top = L->ci->top;
306 } 358 }
307 firstResult = luaV_execute(L); 359 firstResult = luaV_execute(L);
308 if (firstResult == NULL) /* yield? */ 360 if (firstResult == NULL) /* yield? */
309 cast(struct ResS *, ud)->numres = L->ci->u.c.yield_results; 361 *cast(int *, ud) = L->ci->u.c.yield_results;
310 else { /* return */ 362 else { /* return */
311 cast(struct ResS *, ud)->numres = L->top - firstResult; 363 *cast(int *, ud) = L->top - firstResult;
312 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ 364 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
313 } 365 }
314} 366}
@@ -316,7 +368,7 @@ static void resume (lua_State *L, void *ud) {
316 368
317LUA_API int lua_resume (lua_State *L, lua_State *co) { 369LUA_API int lua_resume (lua_State *L, lua_State *co) {
318 CallInfo *ci; 370 CallInfo *ci;
319 struct ResS ud; 371 int numres;
320 int status; 372 int status;
321 lua_lock(L); 373 lua_lock(L);
322 ci = co->ci; 374 ci = co->ci;
@@ -324,11 +376,13 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
324 luaG_runerror(L, "cannot resume dead thread"); 376 luaG_runerror(L, "cannot resume dead thread");
325 if (co->errorJmp != NULL) /* ?? */ 377 if (co->errorJmp != NULL) /* ?? */
326 luaG_runerror(L, "cannot resume active thread"); 378 luaG_runerror(L, "cannot resume active thread");
327 status = luaD_runprotected(co, resume, ud.err); 379 status = luaD_rawrunprotected(co, resume, &numres);
328 if (status == 0) 380 if (status == 0)
329 move_results(L, co->top - ud.numres, co->top); 381 move_results(L, co->top - numres, co->top);
330 else 382 else {
331 pusherrormsg(L, status, ud.err); 383 setobj(L->top++, co->top - 1); /* move error message to other stack */
384 co->ci = co->base_ci; /* `kill' thread */
385 }
332 lua_unlock(L); 386 lua_unlock(L);
333 return status; 387 return status;
334} 388}
@@ -338,9 +392,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
338 CallInfo *ci; 392 CallInfo *ci;
339 lua_lock(L); 393 lua_lock(L);
340 ci = L->ci; 394 ci = L->ci;
341 if (!isLua(ci-1)) 395 if ((ci-1)->pc == NULL)
342 luaG_runerror(L, "cannot yield a C function"); 396 luaG_runerror(L, "cannot yield a C function");
343 lua_assert(!isLua(ci)); 397 lua_assert(ci->pc == NULL); /* current function is not Lua */
344 ci->u.c.yield_results = nresults; 398 ci->u.c.yield_results = nresults;
345 lua_unlock(L); 399 lua_unlock(L);
346 return -1; 400 return -1;
@@ -351,7 +405,6 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
351** Execute a protected call. 405** Execute a protected call.
352*/ 406*/
353struct CallS { /* data to `f_call' */ 407struct CallS { /* data to `f_call' */
354 TObject err[2];
355 StkId func; 408 StkId func;
356 int nresults; 409 int nresults;
357}; 410};
@@ -359,6 +412,8 @@ struct CallS { /* data to `f_call' */
359 412
360static void f_call (lua_State *L, void *ud) { 413static void f_call (lua_State *L, void *ud) {
361 struct CallS *c = cast(struct CallS *, ud); 414 struct CallS *c = cast(struct CallS *, ud);
415 luaM_growvector(L, L->toreset, L->number_toreset, L->size_toreset,
416 Protection, MAX_INT, "");
362 luaD_call(L, c->func, c->nresults); 417 luaD_call(L, c->func, c->nresults);
363} 418}
364 419
@@ -366,13 +421,24 @@ static void f_call (lua_State *L, void *ud) {
366int luaD_pcall (lua_State *L, int nargs, int nresults) { 421int luaD_pcall (lua_State *L, int nargs, int nresults) {
367 struct CallS c; 422 struct CallS c;
368 int status; 423 int status;
424 int protectionlevel = L->number_toreset;
425 Protection protection;
426 protection.top = savestack(L, L->top);
427 protection.ci = saveci(L, L->ci);
428 protection.allowhooks = allowhook(L);
369 c.func = L->top - (nargs+1); /* function to be called */ 429 c.func = L->top - (nargs+1); /* function to be called */
370 c.nresults = nresults; 430 c.nresults = nresults;
371 status = luaD_runprotected(L, &f_call, c.err); 431 status = luaD_rawrunprotected(L, &f_call, &c);
372 if (status != 0) { /* an error occurred? */ 432 if (status != 0) { /* an error occurred? */
373 L->top -= nargs+1; /* remove parameters and func from the stack */ 433 /* remove parameters and func from the stack */
374 luaF_close(L, L->top); /* close eventual pending closures */ 434 protection.top = savestack(L, restorestack(L, protection.top) - (nargs+1));
375 pusherrormsg(L, status, c.err); 435 /* close eventual pending closures */
436 luaF_close(L, restorestack(L, protection.top));
437 L->ci->top = L->top + LUA_MINSTACK; /* extra space to handle error */
438 seterrorobj(L, status);
439 deactivateinfo(L, restoreci(L, protection.ci));
440 L->number_toreset = protectionlevel + 1;
441 L->toreset[L->number_toreset - 1] = protection;
376 } 442 }
377 return status; 443 return status;
378} 444}
@@ -382,7 +448,6 @@ int luaD_pcall (lua_State *L, int nargs, int nresults) {
382** Execute a protected parser. 448** Execute a protected parser.
383*/ 449*/
384struct SParser { /* data to `f_parser' */ 450struct SParser { /* data to `f_parser' */
385 TObject err[2];
386 ZIO *z; 451 ZIO *z;
387 int bin; 452 int bin;
388}; 453};
@@ -401,95 +466,25 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
401 struct SParser p; 466 struct SParser p;
402 lu_mem old_blocks; 467 lu_mem old_blocks;
403 int status; 468 int status;
469 ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
404 p.z = z; p.bin = bin; 470 p.z = z; p.bin = bin;
405 /* before parsing, give a (good) chance to GC */ 471 /* before parsing, give a (good) chance to GC */
406 if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold) 472 if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
407 luaC_collectgarbage(L); 473 luaC_collectgarbage(L);
408 old_blocks = G(L)->nblocks; 474 old_blocks = G(L)->nblocks;
409 status = luaD_runprotected(L, f_parser, p.err); 475 status = luaD_rawrunprotected(L, f_parser, &p);
410 if (status == 0) { 476 if (status == 0) {
411 /* add new memory to threshold (as it probably will stay) */ 477 /* add new memory to threshold (as it probably will stay) */
412 lua_assert(G(L)->nblocks >= old_blocks); 478 lua_assert(G(L)->nblocks >= old_blocks);
413 G(L)->GCthreshold += (G(L)->nblocks - old_blocks); 479 G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
414 } 480 }
415 else 481 else { /* error */
416 pusherrormsg(L, status, p.err); 482 StkId oldtop = restorestack(L, oldtopr);
417 return status; 483 seterrorobj(L, status);
418} 484 setobj(oldtop, L->top - 1); /* copy error message to old top */
419 485 L->top = oldtop+1;
420
421
422/*
423** {======================================================
424** Error-recovery functions (based on long jumps)
425** =======================================================
426*/
427
428static void seterrorobj (lua_State *L, int errcode, TObject *m) {
429 switch (errcode) {
430 case LUA_ERRMEM: {
431 if (G(L) != NULL && G(L)->GCthreshold > 0) /* state is OK? */
432 setsvalue(&m[0], luaS_new(L, MEMERRMSG));
433 break;
434 }
435 case LUA_ERRERR: {
436 setsvalue(&m[0], luaS_new(L, "error in error handling"));
437 break;
438 }
439 case LUA_ERRSYNTAX: { /* message is on stack top */
440 setobj(&m[0], L->top - 1);
441 break;
442 }
443 case LUA_ERRRUN: { /* traceback is on stack top */
444 setobj(&m[0], L->top - 2);
445 setobj(&m[1], L->top - 1);
446 break;
447 }
448 }
449}
450
451
452void luaD_throw (lua_State *L, int errcode) {
453 if (L->errorJmp) {
454 seterrorobj(L, errcode, L->errorJmp->err);
455 L->errorJmp->status = errcode;
456 longjmp(L->errorJmp->b, 1);
457 }
458 else {
459 G(L)->panic(L);
460 exit(EXIT_FAILURE);
461 }
462}
463
464
465int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
466 struct lua_longjmp lj;
467 lj.ci = L->ci;
468 lj.top = L->top;
469 lj.allowhooks = allowhook(L);
470 lj.status = 0;
471 lj.err = ud;
472 lj.previous = L->errorJmp; /* chain new error handler */
473 L->errorJmp = &lj;
474 if (setjmp(lj.b) == 0)
475 (*f)(L, ud);
476 else { /* an error occurred */
477 L->ci = lj.ci; /* restore the state */
478 L->top = lj.top;
479 setallowhook(L, lj.allowhooks);
480 restore_stack_limit(L);
481 } 486 }
482 L->errorJmp = lj.previous; /* restore old error handler */ 487 return status;
483 return lj.status;
484}
485
486
487int luaD_isprotected (lua_State *L, CallInfo *ci) {
488 struct lua_longjmp *l;
489 for (l = L->errorJmp; l; l = l->previous)
490 if (l->ci+1 == ci) return 1;
491 return 0;
492} 488}
493 489
494/* }====================================================== */
495 490