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 | ||