@@ -107,6 +107,7 @@ fn performCall(argc: u8) !void {
107107 .closure = null ,
108108 .func_obj = obj ,
109109 .defer_base = vmState ().defer_top ,
110+ .has_typed_returns = f .has_typed_returns ,
110111 };
111112 vmState ().frame_top += 1 ;
112113 vmState ().ip = f .ip ;
@@ -125,6 +126,7 @@ fn performCall(argc: u8) !void {
125126 .closure = obj ,
126127 .func_obj = cl .func ,
127128 .defer_base = vmState ().defer_top ,
129+ .has_typed_returns = f .has_typed_returns ,
128130 };
129131 vmState ().frame_top += 1 ;
130132 vmState ().ip = f .ip ;
@@ -817,7 +819,7 @@ fn runInner() !void {
817819 const proto = f .object .function ;
818820 const ups = heap .bump (* Object , proto .capture_slots .len ) orelse return error .OutOfMemory ;
819821 if (vmState ().frame_top == 0 and proto .capture_slots .len != 0 ) return error .TypeError ;
820- const frame = if (vmState ().frame_top == 0 ) vms.Frame { .ret_ip = 0 , .base = 0 , .closure = null , .func_obj = f .object , .defer_base = 0 } else vmState ().frames [vmState ().frame_top - 1 ];
822+ const frame = if (vmState ().frame_top == 0 ) vms.Frame { .ret_ip = 0 , .base = 0 , .closure = null , .func_obj = f .object , .defer_base = 0 , . has_typed_returns = false } else vmState ().frames [vmState ().frame_top - 1 ];
821823 var i : usize = 0 ;
822824 while (i < proto .capture_slots .len ) : (i += 1 ) {
823825 const enc = proto .capture_slots [i ];
@@ -979,9 +981,24 @@ fn runInner() !void {
979981 .ret = > {
980982 if (vmState ().frame_top == 0 ) return error .ReturnAtTopLevel ;
981983 const retval = try vmPop ();
982- const frame_defer_base = vmState ().frames [vmState ().frame_top - 1 ].defer_base ;
984+ const fi = vmState ().frame_top - 1 ;
985+ const frame = & vmState ().frames [fi ];
986+
987+ // Fast path: no defers pending, no return-type checks (the common case).
988+ if (vmState ().defer_top == frame .defer_base and ! frame .has_typed_returns ) {
989+ vmState ().frame_top = fi ;
990+ vmState ().stack_top = frame .base - 1 ;
991+ vmState ().ip = frame .ret_ip ;
992+ try vmPush (retval );
993+ if (vmState ().call_depth_target ) | d | {
994+ if (vmState ().frame_top == d ) return ;
995+ }
996+ continue ;
997+ }
998+
999+ // Slow path: run defers and/or enforce return types.
9831000 try pushTempRoot (retval );
984- while (vmState ().defer_top > frame_defer_base ) {
1001+ while (vmState ().defer_top > frame . defer_base ) {
9851002 vmState ().defer_top -= 1 ;
9861003 const deferred = vmState ().defer_stack [vmState ().defer_top ];
9871004 try pushTempRoot (deferred );
@@ -1003,10 +1020,11 @@ fn runInner() !void {
10031020 popTempRoot ();
10041021 }
10051022 popTempRoot ();
1006- vmState ().frame_top -= 1 ;
1007- const frame = vmState ().frames [vmState ().frame_top ];
1008- const fsig = try vmtyp .frameFuncSig (frame .func_obj );
1009- try vmtyp .enforceFuncReturnTypes (fsig , retval );
1023+ vmState ().frame_top = fi ;
1024+ if (frame .has_typed_returns ) {
1025+ const fsig = try vmtyp .frameFuncSig (frame .func_obj );
1026+ try vmtyp .enforceFuncReturnTypes (fsig , retval );
1027+ }
10101028 vmState ().stack_top = frame .base - 1 ;
10111029 vmState ().ip = frame .ret_ip ;
10121030 try vmPush (retval );
0 commit comments