• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 7119175127

06 Dec 2023 06:58PM UTC coverage: 88.591% (-0.03%) from 88.621%
7119175127

push

github

igormunkin
Fix HREFK forwarding vs. table.clear().

Reported by XmiliaH.

(cherry-picked from commit d5a237eae)

When performing HREFK (and also ALOAD, HLOAD) forwarding optimization,
the `table.clear()` function call may be performed on the table operand
from HREFK between table creation and IR, from which value is forwarded.
This call isn't taken in the account, so it may lead to too optimistic
value-forwarding from NEWREF (and also ASTORE, HSTORE), or the omitted
type guard for HREFK operation. Therefore, this leads to incorrect trace
behaviour (for example, taking a non-nil value from the cleared table).

This patch adds necessary checks for `table.clear()` calls.

Sergey Kaplun:
* added the description and the test for the problem

Part of tarantool/tarantool#9145

Reviewed-by: Maxim Kokryashkin <m.kokryashkin@tarantool.org>
Reviewed-by: Sergey Bronnikov <sergeyb@tarantool.org>
Signed-off-by: Igor Munkin <imun@tarantool.org>

5377 of 5987 branches covered (0.0%)

Branch coverage included in aggregate %.

12 of 12 new or added lines in 1 file covered. (100.0%)

24 existing lines in 5 files now uncovered.

20619 of 23357 relevant lines covered (88.28%)

2754697.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.74
/src/lj_api.c
1
/*
2
** Public Lua/C API.
3
** Copyright (C) 2005-2017 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

34
static TValue *index2adr(lua_State *L, int idx)
25,238,644✔
35
{
36
  if (idx > 0) {
25,238,644✔
37
    TValue *o = L->base + (idx - 1);
9,555,024✔
38
    return o < L->top ? o : niltv(L);
9,555,024✔
39
  } else if (idx > LUA_REGISTRYINDEX) {
15,683,620✔
40
    lj_checkapi(idx != 0 && -idx <= L->top - L->base,
10,381,255✔
41
                "bad stack slot %d", idx);
42
    return L->top + idx;
10,381,255✔
43
  } else if (idx == LUA_GLOBALSINDEX) {
5,302,365✔
44
    TValue *o = &G(L)->tmptv;
5,030✔
45
    settabV(L, o, tabref(L->env));
5,030✔
46
    return o;
5,030✔
47
  } else if (idx == LUA_REGISTRYINDEX) {
5,297,335✔
48
    return registry(L);
4,294,596✔
49
  } else {
50
    GCfunc *fn = curr_func(L);
1,002,739✔
51
    lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
1,002,739✔
52
                "calling frame is not a C function");
53
    if (idx == LUA_ENVIRONINDEX) {
1,002,739✔
54
      TValue *o = &G(L)->tmptv;
1,781✔
55
      settabV(L, o, tabref(fn->c.env));
1,781✔
56
      return o;
1,781✔
57
    } else {
58
      idx = LUA_GLOBALSINDEX - idx;
1,000,958✔
59
      return idx <= fn->c.nupvalues ? &fn->c.upvalue[idx-1] : niltv(L);
1,000,958✔
60
    }
61
  }
62
}
63

64
static LJ_AINLINE TValue *index2adr_check(lua_State *L, int idx)
1,169,984✔
65
{
66
  TValue *o = index2adr(L, idx);
2,339,968✔
67
  lj_checkapi(o != niltv(L), "invalid stack slot %d", idx);
1,169,984✔
68
  return o;
1,169,984✔
69
}
70

71
static TValue *index2adr_stack(lua_State *L, int idx)
17,573✔
72
{
73
  if (idx > 0) {
17,573✔
74
    TValue *o = L->base + (idx - 1);
1,432✔
75
    if (o < L->top) {
1,432✔
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,
16,141✔
84
                "invalid stack slot %d", idx);
85
    return L->top + idx;
16,141✔
86
  }
87
}
88

89
static GCtab *getcurrenv(lua_State *L)
1,015,340✔
90
{
91
  GCfunc *fn = curr_func(L);
1,015,340✔
92
  return fn->c.gct == ~LJ_TFUNC ? tabref(fn->c.env) : tabref(L->env);
1,015,340✔
93
}
94

95
static void jit_secure_call(lua_State *L, TValue *base, int nres) {
5,209,837✔
96
  global_State *g = G(L);
5,209,837✔
97
  /* Forbid Lua world re-entrancy while running the trace */
98
  if (tvref(g->jit_base)) {
5,209,837✔
99
    setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITCALL));
1✔
100
    if (g->panic) g->panic(L);
1✔
101
    exit(EXIT_FAILURE);
1✔
102
  }
103
  lj_trace_abort(g);  /* Never record across Lua VM entrance */
5,209,836✔
104
  lj_vm_call(L, base, nres);
5,209,836✔
105
}
5,209,833✔
106

107
/* -- Miscellaneous API functions ----------------------------------------- */
108

109
LUA_API int lua_status(lua_State *L)
×
110
{
111
  return L->status;
×
112
}
113

114
LUA_API int lua_checkstack(lua_State *L, int size)
14,493✔
115
{
116
  if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) {
14,493✔
117
    return 0;  /* Stack overflow. */
118
  } else if (size > 0) {
14,493✔
119
    lj_state_checkstack(L, (MSize)size);
13,724✔
120
  }
121
  return 1;
122
}
123

124
LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
14,437✔
125
{
126
  if (!lua_checkstack(L, size))
14,437✔
127
    lj_err_callerv(L, LJ_ERR_STKOVM, msg);
×
128
}
14,437✔
129

130
LUA_API void lua_xmove(lua_State *L, lua_State *to, int n)
17✔
131
{
132
  TValue *f, *t;
17✔
133
  if (L == to) return;
17✔
134
  lj_checkapi_slot(n);
4✔
135
  lj_checkapi(G(L) == G(to), "move across global states");
4✔
136
  lj_state_checkstack(to, (MSize)n);
4✔
137
  f = L->top;
4✔
138
  t = to->top = to->top + n;
4✔
139
  while (--n >= 0) copyTV(to, --t, --f);
8✔
140
  L->top = f;
4✔
141
}
142

143
LUA_API const lua_Number *lua_version(lua_State *L)
×
144
{
145
  static const lua_Number version = LUA_VERSION_NUM;
×
146
  UNUSED(L);
×
147
  return &version;
×
148
}
149

150
/* -- Stack manipulation -------------------------------------------------- */
151

152
LUA_API int lua_gettop(lua_State *L)
567✔
153
{
154
  return (int)(L->top - L->base);
567✔
155
}
156

157
LUA_API void lua_settop(lua_State *L, int idx)
3,111,466✔
158
{
159
  if (idx >= 0) {
3,111,466✔
160
    lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx);
1,061,820✔
161
    if (L->base + idx > L->top) {
1,061,820✔
162
      if (L->base + idx >= tvref(L->maxstack))
59,808✔
163
        lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
×
164
      do { setnilV(L->top++); } while (L->top < L->base + idx);
161,853✔
165
    } else {
166
      L->top = L->base + idx;
1,002,012✔
167
    }
168
  } else {
169
    lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx);
