Coverage Report

Created: 2026-07-07 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/duckdb/third_party/jemalloc/src/malloc_io.c
Line
Count
Source
1
#include "jemalloc/internal/jemalloc_preamble.h"
2
#include "jemalloc/internal/jemalloc_internal_includes.h"
3
4
#include "jemalloc/internal/malloc_io.h"
5
#include "jemalloc/internal/util.h"
6
7
#ifdef assert
8
#  undef assert
9
#endif
10
#ifdef not_reached
11
#  undef not_reached
12
#endif
13
#ifdef not_implemented
14
#  undef not_implemented
15
#endif
16
#ifdef assert_not_implemented
17
#  undef assert_not_implemented
18
#endif
19
20
/*
21
 * Define simple versions of assertion macros that won't recurse in case
22
 * of assertion failures in malloc_*printf().
23
 */
24
100
#define assert(e) do {             \
25
100
  if (config_debug && !(e)) {         \
26
0
    malloc_write("<jemalloc>: Failed assertion\n");   \
27
0
    abort();            \
28
0
  }                \
29
100
} while (0)
30
31
0
#define not_reached() do {           \
32
0
  if (config_debug) {           \
33
0
    malloc_write("<jemalloc>: Unreachable code reached\n"); \
34
0
    abort();            \
35
0
  }               \
36
0
  unreachable();             \
37
0
} while (0)
38
39
0
#define not_implemented() do {           \
40
0
  if (config_debug) {           \
41
0
    malloc_write("<jemalloc>: Not implemented\n");    \
42
0
    abort();            \
43
0
  }               \
44
0
} while (0)
45
46
100
#define assert_not_implemented(e) do {         \
47
100
  if (unlikely(config_debug && !(e))) {       \
48
0
    not_implemented();         \
49
0
  }                \
50
100
} while (0)
51
52
/******************************************************************************/
53
/* Function prototypes for non-inline static functions. */
54
55
200
#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
56
static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
57
    size_t *slen_p);
58
#define D2S_BUFSIZE (1 + U2S_BUFSIZE)
59
static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p);
60
#define O2S_BUFSIZE (1 + U2S_BUFSIZE)
61
static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p);
62
#define X2S_BUFSIZE (2 + U2S_BUFSIZE)
63
static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
64
    size_t *slen_p);
65
66
/******************************************************************************/
67
68
/* malloc_message() setup. */
69
void
70
0
wrtmessage(void *cbopaque, const char *s) {
71
0
  malloc_write_fd(STDERR_FILENO, s, strlen(s));
72
0
}
73
74
JEMALLOC_EXPORT void  (*je_malloc_message)(void *, const char *s);
75
76
/*
77
 * Wrapper around malloc_message() that avoids the need for
78
 * je_malloc_message(...) throughout the code.
79
 */
80
void
81
0
malloc_write(const char *s) {
82
#ifdef DEBUG
83
  if (je_malloc_message != NULL) {
84
    je_malloc_message(NULL, s);
85
  } else {
86
    wrtmessage(NULL, s);
87
  }
88
#endif
89
0
}
90
91
/*
92
 * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
93
 * provide a wrapper.
94
 */
95
int
96
0
buferror(int err, char *buf, size_t buflen) {
97
#ifdef _WIN32
98
  FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
99
      (LPSTR)buf, (DWORD)buflen, NULL);
100
  return 0;
101
#elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) && defined(_GNU_SOURCE)
102
  char *b = strerror_r(err, buf, buflen);
103
  if (b != buf) {
104
    strncpy(buf, b, buflen);
105
    buf[buflen-1] = '\0';
106
  }
107
  return 0;
108
#else
109
0
  return strerror_r(err, buf, buflen);
