Take number and string boxes out of the candidate buffers before pooling them (#2091)

This commit is contained in:
Chris Tate
2026-10-24 06:30:38 -05:00
committed by GitHub
2 changed files with 31 additions and 2 deletions
+6 -2
View File
@@ -1286,10 +1286,14 @@ void scr_dyn_release(ScrDyn *d) {
return;
}
#ifndef SCR_RC_AUDIT
/* Number and string boxes own at most one string, are never cycle
* candidates and cannot be weak keys: return them to the free list. */
/* Number and string boxes own at most one string and cannot be weak
* keys: return them to the free list. Their releases never buffer them,
* but a collector pass can (a box that traces its payload reaches them,
* and scr_xg_release buffers what it settles), so a buffered box leaves
* its candidate buffer first. */
if ((d->kind == SCR_DYN_NUM || d->kind == SCR_DYN_STR) && !d->prototype &&
!d->symbol_properties && !d->symbol_keys && scr_dyn_free_count < SCR_DYN_FREE_MAX) {
scr_cyc_dead(d);
if (d->kind == SCR_DYN_STR) scr_str_release(d->v.str);
d->v.str = (ScrStr *)scr_dyn_free_misc;
scr_dyn_free_misc = d;
+25
View File
@@ -391,6 +391,30 @@ static bool buffered_after_read(ScrDyn *d) {
return buffered(d);
}
/* A collector pass can buffer a number or string box that it reached
* through an owner that traces it: scr_xg_release, settling an edge a
* restricted pass skipped, calls scr_cyc_on_release on the target. The
* box's last release must take it out of its candidate buffer before its
* block returns to the free list, which hands it to the next box. */
static void buffered_leaf_release(void) {
for (uint16_t gen = SCR_CYC_NURSERY; gen < SCR_CYC_NGENS; gen++) {
ScrStr *text = scr_str_new("buffered", 8);
ScrDyn *leaves[2] = {scr_dyn_new_str(text), scr_dyn_new_num(0.5)};
scr_str_release(text);
for (int i = 0; i < 2; i++) {
scr_cyc_set_gen(scr_cyc_hdr(leaves[i]), gen);
scr_cyc_on_release(leaves[i]);
scr_dyn_release(leaves[i]);
}
ScrDyn *fresh[2] = {scr_dyn_new_num(1.5), scr_dyn_new_num(2.5)};
assert(!buffered(fresh[0]) && !buffered(fresh[1]));
scr_collect_cycles();
assert(fresh[0]->v.num == 1.5 && fresh[1]->v.num == 2.5);
scr_dyn_release(fresh[0]);
scr_dyn_release(fresh[1]);
}
}
static ScrDyn *parse_text(const char *text) {
ScrStr *input = scr_str_new(text, strlen(text));
ScrDyn *parsed = scr_json_parse(input);
@@ -823,6 +847,7 @@ int main(void) {
shared_property_keys();
checked_leaf_cycles();
checked_number_storage();
buffered_leaf_release();
json_intact_regions();
json_schema_parse();
json_schema_special_names();