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

tarantool / luajit / 11139910794

02 Oct 2024 07:45AM UTC coverage: 92.891% (+0.006%) from 92.885%
11139910794

push

github

Buristan
Fix bit op coercion in DUALNUM builds.

Thanks to Sergey Kaplun.

(cherry picked from commit f5fd22203)

The `lj_carith_check64()` function coerces the given number value to the
32-bit wide value. In this case, the 64-bit-wide operands will lose
upper bits.

This patch removes the excess coercion for the DUALNUM mode and drops
the corresponding skipcond introduced for the test in the previous
commit.

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

Part of tarantool/tarantool#10199

5684 of 6026 branches covered (94.32%)

Branch coverage included in aggregate %.

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

2 existing lines in 1 file now uncovered.

21679 of 23431 relevant lines covered (92.52%)

2951479.61 hits per line

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

87.21
/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)
1,166✔
44
{
45
  int idx = 0;
1,166✔
46
  if (L->base == L->top || tvisnil(L->base)) {  /* jit.on/off/flush([nil]) */
1,166✔
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))
100✔
51
      idx = 1;
52
    else if (!tvistrue(L->base))  /* jit.on/off/flush(true, nil|true|false) */
9✔
53
      goto err;
×
54
    if (L->base+1 < L->top && tvisbool(L->base+1))
100✔
55
      mode |= boolV(L->base+1) ? LUAJIT_MODE_ALLFUNC : LUAJIT_MODE_ALLSUBFUNC;
77✔
56
    else
57
      mode |= LUAJIT_MODE_FUNC;
23✔
58
  }
59
  if (luaJIT_setmode(L, idx, mode) != 1) {
1,166✔
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;
1,166✔
66
}
67

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

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

78
LJLIB_CF(jit_flush)
298✔
79
{
80
#if LJ_HASJIT
81
  if (L->base < L->top && tvisnumber(L->base)) {
298✔
82
    int traceno = lj_lib_checkint(L, 1);
6✔
83
    luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
6✔
84
    return 0;
6✔
85
  }
86
#endif
87
  return setjitmode(L, LUAJIT_MODE_FLUSH);
292✔
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,
238✔
93
                                const char *str)
94
{
95
  for (; *str; base <<= 1, str += 1+*str)
2,142✔
96
    if (flags & base)
1,904✔
97
      setstrV(L, L->top++, lj_str_new(L, str+1, *(uint8_t *)str));
1,904✔
98
}
238✔
99
#endif
100

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

