This commit is contained in:
2026-02-13 03:57:18 -06:00
parent 1df6553577
commit 4f18a0b524
7 changed files with 14637 additions and 14046 deletions

View File

@@ -1702,17 +1702,68 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
break;
}
case MACH_GOINVOKE: {
/* Async invoke: call and discard result */
/* Tail call: replace current frame with callee */
JSFrameRegister *fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->slots[a]);
int nr = (int)objhdr_cap56(fr->hdr);
int c_argc = (nr >= 2) ? nr - 2 : 0;
ctx->reg_current_frame = frame_ref.val;
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
JSValue ret = JS_Call(ctx, fr->function, fr->slots[0],
c_argc, &fr->slots[1]);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) goto disrupt;
JSValue fn_val = fr->function;
JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val);
if (fn->kind == JS_FUNC_KIND_REGISTER) {
/* Register function: tail call by replacing current frame */
JSCodeRegister *fn_code = fn->u.reg.code;
JSFrameRegister *new_frame = alloc_frame_register(ctx, fn_code->nr_slots);
if (!new_frame) {
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
goto disrupt;
}
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->slots[a]);
fn_val = fr->function;
fn = JS_VALUE_GET_FUNCTION(fn_val);
fn_code = fn->u.reg.code;
new_frame->function = fn_val;
/* Copy this + args from call frame to new frame */
int copy_count = (c_argc < fn_code->arity) ? c_argc : fn_code->arity;
new_frame->slots[0] = fr->slots[0]; /* this */
for (int i = 0; i < copy_count; i++)
new_frame->slots[1 + i] = fr->slots[1 + i];
/* Tail call: callee returns to OUR caller, not to us */
new_frame->caller = frame->caller;
frame->caller = JS_NULL; /* detach current frame */
/* Switch to callee */
frame = new_frame;
frame_ref.val = JS_MKPTR(frame);
code = fn_code;
env = fn->u.reg.env_record;
pc = code->entry_point;
} else {
/* C/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
ret = JS_CallInternal(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1], 0);
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
ctx->reg_current_frame = JS_NULL;
if (JS_IsException(ret)) goto disrupt;
/* Tail-return: act like MACH_RETURN with the result */
result = ret;
if (JS_IsNull(frame->caller)) goto done;
JSFrameRegister *caller = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->caller);
frame->caller = JS_NULL;
frame = caller;
frame_ref.val = JS_MKPTR(frame);
int ret_info = JS_VALUE_GET_INT(frame->address);
JSFunction *ret_fn = JS_VALUE_GET_FUNCTION(frame->function);
code = ret_fn->u.reg.code;
env = ret_fn->u.reg.env_record;
pc = ret_info >> 16;
int ret_slot = ret_info & 0xFFFF;
if (ret_slot != 0xFFFF) frame->slots[ret_slot] = ret;
}
break;
}

View File

@@ -351,8 +351,8 @@ JSValue cell_rt_goframe(JSContext *ctx, JSValue fn, int64_t nargs) {
return cell_rt_frame(ctx, fn, nargs);
}
void cell_rt_goinvoke(JSContext *ctx, JSValue frame_val) {
cell_rt_invoke(ctx, frame_val);
JSValue cell_rt_goinvoke(JSContext *ctx, JSValue frame_val) {
return cell_rt_invoke(ctx, frame_val);
}
/* --- Array push/pop --- */