Ruby 4.1.0dev (2026-03-20 revision eb04ab9117336f2b3613244cfe8a528c52faf6d6)
pm_arena.c
2
3#include <assert.h>
4
9#define PM_ARENA_BLOCK_SIZE(data_size) (offsetof(pm_arena_block_t, data) + (data_size))
10
12#define PM_ARENA_INITIAL_SIZE 8192
13
15#define PM_ARENA_GROWTH_INTERVAL 8
16
18#define PM_ARENA_MAX_SIZE (1024 * 1024)
19
23static size_t
24pm_arena_next_block_size(const pm_arena_t *arena, size_t min_size) {
25 size_t size = PM_ARENA_INITIAL_SIZE;
26
27 for (size_t exp = PM_ARENA_GROWTH_INTERVAL; exp <= arena->block_count; exp += PM_ARENA_GROWTH_INTERVAL) {
28 if (size < PM_ARENA_MAX_SIZE) size *= 2;
29 }
30
31 return size > min_size ? size : min_size;
32}
33
38static pm_arena_block_t *
39pm_arena_block_new(pm_arena_t *arena, size_t data_size, size_t initial_used) {
40 assert(initial_used <= data_size);
41 pm_arena_block_t *block = (pm_arena_block_t *) xmalloc(PM_ARENA_BLOCK_SIZE(data_size));
42
43 if (block == NULL) {
44 fprintf(stderr, "prism: out of memory; aborting\n");
45 abort();
46 }
47
48 block->capacity = data_size;
49 block->used = initial_used;
50 block->prev = arena->current;
51 arena->current = block;
52 arena->block_count++;
53
54 return block;
55}
56
62void
63pm_arena_reserve(pm_arena_t *arena, size_t capacity) {
64 if (capacity <= PM_ARENA_INITIAL_SIZE) return;
65 if (arena->current != NULL && (arena->current->capacity - arena->current->used) >= capacity) return;
66 pm_arena_block_new(arena, capacity, 0);
67}
68
73void *
74pm_arena_alloc_slow(pm_arena_t *arena, size_t size) {
75 size_t block_data_size = pm_arena_next_block_size(arena, size);
76 pm_arena_block_t *block = pm_arena_block_new(arena, block_data_size, size);
77 return block->data;
78}
79
83void
84pm_arena_free(pm_arena_t *arena) {
85 pm_arena_block_t *block = arena->current;
86
87 while (block != NULL) {
88 pm_arena_block_t *prev = block->prev;
89 xfree_sized(block, PM_ARENA_BLOCK_SIZE(block->capacity));
90 block = prev;
91 }
92
93 *arena = (pm_arena_t) { 0 };
94}
#define xmalloc
Old name of ruby_xmalloc.
Definition xmalloc.h:53
A bump allocator for the prism parser.
A single block of memory in the arena.
Definition pm_arena.h:20
struct pm_arena_block * prev
The previous block in the chain (for freeing).
Definition pm_arena.h:22
char data[PM_FLEX_ARY_LEN]
The block's data.
Definition pm_arena.h:31
size_t used
The number of bytes consumed so far.
Definition pm_arena.h:28
size_t capacity
The total usable bytes in data[].
Definition pm_arena.h:25
A bump allocator.
Definition pm_arena.h:39
size_t block_count
The number of blocks allocated.
Definition pm_arena.h:44
pm_arena_block_t * current
The active block (allocate from here).
Definition pm_arena.h:41