1 /* $NetBSD: lfunc.c,v 1.11 2023/06/08 21:12:08 nikita Exp $ */ 2 3 /* 4 ** Id: lfunc.c 5 ** Auxiliary functions to manipulate prototypes and closures 6 ** See Copyright Notice in lua.h 7 */ 8 9 #define lfunc_c 10 #define LUA_CORE 11 12 #include "lprefix.h" 13 14 15 #ifndef _KERNEL 16 #include <stddef.h> 17 #endif /* _KERNEL */ 18 19 #include "lua.h" 20 21 #include "ldebug.h" 22 #include "ldo.h" 23 #include "lfunc.h" 24 #include "lgc.h" 25 #include "lmem.h" 26 #include "lobject.h" 27 #include "lstate.h" 28 29 30 31 CClosure *luaF_newCclosure (lua_State *L, int nupvals) { 32 GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals)); 33 CClosure *c = gco2ccl(o); 34 c->nupvalues = cast_byte(nupvals); 35 return c; 36 } 37 38 39 LClosure *luaF_newLclosure (lua_State *L, int nupvals) { 40 GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals)); 41 LClosure *c = gco2lcl(o); 42 c->p = NULL; 43 c->nupvalues = cast_byte(nupvals); 44 while (nupvals--) c->upvals[nupvals] = NULL; 45 return c; 46 } 47 48 49 /* 50 ** fill a closure with new closed upvalues 51 */ 52 void luaF_initupvals (lua_State *L, LClosure *cl) { 53 int i; 54 for (i = 0; i < cl->nupvalues; i++) { 55 GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); 56 UpVal *uv = gco2upv(o); 57 uv->v.p = &uv->u.value; /* make it closed */ 58 setnilvalue(uv->v.p); 59 cl->upvals[i] = uv; 60 luaC_objbarrier(L, cl, uv); 61 } 62 } 63 64 65 /* 66 ** Create a new upvalue at the given level, and link it to the list of 67 ** open upvalues of 'L' after entry 'prev'. 68 **/ 69 static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { 70 GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); 71 UpVal *uv = gco2upv(o); 72 UpVal *next = *prev; 73 uv->v.p = s2v(level); /* current value lives in the stack */ 74 uv->u.open.next = next; /* link it to list of open upvalues */ 75 uv->u.open.previous = prev; 76 if (next) 77 next->u.open.previous = &uv->u.open.next; 78 *prev = uv; 79 if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 80 L->twups = G(L)->twups; /* link it to the list */ 81 G(L)->twups = L; 82 } 83 return uv; 84 } 85 86 87 /* 88 ** Find and reuse, or create if it does not exist, an upvalue 89 ** at the given level. 90 */ 91 UpVal *luaF_findupval (lua_State *L, StkId level) { 92 UpVal **pp = &L->openupval; 93 UpVal *p; 94 lua_assert(isintwups(L) || L->openupval == NULL); 95 while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ 96 lua_assert(!isdead(G(L), p)); 97 if (uplevel(p) == level) /* corresponding upvalue? */ 98 return p; /* return it */ 99 pp = &p->u.open.next; 100 } 101 /* not found: create a new upvalue after 'pp' */ 102 return newupval(L, level, pp); 103 } 104 105 106 /* 107 ** Call closing method for object 'obj' with error message 'err'. The 108 ** boolean 'yy' controls whether the call is yieldable. 109 ** (This function assumes EXTRA_STACK.) 110 */ 111 static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { 112 StkId top = L->top.p; 113 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); 114 setobj2s(L, top, tm); /* will call metamethod... */ 115 setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ 116 setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ 117 L->top.p = top + 3; /* add function and arguments */ 118 if (yy) 119 luaD_call(L, top, 0); 120 else 121 luaD_callnoyield(L, top, 0); 122 } 123 124 125 /* 126 ** Check whether object at given level has a close metamethod and raise 127 ** an error if not. 128 */ 129 static void checkclosemth (lua_State *L, StkId level) { 130 const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); 131 if (ttisnil(tm)) { /* no metamethod? */ 132 int idx = cast_int(level - L->ci->func.p); /* variable index */ 133 const char *vname = luaG_findlocal(L, L->ci, idx, NULL); 134 if (vname == NULL) vname = "?"; 135 luaG_runerror(L, "variable '%s' got a non-closable value", vname); 136 } 137 } 138 139 140 /* 141 ** Prepare and call a closing method. 142 ** If status is CLOSEKTOP, the call to the closing method will be pushed 143 ** at the top of the stack. Otherwise, values can be pushed right after 144 ** the 'level' of the upvalue being closed, as everything after that 145 ** won't be used again. 146 */ 147 static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { 148 TValue *uv = s2v(level); /* value being closed */ 149 TValue *errobj; 150 if (status == CLOSEKTOP) 151 errobj = &G(L)->nilvalue; /* error object is nil */ 152 else { /* 'luaD_seterrorobj' will set top to level + 2 */ 153 errobj = s2v(level + 1); /* error object goes after 'uv' */ 154 luaD_seterrorobj(L, status, level + 1); /* set error object */ 155 } 156 callclosemethod(L, uv, errobj, yy); 157 } 158 159 160 /* 161 ** Maximum value for deltas in 'tbclist', dependent on the type 162 ** of delta. (This macro assumes that an 'L' is in scope where it 163 ** is used.) 164 */ 165 #define MAXDELTA \ 166 ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) 167 168 169 /* 170 ** Insert a variable in the list of to-be-closed variables. 171 */ 172 void luaF_newtbcupval (lua_State *L, StkId level) { 173 lua_assert(level > L->tbclist.p); 174 if (l_isfalse(s2v(level))) 175 return; /* false doesn't need to be closed */ 176 checkclosemth(L, level); /* value must have a close method */ 177 while (cast_uint(level - L->tbclist.p) > MAXDELTA) { 178 L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ 179 L->tbclist.p->tbclist.delta = 0; 180 } 181 level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); 182 L->tbclist.p = level; 183 } 184 185 186 void luaF_unlinkupval (UpVal *uv) { 187 lua_assert(upisopen(uv)); 188 *uv->u.open.previous = uv->u.open.next; 189 if (uv->u.open.next) 190 uv->u.open.next->u.open.previous = uv->u.open.previous; 191 } 192 193 194 /* 195 ** Close all upvalues up to the given stack level. 196 */ 197 void luaF_closeupval (lua_State *L, StkId level) { 198 UpVal *uv; 199 StkId upl; /* stack index pointed by 'uv' */ 200 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { 201 TValue *slot = &uv->u.value; /* new position for value */ 202 lua_assert(uplevel(uv) < L->top.p); 203 luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ 204 setobj(L, slot, uv->v.p); /* move value to upvalue slot */ 205 uv->v.p = slot; /* now current value lives here */ 206 if (!iswhite(uv)) { /* neither white nor dead? */ 207 nw2black(uv); /* closed upvalues cannot be gray */ 208 luaC_barrier(L, uv, slot); 209 } 210 } 211 } 212 213 214 /* 215 ** Remove first element from the tbclist plus its dummy nodes. 216 */ 217 static void poptbclist (lua_State *L) { 218 StkId tbc = L->tbclist.p; 219 lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ 220 tbc -= tbc->tbclist.delta; 221 while (tbc > L->stack.p && tbc->tbclist.delta == 0) 222 tbc -= MAXDELTA; /* remove dummy nodes */ 223 L->tbclist.p = tbc; 224 } 225 226 227 /* 228 ** Close all upvalues and to-be-closed variables up to the given stack 229 ** level. Return restored 'level'. 230 */ 231 StkId luaF_close (lua_State *L, StkId level, int status, int yy) { 232 ptrdiff_t levelrel = savestack(L, level); 233 luaF_closeupval(L, level); /* first, close the upvalues */ 234 while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ 235 StkId tbc = L->tbclist.p; /* get variable index */ 236 poptbclist(L); /* remove it from list */ 237 prepcallclosemth(L, tbc, status, yy); /* close variable */ 238 level = restorestack(L, levelrel); 239 } 240 return level; 241 } 242 243 244 Proto *luaF_newproto (lua_State *L) { 245 GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto)); 246 Proto *f = gco2p(o); 247 f->k = NULL; 248 f->sizek = 0; 249 f->p = NULL; 250 f->sizep = 0; 251 f->code = NULL; 252 f->sizecode = 0; 253 f->lineinfo = NULL; 254 f->sizelineinfo = 0; 255 f->abslineinfo = NULL; 256 f->sizeabslineinfo = 0; 257 f->upvalues = NULL; 258 f->sizeupvalues = 0; 259 f->numparams = 0; 260 f->is_vararg = 0; 261 f->maxstacksize = 0; 262 f->locvars = NULL; 263 f->sizelocvars = 0; 264 f->linedefined = 0; 265 f->lastlinedefined = 0; 266 f->source = NULL; 267 return f; 268 } 269 270 271 void luaF_freeproto (lua_State *L, Proto *f) { 272 luaM_freearray(L, f->code, f->sizecode); 273 luaM_freearray(L, f->p, f->sizep); 274 luaM_freearray(L, f->k, f->sizek); 275 luaM_freearray(L, f->lineinfo, f->sizelineinfo); 276 luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); 277 luaM_freearray(L, f->locvars, f->sizelocvars); 278 luaM_freearray(L, f->upvalues, f->sizeupvalues); 279 luaM_free(L, f); 280 } 281 282 283 /* 284 ** Look for n-th local variable at line 'line' in function 'func'. 285 ** Returns NULL if not found. 286 */ 287 const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 288 int i; 289 for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { 290 if (pc < f->locvars[i].endpc) { /* is variable active? */ 291 local_number--; 292 if (local_number == 0) 293 return getstr(f->locvars[i].varname); 294 } 295 } 296 return NULL; /* not found */ 297 } 298 299