diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-18 15:18:09 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-01-18 15:18:09 -0200 |
| commit | 334ba8132bd0471ffe2a9964b577d3ae89ec490a (patch) | |
| tree | 3e0dde3bca4f1f51dad42d8c85ad9cb624aab1fa /lfunc.c | |
| parent | ac71a0891d8571816ce32b5c2c1fd97942decf71 (diff) | |
| download | lua-334ba8132bd0471ffe2a9964b577d3ae89ec490a.tar.gz lua-334ba8132bd0471ffe2a9964b577d3ae89ec490a.tar.bz2 lua-334ba8132bd0471ffe2a9964b577d3ae89ec490a.zip | |
cleaner way to remark open upvalues
Diffstat (limited to 'lfunc.c')
| -rw-r--r-- | lfunc.c | 38 |
1 files changed, 31 insertions, 7 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 2.4 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.5 2004/11/24 19:20:21 roberto Exp $ |
| 3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -43,42 +43,66 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) { | |||
| 43 | UpVal *luaF_newupval (lua_State *L) { | 43 | UpVal *luaF_newupval (lua_State *L) { |
| 44 | UpVal *uv = luaM_new(L, UpVal); | 44 | UpVal *uv = luaM_new(L, UpVal); |
| 45 | luaC_link(L, obj2gco(uv), LUA_TUPVAL); | 45 | luaC_link(L, obj2gco(uv), LUA_TUPVAL); |
| 46 | uv->v = &uv->value; | 46 | uv->v = &uv->u.value; |
| 47 | setnilvalue(uv->v); | 47 | setnilvalue(uv->v); |
| 48 | return uv; | 48 | return uv; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | UpVal *luaF_findupval (lua_State *L, StkId level) { | 52 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
| 53 | global_State *g = G(L); | ||
| 53 | GCObject **pp = &L->openupval; | 54 | GCObject **pp = &L->openupval; |
| 54 | UpVal *p; | 55 | UpVal *p; |
| 55 | UpVal *uv; | 56 | UpVal *uv; |
| 56 | while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { | 57 | while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { |
| 58 | lua_assert(p->v != &p->u.value); | ||
| 57 | if (p->v == level) return p; | 59 | if (p->v == level) return p; |
| 58 | pp = &p->next; | 60 | pp = &p->next; |
| 59 | } | 61 | } |
| 60 | uv = luaM_new(L, UpVal); /* not found: create a new one */ | 62 | uv = luaM_new(L, UpVal); /* not found: create a new one */ |
| 61 | uv->tt = LUA_TUPVAL; | 63 | uv->tt = LUA_TUPVAL; |
| 62 | uv->marked = luaC_white(G(L)); | 64 | uv->marked = luaC_white(g); |
| 63 | uv->v = level; /* current value lives in the stack */ | 65 | uv->v = level; /* current value lives in the stack */ |
| 64 | uv->next = *pp; /* chain it in the proper position */ | 66 | uv->next = *pp; /* chain it in the proper position */ |
| 65 | *pp = obj2gco(uv); | 67 | *pp = obj2gco(uv); |
| 68 | lua_assert(g->uvhead.u.l.next->u.l.prev == &g->uvhead && | ||
| 69 | g->uvhead.u.l.prev->u.l.next == &g->uvhead); | ||
| 70 | uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ | ||
| 71 | uv->u.l.next = g->uvhead.u.l.next; | ||
| 72 | uv->u.l.next->u.l.prev = uv; | ||
| 73 | g->uvhead.u.l.next = uv; | ||
| 74 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | ||
| 66 | return uv; | 75 | return uv; |
| 67 | } | 76 | } |
| 68 | 77 | ||
| 69 | 78 | ||
| 79 | static void unlinkupval (UpVal *uv) { | ||
| 80 | lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | ||
| 81 | uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ | ||
| 82 | uv->u.l.prev->u.l.next = uv->u.l.next; | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | void luaF_freeupval (lua_State *L, UpVal *uv) { | ||
| 87 | if (uv->v != &uv->u.value) /* is it open? */ | ||
| 88 | unlinkupval(uv); /* remove from open list */ | ||
| 89 | luaM_free(L, uv); /* free upvalue */ | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 70 | void luaF_close (lua_State *L, StkId level) { | 93 | void luaF_close (lua_State *L, StkId level) { |
| 71 | UpVal *uv; | 94 | UpVal *uv; |
| 72 | global_State *g = G(L); | 95 | global_State *g = G(L); |
| 73 | while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { | 96 | while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { |
| 74 | GCObject *o = obj2gco(uv); | 97 | GCObject *o = obj2gco(uv); |
| 75 | lua_assert(!isblack(o)); | 98 | lua_assert(!isblack(o) && uv->v != &uv->u.value); |
| 76 | L->openupval = uv->next; /* remove from `open' list */ | 99 | L->openupval = uv->next; /* remove from `open' list */ |
| 77 | if (isdead(g, o)) | 100 | if (isdead(g, o)) |
| 78 | luaM_free(L, uv); /* free upvalue */ | 101 | luaF_freeupval(L, uv); /* free upvalue */ |
| 79 | else { | 102 | else { |
| 80 | setobj(L, &uv->value, uv->v); | 103 | unlinkupval(uv); |
| 81 | uv->v = &uv->value; /* now current value lives here */ | 104 | setobj(L, &uv->u.value, uv->v); |
| 105 | uv->v = &uv->u.value; /* now current value lives here */ | ||
| 82 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ | 106 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ |
| 83 | } | 107 | } |
| 84 | } | 108 | } |
