shorten frames to closure vars only on gc

This commit is contained in:
2026-02-19 01:55:35 -06:00
parent e7fec94e38
commit bab4d50b2a
3 changed files with 77 additions and 22 deletions

View File

@@ -833,7 +833,7 @@ void __asan_on_error(void) {
fprintf(stderr, " %s (%s:%u)\n",
func_name ? func_name : "<anonymous>",
file ? file : "<unknown>", line);
if (JS_IsNull(frame->caller)) break;
if (!JS_IsPtr(frame->caller)) break;
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
is_first = 0;
}
@@ -913,6 +913,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
env = env_gc.val; /* refresh — GC may have moved env during allocation */
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
frame->function = top_fn;
frame->caller = JS_NewInt32(ctx, 0); /* sentinel: active top-level, not eligible for GC shortening */
frame->slots[0] = this_gc.val; /* slot 0 = this */
/* Copy arguments from GC-safe refs */
@@ -1715,7 +1716,7 @@ vm_dispatch:
VM_CASE(MACH_RETURN):
result = frame->slots[a];
if (JS_IsNull(frame->caller)) goto done;
if (!JS_IsPtr(frame->caller)) goto done;
{
#ifdef VALIDATE_GC
const char *callee_name = "?";
@@ -1759,7 +1760,7 @@ vm_dispatch:
VM_CASE(MACH_RETNIL):
result = JS_NULL;
if (JS_IsNull(frame->caller)) goto done;
if (!JS_IsPtr(frame->caller)) goto done;
{
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
@@ -2317,7 +2318,7 @@ vm_dispatch:
if (JS_IsException(ret)) goto disrupt;
/* Tail-return: act like MACH_RETURN with the result */
result = ret;
if (JS_IsNull(frame->caller)) goto done;
if (!JS_IsPtr(frame->caller)) goto done;
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
frame = caller;
@@ -2387,7 +2388,7 @@ vm_dispatch:
ctx->current_exception = JS_NULL;
break;
}
if (JS_IsNull(frame->caller)) {
if (!JS_IsPtr(frame->caller)) {
/* Stack trace was already included in the JS_RaiseDisrupt log via the callback. */
ctx->disruption_reported = TRUE;
frame_ref.val = JS_MKPTR(frame); /* update root for GC / done */
@@ -2423,6 +2424,10 @@ done:
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
}
if (JS_IsPtr(frame_ref.val)) {
JSFrameRegister *f = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
f->caller = JS_NULL; /* mark as returned so GC can shorten */
}
JS_DeleteGCRef(ctx, &frame_ref);
return result;
}