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

tarantool / luajit / 8262096822

13 Mar 2024 09:08AM UTC coverage: 92.669% (+0.04%) from 92.629%
8262096822

push

github

ligurio
ci: bump version of actions/checkout

Bump version of actions/checkout to v4.
Bump fixes an annoying warning that appears in the Github WebUI:

| Node.js 16 actions are deprecated. Please update the following actions
| to use Node.js 20: actions/checkout@v3. For more information see:
| https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.

5661 of 6016 branches covered (94.1%)

Branch coverage included in aggregate %.

21607 of 23409 relevant lines covered (92.3%)

2816109.52 hits per line

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

85.71
/src/lj_sysprof.c
1
/*
2
** Implementation of sysprof - platform and Lua profiler.
3
*/
4

5
#define lj_sysprof_c
6
#define LUA_CORE
7

8
#include "lj_arch.h"
9
#include "lj_sysprof.h"
10

11
#if LJ_HASSYSPROF
12

13
#include "lj_obj.h"
14
#include "lj_debug.h"
15
#include "lj_dispatch.h"
16
#include "lj_frame.h"
17

18
#if LJ_HASJIT
19
#include "lj_jit.h"
20
#include "lj_trace.h"
21
#endif
22

23
#include "lj_wbuf.h"
24
#include "lj_profile_timer.h"
25
#include "lj_symtab.h"
26

27
#include <pthread.h>
28
#include <errno.h>
29
#include <execinfo.h>
30

31
/*
32
** Number of profiler frames we need to omit during stack
33
** unwinding.
34
**   +------------------------+
35
** 0 | default_backtrace_host |
36
**   +------------------------+
37
** 1 | stream_backtrace_host  |
38
**   +------------------------+
39
** 2 |  stream_{guest/host}   |
40
**   +------------------------+
41
** 3 |      stream_event      |
42
**   +------------------------+
43
** 4 | sysprof_record_sample  |
44
**   +------------------------+
45
** 5 | sysprof_signal_handler |
46
**   +------------------------+
47
*/
48
#define SYSPROF_HANDLER_STACK_DEPTH 6
49
#define SYSPROF_BACKTRACE_FRAME_MAX 512
50

51
/* Check that vmstate fits in 4 bits (see streaming format) */
52
#define vmstfit4(st) ((st & ~(uint32_t)((1 << 4) - 1)) == 0)
53

54
enum sysprof_state {
55
  /* Profiler is not running. */
56
  SPS_IDLE,
57
  /* Profiler is running. */
58
  SPS_PROFILE,
59
  /*
60
  ** Stopped in case of stopped or failed stream.
61
  ** Saved errno is set at luaM_sysprof_stop.
62
  */
63
  SPS_HALT
64
};
65

66
struct sysprof {
67
  global_State *g; /* Profiled VM. */
68
  pthread_t thread; /* Profiled thread. */
69
  volatile sig_atomic_t state; /* Internal state. */
70
  struct lj_wbuf out; /* Output accumulator. */
71
  struct luam_Sysprof_Counters counters; /* Profiling counters. */
72
  struct luam_Sysprof_Options opt; /* Profiling options. */
73
  luam_Sysprof_writer writer; /* Writer function for profile events. */
74
  luam_Sysprof_on_stop on_stop; /* Callback on profiling stopping. */
75
  luam_Sysprof_backtracer backtracer; /* Backtracing function for the host stack. */
76
  lj_profile_timer timer; /* Profiling timer. */
77
  int saved_errno; /* Saved errno when profiler failed. */
78
};
79
/*
80
** XXX: Only one VM can be profiled at a time.
81
*/
82

83
static struct sysprof sysprof = {0};
84

85
/* --- Stream ------------------------------------------------------------- */
86

87
static const uint8_t ljp_header[] = {'l', 'j', 'p', LJP_FORMAT_VERSION,
88
                                      0x0, 0x0, 0x0};
89

90
static int stream_is_needed(struct sysprof *sp)
20✔
91
{
92
  return sp->opt.mode != LUAM_SYSPROF_DEFAULT;
20✔
93
}
94

95
static int is_unconfigured(struct sysprof *sp)
900✔
96
{
97
  return sp->backtracer == NULL || sp->on_stop == NULL || sp->writer == NULL;
304✔
98
}
99

