Mercurial
comparison third_party/luajit/src/lj_lib.c @ 186:8cf4ec5e2191 hg-web
Fixed merge conflict.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 22:38:59 -0800 |
| parents | 94705b5986b3 |
| children |
comparison
equal
deleted
inserted
replaced
| 176:fed99fc04e12 | 186:8cf4ec5e2191 |
|---|---|
| 1 /* | |
| 2 ** Library function support. | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 */ | |
| 5 | |
| 6 #define lj_lib_c | |
| 7 #define LUA_CORE | |
| 8 | |
| 9 #include "lauxlib.h" | |
| 10 | |
| 11 #include "lj_obj.h" | |
| 12 #include "lj_gc.h" | |
| 13 #include "lj_err.h" | |
| 14 #include "lj_str.h" | |
| 15 #include "lj_tab.h" | |
| 16 #include "lj_func.h" | |
| 17 #include "lj_bc.h" | |
| 18 #include "lj_dispatch.h" | |
| 19 #if LJ_HASFFI | |
| 20 #include "lj_ctype.h" | |
| 21 #endif | |
| 22 #include "lj_vm.h" | |
| 23 #include "lj_strscan.h" | |
| 24 #include "lj_strfmt.h" | |
| 25 #include "lj_lex.h" | |
| 26 #include "lj_bcdump.h" | |
| 27 #include "lj_lib.h" | |
| 28 | |
| 29 /* -- Library initialization ---------------------------------------------- */ | |
| 30 | |
| 31 static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize) | |
| 32 { | |
| 33 if (libname) { | |
| 34 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16); | |
| 35 lua_getfield(L, -1, libname); | |
| 36 if (!tvistab(L->top-1)) { | |
| 37 L->top--; | |
| 38 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL) | |
| 39 lj_err_callerv(L, LJ_ERR_BADMODN, libname); | |
| 40 settabV(L, L->top, tabV(L->top-1)); | |
| 41 L->top++; | |
| 42 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ | |
| 43 } | |
| 44 L->top--; | |
| 45 settabV(L, L->top-1, tabV(L->top)); | |
| 46 } else { | |
| 47 lua_createtable(L, 0, hsize); | |
| 48 } | |
| 49 return tabV(L->top-1); | |
| 50 } | |
| 51 | |
| 52 static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) | |
| 53 { | |
| 54 int len = *p++; | |
| 55 GCstr *name = lj_str_new(L, (const char *)p, len); | |
| 56 LexState ls; | |
| 57 GCproto *pt; | |
| 58 GCfunc *fn; | |
| 59 memset(&ls, 0, sizeof(ls)); | |
| 60 ls.L = L; | |
| 61 ls.p = (const char *)(p+len); | |
| 62 ls.pe = (const char *)~(uintptr_t)0; | |
| 63 ls.c = -1; | |
| 64 ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); | |
| 65 ls.chunkname = name; | |
| 66 pt = lj_bcread_proto(&ls); | |
| 67 pt->firstline = ~(BCLine)0; | |
| 68 fn = lj_func_newL_empty(L, pt, tabref(L->env)); | |
| 69 /* NOBARRIER: See below for common barrier. */ | |
| 70 setfuncV(L, lj_tab_setstr(L, tab, name), fn); | |
| 71 return (const uint8_t *)ls.p; | |
| 72 } | |
| 73 | |
| 74 void lj_lib_register(lua_State *L, const char *libname, | |
| 75 const uint8_t *p, const lua_CFunction *cf) | |
| 76 { | |
| 77 GCtab *env = tabref(L->env); | |
| 78 GCfunc *ofn = NULL; | |
| 79 int ffid = *p++; | |
| 80 BCIns *bcff = &L2GG(L)->bcff[*p++]; | |
| 81 GCtab *tab = lib_create_table(L, libname, *p++); | |
| 82 ptrdiff_t tpos = L->top - L->base; | |
| 83 | |
| 84 /* Avoid barriers further down. */ | |
| 85 lj_gc_anybarriert(L, tab); | |
| 86 tab->nomm = 0; | |
| 87 | |
| 88 for (;;) { | |
| 89 uint32_t tag = *p++; | |
| 90 MSize len = tag & LIBINIT_LENMASK; | |
| 91 tag &= LIBINIT_TAGMASK; | |
| 92 if (tag != LIBINIT_STRING) { | |
| 93 const char *name; | |
| 94 MSize nuv = (MSize)(L->top - L->base - tpos); | |
| 95 GCfunc *fn = lj_func_newC(L, nuv, env); | |
| 96 if (nuv) { | |
| 97 L->top = L->base + tpos; | |
| 98 memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv); | |
| 99 } | |
| 100 fn->c.ffid = (uint8_t)(ffid++); | |
| 101 name = (const char *)p; | |
| 102 p += len; | |
| 103 if (tag == LIBINIT_CF) | |
| 104 setmref(fn->c.pc, &G(L)->bc_cfunc_int); | |
| 105 else | |
| 106 setmref(fn->c.pc, bcff++); | |
| 107 if (tag == LIBINIT_ASM_) | |
| 108 fn->c.f = ofn->c.f; /* Copy handler from previous function. */ | |
| 109 else | |
| 110 fn->c.f = *cf++; /* Get cf or handler from C function table. */ | |
| 111 if (len) { | |
| 112 /* NOBARRIER: See above for common barrier. */ | |
| 113 setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn); | |
| 114 } | |
| 115 ofn = fn; | |
| 116 } else { | |
| 117 switch (tag | len) { | |
| 118 case LIBINIT_LUA: | |
| 119 p = lib_read_lfunc(L, p, tab); | |
| 120 break; | |
| 121 case LIBINIT_SET: | |
| 122 L->top -= 2; | |
| 123 if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) | |
| 124 env = tabV(L->top); | |
| 125 else /* NOBARRIER: See above for common barrier. */ | |
| 126 copyTV(L, lj_tab_set(L, tab, L->top+1), L->top); | |
| 127 break; | |
| 128 case LIBINIT_NUMBER: | |
| 129 memcpy(&L->top->n, p, sizeof(double)); | |
| 130 L->top++; | |
| 131 p += sizeof(double); | |
| 132 break; | |
| 133 case LIBINIT_COPY: | |
| 134 copyTV(L, L->top, L->top - *p++); | |
| 135 L->top++; | |
| 136 break; | |
| 137 case LIBINIT_LASTCL: | |
| 138 setfuncV(L, L->top++, ofn); | |
| 139 break; | |
| 140 case LIBINIT_FFID: | |
| 141 ffid++; | |
| 142 break; | |
| 143 case LIBINIT_END: | |
| 144 return; | |
| 145 default: | |
| 146 setstrV(L, L->top++, lj_str_new(L, (const char *)p, len)); | |
| 147 p += len; | |
| 148 break; | |
| 149 } | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 /* Push internal function on the stack. */ | |
| 155 GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n) | |
| 156 { | |
| 157 GCfunc *fn; | |
| 158 lua_pushcclosure(L, f, n); | |
| 159 fn = funcV(L->top-1); | |
| 160 fn->c.ffid = (uint8_t)id; | |
| 161 setmref(fn->c.pc, &G(L)->bc_cfunc_int); | |
| 162 return fn; | |
| 163 } | |
| 164 | |
| 165 void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, GCtab *env) | |
| 166 { | |
| 167 luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4); | |
| 168 lua_pushcfunction(L, f); | |
| 169 /* NOBARRIER: The function is new (marked white). */ | |
| 170 setgcref(funcV(L->top-1)->c.env, obj2gco(env)); | |
| 171 lua_setfield(L, -2, name); | |
| 172 L->top--; | |
| 173 } | |
| 174 | |
| 175 int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, const char *name) | |
| 176 { | |
| 177 GCfunc *fn = lj_lib_pushcf(L, cf, id); | |
| 178 GCtab *t = tabref(curr_func(L)->c.env); /* Reference to parent table. */ | |
| 179 setfuncV(L, lj_tab_setstr(L, t, lj_str_newz(L, name)), fn); | |
| 180 lj_gc_anybarriert(L, t); | |
| 181 setfuncV(L, L->top++, fn); | |
| 182 return 1; | |
| 183 } | |
| 184 | |
| 185 /* -- Type checks --------------------------------------------------------- */ | |
| 186 | |
| 187 TValue *lj_lib_checkany(lua_State *L, int narg) | |
| 188 { | |
| 189 TValue *o = L->base + narg-1; | |
| 190 if (o >= L->top) | |
| 191 lj_err_arg(L, narg, LJ_ERR_NOVAL); | |
| 192 return o; | |
| 193 } | |
| 194 | |
| 195 GCstr *lj_lib_checkstr(lua_State *L, int narg) | |
| 196 { | |
| 197 TValue *o = L->base + narg-1; | |
| 198 if (o < L->top) { | |
| 199 if (LJ_LIKELY(tvisstr(o))) { | |
| 200 return strV(o); | |
| 201 } else if (tvisnumber(o)) { | |
| 202 GCstr *s = lj_strfmt_number(L, o); | |
| 203 setstrV(L, o, s); | |
| 204 return s; | |
| 205 } | |
| 206 } | |
| 207 lj_err_argt(L, narg, LUA_TSTRING); | |
| 208 return NULL; /* unreachable */ | |
| 209 } | |
| 210 | |
| 211 GCstr *lj_lib_optstr(lua_State *L, int narg) | |
| 212 { | |
| 213 TValue *o = L->base + narg-1; | |
| 214 return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL; | |
| 215 } | |
| 216 | |
| 217 #if LJ_DUALNUM | |
| 218 void lj_lib_checknumber(lua_State *L, int narg) | |
| 219 { | |
| 220 TValue *o = L->base + narg-1; | |
| 221 if (!(o < L->top && lj_strscan_numberobj(o))) | |
| 222 lj_err_argt(L, narg, LUA_TNUMBER); | |
| 223 } | |
| 224 #endif | |
| 225 | |
| 226 lua_Number lj_lib_checknum(lua_State *L, int narg) | |
| 227 { | |
| 228 TValue *o = L->base + narg-1; | |
| 229 if (!(o < L->top && | |
| 230 (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o))))) | |
| 231 lj_err_argt(L, narg, LUA_TNUMBER); | |
| 232 if (LJ_UNLIKELY(tvisint(o))) { | |
| 233 lua_Number n = (lua_Number)intV(o); | |
| 234 setnumV(o, n); | |
| 235 return n; | |
| 236 } else { | |
| 237 return numV(o); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 int32_t lj_lib_checkint(lua_State *L, int narg) | |
| 242 { | |
| 243 TValue *o = L->base + narg-1; | |
| 244 if (!(o < L->top && lj_strscan_numberobj(o))) | |
| 245 lj_err_argt(L, narg, LUA_TNUMBER); | |
| 246 if (LJ_LIKELY(tvisint(o))) { | |
| 247 return intV(o); | |
| 248 } else { | |
| 249 int32_t i = lj_num2int(numV(o)); | |
| 250 if (LJ_DUALNUM) setintV(o, i); | |
| 251 return i; | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 int32_t lj_lib_optint(lua_State *L, int narg, int32_t def) | |
| 256 { | |
| 257 TValue *o = L->base + narg-1; | |
| 258 return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def; | |
| 259 } | |
| 260 | |
| 261 GCfunc *lj_lib_checkfunc(lua_State *L, int narg) | |
| 262 { | |
| 263 TValue *o = L->base + narg-1; | |
| 264 if (!(o < L->top && tvisfunc(o))) | |
| 265 lj_err_argt(L, narg, LUA_TFUNCTION); | |
| 266 return funcV(o); | |
| 267 } | |
| 268 | |
| 269 GCtab *lj_lib_checktab(lua_State *L, int narg) | |
| 270 { | |
| 271 TValue *o = L->base + narg-1; | |
| 272 if (!(o < L->top && tvistab(o))) | |
| 273 lj_err_argt(L, narg, LUA_TTABLE); | |
| 274 return tabV(o); | |
| 275 } | |
| 276 | |
| 277 GCtab *lj_lib_checktabornil(lua_State *L, int narg) | |
| 278 { | |
| 279 TValue *o = L->base + narg-1; | |
| 280 if (o < L->top) { | |
| 281 if (tvistab(o)) | |
| 282 return tabV(o); | |
| 283 else if (tvisnil(o)) | |
| 284 return NULL; | |
| 285 } | |
| 286 lj_err_arg(L, narg, LJ_ERR_NOTABN); | |
| 287 return NULL; /* unreachable */ | |
| 288 } | |
| 289 | |
| 290 int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst) | |
| 291 { | |
| 292 GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg); | |
| 293 if (s) { | |
| 294 const char *opt = strdata(s); | |
| 295 MSize len = s->len; | |
| 296 int i; | |
| 297 for (i = 0; *(const uint8_t *)lst; i++) { | |
| 298 if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0) | |
| 299 return i; | |
| 300 lst += 1+*(const uint8_t *)lst; | |
| 301 } | |
| 302 lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt); | |
| 303 } | |
| 304 return def; | |
| 305 } | |
| 306 | |
| 307 /* -- Strict type checks -------------------------------------------------- */ | |
| 308 | |
| 309 /* The following type checks do not coerce between strings and numbers. | |
| 310 ** And they handle plain int64_t/uint64_t FFI numbers, too. | |
| 311 */ | |
| 312 | |
| 313 #if LJ_HASBUFFER | |
| 314 GCstr *lj_lib_checkstrx(lua_State *L, int narg) | |
| 315 { | |
| 316 TValue *o = L->base + narg-1; | |
| 317 if (!(o < L->top && tvisstr(o))) lj_err_argt(L, narg, LUA_TSTRING); | |
| 318 return strV(o); | |
| 319 } | |
| 320 | |
| 321 int32_t lj_lib_checkintrange(lua_State *L, int narg, int32_t a, int32_t b) | |
| 322 { | |
| 323 TValue *o = L->base + narg-1; | |
| 324 lj_assertL(b >= 0, "expected range must be non-negative"); | |
| 325 if (o < L->top) { | |
| 326 if (LJ_LIKELY(tvisint(o))) { | |
| 327 int32_t i = intV(o); | |
| 328 if (i >= a && i <= b) return i; | |
| 329 } else if (LJ_LIKELY(tvisnum(o))) { | |
| 330 /* For performance reasons, this doesn't check for integerness or | |
| 331 ** integer overflow. Overflow detection still works, since all FPUs | |
| 332 ** return either MININT or MAXINT, which is then out of range. | |
| 333 */ | |
| 334 int32_t i = (int32_t)numV(o); | |
| 335 if (i >= a && i <= b) return i; | |
| 336 #if LJ_HASFFI | |
| 337 } else if (tviscdata(o)) { | |
| 338 GCcdata *cd = cdataV(o); | |
| 339 if (cd->ctypeid == CTID_INT64) { | |
| 340 int64_t i = *(int64_t *)cdataptr(cd); | |
| 341 if (i >= (int64_t)a && i <= (int64_t)b) return (int32_t)i; | |
| 342 } else if (cd->ctypeid == CTID_UINT64) { | |
| 343 uint64_t i = *(uint64_t *)cdataptr(cd); | |
| 344 if ((a < 0 || i >= (uint64_t)a) && i <= (uint64_t)b) return (int32_t)i; | |
| 345 } else { | |
| 346 goto badtype; | |
| 347 } | |
| 348 #endif | |
| 349 } else { | |
| 350 goto badtype; | |
| 351 } | |
| 352 lj_err_arg(L, narg, LJ_ERR_NUMRNG); | |
| 353 } | |
| 354 badtype: | |
| 355 lj_err_argt(L, narg, LUA_TNUMBER); | |
| 356 return 0; /* unreachable */ | |
| 357 } | |
| 358 #endif | |
| 359 |