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

tarantool / luajit / 10774454435

09 Sep 2024 01:39PM UTC coverage: 92.806% (-0.08%) from 92.882%
10774454435

push

github

Buristan
FFI: Drop finalizer table rehash after GC cycle.

Reported by Sergey Kaplun.

(cherry picked from commit fb22d0f80)

The raising of the OOM error when rehashing the finalizer table (when we
can't allocate a new hash part) leads to crashes in either
`lj_trace_exit()` or `lj_trace_unwind()` due to unprotected error
raising, which either has no DWARF eh_frame [1] or loses the context of
the JIT compiler.

This patch drops rehashing of the cdata finalizer table to avoid these
crashes. It will prevent the cdata finalizer table from shrinking when a
huge amount of the cdata objects is collected by the GC. OTOH, the
finzlizer table most probably will grow anyway to the old size, so this
is not crucial.

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

[1]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html

Part of tarantool/tarantool#10199
Resolves tarantool/tarantool#10290

5681 of 6025 branches covered (94.29%)

Branch coverage included in aggregate %.

21655 of 23430 relevant lines covered (92.42%)

2945096.28 hits per line

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

77.92
/src/lj_wbuf.c
1
/*
2
** Low-level writer for LuaJIT.
3
**
4
** Major portions taken verbatim or adapted from the LuaVela.
5
** Copyright (C) 2015-2019 IPONWEB Ltd.
6
*/
7

8
#define lj_wbuf_c
9
#define LUA_CORE
10

11
#include <errno.h>
12

13
#include "lj_obj.h"
14
#include "lj_wbuf.h"
15
#include "lj_utils.h"
16

17
static LJ_AINLINE void wbuf_set_flag(struct lj_wbuf *buf, uint8_t flag)
×
18
{
19
  buf->flags |= flag;
×
20
}
21

22
static LJ_AINLINE void wbuf_save_errno(struct lj_wbuf *buf)
×
23
{
24
  buf->saved_errno = errno;
×
25
}
×
26

27
static LJ_AINLINE size_t wbuf_len(const struct lj_wbuf *buf)
2,213,959✔
28
{
29
  return (size_t)(buf->pos - buf->buf);
2,213,959✔
30
}
31

32
static LJ_AINLINE size_t wbuf_left(const struct lj_wbuf *buf)
2,213,938✔
33
{
34
  return buf->size - wbuf_len(buf);
2,213,938✔
35
}
36

37
void lj_wbuf_init(struct lj_wbuf *buf, lj_wbuf_writer writer,
40✔
38
                  void *ctx, uint8_t *mem, size_t size)
39
{
40
  buf->ctx = ctx;
40✔
41
  buf->writer = writer;
40✔
42
  buf->buf = mem;
40✔
43
  buf->pos = mem;
40✔
44
  buf->size = size;
40✔
45
  buf->flags = 0;
40✔
46
  buf->saved_errno = 0;
40✔
47
}
20✔
48

49
void LJ_FASTCALL lj_wbuf_terminate(struct lj_wbuf *buf)
20✔
50
{
51
  lj_wbuf_init(buf, NULL, NULL, NULL, 0);
20✔
52
}
20✔
53

54
static LJ_AINLINE void wbuf_reserve(struct lj_wbuf *buf, size_t n)
2,213,938✔
55
{
56
  lj_assertX(n <= buf->size, "wbuf overflow");
2,213,938✔
57
  if (LJ_UNLIKELY(wbuf_left(buf) < n))
2,213,938✔
58
    lj_wbuf_flush(buf);
1✔
59
}
60

61
/* Writes a byte to the output buffer. */
62
void LJ_FASTCALL lj_wbuf_addbyte(struct lj_wbuf *buf, uint8_t b)
554,020✔
63
{
64
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
554,020✔
65
    return;
66
  wbuf_reserve(buf, sizeof(b));
554,020✔
67
  *buf->pos++ = b;
554,020✔
68
}
69

70
/* Writes an unsigned integer which is at most 64 bits long to the output. */
71
void LJ_FASTCALL lj_wbuf_addu64(struct lj_wbuf *buf, uint64_t n)
1,110,044✔
72
{
73
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
1,110,044✔
74
    return;
75
  wbuf_reserve(buf, LEB128_U64_MAXSIZE);
1,110,044✔
76
  buf->pos += (ptrdiff_t)lj_utils_write_uleb128(buf->pos, n);
1,110,044✔
77
}
78

79
/* Writes n bytes from an arbitrary buffer src to the buffer. */
80
void lj_wbuf_addn(struct lj_wbuf *buf, const void *src, size_t n)
549,874✔
81
{
82
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
549,874✔
83
    return;
84
  /*
85
  ** Very unlikely: We are told to write a large buffer at once.
86
  ** Buffer doesn't belong to us so we must to pump data
87
  ** through the buffer.
88
  */
89
  while (LJ_UNLIKELY(n > buf->size)) {
549,874✔
90
    const size_t left = wbuf_left(buf);
×
91
    memcpy(buf->pos, src, left);
×
92
    buf->pos += (ptrdiff_t)left;
×
93
    lj_wbuf_flush(buf);
×
94
    src = (uint8_t *)src + (ptrdiff_t)left;
×
95
    n -= left;
×
96
  }
97

98
  wbuf_reserve(buf, n);
549,874✔
99
  memcpy(buf->pos, src, n);
549,874✔
100
  buf->pos += (ptrdiff_t)n;
549,874✔
101
}
102

103
/* Writes a \0-terminated C string to the output buffer. */
104
void LJ_FASTCALL lj_wbuf_addstring(struct lj_wbuf *buf, const char *s)
549,834✔
105
{
106
  const size_t l = strlen(s);
549,834✔
107

108
  /* Check that profiling is still active is made in the callee's scope. */
109
  lj_wbuf_addu64(buf, (uint64_t)l);
549,834✔
110
  lj_wbuf_addn(buf, s, l);
549,834✔
111
}
549,834✔
112

113
void LJ_FASTCALL lj_wbuf_flush(struct lj_wbuf *buf)
21✔
114
{
115
  const size_t len = wbuf_len(buf);
21✔
116
  size_t written;
21✔
117

118
  if (LJ_UNLIKELY(lj_wbuf_test_flag(buf, STREAM_STOP)))
21✔
119
    return;
120

121
  written = buf->writer((const void **)&buf->buf, len, buf->ctx);
21✔
122

123
  if (LJ_UNLIKELY(written < len)) {
21✔
124
    wbuf_set_flag(buf, STREAM_ERRIO);
×
125
    wbuf_save_errno(buf);
×
126
  }
127
  if (LJ_UNLIKELY(buf->buf == NULL)) {
21✔
128
    wbuf_set_flag(buf, STREAM_STOP);
×
129
    wbuf_save_errno(buf);
×
130
  }
131
  buf->pos = buf->buf;
21✔
132
}
133

134
int LJ_FASTCALL lj_wbuf_test_flag(const struct lj_wbuf *buf, uint8_t flag)
2,217,898✔
135
{
136
  return buf->flags & flag;
2,213,959✔
137
}
138

139
int LJ_FASTCALL lj_wbuf_errno(const struct lj_wbuf *buf)
×
140
{
141
  return buf->saved_errno;
×
142
}
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