diff --git a/mcode.cm b/mcode.cm index 8e914d14..163c1073 100644 --- a/mcode.cm +++ b/mcode.cm @@ -706,9 +706,6 @@ var mcode = function(ast) { var argc = length(args) var frame_slot = alloc_slot() emit_3("frame", frame_slot, func_slot, argc) - var null_slot = alloc_slot() - emit_1("null", null_slot) - emit_3("setarg", frame_slot, 0, null_slot) var arg_idx = 1 var _i = 0 while (_i < argc) { diff --git a/source/mach.c b/source/mach.c index 5d921d8e..6d42aa6f 100644 --- a/source/mach.c +++ b/source/mach.c @@ -2567,7 +2567,15 @@ vm_dispatch: frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); goto disrupt; } - int nr = c + 2; /* argc + this + func overhead */ + JSFunction *fn = JS_VALUE_GET_FUNCTION(func_val); + int nr; + if (fn->kind == JS_FUNC_KIND_REGISTER) { + JSCodeRegister *fn_code = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code; + nr = fn_code->nr_slots; + if (nr < c + 2) nr = c + 2; /* safety: never smaller than argc+2 */ + } else { + nr = c + 2; + } JSFrameRegister *call_frame = alloc_frame_register(ctx, nr); if (!call_frame) { frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); @@ -2576,6 +2584,7 @@ vm_dispatch: frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); func_val = frame->slots[b]; /* re-read after GC */ call_frame->function = func_val; + call_frame->address = JS_NewInt32(ctx, c); /* store actual argc */ frame->slots[a] = JS_MKPTR(call_frame); VM_BREAK(); } @@ -2588,36 +2597,19 @@ vm_dispatch: VM_CASE(MACH_INVOKE): { /* A=frame_slot, B=result_slot */ JSFrameRegister *fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->slots[a]); - int nr = (int)objhdr_cap56(fr->header); - int c_argc = (nr >= 2) ? nr - 2 : 0; + int c_argc = JS_VALUE_GET_INT(fr->address); /* actual argc stored by FRAME */ JSValue fn_val = fr->function; JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val); if (!mach_check_call_arity(ctx, fn, c_argc)) goto disrupt; if (fn->kind == JS_FUNC_KIND_REGISTER) { - /* Register function: switch frames inline (fast path) */ + /* Register function: FRAME already allocated nr_slots — just switch */ JSCodeRegister *fn_code = JS_VALUE_GET_CODE(fn->u.cell.code)->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 = JS_VALUE_GET_CODE(fn->u.cell.code)->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]; /* Save return info */ frame->address = JS_NewInt32(ctx, (pc << 16) | b); - new_frame->caller = JS_MKPTR(frame); - frame = new_frame; + fr->caller = JS_MKPTR(frame); + frame = fr; frame_ref.val = JS_MKPTR(frame); code = fn_code; env = fn->u.cell.env_record; @@ -2661,8 +2653,7 @@ vm_dispatch: VM_CASE(MACH_GOINVOKE): { /* Tail call: replace current frame with callee */ JSFrameRegister *fr = (JSFrameRegister *)JS_VALUE_GET_PTR(frame->slots[a]); - int nr = (int)objhdr_cap56(fr->header); - int c_argc = (nr >= 2) ? nr - 2 : 0; + int c_argc = JS_VALUE_GET_INT(fr->address); /* actual argc stored by FRAME */ JSValue fn_val = fr->function; JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val); if (!mach_check_call_arity(ctx, fn, c_argc)) @@ -2687,25 +2678,10 @@ vm_dispatch: env = fn->u.cell.env_record; pc = code->entry_point; } else { - /* SLOW PATH: callee needs more slots, must allocate */ - 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 = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code; - new_frame->function = fn_val; - 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]; - new_frame->caller = frame->caller; + /* SLOW PATH: GOFRAME already allocated nr_slots — use fr directly */ + fr->caller = frame->caller; frame->caller = JS_NULL; - frame = new_frame; + frame = fr; frame_ref.val = JS_MKPTR(frame); code = fn_code; env = fn->u.cell.env_record;