100
static void stream_prologue(struct sysprof *sp)
4✔
101
{
102
  /*
103
  ** XXX: Must be zero for the symtab module to dump all loaded libraries.
104
  */
105
  uint32_t unused_lib_adds = 0;
4✔
106
  lj_symtab_dump(&sp->out, sp->g, &unused_lib_adds);
4✔
107
  lj_wbuf_addn(&sp->out, ljp_header, sizeof(ljp_header));
4✔
108
}
4✔
109

110
static void stream_epilogue(struct sysprof *sp)
4✔
111
{
112
  lj_wbuf_addbyte(&sp->out, LJP_EPILOGUE_BYTE);
4✔
113
}
114

115
static void stream_ffunc_impl(struct lj_wbuf *buf, uint8_t ffid)
1✔
116
{
117
  lj_wbuf_addbyte(buf, LJP_FRAME_FFUNC);
1✔
118
  lj_wbuf_addu64(buf, ffid);
1✔
119
}
1✔
120

121
static void stream_lfunc(struct lj_wbuf *buf, const GCfunc *func)
122
{
123
  lj_assertX(isluafunc(func), "bad lua function in sysprof stream");
124
  const GCproto *pt = funcproto(func);
125
  lj_assertX(pt != NULL, "bad lua function prototype in sysprof stream");
126
  lj_wbuf_addbyte(buf, LJP_FRAME_LFUNC);
127
  lj_wbuf_addu64(buf, (uintptr_t)pt);
128
  lj_wbuf_addu64(buf, (uint64_t)pt->firstline);
129
}
130

131
static void stream_cfunc(struct lj_wbuf *buf, const GCfunc *func)
9✔
132
{
133
  lj_assertX(iscfunc(func), "bad C function in sysprof stream");
9✔
134
  lj_wbuf_addbyte(buf, LJP_FRAME_CFUNC);
9✔
135
  lj_wbuf_addu64(buf, (uintptr_t)func->c.f);
9✔
136
}
9✔
137

138
static void stream_ffunc(struct lj_wbuf *buf, const GCfunc *func)
×
139
{
140
  lj_assertX(isffunc(func), "bad fast function in sysprof stream");
×
141
  stream_ffunc_impl(buf, func->c.ffid);
×
142
}
×
143

144
static void stream_frame_lua(struct lj_wbuf *buf, const cTValue *frame)
238✔
145
{
146
  const GCfunc *func = frame_func(frame);
238✔
147
  lj_assertX(func != NULL, "bad function in sysprof stream");
238✔
148
  if (isluafunc(func))
238✔
149
    stream_lfunc(buf, func);
229✔
150
  else if (isffunc(func))
9✔
151
    stream_ffunc(buf, func);
×
152
  else if (iscfunc(func))
9✔
153
    stream_cfunc(buf, func);
9✔
154
  else
155
    /* Unreachable. */
156
    lj_assertX(0, "bad function type in sysprof stream");
238✔
157
}
238✔
158

159
static void stream_backtrace_lua(struct sysprof *sp, uint32_t vmstate)
10✔
160
{
161
  global_State *g = sp->g;
10✔
162
  struct lj_wbuf *buf = &sp->out;
10✔
163
  cTValue *top_frame = NULL, *frame = NULL, *bot = NULL;
10✔
164
  lua_State *L = NULL;
10✔
165

166
  lj_assertX(g != NULL, "uninitialized global state in sysprof state");
10✔
167
  L = gco2th(gcref(g->cur_L));
10✔
168
  lj_assertG(L != NULL, "uninitialized Lua state in sysprof state");
10✔
169
  /*
170
  ** Lua stack may be inconsistent during the execution of a
171
  ** fast-function, so instead of updating the `top_frame` for
172
  ** it, its `ffid` is set instead. The first frame on the
173
  ** result stack is streamed manually, and the rest of the
174
  ** stack is streamed based on the previous `top_frame` value.
175
  */
176
  if (vmstate == LJ_VMST_FFUNC) {
10✔
177
    uint8_t ffid = g->top_frame_info.ffid;
1✔
178
    stream_ffunc_impl(buf, ffid);
1✔
179
  }
180

181
  top_frame = g->top_frame_info.top_frame - 1;
10✔
182

183
  bot = tvref(L->stack) + LJ_FR2;
10✔
184
  /* Traverse frames backwards */
185
  for (frame = top_frame; frame > bot; frame = frame_prev(frame)) {
504✔
186
    if (frame_gc(frame) == obj2gco(L) || frame_isvarg(frame))
247✔
187
      continue;  /* Skip dummy frames. See lj_err_optype_call(). */
9✔
188
    stream_frame_lua(buf, frame);
238✔
189
  }
190

191
  lj_wbuf_addbyte(buf, LJP_FRAME_LUA_LAST);
10✔
192
}
10✔
193

