Skip to content

Commit e6affb6

Browse files
committed
feat: simplify the handler type without Result
1 parent 5a193a0 commit e6affb6

File tree

15 files changed

+49
-47
lines changed

15 files changed

+49
-47
lines changed

crates/vm/derive/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,13 @@ fn parse_executor_type(
754754
/// ```
755755
///
756756
/// This will generate a TCO handler function with the same generics and where clauses.
757+
///
758+
/// # Safety
759+
///
760+
/// Do not use this macro if your function wants to terminate execution without error with a
761+
/// specific error code. The handler generated by this macro assumes that execution should continue
762+
/// unless the execute_impl returns an error. This is done for performance to skip an exit code
763+
/// check.
757764
#[proc_macro_attribute]
758765
pub fn create_tco_handler(_attr: TokenStream, item: TokenStream) -> TokenStream {
759766
tco::tco_impl(item)

crates/vm/derive/src/tco.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,25 +46,26 @@ pub fn tco_impl(item: TokenStream) -> TokenStream {
4646
::openvm_circuit::system::memory::online::GuestMemory,
4747
#ctx_type,
4848
>,
49-
) -> Result<(), ::openvm_circuit::arch::ExecutionError>
49+
)
5050
#where_clause
5151
{
5252
let pre_compute = interpreter.get_pre_compute(exec_state.vm_state.pc);
5353
#execute_call;
5454

55-
if std::hint::unlikely(exec_state.exit_code.is_err()) {
56-
return Err(::openvm_circuit::arch::ExecutionError::ExecStateError);
57-
}
58-
if std::hint::unlikely(exec_state.exit_code.as_ref().unwrap().is_some()) {
59-
#ctx_type::on_terminate(exec_state);
60-
// terminate
61-
return Ok(());
55+
if exec_state.exit_code.is_err() {
56+
// stop execution
57+
return;
6258
}
6359
if #ctx_type::should_suspend(exec_state) {
64-
return Ok(());
60+
return;
6561
}
6662
// exec_state.pc should have been updated by execute_impl at this point
67-
let next_handler = interpreter.get_handler(exec_state.vm_state.pc)?;
63+
let next_handler = interpreter.get_handler(exec_state.vm_state.pc);
64+
if next_handler.is_none() {
65+
exec_state.exit_code = Err(interpreter.pc_out_of_bounds_err(exec_state.vm_state.pc));
66+
return;
67+
}
68+
let next_handler = next_handler.unwrap_unchecked();
6869

6970
// The `become` keyword has a bug that is not re-passing the `interpreter`, `exec_state` references properly. But llvm seems to almost always guarantee tail call elimination when the function signature is the same as the current function.
7071
next_handler(interpreter, exec_state)

crates/vm/src/arch/execution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub type ExecuteFunc<F, CTX> =
109109
pub type Handler<F, CTX> = unsafe fn(
110110
interpreter: &InterpretedInstance<F, CTX>,
111111
exec_state: &mut VmExecState<F, GuestMemory, CTX>,
112-
) -> Result<(), ExecutionError>;
112+
);
113113

114114
/// Trait for pure execution via a host interpreter. The trait methods provide the methods to
115115
/// pre-process the program code into function pointers which operate on `pre_compute` instruction

crates/vm/src/arch/interpreter.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,19 @@ where
189189
}
190190
}
191191

192+
pub fn pc_out_of_bounds_err(&self, pc: u32) -> ExecutionError {
193+
ExecutionError::PcOutOfBounds {
194+
pc,
195+
pc_base: self.pc_base,
196+
program_len: self.pre_compute_insns.len(),
197+
}
198+
}
199+
192200
#[cfg(feature = "tco")]
193201
#[inline(always)]
194-
pub fn get_handler(&self, pc: u32) -> Result<Handler<F, Ctx>, ExecutionError> {
202+
pub fn get_handler(&self, pc: u32) -> Option<Handler<F, Ctx>> {
195203
let pc_idx = get_pc_index(self.pc_base, pc);
196-
if std::hint::unlikely(pc_idx >= self.handlers.len()) {
197-
return Err(ExecutionError::PcOutOfBounds {
198-
pc,
199-
pc_base: self.pc_base,
200-
program_len: self.handlers.len(),
201-
});
202-
}
203-
// SAFETY:
204-
// - we checked above that pc_idx is within bounds
205-
let handler = unsafe { self.handlers.get_unchecked(pc_idx) };
206-
Ok(*handler)
204+
self.handlers.get(pc_idx).map(|x| *x)
207205
}
208206
}
209207

