2 ** Function handling (prototypes, functions and upvalues).
3 ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h
5 ** Portions taken verbatim or adapted from the Lua interpreter.
6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
18 /* -- Prototypes ---------------------------------------------------------- */
20 void LJ_FASTCALL
lj_func_freeproto(global_State
*g
, GCproto
*pt
)
22 lj_mem_free(g
, pt
, pt
->sizept
);
25 /* -- Upvalues ------------------------------------------------------------ */
27 static void unlinkuv(global_State
*g
, GCupval
*uv
)
30 lj_assertG(uvprev(uvnext(uv
)) == uv
&& uvnext(uvprev(uv
)) == uv
,
31 "broken upvalue chain");
32 setgcrefr(uvnext(uv
)->prev
, uv
->prev
);
33 setgcrefr(uvprev(uv
)->next
, uv
->next
);
36 /* Find existing open upvalue for a stack slot or create a new one. */
37 static GCupval
*func_finduv(lua_State
*L
, TValue
*slot
)
39 global_State
*g
= G(L
);
40 GCRef
*pp
= &L
->openupval
;
43 /* Search the sorted list of open upvalues. */
44 while (gcref(*pp
) != NULL
&& uvval((p
= gco2uv(gcref(*pp
)))) >= slot
) {
45 lj_assertG(!p
->closed
&& uvval(p
) != &p
->tv
, "closed upvalue in chain");
46 if (uvval(p
) == slot
) { /* Found open upvalue pointing to same slot? */
47 if (isdead(g
, obj2gco(p
))) /* Resurrect it, if it's dead. */
48 flipwhite(obj2gco(p
));
53 /* No matching upvalue found. Create a new one. */
54 uv
= lj_mem_newt(L
, sizeof(GCupval
), GCupval
);
57 uv
->closed
= 0; /* Still open. */
58 setmref(uv
->v
, slot
); /* Pointing to the stack slot. */
59 /* NOBARRIER: The GCupval is new (marked white) and open. */
60 setgcrefr(uv
->nextgc
, *pp
); /* Insert into sorted list of open upvalues. */
61 setgcref(*pp
, obj2gco(uv
));
62 setgcref(uv
->prev
, obj2gco(&g
->uvhead
)); /* Insert into GC list, too. */
63 setgcrefr(uv
->next
, g
->uvhead
.next
);
64 setgcref(uvnext(uv
)->prev
, obj2gco(uv
));
65 setgcref(g
->uvhead
.next
, obj2gco(uv
));
66 lj_assertG(uvprev(uvnext(uv
)) == uv
&& uvnext(uvprev(uv
)) == uv
,
67 "broken upvalue chain");
71 /* Create an empty and closed upvalue. */
72 static GCupval
*func_emptyuv(lua_State
*L
)
74 GCupval
*uv
= (GCupval
*)lj_mem_newgco(L
, sizeof(GCupval
));
78 setmref(uv
->v
, &uv
->tv
);
82 /* Close all open upvalues pointing to some stack level or above. */
83 void LJ_FASTCALL
lj_func_closeuv(lua_State
*L
, TValue
*level
)
86 global_State
*g
= G(L
);
87 while (gcref(L
->openupval
) != NULL
&&
88 uvval((uv
= gco2uv(gcref(L
->openupval
)))) >= level
) {
89 GCobj
*o
= obj2gco(uv
);
90 lj_assertG(!isblack(o
), "bad black upvalue");
91 lj_assertG(!uv
->closed
&& uvval(uv
) != &uv
->tv
, "closed upvalue in chain");
92 setgcrefr(L
->openupval
, uv
->nextgc
); /* No longer in open list. */
94 lj_func_freeuv(g
, uv
);
102 void LJ_FASTCALL
lj_func_freeuv(global_State
*g
, GCupval
*uv
)
109 /* -- Functions (closures) ------------------------------------------------ */
111 GCfunc
*lj_func_newC(lua_State
*L
, MSize nelems
, GCtab
*env
)
113 GCfunc
*fn
= (GCfunc
*)lj_mem_newgco(L
, sizeCfunc(nelems
));
114 fn
->c
.gct
= ~LJ_TFUNC
;
116 fn
->c
.nupvalues
= (uint8_t)nelems
;
117 /* NOBARRIER: The GCfunc is new (marked white). */
118 setmref(fn
->c
.pc
, &G(L
)->bc_cfunc_ext
);
119 setgcref(fn
->c
.env
, obj2gco(env
));
123 static GCfunc
*func_newL(lua_State
*L
, GCproto
*pt
, GCtab
*env
)
126 GCfunc
*fn
= (GCfunc
*)lj_mem_newgco(L
, sizeLfunc((MSize
)pt
->sizeuv
));
127 fn
->l
.gct
= ~LJ_TFUNC
;
129 fn
->l
.nupvalues
= 0; /* Set to zero until upvalues are initialized. */
130 /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */
131 setmref(fn
->l
.pc
, proto_bc(pt
));
132 setgcref(fn
->l
.env
, obj2gco(env
));
133 /* Saturating 3 bit counter (0..7) for created closures. */
134 count
= (uint32_t)pt
->flags
+ PROTO_CLCOUNT
;
135 pt
->flags
= (uint8_t)(count
- ((count
>> PROTO_CLC_BITS
) & PROTO_CLCOUNT
));
139 /* Create a new Lua function with empty upvalues. */
140 GCfunc
*lj_func_newL_empty(lua_State
*L
, GCproto
*pt
, GCtab
*env
)
142 GCfunc
*fn
= func_newL(L
, pt
, env
);
143 MSize i
, nuv
= pt
->sizeuv
;
144 /* NOBARRIER: The GCfunc is new (marked white). */
145 for (i
= 0; i
< nuv
; i
++) {
146 GCupval
*uv
= func_emptyuv(L
);
147 int32_t v
= proto_uv(pt
)[i
];
148 uv
->immutable
= ((v
/ PROTO_UV_IMMUTABLE
) & 1);
149 uv
->dhash
= (uint32_t)(uintptr_t)pt
^ (v
<< 24);
150 setgcref(fn
->l
.uvptr
[i
], obj2gco(uv
));
152 fn
->l
.nupvalues
= (uint8_t)nuv
;
156 /* Do a GC check and create a new Lua function with inherited upvalues. */
157 GCfunc
*lj_func_newL_gc(lua_State
*L
, GCproto
*pt
, GCfuncL
*parent
)
163 lj_gc_check_fixtop(L
);
164 fn
= func_newL(L
, pt
, tabref(parent
->env
));
165 /* NOBARRIER: The GCfunc is new (marked white). */
169 for (i
= 0; i
< nuv
; i
++) {
170 uint32_t v
= proto_uv(pt
)[i
];
172 if ((v
& PROTO_UV_LOCAL
)) {
173 uv
= func_finduv(L
, base
+ (v
& 0xff));
174 uv
->immutable
= ((v
/ PROTO_UV_IMMUTABLE
) & 1);
175 uv
->dhash
= (uint32_t)(uintptr_t)mref(parent
->pc
, char) ^ (v
<< 24);
177 uv
= &gcref(puv
[v
])->uv
;
179 setgcref(fn
->l
.uvptr
[i
], obj2gco(uv
));
181 fn
->l
.nupvalues
= (uint8_t)nuv
;
185 void LJ_FASTCALL
lj_func_free(global_State
*g
, GCfunc
*fn
)
187 MSize size
= isluafunc(fn
) ? sizeLfunc((MSize
)fn
->l
.nupvalues
) :
188 sizeCfunc((MSize
)fn
->c
.nupvalues
);
189 lj_mem_free(g
, fn
, size
);