2,049,646✔
170
    L->top += idx+1;  /* Shrinks top (idx < 0). */
2,049,646✔
171
  }
172
}
3,111,466✔
173

174
LUA_API void lua_remove(lua_State *L, int idx)
16,140✔
175
{
176
  TValue *p = index2adr_stack(L, idx);
16,140✔
177
  while (++p < L->top) copyTV(L, p-1, p);
31,880✔
178
  L->top--;
16,140✔
179
}
16,140✔
180

181
LUA_API void lua_insert(lua_State *L, int idx)
923✔
182
{
183
  TValue *q, *p = index2adr_stack(L, idx);
923✔
184
  for (q = L->top; q > p; q--) copyTV(L, q, q-1);
2,604✔
185
  copyTV(L, p, L->top);
923✔
186
}
923✔
187

188
static void copy_slot(lua_State *L, TValue *f, int idx)
269✔
189
{
190
  if (idx == LUA_GLOBALSINDEX) {
269✔
191
    lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
×
192
    /* NOBARRIER: A thread (i.e. L) is never black. */
193
    setgcref(L->env, obj2gco(tabV(f)));
×
194
  } else if (idx == LUA_ENVIRONINDEX) {
269✔
195
    GCfunc *fn = curr_func(L);
269✔
196
    if (fn->c.gct != ~LJ_TFUNC)
269✔
197
      lj_err_msg(L, LJ_ERR_NOENV);
×
198
    lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
269✔
199
    setgcref(fn->c.env, obj2gco(tabV(f)));
269✔
200
    lj_gc_barrier(L, fn, f);
269✔
201
  } else {
202
    TValue *o = index2adr_check(L, idx);
×
203
    copyTV(L, o, f);
×
204
    if (idx < LUA_GLOBALSINDEX)  /* Need a barrier for upvalues. */
×
205
      lj_gc_barrier(L, curr_func(L), f);
×
206
  }
207
}
269✔
208

209
LUA_API void lua_replace(lua_State *L, int idx)
×
210
{
211
  lj_checkapi_slot(1);
×
212
  copy_slot(L, L->top - 1, idx);
×
213
  L->top--;
×
214
}
×
215

216
LUA_API void lua_copy(lua_State *L, int fromidx, int toidx)
269✔
217
{
218
  copy_slot(L, index2adr(L, fromidx), toidx);
269✔
219
}
269✔
220

221
LUA_API void lua_pushvalue(lua_State *L, int idx)
3,762,960✔
222
{
223
  copyTV(L, L->top, index2adr(L, idx));
3,762,960✔
224
  incr_top(L);
3,762,960✔
225
}
3,762,960✔
226

227
/* -- Stack getters ------------------------------------------------------- */
228

229
LUA_API int lua_type(lua_State *L, int idx)
7,323,968✔
230
{
231
  cTValue *o = index2adr(L, idx);
7,323,968✔
232
  if (tvisnumber(o)) {
7,323,968✔
233
    return LUA_TNUMBER;
234
#if LJ_64 && !LJ_GC64
235
  } else if (tvislightud(o)) {
236
    return LUA_TLIGHTUSERDATA;
237
#endif
238
  } else if (o == niltv(L)) {
7,323,945✔
239
    return LUA_TNONE;
240
  } else {  /* Magic internal/external tag conversion. ORDER LJ_T */
241
    uint32_t t = ~itype(o);
7,323,915✔
242
#if LJ_64
243
    int tt = (int)((U64x(75a06,98042110) >> 4*t) & 15u);
7,323,915✔
244
#else
245
    int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
246
#endif
247
    lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion");
7,323,915✔
248
    return tt;
7,323,915✔
249
  }
250
}
251

252
LUALIB_API void luaL_checktype(lua_State *L, int idx, int tt)
42✔
253
{
254
  if (lua_type(L, idx) != tt)
42✔
255
    lj_err_argt(L, idx, tt);
×
256
}
42✔
257

258
LUALIB_API void luaL_checkany(lua_State *L, int idx)
×
259
{
260
  if (index2adr(L, idx) == niltv(L))
×
261
    lj_err_arg(L, idx, LJ_ERR_NOVAL);
×
262
}
×
263

264
LUA_API const char *lua_typename(lua_State *L, int t)
1✔
265
{
266
  UNUSED(L);
1✔
267
  return lj_obj_typename[t+1];
1✔
268
}
269

270
LUA_API int lua_iscfunction(lua_State *L, int idx)
12✔
271
{
272
  cTValue *o = index2adr(L, idx);
12✔
273
  return tvisfunc(o) && !isluafunc(funcV(o));
12✔
274
}
275

276
LUA_API int lua_isnumber(lua_State *L, int idx)
71,269✔
277
{
278
  cTValue *o = index2adr(L, idx);
71,269✔
279
  TValue tmp;
71,269✔
280
  return (tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), &tmp)));
71,269✔
281
}
282

283
LUA_API int lua_isstring(lua_State *L, int idx)
11,421✔
284
{
285
  cTValue *o = index2adr(L, idx);
11,421✔
286
  return (tvisstr(o) || tvisnumber(o));
11,421✔
287
}
288

289
LUA_API int lua_isuserdata(lua_State *L, int idx)
×
290
{
291
  cTValue *o = index2adr(L, idx);
×
292
  return (tvisudata(o) || tvislightud(o));
×
293
}
294

295
LUA_API int lua_rawequal(lua_State *L, int idx1, int idx2)
×
296
{
297
  cTValue *o1 = index2adr(L, idx1);
×
298
  cTValue *o2 = index2adr(L, idx2);
×
299
  return (o1 == niltv(L) || o2 == niltv(L)) ? 0 : lj_obj_equal(o1, o2);
×
300
}
301

302
LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
×
303
{
304
  cTValue *o1 = index2adr(L, idx1);
×
305
  cTValue *o2 = index2adr(L, idx2);
×
306
  if (tvisint(o1) && tvisint(o2)) {
×
307
    return intV(o1) == intV(o2);
308
  } else if (tvisnumber(o1) && tvisnumber(o2)) {
×
309
    return numberVnum(o1) == numberVnum(o2);
×
310
  } else if (itype(o1) != itype(o2)) {
×
311
    return 0;
312
  } else if (tvispri(o1)) {
×
313
    return o1 != niltv(L) && o2 != niltv(L);
×
314
#if LJ_64 && !LJ_GC64
315
  } else if (tvislightud(o1)) {
316
    return o1->u64 == o2->u64;
317
#endif
318
  } else if (gcrefeq(o1->gcr, o2->gcr)) {
×
319
    return 1;
320
  } else if (!tvistabud(o1)) {
×
321
    return 0;
322
  } else {
323
    TValue *base = lj_meta_equal(L, gcV(o1), gcV(o2), 0);
×
324
    if ((uintptr_t)base <= 1) {
×
325
      return (int)(uintptr_t)base;
×
326
    } else {
327
      L->top = base+2;
×
328
      jit_secure_call(L, base, 1+1);
×
329
      L->top -= 2+LJ_FR2;
×
330
      return tvistruecond(L->top+1+LJ_FR2);
×
331
    }
332
  }
333
}
334

