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

tarantool / luajit / 11380194690

17 Oct 2024 07:17AM UTC coverage: 92.918% (-0.06%) from 92.974%
11380194690

push

github

Buristan
Limit CSE for IR_CARG to fix loop optimizations.

Thanks to Peter Cawley.

(cherry picked from commit 3bdc6498c)

`IR_CALLXS` for the vararg function contains `IR_CARG(fptr, ctid)` as
the second operand. The `loop_emit_phi()` scans only the first operand
of the IR, so the second is not marked as PHI. In this case, when the IR
appears in both the invariant and variant parts of the loop, CSE may
remove it and thus lead to incorrect emitting results.

This patch tweaks the CSE rules to avoid CSE across the `IR_LOOP`.

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

Part of tarantool/tarantool#10199

5692 of 6033 branches covered (94.35%)

Branch coverage included in aggregate %.

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

21 existing lines in 5 files now uncovered.

21702 of 23449 relevant lines covered (92.55%)

2969960.86 hits per line

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

77.8
/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,301,909✔
35
{
36
  if (idx > 0) {
25,301,909✔
37
    TValue *o = L->base + (idx - 1);
9,579,563✔
38
    return o < L->top ? o : niltv(L);
9,579,563✔
39
  } else if (idx > LUA_REGISTRYINDEX) {
15,722,346✔
40
    lj_checkapi(idx != 0 && -idx <= L->top - L->base,
10,412,919✔
41
                "bad stack slot %d", idx);
42
    return L->top + idx;
10,412,919✔
43
  } else if (idx == LUA_GLOBALSINDEX) {
5,309,427✔
44
    TValue *o = &G(L)->tmptv;
6,500✔
45
    settabV(L, o, tabref(L->env));
6,500✔
46
    return o;
6,500✔
47
  } else if (idx == LUA_REGISTRYINDEX) {
5,302,927✔
48
    return registry(L);
4,299,327✔
49
  } else {
50
    GCfunc *fn = curr_func(L);
1,003,600✔
51
    lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
1,003,600✔
52
                "calling frame is not a C function");
53
    if (idx == LUA_ENVIRONINDEX) {
1,003,600✔
54
      TValue *o = &G(L)->tmptv;
2,621✔
55
      settabV(L, o, tabref(fn->c.env));
2,621✔
56
      return o;
2,621✔
57
    } else {
58
      idx = LUA_GLOBALSINDEX - idx;
1,000,979✔
59
      return idx <= fn->c.nupvalues ? &fn->c.upvalue[idx-1] : niltv(L);
1,000,979✔
60
    }
61
  }
62
}
63

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

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

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

95
static void jit_secure_call(lua_State *L, TValue *base, int nres) {
5,214,324✔
96
  global_State *g = G(L);
5,214,324✔
97
  /* Forbid Lua world re-entrancy while running the trace */
98
  if (tvref(g->jit_base)) {
5,214,324✔
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,214,323✔
104
  lj_vm_call(L, base, nres);
5,214,323✔
105
}
5,214,315✔
106

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

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

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

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

130
LUA_API void lua_xmove(lua_State *L, lua_State *to, int n)
38✔
131
{
132
  TValue *f, *t;
38✔
133
  if (L == to) return;
38✔
134
  lj_checkapi_slot(n);
24✔
135
  lj_checkapi(G(L) == G(to), "move across global states");
24✔
136
  lj_state_checkstack(to, (MSize)n);
24✔
137
  f = L->top;
24✔
138
  t = to->top = to->top + n;
24✔
139
  while (--n >= 0) copyTV(to, --t, --f);
64✔
140
  L->top = f;
24✔
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)
197,391✔
153
{
154
  return (int)(L->top - L->base);
197,391✔
155
}
156

157
LUA_API void lua_settop(lua_State *L, int idx)
3,114,383✔
158
{
159
  if (idx >= 0) {
3,114,383✔
160
    lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx);
1,062,494✔
161
    if (L->base + idx > L->top) {
1,062,494✔
162
      if (L->base + idx >= tvref(L->maxstack))
59,963✔
163
        lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
×
164
      do { setnilV(L->top++); } while (L->top < L->base + idx);
162,349✔
165
    } else {
166
      L->top = L->base + idx;
1,002,531✔
167
    }
168
  } else {
169
    lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx);
2,051,889✔
170
    L->top += idx+1;  /* Shrinks top (idx < 0). */
2,051,889✔
171
  }