194
static void *stream_frame_host(int frame_no, void *addr)
105✔
195
{
196
  struct sysprof *sp = &sysprof;
105✔
197
  /*
198
  ** We don't want the profiler stack to be streamed, as it will
199
  ** burden the profile with unnecessary information.
200
  */
201
  if (LJ_UNLIKELY(frame_no <= SYSPROF_HANDLER_STACK_DEPTH))
105✔
202
    return addr;
203
  else if (LJ_UNLIKELY(sp->opt.mode == LUAM_SYSPROF_LEAF &&
14✔
204
                         frame_no > SYSPROF_HANDLER_STACK_DEPTH))
205
    return NULL;
206

207
  lj_wbuf_addu64(&sp->out, (uintptr_t)addr);
14✔
208
  return addr;
14✔
209
}
210

211
static void default_backtrace_host(void *(writer)(int frame_no, void *addr))
16✔
212
{
213
  static void *backtrace_buf[SYSPROF_BACKTRACE_FRAME_MAX] = {};
16✔
214

215
  struct sysprof *sp = &sysprof;
16✔
216
  int max_depth = sp->opt.mode == LUAM_SYSPROF_LEAF
32✔
217
                  ? SYSPROF_HANDLER_STACK_DEPTH + 1
218
                  : SYSPROF_BACKTRACE_FRAME_MAX;
16✔
219
  const int depth = backtrace(backtrace_buf, max_depth);
16✔
220
  int level;
16✔
221

222
  lj_assertX(depth <= max_depth, "depth of C stack is too big");
16✔
223
  for (level = SYSPROF_HANDLER_STACK_DEPTH; level < depth; ++level) {
137✔
224
    if (!writer(level - SYSPROF_HANDLER_STACK_DEPTH + 1, backtrace_buf[level]))
105✔
225
      return;
226
  }
227
}
228

229
static void stream_backtrace_host(struct sysprof *sp)
16✔
230
{
231
  lj_assertX(sp->backtracer != NULL, "uninitialized sysprof backtracer");
16✔
232
  sp->backtracer(stream_frame_host);
16✔
233
  lj_wbuf_addu64(&sp->out, (uintptr_t)LJP_FRAME_HOST_LAST);
16✔
234
}
235

236
#if LJ_HASJIT
237
static void stream_trace(struct sysprof *sp, uint32_t vmstate)
×
238
{
239
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
×
240
  struct lj_wbuf *out = &sp->out;
×
241
  uint32_t traceno = sp->g->vmstate;
×
242
  jit_State *J = G2J(sp->g);
×
243
  GCtrace *trace = traceref(J, traceno);
×
244

245
  GCproto *startpt = gco2pt(gcref(trace->startpt));
×
246

247
  lj_wbuf_addu64(out, traceno);
×
248
  lj_wbuf_addu64(out, (uintptr_t)startpt);
×
249
  lj_wbuf_addu64(out, startpt->firstline);
×
250
}
×
251
#endif
252

253
static void stream_guest(struct sysprof *sp, uint32_t vmstate)
10✔
254
{
255
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
10✔
256
  stream_backtrace_lua(sp, vmstate);
10✔
257
  stream_backtrace_host(sp);
10✔
258
}
10✔
259

260
static void stream_host(struct sysprof *sp, uint32_t vmstate)
6✔
261
{
262
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
6✔
263
  stream_backtrace_host(sp);
6✔
264
}
6✔
265

266
typedef void (*event_streamer)(struct sysprof *sp, uint32_t vmstate);
267

268
static event_streamer event_streamers[] = {
269
  /* XXX: order is important */
270
  stream_host,  /* LJ_VMST_INTERP */
271
  stream_guest, /* LJ_VMST_LFUNC */
272
  stream_guest, /* LJ_VMST_FFUNC */
273
  stream_guest, /* LJ_VMST_CFUNC */
274
  stream_host,  /* LJ_VMST_GC */
275
  stream_host,  /* LJ_VMST_EXIT */
276
  stream_host,  /* LJ_VMST_RECORD */
277
  stream_host,  /* LJ_VMST_OPT */
278
  stream_host,  /* LJ_VMST_ASM */
279
#if LJ_HASJIT
280
  stream_trace  /* LJ_VMST_TRACE */
281
#endif
282
};
283

