1 /*
2 ** Public Lua/C API.
3 ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4 **
5 ** Major 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_api_c
10 #define LUA_CORE
11
12 #include "lj_obj.h"
13 #include "lj_gc.h"
14 #include "lj_err.h"
15 #include "lj_debug.h"
16 #include "lj_str.h"
17 #include "lj_tab.h"
18 #include "lj_func.h"
19 #include "lj_udata.h"
20 #include "lj_meta.h"
21 #include "lj_state.h"
22 #include "lj_bc.h"
23 #include "lj_frame.h"
24 #include "lj_trace.h"
25 #include "lj_vm.h"
26 #include "lj_strscan.h"
27 #include "lj_strfmt.h"
28
29 /* -- Common helper functions --------------------------------------------- */
30
31 #define lj_checkapi_slot(idx) \
32 lj_checkapi((idx) <= (L->top - L->base), "stack slot %d out of range", (idx))
33
index2adr(lua_State * L,int idx)34 static TValue *index2adr(lua_State *L, int idx)
35 {
36 if (idx > 0) {
37 TValue *o = L->base + (idx - 1);
38 return o < L->top ? o : niltv(L);
39 } else if (idx > LUA_REGISTRYINDEX) {
40 lj_checkapi(idx != 0 && -idx <= L->top - L->base,
41 "bad stack slot %d", idx);
42 return L->top + idx;
43 } else if (idx == LUA_GLOBALSINDEX) {
44 TValue *o = &G(L)->tmptv;
45 settabV(L, o, tabref(L->env));
46 return o;
47 } else if (idx == LUA_REGISTRYINDEX) {
48 return registry(L);
49 } else {
50 GCfunc *fn = curr_func(L);
51 lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
52 "calling frame is not a C function");
53 if (idx == LUA_ENVIRONINDEX) {
54 TValue *o = &G(L)->tmptv;
55 settabV(L, o, tabref(fn->c.env));
56 return o;
57 } else {
58 idx = LUA_GLOBALSINDEX - idx;
59 return idx <= fn->c.nupvalues ? &fn->c.upvalue[idx-1] : niltv(L);
60 }
61 }
62 }
63
index2adr_check(lua_State * L,int idx)64 static LJ_AINLINE TValue *index2adr_check(lua_State *L, int idx)
65 {
66 TValue *o = index2adr(L, idx);
67 lj_checkapi(o != niltv(L), "invalid stack slot %d", idx);
68 return o;
69 }
70
index2adr_stack(lua_State * L,int idx)71 static TValue *index2adr_stack(lua_State *L, int idx)
72 {
73 if (idx > 0) {
74 TValue *o = L->base + (idx - 1);
75 if (o < L->top) {
76 return o;
77 } else {
78 lj_checkapi(0, "invalid stack slot %d", idx);
79 return niltv(L);
80 }
81 return o < L->top ? o : niltv(L);
82 } else {
83 lj_checkapi(idx != 0 && -idx <= L->top - L->base,
84 "invalid stack slot %d", idx);
85 return L->top + idx;
86 }
87 }
88
getcurrenv(lua_State * L)89 static GCtab *getcurrenv(lua_State *L)
90 {
91 GCfunc *fn = curr_func(L);
92 return fn->c.gct == ~LJ_TFUNC ? tabref(fn->c.env) : tabref(L->env);
93 }
94
95 /* -- Miscellaneous API functions ----------------------------------------- */
96
lua_status(lua_State * L)97 LUA_API int lua_status(lua_State *L)
98 {
99 return L->status;
100 }
101
lua_checkstack(lua_State * L,int size)102 LUA_API int lua_checkstack(lua_State *L, int size)
103 {
104 if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) {
105 return 0; /* Stack overflow. */
106 } else if (size > 0) {
107 lj_state_checkstack(L, (MSize)size);
108 }
109 return 1;
110 }
111
luaL_checkstack(lua_State * L,int size,const char * msg)112 LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
113 {
114 if (!lua_checkstack(L, size))
115 lj_err_callerv(L, LJ_ERR_STKOVM, msg);
116 }
117
lua_xmove(lua_State * L,lua_State * to,int n)118 LUA_API void lua_xmove(lua_State *L, lua_State *to, int n)
119 {
120 TValue *f, *t;
121 if (L == to) return;
122 lj_checkapi_slot(n);
123 lj_checkapi(G(L) == G(to), "move across global states");
124 lj_state_checkstack(to, (MSize)n);
125 f = L->top;
126 t = to->top = to->top + n;
127 while (--n >= 0) copyTV(to, --t, --f);
128 L->top = f;
129 }
130
lua_version(lua_State * L)131 LUA_API const lua_Number *lua_version(lua_State *L)
132 {
133 static const lua_Number version = LUA_VERSION_NUM;
134 UNUSED(L);
135 return &version;
136 }
137
138 /* -- Stack manipulation -------------------------------------------------- */
139
lua_gettop(lua_State * L)140 LUA_API int lua_gettop(lua_State *L)
141 {
142 return (int)(L->top - L->base);
143 }
144
lua_settop(lua_State * L,int idx)145 LUA_API void lua_settop(lua_State *L, int idx)
146 {
147 if (idx >= 0) {
148 lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx);
149 if (L->base + idx > L->top) {
150 if (L->base + idx >= tvref(L->maxstack))
151 lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
152 do { setnilV(L->top++); } while (L->top < L->base + idx);
153 } else {
154 L->top = L->base + idx;
155 }
156 } else {
157 lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx);
158 L->top += idx+1; /* Shrinks top (idx < 0). */
159 }
160 }
161
lua_remove(lua_State * L,int idx)162 LUA_API void lua_remove(lua_State *L, int idx)
163 {
164 TValue *p = index2adr_stack(L, idx);
165 while (++p < L->top) copyTV(L, p-1, p);
166 L->top--;
167 }
168
lua_insert(lua_State * L,int idx)169 LUA_API void lua_insert(lua_State *L, int idx)
170 {
171 TValue *q, *p = index2adr_stack(L, idx);
172 for (q = L->top; q > p; q--) copyTV(L, q, q-1);
173 copyTV(L, p, L->top);
174 }
175
copy_slot(lua_State * L,TValue * f,int idx)176 static void copy_slot(lua_State *L, TValue *f, int idx)
177 {
178 if (idx == LUA_GLOBALSINDEX) {
179 lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
180 /* NOBARRIER: A thread (i.e. L) is never black. */
181 setgcref(L->env, obj2gco(tabV(f)));
182 } else if (idx == LUA_ENVIRONINDEX) {
183 GCfunc *fn = curr_func(L);
184 if (fn->c.gct != ~LJ_TFUNC)
185 lj_err_msg(L, LJ_ERR_NOENV);
186 lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
187 setgcref(fn->c.env, obj2gco(tabV(f)));
188 lj_gc_barrier(L, fn, f);
189 } else {
190 TValue *o = index2adr_check(L, idx);
191 copyTV(L, o, f);
192 if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
193 lj_gc_barrier(L, curr_func(L), f);
194 }
195 }
196
lua_replace(lua_State * L,int idx)197 LUA_API void lua_replace(lua_State *L, int idx)
198 {
199 lj_checkapi_slot(1);
200 copy_slot(L, L->top - 1, idx);
201 L->top--;
202 }
203
lua_copy(lua_State * L,int fromidx,int toidx)204 LUA_API void lua_copy(lua_State *L, int fromidx, int toidx)
205 {
206 copy_slot(L, index2adr(L, fromidx), toidx);
207 }
208
lua_pushvalue(lua_State * L,int idx)209 LUA_API void lua_pushvalue(lua_State *L, int idx)
210 {
211 copyTV(L, L->top, index2adr(L, idx));
212 incr_top(L);
213 }
214
215 /* -- Stack getters ------------------------------------------------------- */
216
lua_type(lua_State * L,int idx)217 LUA_API int lua_type(lua_State *L, int idx)
218 {
219 cTValue *o = index2adr(L, idx);
220 if (tvisnumber(o)) {
221 return LUA_TNUMBER;
222 #if LJ_64 && !LJ_GC64
223 } else if (tvislightud(o)) {
224 return LUA_TLIGHTUSERDATA;
225 #endif
226 } else if (o == niltv(L)) {
227 return LUA_TNONE;
228 } else { /* Magic internal/external tag conversion. ORDER LJ_T */
229 uint32_t t = ~itype(o);
230 #if LJ_64
231 int tt = (int)((U64x(75a06,98042110) >> 4*t) & 15u);
232 #else
233 int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
234 #endif
235 lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion");
236 return tt;
237 }
238 }
239
luaL_checktype(lua_State * L,int idx,int tt)240 LUALIB_API void luaL_checktype(lua_State *L, int idx, int tt)
241 {
242 if (lua_type(L, idx) != tt)
243 lj_err_argt(L, idx, tt);
244 }
245
luaL_checkany(lua_State * L,int idx)246 LUALIB_API void luaL_checkany(lua_State *L, int idx)
247 {
248 if (index2adr(L, idx) == niltv(L))
249 lj_err_arg(L, idx, LJ_ERR_NOVAL);
250 }
251
lua_typename(lua_State * L,int t)252 LUA_API const char *lua_typename(lua_State *L, int t)
253 {
254 UNUSED(L);
255 return lj_obj_typename[t+1];
256 }
257
lua_iscfunction(lua_State * L,int idx)258 LUA_API int lua_iscfunction(lua_State *L, int idx)
259 {
260 cTValue *o = index2adr(L, idx);
261 return tvisfunc(o) && !isluafunc(funcV(o));
262 }
263
lua_isnumber(lua_State * L,int idx)264 LUA_API int lua_isnumber(lua_State *L, int idx)
265 {
266 cTValue *o = index2adr(L, idx);
267 TValue tmp;
268 return (tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), &tmp)));
269 }
270
lua_isstring(lua_State * L,int idx)271 LUA_API int lua_isstring(lua_State *L, int idx)
272 {
273 cTValue *o = index2adr(L, idx);
274 return (tvisstr(o) || tvisnumber(o));
275 }
276
lua_isuserdata(lua_State * L,int idx)277 LUA_API int lua_isuserdata(lua_State *L, int idx)
278 {
279 cTValue *o = index2adr(L, idx);
280 return (tvisudata(o) || tvislightud(o));
281 }
282
lua_rawequal(lua_State * L,int idx1,int idx2)283 LUA_API int lua_rawequal(lua_State *L, int idx1, int idx2)
284 {
285 cTValue *o1 = index2adr(L, idx1);
286 cTValue *o2 = index2adr(L, idx2);
287 return (o1 == niltv(L) || o2 == niltv(L)) ? 0 : lj_obj_equal(o1, o2);
288 }
289
lua_equal(lua_State * L,int idx1,int idx2)290 LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
291 {
292 cTValue *o1 = index2adr(L, idx1);
293 cTValue *o2 = index2adr(L, idx2);
294 if (tvisint(o1) && tvisint(o2)) {
295 return intV(o1) == intV(o2);
296 } else if (tvisnumber(o1) && tvisnumber(o2)) {
297 return numberVnum(o1) == numberVnum(o2);
298 } else if (itype(o1) != itype(o2)) {
299 return 0;
300 } else if (tvispri(o1)) {
301 return o1 != niltv(L) && o2 != niltv(L);
302 #if LJ_64 && !LJ_GC64
303 } else if (tvislightud(o1)) {
304 return o1->u64 == o2->u64;
305 #endif
306 } else if (gcrefeq(o1->gcr, o2->gcr)) {
307 return 1;
308 } else if (!tvistabud(o1)) {
309 return 0;
310 } else {
311 TValue *base = lj_meta_equal(L, gcV(o1), gcV(o2), 0);
312 if ((uintptr_t)base <= 1) {
313 return (int)(uintptr_t)base;
314 } else {
315 L->top = base+2;
316 lj_vm_call(L, base, 1+1);
317 L->top -= 2+LJ_FR2;
318 return tvistruecond(L->top+1+LJ_FR2);
319 }
320 }
321 }
322
lua_lessthan(lua_State * L,int idx1,int idx2)323 LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
324 {
325 cTValue *o1 = index2adr(L, idx1);
326 cTValue *o2 = index2adr(L, idx2);
327 if (o1 == niltv(L) || o2 == niltv(L)) {
328 return 0;
329 } else if (tvisint(o1) && tvisint(o2)) {
330 return intV(o1) < intV(o2);
331 } else if (tvisnumber(o1) && tvisnumber(o2)) {
332 return numberVnum(o1) < numberVnum(o2);
333 } else {
334 TValue *base = lj_meta_comp(L, o1, o2, 0);
335 if ((uintptr_t)base <= 1) {
336 return (int)(uintptr_t)base;
337 } else {
338 L->top = base+2;
339 lj_vm_call(L, base, 1+1);
340 L->top -= 2+LJ_FR2;
341 return tvistruecond(L->top+1+LJ_FR2);
342 }
343 }
344 }
345
lua_tonumber(lua_State * L,int idx)346 LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
347 {
348 cTValue *o = index2adr(L, idx);
349 TValue tmp;
350 if (LJ_LIKELY(tvisnumber(o)))
351 return numberVnum(o);
352 else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp))
353 return numV(&tmp);
354 else
355 return 0;
356 }
357
lua_tonumberx(lua_State * L,int idx,int * ok)358 LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok)
359 {
360 cTValue *o = index2adr(L, idx);
361 TValue tmp;
362 if (LJ_LIKELY(tvisnumber(o))) {
363 if (ok) *ok = 1;
364 return numberVnum(o);
365 } else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) {
366 if (ok) *ok = 1;
367 return numV(&tmp);
368 } else {
369 if (ok) *ok = 0;
370 return 0;
371 }
372 }
373
luaL_checknumber(lua_State * L,int idx)374 LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
375 {
376 cTValue *o = index2adr(L, idx);
377 TValue tmp;
378 if (LJ_LIKELY(tvisnumber(o)))
379 return numberVnum(o);
380 else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp)))
381 lj_err_argt(L, idx, LUA_TNUMBER);
382 return numV(&tmp);
383 }
384
luaL_optnumber(lua_State * L,int idx,lua_Number def)385 LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def)
386 {
387 cTValue *o = index2adr(L, idx);
388 TValue tmp;
389 if (LJ_LIKELY(tvisnumber(o)))
390 return numberVnum(o);
391 else if (tvisnil(o))
392 return def;
393 else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp)))
394 lj_err_argt(L, idx, LUA_TNUMBER);
395 return numV(&tmp);
396 }
397
lua_tointeger(lua_State * L,int idx)398 LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
399 {
400 cTValue *o = index2adr(L, idx);
401 TValue tmp;
402 lua_Number n;
403 if (LJ_LIKELY(tvisint(o))) {
404 return intV(o);
405 } else if (LJ_LIKELY(tvisnum(o))) {
406 n = numV(o);
407 } else {
408 if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
409 return 0;
410 if (tvisint(&tmp))
411 return intV(&tmp);
412 n = numV(&tmp);
413 }
414 #if LJ_64
415 return (lua_Integer)n;
416 #else
417 return lj_num2int(n);
418 #endif
419 }
420
lua_tointegerx(lua_State * L,int idx,int * ok)421 LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok)
422 {
423 cTValue *o = index2adr(L, idx);
424 TValue tmp;
425 lua_Number n;
426 if (LJ_LIKELY(tvisint(o))) {
427 if (ok) *ok = 1;
428 return intV(o);
429 } else if (LJ_LIKELY(tvisnum(o))) {
430 n = numV(o);
431 } else {
432 if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) {
433 if (ok) *ok = 0;
434 return 0;
435 }
436 if (tvisint(&tmp)) {
437 if (ok) *ok = 1;
438 return intV(&tmp);
439 }
440 n = numV(&tmp);
441 }
442 if (ok) *ok = 1;
443 #if LJ_64
444 return (lua_Integer)n;
445 #else
446 return lj_num2int(n);
447 #endif
448 }
449
luaL_checkinteger(lua_State * L,int idx)450 LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
451 {
452 cTValue *o = index2adr(L, idx);
453 TValue tmp;
454 lua_Number n;
455 if (LJ_LIKELY(tvisint(o))) {
456 return intV(o);
457 } else if (LJ_LIKELY(tvisnum(o))) {
458 n = numV(o);
459 } else {
460 if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
461 lj_err_argt(L, idx, LUA_TNUMBER);
462 if (tvisint(&tmp))
463 return (lua_Integer)intV(&tmp);
464 n = numV(&tmp);
465 }
466 #if LJ_64
467 return (lua_Integer)n;
468 #else
469 return lj_num2int(n);
470 #endif
471 }
472
luaL_optinteger(lua_State * L,int idx,lua_Integer def)473 LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def)
474 {
475 cTValue *o = index2adr(L, idx);
476 TValue tmp;
477 lua_Number n;
478 if (LJ_LIKELY(tvisint(o))) {
479 return intV(o);
480 } else if (LJ_LIKELY(tvisnum(o))) {
481 n = numV(o);
482 } else if (tvisnil(o)) {
483 return def;
484 } else {
485 if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
486 lj_err_argt(L, idx, LUA_TNUMBER);
487 if (tvisint(&tmp))
488 return (lua_Integer)intV(&tmp);
489 n = numV(&tmp);
490 }
491 #if LJ_64
492 return (lua_Integer)n;
493 #else
494 return lj_num2int(n);
495 #endif
496 }
497
lua_toboolean(lua_State * L,int idx)498 LUA_API int lua_toboolean(lua_State *L, int idx)
499 {
500 cTValue *o = index2adr(L, idx);
501 return tvistruecond(o);
502 }
503
lua_tolstring(lua_State * L,int idx,size_t * len)504 LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
505 {
506 TValue *o = index2adr(L, idx);
507 GCstr *s;
508 if (LJ_LIKELY(tvisstr(o))) {
509 s = strV(o);
510 } else if (tvisnumber(o)) {
511 lj_gc_check(L);
512 o = index2adr(L, idx); /* GC may move the stack. */
513 s = lj_strfmt_number(L, o);
514 setstrV(L, o, s);
515 } else {
516 if (len != NULL) *len = 0;
517 return NULL;
518 }
519 if (len != NULL) *len = s->len;
520 return strdata(s);
521 }
522
luaL_checklstring(lua_State * L,int idx,size_t * len)523 LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
524 {
525 TValue *o = index2adr(L, idx);
526 GCstr *s;
527 if (LJ_LIKELY(tvisstr(o))) {
528 s = strV(o);
529 } else if (tvisnumber(o)) {
530 lj_gc_check(L);
531 o = index2adr(L, idx); /* GC may move the stack. */
532 s = lj_strfmt_number(L, o);
533 setstrV(L, o, s);
534 } else {
535 lj_err_argt(L, idx, LUA_TSTRING);
536 }
537 if (len != NULL) *len = s->len;
538 return strdata(s);
539 }
540
luaL_optlstring(lua_State * L,int idx,const char * def,size_t * len)541 LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
542 const char *def, size_t *len)
543 {
544 TValue *o = index2adr(L, idx);
545 GCstr *s;
546 if (LJ_LIKELY(tvisstr(o))) {
547 s = strV(o);
548 } else if (tvisnil(o)) {
549 if (len != NULL) *len = def ? strlen(def) : 0;
550 return def;
551 } else if (tvisnumber(o)) {
552 lj_gc_check(L);
553 o = index2adr(L, idx); /* GC may move the stack. */
554 s = lj_strfmt_number(L, o);
555 setstrV(L, o, s);
556 } else {
557 lj_err_argt(L, idx, LUA_TSTRING);
558 }
559 if (len != NULL) *len = s->len;
560 return strdata(s);
561 }
562
luaL_checkoption(lua_State * L,int idx,const char * def,const char * const lst[])563 LUALIB_API int luaL_checkoption(lua_State *L, int idx, const char *def,
564 const char *const lst[])
565 {
566 ptrdiff_t i;
567 const char *s = lua_tolstring(L, idx, NULL);
568 if (s == NULL && (s = def) == NULL)
569 lj_err_argt(L, idx, LUA_TSTRING);
570 for (i = 0; lst[i]; i++)
571 if (strcmp(lst[i], s) == 0)
572 return (int)i;
573 lj_err_argv(L, idx, LJ_ERR_INVOPTM, s);
574 }
575
lua_objlen(lua_State * L,int idx)576 LUA_API size_t lua_objlen(lua_State *L, int idx)
577 {
578 TValue *o = index2adr(L, idx);
579 if (tvisstr(o)) {
580 return strV(o)->len;
581 } else if (tvistab(o)) {
582 return (size_t)lj_tab_len(tabV(o));
583 } else if (tvisudata(o)) {
584 return udataV(o)->len;
585 } else if (tvisnumber(o)) {
586 GCstr *s = lj_strfmt_number(L, o);
587 setstrV(L, o, s);
588 return s->len;
589 } else {
590 return 0;
591 }
592 }
593
lua_tocfunction(lua_State * L,int idx)594 LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
595 {
596 cTValue *o = index2adr(L, idx);
597 if (tvisfunc(o)) {
598 BCOp op = bc_op(*mref(funcV(o)->c.pc, BCIns));
599 if (op == BC_FUNCC || op == BC_FUNCCW)
600 return funcV(o)->c.f;
601 }
602 return NULL;
603 }
604
lua_touserdata(lua_State * L,int idx)605 LUA_API void *lua_touserdata(lua_State *L, int idx)
606 {
607 cTValue *o = index2adr(L, idx);
608 if (tvisudata(o))
609 return uddata(udataV(o));
610 else if (tvislightud(o))
611 return lightudV(G(L), o);
612 else
613 return NULL;
614 }
615
lua_tothread(lua_State * L,int idx)616 LUA_API lua_State *lua_tothread(lua_State *L, int idx)
617 {
618 cTValue *o = index2adr(L, idx);
619 return (!tvisthread(o)) ? NULL : threadV(o);
620 }
621
lua_topointer(lua_State * L,int idx)622 LUA_API const void *lua_topointer(lua_State *L, int idx)
623 {
624 return lj_obj_ptr(G(L), index2adr(L, idx));
625 }
626
627 /* -- Stack setters (object creation) ------------------------------------- */
628
lua_pushnil(lua_State * L)629 LUA_API void lua_pushnil(lua_State *L)
630 {
631 setnilV(L->top);
632 incr_top(L);
633 }
634
lua_pushnumber(lua_State * L,lua_Number n)635 LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
636 {
637 setnumV(L->top, n);
638 if (LJ_UNLIKELY(tvisnan(L->top)))
639 setnanV(L->top); /* Canonicalize injected NaNs. */
640 incr_top(L);
641 }
642
lua_pushinteger(lua_State * L,lua_Integer n)643 LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
644 {
645 setintptrV(L->top, n);
646 incr_top(L);
647 }
648
lua_pushlstring(lua_State * L,const char * str,size_t len)649 LUA_API void lua_pushlstring(lua_State *L, const char *str, size_t len)
650 {
651 GCstr *s;
652 lj_gc_check(L);
653 s = lj_str_new(L, str, len);
654 setstrV(L, L->top, s);
655 incr_top(L);
656 }
657
lua_pushstring(lua_State * L,const char * str)658 LUA_API void lua_pushstring(lua_State *L, const char *str)
659 {
660 if (str == NULL) {
661 setnilV(L->top);
662 } else {
663 GCstr *s;
664 lj_gc_check(L);
665 s = lj_str_newz(L, str);
666 setstrV(L, L->top, s);
667 }
668 incr_top(L);
669 }
670
lua_pushvfstring(lua_State * L,const char * fmt,va_list argp)671 LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt,
672 va_list argp)
673 {
674 lj_gc_check(L);
675 return lj_strfmt_pushvf(L, fmt, argp);
676 }
677
lua_pushfstring(lua_State * L,const char * fmt,...)678 LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...)
679 {
680 const char *ret;
681 va_list argp;
682 lj_gc_check(L);
683 va_start(argp, fmt);
684 ret = lj_strfmt_pushvf(L, fmt, argp);
685 va_end(argp);
686 return ret;
687 }
688
lua_pushcclosure(lua_State * L,lua_CFunction f,int n)689 LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
690 {
691 GCfunc *fn;
692 lj_gc_check(L);
693 lj_checkapi_slot(n);
694 fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
695 fn->c.f = f;
696 L->top -= n;
697 while (n--)
698 copyTV(L, &fn->c.upvalue[n], L->top+n);
699 setfuncV(L, L->top, fn);
700 lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white");
701 incr_top(L);
702 }
703
lua_pushboolean(lua_State * L,int b)704 LUA_API void lua_pushboolean(lua_State *L, int b)
705 {
706 setboolV(L->top, (b != 0));
707 incr_top(L);
708 }
709
lua_pushlightuserdata(lua_State * L,void * p)710 LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
711 {
712 #if LJ_64
713 p = lj_lightud_intern(L, p);
714 #endif
715 setrawlightudV(L->top, p);
716 incr_top(L);
717 }
718
lua_createtable(lua_State * L,int narray,int nrec)719 LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
720 {
721 lj_gc_check(L);
722 settabV(L, L->top, lj_tab_new_ah(L, narray, nrec));
723 incr_top(L);
724 }
725
luaL_newmetatable(lua_State * L,const char * tname)726 LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
727 {
728 GCtab *regt = tabV(registry(L));
729 TValue *tv = lj_tab_setstr(L, regt, lj_str_newz(L, tname));
730 if (tvisnil(tv)) {
731 GCtab *mt = lj_tab_new(L, 0, 1);
732 settabV(L, tv, mt);
733 settabV(L, L->top++, mt);
734 lj_gc_anybarriert(L, regt);
735 return 1;
736 } else {
737 copyTV(L, L->top++, tv);
738 return 0;
739 }
740 }
741
lua_pushthread(lua_State * L)742 LUA_API int lua_pushthread(lua_State *L)
743 {
744 setthreadV(L, L->top, L);
745 incr_top(L);
746 return (mainthread(G(L)) == L);
747 }
748
lua_newthread(lua_State * L)749 LUA_API lua_State *lua_newthread(lua_State *L)
750 {
751 lua_State *L1;
752 lj_gc_check(L);
753 L1 = lj_state_new(L);
754 setthreadV(L, L->top, L1);
755 incr_top(L);
756 return L1;
757 }
758
lua_newuserdata(lua_State * L,size_t size)759 LUA_API void *lua_newuserdata(lua_State *L, size_t size)
760 {
761 GCudata *ud;
762 lj_gc_check(L);
763 if (size > LJ_MAX_UDATA)
764 lj_err_msg(L, LJ_ERR_UDATAOV);
765 ud = lj_udata_new(L, (MSize)size, getcurrenv(L));
766 setudataV(L, L->top, ud);
767 incr_top(L);
768 return uddata(ud);
769 }
770
lua_concat(lua_State * L,int n)771 LUA_API void lua_concat(lua_State *L, int n)
772 {
773 lj_checkapi_slot(n);
774 if (n >= 2) {
775 n--;
776 do {
777 TValue *top = lj_meta_cat(L, L->top-1, -n);
778 if (top == NULL) {
779 L->top -= n;
780 break;
781 }
782 n -= (int)(L->top - top);
783 L->top = top+2;
784 lj_vm_call(L, top, 1+1);
785 L->top -= 1+LJ_FR2;
786 copyTV(L, L->top-1, L->top+LJ_FR2);
787 } while (--n > 0);
788 } else if (n == 0) { /* Push empty string. */
789 setstrV(L, L->top, &G(L)->strempty);
790 incr_top(L);
791 }
792 /* else n == 1: nothing to do. */
793 }
794
795 /* -- Object getters ------------------------------------------------------ */
796
lua_gettable(lua_State * L,int idx)797 LUA_API void lua_gettable(lua_State *L, int idx)
798 {
799 cTValue *t = index2adr_check(L, idx);
800 cTValue *v = lj_meta_tget(L, t, L->top-1);
801 if (v == NULL) {
802 L->top += 2;
803 lj_vm_call(L, L->top-2, 1+1);
804 L->top -= 2+LJ_FR2;
805 v = L->top+1+LJ_FR2;
806 }
807 copyTV(L, L->top-1, v);
808 }
809
lua_getfield(lua_State * L,int idx,const char * k)810 LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
811 {
812 cTValue *v, *t = index2adr_check(L, idx);
813 TValue key;
814 setstrV(L, &key, lj_str_newz(L, k));
815 v = lj_meta_tget(L, t, &key);
816 if (v == NULL) {
817 L->top += 2;
818 lj_vm_call(L, L->top-2, 1+1);
819 L->top -= 2+LJ_FR2;
820 v = L->top+1+LJ_FR2;
821 }
822 copyTV(L, L->top, v);
823 incr_top(L);
824 }
825
lua_rawget(lua_State * L,int idx)826 LUA_API void lua_rawget(lua_State *L, int idx)
827 {
828 cTValue *t = index2adr(L, idx);
829 lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
830 copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1));
831 }
832
lua_rawgeti(lua_State * L,int idx,int n)833 LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
834 {
835 cTValue *v, *t = index2adr(L, idx);
836 lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
837 v = lj_tab_getint(tabV(t), n);
838 if (v) {
839 copyTV(L, L->top, v);
840 } else {
841 setnilV(L->top);
842 }
843 incr_top(L);
844 }
845
lua_getmetatable(lua_State * L,int idx)846 LUA_API int lua_getmetatable(lua_State *L, int idx)
847 {
848 cTValue *o = index2adr(L, idx);
849 GCtab *mt = NULL;
850 if (tvistab(o))
851 mt = tabref(tabV(o)->metatable);
852 else if (tvisudata(o))
853 mt = tabref(udataV(o)->metatable);
854 else
855 mt = tabref(basemt_obj(G(L), o));
856 if (mt == NULL)
857 return 0;
858 settabV(L, L->top, mt);
859 incr_top(L);
860 return 1;
861 }
862
luaL_getmetafield(lua_State * L,int idx,const char * field)863 LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field)
864 {
865 if (lua_getmetatable(L, idx)) {
866 cTValue *tv = lj_tab_getstr(tabV(L->top-1), lj_str_newz(L, field));
867 if (tv && !tvisnil(tv)) {
868 copyTV(L, L->top-1, tv);
869 return 1;
870 }
871 L->top--;
872 }
873 return 0;
874 }
875
lua_getfenv(lua_State * L,int idx)876 LUA_API void lua_getfenv(lua_State *L, int idx)
877 {
878 cTValue *o = index2adr_check(L, idx);
879 if (tvisfunc(o)) {
880 settabV(L, L->top, tabref(funcV(o)->c.env));
881 } else if (tvisudata(o)) {
882 settabV(L, L->top, tabref(udataV(o)->env));
883 } else if (tvisthread(o)) {
884 settabV(L, L->top, tabref(threadV(o)->env));
885 } else {
886 setnilV(L->top);
887 }
888 incr_top(L);
889 }
890
lua_next(lua_State * L,int idx)891 LUA_API int lua_next(lua_State *L, int idx)
892 {
893 cTValue *t = index2adr(L, idx);
894 int more;
895 lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
896 more = lj_tab_next(tabV(t), L->top-1, L->top-1);
897 if (more > 0) {
898 incr_top(L); /* Return new key and value slot. */
899 } else if (!more) { /* End of traversal. */
900 L->top--; /* Remove key slot. */
901 } else {
902 lj_err_msg(L, LJ_ERR_NEXTIDX);
903 }
904 return more;
905 }
906
lua_getupvalue(lua_State * L,int idx,int n)907 LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
908 {
909 TValue *val;
910 GCobj *o;
911 const char *name = lj_debug_uvnamev(index2adr(L, idx), (uint32_t)(n-1), &val, &o);
912 if (name) {
913 copyTV(L, L->top, val);
914 incr_top(L);
915 }
916 return name;
917 }
918
lua_upvalueid(lua_State * L,int idx,int n)919 LUA_API void *lua_upvalueid(lua_State *L, int idx, int n)
920 {
921 GCfunc *fn = funcV(index2adr(L, idx));
922 n--;
923 lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n);
924 return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
925 (void *)&fn->c.upvalue[n];
926 }
927
lua_upvaluejoin(lua_State * L,int idx1,int n1,int idx2,int n2)928 LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
929 {
930 GCfunc *fn1 = funcV(index2adr(L, idx1));
931 GCfunc *fn2 = funcV(index2adr(L, idx2));
932 n1--; n2--;
933 lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1);
934 lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2);
935 lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1);
936 lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1);
937 setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]);
938 lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
939 }
940
luaL_testudata(lua_State * L,int idx,const char * tname)941 LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname)
942 {
943 cTValue *o = index2adr(L, idx);
944 if (tvisudata(o)) {
945 GCudata *ud = udataV(o);
946 cTValue *tv = lj_tab_getstr(tabV(registry(L)), lj_str_newz(L, tname));
947 if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
948 return uddata(ud);
949 }
950 return NULL; /* value is not a userdata with a metatable */
951 }
952
luaL_checkudata(lua_State * L,int idx,const char * tname)953 LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
954 {
955 void *p = luaL_testudata(L, idx, tname);
956 if (!p) lj_err_argtype(L, idx, tname);
957 return p;
958 }
959
960 /* -- Object setters ------------------------------------------------------ */
961
lua_settable(lua_State * L,int idx)962 LUA_API void lua_settable(lua_State *L, int idx)
963 {
964 TValue *o;
965 cTValue *t = index2adr_check(L, idx);
966 lj_checkapi_slot(2);
967 o = lj_meta_tset(L, t, L->top-2);
968 if (o) {
969 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
970 L->top -= 2;
971 copyTV(L, o, L->top+1);
972 } else {
973 TValue *base = L->top;
974 copyTV(L, base+2, base-3-2*LJ_FR2);
975 L->top = base+3;
976 lj_vm_call(L, base, 0+1);
977 L->top -= 3+LJ_FR2;
978 }
979 }
980
lua_setfield(lua_State * L,int idx,const char * k)981 LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
982 {
983 TValue *o;
984 TValue key;
985 cTValue *t = index2adr_check(L, idx);
986 lj_checkapi_slot(1);
987 setstrV(L, &key, lj_str_newz(L, k));
988 o = lj_meta_tset(L, t, &key);
989 if (o) {
990 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
991 copyTV(L, o, --L->top);
992 } else {
993 TValue *base = L->top;
994 copyTV(L, base+2, base-3-2*LJ_FR2);
995 L->top = base+3;
996 lj_vm_call(L, base, 0+1);
997 L->top -= 2+LJ_FR2;
998 }
999 }
1000
lua_rawset(lua_State * L,int idx)1001 LUA_API void lua_rawset(lua_State *L, int idx)
1002 {
1003 GCtab *t = tabV(index2adr(L, idx));
1004 TValue *dst, *key;
1005 lj_checkapi_slot(2);
1006 key = L->top-2;
1007 dst = lj_tab_set(L, t, key);
1008 copyTV(L, dst, key+1);
1009 lj_gc_anybarriert(L, t);
1010 L->top = key;
1011 }
1012
lua_rawseti(lua_State * L,int idx,int n)1013 LUA_API void lua_rawseti(lua_State *L, int idx, int n)
1014 {
1015 GCtab *t = tabV(index2adr(L, idx));
1016 TValue *dst, *src;
1017 lj_checkapi_slot(1);
1018 dst = lj_tab_setint(L, t, n);
1019 src = L->top-1;
1020 copyTV(L, dst, src);
1021 lj_gc_barriert(L, t, dst);
1022 L->top = src;
1023 }
1024
lua_setmetatable(lua_State * L,int idx)1025 LUA_API int lua_setmetatable(lua_State *L, int idx)
1026 {
1027 global_State *g;
1028 GCtab *mt;
1029 cTValue *o = index2adr_check(L, idx);
1030 lj_checkapi_slot(1);
1031 if (tvisnil(L->top-1)) {
1032 mt = NULL;
1033 } else {
1034 lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
1035 mt = tabV(L->top-1);
1036 }
1037 g = G(L);
1038 if (tvistab(o)) {
1039 setgcref(tabV(o)->metatable, obj2gco(mt));
1040 if (mt)
1041 lj_gc_objbarriert(L, tabV(o), mt);
1042 } else if (tvisudata(o)) {
1043 setgcref(udataV(o)->metatable, obj2gco(mt));
1044 if (mt)
1045 lj_gc_objbarrier(L, udataV(o), mt);
1046 } else {
1047 /* Flush cache, since traces specialize to basemt. But not during __gc. */
1048 if (lj_trace_flushall(L))
1049 lj_err_caller(L, LJ_ERR_NOGCMM);
1050 if (tvisbool(o)) {
1051 /* NOBARRIER: basemt is a GC root. */
1052 setgcref(basemt_it(g, LJ_TTRUE), obj2gco(mt));
1053 setgcref(basemt_it(g, LJ_TFALSE), obj2gco(mt));
1054 } else {
1055 /* NOBARRIER: basemt is a GC root. */
1056 setgcref(basemt_obj(g, o), obj2gco(mt));
1057 }
1058 }
1059 L->top--;
1060 return 1;
1061 }
1062
luaL_setmetatable(lua_State * L,const char * tname)1063 LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
1064 {
1065 lua_getfield(L, LUA_REGISTRYINDEX, tname);
1066 lua_setmetatable(L, -2);
1067 }
1068
lua_setfenv(lua_State * L,int idx)1069 LUA_API int lua_setfenv(lua_State *L, int idx)
1070 {
1071 cTValue *o = index2adr_check(L, idx);
1072 GCtab *t;
1073 lj_checkapi_slot(1);
1074 lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
1075 t = tabV(L->top-1);
1076 if (tvisfunc(o)) {
1077 setgcref(funcV(o)->c.env, obj2gco(t));
1078 } else if (tvisudata(o)) {
1079 setgcref(udataV(o)->env, obj2gco(t));
1080 } else if (tvisthread(o)) {
1081 setgcref(threadV(o)->env, obj2gco(t));
1082 } else {
1083 L->top--;
1084 return 0;
1085 }
1086 lj_gc_objbarrier(L, gcV(o), t);
1087 L->top--;
1088 return 1;
1089 }
1090
lua_setupvalue(lua_State * L,int idx,int n)1091 LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
1092 {
1093 cTValue *f = index2adr(L, idx);
1094 TValue *val;
1095 GCobj *o;
1096 const char *name;
1097 lj_checkapi_slot(1);
1098 name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o);
1099 if (name) {
1100 L->top--;
1101 copyTV(L, val, L->top);
1102 lj_gc_barrier(L, o, L->top);
1103 }
1104 return name;
1105 }
1106
1107 /* -- Calls --------------------------------------------------------------- */
1108
1109 #if LJ_FR2
api_call_base(lua_State * L,int nargs)1110 static TValue *api_call_base(lua_State *L, int nargs)
1111 {
1112 TValue *o = L->top, *base = o - nargs;
1113 L->top = o+1;
1114 for (; o > base; o--) copyTV(L, o, o-1);
1115 setnilV(o);
1116 return o+1;
1117 }
1118 #else
1119 #define api_call_base(L, nargs) (L->top - (nargs))
1120 #endif
1121
lua_call(lua_State * L,int nargs,int nresults)1122 LUA_API void lua_call(lua_State *L, int nargs, int nresults)
1123 {
1124 lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
1125 "thread called in wrong state %d", L->status);
1126 lj_checkapi_slot(nargs+1);
1127 lj_vm_call(L, api_call_base(L, nargs), nresults+1);
1128 }
1129
lua_pcall(lua_State * L,int nargs,int nresults,int errfunc)1130 LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
1131 {
1132 global_State *g = G(L);
1133 uint8_t oldh = hook_save(g);
1134 ptrdiff_t ef;
1135 int status;
1136 lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
1137 "thread called in wrong state %d", L->status);
1138 lj_checkapi_slot(nargs+1);
1139 if (errfunc == 0) {
1140 ef = 0;
1141 } else {
1142 cTValue *o = index2adr_stack(L, errfunc);
1143 ef = savestack(L, o);
1144 }
1145 status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
1146 if (status) hook_restore(g, oldh);
1147 return status;
1148 }
1149
cpcall(lua_State * L,lua_CFunction func,void * ud)1150 static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
1151 {
1152 GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L));
1153 TValue *top = L->top;
1154 fn->c.f = func;
1155 setfuncV(L, top++, fn);
1156 if (LJ_FR2) setnilV(top++);
1157 #if LJ_64
1158 ud = lj_lightud_intern(L, ud);
1159 #endif
1160 setrawlightudV(top++, ud);
1161 cframe_nres(L->cframe) = 1+0; /* Zero results. */
1162 L->top = top;
1163 return top-1; /* Now call the newly allocated C function. */
1164 }
1165
lua_cpcall(lua_State * L,lua_CFunction func,void * ud)1166 LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
1167 {
1168 global_State *g = G(L);
1169 uint8_t oldh = hook_save(g);
1170 int status;
1171 lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
1172 "thread called in wrong state %d", L->status);
1173 status = lj_vm_cpcall(L, func, ud, cpcall);
1174 if (status) hook_restore(g, oldh);
1175 return status;
1176 }
1177
luaL_callmeta(lua_State * L,int idx,const char * field)1178 LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
1179 {
1180 if (luaL_getmetafield(L, idx, field)) {
1181 TValue *top = L->top--;
1182 if (LJ_FR2) setnilV(top++);
1183 copyTV(L, top++, index2adr(L, idx));
1184 L->top = top;
1185 lj_vm_call(L, top-1, 1+1);
1186 return 1;
1187 }
1188 return 0;
1189 }
1190
1191 /* -- Coroutine yield and resume ------------------------------------------ */
1192
lua_isyieldable(lua_State * L)1193 LUA_API int lua_isyieldable(lua_State *L)
1194 {
1195 return cframe_canyield(L->cframe);
1196 }
1197
lua_resetthread(lua_State * L,lua_State * th)1198 LUA_API void lua_resetthread(lua_State *L, lua_State *th)
1199 {
1200 TValue *stend, *st;
1201
1202 th->dummy_ffid = FF_C;
1203 th->status = LUA_OK;
1204
1205 setmrefr(th->glref, L->glref);
1206 setgcrefr(th->env, L->env);
1207
1208 th->cframe = NULL;
1209
1210 st = tvref(th->stack);
1211
1212 if (st != NULL) {
1213 lj_state_relimitstack(th);
1214
1215 stend = st + th->stacksize;
1216 st++; /* Needed for curr_funcisL() on empty stack. */
1217 if (LJ_FR2) st++;
1218 th->base = th->top = st;
1219 lj_func_closeuv(L, st);
1220 while (st < stend) /* Clear new slots. */
1221 setnilV(st++);
1222 }
1223
1224 th->exdata = L->exdata;
1225 th->exdata2 = L->exdata2;
1226 }
1227
lua_yield(lua_State * L,int nresults)1228 LUA_API int lua_yield(lua_State *L, int nresults)
1229 {
1230 void *cf = L->cframe;
1231 global_State *g = G(L);
1232 if (cframe_canyield(cf)) {
1233 cf = cframe_raw(cf);
1234 if (!hook_active(g)) { /* Regular yield: move results down if needed. */
1235 cTValue *f = L->top - nresults;
1236 if (f > L->base) {
1237 TValue *t = L->base;
1238 while (--nresults >= 0) copyTV(L, t++, f++);
1239 L->top = t;
1240 }
1241 L->cframe = NULL;
1242 L->status = LUA_YIELD;
1243 return -1;
1244 } else { /* Yield from hook: add a pseudo-frame. */
1245 TValue *top = L->top;
1246 hook_leave(g);
1247 (top++)->u64 = cframe_multres(cf);
1248 setcont(top, lj_cont_hook);
1249 if (LJ_FR2) top++;
1250 setframe_pc(top, cframe_pc(cf)-1);
1251 top++;
1252 setframe_gc(top, obj2gco(L), LJ_TTHREAD);
1253 if (LJ_FR2) top++;
1254 setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
1255 L->top = L->base = top+1;
1256 #if ((defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND) || LJ_TARGET_WINDOWS
1257 lj_err_throw(L, LUA_YIELD);
1258 #else
1259 L->cframe = NULL;
1260 L->status = LUA_YIELD;
1261 lj_vm_unwind_c(cf, LUA_YIELD);
1262 #endif
1263 }
1264 }
1265 lj_err_msg(L, LJ_ERR_CYIELD);
1266 return 0; /* unreachable */
1267 }
1268
lua_resume(lua_State * L,int nargs)1269 LUA_API int lua_resume(lua_State *L, int nargs)
1270 {
1271 if (L->cframe == NULL && L->status <= LUA_YIELD)
1272 return lj_vm_resume(L,
1273 L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs,
1274 0, 0);
1275 L->top = L->base;
1276 setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
1277 incr_top(L);
1278 return LUA_ERRRUN;
1279 }
1280
1281 /* -- GC and memory management -------------------------------------------- */
1282
lua_gc(lua_State * L,int what,int data)1283 LUA_API int lua_gc(lua_State *L, int what, int data)
1284 {
1285 global_State *g = G(L);
1286 int res = 0;
1287 switch (what) {
1288 case LUA_GCSTOP:
1289 g->gc.threshold = LJ_MAX_MEM;
1290 break;
1291 case LUA_GCRESTART:
1292 g->gc.threshold = data == -1 ? (g->gc.total/100)*g->gc.pause : g->gc.total;
1293 break;
1294 case LUA_GCCOLLECT:
1295 lj_gc_fullgc(L);
1296 break;
1297 case LUA_GCCOUNT:
1298 res = (int)(g->gc.total >> 10);
1299 break;
1300 case LUA_GCCOUNTB:
1301 res = (int)(g->gc.total & 0x3ff);
1302 break;
1303 case LUA_GCSTEP: {
1304 GCSize a = (GCSize)data << 10;
1305 g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0;
1306 while (g->gc.total >= g->gc.threshold)
1307 if (lj_gc_step(L) > 0) {
1308 res = 1;
1309 break;
1310 }
1311 break;
1312 }
1313 case LUA_GCSETPAUSE:
1314 res = (int)(g->gc.pause);
1315 g->gc.pause = (MSize)data;
1316 break;
1317 case LUA_GCSETSTEPMUL:
1318 res = (int)(g->gc.stepmul);
1319 g->gc.stepmul = (MSize)data;
1320 break;
1321 case LUA_GCISRUNNING:
1322 res = (g->gc.threshold != LJ_MAX_MEM);
1323 break;
1324 default:
1325 res = -1; /* Invalid option. */
1326 }
1327 return res;
1328 }
1329
lua_getallocf(lua_State * L,void ** ud)1330 LUA_API lua_Alloc lua_getallocf(lua_State *L, void **ud)
1331 {
1332 global_State *g = G(L);
1333 if (ud) *ud = g->allocd;
1334 return g->allocf;
1335 }
1336
lua_setallocf(lua_State * L,lua_Alloc f,void * ud)1337 LUA_API void lua_setallocf(lua_State *L, lua_Alloc f, void *ud)
1338 {
1339 global_State *g = G(L);
1340 g->allocd = ud;
1341 g->allocf = f;
1342 }
1343
lua_setexdata(lua_State * L,void * exdata)1344 LUA_API void lua_setexdata(lua_State *L, void *exdata)
1345 {
1346 L->exdata = exdata;
1347 }
1348
lua_getexdata(lua_State * L)1349 LUA_API void *lua_getexdata(lua_State *L)
1350 {
1351 return L->exdata;
1352 }
1353
lua_setexdata2(lua_State * L,void * exdata2)1354 LUA_API void lua_setexdata2(lua_State *L, void *exdata2)
1355 {
1356 L->exdata2 = exdata2;
1357 }
1358
lua_getexdata2(lua_State * L)1359 LUA_API void *lua_getexdata2(lua_State *L)
1360 {
1361 return L->exdata2;
1362 }
1363