/src/tarantool/third_party/luajit/src/lj_lib.c
Line | Count | Source |
1 | | /* |
2 | | ** Library function support. |
3 | | ** Copyright (C) 2005-2017 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 | | #include "lj_vm.h" |
20 | | #include "lj_strscan.h" |
21 | | #include "lj_strfmt.h" |
22 | | #include "lj_lex.h" |
23 | | #include "lj_bcdump.h" |
24 | | #include "lj_lib.h" |
25 | | |
26 | | /* -- Library initialization ---------------------------------------------- */ |
27 | | |
28 | | static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize) |
29 | 477k | { |
30 | 477k | if (libname) { |
31 | 397k | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16); |
32 | 397k | lua_getfield(L, -1, libname); |
33 | 397k | if (!tvistab(L->top-1)) { |
34 | 397k | L->top--; |
35 | 397k | if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL) |
36 | 0 | lj_err_callerv(L, LJ_ERR_BADMODN, libname); |
37 | 397k | settabV(L, L->top, tabV(L->top-1)); |
38 | 0 | L->top++; |
39 | 397k | lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ |
40 | 397k | } |
41 | 397k | L->top--; |
42 | 397k | settabV(L, L->top-1, tabV(L->top)); |
43 | 397k | } else { |
44 | 79.8k | lua_createtable(L, 0, hsize); |
45 | 79.8k | } |
46 | 477k | return tabV(L->top-1); |
47 | 477k | } |
48 | | |
49 | | static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) |
50 | 227k | { |
51 | 227k | int len = *p++; |
52 | 227k | GCstr *name = lj_str_new(L, (const char *)p, len); |
53 | 227k | LexState ls; |
54 | 227k | GCproto *pt; |
55 | 227k | GCfunc *fn; |
56 | 227k | memset(&ls, 0, sizeof(ls)); |
57 | 227k | ls.L = L; |
58 | 227k | ls.p = (const char *)(p+len); |
59 | 227k | ls.pe = (const char *)~(uintptr_t)0; |
60 | 227k | ls.c = -1; |
61 | 227k | ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); |
62 | 227k | ls.chunkname = name; |
63 | 227k | pt = lj_bcread_proto(&ls); |
64 | 227k | pt->firstline = ~(BCLine)0; |
65 | 227k | fn = lj_func_newL_empty(L, pt, tabref(L->env)); |
66 | | /* NOBARRIER: See below for common barrier. */ |
67 | 227k | setfuncV(L, lj_tab_setstr(L, tab, name), fn); |
68 | 227k | return (const uint8_t *)ls.p; |
69 | 227k | } |
70 | | |
71 | | void lj_lib_register(lua_State *L, const char *libname, |
72 | | const uint8_t *p, const lua_CFunction *cf) |
73 | 477k | { |
74 | 477k | GCtab *env = tabref(L->env); |
75 | 477k | GCfunc *ofn = NULL; |
76 | 477k | int ffid = *p++; |
77 | 477k | BCIns *bcff = &L2GG(L)->bcff[*p++]; |
78 | 477k | GCtab *tab = lib_create_table(L, libname, *p++); |
79 | 477k | ptrdiff_t tpos = L->top - L->base; |
80 | | |
81 | | /* Avoid barriers further down. */ |
82 | 477k | lj_gc_anybarriert(L, tab); |
83 | 477k | tab->nomm = 0; |
84 | | |
85 | 7.17M | for (;;) { |
86 | 7.17M | uint32_t tag = *p++; |
87 | 7.17M | MSize len = tag & LIBINIT_LENMASK; |
88 | 7.17M | tag &= LIBINIT_TAGMASK; |
89 | 7.17M | if (tag != LIBINIT_STRING) { |
90 | 4.74M | const char *name; |
91 | 4.74M | MSize nuv = (MSize)(L->top - L->base - tpos); |
92 | 4.74M | GCfunc *fn = lj_func_newC(L, nuv, env); |
93 | 4.74M | if (nuv) { |
94 | 198k | L->top = L->base + tpos; |
95 | 198k | memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv); |
96 | 198k | } |
97 | 4.74M | fn->c.ffid = (uint8_t)(ffid++); |
98 | 4.74M | name = (const char *)p; |
99 | 4.74M | p += len; |
100 | 4.74M | if (tag == LIBINIT_CF) |
101 | 3.15M | setmref(fn->c.pc, &G(L)->bc_cfunc_int); |
102 | 1.59M | else |
103 | 1.59M | setmref(fn->c.pc, bcff++); |
104 | 4.74M | if (tag == LIBINIT_ASM_) |
105 | 823k | fn->c.f = ofn->c.f; /* Copy handler from previous function. */ |
106 | 3.92M | else |
107 | 3.92M | fn->c.f = *cf++; /* Get cf or handler from C function table. */ |
108 | 4.74M | if (len) { |
109 | | /* NOBARRIER: See above for common barrier. */ |
110 | 4.71M | setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn); |
111 | 4.71M | } |
112 | 4.74M | ofn = fn; |
113 | 4.74M | } else { |
114 | 2.42M | switch (tag | len) { |
115 | 227k | case LIBINIT_LUA: |
116 | 227k | p = lib_read_lfunc(L, p, tab); |
117 | 227k | break; |
118 | 345k | case LIBINIT_SET: |
119 | 345k | L->top -= 2; |
120 | 691k | if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) |
121 | 54.1k | env = tabV(L->top); |
122 | 291k | else /* NOBARRIER: See above for common barrier. */ |
123 | 291k | copyTV(L, lj_tab_set(L, tab, L->top+1), L->top); |
124 | 345k | break; |
125 | 345k | case LIBINIT_NUMBER: |
126 | 56.8k | memcpy(&L->top->n, p, sizeof(double)); |
127 | 56.8k | L->top++; |
128 | 56.8k | p += sizeof(double); |
129 | 56.8k | break; |
130 | 418k | case LIBINIT_COPY: |
131 | 418k | copyTV(L, L->top, L->top - *p++); |
132 | 418k | L->top++; |
133 | 418k | break; |
134 | 56.8k | case LIBINIT_LASTCL: |
135 | 56.8k | setfuncV(L, L->top++, ofn); |
136 | 56.8k | break; |
137 | 113k | case LIBINIT_FFID: |
138 | 113k | ffid++; |
139 | 113k | break; |
140 | 477k | case LIBINIT_END: |
141 | 477k | return; |
142 | 727k | default: |
143 | 727k | setstrV(L, L->top++, lj_str_new(L, (const char *)p, len)); |
144 | 727k | p += len; |
145 | 727k | break; |
146 | 2.42M | } |
147 | 2.42M | } |
148 | 7.17M | } |
149 | 477k | } |
150 | | |
151 | | /* Push internal function on the stack. */ |
152 | | GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n) |
153 | 142k | { |
154 | 142k | GCfunc *fn; |
155 | 142k | lua_pushcclosure(L, f, n); |
156 | 142k | fn = funcV(L->top-1); |
157 | 0 | fn->c.ffid = (uint8_t)id; |
158 | 142k | setmref(fn->c.pc, &G(L)->bc_cfunc_int); |
159 | 142k | return fn; |
160 | 142k | } |
161 | | |
162 | | void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, GCtab *env) |
163 | 113k | { |
164 | 113k | luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4); |
165 | 113k | lua_pushcfunction(L, f); |
166 | | /* NOBARRIER: The function is new (marked white). */ |
167 | 113k | setgcref(funcV(L->top-1)->c.env, obj2gco(env)); |
168 | 0 | lua_setfield(L, -2, name); |
169 | 113k | L->top--; |
170 | 113k | } |
171 | | |
172 | | int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, const char *name) |
173 | 0 | { |
174 | 0 | GCfunc *fn = lj_lib_pushcf(L, cf, id); |
175 | 0 | GCtab *t = tabref(curr_func(L)->c.env); /* Reference to parent table. */ |
176 | 0 | setfuncV(L, lj_tab_setstr(L, t, lj_str_newz(L, name)), fn); |
177 | 0 | lj_gc_anybarriert(L, t); |
178 | 0 | setfuncV(L, L->top++, fn); |
179 | 0 | return 1; |
180 | 0 | } |
181 | | |
182 | | /* -- Type checks --------------------------------------------------------- */ |
183 | | |
184 | | TValue *lj_lib_checkany(lua_State *L, int narg) |
185 | 3.72M | { |
186 | 3.72M | TValue *o = L->base + narg-1; |
187 | 3.72M | if (o >= L->top) |
188 | 5.27k | lj_err_arg(L, narg, LJ_ERR_NOVAL); |
189 | 3.71M | return o; |
190 | 3.72M | } |
191 | | |
192 | | GCstr *lj_lib_checkstr(lua_State *L, int narg) |
193 | 6.37M | { |
194 | 6.37M | TValue *o = L->base + narg-1; |
195 | 6.37M | if (o < L->top) { |
196 | 6.35M | if (LJ_LIKELY(tvisstr(o))) { |
197 | 6.19M | return strV(o); |
198 | 6.19M | } else if (tvisnumber(o)) { |
199 | 155k | GCstr *s = lj_strfmt_number(L, o); |
200 | 155k | setstrV(L, o, s); |
201 | 155k | return s; |
202 | 155k | } |
203 | 6.35M | } |
204 | 23.8k | lj_err_argt(L, narg, LUA_TSTRING); |
205 | 0 | return NULL; /* unreachable */ |
206 | 6.37M | } |
207 | | |
208 | | GCstr *lj_lib_optstr(lua_State *L, int narg) |
209 | 12.3M | { |
210 | 12.3M | TValue *o = L->base + narg-1; |
211 | 12.3M | return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL; |
212 | 12.3M | } |
213 | | |
214 | | #if LJ_DUALNUM |
215 | | void lj_lib_checknumber(lua_State *L, int narg) |
216 | | { |
217 | | TValue *o = L->base + narg-1; |
218 | | if (!(o < L->top && lj_strscan_numberobj(o))) |
219 | | lj_err_argt(L, narg, LUA_TNUMBER); |
220 | | } |
221 | | #endif |
222 | | |
223 | | lua_Number lj_lib_checknum(lua_State *L, int narg) |
224 | 851k | { |
225 | 851k | TValue *o = L->base + narg-1; |
226 | 851k | if (!(o < L->top && |
227 | 851k | (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o))))) |
228 | 107 | lj_err_argt(L, narg, LUA_TNUMBER); |
229 | 851k | if (LJ_UNLIKELY(tvisint(o))) { |
230 | 0 | lua_Number n = (lua_Number)intV(o); |
231 | 0 | setnumV(o, n); |
232 | 0 | return n; |
233 | 851k | } else { |
234 | 851k | return numV(o); |
235 | 851k | } |
236 | 851k | } |
237 | | |
238 | | int32_t lj_lib_checkint(lua_State *L, int narg) |
239 | 2.40M | { |
240 | 2.40M | TValue *o = L->base + narg-1; |
241 | 2.40M | if (!(o < L->top && lj_strscan_numberobj(o))) |
242 | 2.73k | lj_err_argt(L, narg, LUA_TNUMBER); |
243 | 2.39M | if (LJ_LIKELY(tvisint(o))) { |
244 | 0 | return intV(o); |
245 | 2.39M | } else { |
246 | 2.39M | int32_t i = lj_num2int(numV(o)); |
247 | 2.39M | if (LJ_DUALNUM) setintV(o, i); |
248 | 2.39M | return i; |
249 | 2.39M | } |
250 | 2.39M | } |
251 | | |
252 | | int32_t lj_lib_optint(lua_State *L, int narg, int32_t def) |
253 | 2.71M | { |
254 | 2.71M | TValue *o = L->base + narg-1; |
255 | 2.71M | return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def; |
256 | 2.71M | } |
257 | | |
258 | | GCfunc *lj_lib_checkfunc(lua_State *L, int narg) |
259 | 502k | { |
260 | 502k | TValue *o = L->base + narg-1; |
261 | 502k | if (!(o < L->top && tvisfunc(o))) |
262 | 48.1k | lj_err_argt(L, narg, LUA_TFUNCTION); |
263 | 454k | return funcV(o); |
264 | 454k | } |
265 | | |
266 | | GCtab *lj_lib_checktab(lua_State *L, int narg) |
267 | 2.22M | { |
268 | 2.22M | TValue *o = L->base + narg-1; |
269 | 2.22M | if (!(o < L->top && tvistab(o))) |
270 | 917 | lj_err_argt(L, narg, LUA_TTABLE); |
271 | 2.22M | return tabV(o); |
272 | 2.22M | } |
273 | | |
274 | | GCtab *lj_lib_checktabornil(lua_State *L, int narg) |
275 | 78.2k | { |
276 | 78.2k | TValue *o = L->base + narg-1; |
277 | 78.2k | if (o < L->top) { |
278 | 78.1k | if (tvistab(o)) |
279 | 78.1k | return tabV(o); |
280 | 4.98k | else if (tvisnil(o)) |
281 | 4.89k | return NULL; |
282 | 78.1k | } |
283 | 162 | lj_err_arg(L, narg, LJ_ERR_NOTABN); |
284 | 0 | return NULL; /* unreachable */ |
285 | 78.2k | } |
286 | | |
287 | | int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst) |
288 | 95.5k | { |
289 | 95.5k | GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg); |
290 | 95.5k | if (s) { |
291 | 27.4k | const char *opt = strdata(s); |
292 | 27.4k | MSize len = s->len; |
293 | 27.4k | int i; |
294 | 156k | for (i = 0; *(const uint8_t *)lst; i++) { |
295 | 155k | if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0) |
296 | 26.4k | return i; |
297 | 128k | lst += 1+*(const uint8_t *)lst; |
298 | 128k | } |
299 | 1.06k | lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt); |
300 | 27.4k | } |
301 | 68.0k | return def; |
302 | 95.5k | } |
303 | | |