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

tarantool / luajit / 8062004225

27 Feb 2024 08:41AM UTC coverage: 92.591% (-0.007%) from 92.598%
8062004225

push

github

Buristan
test: enable CLI-related lua-Harness tests back

Tarantool supports -b and -j options to use LuaJIT modules since the
commit bf8b76a4d ("lua: proxy -j and -b
flags"), so 241-standalone.t and 411-luajit.t tests in the lua-Harness
suite, disabled in the commit 39a4db500
("test: support Tarantool in lua-Harness"), can be enabled back.

However, the -O option is still not implemented in Tarantool, so the
related part in the 411-luajit.t test chunk is still disabled.

Follows up tarantool/tarantool#5541

Reviewed-by: Maxim Kokryashkin <m.kokryashkin@tarantool.org>
Reviewed-by: Sergey Kaplun <skaplun@tarantool.org>
Signed-off-by: Sergey Kaplun <skaplun@tarantool.org>
(cherry picked from commit e316cbf0d)

5657 of 6016 branches covered (94.03%)

Branch coverage included in aggregate %.

21588 of 23409 relevant lines covered (92.22%)

2817149.02 hits per line

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

86.45
/src/lib_jit.c
1
/*
2
** JIT library.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#define lib_jit_c
7
#define LUA_LIB
8

9
#include "lua.h"
10
#include "lauxlib.h"
11
#include "lualib.h"
12

13
#include "lj_obj.h"
14
#include "lj_gc.h"
15
#include "lj_err.h"
16
#include "lj_debug.h"
17
#include "lj_str.h"
18
#include "lj_tab.h"
19
#include "lj_state.h"
20
#include "lj_bc.h"
21
#if LJ_HASFFI
22
#include "lj_ctype.h"
23
#endif
24
#if LJ_HASJIT
25
#include "lj_ir.h"
26
#include "lj_jit.h"
27
#include "lj_ircall.h"
28
#include "lj_iropt.h"
29
#include "lj_target.h"
30
#endif
31
#include "lj_trace.h"
32
#include "lj_dispatch.h"
33
#include "lj_vm.h"
34
#include "lj_vmevent.h"
35
#include "lj_lib.h"
36

37
#include "luajit.h"
38

39
/* -- jit.* functions ----------------------------------------------------- */
40

41
#define LJLIB_MODULE_jit
42

43
static int setjitmode(lua_State *L, int mode)
863✔
44
{
45
  int idx = 0;
863✔
46
  if (L->base == L->top || tvisnil(L->base)) {  /* jit.on/off/flush([nil]) */
863✔
47
    mode |= LUAJIT_MODE_ENGINE;
48
  } else {
49
    /* jit.on/off/flush(func|proto, nil|true|false) */
50
    if (tvisfunc(L->base) || tvisproto(L->base))
61✔
51
      idx = 1;
52
    else if (!tvistrue(L->base))  /* jit.on/off/flush(true, nil|true|false) */
4✔
53
      goto err;
×
54
    if (L->base+1 < L->top && tvisbool(L->base+1))
61✔
55
      mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC;
44✔
56
    else
57
      mode |= LUAJIT_MODE_FUNC;
17✔
58
  }
59
  if (luaJIT_setmode(L, idx, mode) != 1) {
863✔
60
    if ((mode & LUAJIT_MODE_MASK) == LUAJIT_MODE_ENGINE)
×
61
      lj_err_caller(L, LJ_ERR_NOJIT);
×
62
  err:
×
63
    lj_err_argt(L, 1, LUA_TFUNCTION);
×
64
  }
65
  return 0;
863✔
66
}
67

68
LJLIB_CF(jit_on)
285✔
69
{
70
  return setjitmode(L, LUAJIT_MODE_ON);
285✔
71
}
72

73
LJLIB_CF(jit_off)
314✔
74
{
75
  return setjitmode(L, LUAJIT_MODE_OFF);
314✔
76
}
77

78
LJLIB_CF(jit_flush)
264✔
79
{
80
#if LJ_HASJIT
81
  if (L->base < L->top && tvisnumber(L->base)) {
264✔
82
    int traceno = lj_lib_checkint(L, 1);
×
83
    luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
×
84
    return 0;
×
85
  }
86
#endif
87
  return setjitmode(L, LUAJIT_MODE_FLUSH);
264✔
88
}
89

90
#if LJ_HASJIT
91
/* Push a string for every flag bit that is set. */
92
static void flagbits_to_strings(lua_State *L, uint32_t flags, uint32_t base,
202✔
93
                                const char *str)
94
{
95
  for (; *str; base <<= 1, str += 1+*str)
1,818✔
96
    if (flags & base)
1,616✔
97
      setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str));