110
0
#endif
111
0
}
112
113
uintmax_t
114
36.1k
malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) {
115
36.1k
  uintmax_t ret, digit;
116
36.1k
  unsigned b;
117
36.1k
  bool neg;
118
36.1k
  const char *p, *ns;
119
120
36.1k
  p = nptr;
121
36.1k
  if (base < 0 || base == 1 || base > 36) {
122
0
    ns = p;
123
0
    set_errno(EINVAL);
124
0
    ret = UINTMAX_MAX;
125
0
    goto label_return;
126
0
  }
127
36.1k
  b = base;
128
129
  /* Swallow leading whitespace and get sign, if any. */
130
36.1k
  neg = false;
131
36.1k
  while (true) {
132
36.1k
    switch (*p) {
133
0
    case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
134
0
      p++;
135
0
      break;
136
0
    case '-':
137
0
      neg = true;
138
0
      JEMALLOC_FALLTHROUGH;
139
0
    case '+':
140
0
      p++;
141
0
      JEMALLOC_FALLTHROUGH;
142
36.1k
    default:
143
36.1k
      goto label_prefix;
144
36.1k
    }
145
36.1k
  }
146
147
  /* Get prefix, if any. */
148
36.1k
  label_prefix:
149
  /*
150
   * Note where the first non-whitespace/sign character is so that it is
151
   * possible to tell whether any digits are consumed (e.g., "  0" vs.
152
   * "  -x").
153
   */
154
36.1k
  ns = p;
155
36.1k
  if (*p == '0') {
156
0
    switch (p[1]) {
157
0
    case '0': case '1': case '2': case '3': case '4': case '5':
158
0
    case '6': case '7':
159
0
      if (b == 0) {
160
0
        b = 8;
161
0
      }
162
0
      if (b == 8) {
163
0
        p++;
164
0
      }
165
0
      break;
166
0
    case 'X': case 'x':
167
0
      switch (p[2]) {
168
0
      case '0': case '1': case '2': case '3': case '4':
169
0
      case '5': case '6': case '7': case '8': case '9':
170
0
      case 'A': case 'B': case 'C': case 'D': case 'E':
171
0
      case 'F':
172
0
      case 'a': case 'b': case 'c': case 'd': case 'e':
173
0
      case 'f':
174
0
        if (b == 0) {
175
0
          b = 16;
176
0
        }
177
0
        if (b == 16) {
178
0
          p += 2;
179
0
        }
180
0
        break;
181
0
      default:
182
0
        break;
183
0
      }
184
0
      break;
185
0
    default:
186
0
      p++;
187
0
      ret = 0;
188
0
      goto label_return;
189
0
    }
190
0
  }
191
36.1k
  if (b == 0) {
192
30
    b = 10;
193
30
  }
194
195
  /* Convert. */
196
36.1k
  ret = 0;
197
180k
  while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b)
198
36.1k
      || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b)
199
144k
      || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) {
200
144k
    uintmax_t pret = ret;
201
144k
    ret *= b;
202
144k
    ret += digit;
203
144k
    if (ret < pret) {
204
      /* Overflow. */
205
0
      set_errno(ERANGE);
206
0
      ret = UINTMAX_MAX;
207
0
      goto label_return;
208
0
    }
209
144k
    p++;
210
144k
  }
211
36.1k
  if (neg) {
212
0
    ret = (uintmax_t)(-((intmax_t)ret));
213
0
  }
214
215
36.1k
  if (p == ns) {
216
    /* No conversion performed. */
217
0
    set_errno(EINVAL);
218
0
    ret = UINTMAX_MAX;
219
0
    goto label_return;
220
0
  }
221
222
36.1k
label_return:
223
36.1k
  if (endptr != NULL) {
224
30
    if (p == ns) {
225
      /* No characters were converted. */
226
0
      *endptr = (char *)nptr;
227
30
    } else {
228
30
      *endptr = (char *)p;
229
30
    }
230
30
  }
231
36.1k
  return ret;
