diff options
Diffstat (limited to '')
| -rw-r--r-- | lfunc.c | 100 |
1 files changed, 95 insertions, 5 deletions
| @@ -12,15 +12,20 @@ | |||
| 12 | 12 | ||
| 13 | #include "lfunc.h" | 13 | #include "lfunc.h" |
| 14 | #include "lmem.h" | 14 | #include "lmem.h" |
| 15 | #include "lobject.h" | ||
| 15 | #include "lstate.h" | 16 | #include "lstate.h" |
| 16 | 17 | ||
| 17 | 18 | ||
| 18 | #define sizeclosure(n) (cast(int, sizeof(Closure)) + \ | 19 | #define sizeCclosure(n) (cast(int, sizeof(Closure)) + \ |
| 19 | cast(int, sizeof(TObject)*((n)-1))) | 20 | cast(int, sizeof(TObject)*((n)-1))) |
| 20 | 21 | ||
| 22 | #define sizeLclosure(n) (cast(int, sizeof(Closure)) + \ | ||
| 23 | cast(int, sizeof(TObject *)*((n)-1))) | ||
| 21 | 24 | ||
| 22 | Closure *luaF_newclosure (lua_State *L, int nelems) { | 25 | |
| 23 | Closure *c = cast(Closure *, luaM_malloc(L, sizeclosure(nelems))); | 26 | Closure *luaF_newCclosure (lua_State *L, int nelems) { |
| 27 | Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); | ||
| 28 | c->isC = 1; | ||
| 24 | c->next = G(L)->rootcl; | 29 | c->next = G(L)->rootcl; |
| 25 | G(L)->rootcl = c; | 30 | G(L)->rootcl = c; |
| 26 | c->mark = c; | 31 | c->mark = c; |
| @@ -29,6 +34,90 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { | |||
| 29 | } | 34 | } |
| 30 | 35 | ||
| 31 | 36 | ||
| 37 | Closure *luaF_newLclosure (lua_State *L, int nelems) { | ||
| 38 | Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); | ||
| 39 | c->isC = 0; | ||
| 40 | c->mark = c; | ||
| 41 | c->u.l.isopen = 0; | ||
| 42 | c->nupvalues = nelems; | ||
| 43 | return c; | ||
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | ** returns the open pointer in a closure that points higher into the stack | ||
| 49 | */ | ||
| 50 | static StkId uppoint (Closure *cl) { | ||
| 51 | StkId lp = NULL; | ||
| 52 | int i; | ||
| 53 | lua_assert(cl->u.l.isopen); | ||
| 54 | for (i=0; i<cl->nupvalues; i++) { | ||
| 55 | if (!luaF_isclosed(cl, i)) | ||
| 56 | if (lp == NULL || cl->u.l.upvals[i] > lp) | ||
| 57 | lp = cl->u.l.upvals[i]; | ||
| 58 | } | ||
| 59 | lua_assert(lp != NULL); | ||
| 60 | return lp; | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | void luaF_LConlist (lua_State *L, Closure *cl) { | ||
| 65 | lua_assert(!cl->isC); | ||
| 66 | if (cl->u.l.isopen == 0) { /* no more open entries? */ | ||
| 67 | cl->next = G(L)->rootcl; /* insert in final list */ | ||
| 68 | G(L)->rootcl = cl; | ||
| 69 | } | ||
| 70 | else { /* insert in list of open closures, ordered by decreasing uppoints */ | ||
| 71 | StkId cli = uppoint(cl); | ||
| 72 | Closure **p = &L->opencl; | ||
| 73 | while (*p != NULL && uppoint(*p) > cli) p = &(*p)->next; | ||
| 74 | cl->next = *p; | ||
| 75 | *p = cl; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 80 | static int closeCl (lua_State *L, Closure *cl, StkId level) { | ||
| 81 | int got = 0; /* flag: 1 if some pointer in the closure was corrected */ | ||
| 82 | int i; | ||
| 83 | for (i=0; i<cl->nupvalues; i++) { | ||
| 84 | StkId var; | ||
| 85 | if (!luaF_isclosed(cl, i) && (var=cl->u.l.upvals[i]) >= level) { | ||
| 86 | if (ttype(var) != LUA_TUPVAL) { | ||
| 87 | UpVal *v = luaM_new(L, UpVal); | ||
| 88 | v->val = *var; | ||
| 89 | v->marked = 0; | ||
| 90 | v->next = G(L)->rootupval; | ||
| 91 | G(L)->rootupval = v; | ||
| 92 | setupvalue(var, v); | ||
| 93 | } | ||
| 94 | cl->u.l.upvals[i] = cast(TObject *, vvalue(var)); | ||
| 95 | luaF_closeentry(cl, i); | ||
| 96 | got = 1; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return got; | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | void luaF_close (lua_State *L, StkId level) { | ||
| 104 | Closure *affected = NULL; /* closures with open pointers >= level */ | ||
| 105 | Closure *cl; | ||
| 106 | while ((cl=L->opencl) != NULL) { | ||
| 107 | if (!closeCl(L, cl, level)) break; | ||
| 108 | /* some pointer in `cl' changed; will re-insert it in original list */ | ||
| 109 | L->opencl = cl->next; /* remove from original list */ | ||
| 110 | cl->next = affected; | ||
| 111 | affected = cl; /* insert in affected list */ | ||
| 112 | } | ||
| 113 | /* re-insert all affected closures in original list */ | ||
| 114 | while ((cl=affected) != NULL) { | ||
| 115 | affected = cl->next; | ||
| 116 | luaF_LConlist(L, cl); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 32 | Proto *luaF_newproto (lua_State *L) { | 121 | Proto *luaF_newproto (lua_State *L) { |
| 33 | Proto *f = luaM_new(L, Proto); | 122 | Proto *f = luaM_new(L, Proto); |
| 34 | f->k = NULL; | 123 | f->k = NULL; |
| @@ -60,12 +149,13 @@ void luaF_freeproto (lua_State *L, Proto *f) { | |||
| 60 | luaM_freearray(L, f->k, f->sizek, TObject); | 149 | luaM_freearray(L, f->k, f->sizek, TObject); |
| 61 | luaM_freearray(L, f->p, f->sizep, Proto *); | 150 | luaM_freearray(L, f->p, f->sizep, Proto *); |
| 62 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | 151 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); |
| 63 | luaM_freelem(L, f, Proto); | 152 | luaM_freelem(L, f); |
| 64 | } | 153 | } |
| 65 | 154 | ||
| 66 | 155 | ||
| 67 | void luaF_freeclosure (lua_State *L, Closure *c) { | 156 | void luaF_freeclosure (lua_State *L, Closure *c) { |
| 68 | luaM_free(L, c, sizeclosure(c->nupvalues)); | 157 | int size = (c->isC) ? sizeCclosure(c->nupvalues) : sizeLclosure(c->nupvalues); |
| 158 | luaM_free(L, c, size); | ||
| 69 | } | 159 | } |
| 70 | 160 | ||
| 71 | 161 | ||
