Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/eigenscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,22 @@ Value* make_list(int capacity) {
return v;
}

/* Heap-forced list — for VM-internal wrappers that must outlive an arena
* window. An arena list freezes val_decref into a no-op, so any heap items
* it incref'd via list_append are leaked when the arena is reclaimed.
* Used by the builtin-arg packing path: the wrapper holds incref'd args,
* and val_decref(arg) must actually walk and release them on return. */
Value* make_list_heap(int capacity) {
Value *v = xcalloc(1, sizeof(Value));
v->type = VAL_LIST;
v->data.list.capacity = capacity < 8 ? 8 : capacity;
v->data.list.items = xcalloc(v->data.list.capacity, sizeof(Value*));
v->data.list.count = 0;
v->refcount = 1;
v->arena = 0;
return v;
}

Value* make_text_builder(void) {
Value *v = xcalloc(1, sizeof(Value));
v->type = VAL_TEXT_BUILDER;
Expand Down
1 change: 1 addition & 0 deletions src/eigenscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ Value* make_str(const char *s);
Value* make_str_owned(char *s);
Value* make_null(void);
Value* make_list(int capacity);
Value* make_list_heap(int capacity);
Value* make_text_builder(void);
Value* make_fn(const char *name, char **params, int param_count, Env *closure);
Value* make_builtin(BuiltinFn fn);
Expand Down
8 changes: 6 additions & 2 deletions src/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,10 @@ int jit_helper_call(EigsChunk *caller_chunk, int argc, int resume_off) {
arg = STK_AS_VAL(g_vm.sp - 1);
val_incref(arg);
} else {
arg = make_list(argc);
/* Wrapper must be heap: val_decref(arg) below has to actually
* release the list_append increfs on heap items, which an arena
* list silently swallows. */
arg = make_list_heap(argc);
for (int i = 0; i < argc; i++) {
list_append(arg, STK_AS_VAL(g_vm.sp - argc + i));
}
Expand Down Expand Up @@ -2646,7 +2649,8 @@ static Value *vm_run(EigsChunk *chunk, Env *env) {
arg = STK_AS_VAL(g_vm.sp - 1);
val_incref(arg);
} else {
arg = make_list(argc);
/* Heap-forced: see jit_helper_call wrapper rationale. */
arg = make_list_heap(argc);
for (int i = 0; i < argc; i++) {
list_append(arg, STK_AS_VAL(g_vm.sp - argc + i));
}
Expand Down
Loading