232
36.1k
}
233
234
static char *
235
100
u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) {
236
100
  unsigned i;
237
238
100
  i = U2S_BUFSIZE - 1;
239
100
  s[i] = '\0';
240
100
  switch (base) {
241
100
  case 10:
242
167
    do {
243
167
      i--;
244
167
      s[i] = "0123456789"[x % (uint64_t)10];
245
167
      x /= (uint64_t)10;
246
167
    } while (x > 0);
247
100
    break;
248
0
  case 16: {
249
0
    const char *digits = (uppercase)
250
0
        ? "0123456789ABCDEF"
251
0
        : "0123456789abcdef";
252
253
0
    do {
254
0
      i--;
255
0
      s[i] = digits[x & 0xf];
256
0
      x >>= 4;
257
0
    } while (x > 0);
258
0
    break;
259
0
  } default: {
260
0
    const char *digits = (uppercase)
261
0
        ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
262
0
        : "0123456789abcdefghijklmnopqrstuvwxyz";
263
264
0
    assert(base >= 2 && base <= 36);
265
0
    do {
266
0
      i--;
267
0
      s[i] = digits[x % (uint64_t)base];
268
0
      x /= (uint64_t)base;
269
0
    } while (x > 0);
270
0
  }}
271
272
100
  *slen_p = U2S_BUFSIZE - 1 - i;
273
100
  return &s[i];
274
100
}
275
276
static char *
277
0
d2s(intmax_t x, char sign, char *s, size_t *slen_p) {
278
0
  bool neg;
279
280
0
  if ((neg = (x < 0))) {
281
0
    x = -x;
282
0
  }
283
0
  s = u2s(x, 10, false, s, slen_p);
284
0
  if (neg) {
285
0
    sign = '-';
286
0
  }
287
0
  switch (sign) {
288
0
  case '-':
289
0
    if (!neg) {
290
0
      break;
291
0
    }
292
0
    JEMALLOC_FALLTHROUGH;
293
0
  case ' ':
294
0
  case '+':
295
0
    s--;
296
0
    (*slen_p)++;
297
0
    *s = sign;
298
0
    break;
299
0
  default: not_reached();
300
0
  }
301
0
  return s;
302
0
}
303
304
static char *
305
0
o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) {
306
0
  s = u2s(x, 8, false, s, slen_p);
307
0
  if (alt_form && *s != '0') {
308
0
    s--;
309
0
    (*slen_p)++;
310
0
    *s = '0';
311
0
  }
312
0
  return s;
313
0
}
314
315
static char *
316
0
x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) {
317
0
  s = u2s(x, 16, uppercase, s, slen_p);
318
0
  if (alt_form) {
319
0
    s -= 2;
320
0
    (*slen_p) += 2;
321
0
    s[0] = '0';
322
0
    s[1] = uppercase ? 'X' : 'x';
323
0
  }
324
0
  return s;
325
0
}
326
327
JEMALLOC_COLD
328
size_t
329
100
malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
330
100
  size_t i;
331
100
  const char *f;
332
333
100
#define APPEND_C(c) do {           \
334
100
  if (i < size) {             \
335
100
    str[i] = (c);           \
336
100
  }                \
337
100
  i++;                \
338
100
} while (0)
339
200
#define APPEND_S(s, slen) do {           \
340
200
  if (i < size) {             \
341
200
    size_t cpylen = (slen <= size - i) ? slen : size - i; \
342
200
    memcpy(&str[i], s, cpylen);       \
343
200
  }               \
344
200
  i += slen;              \
345
200
} while (0)
346
200
#define APPEND_PADDED_S(s, slen, width, left_justify) do {   \
347
  /* Left padding. */            \
348
200
  size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ?  \
349
0
      (size_t)width - slen : 0);         \
350
200
  if (!left_justify && pad_len != 0) {       \
351
0
    size_t j;           \
352
0
    for (j = 0; j < pad_len; j++) {       \
353
0
      if (pad_zero) {         \
354
0
        APPEND_C('0');        \
355
0
      } else {         \
356
0
        APPEND_C(' ');        \
357
0
      }           \
358
0
    }             \
359
0
  }                \
360
  /* Value. */              \
361
200
  APPEND_S(s, slen);            \
362
  /* Right padding. */            \
