Mercurial
comparison third_party/luajit/src/lj_func.c @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 /* | |
| 2 ** Function handling (prototypes, functions and upvalues). | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 ** | |
| 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 | |
| 7 */ | |
| 8 | |
| 9 #define lj_func_c | |
| 10 #define LUA_CORE | |
| 11 | |
| 12 #include "lj_obj.h" | |
| 13 #include "lj_gc.h" | |
| 14 #include "lj_func.h" | |
| 15 #include "lj_trace.h" | |
| 16 #include "lj_vm.h" | |
| 17 | |
| 18 /* -- Prototypes ---------------------------------------------------------- */ | |
| 19 | |
| 20 void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt) | |
| 21 { | |
| 22 lj_mem_free(g, pt, pt->sizept); | |
| 23 } | |
| 24 | |
| 25 /* -- Upvalues ------------------------------------------------------------ */ | |
| 26 | |
| 27 static void unlinkuv(global_State *g, GCupval *uv) | |
| 28 { | |
| 29 UNUSED(g); | |
| 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); | |
| 34 } | |
| 35 | |
| 36 /* Find existing open upvalue for a stack slot or create a new one. */ | |
| 37 static GCupval *func_finduv(lua_State *L, TValue *slot) | |
| 38 { | |
| 39 global_State *g = G(L); | |
| 40 GCRef *pp = &L->openupval; | |
| 41 GCupval *p; | |
| 42 GCupval *uv; | |
| 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)); | |
| 49 return p; | |
| 50 } | |
| 51 pp = &p->nextgc; | |
| 52 } | |
| 53 /* No matching upvalue found. Create a new one. */ | |
| 54 uv = lj_mem_newt(L, sizeof(GCupval), GCupval); | |
| 55 newwhite(g, uv); | |
| 56 uv->gct = ~LJ_TUPVAL; | |
| 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"); | |
| 68 return uv; | |
| 69 } | |
| 70 | |
| 71 /* Create an empty and closed upvalue. */ | |
| 72 static GCupval *func_emptyuv(lua_State *L) | |
| 73 { | |
| 74 GCupval *uv = (GCupval *)lj_mem_newgco(L, sizeof(GCupval)); | |
| 75 uv->gct = ~LJ_TUPVAL; | |
| 76 uv->closed = 1; | |
| 77 setnilV(&uv->tv); | |
| 78 setmref(uv->v, &uv->tv); | |
| 79 return uv; | |
| 80 } | |
| 81 | |
| 82 /* Close all open upvalues pointing to some stack level or above. */ | |
| 83 void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level) | |
| 84 { | |
| 85 GCupval *uv; | |
| 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. */ | |
| 93 if (isdead(g, o)) { | |
| 94 lj_func_freeuv(g, uv); | |
| 95 } else { | |
| 96 unlinkuv(g, uv); | |
| 97 lj_gc_closeuv(g, uv); | |
| 98 } | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv) | |
| 103 { | |
| 104 if (!uv->closed) | |
| 105 unlinkuv(g, uv); | |
| 106 lj_mem_freet(g, uv); | |
| 107 } | |
| 108 | |
| 109 /* -- Functions (closures) ------------------------------------------------ */ | |
| 110 | |
| 111 GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env) | |
| 112 { | |
| 113 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeCfunc(nelems)); | |
| 114 fn->c.gct = ~LJ_TFUNC; | |
| 115 fn->c.ffid = FF_C; | |
| 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)); | |
| 120 return fn; | |
| 121 } | |
| 122 | |
| 123 static GCfunc *func_newL(lua_State *L, GCproto *pt, GCtab *env) | |
| 124 { | |
| 125 uint32_t count; | |
| 126 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv)); | |
| 127 fn->l.gct = ~LJ_TFUNC; | |
| 128 fn->l.ffid = FF_LUA; | |
| 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)); | |
| 136 return fn; | |
| 137 } | |
| 138 | |
| 139 /* Create a new Lua function with empty upvalues. */ | |
| 140 GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env) | |
| 141 { | |
| 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)); | |
| 151 } | |
| 152 fn->l.nupvalues = (uint8_t)nuv; | |
| 153 return fn; | |
| 154 } | |
| 155 | |
| 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) | |
| 158 { | |
| 159 GCfunc *fn; | |
| 160 GCRef *puv; | |
| 161 MSize i, nuv; | |
| 162 TValue *base; | |
| 163 lj_gc_check_fixtop(L); | |
| 164 fn = func_newL(L, pt, tabref(parent->env)); | |
| 165 /* NOBARRIER: The GCfunc is new (marked white). */ | |
| 166 puv = parent->uvptr; | |
| 167 nuv = pt->sizeuv; | |
| 168 base = L->base; | |
| 169 for (i = 0; i < nuv; i++) { | |
| 170 uint32_t v = proto_uv(pt)[i]; | |
| 171 GCupval *uv; | |
| 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); | |
| 176 } else { | |
| 177 uv = &gcref(puv[v])->uv; | |
| 178 } | |
| 179 setgcref(fn->l.uvptr[i], obj2gco(uv)); | |
| 180 } | |
| 181 fn->l.nupvalues = (uint8_t)nuv; | |
| 182 return fn; | |
| 183 } | |
| 184 | |
| 185 void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *fn) | |
| 186 { | |
| 187 MSize size = isluafunc(fn) ? sizeLfunc((MSize)fn->l.nupvalues) : | |
| 188 sizeCfunc((MSize)fn->c.nupvalues); | |
| 189 lj_mem_free(g, fn, size); | |
| 190 } | |
| 191 |