172
}
3,114,383✔
173

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

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

188
static void copy_slot(lua_State *L, TValue *f, int idx)
350✔
189
{
190
  if (idx == LUA_GLOBALSINDEX) {
350✔
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) {
350✔
195
    GCfunc *fn = curr_func(L);
350✔
196
    if (fn->c.gct != ~LJ_TFUNC)
350✔
197
      lj_err_msg(L, LJ_ERR_NOENV);
×
198
    lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
350✔
199
    setgcref(fn->c.env, obj2gco(tabV(f)));
350✔
200
    lj_gc_barrier(L, fn, f);
350✔
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
}
350✔
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)
350✔
217
{
218
  copy_slot(L, index2adr(L, fromidx), toidx);
350✔
219
}
350✔
220

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

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

229
LUA_API int lua_type(lua_State *L, int idx)
7,334,693✔
230
{
231
  cTValue *o = index2adr(L, idx);
7,334,693✔
232
  if (tvisnumber(o)) {
7,334,693✔
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,334,665✔
239
    return LUA_TNONE;
240
  } else {  /* Magic internal/external tag conversion. ORDER LJ_T */
241
    uint32_t t = ~itype(o);
7,334,633✔
242
#if LJ_64
243
    int tt = (int)((U64x(75a06,98042110) >> 4*t) & 15u);
7,334,633✔
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,334,633✔
248
    return tt;
7,334,633✔
249
  }
250
}
251

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

258
LUALIB_API void luaL_checkany(lua_State *L, int idx)
5✔
259
{
260
  if (index2adr(L, idx) == niltv(L))
5✔
261
    lj_err_arg(L, idx, LJ_ERR_NOVAL);
×
262
}
5✔
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)
18✔
271
{
272
  cTValue *o = index2adr(L, idx);
18✔
273
  return tvisfunc(o) && !isluafunc(funcV(o));
18✔
274
}
275

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