335
LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
1,049,215✔
336
{
337
  cTValue *o1 = index2adr(L, idx1);
1,049,215✔
338
  cTValue *o2 = index2adr(L, idx2);
1,049,215✔
339
  if (o1 == niltv(L) || o2 == niltv(L)) {
1,049,215✔
340
    return 0;
341
  } else if (tvisint(o1) && tvisint(o2)) {
1,049,215✔
342
    return intV(o1) < intV(o2);
343
  } else if (tvisnumber(o1) && tvisnumber(o2)) {
1,049,215✔
344
    return numberVnum(o1) < numberVnum(o2);
937,096✔
345
  } else {
346
    TValue *base = lj_meta_comp(L, o1, o2, 0);
112,119✔
347
    if ((uintptr_t)base <= 1) {
112,119✔
348
      return (int)(uintptr_t)base;
102,133✔
349
    } else {
350
      L->top = base+2;
9,986✔
351
      jit_secure_call(L, base, 1+1);
9,986✔
352
      L->top -= 2+LJ_FR2;
9,986✔
353
      return tvistruecond(L->top+1+LJ_FR2);
9,986✔
354
    }
355
  }
356
}
357

358
LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
269✔
359
{
360
  cTValue *o = index2adr(L, idx);
269✔
361
  TValue tmp;
269✔
362
  if (LJ_LIKELY(tvisnumber(o)))
269✔
363
    return numberVnum(o);
265✔
364
  else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp))
4✔
365
    return numV(&tmp);
4✔
366
  else
367
    return 0;
×
368
}
369

370
LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok)
×
371
{
372
  cTValue *o = index2adr(L, idx);
×
373
  TValue tmp;
×
374
  if (LJ_LIKELY(tvisnumber(o))) {
×
375
    if (ok) *ok = 1;
×
376
    return numberVnum(o);
×
377
  } else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) {
×
378
    if (ok) *ok = 1;
×
379
    return numV(&tmp);
×
380
  } else {
381
    if (ok) *ok = 0;
×
382
    return 0;
×
383
  }
384
}
385

386
LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
12✔
387
{
388
  cTValue *o = index2adr(L, idx);
12✔
389
  TValue tmp;
12✔
390
  if (LJ_LIKELY(tvisnumber(o)))
12✔
391
    return numberVnum(o);
12✔
392
  else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp)))
×
393
    lj_err_argt(L, idx, LUA_TNUMBER);
×
394
  return numV(&tmp);
×
395
}
396

397
LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def)
4✔
398
{
399
  cTValue *o = index2adr(L, idx);
4✔
400
  TValue tmp;
4✔
401
  if (LJ_LIKELY(tvisnumber(o)))
4✔
402
    return numberVnum(o);
4✔
403
  else if (tvisnil(o))
×
404
    return def;
405
  else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp)))
×
406
    lj_err_argt(L, idx, LUA_TNUMBER);
×
407
  return numV(&tmp);
×
408
}
409

410
LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
71,232✔
411
{
412
  cTValue *o = index2adr(L, idx);
71,232✔
413
  TValue tmp;
71,232✔
414
  lua_Number n;
71,232✔
415
  if (LJ_LIKELY(tvisint(o))) {
71,232✔
416
    return intV(o);
417
  } else if (LJ_LIKELY(tvisnum(o))) {
71,232✔
418
    n = numV(o);
71,230✔
419
  } else {
420
    if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
2✔
421
      return 0;
2✔
422
    if (tvisint(&tmp))
×
423
      return intV(&tmp);
424
    n = numV(&tmp);
×
425
  }
426
#if LJ_64
427
  return (lua_Integer)n;
71,230✔
428
#else
429
  return lj_num2int(n);
430
#endif
431
}
432

433
LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok)
×
434
{
435
  cTValue *o = index2adr(L, idx);
×
436
  TValue tmp;
×
437
  lua_Number n;
×
438
  if (LJ_LIKELY(tvisint(o))) {
×
439
    if (ok) *ok = 1;
440
    return intV(o);
441
  } else if (LJ_LIKELY(tvisnum(o))) {
×
442
    n = numV(o);
×
443
  } else {
444
    if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) {
×
445
      if (ok) *ok = 0;
×
446
      return 0;
×
447
    }
448
    if (tvisint(&tmp)) {
×
449
      if (ok) *ok = 1;
450
      return intV(&tmp);
451
    }
452
    n = numV(&tmp);
×
453
  }
454
  if (ok) *ok = 1;
×
455
#if LJ_64
456
  return (lua_Integer)n;
×
457
#else
458
  return lj_num2int(n);
459
#endif
460
}
461

462
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
×
463
{
464
  cTValue *o = index2adr(L, idx);
×
465
  TValue tmp;
×
466
  lua_Number n;
×
467
  if (LJ_LIKELY(tvisint(o))) {
×
468
    return intV(o);
469
  } else if (LJ_LIKELY(tvisnum(o))) {
×
470
    n = numV(o);
×
471
  } else {
472
    if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
×
473
      lj_err_argt(L, idx, LUA_TNUMBER);
×
474
    if (tvisint(&tmp))
×
475
      return (lua_Integer)intV(&tmp);
476
    n = numV(&tmp);
×
477
  }
478
#if LJ_64
479
  return (lua_Integer)n;
×
480
#else
481
  return lj_num2int(n);
482
#endif
483
}
484

485
LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def)
22,364✔
486
{
487
  cTValue *o = index2adr(L, idx);
22,364✔
488
  TValue tmp;
22,364✔
489
  lua_Number n;
22,364✔
490
  if (LJ_LIKELY(tvisint(o))) {
22,364✔
491
    return intV(o);
492
  } else if (LJ_LIKELY(tvisnum(o))) {
22,364✔
493
    n = numV(o);
33✔
494
  } else if (tvisnil(o)) {
22,331✔
495
    return def;
496
  } else {
497
    if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
×
498
      lj_err_argt(L, idx, LUA_TNUMBER);
×
499
    if (tvisint(&tmp))
×
500
      return (lua_Integer)intV(&tmp);
501
    n = numV(&tmp);
×
502
  }
503
#if LJ_64
504
  return (lua_Integer)n;
33✔
505
#else
506
  return lj_num2int(n);
507
#endif
508
}
509

510
LUA_API int lua_toboolean(lua_State *L, int idx)
1,912,895✔
511
{
512
  cTValue *o = index2adr(L, idx);
1,912,895✔
513
  return tvistruecond(o);
1,912,895✔
514
}
515

516
LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
58,065✔
517
{
518
  TValue *o = index2adr(L, idx);
58,065✔
519
  GCstr *s;
58,065✔
520
  if (LJ_LIKELY(tvisstr(o))) {
58,065✔
521
    s = strV(o);
53,030✔
522
  } else if (tvisnumber(o)) {
5,035✔
523
    lj_gc_check(L);
5,008✔
524
    o = index2adr(L, idx);  /* GC may move the stack. */
5,008✔
525
    s = lj_strfmt_number(L, o);
5,008✔
526
    setstrV(L, o, s);
5,008✔
527
  } else {
528
    if (len != NULL) *len = 0;
27✔
529
    return NULL;
27✔
530
  }
531
  if (len != NULL) *len = s->len;
58,038✔
532
  return strdata(s);
58,038✔
533
}
534