363
200
  if (left_justify && pad_len != 0) {       \
364
0
    size_t j;           \
365
0
    for (j = 0; j < pad_len; j++) {       \
366
0
      APPEND_C(' ');          \
367
0
    }             \
368
0
  }                \
369
200
} while (0)
370
100
#define GET_ARG_NUMERIC(val, len) do {         \
371
100
  switch ((unsigned char)len) {         \
372
0
  case '?':             \
373
0
    val = va_arg(ap, int);          \
374
0
    break;             \
375
100
  case '?' | 0x80:            \
376
100
    val = va_arg(ap, unsigned int);       \
377
100
    break;             \
378
0
  case 'l':             \
379
0
    val = va_arg(ap, long);         \
380
0
    break;             \
381
0
  case 'l' | 0x80:            \
382
0
    val = va_arg(ap, unsigned long);      \
383
0
    break;             \
384
0
  case 'q':             \
385
0
    val = va_arg(ap, long long);        \
386
0
    break;             \
387
0
  case 'q' | 0x80:            \
388
0
    val = va_arg(ap, unsigned long long);     \
389
0
    break;             \
390
0
  case 'j':             \
391
0
    val = va_arg(ap, intmax_t);       \
392
0
    break;             \
393
0
  case 'j' | 0x80:            \
394
0
    val = va_arg(ap, uintmax_t);        \
395
0
    break;             \
396
0
  case 't':             \
397
0
    val = va_arg(ap, ptrdiff_t);        \
398
0
    break;             \
399
0
  case 'z':             \
400
0
    val = va_arg(ap, ssize_t);        \
401
0
    break;             \
402
0
  case 'z' | 0x80:            \
403
0
    val = va_arg(ap, size_t);       \
404
0
    break;             \
405
0
  case 'p': /* Synthetic; used for %p. */       \
406
0
    val = va_arg(ap, uintptr_t);        \
407
0
    break;             \
408
0
  default:              \
409
0
    not_reached();           \
410
0
    val = 0;           \
411
100
  }               \
412
100
} while (0)
413
414
100
  i = 0;
415
100
  f = format;