283
LUA_API int lua_isstring(lua_State *L, int idx)
12,030✔
284
{
285
  cTValue *o = index2adr(L, idx);
12,030✔
286
  return (tvisstr(o) || tvisnumber(o));
12,030✔
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)
288✔
359
{
360
  cTValue *o = index2adr(L, idx);
288✔
361
  TValue tmp;
288✔
362
  if (LJ_LIKELY(tvisnumber(o)))
288✔
363
    return numberVnum(o);
284✔
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,263✔
411
{
412
  cTValue *o = index2adr(L, idx);
71,263✔
413
  TValue tmp;
71,263✔
414
  lua_Number n;
71,263✔
415
  if (LJ_LIKELY(tvisint(o))) {
71,263✔
416
    return intV(o);
417
  } else if (LJ_LIKELY(tvisnum(o))) {
71,263✔
418
    n = numV(o);
71,261✔
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,261✔
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)
60✔
463
{
464
  cTValue *o = index2adr(L, idx);
60✔
465
  TValue tmp;
60✔
466
  lua_Number n;
60✔
467
  if (LJ_LIKELY(tvisint(o))) {
60✔
468
    return intV(o);
469
  } else if (LJ_LIKELY(tvisnum(o))) {
60✔
470
    n = numV(o);
60✔
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;
60✔
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,534✔
486
{
487
  cTValue *o = index2adr(L, idx);
22,534✔
488
  TValue tmp;
22,534✔
489
  lua_Number n;
22,534✔
490
  if (LJ_LIKELY(tvisint(o))) {
22,534✔
491
    return intV(o);
492
  } else if (LJ_LIKELY(tvisnum(o))) {
22,534✔
493
    n = numV(o);
47✔
494
  } else if (tvisnil(o)) {
22,487✔
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;
47✔
505
#else
506
  return lj_num2int(n);
507
#endif
508
}
509

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

516
LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
65,383✔
517
{
518
  TValue *o = index2adr(L, idx);
65,383✔
519
  GCstr *s;
65,383✔
520
  if (LJ_LIKELY(tvisstr(o))) {
65,383✔
521
    s = strV(o);
60,350✔
522
  } else if (tvisnumber(o)) {
5,033✔
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;
25✔
529
    return NULL;
25✔
530
  }
531
  if (len != NULL) *len = s->len;
65,358✔
532
  return strdata(s);
65,358✔
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)
48,329✔
546
{
547
  TValue *o = index2adr(L, idx);
48,329✔
548
  GCstr *s;
48,329✔
549
  if (LJ_LIKELY(tvisstr(o))) {
48,329✔
550
    s = strV(o);
48,329✔
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;
48,329✔
560
  return strdata(s);
48,329✔
561
}
562

563
LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
71,287✔
564
                                       const char *def, size_t *len)
565
{
566
  TValue *o = index2adr(L, idx);
71,287✔
567
  GCstr *s;
71,287✔
568
  if (LJ_LIKELY(tvisstr(o))) {
71,287✔
569
    s = strV(o);
71,164✔
570
  } else if (tvisnil(o)) {
123✔
571
    if (len != NULL) *len = def ? strlen(def) : 0;
123✔
572
    return def;
123✔
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,164✔
582
  return strdata(s);
71,164✔
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)
519✔
599
{
600
  TValue *o = index2adr(L, idx);
519✔
601
  if (tvisstr(o)) {
519✔
602
    return strV(o)->len;
517✔
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)
4✔
617
{
618
  cTValue *o = index2adr(L, idx);
4✔
619
  if (tvisfunc(o)) {
4✔
620
    BCOp op = bc_op(*mref(funcV(o)->c.pc, BCIns));
4✔
621
    if (op == BC_FUNCC || op == BC_FUNCCW)
4✔
622
      return funcV(o)->c.f;
4✔
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)
12✔
639
{
640
  cTValue *o = index2adr(L, idx);
12✔
641
  return (!tvisthread(o)) ? NULL : threadV(o);
12✔
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)
3,766✔
652
{
653
  setnilV(L->top);
3,766✔
654
  incr_top(L);
3,766✔
655
}
3,766✔
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,506,079✔
666
{
667
  setintptrV(L->top, n);
4,506,079✔
668
  incr_top(L);
4,506,079✔
669
}
4,506,075✔
670

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

680
LUA_API void lua_pushstring(lua_State *L, const char *str)
4,440,689✔
681
{
682
  if (str == NULL) {
4,440,689✔
683
    setnilV(L->top);
109✔
684
  } else {
685
    GCstr *s;
4,440,580✔
686
    lj_gc_check(L);
4,440,580✔
687
    s = lj_str_newz(L, str);
4,440,580✔
688
    setstrV(L, L->top, s);
4,440,580✔
689
  }
690
  incr_top(L);
4,440,689✔
691
}
4,440,689✔
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, ...)
4,422✔
701
{
702
  const char *ret;
4,422✔
703
  va_list argp;
4,422✔
704
  lj_gc_check(L);
4,422✔
705
  va_start(argp, fmt);
4,422✔
706
  ret = lj_strfmt_pushvf(L, fmt, argp);
4,422✔
707
  va_end(argp);
4,422✔
708
  return ret;
4,422✔
709
}
710

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

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

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

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

748
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
353✔
749
{
750
  GCtab *regt = tabV(registry(L));
353✔
751
  TValue *tv = lj_tab_setstr(L, regt, lj_str_newz(L, tname));
353✔
752
  if (tvisnil(tv)) {
353✔
753
    GCtab *mt = lj_tab_new(L, 0, 1);
353✔
754
    settabV(L, tv, mt);
353✔
755
    settabV(L, L->top++, mt);
353✔
756
    lj_gc_anybarriert(L, regt);
353✔
757
    return 1;
353✔
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,105✔
772
{
773
  lua_State *L1;
1,105✔
774
  lj_gc_check(L);
1,105✔
775
  L1 = lj_state_new(L);
1,105✔
776
  setthreadV(L, L->top, L1);
1,105✔
777
  incr_top(L);
1,105✔
778
  return L1;
1,105✔
779
}
780

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

793
LUA_API void lua_concat(lua_State *L, int n)
27,957✔
794
{
795
  lj_checkapi_slot(n);
27,957✔
796
  if (n >= 2) {
27,957✔
797
    n--;
1,096✔
798
    do {
1,096✔
799
      TValue *top = lj_meta_cat(L, L->top-1, -n);
1,096✔
800
      if (top == NULL) {
1,096✔
801
        L->top -= n;
1,095✔
802
        break;
1,095✔
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,861✔
811
    setstrV(L, L->top, &G(L)->strempty);
25✔
812
    incr_top(L);
25✔
813
  }
814
  /* else n == 1: nothing to do. */
815
}
27,957✔
816

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

819
LUA_API void lua_gettable(lua_State *L, int idx)
148✔
820
{
821
  cTValue *t = index2adr_check(L, idx);
148✔
822
  cTValue *v = lj_meta_tget(L, t, L->top-1);
148✔
823
  if (v == NULL) {
148✔
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);
148✔
830
}
148✔
831

832
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
13,471✔
833
{
834
  cTValue *v, *t = index2adr_check(L, idx);
13,471✔
835
  TValue key;
13,471✔
836
  setstrV(L, &key, lj_str_newz(L, k));
13,471✔
837
  v = lj_meta_tget(L, t, &key);
13,471✔
838
  if (v == NULL) {
13,471✔
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);
13,471✔
845
  incr_top(L);
13,471✔
846
}
13,471✔
847

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

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

868
LUA_API int lua_getmetatable(lua_State *L, int idx)
21,979✔
869
{
870
  cTValue *o = index2adr(L, idx);
21,979✔
871
  GCtab *mt = NULL;
21,979✔
872
  if (tvistab(o))
21,979✔
873
    mt = tabref(tabV(o)->metatable);
16✔
874
  else if (tvisudata(o))
21,963✔
875
    mt = tabref(udataV(o)->metatable);
1,924✔
876
  else
877
    mt = tabref(basemt_obj(G(L), o));
20,039✔
878
  if (mt == NULL)
21,979✔
879
    return 0;
880
  settabV(L, L->top, mt);
21,965✔
881
  incr_top(L);
21,965✔
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)
156✔
914
{
915
  cTValue *t = index2adr(L, idx);
156✔
916
  int more;
156✔
917
  lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
156✔
918
  more = lj_tab_next(L, tabV(t), L->top-1);
156✔
919
  if (more) {
156✔
920
    incr_top(L);  /* Return new key and value slot. */
104✔
921
  } else {  /* End of traversal. */
922
    L->top--;  /* Remove key slot. */
52✔
923
  }
924
  return more;
156✔
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)
26✔
962
{
963
  cTValue *o = index2adr(L, idx);
26✔
964
  if (tvisudata(o)) {
26✔
965
    GCudata *ud = udataV(o);
26✔
966
    cTValue *tv = lj_tab_getstr(tabV(registry(L)), lj_str_newz(L, tname));
26✔
967
    if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
26✔
968
      return uddata(ud);
26✔
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)
26✔
974
{
975
  void *p = luaL_testudata(L, idx, tname);
26✔
976
  if (!p) lj_err_argtype(L, idx, tname);
26✔
977
  return p;
26✔
978
}
979

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

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

1001
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
158,593✔
1002
{
1003
  TValue *o;
158,593✔
1004
  TValue key;
158,593✔
1005
  cTValue *t = index2adr_check(L, idx);
158,593✔
1006
  lj_checkapi_slot(1);
158,593✔
1007
  setstrV(L, &key, lj_str_newz(L, k));
158,593✔
1008
  o = lj_meta_tset(L, t, &key);
158,593✔
1009
  if (o) {
158,593✔
1010
    /* NOBARRIER: lj_meta_tset ensures the table is not black. */
1011
    copyTV(L, o, --L->top);
158,593✔
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
}
158,593✔
1020

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

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

1045
LUA_API int lua_setmetatable(lua_State *L, int idx)
1,001,046✔
1046
{
1047
  global_State *g;
1,001,046✔
1048
  GCtab *mt;
1,001,046✔
1049
  cTValue *o = index2adr_check(L, idx);
1,001,046✔
1050
  lj_checkapi_slot(1);
1,001,046✔
1051
  if (tvisnil(L->top-1)) {
1,001,046✔
1052
    mt = NULL;
1053
  } else {
1054
    lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
1,001,040✔
1055
    mt = tabV(L->top-1);
1,001,040✔
1056
  }
1057
  g = G(L);
1,001,046✔
1058
  if (tvistab(o)) {
1,001,046✔
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,036✔
1063
    setgcref(udataV(o)->metatable, obj2gco(mt));
1,001,011✔
1064
    if (mt)
1,001,011✔
1065
      lj_gc_objbarrier(L, udataV(o), mt);
1,001,011✔
1066
  } else {
1067
    /* Flush cache, since traces specialize to basemt. But not during __gc. */
1068
    if (lj_trace_flushall(L))
25✔
1069
      lj_err_caller(L, LJ_ERR_NOGCMM);
×
1070
    o = index2adr(L, idx);  /* Stack may have been reallocated. */
25✔
1071
    if (tvisbool(o)) {
25✔
1072
      /* NOBARRIER: basemt is a GC root. */
1073
      setgcref(basemt_it(g, LJ_TTRUE), obj2gco(mt));
4✔
1074
      setgcref(basemt_it(g, LJ_TFALSE), obj2gco(mt));
4✔
1075
    } else {
1076
      /* NOBARRIER: basemt is a GC root. */
1077
      setgcref(basemt_obj(g, o), obj2gco(mt));
21✔
1078
    }
1079
  }
1080
  L->top--;
1,001,046✔
1081
  return 1;
1,001,046✔
1082
}
1083

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

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

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

1128
/* -- Calls --------------------------------------------------------------- */
1129

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

1143
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
5,204,333✔
1144
{
1145
  lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
5,204,333✔
1146
              "thread called in wrong state %d", L->status);
1147
  lj_checkapi_slot(nargs+1);
5,204,333✔
1148
  jit_secure_call(L, api_call_base(L, nargs), nresults+1);
10,408,666✔
1149
}
5,204,324✔
1150

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

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

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

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

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

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

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

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

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

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

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

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

1349
LUA_API uint32_t lua_hash(const char *str, uint32_t len)
9,499,083✔
1350
{
1351
  uint32_t h = len, a, b;
9,499,083✔
1352
  if (len >= 4) {
9,499,083✔
1353
    a = lj_getu32(str);
7,178,579✔
1354
    h ^= lj_getu32(str+len-4);
7,178,579✔
1355
    b = lj_getu32(str+(len>>1)-2);
7,178,579✔
1356
    h ^= b; h -= lj_rol(b, 14);
7,178,579✔
1357
    b += lj_getu32(str+(len>>2)-1);
7,178,579✔
1358
  } else if (len > 0) {
2,320,504✔
1359
    a = *str;
2,320,504✔
1360
    h ^= *(str+len-1);
2,320,504✔
1361
    b = *(str+(len>>1));
2,320,504✔
1362
    h ^= b; h -= lj_rol(b, 14);
2,320,504✔
1363
  } else {
1364
    return 0;
1365
  }
1366
  a ^= h; a -= lj_rol(h, 11);
9,499,083✔
1367
  b ^= a; b -= lj_rol(a, 25);
9,499,083✔
1368
  h ^= b; h -= lj_rol(b, 16);
9,499,083✔
1369
  return h;
9,499,083✔
1370
}
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