1,616✔
98
}
202✔
99
#endif
100

101
LJLIB_CF(jit_status)
101✔
102
{
103
#if LJ_HASJIT
104
  jit_State *J = L2J(L);
101✔
105
  L->top = L->base;
101✔
106
  setboolV(L->top++, (J->flags & JIT_F_ON) ? 1 : 0);
101✔
107
  flagbits_to_strings(L, J->flags, JIT_F_CPU_FIRST, JIT_F_CPUSTRING);
101✔
108
  flagbits_to_strings(L, J->flags, JIT_F_OPT_FIRST, JIT_F_OPTSTRING);
101✔
109
  return (int)(L->top - L->base);
101✔
110
#else
111
  setboolV(L->top++, 0);
112
  return 1;
113
#endif
114
}
115

116
LJLIB_CF(jit_attach)
45✔
117
{
118
#ifdef LUAJIT_DISABLE_VMEVENT
119
  luaL_error(L, "vmevent API disabled");
120
#else
121
  GCfunc *fn = lj_lib_checkfunc(L, 1);
45✔
122
  GCstr *s = lj_lib_optstr(L, 2);
45✔
123
  luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
45✔
124
  if (s) {  /* Attach to given event. */
45✔
125
    const uint8_t *p = (const uint8_t *)strdata(s);
15✔
126
    uint32_t h = s->len;
15✔
127
    while (*p) h = h ^ (lj_rol(h, 6) + *p++);
93✔
128
    lua_pushvalue(L, 1);
15✔
129
    lua_rawseti(L, -2, VMEVENT_HASHIDX(h));
15✔
130
    G(L)->vmevmask = VMEVENT_NOCACHE;  /* Invalidate cache. */
15✔
131
  } else {  /* Detach if no event given. */
132
    setnilV(L->top++);
30✔
133
    while (lua_next(L, -2)) {
90✔
134
      L->top--;
60✔
135
      if (tvisfunc(L->top) && funcV(L->top) == fn) {
60✔
136
        setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1));
10✔
137
      }
138
    }
139
  }
140
#endif
141
  return 0;
45✔
142
}
143

144
LJLIB_PUSH(top-5) LJLIB_SET(os)
145
LJLIB_PUSH(top-4) LJLIB_SET(arch)
146
LJLIB_PUSH(top-3) LJLIB_SET(version_num)
147
LJLIB_PUSH(top-2) LJLIB_SET(version)
148

149
#include "lj_libdef.h"
150

151
/* -- jit.util.* functions ------------------------------------------------ */
152

153
#define LJLIB_MODULE_jit_util
154

155
/* -- Reflection API for Lua functions ------------------------------------ */
156

157
/* Return prototype of first argument (Lua function or prototype object) */
158
static GCproto *check_Lproto(lua_State *L, int nolua)
784✔
159
{
160
  TValue *o = L->base;
784✔
161
  if (L->top > o) {
784✔
162
    if (tvisproto(o)) {
784✔
163
      return protoV(o);
×
164
    } else if (tvisfunc(o)) {
784✔
165
      if (isluafunc(funcV(o)))
784✔
166
        return funcproto(funcV(o));
753✔
167
      else if (nolua)
31✔
168
        return NULL;
169
    }
170
  }
171
  lj_err_argt(L, 1, LUA_TFUNCTION);
×
172
  return NULL;  /* unreachable */
173
}
174

175
static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val)
556✔
176
{
177
  setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
556✔
178
}
556✔
179