@@ -302,15 +300,21 @@ where
302300
}
303301
#[cfg(feature = "tco")]
304302
unsafe {
305-
let handler = self.get_handler(exec_state.pc)?;
306-
let res = handler(self, &mut exec_state);
307-
if let Err(err) = res {
308-
match err {
309-
ExecutionError::ExecStateError => {}
310-
_ => {
311-
return Err(err);
312-
}
313-
}
303+
let handler = self
304+
.get_handler(exec_state.pc)
305+
.ok_or(ExecutionError::PcOutOfBounds {
306+
pc: exec_state.pc,
307+
pc_base: self.pc_base,
308+
program_len: self.handlers.len(),
309+
})?;
310+
handler(self, &mut exec_state);
311+
312+
if exec_state
313+
.exit_code
314+
.as_ref()
315+
.is_ok_and(|exit_code| exit_code.is_some())
316+
{
317+
ExecutionCtx::on_terminate(&mut exec_state);
314318
}
315319
}
316320

@@ -540,17 +544,16 @@ unsafe fn terminate_execute_e12_impl<F: PrimeField32, CTX: ExecutionCtxTrait>(
540544
unsafe fn terminate_execute_e12_tco_handler<F: PrimeField32, CTX: ExecutionCtxTrait>(
541545
interpreter: &InterpretedInstance<F, CTX>,
542546
vm_state: &mut VmExecState<F, GuestMemory, CTX>,
543-
) -> Result<(), ExecutionError> {
547+
) {
544548
let pre_compute = interpreter.get_pre_compute(vm_state.pc);
545549
terminate_execute_e12_impl(pre_compute, vm_state);
546-
Ok(())
547550
}
548551
#[cfg(feature = "tco")]
549552
unsafe fn unreachable_tco_handler<F: PrimeField32, CTX>(
550553
_: &InterpretedInstance<F, CTX>,
551554
vm_state: &mut VmExecState<F, GuestMemory, CTX>,
552-
) -> Result<(), ExecutionError> {
553-
Err(ExecutionError::Unreachable(vm_state.pc))
555+
) {
556+
vm_state.exit_code = Err(ExecutionError::Unreachable(vm_state.pc));
554557
}
555558

556559
fn get_pre_compute_max_size<F, E: Executor<F>>(

crates/vm/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg_attr(feature = "tco", allow(incomplete_features))]
2-
#![cfg_attr(feature = "tco", feature(likely_unlikely))]
32
#![cfg_attr(feature = "tco", feature(explicit_tail_calls))]
43
extern crate self as openvm_circuit;
54

crates/vm/src/system/phantom/execution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ unsafe fn execute_e12_impl<F: PrimeField32, CTX: ExecutionCtxTrait>(
101101
vm_state.instret += 1;
102102
}
103103

104-
#[cfg_attr(feature = "tco", create_tco_handler)]
104+
#[create_tco_handler]
105105
#[inline(always)]
106106
unsafe fn execute_e1_impl<F: PrimeField32, CTX: ExecutionCtxTrait>(
107107
pre_compute: &[u8],

crates/vm/src/system/public_values/execution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ unsafe fn execute_e12_impl<F: PrimeField32, CTX, const B_IS_IMM: bool, const C_I
179179
state.instret += 1;
180180
}
181181

182-
#[cfg_attr(feature = "tco", create_tco_handler)]
182+
#[create_tco_handler]
183183
#[inline(always)]
184184
unsafe fn execute_e1_impl<F: PrimeField32, CTX, const B_IS_IMM: bool, const C_IS_IMM: bool>(
185185
pre_compute: &[u8],

extensions/algebra/circuit/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg_attr(feature = "tco", allow(incomplete_features))]
2-
#![cfg_attr(feature = "tco", feature(likely_unlikely))]
32
#![cfg_attr(feature = "tco", feature(explicit_tail_calls))]
43

54
use derive_more::derive::{Deref, DerefMut};

extensions/bigint/circuit/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg_attr(feature = "tco", allow(incomplete_features))]
2-
#![cfg_attr(feature = "tco", feature(likely_unlikely))]
32
#![cfg_attr(feature = "tco", feature(explicit_tail_calls))]
43
use openvm_circuit::{
54
self,

extensions/ecc/circuit/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![cfg_attr(feature = "tco", allow(incomplete_features))]
2-
#![cfg_attr(feature = "tco", feature(likely_unlikely))]
32
#![cfg_attr(feature = "tco", feature(explicit_tail_calls))]
43

54
mod weierstrass_chip;

0 commit comments

Comments
 (0)