This commit is contained in:
2026-02-19 01:23:41 -06:00
parent 3f206d80dd
commit 85ef711229
12 changed files with 63609 additions and 58305 deletions

View File

@@ -768,6 +768,20 @@ void cell_rt_signal_tail_call(JSContext *ctx, void *fp, int64_t frame_slot) {
st->pending_is_tail = 1;
}
static int cell_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
if (unlikely(fn->length >= 0 && argc > fn->length)) {
char buf[KEY_GET_STR_BUF_SIZE];
fprintf(stderr, "[arity-qbe] callee=%s expected=%d got=%d\n",
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name),
fn->length, argc);
JS_RaiseDisrupt(ctx, "too many arguments for %s: expected %d, got %d",
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name),
fn->length, argc);
return 0;
}
return 1;
}
/* Entry point called from JS_CallInternal / JS_Call / MACH_INVOKE
for JS_FUNC_KIND_NATIVE functions. */
JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
@@ -788,6 +802,9 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
return (v); \
} while (0)
if (!cell_check_call_arity(ctx, f, argc))
RETURN_DISPATCH(JS_EXCEPTION);
/* Root func_obj across allocation — GC can move it */
JSGCRef func_ref;
JS_PushGCRef(ctx, &func_ref);
@@ -865,10 +882,13 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
continue;
}
JSGCRef callee_fn_ref;
JS_PushGCRef(ctx, &callee_fn_ref);
callee_fn_ref.val = callee_fn_val;
JSFunction *callee_fn = JS_VALUE_GET_FUNCTION(callee_fn_ref.val);
JSFunction *callee_fn = JS_VALUE_GET_FUNCTION(callee_fn_val);
if (!cell_check_call_arity(ctx, callee_fn, callee_argc)) {
JSFunction *exc_fn = JS_VALUE_GET_FUNCTION(frame->function);
fn = (cell_compiled_fn)JS_VALUE_GET_CODE(exc_fn->u.cell.code)->u.native.fn_ptr;
JS_PopGCRef(ctx, &callee_ref);
continue;
}
if (callee_fn->kind == JS_FUNC_KIND_NATIVE) {
/* Native-to-native call — no C stack growth */
@@ -882,13 +902,11 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
cell_rt_leave_frame(ctx);
callee_fr = (JSFrameRegister *)JS_VALUE_GET_PTR(callee_ref.val);
callee_fn_val = callee_fn_ref.val;
callee_fr->function = callee_fn_val;
callee_fr->caller = saved_caller;
callee_fr->address = JS_NewInt32(ctx, 0);
if (!cell_rt_push_existing_frame(ctx, callee_ref.val)) {
JS_PopGCRef(ctx, &callee_fn_ref);
JS_PopGCRef(ctx, &callee_ref);
RETURN_DISPATCH(JS_EXCEPTION);
}
@@ -905,7 +923,6 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
frame->address = JS_NewInt32(ctx, (resume_seg << 16) | ret_slot);
callee_fr = (JSFrameRegister *)JS_VALUE_GET_PTR(callee_ref.val);
callee_fn_val = callee_fn_ref.val;
callee_fr->function = callee_fn_val;
callee_fr->caller = JS_MKPTR(frame);
callee_fr->address = JS_NewInt32(ctx, 0);
@@ -917,7 +934,6 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
fp = (JSValue *)frame->slots;
JSFunction *exc_fn = JS_VALUE_GET_FUNCTION(frame->function);
fn = (cell_compiled_fn)JS_VALUE_GET_CODE(exc_fn->u.cell.code)->u.native.fn_ptr;
JS_PopGCRef(ctx, &callee_fn_ref);
JS_PopGCRef(ctx, &callee_ref);
continue;
}
@@ -997,7 +1013,6 @@ JSValue cell_native_dispatch(JSContext *ctx, JSValue func_obj,
fn = (cell_compiled_fn)JS_VALUE_GET_CODE(cur_fn->u.cell.code)->u.native.fn_ptr;
}
}
JS_PopGCRef(ctx, &callee_fn_ref);
JS_PopGCRef(ctx, &callee_ref);
continue;
}
@@ -1167,6 +1182,8 @@ JSValue cell_rt_invoke(JSContext *ctx, JSValue frame_val) {
JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val);
JSValue result;
if (!cell_check_call_arity(ctx, fn, c_argc))
return JS_EXCEPTION;
if (fn->kind == JS_FUNC_KIND_C) {
result = js_call_c_function(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);