180
/* local info = jit.util.funcinfo(func [,pc]) */
181
LJLIB_CF(jit_util_funcinfo)
69✔
182
{
183
  GCproto *pt = check_Lproto(L, 1);
69✔
184
  if (pt) {
69✔
185
    BCPos pc = (BCPos)lj_lib_optint(L, 2, 0);
38✔
186
    GCtab *t;
38✔
187
    lua_createtable(L, 0, 16);  /* Increment hash size if fields are added. */
38✔
188
    t = tabV(L->top-1);
38✔
189
    setintfield(L, t, "linedefined", pt->firstline);
38✔
190
    setintfield(L, t, "lastlinedefined", pt->firstline + pt->numline);
38✔
191
    setintfield(L, t, "stackslots", pt->framesize);
38✔
192
    setintfield(L, t, "params", pt->numparams);
38✔
193
    setintfield(L, t, "bytecodes", (int32_t)pt->sizebc);
38✔
194
    setintfield(L, t, "gcconsts", (int32_t)pt->sizekgc);
38✔
195
    setintfield(L, t, "nconsts", (int32_t)pt->sizekn);
38✔
196
    setintfield(L, t, "upvalues", (int32_t)pt->sizeuv);
38✔
197
    if (pc < pt->sizebc)
38✔
198
      setintfield(L, t, "currentline", lj_debug_line(pt, pc));
38✔
199
    lua_pushboolean(L, (pt->flags & PROTO_VARARG));
38✔
200
    lua_setfield(L, -2, "isvararg");
38✔
201
    lua_pushboolean(L, (pt->flags & PROTO_CHILD));
38✔
202
    lua_setfield(L, -2, "children");
38✔
203
    setstrV(L, L->top++, proto_chunkname(pt));
38✔
204
    lua_setfield(L, -2, "source");
38✔
205
    lj_debug_pushloc(L, pt, pc);
38✔
206
    lua_setfield(L, -2, "loc");
38✔
207
    setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt);
38✔
208
  } else {
209
    GCfunc *fn = funcV(L->base);
31✔
210
    GCtab *t;
31✔
211
    lua_createtable(L, 0, 4);  /* Increment hash size if fields are added. */
31✔
212
    t = tabV(L->top-1);
31✔
213
    if (!iscfunc(fn))
31✔
214
      setintfield(L, t, "ffid", fn->c.ffid);
31✔
215
    setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
31✔
216
               (intptr_t)(void *)fn->c.f);
217
    setintfield(L, t, "upvalues", fn->c.nupvalues);
31✔
218
  }
219
  return 1;
69✔
220
}
221

222
/* local ins, m = jit.util.funcbc(func, pc) */
223
LJLIB_CF(jit_util_funcbc)
623✔
224
{
225
  GCproto *pt = check_Lproto(L, 0);
623✔
226
  BCPos pc = (BCPos)lj_lib_checkint(L, 2);
623✔
227
  if (pc < pt->sizebc) {
623✔
228
    BCIns ins = proto_bc(pt)[pc];
611✔
229
    BCOp op = bc_op(ins);
611✔
230
    lj_assertL(op < BC__MAX, "bad bytecode op %d", op);
611✔
231
    setintV(L->top, ins);
611✔
232
    setintV(L->top+1, lj_bc_mode[op]);
611✔
233
    L->top += 2;
611✔
234
    return 2;
611✔
235
  }
236
  return 0;
237
}
238

239
/* local k = jit.util.funck(func, idx) */
240
LJLIB_CF(jit_util_funck)
52✔
241
{
242
  GCproto *pt = check_Lproto(L, 0);
52✔
243
  ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
52✔
244
  if (idx >= 0) {
52✔
245
    if (idx < (ptrdiff_t)pt->sizekn) {
29✔
246
      copyTV(L, L->top-1, proto_knumtv(pt, idx));
29✔
247
      return 1;
29✔
248
    }
249
  } else {
250
    if (~idx < (ptrdiff_t)pt->sizekgc) {
23✔
251
      GCobj *gc = proto_kgc(pt, idx);
23✔
252
      setgcV(L, L->top-1, gc, ~gc->gch.gct);
23✔
253
      return 1;
23✔
254
    }
255
  }
256
  return 0;
257
}
258

259
/* local name = jit.util.funcuvname(func, idx) */
260
LJLIB_CF(jit_util_funcuvname)
40✔
261
{
262
  GCproto *pt = check_Lproto(L, 0);
40✔
263
  uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
40✔
264
  if (idx < pt->sizeuv) {
40✔
265
    setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
40✔
266
    return 1;
40✔
267
  }
268
  return 0;
269
}
270