535
LUA_API uint32_t lua_hashstring(lua_State *L, int idx)
×
536
{
537
  TValue *o = index2adr(L, idx);
×
538
  lj_checkapi(tvisstr(o), "stack slot %d is not a string", idx);
×
539
  GCstr *s = strV(o);
×
540
  if (! strsmart(s))
×
541
    return s->hash;
×
542
  return lua_hash(strdata(s), s->len);
×
543
}
544

545
LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
46,968✔
546
{
547
  TValue *o = index2adr(L, idx);
46,968✔
548
  GCstr *s;
46,968✔
549
  if (LJ_LIKELY(tvisstr(o))) {
46,968✔
550
    s = strV(o);
46,968✔
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;
46,968✔
560
  return strdata(s);
46,968✔
561
}
562

563
LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
71,250✔
564
                                       const char *def, size_t *len)
565
{
566
  TValue *o = index2adr(L, idx);
71,250✔
567
  GCstr *s;
71,250✔
568
  if (LJ_LIKELY(tvisstr(o))) {
71,250✔
569
    s = strV(o);
71,159✔
570
  } else if (tvisnil(o)) {
91✔
571
    if (len != NULL) *len = def ? strlen(def) : 0;
91✔
572
    return def;
91✔
573
  } else if (tvisnumber(o)) {
×
574
    lj_gc_check(L);
×
575
    o = index2adr(L, idx);  /* GC may move the stack. */
×
576
    s = lj_strfmt_number(L, o);
×
577
    setstrV(L, o, s);
×
578
  } else {
579
    lj_err_argt(L, idx, LUA_TSTRING);
×
580
  }
581
  if (len != NULL) *len = s->len;
71,159✔
582
  return strdata(s);
71,159✔
583
}
584

585
LUALIB_API int luaL_checkoption(lua_State *L, int idx, const char *def,
×
586
                                const char *const lst[])
587
{
588
  ptrdiff_t i;
×
589
  const char *s = lua_tolstring(L, idx, NULL);
×
590
  if (s == NULL && (s = def) == NULL)
×
591
    lj_err_argt(L, idx, LUA_TSTRING);
×
592
  for (i = 0; lst[i]; i++)
×
593
    if (strcmp(lst[i], s) == 0)
×
594
      return (int)i;
×
595
  lj_err_argv(L, idx, LJ_ERR_INVOPTM, s);
×
596
}
597

598
LUA_API size_t lua_objlen(lua_State *L, int idx)
292✔
599
{
600
  TValue *o = index2adr(L, idx);
292✔
601
  if (tvisstr(o)) {
292✔
602
    return strV(o)->len;
290✔
603
  } else if (tvistab(o)) {
2✔
604
    return (size_t)lj_tab_len(tabV(o));
2✔
605
  } else if (tvisudata(o)) {
×
606
    return udataV(o)->len;
×
607
  } else if (tvisnumber(o)) {
×
608
    GCstr *s = lj_strfmt_number(L, o);
×
609
    setstrV(L, o, s);
×
610
    return s->len;
×
611
  } else {
612
    return 0;
613
  }
614
}
615

616
LUA_API lua_CFunction lua_tocfunction(lua_State *L, int idx)
×
617
{
618
  cTValue *o = index2adr(L, idx);
×
619
  if (tvisfunc(o)) {
×
620
    BCOp op = bc_op(*mref(funcV(o)->c.pc, BCIns));
×
621
    if (op == BC_FUNCC || op == BC_FUNCCW)
×
622
      return funcV(o)->c.f;
×
623
  }
624
  return NULL;
625
}
626

627
LUA_API void *lua_touserdata(lua_State *L, int idx)
4✔
628
{
629
  cTValue *o = index2adr(L, idx);
4✔
630
  if (tvisudata(o))
4✔
631
    return uddata(udataV(o));
4✔
632
  else if (tvislightud(o))
×
633
    return lightudV(G(L), o);
×
634
  else
635
    return NULL;
636
}
637

638
LUA_API lua_State *lua_tothread(lua_State *L, int idx)
×
639
{
640
  cTValue *o = index2adr(L, idx);
×
641
  return (!tvisthread(o)) ? NULL : threadV(o);
×
642
}
643

644
LUA_API const void *lua_topointer(lua_State *L, int idx)
256✔
645
{
646
  return lj_obj_ptr(G(L), index2adr(L, idx));
256✔
647
}
648

649
/* -- Stack setters (object creation) ------------------------------------- */
650

651
LUA_API void lua_pushnil(lua_State *L)
1,605✔
652
{
653
  setnilV(L->top);
1,605✔
654
  incr_top(L);
1,605✔
655
}
1,605✔
656

657
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
283✔
658
{
659
  setnumV(L->top, n);
283✔
660
  if (LJ_UNLIKELY(tvisnan(L->top)))
283✔
661
    setnanV(L->top);  /* Canonicalize injected NaNs. */
×
662
  incr_top(L);
283✔
663
}
283✔
664

665
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
4,308,802✔
666
{
667
  setintptrV(L->top, n);
4,308,802✔
668
  incr_top(L);
4,308,802✔
669
}
4,308,802✔
670

671
LUA_API void lua_pushlstring(lua_State *L, const char *str, size_t len)
61,116✔
672
{
673
  GCstr *s;
61,116✔
674
  lj_gc_check(L);
61,116✔
675
  s = lj_str_new(L, str, len);
61,116✔
676
  setstrV(L, L->top, s);
61,116✔
677
  incr_top(L);
61,116✔
678
}
61,116✔
679

680
LUA_API void lua_pushstring(lua_State *L, const char *str)
4,436,004✔
681
{
682
  if (str == NULL) {
4,436,004✔
683
    setnilV(L->top);
48✔
684
  } else {
685
    GCstr *s;
4,435,956✔
686
    lj_gc_check(L);
4,435,956✔
687
    s = lj_str_newz(L, str);
4,435,956✔
688
    setstrV(L, L->top, s);
4,435,956✔
689
  }
690
  incr_top(L);
4,436,004✔
691
}
4,436,004✔
692

693
LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt,
×
694
                                     va_list argp)
695
{
696
  lj_gc_check(L);
×
697
  return lj_strfmt_pushvf(L, fmt, argp);
×
698
}
699

700
LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...)
3,413✔
701
{
702
  const char *ret;
3,413✔
703
  va_list argp;
3,413✔
704
  lj_gc_check(L);
3,413✔
705
  va_start(argp, fmt);
3,413✔
706
  ret = lj_strfmt_pushvf(L, fmt, argp);
3,413✔
707
  va_end(argp);
3,413✔
708
  return ret;
3,413✔
709
}
710

