GitHub

@@ -86,6 +86,35 @@ sym_validate_len(mrb_state *mrb, size_t len)

8686

}

8787

}

888889+

/* Chunk-based string pool for heap-allocated symbol names */

90+

#define MRB_SYM_POOL_CHUNK_SIZE 4096

91+92+

struct sym_pool_chunk {

93+

struct sym_pool_chunk *next;

94+

size_t used;

95+

char buf[]; /* flexible array */

96+

};

97+98+

static char*

99+

sym_pool_alloc(mrb_state *mrb, size_t size)

100+

{

101+

/* round up to even size to keep pointers even-aligned (LSB tagging) */

102+

size_t asize = (size + 1) & ~(size_t)1;

103+

struct sym_pool_chunk *chunk = (struct sym_pool_chunk*)mrb->sym_pool;

104+

if (chunk && chunk->used + asize <= MRB_SYM_POOL_CHUNK_SIZE) {

105+

char *p = chunk->buf + chunk->used;

106+

chunk->used += asize;

107+

return p;

108+

}

109+

size_t csize = asize > MRB_SYM_POOL_CHUNK_SIZE ? asize : MRB_SYM_POOL_CHUNK_SIZE;

110+

chunk = (struct sym_pool_chunk*)mrb_malloc(mrb,

111+

offsetof(struct sym_pool_chunk, buf) + csize);

112+

chunk->next = (struct sym_pool_chunk*)mrb->sym_pool;

113+

chunk->used = asize;

114+

mrb->sym_pool = (void*)chunk;

115+

return chunk->buf;

116+

}

117+89118

/* Hash table for symbols (allocated on demand when symbols exceed threshold) */

90119

struct mrb_sym_hash_table {

91120

uint8_t *symlink; /* collision resolution chains */

@@ -316,7 +345,7 @@ sym_intern_common(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)

316345

/* Always heap-allocate when not explicitly literal */

317346

uint32_t ulen = (uint32_t)len;

318347

size_t ilen = mrb_packed_int_len(ulen);

319-

char *p = (char*)mrb_malloc(mrb, len+ilen+1);

348+

char *p = sym_pool_alloc(mrb, len+ilen+1);

320349

mrb_packed_int_encode(ulen, (uint8_t*)p);

321350

memcpy(p+ilen, name, len);

322351

p[ilen+len] = 0;

@@ -604,16 +633,15 @@ mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)

604633

void

605634

mrb_free_symtbl(mrb_state *mrb)

606635

{

607-

mrb_sym i, lim;

608-609-

for (i=1,lim=mrb->symidx+1; i<lim; i++) {

610-

const char *tagged_ptr = mrb->symtbl[i];

611-

if (!symtbl_is_literal(tagged_ptr)) {

612-

/* CRITICAL: Untag before mrb_free */

613-

const char *clean_ptr = symtbl_get_ptr(tagged_ptr);

614-

mrb_free(mrb, (char*)clean_ptr);

615-

}

636+

/* Free symbol string pool chunks */

637+

struct sym_pool_chunk *chunk = (struct sym_pool_chunk*)mrb->sym_pool;

638+

while (chunk) {

639+

struct sym_pool_chunk *next = chunk->next;

640+

mrb_free(mrb, chunk);

641+

chunk = next;

616642

}

643+

mrb->sym_pool = NULL;

644+617645

mrb_free(mrb, (void*)mrb->symtbl);

618646619647

/* Free hash table if allocated */

@@ -629,6 +657,7 @@ mrb_init_symtbl(mrb_state *mrb)

629657

{

630658

/* Initialize in linear mode - hash table allocated on demand */

631659

mrb->symhash = NULL;

660+

mrb->sym_pool = NULL;

632661

}

633662634663

/**********************************************************************

Read the original on github.com ↗