271
/* -- Reflection API for traces ------------------------------------------- */
272

273
#if LJ_HASJIT
274

275
/* Check trace argument. Must not throw for non-existent trace numbers. */
276
static GCtrace *jit_checktrace(lua_State *L)
8,582✔
277
{
278
  TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
8,582✔
279
  jit_State *J = L2J(L);
8,582✔
280
  if (tr > 0 && tr < J->sizetrace)
8,582✔
281
    return traceref(J, tr);
3,392✔
282
  return NULL;
283
}
284

285
/* Names of link types. ORDER LJ_TRLINK */
286
static const char *const jit_trlinkname[] = {
287
  "none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
288
  "interpreter", "return", "stitch"
289
};
290

291
/* local info = jit.util.traceinfo(tr) */
292
LJLIB_CF(jit_util_traceinfo)
50✔
293
{
294
  GCtrace *T = jit_checktrace(L);
50✔
295
  if (T) {
50✔
296
    GCtab *t;
38✔
297
    lua_createtable(L, 0, 8);  /* Increment hash size if fields are added. */
38✔
298
    t = tabV(L->top-1);
38✔
299
    setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
38✔
300
    setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
38✔
301
    setintfield(L, t, "link", T->link);
38✔
302
    setintfield(L, t, "nexit", T->nsnap);
38✔
303
    setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
38✔
304
    lua_setfield(L, -2, "linktype");
38✔
305
    /* There are many more fields. Add them only when needed. */
306
    return 1;
38✔
307
  }
308
  return 0;
309
}
310

311
/* local m, ot, op1, op2, prev = jit.util.traceir(tr, idx) */
312
LJLIB_CF(jit_util_traceir)
150✔
313
{
314
  GCtrace *T = jit_checktrace(L);
150✔
315
  IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
150✔
316
  if (T && ref >= REF_BIAS && ref < T->nins) {
150✔
317
    IRIns *ir = &T->ir[ref];
150✔
318
    int32_t m = lj_ir_mode[ir->o];
150✔
319
    setintV(L->top-2, m);
150✔
320
    setintV(L->top-1, ir->ot);
150✔
321
    setintV(L->top++, (int32_t)ir->op1 - (irm_op1(m)==IRMref ? REF_BIAS : 0));
204✔
322
    setintV(L->top++, (int32_t)ir->op2 - (irm_op2(m)==IRMref ? REF_BIAS : 0));
217✔
323
    setintV(L->top++, ir->prev);
150✔
324
    return 5;
150✔
325
  }
326
  return 0;
327
}
328

329
/* local k, t [, slot] = jit.util.tracek(tr, idx) */
330
LJLIB_CF(jit_util_tracek)
62✔
331
{
332
  GCtrace *T = jit_checktrace(L);
62✔
333
  IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
62✔
334
  if (T && ref >= T->nk && ref < REF_BIAS) {
62✔
335
    IRIns *ir = &T->ir[ref];
62✔
336
    int32_t slot = -1;
62✔
337
    if (ir->o == IR_KSLOT) {
62✔
338
      slot = ir->op2;
×
339
      ir = &T->ir[ir->op1];
×
340
    }
341
#if LJ_HASFFI
342
    if (ir->o == IR_KINT64) ctype_loadffi(L);
62✔
343
#endif
344
    lj_ir_kvalue(L, L->top-2, ir);
62✔
345
    setintV(L->top-1, (int32_t)irt_type(ir->t));
62✔
346
    if (slot == -1)
62✔
347
      return 2;
348
    setintV(L->top++, slot);
×
349
    return 3;
×
350
  }
351
  return 0;
352
}
353

