aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/lfunc.c b/lfunc.c
index 0f839e7c..898104ac 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp roberto $ 2** $Id: lfunc.c,v 2.46 2017/04/06 13:08:56 roberto Exp roberto $
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*/
@@ -45,31 +45,35 @@ LClosure *luaF_newLclosure (lua_State *L, int n) {
45void luaF_initupvals (lua_State *L, LClosure *cl) { 45void luaF_initupvals (lua_State *L, LClosure *cl) {
46 int i; 46 int i;
47 for (i = 0; i < cl->nupvalues; i++) { 47 for (i = 0; i < cl->nupvalues; i++) {
48 UpVal *uv = luaM_new(L, UpVal); 48 GCObject *o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal));
49 uv->refcount = 1; 49 UpVal *uv = gco2upv(o);
50 uv->v = &uv->u.value; /* make it closed */ 50 uv->v = &uv->u.value; /* make it closed */
51 setnilvalue(uv->v); 51 setnilvalue(uv->v);
52 cl->upvals[i] = uv; 52 cl->upvals[i] = uv;
53 luaC_objbarrier(L, cl, o);
53 } 54 }
54} 55}
55 56
56 57
57UpVal *luaF_findupval (lua_State *L, StkId level) { 58UpVal *luaF_findupval (lua_State *L, StkId level) {
58 UpVal **pp = &L->openupval; 59 UpVal **pp = &L->openupval;
60 GCObject *o;
59 UpVal *p; 61 UpVal *p;
60 UpVal *uv; 62 UpVal *uv;
61 lua_assert(isintwups(L) || L->openupval == NULL); 63 lua_assert(isintwups(L) || L->openupval == NULL);
62 while (*pp != NULL && (p = *pp)->v >= level) { 64 while ((p = *pp) != NULL && p->v >= level) {
63 lua_assert(upisopen(p)); 65 lua_assert(upisopen(p));
64 if (p->v == level) /* found a corresponding upvalue? */ 66 if (p->v == level) /* found a corresponding upvalue? */
65 return p; /* return it */ 67 return p; /* return it */
66 pp = &p->u.open.next; 68 pp = &p->u.open.next;
67 } 69 }
68 /* not found: create a new upvalue */ 70 /* not found: create a new upvalue between 'pp' and 'p' */
69 uv = luaM_new(L, UpVal); 71 o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal));
70 uv->refcount = 0; 72 uv = gco2upv(o);
71 uv->u.open.next = *pp; /* link it to list of open upvalues */ 73 uv->u.open.next = p; /* link it to list of open upvalues */
72 uv->u.open.touched = 1; 74 uv->u.open.previous = pp;
75 if (p)
76 p->u.open.previous = &uv->u.open.next;
73 *pp = uv; 77 *pp = uv;
74 uv->v = level; /* current value lives in the stack */ 78 uv->v = level; /* current value lives in the stack */
75 if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 79 if (!isintwups(L)) { /* thread not in list of threads with upvalues? */
@@ -80,19 +84,24 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
80} 84}
81 85
82 86
87void luaF_unlinkupval (UpVal *uv) {
88 lua_assert(upisopen(uv));
89 *uv->u.open.previous = uv->u.open.next;
90 if (uv->u.open.next)
91 uv->u.open.next->u.open.previous = uv->u.open.previous;
92}
93
94
83void luaF_close (lua_State *L, StkId level) { 95void luaF_close (lua_State *L, StkId level) {
84 UpVal *uv; 96 UpVal *uv;
85 while (L->openupval != NULL && (uv = L->openupval)->v >= level) { 97 while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
86 lua_assert(upisopen(uv)); 98 TValue *slot = &uv->u.value; /* new position for value */
87 L->openupval = uv->u.open.next; /* remove from 'open' list */ 99 luaF_unlinkupval(uv);
88 if (uv->refcount == 0) /* no references? */ 100 setobj(L, slot, uv->v); /* move value to upvalue slot */
89 luaM_free(L, uv); /* free upvalue */ 101 uv->v = slot; /* now current value lives here */
90 else { 102 if (!iswhite(uv))
91 TValue *slot = &uv->u.value; /* new position for value */ 103 gray2black(uv); /* closed upvalues cannot be gray */
92 setobj(L, slot, uv->v); /* move value to upvalue slot */ 104 luaC_barrier(L, uv, slot);
93 uv->v = slot; /* now current value lives here */
94 luaC_upvalbarrier(L, uv, slot);
95 }
96 } 105 }
97} 106}
98 107