284
static void stream_event(struct sysprof *sp, uint32_t vmstate)
285
{
286
  event_streamer stream = NULL;
287

288
  lj_assertX(vmstfit4(vmstate), "vmstate don't fit in 4 bits");
289
  stream = event_streamers[vmstate];
290
  lj_assertX(stream != NULL, "uninitialized sysprof stream");
291
  stream(sp, vmstate);
292
}
293

294
/* -- Signal handler ------------------------------------------------------ */
295

296
static void sysprof_record_sample(struct sysprof *sp, siginfo_t *info)
297
{
298
  global_State *g = sp->g;
299
  uint32_t _vmstate = ~(uint32_t)(g->vmstate);
300
  uint32_t vmstate = _vmstate < LJ_VMST_TRACE ? _vmstate : LJ_VMST_TRACE;
301

302
  lj_assertX(pthread_self() == sp->thread,
303
             "bad thread during sysprof record sample");
304

305
  /* Caveat: order of counters must match vmstate order in <lj_obj.h>. */
306
  ((uint64_t *)&sp->counters)[vmstate]++;
307

308
  sp->counters.samples++;
309

310
  if (!stream_is_needed(sp))
311
    return;
312

313
  stream_event(sp, vmstate);
314
  if (LJ_UNLIKELY(lj_wbuf_test_flag(&sp->out, STREAM_ERRIO|STREAM_STOP))) {
315
    sp->saved_errno = lj_wbuf_errno(&sp->out);
316
    lj_wbuf_terminate(&sp->out);
317
    sp->state = SPS_HALT;
318
  }
319
}
320

321
static void sysprof_signal_handler(int sig, siginfo_t *info, void *ctx)
17✔
322
{
323
  struct sysprof *sp = &sysprof;
17✔
324
  UNUSED(sig);
17✔
325
  UNUSED(ctx);
17✔
326

327
  switch (sp->state) {
17✔
328
    case SPS_PROFILE:
17✔
329
      sysprof_record_sample(sp, info);
17✔
330
      break;
17✔
331

332
    case SPS_IDLE:
333
    case SPS_HALT:
334
      /* noop */
335
      break;
336

337
    default:
338
      lj_assertX(0, "bad sysprof profiler state");
339
      break;
340
  }
341
}
17✔
342

343
/* -- Internal ------------------------------------------------------------ */
344

345
static int sysprof_validate(struct sysprof *sp,
15✔
346
                            const struct luam_Sysprof_Options *opt)
347
{
348
  switch (sp->state) {
15✔
349
    case SPS_IDLE:
13✔
350
      if (opt->mode > LUAM_SYSPROF_CALLGRAPH) {
13✔
351
        return PROFILE_ERRUSE;
352
      } else if (opt->mode != LUAM_SYSPROF_DEFAULT &&
12✔
353
                 (opt->buf == NULL || opt->len == 0 || is_unconfigured(sp))) {
5✔
354
        return PROFILE_ERRUSE;
355
      } else if (opt->interval == 0) {
11✔
356
        return PROFILE_ERRUSE;
1✔
357
      }
358
      break;
359

360
    case SPS_PROFILE:
361
    case SPS_HALT:
362
      return PROFILE_ERRRUN;
363

364
    default:
365
      lj_assertX(0, "bad sysprof profiler state");
366
      break;
367
  }
368

369
  return PROFILE_SUCCESS;
370
}
371

372
static int sysprof_init(struct sysprof *sp, lua_State *L,
373
                        const struct luam_Sysprof_Options *opt)
374
{
375
  const int status = sysprof_validate(sp, opt);
376
  if (PROFILE_SUCCESS != status)
377
    return status;
378

379
  /* Copy validated options to sysprof state. */
380
  memcpy(&sp->opt, opt, sizeof(sp->opt));
381

382
  /* Init general fields. */
383
  sp->g = G(L);
384
  sp->thread = pthread_self();
385

386
  /* Reset counters. */
387
  memset(&sp->counters, 0, sizeof(sp->counters));
388

389
  /* Reset saved errno. */
390
  sp->saved_errno = 0;
391

392
  if (stream_is_needed(sp))
393
    lj_wbuf_init(&sp->out, sp->writer, opt->ctx, opt->buf, opt->len);
394

395
  return PROFILE_SUCCESS;
396
}
397

398
/* -- Public profiling API ------------------------------------------------ */
399