354
/* local snap = jit.util.tracesnap(tr, sn) */
355
LJLIB_CF(jit_util_tracesnap)
×
356
{
357
  GCtrace *T = jit_checktrace(L);
×
358
  SnapNo sn = (SnapNo)lj_lib_checkint(L, 2);
×
359
  if (T && sn < T->nsnap) {
×
360
    SnapShot *snap = &T->snap[sn];
×
361
    SnapEntry *map = &T->snapmap[snap->mapofs];
×
362
    MSize n, nent = snap->nent;
×
363
    GCtab *t;
×
364
    lua_createtable(L, nent+2, 0);
×
365
    t = tabV(L->top-1);
×
366
    setintV(lj_tab_setint(L, t, 0), (int32_t)snap->ref - REF_BIAS);
×
367
    setintV(lj_tab_setint(L, t, 1), (int32_t)snap->nslots);
×
368
    for (n = 0; n < nent; n++)
×
369
      setintV(lj_tab_setint(L, t, (int32_t)(n+2)), (int32_t)map[n]);
×
370
    setintV(lj_tab_setint(L, t, (int32_t)(nent+2)), (int32_t)SNAP(255, 0, 0));
×
371
    return 1;
×
372
  }
373
  return 0;
374
}
375

376
/* local mcode, addr, loop = jit.util.tracemc(tr) */
377
LJLIB_CF(jit_util_tracemc)
8,320✔
378
{
379
  GCtrace *T = jit_checktrace(L);
8,320✔
380
  if (T && T->mcode != NULL) {
8,320✔
381
    setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
1,906✔
382
    setintptrV(L->top++, (intptr_t)(void *)T->mcode);
1,906✔
383
    setintV(L->top++, T->mcloop);
1,906✔
384
    return 3;
1,906✔
385
  }
386
  return 0;
387
}
388

389
/* local addr = jit.util.traceexitstub([tr,] exitno) */
390
LJLIB_CF(jit_util_traceexitstub)
×
391
{
392
#ifdef EXITSTUBS_PER_GROUP
393
  ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
×
394
  jit_State *J = L2J(L);
×
395
  if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
×
396
    setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
×
397
    return 1;
×
398
  }
399
#else
400
  if (L->top > L->base+1) {  /* Don't throw for one-argument variant. */
401
    GCtrace *T = jit_checktrace(L);
402
    ExitNo exitno = (ExitNo)lj_lib_checkint(L, 2);
403
    ExitNo maxexit = T->root ? T->nsnap+1 : T->nsnap;
404
    if (T && T->mcode != NULL && exitno < maxexit) {
405
      setintptrV(L->top-1, (intptr_t)(void *)exitstub_trace_addr(T, exitno));
406
      return 1;
407
    }
408
  }
409
#endif
410
  return 0;
411
}
412

413
/* local addr = jit.util.ircalladdr(idx) */
414
LJLIB_CF(jit_util_ircalladdr)
×
415
{
416
  uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
×
417
  if (idx < IRCALL__MAX) {
×
418
    setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func);
×
419
    return 1;
×
420
  }
421
  return 0;
422
}
423

424
#endif
425

426
#include "lj_libdef.h"
427

428
static int luaopen_jit_util(lua_State *L)
20✔
429
{
430
  LJ_LIB_REG(L, NULL, jit_util);
20✔
431
  return 1;
20✔
432
}
433

434
/* -- jit.opt module ------------------------------------------------------ */
435

436
#if LJ_HASJIT
437

438
#define LJLIB_MODULE_jit_opt
439

440
/* Parse optimization level. */
441
static int jitopt_level(jit_State *J, const char *str)
214✔
442
{
443
  if (str[0] >= '0' && str[0] <= '9' && str[1] == '\0') {
29✔
444
    uint32_t flags;
29✔
445
    if (str[0] == '0') flags = JIT_F_OPT_0;
29✔
446
    else if (str[0] == '1') flags = JIT_F_OPT_1;
16✔
447
    else if (str[0] == '2') flags = JIT_F_OPT_2;
16✔
448
    else flags = JIT_F_OPT_3;
16✔
449
    J->flags = (J->flags & ~JIT_F_OPT_MASK) | flags;
29✔
450
    return 1;  /* Ok. */
29✔
451
  }
452
  return 0;  /* No match. */
453
}
454