711
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
8,863✔
712
{
713
  GCfunc *fn;
8,863✔
714
  lj_gc_check(L);
8,863✔
715
  lj_checkapi_slot(n);
8,863✔
716
  fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
17,726✔
717
  fn->c.f = f;
8,863✔
718
  L->top -= n;
8,863✔
719
  while (n--)
8,863✔
720
    copyTV(L, &fn->c.upvalue[n], L->top+n);
9,814✔
721
  setfuncV(L, L->top, fn);
8,863✔
722
  lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white");
8,863✔
723
  incr_top(L);
8,863✔
724
}
8,863✔
725

726
LUA_API void lua_pushboolean(lua_State *L, int b)
1,000,249✔
727
{
728
  setboolV(L->top, (b != 0));
1,000,249✔
729
  incr_top(L);
1,000,249✔
730
}
1,000,249✔
731

732
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
260✔
733
{
734
#if LJ_64
735
  p = lj_lightud_intern(L, p);
260✔
736
#endif
737
  setrawlightudV(L->top, p);
258✔
738
  incr_top(L);
258✔
739
}
258✔
740

741
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
1,079,055✔
742
{
743
  lj_gc_check(L);
1,079,055✔
744
  settabV(L, L->top, lj_tab_new_ah(L, narray, nrec));
1,079,055✔
745
  incr_top(L);
1,079,055✔
746
}
1,079,055✔
747

748
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
272✔
749
{
750
  GCtab *regt = tabV(registry(L));
272✔
751
  TValue *tv = lj_tab_setstr(L, regt, lj_str_newz(L, tname));
272✔
752
  if (tvisnil(tv)) {
272✔
753
    GCtab *mt = lj_tab_new(L, 0, 1);
272✔
754
    settabV(L, tv, mt);
272✔
755
    settabV(L, L->top++, mt);
272✔
756
    lj_gc_anybarriert(L, regt);
272✔
757
    return 1;
272✔
758
  } else {
759
    copyTV(L, L->top++, tv);
×
760
    return 0;
×
761
  }
762
}
763

764
LUA_API int lua_pushthread(lua_State *L)
4✔
765
{
766
  setthreadV(L, L->top, L);
4✔
767
  incr_top(L);
4✔
768
  return (mainthread(G(L)) == L);
4✔
769
}
770

771
LUA_API lua_State *lua_newthread(lua_State *L)
1,097✔
772
{
773
  lua_State *L1;
1,097✔
774
  lj_gc_check(L);
1,097✔
775
  L1 = lj_state_new(L);
1,097✔
776
  setthreadV(L, L->top, L1);
1,097✔
777
  incr_top(L);
1,097✔
778
  return L1;
1,097✔
779
}
780

781
LUA_API void *lua_newuserdata(lua_State *L, size_t size)
1,006,209✔
782
{
783
  GCudata *ud;
1,006,209✔
784
  lj_gc_check(L);
1,006,209✔
785
  if (size > LJ_MAX_UDATA)
1,006,209✔
786
    lj_err_msg(L, LJ_ERR_UDATAOV);
×
787
  ud = lj_udata_new(L, (MSize)size, getcurrenv(L));
2,012,418✔
788
  setudataV(L, L->top, ud);
1,006,209✔
789
  incr_top(L);
1,006,209✔
790
  return uddata(ud);
1,006,209✔
791
}
792

793
LUA_API void lua_concat(lua_State *L, int n)
26,926✔
794
{
795
  lj_checkapi_slot(n);
26,926✔
796
  if (n >= 2) {
26,926✔
797
    n--;
801✔
798
    do {
801✔
799
      TValue *top = lj_meta_cat(L, L->top-1, -n);
801✔
800
      if (top == NULL) {
801✔
801
        L->top -= n;
800✔
802
        break;
800✔
803
      }
804
      n -= (int)(L->top - (top - 2*LJ_FR2));
1✔
805
      L->top = top+2;
1✔
806
      jit_secure_call(L, top, 1+1);
1✔
807
      L->top -= 1+LJ_FR2;
1✔
808
      copyTV(L, L->top-1, L->top+LJ_FR2);
1✔
809
    } while (--n > 0);
1✔
810
  } else if (n == 0) {  /* Push empty string. */
26,125✔
811
    setstrV(L, L->top, &G(L)->strempty);
10✔
812
    incr_top(L);
10✔
813
  }
814
  /* else n == 1: nothing to do. */
815
}
26,926✔
816

817
/* -- Object getters ------------------------------------------------------ */
818

819
LUA_API void lua_gettable(lua_State *L, int idx)
124✔
820
{
821
  cTValue *t = index2adr_check(L, idx);
124✔
822
  cTValue *v = lj_meta_tget(L, t, L->top-1);
124✔
823
  if (v == NULL) {
124✔
824
    L->top += 2;
2✔
825
    jit_secure_call(L, L->top-2, 1+1);
2✔
826
    L->top -= 2+LJ_FR2;
2✔
827
    v = L->top+1+LJ_FR2;
2✔
828
  }
829
  copyTV(L, L->top-1, v);
124✔
830
}
124✔
831

832
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
9,732✔
833
{
834
  cTValue *v, *t = index2adr_check(L, idx);
9,732✔
835
  TValue key;
9,732✔
836
  setstrV(L, &key, lj_str_newz(L, k));
9,732✔
837
  v = lj_meta_tget(L, t, &key);
9,732✔
838
  if (v == NULL) {
9,732✔
839
    L->top += 2;
×
840
    jit_secure_call(L, L->top-2, 1+1);
×
841
    L->top -= 2+LJ_FR2;
×
842
    v = L->top+1+LJ_FR2;
×
843
  }
844
  copyTV(L, L->top, v);
9,732✔
845
  incr_top(L);
9,732✔
846
}
9,732✔
847

848
LUA_API void lua_rawget(lua_State *L, int idx)
4,298,826✔
849
{
850
  cTValue *t = index2adr(L, idx);
4,298,826✔
851
  lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
4,298,826✔
852
  copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1));
4,298,826✔
853
}
4,298,826✔
854

855
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
2,295,650✔
856
{
857
  cTValue *v, *t = index2adr(L, idx);
2,295,650✔
858
  lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
2,295,650✔
859
  v = lj_tab_getint(tabV(t), n);
2,295,650✔
860
  if (v) {
2,295,650✔
861
    copyTV(L, L->top, v);
2,295,593✔
862
  } else {
863
    setnilV(L->top);
57✔
864
  }
865
  incr_top(L);
2,295,650✔
866
}
2,295,650✔
867

868
LUA_API int lua_getmetatable(lua_State *L, int idx)
1,911✔
869
{
870
  cTValue *o = index2adr(L, idx);
1,911✔
871
  GCtab *mt = NULL;
1,911✔
872
  if (tvistab(o))
1,911✔
873
    mt = tabref(tabV(o)->metatable);
15✔
874
  else if (tvisudata(o))
1,896✔
875
    mt = tabref(udataV(o)->metatable);
1,891✔
876
  else
877
    mt = tabref(basemt_obj(G(L), o));
5✔
878
  if (mt == NULL)
1,911✔
879
    return 0;
880
  settabV(L, L->top, mt);
1,898✔
881
  incr_top(L);
1,898✔
882
  return 1;
883
}
884