116
LJLIB_CF(jit_attach)
76✔
117
{
118
#ifdef LUAJIT_DISABLE_VMEVENT
119
  luaL_error(L, "vmevent API disabled");
120
#else
121
  GCfunc *fn = lj_lib_checkfunc(L, 1);
76✔
122
  GCstr *s = lj_lib_optstr(L, 2);
76✔
123
  luaL_findtable(L, LUA_REGISTRYINDEX, LJ_VMEVENTS_REGKEY, LJ_VMEVENTS_HSIZE);
76✔
124
  if (s) {  /* Attach to given event. */
76✔
125
    const uint8_t *p = (const uint8_t *)strdata(s);
24✔
126
    uint32_t h = s->len;
24✔
127
    while (*p) h = h ^ (lj_rol(h, 6) + *p++);
148✔
128
    lua_pushvalue(L, 1);
24✔
129
    lua_rawseti(L, -2, VMEVENT_HASHIDX(h));
24✔
130
    G(L)->vmevmask = VMEVENT_NOCACHE;  /* Invalidate cache. */
24✔
131
  } else {  /* Detach if no event given. */
132
    setnilV(L->top++);
52✔
133
    while (lua_next(L, -2)) {
156✔
134
      L->top--;
104✔
135
      if (tvisfunc(L->top) && funcV(L->top) == fn) {
104✔
136
        setnilV(lj_tab_set(L, tabV(L->top-2), L->top-1));
18✔
137
      }
138
    }
139
  }
140
#endif
141
  return 0;
76✔
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)
573✔
159
{
160
  TValue *o = L->base;
573✔
161
  if (L->top > o) {
573✔
162
    if (tvisproto(o)) {
573✔
163
      return protoV(o);
×
164
    } else if (tvisfunc(o)) {
573✔
165
      if (isluafunc(funcV(o)))
573✔
166
        return funcproto(funcV(o));
554✔
167
      else if (nolua)
19✔
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)
662✔
176
{
177
  setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
662✔
178
}
662✔
179

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

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

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

259
/* local name = jit.util.funcuvname(func, idx) */
260
LJLIB_CF(jit_util_funcuvname)
30✔
261
{
262
  GCproto *pt = check_Lproto(L, 0);
30✔
263
  uint32_t idx = (uint32_t)lj_lib_checkint(L, 2);
30✔
264
  if (idx < pt->sizeuv) {
30✔
265
    setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx)));
30✔
266
    return 1;
30✔
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,252✔
277
{
278
  TraceNo tr = (TraceNo)lj_lib_checkint(L, 1);
8,252✔
279
  jit_State *J = L2J(L);
8,252✔
280
  if (tr > 0 && tr < J->sizetrace)
8,252✔
281
    return traceref(J, tr);
3,062✔
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)
65✔
293
{
294
  GCtrace *T = jit_checktrace(L);
65✔
295
  if (T) {
65✔
296
    GCtab *t;
48✔
297
    lua_createtable(L, 0, 8);  /* Increment hash size if fields are added. */
48✔
298
    t = tabV(L->top-1);
48✔
299
    setintfield(L, t, "nins", (int32_t)T->nins - REF_BIAS - 1);
48✔
300
    setintfield(L, t, "nk", REF_BIAS - (int32_t)T->nk);
48✔
301
    setintfield(L, t, "link", T->link);
48✔
302
    setintfield(L, t, "nexit", T->nsnap);
48✔
303
    setstrV(L, L->top++, lj_str_newz(L, jit_trlinkname[T->linktype]));
48✔
304
    lua_setfield(L, -2, "linktype");
48✔
305
    /* There are many more fields. Add them only when needed. */
306
    return 1;
48✔
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)
71✔
331
{
332
  GCtrace *T = jit_checktrace(L);
71✔
333
  IRRef ref = (IRRef)lj_lib_checkint(L, 2) + REF_BIAS;
71✔
334
  if (T && ref >= T->nk && ref < REF_BIAS) {
71✔
335
    IRIns *ir = &T->ir[ref];
71✔
336
    int32_t slot = -1;
71✔
337
    if (ir->o == IR_KSLOT) {
71✔
338
      slot = ir->op2;
×
339
      ir = &T->ir[ir->op1];
×
340
    }
341
#if LJ_HASFFI
342
    if (ir->o == IR_KINT64) ctype_loadffi(L);
71✔
343
#endif
344
    lj_ir_kvalue(L, L->top-2, ir);
71✔
345
    setintV(L->top-1, (int32_t)irt_type(ir->t));
71✔
346
    if (slot == -1)
71✔
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)
7,966✔
378
{
379
  GCtrace *T = jit_checktrace(L);
7,966✔
380
  if (T && T->mcode != NULL) {
7,966✔
381
    setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
1,564✔
382
    setintptrV(L->top++, (intptr_t)(void *)T->mcode);
1,564✔
383
    setintV(L->top++, T->mcloop);
1,564✔
384
    return 3;
1,564✔
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)
28✔
429
{
430
  LJ_LIB_REG(L, NULL, jit_util);
28✔
431
  return 1;
28✔
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)
249✔
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)
205✔
485
{
486
  const char *lst = JIT_P_STRING;
205✔
487
  int i;
205✔
488
  for (i = 0; i < JIT_P__MAX; i++) {
1,489✔
489
    size_t len = *(const uint8_t *)lst;
1,488✔
490
    lj_assertJ(len != 0, "bad JIT_P_STRING");
1,488✔
491
    if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
1,488✔
492
      int32_t n = 0;
204✔
493
      const char *p = &str[len+1];
204✔
494
      while (*p >= '0' && *p <= '9')
456✔
495
        n = n*10 + (*p++ - '0');
252✔
496
      if (*p) return 0;  /* Malformed number. */
204✔
497
      J->param[i] = n;
204✔
498
      if (i == JIT_P_hotloop)
204✔
499
        lj_dispatch_init_hotcount(J2G(J));
145✔
500
      return 1;  /* Ok. */
204✔
501
    }
502
    lst += 1+len;
1,284✔
503
  }
504
  return 0;  /* No match. */
505
}
506

507
/* jit.opt.start(flags...) */
508
LJLIB_CF(jit_opt_start)
155✔
509
{
510
  jit_State *J = L2J(L);
155✔
511
  int nargs = (int)(L->top - L->base);
155✔
512
  if (nargs == 0) {
155✔
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++) {
402✔
517
      const char *str = strdata(lj_lib_checkstr(L, i));
249✔
518
      if (!jitopt_level(J, str) &&
498✔
519
          !jitopt_flag(J, str) &&
425✔
520
          !jitopt_param(J, str))
205✔
521
        lj_err_callerv(L, LJ_ERR_JITOPT, str);
1✔
522
    }
523
  }
524
  return 0;
154✔
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,
64✔
543
                                 int vmstate)
544
{
545
  TValue key;
64✔
546
  cTValue *tv;
64✔
547
  key.u64 = KEY_PROFILE_FUNC;
64✔
548
  tv = lj_tab_get(L, tabV(registry(L)), &key);
64✔
549
  if (tvisfunc(tv)) {
64✔
550
    char vmst = (char)vmstate;
64✔
551
    int status;
64✔
552
    setfuncV(L2, L2->top++, funcV(tv));
64✔
553
    setthreadV(L2, L2->top++, L);
64✔
554
    setintV(L2->top++, samples);
64✔
555
    setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
64✔
556
    status = lua_pcall(L2, 3, 0, 0);  /* callback(thread, samples, vmstate) */
64✔
557
    if (status) {
64✔
558
      if (G(L2)->panic) G(L2)->panic(L2);
×
559
      exit(EXIT_FAILURE);
×
560
    }
561
    lj_trace_abort(G(L2));
64✔
562
  }
563
}
64✔
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)
335✔
753
{
754
  jit_init(L);
335✔
755
  lua_pushliteral(L, LJ_OS_NAME);
335✔
756
  lua_pushliteral(L, LJ_ARCH_NAME);
335✔
757
  lua_pushinteger(L, LUAJIT_VERSION_NUM);
335✔
758
  lua_pushliteral(L, LUAJIT_VERSION);
335✔
759
  LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
335✔
760
#if LJ_HASPROFILE
761
  lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
335✔
762
                tabref(L->env));
335✔
763
#endif
764
#ifndef LUAJIT_DISABLE_JITUTIL
765
  lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
335✔
766
#endif
767
#if LJ_HASJIT
768
  LJ_LIB_REG(L, "jit.opt", jit_opt);
335✔
769
#endif
770
  L->top -= 2;
335✔
771
  return 1;
335✔
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