455
/* Parse optimization flag. */
456
static int jitopt_flag(jit_State *J, const char *str)
457
{
458
  const char *lst = JIT_F_OPTSTRING;
459
  uint32_t opt;
460
  int set = 1;
461
  if (str[0] == '+') {
462
    str++;
463
  } else if (str[0] == '-') {
464
    str++;
465
    set = 0;
466
  } else if (str[0] == 'n' && str[1] == 'o') {
467
    str += str[2] == '-' ? 3 : 2;
468
    set = 0;
469
  }
470
  for (opt = JIT_F_OPT_FIRST; ; opt <<= 1) {
471
    size_t len = *(const uint8_t *)lst;
472
    if (len == 0)
473
      break;
474
    if (strncmp(str, lst+1, len) == 0 && str[len] == '\0') {
475
      if (set) J->flags |= opt; else J->flags &= ~opt;
476
      return 1;  /* Ok. */
477
    }
478
    lst += 1+len;
479
  }
480
  return 0;  /* No match. */
481
}
482

483
/* Parse optimization parameter. */
484
static int jitopt_param(jit_State *J, const char *str)
176✔
485
{
486
  const char *lst = JIT_P_STRING;
176✔
487
  int i;
176✔
488
  for (i = 0; i < JIT_P__MAX; i++) {
1,284✔
489
    size_t len = *(const uint8_t *)lst;
1,283✔
490
    lj_assertJ(len != 0, "bad JIT_P_STRING");
1,283✔
491
    if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
1,283✔
492
      int32_t n = 0;
175✔
493
      const char *p = &str[len+1];
175✔
494
      while (*p >= '0' && *p <= '9')
397✔
495
        n = n*10 + (*p++ - '0');
222✔
496
      if (*p) return 0;  /* Malformed number. */
175✔
497
      J->param[i] = n;
175✔
498
      if (i == JIT_P_hotloop)
175✔
499
        lj_dispatch_init_hotcount(J2G(J));
121✔
500
      return 1;  /* Ok. */
175✔
501
    }
502
    lst += 1+len;
1,108✔
503
  }
504
  return 0;  /* No match. */
505
}
506

507
/* jit.opt.start(flags...) */
508
LJLIB_CF(jit_opt_start)
129✔
509
{
510
  jit_State *J = L2J(L);
129✔
511
  int nargs = (int)(L->top - L->base);
129✔
512
  if (nargs == 0) {
129✔
513
    J->flags = (J->flags & ~JIT_F_OPT_MASK) | JIT_F_OPT_DEFAULT;
1✔
514
  } else {
515
    int i;
516
    for (i = 1; i <= nargs; i++) {
341✔
517
      const char *str = strdata(lj_lib_checkstr(L, i));
214✔
518
      if (!jitopt_level(J, str) &&
428✔
519
          !jitopt_flag(J, str) &&
361✔
520
          !jitopt_param(J, str))
176✔
521
        lj_err_callerv(L, LJ_ERR_JITOPT, str);
1✔
522
    }
523
  }
524
  return 0;
128✔
525
}
526

527
#include "lj_libdef.h"
528

529
#endif
530

531
/* -- jit.profile module -------------------------------------------------- */
532

533
#if LJ_HASPROFILE
534

535
#define LJLIB_MODULE_jit_profile
536

537
/* Not loaded by default, use: local profile = require("jit.profile") */
538

539
#define KEY_PROFILE_THREAD        (U64x(80000000,00000000)|'t')
540
#define KEY_PROFILE_FUNC        (U64x(80000000,00000000)|'f')
541

542
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
66✔
543
                                 int vmstate)
544
{
545
  TValue key;
66✔
546
  cTValue *tv;
66✔
547
  key.u64 = KEY_PROFILE_FUNC;
66✔
548
  tv = lj_tab_get(L, tabV(registry(L)), &key);
66✔
549
  if (tvisfunc(tv)) {
66✔
550
    char vmst = (char)vmstate;
66✔
551
    int status;
66✔
552
    setfuncV(L2, L2->top++, funcV(tv));
66✔
553
    setthreadV(L2, L2->top++, L);
66✔
554
    setintV(L2->top++, samples);
66✔
555
    setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
66✔
556
    status = lua_pcall(L2, 3, 0, 0);  /* callback(thread, samples, vmstate) */
66✔
557
    if (status) {
66✔
558
      if (G(L2)->panic) G(L2)->panic(L2);
×
559
      exit(EXIT_FAILURE);
×
560
    }
561
    lj_trace_abort(G(L2));
66✔
562
  }
563
}
66✔
564

