@@ -30,16 +30,19 @@ pub fn tco_impl(item: TokenStream) -> TokenStream {
30
30
// Build the function call with all the generics
31
31
let generic_args = build_generic_args ( generics) ;
32
32
let execute_call = if generic_args. is_empty ( ) {
33
- quote ! { #fn_name( pre_compute, exec_state) }
33
+ quote ! { #fn_name( pre_compute, & mut instret , & mut pc , arg , exec_state) }
34
34
} else {
35
- quote ! { #fn_name:: <#( #generic_args) , * >( pre_compute, exec_state) }
35
+ quote ! { #fn_name:: <#( #generic_args) , * >( pre_compute, & mut instret , & mut pc , arg , exec_state) }
36
36
} ;
37
37
38
38
// Generate the TCO handler function
39
39
let handler_fn = quote ! {
40
40
#[ inline( never) ]
41
41
unsafe fn #handler_name #handler_generics (
42
42
interpreter: & :: openvm_circuit:: arch:: interpreter:: InterpretedInstance <#f_type, #ctx_type>,
43
+ mut instret: u64 ,
44
+ mut pc: u32 ,
45
+ arg: u64 ,
43
46
exec_state: & mut :: openvm_circuit:: arch:: VmExecState <
44
47
#f_type,
45
48
:: openvm_circuit:: system:: memory:: online:: GuestMemory ,
@@ -50,28 +53,30 @@ pub fn tco_impl(item: TokenStream) -> TokenStream {
50
53
{
51
54
use :: openvm_circuit:: arch:: ExecutionError ;
52
55
53
- let pre_compute = interpreter. get_pre_compute( exec_state . vm_state . pc) ;
56
+ let pre_compute = interpreter. get_pre_compute( pc) ;
54
57
#execute_call;
55
58
56
- if exec_state. exit_code. is_err( ) {
57
- // stop execution
59
+ if :: core :: intrinsics :: unlikely ( exec_state. exit_code. is_err( ) ) {
60
+ exec_state . set_instret_and_pc ( instret , pc ) ;
58
61
return ;
59
62
}
60
- if #ctx_type:: should_suspend( exec_state) {
63
+ if :: core:: intrinsics:: unlikely( #ctx_type:: should_suspend( instret, pc, arg, exec_state) ) {
64
+ exec_state. set_instret_and_pc( instret, pc) ;
61
65
return ;
62
66
}
63
- // exec_state.pc should have been updated by execute_impl at this point
64
- let next_handler = interpreter. get_handler( exec_state. vm_state. pc) ;
65
- if next_handler. is_none( ) {
66
- exec_state. exit_code = Err ( ExecutionError :: PcOutOfBounds ( exec_state. vm_state. pc) ) ;
67
+
68
+ let next_handler = interpreter. get_handler( pc) ;
69
+ if :: core:: intrinsics:: unlikely( next_handler. is_none( ) ) {
70
+ exec_state. set_instret_and_pc( instret, pc) ;
71
+ exec_state. exit_code = Err ( ExecutionError :: PcOutOfBounds ( pc) ) ;
67
72
return ;
68
73
}
69
74
let next_handler = next_handler. unwrap_unchecked( ) ;
70
75
71
76
// NOTE: `become` is a keyword that requires Rust Nightly.
72
77
// It is part of the explicit tail calls RFC: <https://github.com/rust-lang/rust/issues/112788>
73
78
// which is still incomplete.
74
- become next_handler( interpreter, exec_state)
79
+ become next_handler( interpreter, instret , pc , arg , exec_state)
75
80
}
76
81
} ;
77
82
0 commit comments