summaryrefslogtreecommitdiff
path: root/src/lj_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_api.c')
-rw-r--r--src/lj_api.c1046
1 files changed, 1046 insertions, 0 deletions
diff --git a/src/lj_api.c b/src/lj_api.c
new file mode 100644
index 00000000..ea4eaf66
--- /dev/null
+++ b/src/lj_api.c
@@ -0,0 +1,1046 @@
1/*
2** Public Lua/C API.
3** Copyright (C) 2005-2009 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_str.h"
16#include "lj_tab.h"
17#include "lj_func.h"
18#include "lj_udata.h"
19#include "lj_meta.h"
20#include "lj_state.h"
21#include "lj_frame.h"
22#include "lj_trace.h"
23#include "lj_vm.h"
24#include "lj_lex.h"
25#include "lj_parse.h"
26
27/* -- Common helper functions --------------------------------------------- */
28
29#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
30#define api_checkvalidindex(L, i) api_check(L, (i) != niltv(L))
31
32static TValue *index2adr(lua_State *L, int idx)
33{
34 if (idx > 0) {
35 TValue *o = L->base + (idx - 1);
36 return o < L->top ? o : niltv(L);
37 } else if (idx > LUA_REGISTRYINDEX) {
38 api_check(L, idx != 0 && -idx <= L->top - L->base);
39 return L->top + idx;
40 } else if (idx == LUA_GLOBALSINDEX) {
41 TValue *o = &G(L)->tmptv;
42 settabV(L, o, tabref(L->env));
43 return o;
44 } else if (idx == LUA_REGISTRYINDEX) {
45 return registry(L);
46 } else {
47 GCfunc *fn = curr_func(L);
48 api_check(L, fn->c.gct == ~LJ_TFUNC && !isluafunc(fn));
49 if (idx == LUA_ENVIRONINDEX) {
50 TValue *o = &G(L)->tmptv;
51 settabV(L, o, tabref(fn->c.env));
52 return o;
53 } else {
54 idx = LUA_GLOBALSINDEX - idx;
55 return idx <= fn->c.nupvalues ? &fn->c.upvalue[idx-1] : niltv(L);
56 }
57 }
58}
59
60static TValue *stkindex2adr(lua_State *L, int idx)
61{
62 if (idx > 0) {
63 TValue *o = L->base + (idx - 1);
64 return o < L->top ? o : niltv(L);
65 } else {
66 api_check(L, idx != 0 && -idx <= L->top - L->base);
67 return L->top + idx;
68 }
69}
70
71static GCtab *getcurrenv(lua_State *L)
72{
73 GCfunc *fn = curr_func(L);
74 return fn->c.gct == ~LJ_TFUNC ? tabref(fn->c.env) : tabref(L->env);
75}
76
77/* -- Miscellaneous API functions ----------------------------------------- */
78
79LUA_API int lua_status(lua_State *L)
80{
81 return L->status;
82}
83
84LUA_API int lua_checkstack(lua_State *L, int size)
85{
86 if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) {
87 return 0; /* Stack overflow. */
88 } else if (size > 0) {
89 lj_state_checkstack(L, (MSize)size);
90 }
91 return 1;
92}
93
94LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
95{
96 TValue *f, *t;
97 if (from == to) return;
98 api_checknelems(from, n);
99 api_check(from, G(from) == G(to));
100 lj_state_checkstack(to, (MSize)n);
101 f = from->top;
102 t = to->top = to->top + n;
103 while (--n >= 0) copyTV(to, --t, --f);
104 from->top = f;
105}
106
107/* -- Stack manipulation -------------------------------------------------- */
108
109LUA_API int lua_gettop(lua_State *L)
110{
111 return cast_int(L->top - L->base);
112}
113
114LUA_API void lua_settop(lua_State *L, int idx)
115{
116 if (idx >= 0) {
117 api_check(L, idx <= L->maxstack - L->base);
118 if (L->base + idx > L->top) {
119 if (L->base + idx >= L->maxstack)
120 lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
121 do { setnilV(L->top++); } while (L->top < L->base + idx);
122 } else {
123 L->top = L->base + idx;
124 }
125 } else {
126 api_check(L, -(idx+1) <= (L->top - L->base));
127 L->top += idx+1; /* Shrinks top (idx < 0). */
128 }
129}
130
131LUA_API void lua_remove(lua_State *L, int idx)
132{
133 TValue *p = stkindex2adr(L, idx);
134 api_checkvalidindex(L, p);
135 while (++p < L->top) copyTV(L, p-1, p);
136 L->top--;
137}
138
139LUA_API void lua_insert(lua_State *L, int idx)
140{
141 TValue *q, *p = stkindex2adr(L, idx);
142 api_checkvalidindex(L, p);
143 for (q = L->top; q > p; q--) copyTV(L, q, q-1);
144 copyTV(L, p, L->top);
145}
146
147LUA_API void lua_replace(lua_State *L, int idx)
148{
149 api_checknelems(L, 1);
150 if (idx == LUA_GLOBALSINDEX) {
151 api_check(L, tvistab(L->top-1));
152 /* NOBARRIER: A thread (i.e. L) is never black. */
153 setgcref(L->env, obj2gco(tabV(L->top-1)));
154 } else if (idx == LUA_ENVIRONINDEX) {
155 GCfunc *fn = curr_func(L);
156 if (fn->c.gct != ~LJ_TFUNC)
157 lj_err_msg(L, LJ_ERR_NOENV);
158 api_check(L, tvistab(L->top-1));
159 setgcref(fn->c.env, obj2gco(tabV(L->top-1)));
160 lj_gc_barrier(L, fn, L->top-1);
161 } else {
162 TValue *o = index2adr(L, idx);
163 api_checkvalidindex(L, o);
164 copyTV(L, o, L->top-1);
165 if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
166 lj_gc_barrier(L, curr_func(L), L->top-1);
167 }
168 L->top--;
169}
170
171LUA_API void lua_pushvalue(lua_State *L, int idx)
172{
173 copyTV(L, L->top, index2adr(L, idx));
174 incr_top(L);
175}
176
177/* -- Stack getters ------------------------------------------------------- */
178
179LUA_API int lua_type(lua_State *L, int idx)
180{
181 cTValue *o = index2adr(L, idx);
182 if (tvisnum(o)) {
183 return LUA_TNUMBER;
184#if LJ_64
185 } else if (tvislightud(o)) {
186 return LUA_TLIGHTUSERDATA;
187#endif
188 } else if (o == niltv(L)) {
189 return LUA_TNONE;
190 } else { /* Magic internal/external tag conversion. ORDER LJ_T */
191 int t = ~itype(o);
192 return (int)(((t < 8 ? 0x98a42110 : 0x75b6) >> 4*(t&7)) & 15u);
193 }
194}
195
196LUA_API const char *lua_typename(lua_State *L, int t)
197{
198 UNUSED(L);
199 return lj_obj_typename[t+1];
200}
201
202LUA_API int lua_iscfunction(lua_State *L, int idx)
203{
204 cTValue *o = index2adr(L, idx);
205 return !isluafunc(funcV(o));
206}
207
208LUA_API int lua_isnumber(lua_State *L, int idx)
209{
210 cTValue *o = index2adr(L, idx);
211 TValue tmp;
212 return (tvisnum(o) || (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp)));
213}
214
215LUA_API int lua_isstring(lua_State *L, int idx)
216{
217 cTValue *o = index2adr(L, idx);
218 return (tvisstr(o) || tvisnum(o));
219}
220
221LUA_API int lua_isuserdata(lua_State *L, int idx)
222{
223 cTValue *o = index2adr(L, idx);
224 return (tvisudata(o) || tvislightud(o));
225}
226
227LUA_API int lua_rawequal(lua_State *L, int idx1, int idx2)
228{
229 cTValue *o1 = index2adr(L, idx1);
230 cTValue *o2 = index2adr(L, idx2);
231 return (o1 == niltv(L) || o2 == niltv(L)) ? 0 : lj_obj_equal(o1, o2);
232}
233
234LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
235{
236 cTValue *o1 = index2adr(L, idx1);
237 cTValue *o2 = index2adr(L, idx2);
238 if (tvisnum(o1) && tvisnum(o2)) {
239 return numV(o1) == numV(o2);
240 } else if (itype(o1) != itype(o2)) {
241 return 0;
242 } else if (tvispri(o1)) {
243 return o1 != niltv(L) && o2 != niltv(L);
244#if LJ_64
245 } else if (tvislightud(o1)) {
246 return o1->u64 == o2->u64;
247#endif
248 } else if (gcrefeq(o1->gcr, o2->gcr)) {
249 return 1;
250 } else if (!tvistabud(o1)) {
251 return 0;
252 } else {
253 TValue *base = lj_meta_equal(L, gcV(o1), gcV(o2), 0);
254 if ((uintptr_t)base <= 1) {
255 return (int)(uintptr_t)base;
256 } else {
257 L->top = base+2;
258 lj_vm_call(L, base, 1+1);
259 L->top -= 2;
260 return tvistruecond(L->top+1);
261 }
262 }
263}
264
265LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
266{
267 cTValue *o1 = index2adr(L, idx1);
268 cTValue *o2 = index2adr(L, idx2);
269 if (o1 == niltv(L) || o2 == niltv(L)) {
270 return 0;
271 } else if (tvisnum(o1) && tvisnum(o2)) {
272 return numV(o1) < numV(o2);
273 } else {
274 TValue *base = lj_meta_comp(L, o1, o2, 0);
275 if ((uintptr_t)base <= 1) {
276 return (int)(uintptr_t)base;
277 } else {
278 L->top = base+2;
279 lj_vm_call(L, base, 1+1);
280 L->top -= 2;
281 return tvistruecond(L->top+1);
282 }
283 }
284}
285
286LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
287{
288 cTValue *o = index2adr(L, idx);
289 TValue tmp;
290 if (LJ_LIKELY(tvisnum(o)))
291 return numV(o);
292 else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
293 return numV(&tmp);
294 else
295 return 0;
296}
297
298LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
299{
300 cTValue *o = index2adr(L, idx);
301 TValue tmp;
302 lua_Number n;
303 if (LJ_LIKELY(tvisnum(o)))
304 n = numV(o);
305 else if (tvisstr(o) && lj_str_numconv(strVdata(o), &tmp))
306 n = numV(&tmp);
307 else
308 return 0;
309#if LJ_64
310 return (lua_Integer)n;
311#else
312 return lj_num2int(n);
313#endif
314}
315
316LUA_API int lua_toboolean(lua_State *L, int idx)
317{
318 cTValue *o = index2adr(L, idx);
319 return tvistruecond(o);
320}
321
322LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
323{
324 TValue *o = index2adr(L, idx);
325 GCstr *s;
326 if (LJ_LIKELY(tvisstr(o))) {
327 s = strV(o);
328 } else if (tvisnum(o)) {
329 lj_gc_check(L);
330 o = index2adr(L, idx); /* GC may move the stack. */
331 s = lj_str_fromnum(L, &o->n);
332 } else {
333 if (len != NULL) *len = 0;
334 return NULL;
335 }
336 if (len != NULL) *len = s->len;
337 return strdata(s);
338}
339
340LUA_API size_t lua_objlen(lua_State *L, int idx)
341{
342 TValue *o = index2adr(L, idx);
343 if (tvisstr(o))
344 return strV(o)->len;
345 else if (tvistab(o))
346 return cast(size_t, lj_tab_len(tabV(o)));
347 else if (tvisudata(o))
348 return udataV(o)->len;
349 else if (tvisnum(o))
350 return lj_str_fromnum(L, &o->n)->len;
351 else
352 return 0;
353}
354
355LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
356{
357 cTValue *o = index2adr(L, idx);
358 return funcV(o)->c.gate == lj_gate_c ? funcV(o)->c.f : NULL;
359}
360
361LUA_API void *lua_touserdata(lua_State *L, int idx)
362{
363 cTValue *o = index2adr(L, idx);
364 if (tvisudata(o))
365 return uddata(udataV(o));
366 else if (tvislightud(o))
367 return lightudV(o);
368 else
369 return NULL;
370}
371
372LUA_API lua_State *lua_tothread(lua_State *L, int idx)
373{
374 cTValue *o = index2adr(L, idx);
375 return (!tvisthread(o)) ? NULL : threadV(o);
376}
377
378LUA_API const void *lua_topointer(lua_State *L, int idx)
379{
380 cTValue *o = index2adr(L, idx);
381 if (tvisudata(o))
382 return uddata(udataV(o));
383 else if (tvislightud(o))
384 return lightudV(o);
385 else if (tvisgcv(o))
386 return gcV(o);
387 else
388 return NULL;
389}
390
391/* -- Stack setters (object creation) ------------------------------------- */
392
393LUA_API void lua_pushnil(lua_State *L)
394{
395 setnilV(L->top);
396 incr_top(L);
397}
398
399LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
400{
401 setnumV(L->top, n);
402 if (LJ_UNLIKELY(tvisnan(L->top)))
403 setnanV(L->top); /* Canonicalize injected NaNs. */
404 incr_top(L);
405}
406
407LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
408{
409 setnumV(L->top, cast_num(n));
410 incr_top(L);
411}
412
413LUA_API void lua_pushlstring(lua_State *L, const char *str, size_t len)
414{
415 GCstr *s;
416 lj_gc_check(L);
417 s = lj_str_new(L, str, len);
418 setstrV(L, L->top, s);
419 incr_top(L);
420}
421
422LUA_API void lua_pushstring(lua_State *L, const char *str)
423{
424 if (str == NULL) {
425 setnilV(L->top);
426 } else {
427 GCstr *s;
428 lj_gc_check(L);
429 s = lj_str_newz(L, str);
430 setstrV(L, L->top, s);
431 }
432 incr_top(L);
433}
434
435LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt,
436 va_list argp)
437{
438 lj_gc_check(L);
439 return lj_str_pushvf(L, fmt, argp);
440}
441
442LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...)
443{
444 const char *ret;
445 va_list argp;
446 lj_gc_check(L);
447 va_start(argp, fmt);
448 ret = lj_str_pushvf(L, fmt, argp);
449 va_end(argp);
450 return ret;
451}
452
453LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
454{
455 GCfunc *fn;
456 lj_gc_check(L);
457 api_checknelems(L, n);
458 fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
459 fn->c.f = f;
460 L->top -= n;
461 while (n--)
462 copyTV(L, &fn->c.upvalue[n], L->top+n);
463 setfuncV(L, L->top, fn);
464 lua_assert(iswhite(obj2gco(fn)));
465 incr_top(L);
466}
467
468LUA_API void lua_pushboolean(lua_State *L, int b)
469{
470 setboolV(L->top, (b != 0));
471 incr_top(L);
472}
473
474LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
475{
476 setlightudV(L->top, checklightudptr(L, p));
477 incr_top(L);
478}
479
480LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
481{
482 GCtab *t;
483 lj_gc_check(L);
484 t = lj_tab_new(L, (uint32_t)(narray > 0 ? narray+1 : 0), hsize2hbits(nrec));
485 settabV(L, L->top, t);
486 incr_top(L);
487}
488
489LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
490{
491 GCtab *regt = tabV(registry(L));
492 TValue *tv = lj_tab_setstr(L, regt, lj_str_newz(L, tname));
493 if (tvisnil(tv)) {
494 GCtab *mt = lj_tab_new(L, 0, 1);
495 settabV(L, tv, mt);
496 settabV(L, L->top++, mt);
497 lj_gc_objbarriert(L, regt, mt);
498 return 1;
499 } else {
500 copyTV(L, L->top++, tv);
501 return 0;
502 }
503}
504
505LUA_API int lua_pushthread(lua_State *L)
506{
507 setthreadV(L, L->top, L);
508 incr_top(L);
509 return (mainthread(G(L)) == L);
510}
511
512LUA_API lua_State *lua_newthread(lua_State *L)
513{
514 lua_State *L1;
515 lj_gc_check(L);
516 L1 = lj_state_new(L);
517 setthreadV(L, L->top, L1);
518 incr_top(L);
519 return L1;
520}
521
522LUA_API void *lua_newuserdata(lua_State *L, size_t size)
523{
524 GCudata *ud;
525 lj_gc_check(L);
526 if (size > LJ_MAX_UDATA)
527 lj_err_msg(L, LJ_ERR_UDATAOV);
528 ud = lj_udata_new(L, (MSize)size, getcurrenv(L));
529 setudataV(L, L->top, ud);
530 incr_top(L);
531 return uddata(ud);
532}
533
534LUA_API void lua_concat(lua_State *L, int n)
535{
536 api_checknelems(L, n);
537 if (n >= 2) {
538 n--;
539 do {
540 TValue *top = lj_meta_cat(L, L->top-1, n);
541 if (top == NULL) {
542 L->top -= n;
543 break;
544 }
545 n -= cast_int(L->top - top);
546 L->top = top+2;
547 lj_vm_call(L, top, 1+1);
548 L->top--;
549 copyTV(L, L->top-1, L->top);
550 } while (--n > 0);
551 } else if (n == 0) { /* Push empty string. */
552 setstrV(L, L->top, lj_str_new(L, "", 0));
553 incr_top(L);
554 }
555 /* else n == 1: nothing to do. */
556}
557
558/* -- Object getters ------------------------------------------------------ */
559
560LUA_API void lua_gettable(lua_State *L, int idx)
561{
562 cTValue *v, *t = index2adr(L, idx);
563 api_checkvalidindex(L, t);
564 v = lj_meta_tget(L, t, L->top-1);
565 if (v == NULL) {
566 L->top += 2;
567 lj_vm_call(L, L->top-2, 1+1);
568 L->top -= 2;
569 v = L->top+1;
570 }
571 copyTV(L, L->top-1, v);
572}
573
574LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
575{
576 cTValue *v, *t = index2adr(L, idx);
577 TValue key;
578 api_checkvalidindex(L, t);
579 setstrV(L, &key, lj_str_newz(L, k));
580 v = lj_meta_tget(L, t, &key);
581 if (v == NULL) {
582 L->top += 2;
583 lj_vm_call(L, L->top-2, 1+1);
584 L->top -= 2;
585 v = L->top+1;
586 }
587 copyTV(L, L->top, v);
588 incr_top(L);
589}
590
591LUA_API void lua_rawget(lua_State *L, int idx)
592{
593 cTValue *t = index2adr(L, idx);
594 api_check(L, tvistab(t));
595 copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1));
596}
597
598LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
599{
600 cTValue *v, *t = index2adr(L, idx);
601 api_check(L, tvistab(t));
602 v = lj_tab_getint(tabV(t), n);
603 if (v) {
604 copyTV(L, L->top, v);
605 } else {
606 setnilV(L->top);
607 }
608 incr_top(L);
609}
610
611LUA_API int lua_getmetatable(lua_State *L, int idx)
612{
613 cTValue *o = index2adr(L, idx);
614 GCtab *mt = NULL;
615 if (tvistab(o))
616 mt = tabref(tabV(o)->metatable);
617 else if (tvisudata(o))
618 mt = tabref(udataV(o)->metatable);
619 else
620 mt = tabref(G(L)->basemt[itypemap(o)]);
621 if (mt == NULL)
622 return 0;
623 settabV(L, L->top, mt);
624 incr_top(L);
625 return 1;
626}
627
628LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field)
629{
630 if (lua_getmetatable(L, idx)) {
631 cTValue *tv = lj_tab_getstr(tabV(L->top-1), lj_str_newz(L, field));
632 if (tv && !tvisnil(tv)) {
633 copyTV(L, L->top-1, tv);
634 return 1;
635 }
636 L->top--;
637 }
638 return 0;
639}
640
641LUA_API void lua_getfenv(lua_State *L, int idx)
642{
643 cTValue *o = index2adr(L, idx);
644 api_checkvalidindex(L, o);
645 if (tvisfunc(o)) {
646 settabV(L, L->top, tabref(funcV(o)->c.env));
647 } else if (tvisudata(o)) {
648 settabV(L, L->top, tabref(udataV(o)->env));
649 } else if (tvisthread(o)) {
650 settabV(L, L->top, tabref(threadV(o)->env));
651 } else {
652 setnilV(L->top);
653 }
654 incr_top(L);
655}
656
657LUA_API int lua_next(lua_State *L, int idx)
658{
659 cTValue *t = index2adr(L, idx);
660 int more;
661 api_check(L, tvistab(t));
662 more = lj_tab_next(L, tabV(t), L->top-1);
663 if (more) {
664 incr_top(L); /* Return new key and value slot. */
665 } else { /* End of traversal. */
666 L->top--; /* Remove key slot. */
667 }
668 return more;
669}
670
671static const char *aux_upvalue(cTValue *f, uint32_t idx, TValue **val)
672{
673 GCfunc *fn;
674 if (!tvisfunc(f)) return NULL;
675 fn = funcV(f);
676 if (isluafunc(fn)) {
677 GCproto *pt = funcproto(fn);
678 if (idx < pt->sizeuvname) {
679 *val = gcref(fn->l.uvptr[idx])->uv.v;
680 return strdata(pt->uvname[idx]);
681 }
682 } else {
683 if (idx < fn->c.nupvalues) {
684 *val = &fn->c.upvalue[idx];
685 return "";
686 }
687 }
688 return NULL;
689}
690
691LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
692{
693 TValue *val;
694 const char *name = aux_upvalue(index2adr(L, idx), (uint32_t)(n-1), &val);
695 if (name) {
696 copyTV(L, L->top, val);
697 incr_top(L);
698 }
699 return name;
700}
701
702LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
703{
704 cTValue *o = index2adr(L, idx);
705 if (tvisudata(o)) {
706 GCudata *ud = udataV(o);
707 cTValue *tv = lj_tab_getstr(tabV(registry(L)), lj_str_newz(L, tname));
708 if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
709 return uddata(ud);
710 }
711 lj_err_argtype(L, idx, tname);
712 return NULL; /* unreachable */
713}
714
715/* -- Object setters ------------------------------------------------------ */
716
717LUA_API void lua_settable(lua_State *L, int idx)
718{
719 TValue *o;
720 cTValue *t = index2adr(L, idx);
721 api_checknelems(L, 2);
722 api_checkvalidindex(L, t);
723 o = lj_meta_tset(L, t, L->top-2);
724 if (o) {
725 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
726 copyTV(L, o, L->top-1);
727 L->top -= 2;
728 } else {
729 L->top += 3;
730 copyTV(L, L->top-1, L->top-6);
731 lj_vm_call(L, L->top-3, 0+1);
732 L->top -= 3;
733 }
734}
735
736LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
737{
738 TValue *o;
739 TValue key;
740 cTValue *t = index2adr(L, idx);
741 api_checknelems(L, 1);
742 api_checkvalidindex(L, t);
743 setstrV(L, &key, lj_str_newz(L, k));
744 o = lj_meta_tset(L, t, &key);
745 if (o) {
746 L->top--;
747 /* NOBARRIER: lj_meta_tset ensures the table is not black. */
748 copyTV(L, o, L->top);
749 } else {
750 L->top += 3;
751 copyTV(L, L->top-1, L->top-6);
752 lj_vm_call(L, L->top-3, 0+1);
753 L->top -= 2;
754 }
755}
756
757LUA_API void lua_rawset(lua_State *L, int idx)
758{
759 GCtab *t = tabV(index2adr(L, idx));
760 TValue *dst, *key;
761 api_checknelems(L, 2);
762 key = L->top-2;
763 dst = lj_tab_set(L, t, key);
764 copyTV(L, dst, key+1);
765 lj_gc_barriert(L, t, dst);
766 L->top = key;
767}
768
769LUA_API void lua_rawseti(lua_State *L, int idx, int n)
770{
771 GCtab *t = tabV(index2adr(L, idx));
772 TValue *dst, *src;
773 api_checknelems(L, 1);
774 dst = lj_tab_setint(L, t, n);
775 src = L->top-1;
776 copyTV(L, dst, src);
777 lj_gc_barriert(L, t, dst);
778 L->top = src;
779}
780
781LUA_API int lua_setmetatable(lua_State *L, int idx)
782{
783 global_State *g;
784 GCtab *mt;
785 cTValue *o = index2adr(L, idx);
786 api_checknelems(L, 1);
787 api_checkvalidindex(L, o);
788 if (tvisnil(L->top-1)) {
789 mt = NULL;
790 } else {
791 api_check(L, tvistab(L->top-1));
792 mt = tabV(L->top-1);
793 }
794 g = G(L);
795 if (tvistab(o)) {
796 setgcref(tabV(o)->metatable, obj2gco(mt));
797 if (mt)
798 lj_gc_objbarriert(L, tabV(o), mt);
799 } else if (tvisudata(o)) {
800 setgcref(udataV(o)->metatable, obj2gco(mt));
801 if (mt)
802 lj_gc_objbarrier(L, udataV(o), mt);
803 } else {
804 /* Flush cache, since traces specialize to basemt. But not during __gc. */
805 if (lj_trace_flushall(L))
806 lj_err_caller(L, LJ_ERR_NOGCMM);
807 if (tvisbool(o)) {
808 /* NOBARRIER: g->basemt[] is a GC root. */
809 setgcref(g->basemt[~LJ_TTRUE], obj2gco(mt));
810 setgcref(g->basemt[~LJ_TFALSE], obj2gco(mt));
811 } else {
812 /* NOBARRIER: g->basemt[] is a GC root. */
813 setgcref(g->basemt[itypemap(o)], obj2gco(mt));
814 }
815 }
816 L->top--;
817 return 1;
818}
819
820LUA_API int lua_setfenv(lua_State *L, int idx)
821{
822 cTValue *o = index2adr(L, idx);
823 GCtab *t;
824 api_checknelems(L, 1);
825 api_checkvalidindex(L, o);
826 api_check(L, tvistab(L->top-1));
827 t = tabV(L->top-1);
828 if (tvisfunc(o)) {
829 setgcref(funcV(o)->c.env, obj2gco(t));
830 } else if (tvisudata(o)) {
831 setgcref(udataV(o)->env, obj2gco(t));
832 } else if (tvisthread(o)) {
833 setgcref(threadV(o)->env, obj2gco(t));
834 } else {
835 L->top--;
836 return 0;
837 }
838 lj_gc_objbarrier(L, gcV(o), t);
839 L->top--;
840 return 1;
841}
842
843LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
844{
845 cTValue *f = index2adr(L, idx);
846 TValue *val;
847 const char *name;
848 api_checknelems(L, 1);
849 name = aux_upvalue(f, (uint32_t)(n-1), &val);
850 if (name) {
851 L->top--;
852 copyTV(L, val, L->top);
853 lj_gc_barrier(L, funcV(f), L->top);
854 }
855 return name;
856}
857
858/* -- Calls --------------------------------------------------------------- */
859
860LUA_API void lua_call(lua_State *L, int nargs, int nresults)
861{
862 api_checknelems(L, nargs+1);
863 lj_vm_call(L, L->top - nargs, nresults+1);
864}
865
866LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
867{
868 global_State *g = G(L);
869 uint8_t oldh = hook_save(g);
870 ptrdiff_t ef;
871 int status;
872 api_checknelems(L, nargs+1);
873 if (errfunc == 0) {
874 ef = 0;
875 } else {
876 cTValue *o = stkindex2adr(L, errfunc);
877 api_checkvalidindex(L, o);
878 ef = savestack(L, o);
879 }
880 status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef);
881 if (status) hook_restore(g, oldh);
882 return status;
883}
884
885static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
886{
887 GCfunc *fn;
888 fn = lj_func_newC(L, 0, getcurrenv(L));
889 fn->c.f = func;
890 setfuncV(L, L->top, fn);
891 setlightudV(L->top+1, checklightudptr(L, ud));
892 cframe_nres(L->cframe) = 1+0; /* Zero results. */
893 L->top += 2;
894 return L->top-1; /* Now call the newly allocated C function. */
895}
896
897LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
898{
899 global_State *g = G(L);
900 uint8_t oldh = hook_save(g);
901 int status = lj_vm_cpcall(L, cpcall, func, ud);
902 if (status) hook_restore(g, oldh);
903 return status;
904}
905
906LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
907{
908 if (luaL_getmetafield(L, idx, field)) {
909 TValue *base = L->top--;
910 copyTV(L, base, index2adr(L, idx));
911 L->top = base+1;
912 lj_vm_call(L, base, 1+1);
913 return 1;
914 }
915 return 0;
916}
917
918/* -- Coroutine yield and resume ------------------------------------------ */
919
920LUA_API int lua_yield(lua_State *L, int nresults)
921{
922 void *cf = L->cframe;
923 cTValue *f;
924 if (!cframe_canyield(cf))
925 lj_err_msg(L, LJ_ERR_CYIELD);
926 f = L->top - nresults;
927 if (f > L->base) {
928 TValue *t = L->base;
929 while (--nresults >= 0) copyTV(L, t++, f++);
930 L->top = t;
931 }
932 L->cframe = NULL;
933 L->status = LUA_YIELD;
934 lj_vm_unwind_c(cf, LUA_YIELD);
935 return -1; /* unreachable */
936}
937
938LUA_API int lua_resume(lua_State *L, int nargs)
939{
940 if (L->cframe == NULL && L->status <= LUA_YIELD)
941 return lj_vm_resume(L, L->top - nargs, 0, 0);
942 L->top = L->base;
943 setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
944 incr_top(L);
945 return LUA_ERRRUN;
946}
947
948/* -- Load and dump Lua code ---------------------------------------------- */
949
950static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud)
951{
952 LexState *ls = cast(LexState *, ud);
953 GCfunc *fn;
954 UNUSED(dummy);
955 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
956 lj_lex_start(L, ls);
957 fn = lj_func_newL(L, lj_parse(ls), tabref(L->env));
958 /* Parser may realloc stack. Don't combine above/below into one statement. */
959 setfuncV(L, L->top++, fn);
960 return NULL;
961}
962
963LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data,
964 const char *chunkname)
965{
966 LexState ls;
967 int status;
968 global_State *g;
969 ls.rfunc = reader;
970 ls.rdata = data;
971 ls.chunkarg = chunkname ? chunkname : "?";
972 lj_str_initbuf(L, &ls.sb);
973 status = lj_vm_cpcall(L, cpparser, NULL, &ls);
974 g = G(L);
975 lj_str_freebuf(g, &ls.sb);
976 lj_gc_check(L);
977 return status;
978}
979
980LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data)
981{
982 api_checknelems(L, 1);
983 UNUSED(L); UNUSED(writer); UNUSED(data);
984 return 1; /* Error, not supported. */
985}
986
987/* -- GC and memory management -------------------------------------------- */
988
989LUA_API int lua_gc(lua_State *L, int what, int data)
990{
991 global_State *g = G(L);
992 int res = 0;
993 switch (what) {
994 case LUA_GCSTOP:
995 g->gc.threshold = LJ_MAX_MEM;
996 break;
997 case LUA_GCRESTART:
998 g->gc.threshold = g->gc.total;
999 break;
1000 case LUA_GCCOLLECT:
1001 lj_gc_fullgc(L);
1002 break;
1003 case LUA_GCCOUNT:
1004 res = cast_int(g->gc.total >> 10);
1005 break;
1006 case LUA_GCCOUNTB:
1007 res = cast_int(g->gc.total & 0x3ff);
1008 break;
1009 case LUA_GCSTEP: {
1010 MSize a = (MSize)data << 10;
1011 g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0;
1012 while (g->gc.total >= g->gc.threshold)
1013 if (lj_gc_step(L)) {
1014 res = 1;
1015 break;
1016 }
1017 break;
1018 }
1019 case LUA_GCSETPAUSE:
1020 res = cast_int(g->gc.pause);
1021 g->gc.pause = (MSize)data;
1022 break;
1023 case LUA_GCSETSTEPMUL:
1024 res = cast_int(g->gc.stepmul);
1025 g->gc.stepmul = (MSize)data;
1026 break;
1027 default:
1028 res = -1; /* Invalid option. */
1029 }
1030 return res;
1031}
1032
1033LUA_API lua_Alloc lua_getallocf(lua_State *L, void **ud)
1034{
1035 global_State *g = G(L);
1036 if (ud) *ud = g->allocd;
1037 return g->allocf;
1038}
1039
1040LUA_API void lua_setallocf(lua_State *L, lua_Alloc f, void *ud)
1041{
1042 global_State *g = G(L);
1043 g->allocd = ud;
1044 g->allocf = f;
1045}
1046