Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/lapi.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "lapi.h"
4
5
#include "lstate.h"
6
#include "lstring.h"
7
#include "ltable.h"
8
#include "lfunc.h"
9
#include "lgc.h"
10
#include "ldo.h"
11
#include "ludata.h"
12
#include "lvm.h"
13
#include "lnumutils.h"
14
#include "lbuffer.h"
15
16
#include <string.h>
17
18
/*
19
* This file contains most implementations of core Lua APIs from lua.h.
20
*
21
* These implementations should use api_check macros to verify that stack and type contracts hold; it's the callers
22
* responsibility to, for example, pass a valid table index to lua_rawgetfield. Generally errors should only be raised
23
* for conditions caller can't predict such as an out-of-memory error.
24
*
25
* The caller is expected to handle stack reservation (by using less than LUA_MINSTACK slots or by calling lua_checkstack).
26
* To ensure this is handled correctly, use api_incr_top(L) when pushing values to the stack.
27
*
28
* Functions that push any collectable objects to the stack *should* call luaC_threadbarrier. Failure to do this can result
29
* in stack references that point to dead objects since black threads don't get rescanned.
30
*
31
* Functions that push newly created objects to the stack *should* call luaC_checkGC in addition to luaC_threadbarrier.
32
* Failure to do this can result in OOM since GC may never run.
33
*
34
* Note that luaC_checkGC may mark the thread and paint it black; functions that call both before pushing objects must
35
* therefore call luaC_checkGC before luaC_threadbarrier to guarantee the object is pushed to a gray thread.
36
*/
37
38
const char* lua_ident = "$Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio $\n"
39
"$Authors: R. Ierusalimschy, L. H. de Figueiredo & W. Celes $\n"
40
"$URL: www.lua.org $\n";
41
42
const char* luau_ident = "$Luau: Copyright (C) 2019-2024 Roblox Corporation $\n"
43
"$URL: luau.org $\n";
44
45
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
46
47
#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject)
48
49
#define api_incr_top(L) \
50
{ \
51
api_check(L, L->top < L->ci->top); \
52
L->top++; \
53
}
54
55
#define api_update_top(L, p) \
56
{ \
57
api_check(L, p >= L->base && p <= L->ci->top); \
58
L->top = p; \
59
}
60
61
#define updateatom(L, ts) \
62
{ \
63
if (ts->atom == ATOM_UNDEF) \
64
ts->atom = L->global->cb.useratom ? L->global->cb.useratom(L, ts->data, ts->len) : -1; \
65
}
66
67
static LuaTable* getcurrenv(lua_State* L)
68
{
69
if (L->ci == L->base_ci) // no enclosing function?
70
return L->gt; // use global table as environment
71
else
72
return curr_func(L)->env;
73
}
74
75
static LUAU_NOINLINE TValue* pseudo2addr(lua_State* L, int idx)
76
{
77
api_check(L, lua_ispseudo(idx));
78
switch (idx)
79
{ // pseudo-indices
80
case LUA_REGISTRYINDEX:
81
return registry(L);
82
case LUA_ENVIRONINDEX:
83
{
84
sethvalue(L, &L->global->pseudotemp, getcurrenv(L));
85
return &L->global->pseudotemp;
86
}
87
case LUA_GLOBALSINDEX:
88
{
89
sethvalue(L, &L->global->pseudotemp, L->gt);
90
return &L->global->pseudotemp;
91
}
92
default:
93
{
94
Closure* func = curr_func(L);
95
idx = LUA_GLOBALSINDEX - idx;
96
return (idx <= func->nupvalues) ? &func->c.upvals[idx - 1] : cast_to(TValue*, luaO_nilobject);
97
}
98
}
99
}
100
101
static LUAU_FORCEINLINE TValue* index2addr(lua_State* L, int idx)
102
{
103
if (idx > 0)
104
{
105
TValue* o = L->base + (idx - 1);
106
api_check(L, idx <= L->ci->top - L->base);
107
if (o >= L->top)
108
return cast_to(TValue*, luaO_nilobject);
109
else
110
return o;
111
}
112
else if (idx > LUA_REGISTRYINDEX)
113
{
114
api_check(L, idx != 0 && -idx <= L->top - L->base);
115
return L->top + idx;
116
}
117
else
118
{
119
return pseudo2addr(L, idx);
120
}
121
}
122
123
const TValue* luaA_toobject(lua_State* L, int idx)
124
{
125
StkId p = index2addr(L, idx);
126
return (p == luaO_nilobject) ? NULL : p;
127
}
128
129
void luaA_pushobject(lua_State* L, const TValue* o)
130
{
131
setobj2s(L, L->top, o);
132
api_incr_top(L);
133
}
134
135
int lua_checkstack(lua_State* L, int size)
136
{
137
int res = 1;
138
if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)
139
res = 0; // stack overflow
140
else if (size > 0)
141
{
142
if (stacklimitreached(L, size))
143
{
144
struct CallContext
145
{
146
int size;
147
148
static void run(lua_State* L, void* ud)
149
{
150
CallContext* ctx = (CallContext*)ud;
151
152
luaD_growstack(L, ctx->size);
153
}
154
} ctx = {size};
155
156
// there could be no memory to extend the stack
157
if (luaD_rawrunprotected(L, &CallContext::run, &ctx) != LUA_OK)
158
return 0;
159
}
160
else
161
{
162
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK, 0));
163
}
164
165
expandstacklimit(L, L->top + size);
166
}
167
return res;
168
}
169
170
void lua_rawcheckstack(lua_State* L, int size)
171
{
172
luaD_checkstack(L, size);
173
expandstacklimit(L, L->top + size);
174
}
175
176
void lua_xmove(lua_State* from, lua_State* to, int n)
177
{
178
if (from == to)
179
return;
180
api_checknelems(from, n);
181
api_check(from, from->global == to->global);
182
api_check(from, to->ci->top - to->top >= n);
183
luaC_threadbarrier(to);
184
185
StkId ttop = to->top;
186
StkId ftop = from->top - n;
187
for (int i = 0; i < n; i++)
188
setobj2s(to, ttop + i, ftop + i);
189
190
from->top = ftop;
191
to->top = ttop + n;
192
}
193
194
void lua_xpush(lua_State* from, lua_State* to, int idx)
195
{
196
api_check(from, from->global == to->global);
197
luaC_threadbarrier(to);
198
setobj2s(to, to->top, index2addr(from, idx));
199
api_incr_top(to);
200
}
201
202
lua_State* lua_newthread(lua_State* L)
203
{
204
luaC_checkGC(L);
205
luaC_threadbarrier(L);
206
lua_State* L1 = luaE_newthread(L);
207
setthvalue(L, L->top, L1);
208
api_incr_top(L);
209
global_State* g = L->global;
210
if (g->cb.userthread)
211
g->cb.userthread(L, L1);
212
return L1;
213
}
214
215
lua_State* lua_mainthread(lua_State* L)
216
{
217
return L->global->mainthread;
218
}
219
220
/*
221
** basic stack manipulation
222
*/
223
224
int lua_absindex(lua_State* L, int idx)
225
{
226
api_check(L, (idx > 0 && idx <= L->top - L->base) || (idx < 0 && -idx <= L->top - L->base) || lua_ispseudo(idx));
227
return idx > 0 || lua_ispseudo(idx) ? idx : cast_int(L->top - L->base) + idx + 1;
228
}
229
230
int lua_gettop(lua_State* L)
231
{
232
return cast_int(L->top - L->base);
233
}
234
235
void lua_settop(lua_State* L, int idx)
236
{
237
if (idx >= 0)
238
{
239
api_check(L, idx <= L->stack_last - L->base);
240
while (L->top < L->base + idx)
241
setnilvalue(L->top++);
242
L->top = L->base + idx;
243
}
244
else
245
{
246
api_check(L, -(idx + 1) <= (L->top - L->base));
247
L->top += idx + 1; // `subtract' index (index is negative)
248
}
249
}
250
251
void lua_remove(lua_State* L, int idx)
252
{
253
StkId p = index2addr(L, idx);
254
api_checkvalidindex(L, p);
255
while (++p < L->top)
256
setobj2s(L, p - 1, p);
257
L->top--;
258
}
259
260
void lua_insert(lua_State* L, int idx)
261
{
262
luaC_threadbarrier(L);
263
StkId p = index2addr(L, idx);
264
api_checkvalidindex(L, p);
265
for (StkId q = L->top; q > p; q--)
266
setobj2s(L, q, q - 1);
267
setobj2s(L, p, L->top);
268
}
269
270
void lua_replace(lua_State* L, int idx)
271
{
272
api_checknelems(L, 1);
273
luaC_threadbarrier(L);
274
StkId o = index2addr(L, idx);
275
api_checkvalidindex(L, o);
276
if (idx == LUA_ENVIRONINDEX)
277
{
278
api_check(L, L->ci != L->base_ci);
279
Closure* func = curr_func(L);
280
api_check(L, ttistable(L->top - 1));
281
func->env = hvalue(L->top - 1);
282
luaC_barrier(L, func, L->top - 1);
283
}
284
else if (idx == LUA_GLOBALSINDEX)
285
{
286
api_check(L, ttistable(L->top - 1));
287
L->gt = hvalue(L->top - 1);
288
}
289
else
290
{
291
setobj(L, o, L->top - 1);
292
if (idx < LUA_GLOBALSINDEX) // function upvalue?
293
luaC_barrier(L, curr_func(L), L->top - 1);
294
}
295
L->top--;
296
}
297
298
void lua_pushvalue(lua_State* L, int idx)
299
{
300
luaC_threadbarrier(L);
301
StkId o = index2addr(L, idx);
302
setobj2s(L, L->top, o);
303
api_incr_top(L);
304
}
305
306
/*
307
** access functions (stack -> C)
308
*/
309
310
int lua_type(lua_State* L, int idx)
311
{
312
StkId o = index2addr(L, idx);
313
return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
314
}
315
316
const char* lua_typename(lua_State* L, int t)
317
{
318
return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
319
}
320
321
int lua_iscfunction(lua_State* L, int idx)
322
{
323
StkId o = index2addr(L, idx);
324
return iscfunction(o);
325
}
326
327
int lua_isLfunction(lua_State* L, int idx)
328
{
329
StkId o = index2addr(L, idx);
330
return isLfunction(o);
331
}
332
333
int lua_isnumber(lua_State* L, int idx)
334
{
335
TValue n;
336
const TValue* o = index2addr(L, idx);
337
return tonumber(o, &n);
338
}
339
340
int lua_isstring(lua_State* L, int idx)
341
{
342
int t = lua_type(L, idx);
343
return (t == LUA_TSTRING || t == LUA_TNUMBER);
344
}
345
346
int lua_isuserdata(lua_State* L, int idx)
347
{
348
const TValue* o = index2addr(L, idx);
349
return (ttisuserdata(o) || ttislightuserdata(o));
350
}
351
352
int lua_rawequal(lua_State* L, int index1, int index2)
353
{
354
StkId o1 = index2addr(L, index1);
355
StkId o2 = index2addr(L, index2);
356
return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaO_rawequalObj(o1, o2);
357
}
358
359
int lua_equal(lua_State* L, int index1, int index2)
360
{
361
StkId o1, o2;
362
int i;
363
o1 = index2addr(L, index1);
364
o2 = index2addr(L, index2);
365
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
366
return i;
367
}
368
369
int lua_lessthan(lua_State* L, int index1, int index2)
370
{
371
StkId o1, o2;
372
int i;
373
o1 = index2addr(L, index1);
374
o2 = index2addr(L, index2);
375
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaV_lessthan(L, o1, o2);
376
return i;
377
}
378
379
double lua_tonumberx(lua_State* L, int idx, int* isnum)
380
{
381
TValue n;
382
const TValue* o = index2addr(L, idx);
383
if (tonumber(o, &n))
384
{
385
if (isnum)
386
*isnum = 1;
387
return nvalue(o);
388
}
389
else
390
{
391
if (isnum)
392
*isnum = 0;
393
return 0;
394
}
395
}
396
397
int lua_tointegerx(lua_State* L, int idx, int* isnum)
398
{
399
TValue n;
400
const TValue* o = index2addr(L, idx);
401
if (tonumber(o, &n))
402
{
403
int res;
404
double num = nvalue(o);
405
luai_num2int(res, num);
406
if (isnum)
407
*isnum = 1;
408
return res;
409
}
410
else
411
{
412
if (isnum)
413
*isnum = 0;
414
return 0;
415
}
416
}
417
418
unsigned lua_tounsignedx(lua_State* L, int idx, int* isnum)
419
{
420
TValue n;
421
const TValue* o = index2addr(L, idx);
422
if (tonumber(o, &n))
423
{
424
unsigned res;
425
double num = nvalue(o);
426
luai_num2unsigned(res, num);
427
if (isnum)
428
*isnum = 1;
429
return res;
430
}
431
else
432
{
433
if (isnum)
434
*isnum = 0;
435
return 0;
436
}
437
}
438
439
int lua_toboolean(lua_State* L, int idx)
440
{
441
const TValue* o = index2addr(L, idx);
442
return !l_isfalse(o);
443
}
444
445
int64_t lua_tointeger64(lua_State* L, int idx, int* isinteger)
446
{
447
const TValue* o = index2addr(L, idx);
448
if (ttisinteger(o))
449
{
450
if (isinteger)
451
*isinteger = 1;
452
return lvalue(o);
453
}
454
else
455
{
456
if (isinteger)
457
*isinteger = 0;
458
return 0;
459
}
460
}
461
462
const char* lua_tolstring(lua_State* L, int idx, size_t* len)
463
{
464
StkId o = index2addr(L, idx);
465
if (!ttisstring(o))
466
{
467
luaC_threadbarrier(L);
468
if (!luaV_tostring(L, o))
469
{ // conversion failed?
470
if (len != NULL)
471
*len = 0;
472
return NULL;
473
}
474
luaC_checkGC(L);
475
o = index2addr(L, idx); // previous call may reallocate the stack
476
}
477
if (len != NULL)
478
*len = tsvalue(o)->len;
479
return svalue(o);
480
}
481
482
const char* lua_tostringatom(lua_State* L, int idx, int* atom)
483
{
484
StkId o = index2addr(L, idx);
485
if (!ttisstring(o))
486
return NULL;
487
TString* s = tsvalue(o);
488
if (atom)
489
{
490
updateatom(L, s);
491
*atom = s->atom;
492
}
493
return getstr(s);
494
}
495
496
const char* lua_tolstringatom(lua_State* L, int idx, size_t* len, int* atom)
497
{
498
StkId o = index2addr(L, idx);
499
500
if (!ttisstring(o))
501
{
502
if (len)
503
*len = 0;
504
return NULL;
505
}
506
507
TString* s = tsvalue(o);
508
if (len)
509
*len = s->len;
510
if (atom)
511
{
512
updateatom(L, s);
513
*atom = s->atom;
514
}
515
516
return getstr(s);
517
}
518
519
const char* lua_namecallatom(lua_State* L, int* atom)
520
{
521
TString* s = L->namecall;
522
if (!s)
523
return NULL;
524
if (atom)
525
{
526
updateatom(L, s);
527
*atom = s->atom;
528
}
529
return getstr(s);
530
}
531
532
const float* lua_tovector(lua_State* L, int idx)
533
{
534
StkId o = index2addr(L, idx);
535
if (!ttisvector(o))
536
return NULL;
537
return vvalue(o);
538
}
539
540
int lua_objlen(lua_State* L, int idx)
541
{
542
StkId o = index2addr(L, idx);
543
switch (ttype(o))
544
{
545
case LUA_TSTRING:
546
return tsvalue(o)->len;
547
case LUA_TUSERDATA:
548
return uvalue(o)->len;
549
case LUA_TBUFFER:
550
return bufvalue(o)->len;
551
case LUA_TTABLE:
552
return luaH_getn(hvalue(o));
553
default:
554
return 0;
555
}
556
}
557
558
lua_CFunction lua_tocfunction(lua_State* L, int idx)
559
{
560
StkId o = index2addr(L, idx);
561
return (!iscfunction(o)) ? NULL : cast_to(lua_CFunction, clvalue(o)->c.f);
562
}
563
564
void* lua_tolightuserdata(lua_State* L, int idx)
565
{
566
StkId o = index2addr(L, idx);
567
return (!ttislightuserdata(o)) ? NULL : pvalue(o);
568
}
569
570
void* lua_tolightuserdatatagged(lua_State* L, int idx, int tag)
571
{
572
StkId o = index2addr(L, idx);
573
return (!ttislightuserdata(o) || lightuserdatatag(o) != tag) ? NULL : pvalue(o);
574
}
575
576
void* lua_touserdata(lua_State* L, int idx)
577
{
578
StkId o = index2addr(L, idx);
579
if (ttisuserdata(o))
580
return uvalue(o)->data;
581
else if (ttislightuserdata(o))
582
return pvalue(o);
583
else
584
return NULL;
585
}
586
587
void* lua_touserdatatagged(lua_State* L, int idx, int tag)
588
{
589
StkId o = index2addr(L, idx);
590
return (ttisuserdata(o) && uvalue(o)->tag == tag) ? uvalue(o)->data : NULL;
591
}
592
593
int lua_userdatatag(lua_State* L, int idx)
594
{
595
StkId o = index2addr(L, idx);
596
if (ttisuserdata(o))
597
return uvalue(o)->tag;
598
return -1;
599
}
600
601
int lua_lightuserdatatag(lua_State* L, int idx)
602
{
603
StkId o = index2addr(L, idx);
604
if (ttislightuserdata(o))
605
return lightuserdatatag(o);
606
return -1;
607
}
608
609
lua_State* lua_tothread(lua_State* L, int idx)
610
{
611
StkId o = index2addr(L, idx);
612
return (!ttisthread(o)) ? NULL : thvalue(o);
613
}
614
615
void* lua_tobuffer(lua_State* L, int idx, size_t* len)
616
{
617
StkId o = index2addr(L, idx);
618
619
if (!ttisbuffer(o))
620
return NULL;
621
622
Buffer* b = bufvalue(o);
623
624
if (len)
625
*len = b->len;
626
627
return b->data;
628
}
629
630
const void* lua_topointer(lua_State* L, int idx)
631
{
632
StkId o = index2addr(L, idx);
633
switch (ttype(o))
634
{
635
case LUA_TUSERDATA:
636
return uvalue(o)->data;
637
case LUA_TLIGHTUSERDATA:
638
return pvalue(o);
639
default:
640
return iscollectable(o) ? gcvalue(o) : NULL;
641
}
642
}
643
644
/*
645
** push functions (C -> stack)
646
*/
647
648
void lua_pushnil(lua_State* L)
649
{
650
setnilvalue(L->top);
651
api_incr_top(L);
652
}
653
654
void lua_pushnumber(lua_State* L, double n)
655
{
656
setnvalue(L->top, n);
657
api_incr_top(L);
658
}
659
660
void lua_pushinteger(lua_State* L, int n)
661
{
662
setnvalue(L->top, cast_num(n));
663
api_incr_top(L);
664
}
665
666
void lua_pushinteger64(lua_State* L, int64_t n)
667
{
668
setlvalue(L->top, n);
669
api_incr_top(L);
670
}
671
672
void lua_pushunsigned(lua_State* L, unsigned u)
673
{
674
setnvalue(L->top, cast_num(u));
675
api_incr_top(L);
676
}
677
678
#if LUA_VECTOR_SIZE == 4
679
void lua_pushvector(lua_State* L, float x, float y, float z, float w)
680
{
681
setvvalue(L->top, x, y, z, w);
682
api_incr_top(L);
683
}
684
#else
685
void lua_pushvector(lua_State* L, float x, float y, float z)
686
{
687
setvvalue(L->top, x, y, z, 0.0f);
688
api_incr_top(L);
689
}
690
#endif
691
692
void lua_pushlstring(lua_State* L, const char* s, size_t len)
693
{
694
luaC_checkGC(L);
695
luaC_threadbarrier(L);
696
setsvalue(L, L->top, luaS_newlstr(L, s, len));
697
api_incr_top(L);
698
}
699
700
void lua_pushstring(lua_State* L, const char* s)
701
{
702
if (s == NULL)
703
lua_pushnil(L);
704
else
705
lua_pushlstring(L, s, strlen(s));
706
}
707
708
const char* lua_pushvfstring(lua_State* L, const char* fmt, va_list argp)
709
{
710
luaC_checkGC(L);
711
luaC_threadbarrier(L);
712
const char* ret = luaO_pushvfstring(L, fmt, argp);
713
return ret;
714
}
715
716
const char* lua_pushfstringL(lua_State* L, const char* fmt, ...)
717
{
718
luaC_checkGC(L);
719
luaC_threadbarrier(L);
720
va_list argp;
721
va_start(argp, fmt);
722
const char* ret = luaO_pushvfstring(L, fmt, argp);
723
va_end(argp);
724
return ret;
725
}
726
727
void lua_pushcclosurek(lua_State* L, lua_CFunction fn, const char* debugname, int nup, lua_Continuation cont)
728
{
729
luaC_checkGC(L);
730
luaC_threadbarrier(L);
731
api_checknelems(L, nup);
732
Closure* cl = luaF_newCclosure(L, nup, getcurrenv(L));
733
cl->c.f = fn;
734
cl->c.cont = cont;
735
cl->c.debugname = debugname;
736
L->top -= nup;
737
while (nup--)
738
setobj2n(L, &cl->c.upvals[nup], L->top + nup);
739
setclvalue(L, L->top, cl);
740
LUAU_ASSERT(iswhite(obj2gco(cl)));
741
api_incr_top(L);
742
}
743
744
void lua_pushboolean(lua_State* L, int b)
745
{
746
setbvalue(L->top, (b != 0)); // ensure that true is 1
747
api_incr_top(L);
748
}
749
750
void lua_pushlightuserdatatagged(lua_State* L, void* p, int tag)
751
{
752
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
753
setpvalue(L->top, p, tag);
754
api_incr_top(L);
755
}
756
757
int lua_pushthread(lua_State* L)
758
{
759
luaC_threadbarrier(L);
760
setthvalue(L, L->top, L);
761
api_incr_top(L);
762
return L->global->mainthread == L;
763
}
764
765
/*
766
** get functions (Lua -> stack)
767
*/
768
769
int lua_gettable(lua_State* L, int idx)
770
{
771
luaC_threadbarrier(L);
772
StkId t = index2addr(L, idx);
773
api_checkvalidindex(L, t);
774
luaV_gettable(L, t, L->top - 1, L->top - 1);
775
return ttype(L->top - 1);
776
}
777
778
int lua_getfield(lua_State* L, int idx, const char* k)
779
{
780
luaC_threadbarrier(L);
781
StkId t = index2addr(L, idx);
782
api_checkvalidindex(L, t);
783
TValue key;
784
setsvalue(L, &key, luaS_new(L, k));
785
luaV_gettable(L, t, &key, L->top);
786
api_incr_top(L);
787
return ttype(L->top - 1);
788
}
789
790
int lua_rawgetfield(lua_State* L, int idx, const char* k)
791
{
792
luaC_threadbarrier(L);
793
StkId t = index2addr(L, idx);
794
api_check(L, ttistable(t));
795
TValue key;
796
setsvalue(L, &key, luaS_new(L, k));
797
setobj2s(L, L->top, luaH_getstr(hvalue(t), tsvalue(&key)));
798
api_incr_top(L);
799
return ttype(L->top - 1);
800
}
801
802
int lua_rawget(lua_State* L, int idx)
803
{
804
luaC_threadbarrier(L);
805
StkId t = index2addr(L, idx);
806
api_check(L, ttistable(t));
807
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
808
return ttype(L->top - 1);
809
}
810
811
int lua_rawgeti(lua_State* L, int idx, int n)
812
{
813
luaC_threadbarrier(L);
814
StkId t = index2addr(L, idx);
815
api_check(L, ttistable(t));
816
setobj2s(L, L->top, luaH_getnum(hvalue(t), n));
817
api_incr_top(L);
818
return ttype(L->top - 1);
819
}
820
821
int lua_rawgetptagged(lua_State* L, int idx, void* p, int tag)
822
{
823
luaC_threadbarrier(L);
824
StkId t = index2addr(L, idx);
825
api_check(L, ttistable(t));
826
setobj2s(L, L->top, luaH_getp(hvalue(t), p, tag));
827
api_incr_top(L);
828
return ttype(L->top - 1);
829
}
830
831
void lua_createtable(lua_State* L, int narray, int nrec)
832
{
833
luaC_checkGC(L);
834
luaC_threadbarrier(L);
835
sethvalue(L, L->top, luaH_new(L, narray, nrec));
836
api_incr_top(L);
837
}
838
839
void lua_setreadonly(lua_State* L, int objindex, int enabled)
840
{
841
const TValue* o = index2addr(L, objindex);
842
api_check(L, ttistable(o));
843
LuaTable* t = hvalue(o);
844
api_check(L, t != hvalue(registry(L)));
845
t->readonly = bool(enabled);
846
}
847
848
int lua_getreadonly(lua_State* L, int objindex)
849
{
850
const TValue* o = index2addr(L, objindex);
851
api_check(L, ttistable(o));
852
LuaTable* t = hvalue(o);
853
int res = t->readonly;
854
return res;
855
}
856
857
void lua_setsafeenv(lua_State* L, int objindex, int enabled)
858
{
859
const TValue* o = index2addr(L, objindex);
860
api_check(L, ttistable(o));
861
LuaTable* t = hvalue(o);
862
t->safeenv = bool(enabled);
863
}
864
865
int lua_getmetatable(lua_State* L, int objindex)
866
{
867
luaC_threadbarrier(L);
868
LuaTable* mt = NULL;
869
const TValue* obj = index2addr(L, objindex);
870
switch (ttype(obj))
871
{
872
case LUA_TTABLE:
873
mt = hvalue(obj)->metatable;
874
break;
875
case LUA_TUSERDATA:
876
mt = uvalue(obj)->metatable;
877
break;
878
default:
879
mt = L->global->mt[ttype(obj)];
880
break;
881
}
882
if (mt)
883
{
884
sethvalue(L, L->top, mt);
885
api_incr_top(L);
886
}
887
return mt != NULL;
888
}
889
890
void lua_getfenv(lua_State* L, int idx)
891
{
892
luaC_threadbarrier(L);
893
StkId o = index2addr(L, idx);
894
api_checkvalidindex(L, o);
895
switch (ttype(o))
896
{
897
case LUA_TFUNCTION:
898
sethvalue(L, L->top, clvalue(o)->env);
899
break;
900
case LUA_TTHREAD:
901
sethvalue(L, L->top, thvalue(o)->gt);
902
break;
903
default:
904
setnilvalue(L->top);
905
break;
906
}
907
api_incr_top(L);
908
}
909
910
/*
911
** set functions (stack -> Lua)
912
*/
913
914
void lua_settable(lua_State* L, int idx)
915
{
916
api_checknelems(L, 2);
917
StkId t = index2addr(L, idx);
918
api_checkvalidindex(L, t);
919
luaV_settable(L, t, L->top - 2, L->top - 1);
920
L->top -= 2; // pop index and value
921
}
922
923
void lua_setfield(lua_State* L, int idx, const char* k)
924
{
925
api_checknelems(L, 1);
926
StkId t = index2addr(L, idx);
927
api_checkvalidindex(L, t);
928
TValue key;
929
setsvalue(L, &key, luaS_new(L, k));
930
luaV_settable(L, t, &key, L->top - 1);
931
L->top--;
932
}
933
934
void lua_rawsetfield(lua_State* L, int idx, const char* k)
935
{
936
api_checknelems(L, 1);
937
StkId t = index2addr(L, idx);
938
api_check(L, ttistable(t));
939
if (hvalue(t)->readonly)
940
luaG_readonlyerror(L);
941
setobj2t(L, luaH_setstr(L, hvalue(t), luaS_new(L, k)), L->top - 1);
942
luaC_barriert(L, hvalue(t), L->top - 1);
943
L->top--;
944
}
945
946
void lua_rawset(lua_State* L, int idx)
947
{
948
api_checknelems(L, 2);
949
StkId t = index2addr(L, idx);
950
api_check(L, ttistable(t));
951
if (hvalue(t)->readonly)
952
luaG_readonlyerror(L);
953
setobj2t(L, luaH_set(L, hvalue(t), L->top - 2), L->top - 1);
954
luaC_barriert(L, hvalue(t), L->top - 1);
955
L->top -= 2;
956
}
957
958
void lua_rawseti(lua_State* L, int idx, int n)
959
{
960
api_checknelems(L, 1);
961
StkId o = index2addr(L, idx);
962
api_check(L, ttistable(o));
963
if (hvalue(o)->readonly)
964
luaG_readonlyerror(L);
965
setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top - 1);
966
luaC_barriert(L, hvalue(o), L->top - 1);
967
L->top--;
968
}
969
970
void lua_rawsetptagged(lua_State* L, int idx, void* p, int tag)
971
{
972
api_checknelems(L, 1);
973
StkId o = index2addr(L, idx);
974
api_check(L, ttistable(o));
975
if (hvalue(o)->readonly)
976
luaG_readonlyerror(L);
977
setobj2t(L, luaH_setp(L, hvalue(o), p, tag), L->top - 1);
978
luaC_barriert(L, hvalue(o), L->top - 1);
979
L->top--;
980
}
981
982
int lua_setmetatable(lua_State* L, int objindex)
983
{
984
api_checknelems(L, 1);
985
TValue* obj = index2addr(L, objindex);
986
api_checkvalidindex(L, obj);
987
LuaTable* mt = NULL;
988
if (!ttisnil(L->top - 1))
989
{
990
api_check(L, ttistable(L->top - 1));
991
mt = hvalue(L->top - 1);
992
}
993
switch (ttype(obj))
994
{
995
case LUA_TTABLE:
996
{
997
if (hvalue(obj)->readonly)
998
luaG_readonlyerror(L);
999
hvalue(obj)->metatable = mt;
1000
if (mt)
1001
luaC_objbarrier(L, hvalue(obj), mt);
1002
break;
1003
}
1004
case LUA_TUSERDATA:
1005
{
1006
uvalue(obj)->metatable = mt;
1007
if (mt)
1008
luaC_objbarrier(L, uvalue(obj), mt);
1009
break;
1010
}
1011
default:
1012
{
1013
L->global->mt[ttype(obj)] = mt;
1014
break;
1015
}
1016
}
1017
L->top--;
1018
return 1;
1019
}
1020
1021
int lua_setfenv(lua_State* L, int idx)
1022
{
1023
int res = 1;
1024
api_checknelems(L, 1);
1025
StkId o = index2addr(L, idx);
1026
api_checkvalidindex(L, o);
1027
api_check(L, ttistable(L->top - 1));
1028
switch (ttype(o))
1029
{
1030
case LUA_TFUNCTION:
1031
clvalue(o)->env = hvalue(L->top - 1);
1032
break;
1033
case LUA_TTHREAD:
1034
thvalue(o)->gt = hvalue(L->top - 1);
1035
break;
1036
default:
1037
res = 0;
1038
break;
1039
}
1040
if (res)
1041
{
1042
luaC_objbarrier(L, &gcvalue(o)->gch, hvalue(L->top - 1));
1043
}
1044
L->top--;
1045
return res;
1046
}
1047
1048
/*
1049
** `load' and `call' functions (run Lua code)
1050
*/
1051
1052
#define adjustresults(L, nres) \
1053
{ \
1054
if (nres == LUA_MULTRET && L->top >= L->ci->top) \
1055
L->ci->top = L->top; \
1056
}
1057
1058
#define checkresults(L, na, nr) api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
1059
1060
void lua_call(lua_State* L, int nargs, int nresults)
1061
{
1062
StkId func;
1063
api_checknelems(L, nargs + 1);
1064
api_check(L, L->status == 0);
1065
checkresults(L, nargs, nresults);
1066
func = L->top - (nargs + 1);
1067
1068
luaD_call(L, func, nresults);
1069
1070
adjustresults(L, nresults);
1071
}
1072
1073
/*
1074
** Execute a protected call.
1075
*/
1076
// data to `f_call'
1077
struct CallS
1078
{
1079
StkId func;
1080
int nresults;
1081
};
1082
1083
static void f_call(lua_State* L, void* ud)
1084
{
1085
struct CallS* c = cast_to(struct CallS*, ud);
1086
luaD_call(L, c->func, c->nresults);
1087
}
1088
1089
int lua_pcall(lua_State* L, int nargs, int nresults, int errfunc)
1090
{
1091
api_checknelems(L, nargs + 1);
1092
api_check(L, L->status == 0);
1093
checkresults(L, nargs, nresults);
1094
ptrdiff_t func = 0;
1095
if (errfunc != 0)
1096
{
1097
StkId o = index2addr(L, errfunc);
1098
api_checkvalidindex(L, o);
1099
func = savestack(L, o);
1100
}
1101
struct CallS c;
1102
c.func = L->top - (nargs + 1); // function to be called
1103
c.nresults = nresults;
1104
1105
int status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
1106
1107
adjustresults(L, nresults);
1108
return status;
1109
}
1110
1111
/*
1112
** Execute a protected C call.
1113
*/
1114
// data to `f_Ccall'
1115
struct CCallS
1116
{
1117
lua_CFunction func;
1118
void* ud;
1119
};
1120
1121
static void f_Ccall(lua_State* L, void* ud)
1122
{
1123
struct CCallS* c = cast_to(struct CCallS*, ud);
1124
1125
if (!lua_checkstack(L, 2))
1126
luaG_runerror(L, "stack limit");
1127
1128
lua_pushcclosurek(L, c->func, nullptr, 0, nullptr);
1129
lua_pushlightuserdata(L, c->ud);
1130
luaD_call(L, L->top - 2, 0);
1131
}
1132
1133
int lua_cpcall(lua_State* L, lua_CFunction func, void* ud)
1134
{
1135
api_check(L, L->status == 0);
1136
1137
struct CCallS c;
1138
c.func = func;
1139
c.ud = ud;
1140
1141
return luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
1142
}
1143
1144
int lua_status(lua_State* L)
1145
{
1146
return L->status;
1147
}
1148
1149
int lua_costatus(lua_State* L, lua_State* co)
1150
{
1151
if (co == L)
1152
return LUA_CORUN;
1153
if (co->status == LUA_YIELD)
1154
return LUA_COSUS;
1155
if (co->status == LUA_BREAK)
1156
return LUA_CONOR;
1157
if (co->status != 0) // some error occurred
1158
return LUA_COERR;
1159
if (co->ci != co->base_ci) // does it have frames?
1160
return LUA_CONOR;
1161
if (co->top == co->base)
1162
return LUA_COFIN;
1163
return LUA_COSUS; // initial state
1164
}
1165
1166
void* lua_getthreaddata(lua_State* L)
1167
{
1168
return L->userdata;
1169
}
1170
1171
void lua_setthreaddata(lua_State* L, void* data)
1172
{
1173
L->userdata = data;
1174
}
1175
1176
/*
1177
** Garbage-collection function
1178
*/
1179
1180
int lua_gc(lua_State* L, int what, int data)
1181
{
1182
int res = 0;
1183
condhardmemtests(luaC_validate(L), 1);
1184
global_State* g = L->global;
1185
switch (what)
1186
{
1187
case LUA_GCSTOP:
1188
{
1189
g->GCthreshold = SIZE_MAX;
1190
break;
1191
}
1192
case LUA_GCRESTART:
1193
{
1194
g->GCthreshold = g->totalbytes;
1195
break;
1196
}
1197
case LUA_GCCOLLECT:
1198
{
1199
luaC_fullgc(L);
1200
break;
1201
}
1202
case LUA_GCCOUNT:
1203
{
1204
// GC values are expressed in Kbytes: #bytes/2^10
1205
res = cast_int(g->totalbytes >> 10);
1206
break;
1207
}
1208
case LUA_GCCOUNTB:
1209
{
1210
res = cast_int(g->totalbytes & 1023);
1211
break;
1212
}
1213
case LUA_GCISRUNNING:
1214
{
1215
res = (g->GCthreshold != SIZE_MAX);
1216
break;
1217
}
1218
case LUA_GCSTEP:
1219
{
1220
size_t amount = (cast_to(size_t, data) << 10);
1221
ptrdiff_t oldcredit = g->gcstate == GCSpause ? 0 : g->GCthreshold - g->totalbytes;
1222
1223
// temporarily adjust the threshold so that we can perform GC work
1224
if (amount <= g->totalbytes)
1225
g->GCthreshold = g->totalbytes - amount;
1226
else
1227
g->GCthreshold = 0;
1228
1229
#ifdef LUAI_GCMETRICS
1230
double startmarktime = g->gcmetrics.currcycle.marktime;
1231
double startsweeptime = g->gcmetrics.currcycle.sweeptime;
1232
#endif
1233
1234
// track how much work the loop will actually perform
1235
size_t actualwork = 0;
1236
1237
while (g->GCthreshold <= g->totalbytes)
1238
{
1239
size_t stepsize = luaC_step(L, false);
1240
1241
actualwork += stepsize;
1242
1243
if (g->gcstate == GCSpause)
1244
{ // end of cycle?
1245
res = 1; // signal it
1246
break;
1247
}
1248
}
1249
1250
#ifdef LUAI_GCMETRICS
1251
// record explicit step statistics
1252
GCCycleMetrics* cyclemetrics = g->gcstate == GCSpause ? &g->gcmetrics.lastcycle : &g->gcmetrics.currcycle;
1253
1254
double totalmarktime = cyclemetrics->marktime - startmarktime;
1255
double totalsweeptime = cyclemetrics->sweeptime - startsweeptime;
1256
1257
if (totalmarktime > 0.0)
1258
{
1259
cyclemetrics->markexplicitsteps++;
1260
1261
if (totalmarktime > cyclemetrics->markmaxexplicittime)
1262
cyclemetrics->markmaxexplicittime = totalmarktime;
1263
}
1264
1265
if (totalsweeptime > 0.0)
1266
{
1267
cyclemetrics->sweepexplicitsteps++;
1268
1269
if (totalsweeptime > cyclemetrics->sweepmaxexplicittime)
1270
cyclemetrics->sweepmaxexplicittime = totalsweeptime;
1271
}
1272
#endif
1273
1274
// if cycle hasn't finished, advance threshold forward for the amount of extra work performed
1275
if (g->gcstate != GCSpause)
1276
{
1277
// if a new cycle was triggered by explicit step, old 'credit' of GC work is 0
1278
ptrdiff_t newthreshold = g->totalbytes + actualwork + oldcredit;
1279
g->GCthreshold = newthreshold < 0 ? 0 : newthreshold;
1280
}
1281
break;
1282
}
1283
case LUA_GCSETGOAL:
1284
{
1285
res = g->gcgoal;
1286
g->gcgoal = data;
1287
break;
1288
}
1289
case LUA_GCSETSTEPMUL:
1290
{
1291
res = g->gcstepmul;
1292
g->gcstepmul = data;
1293
break;
1294
}
1295
case LUA_GCSETSTEPSIZE:
1296
{
1297
// GC values are expressed in Kbytes: #bytes/2^10
1298
res = g->gcstepsize >> 10;
1299
g->gcstepsize = data << 10;
1300
break;
1301
}
1302
default:
1303
res = -1; // invalid option
1304
}
1305
return res;
1306
}
1307
1308
/*
1309
** miscellaneous functions
1310
*/
1311
1312
l_noret lua_error(lua_State* L)
1313
{
1314
api_checknelems(L, 1);
1315
1316
luaD_throw(L, LUA_ERRRUN);
1317
}
1318
1319
int lua_next(lua_State* L, int idx)
1320
{
1321
luaC_threadbarrier(L);
1322
StkId t = index2addr(L, idx);
1323
api_check(L, ttistable(t));
1324
int more = luaH_next(L, hvalue(t), L->top - 1);
1325
if (more)
1326
{
1327
api_incr_top(L);
1328
}
1329
else // no more elements
1330
L->top -= 1; // remove key
1331
return more;
1332
}
1333
1334
int lua_rawiter(lua_State* L, int idx, int iter)
1335
{
1336
luaC_threadbarrier(L);
1337
StkId t = index2addr(L, idx);
1338
api_check(L, ttistable(t));
1339
api_check(L, iter >= 0);
1340
1341
LuaTable* h = hvalue(t);
1342
int sizearray = h->sizearray;
1343
1344
// first we advance iter through the array portion
1345
for (; unsigned(iter) < unsigned(sizearray); ++iter)
1346
{
1347
TValue* e = &h->array[iter];
1348
1349
if (!ttisnil(e))
1350
{
1351
StkId top = L->top;
1352
setnvalue(top + 0, double(iter + 1));
1353
setobj2s(L, top + 1, e);
1354
api_update_top(L, top + 2);
1355
return iter + 1;
1356
}
1357
}
1358
1359
int sizenode = 1 << h->lsizenode;
1360
1361
// then we advance iter through the hash portion
1362
for (; unsigned(iter - sizearray) < unsigned(sizenode); ++iter)
1363
{
1364
LuaNode* n = &h->node[iter - sizearray];
1365
1366
if (!ttisnil(gval(n)))
1367
{
1368
StkId top = L->top;
1369
getnodekey(L, top + 0, n);
1370
setobj2s(L, top + 1, gval(n));
1371
api_update_top(L, top + 2);
1372
return iter + 1;
1373
}
1374
}
1375
1376
// traversal finished
1377
return -1;
1378
}
1379
1380
void lua_concat(lua_State* L, int n)
1381
{
1382
api_checknelems(L, n);
1383
if (n >= 2)
1384
{
1385
luaC_checkGC(L);
1386
luaC_threadbarrier(L);
1387
luaV_concat(L, n, cast_int(L->top - L->base) - 1);
1388
L->top -= (n - 1);
1389
}
1390
else if (n == 0)
1391
{ // push empty string
1392
luaC_threadbarrier(L);
1393
setsvalue(L, L->top, luaS_newlstr(L, "", 0));
1394
api_incr_top(L);
1395
}
1396
// else n == 1; nothing to do
1397
}
1398
1399
void* lua_newuserdatatagged(lua_State* L, size_t sz, int tag)
1400
{
1401
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT || tag == UTAG_PROXY);
1402
luaC_checkGC(L);
1403
luaC_threadbarrier(L);
1404
Udata* u = luaU_newudata(L, sz, tag);
1405
setuvalue(L, L->top, u);
1406
api_incr_top(L);
1407
return u->data;
1408
}
1409
1410
void* lua_newuserdatataggedwithmetatable(lua_State* L, size_t sz, int tag)
1411
{
1412
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1413
luaC_checkGC(L);
1414
luaC_threadbarrier(L);
1415
Udata* u = luaU_newudata(L, sz, tag);
1416
1417
// currently, we always allocate unmarked objects, so forward barrier can be skipped
1418
LUAU_ASSERT(!isblack(obj2gco(u)));
1419
1420
LuaTable* h = L->global->udatamt[tag];
1421
api_check(L, h != nullptr);
1422
1423
u->metatable = h;
1424
1425
setuvalue(L, L->top, u);
1426
api_incr_top(L);
1427
return u->data;
1428
}
1429
1430
void* lua_newuserdatadtor(lua_State* L, size_t sz, void (*dtor)(void*))
1431
{
1432
luaC_checkGC(L);
1433
luaC_threadbarrier(L);
1434
// make sure sz + sizeof(dtor) doesn't overflow; luaU_newdata will reject SIZE_MAX correctly
1435
size_t as = sz < SIZE_MAX - sizeof(dtor) ? sz + sizeof(dtor) : SIZE_MAX;
1436
Udata* u = luaU_newudata(L, as, UTAG_IDTOR);
1437
memcpy(&u->data + sz, &dtor, sizeof(dtor));
1438
setuvalue(L, L->top, u);
1439
api_incr_top(L);
1440
return u->data;
1441
}
1442
1443
void* lua_newbuffer(lua_State* L, size_t sz)
1444
{
1445
luaC_checkGC(L);
1446
luaC_threadbarrier(L);
1447
Buffer* b = luaB_newbuffer(L, sz);
1448
setbufvalue(L, L->top, b);
1449
api_incr_top(L);
1450
return b->data;
1451
}
1452
1453
static const char* aux_upvalue(StkId fi, int n, TValue** val)
1454
{
1455
Closure* f;
1456
if (!ttisfunction(fi))
1457
return NULL;
1458
f = clvalue(fi);
1459
if (f->isC)
1460
{
1461
if (!(1 <= n && n <= f->nupvalues))
1462
return NULL;
1463
*val = &f->c.upvals[n - 1];
1464
return "";
1465
}
1466
else
1467
{
1468
Proto* p = f->l.p;
1469
if (!(1 <= n && n <= p->nups)) // not a valid upvalue
1470
return NULL;
1471
TValue* r = &f->l.uprefs[n - 1];
1472
*val = ttisupval(r) ? upvalue(r)->v : r;
1473
if (!(1 <= n && n <= p->sizeupvalues)) // don't have a name for this upvalue
1474
return "";
1475
return getstr(p->upvalues[n - 1]);
1476
}
1477
}
1478
1479
const char* lua_getupvalue(lua_State* L, int funcindex, int n)
1480
{
1481
luaC_threadbarrier(L);
1482
TValue* val;
1483
const char* name = aux_upvalue(index2addr(L, funcindex), n, &val);
1484
if (name)
1485
{
1486
setobj2s(L, L->top, val);
1487
api_incr_top(L);
1488
}
1489
return name;
1490
}
1491
1492
const char* lua_setupvalue(lua_State* L, int funcindex, int n)
1493
{
1494
api_checknelems(L, 1);
1495
StkId fi = index2addr(L, funcindex);
1496
TValue* val;
1497
const char* name = aux_upvalue(fi, n, &val);
1498
if (name)
1499
{
1500
L->top--;
1501
setobj(L, val, L->top);
1502
luaC_barrier(L, clvalue(fi), L->top);
1503
}
1504
return name;
1505
}
1506
1507
uintptr_t lua_encodepointer(lua_State* L, uintptr_t p)
1508
{
1509
global_State* g = L->global;
1510
return uintptr_t((g->ptrenckey[0] * p + g->ptrenckey[2]) ^ (g->ptrenckey[1] * p + g->ptrenckey[3]));
1511
}
1512
1513
int lua_ref(lua_State* L, int idx)
1514
{
1515
api_check(L, idx != LUA_REGISTRYINDEX); // idx is a stack index for value
1516
int ref = LUA_REFNIL;
1517
global_State* g = L->global;
1518
StkId p = index2addr(L, idx);
1519
if (!ttisnil(p))
1520
{
1521
LuaTable* reg = hvalue(registry(L));
1522
1523
if (g->registryfree != 0)
1524
{ // reuse existing slot
1525
ref = g->registryfree;
1526
}
1527
else
1528
{ // no free elements
1529
ref = luaH_getn(reg);
1530
ref++; // create new reference
1531
}
1532
1533
TValue* slot = luaH_setnum(L, reg, ref);
1534
if (g->registryfree != 0)
1535
g->registryfree = int(nvalue(slot));
1536
setobj2t(L, slot, p);
1537
luaC_barriert(L, reg, p);
1538
}
1539
return ref;
1540
}
1541
1542
void lua_unref(lua_State* L, int ref)
1543
{
1544
if (ref <= LUA_REFNIL)
1545
return;
1546
1547
global_State* g = L->global;
1548
LuaTable* reg = hvalue(registry(L));
1549
1550
const TValue* slot = luaH_getnum(reg, ref);
1551
api_check(L, slot != luaO_nilobject);
1552
1553
// similar to how 'luaH_setnum' makes non-nil slot value mutable
1554
TValue* mutableSlot = (TValue*)slot;
1555
1556
// NB: no barrier needed because value isn't collectable
1557
setnvalue(mutableSlot, g->registryfree);
1558
1559
g->registryfree = ref;
1560
}
1561
1562
void lua_setuserdatatag(lua_State* L, int idx, int tag)
1563
{
1564
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1565
StkId o = index2addr(L, idx);
1566
api_check(L, ttisuserdata(o));
1567
uvalue(o)->tag = uint8_t(tag);
1568
}
1569
1570
void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor)
1571
{
1572
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1573
L->global->udatagc[tag] = dtor;
1574
}
1575
1576
lua_Destructor lua_getuserdatadtor(lua_State* L, int tag)
1577
{
1578
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1579
return L->global->udatagc[tag];
1580
}
1581
1582
void lua_setuserdatametatable(lua_State* L, int tag)
1583
{
1584
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1585
api_check(L, !L->global->udatamt[tag]); // reassignment not supported
1586
api_check(L, ttistable(L->top - 1));
1587
L->global->udatamt[tag] = hvalue(L->top - 1);
1588
L->top--;
1589
}
1590
1591
void lua_getuserdatametatable(lua_State* L, int tag)
1592
{
1593
api_check(L, unsigned(tag) < LUA_UTAG_LIMIT);
1594
luaC_threadbarrier(L);
1595
1596
if (LuaTable* h = L->global->udatamt[tag])
1597
{
1598
sethvalue(L, L->top, h);
1599
}
1600
else
1601
{
1602
setnilvalue(L->top);
1603
}
1604
1605
api_incr_top(L);
1606
}
1607
1608
void lua_setlightuserdataname(lua_State* L, int tag, const char* name)
1609
{
1610
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
1611
api_check(L, !L->global->lightuserdataname[tag]); // renaming not supported
1612
if (!L->global->lightuserdataname[tag])
1613
{
1614
L->global->lightuserdataname[tag] = luaS_new(L, name);
1615
luaS_fix(L->global->lightuserdataname[tag]); // never collect these names
1616
}
1617
}
1618
1619
const char* lua_getlightuserdataname(lua_State* L, int tag)
1620
{
1621
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
1622
const TString* name = L->global->lightuserdataname[tag];
1623
return name ? getstr(name) : nullptr;
1624
}
1625
1626
void lua_clonefunction(lua_State* L, int idx)
1627
{
1628
luaC_checkGC(L);
1629
luaC_threadbarrier(L);
1630
StkId p = index2addr(L, idx);
1631
api_check(L, isLfunction(p));
1632
Closure* cl = clvalue(p);
1633
Closure* newcl = luaF_newLclosure(L, cl->nupvalues, L->gt, cl->l.p);
1634
for (int i = 0; i < cl->nupvalues; ++i)
1635
setobj2n(L, &newcl->l.uprefs[i], &cl->l.uprefs[i]);
1636
setclvalue(L, L->top, newcl);
1637
api_incr_top(L);
1638
}
1639
1640
void lua_cleartable(lua_State* L, int idx)
1641
{
1642
StkId t = index2addr(L, idx);
1643
api_check(L, ttistable(t));
1644
LuaTable* tt = hvalue(t);
1645
if (tt->readonly)
1646
luaG_readonlyerror(L);
1647
luaH_clear(tt);
1648
}
1649
1650
void lua_clonetable(lua_State* L, int idx)
1651
{
1652
StkId t = index2addr(L, idx);
1653
api_check(L, ttistable(t));
1654
1655
LuaTable* tt = luaH_clone(L, hvalue(t));
1656
sethvalue(L, L->top, tt);
1657
api_incr_top(L);
1658
}
1659
1660
lua_Callbacks* lua_callbacks(lua_State* L)
1661
{
1662
return &L->global->cb;
1663
}
1664
1665
void lua_setmemcat(lua_State* L, int category)
1666
{
1667
api_check(L, unsigned(category) < LUA_MEMORY_CATEGORIES);
1668
L->activememcat = uint8_t(category);
1669
}
1670
1671
size_t lua_totalbytes(lua_State* L, int category)
1672
{
1673
api_check(L, category < LUA_MEMORY_CATEGORIES);
1674
return category < 0 ? L->global->totalbytes : L->global->memcatbytes[category];
1675
}
1676
1677
lua_Alloc lua_getallocf(lua_State* L, void** ud)
1678
{
1679
lua_Alloc f = L->global->frealloc;
1680
if (ud)
1681
*ud = L->global->ud;
1682
return f;
1683
}
1684
1685