565
/* profile.start(mode, cb) */
566
LJLIB_CF(jit_profile_start)
2✔
567
{
568
  GCtab *registry = tabV(registry(L));
2✔
569
  GCstr *mode = lj_lib_optstr(L, 1);
2✔
570
  GCfunc *func = lj_lib_checkfunc(L, 2);
2✔
571
  lua_State *L2 = lua_newthread(L);  /* Thread that runs profiler callback. */
2✔
572
  TValue key;
2✔
573
  /* Anchor thread and function in registry. */
574
  key.u64 = KEY_PROFILE_THREAD;
2✔
575
  setthreadV(L, lj_tab_set(L, registry, &key), L2);
2✔
576
  key.u64 = KEY_PROFILE_FUNC;
2✔
577
  setfuncV(L, lj_tab_set(L, registry, &key), func);
2✔
578
  lj_gc_anybarriert(L, registry);
2✔
579
  luaJIT_profile_start(L, mode ? strdata(mode) : "",
2✔
580
                       (luaJIT_profile_callback)jit_profile_callback, L2);
581
  return 0;
2✔
582
}
583

584
/* profile.stop() */
585
LJLIB_CF(jit_profile_stop)
2✔
586
{
587
  GCtab *registry;
2✔
588
  TValue key;
2✔
589
  luaJIT_profile_stop(L);
2✔
590
  registry = tabV(registry(L));
2✔
591
  key.u64 = KEY_PROFILE_THREAD;
2✔
592
  setnilV(lj_tab_set(L, registry, &key));
2✔
593
  key.u64 = KEY_PROFILE_FUNC;
2✔
594
  setnilV(lj_tab_set(L, registry, &key));
2✔
595
  lj_gc_anybarriert(L, registry);
2✔
596
  return 0;
2✔
597
}
598

599
/* dump = profile.dumpstack([thread,] fmt, depth) */
600
LJLIB_CF(jit_profile_dumpstack)
1✔
601
{
602
  lua_State *L2 = L;
1✔
603
  int arg = 0;
1✔
604
  size_t len;
1✔
605
  int depth;
1✔
606
  GCstr *fmt;
1✔
607
  const char *p;
1✔
608
  if (L->top > L->base && tvisthread(L->base)) {
1✔
609
    L2 = threadV(L->base);
1✔
610
    arg = 1;
1✔
611
  }
612
  fmt = lj_lib_checkstr(L, arg+1);
1✔
613
  depth = lj_lib_checkint(L, arg+2);
1✔
614
  p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len);
1✔
615
  lua_pushlstring(L, p, len);
1✔
616
  return 1;
1✔
617
}
618

619
#include "lj_libdef.h"
620

621
static int luaopen_jit_profile(lua_State *L)
3✔
622
{
623
  LJ_LIB_REG(L, NULL, jit_profile);
3✔
624
  return 1;
3✔
625
}
626

627
#endif
628

629
/* -- JIT compiler initialization ----------------------------------------- */
630

631
#if LJ_HASJIT
632
/* Default values for JIT parameters. */
633
static const int32_t jit_param_default[JIT_P__MAX+1] = {
634
#define JIT_PARAMINIT(len, name, value)        (value),
635
JIT_PARAMDEF(JIT_PARAMINIT)
636
#undef JIT_PARAMINIT
637
  0
638
};
639
#endif
640

641
#if LJ_TARGET_ARM && LJ_TARGET_LINUX
642
#include <sys/utsname.h>
643
#endif
644

645
/* Arch-dependent CPU detection. */
646
static uint32_t jit_cpudetect(lua_State *L)
647
{
648
  uint32_t flags = 0;
649
#if LJ_TARGET_X86ORX64
650
  uint32_t vendor[4];
651
  uint32_t features[4];
652
  if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
653
#if !LJ_HASJIT
654
#define JIT_F_SSE2        2
655
#endif
656
    flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
657
#if LJ_HASJIT
658
    flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
659
    flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
660
    if (vendor[2] == 0x6c65746e) {  /* Intel. */
661
      if ((features[0] & 0x0fff0ff0) == 0x000106c0)  /* Atom. */
662
        flags |= JIT_F_LEA_AGU;
663
    } else if (vendor[2] == 0x444d4163) {  /* AMD. */
664
      uint32_t fam = (features[0] & 0x0ff00f00);
665
      if (fam >= 0x00000f00)  /* K8, K10. */
666
        flags |= JIT_F_PREFER_IMUL;
667
    }
668
    if (vendor[0] >= 7) {
669
      uint32_t xfeatures[4];
670
      lj_vm_cpuid(7, xfeatures);
671
      flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
672
    }
673
#endif
674
  }