400
int lj_sysprof_set_writer(luam_Sysprof_writer writer) {
299✔
401
  struct sysprof *sp = &sysprof;
299✔
402

403
  if (sp->state != SPS_IDLE || writer == NULL)
299✔
404
    return PROFILE_ERRUSE;
405

406
  sp->writer = writer;
299✔
407
  if (!is_unconfigured(sp)) {
299✔
408
    sp->state = SPS_IDLE;
1✔
409
  }
410
  return PROFILE_SUCCESS;
411
}
412

413
int lj_sysprof_set_on_stop(luam_Sysprof_on_stop on_stop) {
299✔
414
  struct sysprof *sp = &sysprof;
299✔
415

416
  if (sp->state != SPS_IDLE || on_stop == NULL)
299✔
417
    return PROFILE_ERRUSE;
418

419
  sp->on_stop = on_stop;
299✔
420
  if (!is_unconfigured(sp)) {
299✔
421
    sp->state = SPS_IDLE;
1✔
422
  }
423
  return PROFILE_SUCCESS;
424
}
425

426
int lj_sysprof_set_backtracer(luam_Sysprof_backtracer backtracer) {
298✔
427
  struct sysprof *sp = &sysprof;
298✔
428

429
  if (sp->state != SPS_IDLE)
298✔
430
    return PROFILE_ERRUSE;
431
  if (backtracer == NULL) {
298✔
432
    sp->backtracer = default_backtrace_host;
298✔
433
    /*
434
    ** XXX: `backtrace` is not signal-safe, according to man,
435
    ** because it is lazy loaded on the first call, which triggers
436
    ** allocations. We need to call `backtrace` before starting profiling
437
    ** to avoid lazy loading.
438
    */
439
    void *dummy = NULL;
298✔
440
    backtrace(&dummy, 1);
298✔
441
  }
442
  else {
443
    sp->backtracer = backtracer;
×
444
  }
445
  if (!is_unconfigured(sp)) {
298✔
446
    sp->state = SPS_IDLE;
298✔
447
  }
448
  return PROFILE_SUCCESS;
449
}
450

451
int lj_sysprof_start(lua_State *L, const struct luam_Sysprof_Options *opt)
15✔
452
{
453
  struct sysprof *sp = &sysprof;
15✔
454

455
  int status = sysprof_init(sp, L, opt);
15✔
456
  if (PROFILE_SUCCESS != status) {
15✔
457
    if (NULL != sp->on_stop) {
5✔
458
      /*
459
      ** Initialization may fail in case of unconfigured sysprof,
460
      ** so we cannot guarantee cleaning up resources in this case.
461
      */
462
      sp->on_stop(opt->ctx, opt->buf);
5✔
463
    }
464
    return status;
5✔
465
  }
466

467
  sp->state = SPS_PROFILE;
10✔
468

469
  if (stream_is_needed(sp)) {
10✔
470
    stream_prologue(sp);
4✔
471
    if (LJ_UNLIKELY(lj_wbuf_test_flag(&sp->out, STREAM_ERRIO|STREAM_STOP))) {
4✔
472
      /* on_stop call may change errno value. */
473
      const int saved_errno = lj_wbuf_errno(&sp->out);
×
474
      /* Ignore possible errors. mp->out.buf may be NULL here. */
475
      sp->on_stop(opt->ctx, sp->out.buf);
×
476
      lj_wbuf_terminate(&sp->out);
×
477
      sp->state = SPS_IDLE;
×
478
      errno = saved_errno;
×
479
      return PROFILE_ERRIO;
×
480
    }
481
  }
482

483
  sp->timer.opt.interval_msec = opt->interval;
10✔
484
  sp->timer.opt.handler = sysprof_signal_handler;
10✔
485
  lj_profile_timer_start(&sp->timer);
10✔
486

487
  return PROFILE_SUCCESS;
10✔
488
}
489