416
400
  while (true) {
417
400
    switch (*f) {
418
100
    case '\0': goto label_out;
419
200
    case '%': {
420
200
      bool alt_form = false;
421
200
      bool left_justify = false;
422
200
      bool plus_space = false;
423
200
      bool plus_plus = false;
424
200
      int prec = -1;
425
200
      int width = -1;
426
200
      unsigned char len = '?';
427
200
      char *s;
428
200
      size_t slen;
429
200
      bool pad_zero = false;
430
431
200
      f++;
432
      /* Flags. */
433
200
      while (true) {
434
200
        switch (*f) {
435
0
        case '#':
436
0
          assert(!alt_form);
437
0
          alt_form = true;
438
0
          break;
439
0
        case '-':
440
0
          assert(!left_justify);
441
0
          left_justify = true;
442
0
          break;
443
0
        case ' ':
444
0
          assert(!plus_space);
445
0
          plus_space = true;
446
0
          break;
447
0
        case '+':
448
0
          assert(!plus_plus);
449
0
          plus_plus = true;
450
0
          break;
451
200
        default: goto label_width;
452
200
        }
453
0
        f++;
454
0
      }
455
      /* Width. */
456
200
      label_width:
457
200
      switch (*f) {
458
0
      case '*':
459
0
        width = va_arg(ap, int);
460
0
        f++;
461
0
        if (width < 0) {
462
0
          left_justify = true;
463
0
          width = -width;
464
0
        }
465
0
        break;
466
0
      case '0':
467
0
        pad_zero = true;
468
0
        JEMALLOC_FALLTHROUGH;
469
0
      case '1': case '2': case '3': case '4':
470
0
      case '5': case '6': case '7': case '8': case '9': {
471
0
        uintmax_t uwidth;
472
0
        set_errno(0);
473
0
        uwidth = malloc_strtoumax(f, (char **)&f, 10);
474
0
        assert(uwidth != UINTMAX_MAX || get_errno() !=
475
0
            ERANGE);
476
0
        width = (int)uwidth;
477
0
        break;
478
200
      } default:
479
200
        break;
480
200
      }
481
      /* Width/precision separator. */
482
200
      if (*f == '.') {
483
0
        f++;
484
200
      } else {
485
200
        goto label_length;
486
200
      }
487
      /* Precision. */
488
0
      switch (*f) {
489
0
      case '*':
490
0
        prec = va_arg(ap, int);
491
0
        f++;
492
0
        break;
493
0
      case '0': case '1': case '2': case '3': case '4':
494
0
      case '5': case '6': case '7': case '8': case '9': {
495
0
        uintmax_t uprec;
496
0
        set_errno(0);
497
0
        uprec = malloc_strtoumax(f, (char **)&f, 10);
498
0
        assert(uprec != UINTMAX_MAX || get_errno() !=
499
0
            ERANGE);
500
0
        prec = (int)uprec;
501
0
        break;
502
0
      }
503
0
      default: break;
504
0
      }
505
      /* Length. */
506
200
      label_length:
507
200
      switch (*f) {
508
0
      case 'l':
509
0
        f++;
510
0
        if (*f == 'l') {
511
0
          len = 'q';
512
0
          f++;
513
0
        } else {
514
0
          len = 'l';
515
0
        }
516
0
        break;
517
0
      case 'q': case 'j': case 't': case 'z':
518
0
        len = *f;
519
0
        f++;
520
0
        break;
521
200
      default: break;
522
200
      }
523
      /* Conversion specifier. */
524
200
      switch (*f) {
525
0
      case '%':
526
        /* %% */
527
0
        APPEND_C(*f);
528
0
        f++;
529
0
        break;
530
0
      case 'd': case 'i': {
531
0
        intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
532
0
        char buf[D2S_BUFSIZE];
533
534
        /*
535
         * Outputting negative, zero-padded numbers
536
         * would require a nontrivial rework of the
537
         * interaction between the width and padding
538
         * (since 0 padding goes between the '-' and the
539
         * number, while ' ' padding goes either before
540
         * the - or after the number.  Since we
541
         * currently don't ever need 0-padded negative
542
         * numbers, just don't bother supporting it.
543
         */
544
0
        assert(!pad_zero);
545
546
0
        GET_ARG_NUMERIC(val, len);
547
0
        s = d2s(val, (plus_plus ? '+' : (plus_space ?
548
0
            ' ' : '-')), buf, &slen);
549
0
        APPEND_PADDED_S(s, slen, width, left_justify);
550
0
        f++;
551
0
        break;
552
0
      } case 'o': {
553
0
        uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
554
0
        char buf[O2S_BUFSIZE];
555
556
0
        GET_ARG_NUMERIC(val, len | 0x80);
557
0
        s = o2s(val, alt_form, buf, &slen);
558
0
        APPEND_PADDED_S(s, slen, width, left_justify);
559
0
        f++;
560
0
        break;
561
100
      } case 'u': {
562
100
        uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
563
100
        char buf[U2S_BUFSIZE];
564
565
100
        GET_ARG_NUMERIC(val, len | 0x80);
566
100
        s = u2s(val, 10, false, buf, &slen);
567
100
        APPEND_PADDED_S(s, slen, width, left_justify);
568
100
        f++;
569
100
        break;
570
100
      } case 'x': case 'X': {
571
0
        uintmax_t val JEMALLOC_CC_SILENCE_INIT(0);
572
0
        char buf[X2S_BUFSIZE];
573
574
0
        GET_ARG_NUMERIC(val, len | 0x80);
575
0
        s = x2s(val, alt_form, *f == 'X', buf, &slen);
576
0
        APPEND_PADDED_S(s, slen, width, left_justify);
577
0
        f++;
578
0
        break;
579
0
      } case 'c': {
580
0
        unsigned char val;
581
0
        char buf[2];
582
583
0
        assert(len == '?' || len == 'l');
584
0
        assert_not_implemented(len != 'l');
585
0
        val = va_arg(ap, int);
586
0
        buf[0] = val;
587
0
        buf[1] = '\0';
588
0
        APPEND_PADDED_S(buf, 1, width, left_justify);
589
0
        f++;
590
0
        break;
591
100
      } case 's':
592
100
        assert(len == '?' || len == 'l');
593
100
        assert_not_implemented(len != 'l');
594
100
        s = va_arg(ap, char *);
595
100
        slen = (prec < 0) ? strlen(s) : (size_t)prec;
596
100
        APPEND_PADDED_S(s, slen, width, left_justify);
597
100
        f++;
598
100
        break;
599
0
      case 'p': {
600
0
        uintmax_t val;
601
0
        char buf[X2S_BUFSIZE];
602
603
0
        GET_ARG_NUMERIC(val, 'p');
604
0
        s = x2s(val, true, false, buf, &slen);
605
0
        APPEND_PADDED_S(s, slen, width, left_justify);
606
0
        f++;
607
0
        break;
608
0
      } default: not_reached();
609
200
      }
610
200
      break;
611
200
    } default: {
612
100
      APPEND_C(*f);
613
100
      f++;
614
100
      break;
615
200
    }}
616
400
  }
