diff options
Diffstat (limited to 'lfunc.c')
| -rw-r--r-- | lfunc.c | 82 |
1 files changed, 23 insertions, 59 deletions
| @@ -22,6 +22,7 @@ | |||
| 22 | cast(int, sizeof(TObject *)*((n)-1))) | 22 | cast(int, sizeof(TObject *)*((n)-1))) |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | |||
| 25 | Closure *luaF_newCclosure (lua_State *L, int nelems) { | 26 | Closure *luaF_newCclosure (lua_State *L, int nelems) { |
| 26 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | 27 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); |
| 27 | c->c.isC = 1; | 28 | c->c.isC = 1; |
| @@ -36,76 +37,39 @@ Closure *luaF_newCclosure (lua_State *L, int nelems) { | |||
| 36 | Closure *luaF_newLclosure (lua_State *L, int nelems) { | 37 | Closure *luaF_newLclosure (lua_State *L, int nelems) { |
| 37 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | 38 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); |
| 38 | c->l.isC = 0; | 39 | c->l.isC = 0; |
| 40 | c->c.next = G(L)->rootcl; | ||
| 41 | G(L)->rootcl = c; | ||
| 39 | c->l.marked = 0; | 42 | c->l.marked = 0; |
| 40 | c->l.nupvalues = nelems; | 43 | c->l.nupvalues = nelems; |
| 41 | return c; | 44 | return c; |
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | 47 | ||
| 45 | /* | 48 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
| 46 | ** returns the open pointer in a closure that points higher into the stack | 49 | UpVal **pp = &L->openupval; |
| 47 | */ | 50 | UpVal *p; |
| 48 | static StkId uppoint (LClosure *cl) { | 51 | while ((p = *pp) != NULL && p->v >= level) { |
| 49 | StkId lp = NULL; | 52 | if (p->v == level) return p; |
| 50 | int i; | 53 | pp = &p->next; |
| 51 | for (i=0; i<cl->nupvalues; i++) { | ||
| 52 | if (!isclosed(cl->upvals[i]) && (lp == NULL || cl->upvals[i] > lp)) | ||
| 53 | lp = cl->upvals[i]; | ||
| 54 | } | ||
| 55 | return lp; | ||
| 56 | } | ||
| 57 | |||
| 58 | |||
| 59 | void luaF_LConlist (lua_State *L, Closure *cl) { | ||
| 60 | StkId cli = uppoint(&cl->l); | ||
| 61 | if (cli == NULL) { /* no more open entries? */ | ||
| 62 | cl->l.next = G(L)->rootcl; /* insert in final list */ | ||
| 63 | G(L)->rootcl = cl; | ||
| 64 | } | ||
| 65 | else { /* insert in list of open closures, ordered by decreasing uppoints */ | ||
| 66 | Closure **p = &L->opencl; | ||
| 67 | while (*p != NULL && uppoint(&(*p)->l) > cli) p = &(*p)->l.next; | ||
| 68 | cl->l.next = *p; | ||
| 69 | *p = cl; | ||
| 70 | } | 54 | } |
| 71 | } | 55 | p = luaM_new(L, UpVal); /* not found: create a new one */ |
| 72 | 56 | p->v = level; /* current value lives in the stack */ | |
| 73 | 57 | p->mark = 1; /* won't participate in GC while open */ | |
| 74 | static int closeCl (lua_State *L, LClosure *cl, StkId level) { | 58 | p->next = *pp; /* chain it in the proper position */ |
| 75 | int got = 0; /* flag: 1 if some pointer in the closure was corrected */ | 59 | *pp = p; |
| 76 | int i; | 60 | return p; |
| 77 | for (i=0; i<cl->nupvalues; i++) { | ||
| 78 | StkId var; | ||
| 79 | if (!isclosed(cl->upvals[i]) && (var=cl->upvals[i]) >= level) { | ||
| 80 | if (ttype(var) != LUA_TUPVAL) { | ||
| 81 | TObject *v = luaM_newvector(L, 2, TObject); | ||
| 82 | v[1] = *var; | ||
| 83 | setupvalue(v, G(L)->rootupval, LUA_HEAPUPVAL); | ||
| 84 | G(L)->rootupval = v; | ||
| 85 | setupvalue(var, &v[1], LUA_TUPVAL); | ||
| 86 | } | ||
| 87 | cl->upvals[i] = vvalue(var); | ||
| 88 | got = 1; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | return got; | ||
| 92 | } | 61 | } |
| 93 | 62 | ||
| 94 | 63 | ||
| 95 | void luaF_close (lua_State *L, StkId level) { | 64 | void luaF_close (lua_State *L, StkId level) { |
| 96 | Closure *affected = NULL; /* closures with open pointers >= level */ | 65 | UpVal *p; |
| 97 | Closure *cl; | 66 | while ((p = L->openupval) != NULL && p->v >= level) { |
| 98 | while ((cl=L->opencl) != NULL) { | 67 | setobj(&p->value, p->v); /* save current value */ |
| 99 | if (!closeCl(L, cast(LClosure *, cl), level)) break; | 68 | p->v = &p->value; /* now current value lives here */ |
| 100 | /* some pointer in `cl' changed; will re-insert it in original list */ | 69 | L->openupval = p->next; /* remove from `open' list */ |
| 101 | L->opencl = cl->l.next; /* remove from original list */ | 70 | p->next = G(L)->rootupval; /* chain in `closed' list */ |
| 102 | cl->l.next = affected; | 71 | p->mark = 0; /* now it can be collected */ |
| 103 | affected = cl; /* insert in affected list */ | 72 | G(L)->rootupval = p; |
| 104 | } | ||
| 105 | /* re-insert all affected closures in original list */ | ||
| 106 | while ((cl=affected) != NULL) { | ||
| 107 | affected = cl->l.next; | ||
| 108 | luaF_LConlist(L, cl); | ||
| 109 | } | 73 | } |
| 110 | } | 74 | } |
| 111 | 75 | ||