490
int lj_sysprof_stop(lua_State *L)
305✔
491
{
492
  struct sysprof *sp = &sysprof;
305✔
493
  global_State *g = sp->g;
305✔
494
  struct lj_wbuf *out = &sp->out;
305✔
495

496
  if (SPS_IDLE == sp->state)
305✔
497
    return PROFILE_ERRRUN;
498
  else if (G(L) != g)
10✔
499
    return PROFILE_ERRUSE;
500

501
  lj_profile_timer_stop(&sp->timer);
10✔
502

503
  if (SPS_HALT == sp->state) {
10✔
504
    errno = sp->saved_errno;
×
505
    sp->state = SPS_IDLE;
×
506
    /* wbuf was terminated when error occurred. */
507
    return PROFILE_ERRIO;
×
508
  }
509

510
  sp->state = SPS_IDLE;
10✔
511

512
  if (stream_is_needed(sp)) {
10✔
513
    int cb_status = 0;
4✔
514

515
    stream_epilogue(sp);
4✔
516
    lj_wbuf_flush(out);
4✔
517

518
    cb_status = sp->on_stop(sp->opt.ctx, out->buf);
4✔
519
    if (LJ_UNLIKELY(lj_wbuf_test_flag(out, STREAM_ERRIO | STREAM_STOP)) ||
4✔
520
        cb_status != 0) {
521
      errno = lj_wbuf_errno(out);
×
522
      lj_wbuf_terminate(out);
×
523
      return PROFILE_ERRIO;
×
524
    }
525

526
    lj_wbuf_terminate(out);
4✔
527
  }
528

529
  return PROFILE_SUCCESS;
530
}
531

532
int lj_sysprof_report(struct luam_Sysprof_Counters *counters)
4✔
533
{
534
  const struct sysprof *sp = &sysprof;
4✔
535
  if (sp->state != SPS_IDLE)
4✔
536
    return PROFILE_ERRUSE;
537
  memcpy(counters, &sp->counters, sizeof(sp->counters));
4✔
538
  return PROFILE_SUCCESS;
4✔
539
}
540

541
void lj_sysprof_add_proto(const struct GCproto *pt)
59,343✔
542
{
543
  struct sysprof *sp = &sysprof;
59,343✔
544

545
  if (sp->state != SPS_PROFILE || sp->opt.mode == LUAM_SYSPROF_DEFAULT)
59,343✔
546
    return;
547

548
  /*
549
  ** XXX: Avoid sampling during the symtab extension. That shouldn't have any
550
  ** significant effect on profile precision, but if it does, it's better to
551
  ** implement an async-safe queue for the symtab events.
552
  */
553
  sp->state = SPS_IDLE;
1✔
554
  lj_wbuf_addbyte(&sp->out, LJP_SYMTAB_LFUNC_EVENT);
1✔
555
  lj_symtab_dump_proto(&sp->out, pt);
1✔
556
  sp->state = SPS_PROFILE;
1✔
557
}
558

559
#if LJ_HASJIT
560
void lj_sysprof_add_trace(const struct GCtrace *tr)
5,322✔
561
{
562
  struct sysprof *sp = &sysprof;
5,322✔
563

564
  if (sp->state != SPS_PROFILE || sp->opt.mode == LUAM_SYSPROF_DEFAULT)
5,322✔
565
    return;
566

567
  /* See the comment about the sysprof state above. */
568
  sp->state = SPS_IDLE;
×
569
  lj_wbuf_addbyte(&sp->out, LJP_SYMTAB_TRACE_EVENT);
×
570
  lj_symtab_dump_trace(&sp->out, tr);
×
571
  sp->state = SPS_PROFILE;
×
572
}
573
#endif /* LJ_HASJIT */
574

575
#else /* LJ_HASSYSPROF */
576

577
int lj_sysprof_set_writer(luam_Sysprof_writer writer) {
578
  UNUSED(writer);
579
  return PROFILE_ERRUSE;
580
}
581

582
int lj_sysprof_set_on_stop(luam_Sysprof_on_stop on_stop) {
583
  UNUSED(on_stop);
584
  return PROFILE_ERRUSE;
585
}
586

587
int lj_sysprof_set_backtracer(luam_Sysprof_backtracer backtracer) {
588
  UNUSED(backtracer);
589
  return PROFILE_ERRUSE;
590
}
591

592
int lj_sysprof_start(lua_State *L, const struct luam_Sysprof_Options *opt)
593
{
594
  UNUSED(L);
595
  return PROFILE_ERRUSE;
596
}
597

598
int lj_sysprof_stop(lua_State *L)
599
{
600
  UNUSED(L);
601
  return PROFILE_ERRUSE;
602
}
603

604
int lj_sysprof_report(struct luam_Sysprof_Counters *counters)
605
{
606
  UNUSED(counters);
607
  return PROFILE_ERRUSE;
608
}
609

610
void lj_sysprof_add_proto(const struct GCproto *pt)
611
{
612
  UNUSED(pt);
613
}
614

615
#if LJ_HASJIT
616
void lj_sysprof_add_trace(const struct GCtrace *tr)
617
{
618
  UNUSED(tr);
619
}
620
#endif /* LJ_HASJIT */
621

622
#endif /* LJ_HASSYSPROF */
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