675
  /* Check for required instruction set support on x86 (unnecessary on x64). */
676
#if LJ_TARGET_X86
677
  if (!(flags & JIT_F_SSE2))
678
    luaL_error(L, "CPU with SSE2 required");
679
#endif
680
#elif LJ_TARGET_ARM
681
#if LJ_HASJIT
682
  int ver = LJ_ARCH_VERSION;  /* Compile-time ARM CPU detection. */
683
#if LJ_TARGET_LINUX
684
  if (ver < 70) {  /* Runtime ARM CPU detection. */
685
    struct utsname ut;
686
    uname(&ut);
687
    if (strncmp(ut.machine, "armv", 4) == 0) {
688
      if (ut.machine[4] >= '7')
689
        ver = 70;
690
      else if (ut.machine[4] == '6')
691
        ver = 60;
692
    }
693
  }
694
#endif
695
  flags |= ver >= 70 ? JIT_F_ARMV7 :
696
           ver >= 61 ? JIT_F_ARMV6T2_ :
697
           ver >= 60 ? JIT_F_ARMV6_ : 0;
698
  flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
699
#endif
700
#elif LJ_TARGET_ARM64
701
  /* No optional CPU features to detect (for now). */
702
#elif LJ_TARGET_PPC
703
#if LJ_HASJIT
704
#if LJ_ARCH_SQRT
705
  flags |= JIT_F_SQRT;
706
#endif
707
#if LJ_ARCH_ROUND
708
  flags |= JIT_F_ROUND;
709
#endif
710
#endif
711
#elif LJ_TARGET_MIPS
712
#if LJ_HASJIT
713
  /* Compile-time MIPS CPU detection. */
714
#if LJ_ARCH_VERSION >= 20
715
  flags |= JIT_F_MIPSXXR2;
716
#endif
717
  /* Runtime MIPS CPU detection. */
718
#if defined(__GNUC__)
719
  if (!(flags & JIT_F_MIPSXXR2)) {
720
    int x;
721
#ifdef __mips16
722
    x = 0;  /* Runtime detection is difficult. Ensure optimal -march flags. */
723
#else
724
    /* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
725
    __asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
726
#endif
727
    if (x) flags |= JIT_F_MIPSXXR2;  /* Either 0x80000000 (R2) or 0 (R1). */
728
  }
729
#endif
730
#endif
731
#else
732
#error "Missing CPU detection for this architecture"
733
#endif
734
  UNUSED(L);
735
  return flags;
736
}
737

738
/* Initialize JIT compiler. */
739
static void jit_init(lua_State *L)
740
{
741
  uint32_t flags = jit_cpudetect(L);
742
#if LJ_HASJIT
743
  jit_State *J = L2J(L);
744
  J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
745
  memcpy(J->param, jit_param_default, sizeof(J->param));
746
  lj_dispatch_update(G(L));
747
#else
748
  UNUSED(flags);
749
#endif
750
}
751

752
LUALIB_API int luaopen_jit(lua_State *L)
295✔
753
{
754
  jit_init(L);
295✔
755
  lua_pushliteral(L, LJ_OS_NAME);
295✔
756
  lua_pushliteral(L, LJ_ARCH_NAME);
295✔
757
  lua_pushinteger(L, LUAJIT_VERSION_NUM);
295✔
758
  lua_pushliteral(L, LUAJIT_VERSION);
295✔
759
  LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
295✔
760
#if LJ_HASPROFILE
761
  lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
295✔
762
                tabref(L->env));
295✔
763
#endif
764
#ifndef LUAJIT_DISABLE_JITUTIL
765
  lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
295✔
766
#endif
767
#if LJ_HASJIT
768
  LJ_LIB_REG(L, "jit.opt", jit_opt);
295✔
769
#endif
770
  L->top -= 2;
295✔
771
  return 1;
295✔
772
}
773

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