617
100
  label_out:
618
100
  if (i < size) {
619
100
    str[i] = '\0';
620
100
  } else {
621
0
    str[size - 1] = '\0';
622
0
  }
623
624
100
#undef APPEND_C
625
100
#undef APPEND_S
626
100
#undef APPEND_PADDED_S
627
100
#undef GET_ARG_NUMERIC
628
100
  return i;
629
100
}
630
631
JEMALLOC_FORMAT_PRINTF(3, 4)
632
size_t
633
100
malloc_snprintf(char *str, size_t size, const char *format, ...) {
634
100
  size_t ret;
635
100
  va_list ap;
636
637
100
  va_start(ap, format);
638
100
  ret = malloc_vsnprintf(str, size, format, ap);
639
100
  va_end(ap);
640
641
100
  return ret;
642
100
}
643
644
void
645
malloc_vcprintf(write_cb_t *write_cb, void *cbopaque, const char *format,
646
0
    va_list ap) {
647
0
  char buf[MALLOC_PRINTF_BUFSIZE];
648
649
0
  if (write_cb == NULL) {
650
    /*
651
     * The caller did not provide an alternate write_cb callback
652
     * function, so use the default one.  malloc_write() is an
653
     * inline function, so use malloc_message() directly here.
654
     */
655
0
    write_cb = (je_malloc_message != NULL) ? je_malloc_message :
656
0
        wrtmessage;
657
0
  }
658
659
0
  malloc_vsnprintf(buf, sizeof(buf), format, ap);
660
0
  write_cb(cbopaque, buf);
661
0
}
662
663
/*
664
 * Print to a callback function in such a way as to (hopefully) avoid memory
665
 * allocation.
666
 */
667
JEMALLOC_FORMAT_PRINTF(3, 4)
668
void
669
0
malloc_cprintf(write_cb_t *write_cb, void *cbopaque, const char *format, ...) {
670
0
  va_list ap;
671
672
0
  va_start(ap, format);
673
0
  malloc_vcprintf(write_cb, cbopaque, format, ap);
674
0
  va_end(ap);
675
0
}
676
677
/* Print to stderr in such a way as to avoid memory allocation. */
678
JEMALLOC_FORMAT_PRINTF(1, 2)
679
void
680
0
malloc_printf(const char *format, ...) {
681
0
  va_list ap;
682
683
0
  va_start(ap, format);
684
0
  malloc_vcprintf(NULL, NULL, format, ap);
685
  va_end(ap);
686
0
}
687
688
/*
689
 * Restore normal assertion macros, in order to make it possible to compile all
690
 * C files as a single concatenation.
691
 */
692
#undef assert
693
#undef not_reached
694
#undef not_implemented
695
#undef assert_not_implemented
696
#include "jemalloc/internal/assert.h"