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

tarantool / luajit / 7276254962

20 Dec 2023 01:40PM UTC coverage: 88.567% (+0.006%) from 88.561%
7276254962

push

github

igormunkin
test: fix flaky finalizer error handler tests

Finalizer error tests require a certain amount of cdata objects
to be allocated for the issue to strike. It turns out that the
present number of iterations may not be sufficient. This patch
fixes the issue by increasing the number of iterations to 10000.

Follows up tarantool/tarantool#9145

Reviewed-by: Sergey Kaplun <skaplun@tarantool.org>
Signed-off-by: Igor Munkin <imun@tarantool.org>

5378 of 5988 branches covered (0.0%)

Branch coverage included in aggregate %.

20613 of 23358 relevant lines covered (88.25%)

2763551.65 hits per line

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

85.78
/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
  uint32_t lib_adds; /* Number of libs loaded. Monotonic. */
79
};
80
/*
81
** XXX: Only one VM can be profiled at a time.
82
*/
83

84
static struct sysprof sysprof = {0};
85

86
/* --- Stream ------------------------------------------------------------- */
87

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

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

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

101
static void stream_prologue(struct sysprof *sp)
4✔
102
{
103
  lj_symtab_dump(&sp->out, sp->g, &sp->lib_adds);
4✔
104
  lj_wbuf_addn(&sp->out, ljp_header, sizeof(ljp_header));
4✔
105
}
4✔
106

107
static void stream_epilogue(struct sysprof *sp)
4✔
108
{
109
  lj_wbuf_addbyte(&sp->out, LJP_EPILOGUE_BYTE);
4✔
110
}
111

112
static void stream_ffunc_impl(struct lj_wbuf *buf, uint8_t ffid)
1✔
113
{
114
  lj_wbuf_addbyte(buf, LJP_FRAME_FFUNC);
1✔
115
  lj_wbuf_addu64(buf, ffid);
1✔
116
}
1✔
117

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

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

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

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

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

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

178
  top_frame = g->top_frame_info.top_frame - 1;
9✔
179

180
  bot = tvref(L->stack) + LJ_FR2;
9✔
181
  /* Traverse frames backwards */
182
  for (frame = top_frame; frame > bot; frame = frame_prev(frame)) {
437✔
183
    if (frame_gc(frame) == obj2gco(L) || frame_isvarg(frame))
214✔
184
      continue;  /* Skip dummy frames. See lj_err_optype_call(). */
8✔
185
    stream_frame_lua(buf, frame);
206✔
186
  }
187

188
  lj_wbuf_addbyte(buf, LJP_FRAME_LUA_LAST);
9✔
189
}
9✔
190

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

204
  lj_wbuf_addu64(&sp->out, (uintptr_t)addr);
15✔
205
  return addr;
15✔
206
}
207

208
static void default_backtrace_host(void *(writer)(int frame_no, void *addr))
17✔
209
{
210
  static void *backtrace_buf[SYSPROF_BACKTRACE_FRAME_MAX] = {};
17✔
211

212
  struct sysprof *sp = &sysprof;
17✔
213
  int max_depth = sp->opt.mode == LUAM_SYSPROF_LEAF
34✔
214
                  ? SYSPROF_HANDLER_STACK_DEPTH + 1
215
                  : SYSPROF_BACKTRACE_FRAME_MAX;
17✔
216
  const int depth = backtrace(backtrace_buf, max_depth);
17✔
217
  int level;
17✔
218

219
  lj_assertX(depth <= max_depth, "depth of C stack is too big");
17✔
220
  for (level = SYSPROF_HANDLER_STACK_DEPTH; level < depth; ++level) {
146✔
221
    if (!writer(level - SYSPROF_HANDLER_STACK_DEPTH + 1, backtrace_buf[level]))
112✔
222
      return;
223
  }
224
}
225

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

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

242
  GCproto *startpt = gco2pt(gcref(trace->startpt));
×
243

244
  lj_wbuf_addu64(out, traceno);
×
245
  lj_wbuf_addu64(out, (uintptr_t)startpt);
×
246
  lj_wbuf_addu64(out, startpt->firstline);
×
247
}
×
248
#endif
249

250
static void stream_guest(struct sysprof *sp, uint32_t vmstate)
9✔
251
{
252
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
9✔
253
  stream_backtrace_lua(sp, vmstate);
9✔
254
  stream_backtrace_host(sp);
9✔
255
}
9✔
256

257
static void stream_host(struct sysprof *sp, uint32_t vmstate)
8✔
258
{
259
  struct lua_State *L = gco2th(gcref(sp->g->cur_L));
8✔
260
  lj_symtab_dump_newc(&sp->lib_adds, &sp->out, LJP_SYMTAB_CFUNC_EVENT, L);
8✔
261
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
8✔
262
  stream_backtrace_host(sp);
8✔
263
}
8✔
264

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

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

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

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

293
/* -- Signal handler ------------------------------------------------------ */
294

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

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

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

307
  sp->counters.samples++;
308

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

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

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

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

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

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

342
/* -- Internal ------------------------------------------------------------ */
343

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

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

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

368
  return PROFILE_SUCCESS;
369
}
370

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

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

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

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

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

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

394
  return PROFILE_SUCCESS;
395
}
396

397
/* -- Public profiling API ------------------------------------------------ */
398

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

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

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

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

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

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

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

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

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

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

466
  sp->state = SPS_PROFILE;
10✔
467

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

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

486
  return PROFILE_SUCCESS;
10✔
487
}
488

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

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

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

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

509
  sp->state = SPS_IDLE;
10✔
510

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

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

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

525
    lj_wbuf_terminate(out);
4✔
526
  }
527

528
  return PROFILE_SUCCESS;
529
}
530

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

540
void lj_sysprof_add_proto(const struct GCproto *pt)
57,764✔
541
{
542
  struct sysprof *sp = &sysprof;
57,764✔
543

544
  if (sp->state != SPS_PROFILE || sp->opt.mode == LUAM_SYSPROF_DEFAULT)
57,764✔
545
    return;
546

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

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

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

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

574
#else /* LJ_HASSYSPROF */
575

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

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

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

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

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

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

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

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

621
#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

© 2026 Coveralls, Inc