diff options
-rw-r--r-- | ldo.c | 26 | ||||
-rw-r--r-- | lgc.c | 70 | ||||
-rw-r--r-- | lgc.h | 9 | ||||
-rw-r--r-- | lstate.c | 5 |
4 files changed, 63 insertions, 47 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.61 2009/04/17 22:00:01 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.62 2009/04/26 21:55:35 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 | */ |
@@ -131,9 +131,12 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
131 | 131 | ||
132 | void luaD_reallocstack (lua_State *L, int newsize) { | 132 | void luaD_reallocstack (lua_State *L, int newsize) { |
133 | TValue *oldstack = L->stack; | 133 | TValue *oldstack = L->stack; |
134 | int lim = L->stacksize; | ||
134 | int realsize = newsize + 1 + EXTRA_STACK; | 135 | int realsize = newsize + 1 + EXTRA_STACK; |
135 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); | 136 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); |
136 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); | 137 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); |
138 | for (; lim < realsize; lim++) | ||
139 | setnilvalue(L->stack + lim); /* erase new segment */ | ||
137 | L->stacksize = realsize; | 140 | L->stacksize = realsize; |
138 | L->stack_last = L->stack+newsize; | 141 | L->stack_last = L->stack+newsize; |
139 | correctstack(L, oldstack); | 142 | correctstack(L, oldstack); |
@@ -182,14 +185,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | |||
182 | int i; | 185 | int i; |
183 | int nfixargs = p->numparams; | 186 | int nfixargs = p->numparams; |
184 | StkId base, fixed; | 187 | StkId base, fixed; |
185 | for (; actual < nfixargs; ++actual) | 188 | lua_assert(actual >= nfixargs); |
186 | setnilvalue(L->top++); | ||
187 | /* move fixed parameters to final position */ | 189 | /* move fixed parameters to final position */ |
188 | fixed = L->top - actual; /* first fixed argument */ | 190 | fixed = L->top - actual; /* first fixed argument */ |
189 | base = L->top; /* final position of first argument */ | 191 | base = L->top; /* final position of first argument */ |
190 | for (i=0; i<nfixargs; i++) { | 192 | for (i=0; i<nfixargs; i++) { |
191 | setobjs2s(L, L->top++, fixed+i); | 193 | setobjs2s(L, L->top++, fixed + i); |
192 | setnilvalue(fixed+i); | 194 | setnilvalue(fixed + i); |
193 | } | 195 | } |
194 | return base; | 196 | return base; |
195 | } | 197 | } |
@@ -227,17 +229,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
227 | L->ci->nresults = nresults; | 229 | L->ci->nresults = nresults; |
228 | if (!cl->isC) { /* Lua function? prepare its call */ | 230 | if (!cl->isC) { /* Lua function? prepare its call */ |
229 | CallInfo *ci; | 231 | CallInfo *ci; |
230 | StkId st, base; | 232 | int nparams, nargs; |
233 | StkId base; | ||
231 | Proto *p = cl->p; | 234 | Proto *p = cl->p; |
232 | luaD_checkstack(L, p->maxstacksize); | 235 | luaD_checkstack(L, p->maxstacksize); |
233 | func = restorestack(L, funcr); | 236 | func = restorestack(L, funcr); |
237 | nargs = cast_int(L->top - func) - 1; /* number of real arguments */ | ||
238 | nparams = p->numparams; /* number of expected parameters */ | ||
239 | for (; nargs < nparams; nargs++) | ||
240 | setnilvalue(L->top++); /* complete missing arguments */ | ||
234 | if (!p->is_vararg) /* no varargs? */ | 241 | if (!p->is_vararg) /* no varargs? */ |
235 | base = func + 1; | 242 | base = func + 1; |
236 | else { /* vararg function */ | 243 | else /* vararg function */ |
237 | int nargs = cast_int(L->top - func) - 1; | ||
238 | base = adjust_varargs(L, p, nargs); | 244 | base = adjust_varargs(L, p, nargs); |
239 | func = restorestack(L, funcr); /* previous call may change the stack */ | ||
240 | } | ||
241 | ci = next_ci(L); /* now 'enter' new function */ | 245 | ci = next_ci(L); /* now 'enter' new function */ |
242 | ci->func = func; | 246 | ci->func = func; |
243 | L->base = ci->base = base; | 247 | L->base = ci->base = base; |
@@ -246,8 +250,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
246 | ci->u.l.savedpc = p->code; /* starting point */ | 250 | ci->u.l.savedpc = p->code; /* starting point */ |
247 | ci->u.l.tailcalls = 0; | 251 | ci->u.l.tailcalls = 0; |
248 | ci->callstatus = CIST_LUA; | 252 | ci->callstatus = CIST_LUA; |
249 | for (st = L->top; st < ci->top; st++) | ||
250 | setnilvalue(st); | ||
251 | L->top = ci->top; | 253 | L->top = ci->top; |
252 | if (L->hookmask & LUA_MASKCALL) { | 254 | if (L->hookmask & LUA_MASKCALL) { |
253 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 255 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.49 2009/03/10 17:14:37 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.50 2009/04/17 14:28:06 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -379,34 +379,17 @@ static void traverseclosure (global_State *g, Closure *cl) { | |||
379 | } | 379 | } |
380 | 380 | ||
381 | 381 | ||
382 | static void checkstacksize (lua_State *L, StkId max) { | ||
383 | /* should not change the stack during an emergency gc cycle */ | ||
384 | if (G(L)->gckind == KGC_EMERGENCY) | ||
385 | return; /* do not touch the stack */ | ||
386 | else { | ||
387 | int s_used = cast_int(max - L->stack) + 1; /* part of stack in use */ | ||
388 | if (2*s_used < (L->stacksize - EXTRA_STACK)) | ||
389 | luaD_reallocstack(L, 2*s_used); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | |||
394 | static void traversestack (global_State *g, lua_State *L) { | 382 | static void traversestack (global_State *g, lua_State *L) { |
395 | StkId o, lim; | 383 | StkId o; |
396 | CallInfo *ci; | ||
397 | if (L->stack == NULL) | 384 | if (L->stack == NULL) |
398 | return; /* stack not completely built yet */ | 385 | return; /* stack not completely built yet */ |
399 | markvalue(g, gt(L)); | 386 | markvalue(g, gt(L)); /* mark global table */ |
400 | lim = L->top; | ||
401 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||
402 | lua_assert(ci->top <= L->stack_last); | ||
403 | if (lim < ci->top) lim = ci->top; | ||
404 | } | ||
405 | for (o = L->stack; o < L->top; o++) | 387 | for (o = L->stack; o < L->top; o++) |
406 | markvalue(g, o); | 388 | markvalue(g, o); |
407 | for (; o <= lim; o++) | 389 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
408 | setnilvalue(o); | 390 | for (; o <= L->stack_last; o++) /* clear not-marked stack slice */ |
409 | checkstacksize(L, lim); | 391 | setnilvalue(o); |
392 | } | ||
410 | } | 393 | } |
411 | 394 | ||
412 | 395 | ||
@@ -542,7 +525,35 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
542 | } | 525 | } |
543 | 526 | ||
544 | 527 | ||
528 | static int stackinuse (lua_State *L) { | ||
529 | CallInfo *ci; | ||
530 | StkId lim = L->top; | ||
531 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||
532 | lua_assert(ci->top <= L->stack_last); | ||
533 | if (lim < ci->top) lim = ci->top; | ||
534 | } | ||
535 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | ||
536 | } | ||
537 | |||
538 | |||
545 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) | 539 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) |
540 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); | ||
541 | |||
542 | |||
543 | static void sweepthread (lua_State *L, lua_State *L1, int alive) { | ||
544 | if (L1->stack == NULL) return; /* stack not completely built yet */ | ||
545 | sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ | ||
546 | if (L1->nci < LUAI_MAXCALLS) /* not handling stack overflow? */ | ||
547 | luaE_freeCI(L1); /* free extra CallInfo slots */ | ||
548 | /* should not change the stack during an emergency gc cycle */ | ||
549 | if (alive && G(L)->gckind != KGC_EMERGENCY) { | ||
550 | int goodsize = 5 * stackinuse(L1) / 4 + LUA_MINSTACK; | ||
551 | if ((L1->stacksize - EXTRA_STACK) > goodsize) | ||
552 | luaD_reallocstack(L1, goodsize); | ||
553 | else | ||
554 | condhardstacktests(luaD_reallocstack(L, L1->stacksize - EXTRA_STACK - 1)); | ||
555 | } | ||
556 | } | ||
546 | 557 | ||
547 | 558 | ||
548 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 559 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
@@ -550,12 +561,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
550 | global_State *g = G(L); | 561 | global_State *g = G(L); |
551 | int deadmask = otherwhite(g); | 562 | int deadmask = otherwhite(g); |
552 | while ((curr = *p) != NULL && count-- > 0) { | 563 | while ((curr = *p) != NULL && count-- > 0) { |
553 | if (ttisthread(gch(curr))) { | 564 | int alive = (gch(curr)->marked ^ WHITEBITS) & deadmask; |
554 | lua_State *L1 = gco2th(curr); | 565 | if (ttisthread(gch(curr))) |
555 | sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ | 566 | sweepthread(L, gco2th(curr), alive); |
556 | luaE_freeCI(L1); /* free extra CallInfo slots */ | 567 | if (alive) { |
557 | } | ||
558 | if ((gch(curr)->marked ^ WHITEBITS) & deadmask) { /* not dead? */ | ||
559 | lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); | 568 | lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); |
560 | makewhite(g, curr); /* make it white (for next cycle) */ | 569 | makewhite(g, curr); /* make it white (for next cycle) */ |
561 | p = &gch(curr)->next; | 570 | p = &gch(curr)->next; |
@@ -704,6 +713,7 @@ static void atomic (lua_State *L) { | |||
704 | global_State *g = G(L); | 713 | global_State *g = G(L); |
705 | size_t udsize; /* total size of userdata to be finalized */ | 714 | size_t udsize; /* total size of userdata to be finalized */ |
706 | /* remark occasional upvalues of (maybe) dead threads */ | 715 | /* remark occasional upvalues of (maybe) dead threads */ |
716 | g->gcstate = GCSatomic; | ||
707 | remarkupvals(g); | 717 | remarkupvals(g); |
708 | /* traverse objects cautch by write barrier and by 'remarkupvals' */ | 718 | /* traverse objects cautch by write barrier and by 'remarkupvals' */ |
709 | propagateall(g); | 719 | propagateall(g); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.18 2008/02/19 18:55:09 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.19 2008/06/26 19:42:45 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,9 +16,10 @@ | |||
16 | */ | 16 | */ |
17 | #define GCSpause 0 | 17 | #define GCSpause 0 |
18 | #define GCSpropagate 1 | 18 | #define GCSpropagate 1 |
19 | #define GCSsweepstring 2 | 19 | #define GCSatomic 2 |
20 | #define GCSsweep 3 | 20 | #define GCSsweepstring 3 |
21 | #define GCSfinalize 4 | 21 | #define GCSsweep 4 |
22 | #define GCSfinalize 5 | ||
22 | 23 | ||
23 | 24 | ||
24 | #define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | 25 | #define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.52 2009/04/17 14:40:13 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.53 2009/04/17 22:00:01 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -75,9 +75,12 @@ void luaE_freeCI (lua_State *L) { | |||
75 | 75 | ||
76 | 76 | ||
77 | static void stack_init (lua_State *L1, lua_State *L) { | 77 | static void stack_init (lua_State *L1, lua_State *L) { |
78 | int i; | ||
78 | /* initialize stack array */ | 79 | /* initialize stack array */ |
79 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); | 80 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); |
80 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; | 81 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; |
82 | for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) | ||
83 | setnilvalue(L1->stack + i); /* erase new stack */ | ||
81 | L1->top = L1->stack; | 84 | L1->top = L1->stack; |
82 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; | 85 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; |
83 | /* initialize first ci */ | 86 | /* initialize first ci */ |