native function type

This commit is contained in:
2026-02-17 17:40:44 -06:00
parent b25285f2e1
commit ad419797b4
8 changed files with 603 additions and 265 deletions

View File

@@ -490,6 +490,32 @@ JSValue js_new_register_function(JSContext *ctx, JSCodeRegister *code, JSValue e
return JS_MKPTR(fn);
}
/* Create a native (QBE-compiled) function */
JSValue js_new_native_function(JSContext *ctx, void *fn_ptr, void *dl_handle,
uint16_t nr_slots, int arity, JSValue outer_frame) {
JSGCRef frame_ref;
JS_PushGCRef(ctx, &frame_ref);
frame_ref.val = outer_frame;
JSFunction *fn = js_mallocz(ctx, sizeof(JSFunction));
if (!fn) {
JS_PopGCRef(ctx, &frame_ref);
return JS_EXCEPTION;
}
fn->header = objhdr_make(0, OBJ_FUNCTION, 0, 0, 0, 0);
fn->kind = JS_FUNC_KIND_NATIVE;
fn->length = arity;
fn->name = JS_NULL;
fn->u.native.fn_ptr = fn_ptr;
fn->u.native.dl_handle = dl_handle;
fn->u.native.nr_slots = nr_slots;
fn->u.native.outer_frame = frame_ref.val;
JS_PopGCRef(ctx, &frame_ref);
return JS_MKPTR(fn);
}
/* Binary operations helper */
static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
/* Fast path for integers */
@@ -1924,12 +1950,14 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
env = fn->u.reg.env_record;
pc = code->entry_point;
} else {
/* C or bytecode function: args already in fr->slots (GC-protected via frame chain) */
/* C, native, or bytecode function */
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret;
if (fn->kind == JS_FUNC_KIND_C)
ret = js_call_c_function(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
else if (fn->kind == JS_FUNC_KIND_NATIVE)
ret = cell_native_dispatch(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
else
ret = JS_CallInternal(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1], 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
@@ -2007,12 +2035,14 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
pc = code->entry_point;
}
} else {
/* C/bytecode function: call it, then return result to our caller */
/* C, native, or bytecode function: call it, then return result to our caller */
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret;
if (fn->kind == JS_FUNC_KIND_C)
ret = js_call_c_function(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
else if (fn->kind == JS_FUNC_KIND_NATIVE)
ret = cell_native_dispatch(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
else
ret = JS_CallInternal(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1], 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);