885
LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field)
1✔
886
{
887
  if (lua_getmetatable(L, idx)) {
1✔
UNCOV
888
    cTValue *tv = lj_tab_getstr(tabV(L->top-1), lj_str_newz(L, field));
×
UNCOV
889
    if (tv && !tvisnil(tv)) {
×
UNCOV
890
      copyTV(L, L->top-1, tv);
×
UNCOV
891
      return 1;
×
892
    }
893
    L->top--;
×
894
  }
895
  return 0;
896
}
897

898
LUA_API void lua_getfenv(lua_State *L, int idx)
14✔
899
{
900
  cTValue *o = index2adr_check(L, idx);
14✔
901
  if (tvisfunc(o)) {
14✔
902
    settabV(L, L->top, tabref(funcV(o)->c.env));
8✔
903
  } else if (tvisudata(o)) {
6✔
904
    settabV(L, L->top, tabref(udataV(o)->env));
×
905
  } else if (tvisthread(o)) {
6✔
906
    settabV(L, L->top, tabref(threadV(o)->env));
5✔
907
  } else {
908
    setnilV(L->top);
1✔
909
  }
910
  incr_top(L);
14✔
911
}
14✔
912

913
LUA_API int lua_next(lua_State *L, int idx)
45✔
914
{
915
  cTValue *t = index2adr(L, idx);
45✔
916
  int more;
45✔
917
  lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
45✔
918
  more = lj_tab_next(L, tabV(t), L->top-1);
45✔
919
  if (more) {
45✔
920
    incr_top(L);  /* Return new key and value slot. */
30✔
921
  } else {  /* End of traversal. */
922
    L->top--;  /* Remove key slot. */
15✔
923
  }
924
  return more;
45✔
925
}
926

927
LUA_API const char *lua_getupvalue(lua_State *L, int idx, int n)
12✔
928
{
929
  TValue *val;
12✔
930
  GCobj *o;
12✔
931
  const char *name = lj_debug_uvnamev(index2adr(L, idx), (uint32_t)(n-1), &val, &o);
12✔
932
  if (name) {
12✔
933
    copyTV(L, L->top, val);
7✔
934
    incr_top(L);
7✔
935
  }
936
  return name;
12✔
937
}
938

939
LUA_API void *lua_upvalueid(lua_State *L, int idx, int n)
×
940
{
941
  GCfunc *fn = funcV(index2adr(L, idx));
×
942
  n--;
×
943
  lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n);
×
944
  return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
×
945
                         (void *)&fn->c.upvalue[n];
946
}
947

948
LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
×
949
{
950
  GCfunc *fn1 = funcV(index2adr(L, idx1));
×
951
  GCfunc *fn2 = funcV(index2adr(L, idx2));
×
952
  n1--; n2--;
×
953
  lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1);
×
954
  lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2);
×
955
  lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1);
×
956
  lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1);
×
957
  setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]);
×
958
  lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
×
959
}
×
960

961
LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname)
18✔
962
{
963
  cTValue *o = index2adr(L, idx);
18✔
964
  if (tvisudata(o)) {
18✔
965
    GCudata *ud = udataV(o);
18✔
966
    cTValue *tv = lj_tab_getstr(tabV(registry(L)), lj_str_newz(L, tname));
18✔
967
    if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
18✔
968
      return uddata(ud);
18✔
969
  }
970
  return NULL;  /* value is not a userdata with a metatable */
971
}
972

973
LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
18✔
974
{
975
  void *p = luaL_testudata(L, idx, tname);
18✔
976
  if (!p) lj_err_argtype(L, idx, tname);
18✔
977
  return p;
18✔
978
}
979

980
/* -- Object setters ------------------------------------------------------ */
981

982
LUA_API void lua_settable(lua_State *L, int idx)
4,617✔
983
{
984
  TValue *o;
4,617✔
985
  cTValue *t = index2adr_check(L, idx);
4,617✔
986
  lj_checkapi_slot(2);
4,617✔
987
  o = lj_meta_tset(L, t, L->top-2);
4,617✔
988
  if (o) {
4,617✔
989
    /* NOBARRIER: lj_meta_tset ensures the table is not black. */
990
    L->top -= 2;
4,617✔
991
    copyTV(L, o, L->top+1);
4,617✔
992
  } else {
993
    TValue *base = L->top;
×
994
    copyTV(L, base+2, base-3-2*LJ_FR2);
×
995
    L->top = base+3;
×
996
    jit_secure_call(L, base, 0+1);
×
997
    L->top -= 3+LJ_FR2;
×
998
  }
999
}
4,617✔
1000

1001
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
154,463✔
1002
{
1003
  TValue *o;
154,463✔
1004
  TValue key;
154,463✔
1005
  cTValue *t = index2adr_check(L, idx);
154,463✔
1006
  lj_checkapi_slot(1);
154,463✔
1007
  setstrV(L, &key, lj_str_newz(L, k));
154,463✔
1008
  o = lj_meta_tset(L, t, &key);
154,463✔
1009
  if (o) {
154,463✔
1010
    /* NOBARRIER: lj_meta_tset ensures the table is not black. */
1011
    copyTV(L, o, --L->top);
154,463✔
1012
  } else {
1013
    TValue *base = L->top;
×
1014
    copyTV(L, base+2, base-3-2*LJ_FR2);
×
1015
    L->top = base+3;
×
1016
    jit_secure_call(L, base, 0+1);
×
1017
    L->top -= 2+LJ_FR2;
×
1018
  }
1019
}
154,463✔
1020

1021
LUA_API void lua_rawset(lua_State *L, int idx)
1,000,352✔
1022
{
1023
  GCtab *t = tabV(index2adr(L, idx));
1,000,352✔
1024
  TValue *dst, *key;
1,000,352✔
1025
  lj_checkapi_slot(2);
1,000,352✔
1026
  key = L->top-2;
1,000,352✔
1027
  dst = lj_tab_set(L, t, key);
1,000,352✔
1028
  copyTV(L, dst, key+1);
1,000,351✔
1029
  lj_gc_anybarriert(L, t);
1,000,351✔
1030
  L->top = key;
1,000,351✔
1031
}
1,000,351✔
1032

1033
LUA_API void lua_rawseti(lua_State *L, int idx, int n)
1,014,889✔
1034
{
1035
  GCtab *t = tabV(index2adr(L, idx));
1,014,889✔
1036
  TValue *dst, *src;
1,014,889✔
1037
  lj_checkapi_slot(1);
1,014,889✔
1038
  dst = lj_tab_setint(L, t, n);
1,014,889✔
1039
  src = L->top-1;
1,014,889✔
1040
  copyTV(L, dst, src);
1,014,889✔
1041
  lj_gc_barriert(L, t, dst);
1,014,889✔
1042
  L->top = src;
1,014,889✔
1043
}
1,014,889✔
1044

