diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-04-28 16:04:36 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-04-28 16:04:36 -0300 |
commit | e091a254dfe4521d837469d3ae7cc329e2df3376 (patch) | |
tree | 7ee2f1c83a9a07500b6826bb55f0f1e977785d02 /lgc.c | |
parent | 58c3aa8b5f51194980a9abf463a2648bb1413925 (diff) | |
download | lua-e091a254dfe4521d837469d3ae7cc329e2df3376.tar.gz lua-e091a254dfe4521d837469d3ae7cc329e2df3376.tar.bz2 lua-e091a254dfe4521d837469d3ae7cc329e2df3376.zip |
new way to GC stacks: the entire stack must be correct all the times;
the 'dead' part of a stack (after the top) must have only nil's, so
that 'top' may go up without cleaning the stack.
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 70 |
1 files changed, 40 insertions, 30 deletions
@@ -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); |