1045
LUA_API int lua_setmetatable(lua_State *L, int idx)
1,001,015✔
1046
{
1047
  global_State *g;
1,001,015✔
1048
  GCtab *mt;
1,001,015✔
1049
  cTValue *o = index2adr_check(L, idx);
1,001,015✔
1050
  lj_checkapi_slot(1);
1,001,015✔
1051
  if (tvisnil(L->top-1)) {
1,001,015✔
1052
    mt = NULL;
1053
  } else {
1054
    lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
1,001,009✔
1055
    mt = tabV(L->top-1);
1,001,009✔
1056
  }
1057
  g = G(L);
1,001,015✔
1058
  if (tvistab(o)) {
1,001,015✔
1059
    setgcref(tabV(o)->metatable, obj2gco(mt));
10✔
1060
    if (mt)
10✔
1061
      lj_gc_objbarriert(L, tabV(o), mt);
10✔
1062
  } else if (tvisudata(o)) {
1,001,005✔
1063
    setgcref(udataV(o)->metatable, obj2gco(mt));
1,000,982✔
1064
    if (mt)
1,000,982✔
1065
      lj_gc_objbarrier(L, udataV(o), mt);
1,000,982✔
1066
  } else {
1067
    /* Flush cache, since traces specialize to basemt. But not during __gc. */
1068
    if (lj_trace_flushall(L))
23✔
1069
      lj_err_caller(L, LJ_ERR_NOGCMM);
×
1070
    if (tvisbool(o)) {
23✔
1071
      /* NOBARRIER: basemt is a GC root. */
1072
      setgcref(basemt_it(g, LJ_TTRUE), obj2gco(mt));
4✔
1073
      setgcref(basemt_it(g, LJ_TFALSE), obj2gco(mt));
4✔
1074
    } else {
1075
      /* NOBARRIER: basemt is a GC root. */
1076
      setgcref(basemt_obj(g, o), obj2gco(mt));
19✔
1077
    }
1078
  }
1079
  L->top--;
1,001,015✔
1080
  return 1;
1,001,015✔
1081
}
1082

1083
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
18✔
1084
{
1085
  lua_getfield(L, LUA_REGISTRYINDEX, tname);
18✔
1086
  lua_setmetatable(L, -2);
18✔
1087
}
18✔
1088

1089
LUA_API int lua_setfenv(lua_State *L, int idx)
19✔
1090
{
1091
  cTValue *o = index2adr_check(L, idx);
19✔
1092
  GCtab *t;
19✔
1093
  lj_checkapi_slot(1);
19✔
1094
  lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
19✔
1095
  t = tabV(L->top-1);
19✔
1096
  if (tvisfunc(o)) {
19✔
1097
    setgcref(funcV(o)->c.env, obj2gco(t));
14✔
1098
  } else if (tvisudata(o)) {
5✔
1099
    setgcref(udataV(o)->env, obj2gco(t));
×
1100
  } else if (tvisthread(o)) {
5✔
1101
    setgcref(threadV(o)->env, obj2gco(t));
4✔
1102
  } else {
1103
    L->top--;
1✔
1104
    return 0;
1✔
1105
  }
1106
  lj_gc_objbarrier(L, gcV(o), t);
18✔
1107
  L->top--;
18✔
1108
  return 1;
18✔
1109
}
1110

1111
LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
9✔
1112
{
1113
  cTValue *f = index2adr(L, idx);
9✔
1114
  TValue *val;
9✔
1115
  GCobj *o;
9✔
1116
  const char *name;
9✔
1117
  lj_checkapi_slot(1);
9✔
1118
  name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o);
9✔
1119
  if (name) {
9✔
1120
    L->top--;
5✔
1121
    copyTV(L, val, L->top);
5✔
1122
    lj_gc_barrier(L, o, L->top);
5✔
1123
  }
1124
  return name;
9✔
1125
}
1126

1127
/* -- Calls --------------------------------------------------------------- */
1128

1129
#if LJ_FR2
1130
static TValue *api_call_base(lua_State *L, int nargs)
5,200,724✔
1131
{
1132
  TValue *o = L->top, *base = o - nargs;
5,200,724✔
1133
  L->top = o+1;
5,200,724✔
1134
  for (; o > base; o--) copyTV(L, o, o-1);
15,583,908✔
1135
  setnilV(o);
5,200,724✔
1136
  return o+1;
5,200,724✔
1137
}
1138
#else
1139
#define api_call_base(L, nargs)        (L->top - (nargs))
1140
#endif
1141

1142
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
5,199,848✔
1143
{
1144
  lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
5,199,848✔
1145
              "thread called in wrong state %d", L->status);
1146
  lj_checkapi_slot(nargs+1);
5,199,848✔
1147
  jit_secure_call(L, api_call_base(L, nargs), nresults+1);
10,399,696✔
1148
}
5,199,844✔
1149

1150
LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
876✔
1151
{
1152
  global_State *g = G(L);
876✔
1153
  uint8_t oldh = hook_save(g);
876✔
1154
  ptrdiff_t ef;
876✔
1155
  int status;
876✔
1156
  lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
876✔
1157
              "thread called in wrong state %d", L->status);
1158
  lj_checkapi_slot(nargs+1);
876✔
1159
  if (errfunc == 0) {
876✔
1160
    ef = 0;
1161
  } else {
1162
    cTValue *o = index2adr_stack(L, errfunc);
510✔
1163
    ef = savestack(L, o);
510✔
1164
  }
1165
  /* Forbid Lua world re-entrancy while running the trace */
1166
  if (tvref(g->jit_base)) {
876✔
1167
    setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITCALL));
×
1168
    if (g->panic) g->panic(L);
×
1169
    exit(EXIT_FAILURE);
×
1170
  }
1171
  lj_trace_abort(g);  /* Never record across Lua VM entrance */
876✔
1172
  status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
1,752✔
1173
  if (status) hook_restore(g, oldh);
748✔
1174
  return status;
748✔
1175
}
1176

1177
static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
268✔
1178
{
1179
  GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L));
536✔
1180
  TValue *top = L->top;
268✔
1181
  fn->c.f = func;
268✔
1182
  setfuncV(L, top++, fn);
268✔
1183
  if (LJ_FR2) setnilV(top++);
268✔
1184
#if LJ_64
1185
  ud = lj_lightud_intern(L, ud);
268✔
1186
#endif
1187
  setrawlightudV(top++, ud);
268✔
1188
  cframe_nres(L->cframe) = 1+0;  /* Zero results. */
268✔
1189
  L->top = top;
268✔
1190
  return top-1;  /* Now call the newly allocated C function. */
268✔
1191
}
1192

1193
LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
268✔
1194
{
1195
  global_State *g = G(L);
268✔
1196
  uint8_t oldh = hook_save(g);
268✔
1197
  int status;
268✔
1198
  lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
268✔
1199
              "thread called in wrong state %d", L->status);
1200
  /* Forbid Lua world re-entrancy while running the trace */
1201
  if (tvref(g->jit_base)) {
268✔
1202
    setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITCALL));
×
1203
    if (g->panic) g->panic(L);
×
1204
    exit(EXIT_FAILURE);
×
1205
  }
1206
  lj_trace_abort(g);  /* Never record across Lua VM entrance */
268✔
1207
  status = lj_vm_cpcall(L, func, ud, cpcall);
268✔
1208
  if (status) hook_restore(g, oldh);
140✔
1209
  return status;
140✔
1210
}
1211

1212
LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
1✔
1213
{
1214
  if (luaL_getmetafield(L, idx, field)) {
1✔
UNCOV
1215
    TValue *top = L->top--;
×
UNCOV
1216
    if (LJ_FR2) setnilV(top++);
×
UNCOV
1217
    copyTV(L, top++, index2adr(L, idx));
×
UNCOV
1218
    L->top = top;
×
UNCOV
1219
    jit_secure_call(L, top-1, 1+1);
×
UNCOV
1220
    return 1;
×
1221
  }
1222
  return 0;
1223
}
1224

1225
/* -- Coroutine yield and resume ------------------------------------------ */
1226

1227
LUA_API int lua_isyieldable(lua_State *L)
×
1228
{
1229
  return cframe_canyield(L->cframe);
×
1230
}
1231

1232
LUA_API int lua_yield(lua_State *L, int nresults)
2✔
1233
{
1234
  void *cf = L->cframe;
2✔
1235
  global_State *g = G(L);
2✔
1236
  if (cframe_canyield(cf)) {
2✔
1237
    cf = cframe_raw(cf);
2✔
1238
    if (!hook_active(g)) {  /* Regular yield: move results down if needed. */
2✔
1239
      cTValue *f = L->top - nresults;
×
1240
      if (f > L->base) {
×
1241
        TValue *t = L->base;
1242
        while (--nresults >= 0) copyTV(L, t++, f++);
×
1243
        L->top = t;
×
1244
      }
1245
      L->cframe = NULL;
×
1246
      L->status = LUA_YIELD;
×
1247
      return -1;
×
1248
    } else {  /* Yield from hook: add a pseudo-frame. */
1249
      TValue *top = L->top;
2✔
1250
      hook_leave(g);
2✔
1251
      (top++)->u64 = cframe_multres(cf);
2✔
1252
      setcont(top, lj_cont_hook);
2✔
1253
      if (LJ_FR2) top++;
2✔
1254
      setframe_pc(top, cframe_pc(cf)-1);
2✔
1255
      top++;
2✔
1256
      setframe_gc(top, obj2gco(L), LJ_TTHREAD);
2✔
1257
      if (LJ_FR2) top++;
2✔
1258
      setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
2✔
1259
      L->top = L->base = top+1;
2✔
1260
#if ((defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND) || LJ_TARGET_WINDOWS
1261
      lj_err_throw(L, LUA_YIELD);
2✔
1262
#else
1263
      L->cframe = NULL;
1264
      L->status = LUA_YIELD;
1265
      lj_vm_unwind_c(cf, LUA_YIELD);
1266
#endif
1267
    }
1268
  }
1269
  lj_err_msg(L, LJ_ERR_CYIELD);
×
1270
  return 0;  /* unreachable */
1271
}
1272

1273
LUA_API int lua_resume(lua_State *L, int nargs)
×
1274
{
1275
  if (L->cframe == NULL && L->status <= LUA_YIELD)
×
1276
    return lj_vm_resume(L,
×
1277
      L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs,
×
1278
      0, 0);
1279
  L->top = L->base;
×
1280
  setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
×
1281
  incr_top(L);
×
1282
  return LUA_ERRRUN;
1283
}
1284

1285
/* -- GC and memory management -------------------------------------------- */
1286

1287
LUA_API int lua_gc(lua_State *L, int what, int data)
1,886✔
1288
{
1289
  global_State *g = G(L);
1,886✔
1290
  int res = 0;
1,886✔
1291
  switch (what) {
1,886✔
1292
  case LUA_GCSTOP:
284✔
1293
    g->gc.threshold = LJ_MAX_MEM;
284✔
1294
    break;
284✔
1295
  case LUA_GCRESTART:
271✔
1296
    g->gc.threshold = data == -1 ? (g->gc.total/100)*g->gc.pause : g->gc.total;
271✔
1297
    break;
271✔
1298
  case LUA_GCCOLLECT:
891✔
1299
    lj_gc_fullgc(L);
891✔
1300
    break;
891✔
1301
  case LUA_GCCOUNT:
×
1302
    res = (int)(g->gc.total >> 10);
×
1303
    break;
×
1304
  case LUA_GCCOUNTB:
×
1305
    res = (int)(g->gc.total & 0x3ff);
×
1306
    break;
×
1307
  case LUA_GCSTEP: {
432✔
1308
    GCSize a = (GCSize)data << 10;
432✔
1309
    g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0;
432✔
1310
    while (g->gc.total >= g->gc.threshold)
988✔
1311
      if (lj_gc_step(L) > 0) {
563✔
1312
        res = 1;
1313
        break;
1314
      }
1315
    break;
1316
  }
1317
  case LUA_GCSETPAUSE:
2✔
1318
    res = (int)(g->gc.pause);
2✔
1319
    g->gc.pause = (MSize)data;
2✔
1320
    break;
2✔
1321
  case LUA_GCSETSTEPMUL:
6✔
1322
    res = (int)(g->gc.stepmul);
6✔
1323
    g->gc.stepmul = (MSize)data;
6✔
1324
    break;
6✔
1325
  case LUA_GCISRUNNING:
×
1326
    res = (g->gc.threshold != LJ_MAX_MEM);
×
1327
    break;
×
1328
  default:
1329
    res = -1;  /* Invalid option. */
1330
  }
1331
  return res;
1,886✔
1332
}
1333

1334
LUA_API lua_Alloc lua_getallocf(lua_State *L, void **ud)
10✔
1335
{
1336
  global_State *g = G(L);
10✔
1337
  if (ud) *ud = g->allocd;
10✔
1338
  return g->allocf;
10✔
1339
}
1340

1341
LUA_API void lua_setallocf(lua_State *L, lua_Alloc f, void *ud)
20✔
1342
{
1343
  global_State *g = G(L);
20✔
1344
  g->allocd = ud;
20✔
1345
  g->allocf = f;
20✔
1346
}
20✔
1347

1348
LUA_API uint32_t lua_hash(const char *str, uint32_t len)
8,966,083✔
1349
{
1350
  uint32_t h = len, a, b;
8,966,083✔
1351
  if (len >= 4) {
8,966,083✔
1352
    a = lj_getu32(str);
6,696,672✔
1353
    h ^= lj_getu32(str+len-4);
6,696,672✔
1354
    b = lj_getu32(str+(len>>1)-2);
6,696,672✔
1355
    h ^= b; h -= lj_rol(b, 14);
6,696,672✔
1356
    b += lj_getu32(str+(len>>2)-1);
6,696,672✔
1357
  } else if (len > 0) {
2,269,411✔
1358
    a = *str;
2,269,411✔
1359
    h ^= *(str+len-1);
2,269,411✔
1360
    b = *(str+(len>>1));
2,269,411✔
1361
    h ^= b; h -= lj_rol(b, 14);
2,269,411✔
1362
  } else {
1363
    return 0;
1364
  }
1365
  a ^= h; a -= lj_rol(h, 11);
8,966,083✔
1366
  b ^= a; b -= lj_rol(a, 25);
8,966,083✔
1367
  h ^= b; h -= lj_rol(b, 16);
8,966,083✔
1368
  return h;
8,966,083✔
1369
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc