From 367d8697a41dad1cd3178148d22f5ec7f4329638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Fri, 3 Oct 2025 12:12:07 -0300 Subject: [PATCH 1/2] Add MaybeOwned --- vm/src/utils.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 6824252fe2..5dd0ce894d 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -1,4 +1,4 @@ -use crate::stdlib::prelude::*; +use crate::stdlib::{ops::Deref, prelude::*}; use crate::types::relocatable::Relocatable; use lazy_static::lazy_static; use num_bigint::BigUint; @@ -49,6 +49,32 @@ pub fn from_relocatable_to_indexes(relocatable: Relocatable) -> (usize, usize) { } } +/// Like [Cow], but doesn't require the type to implement [ToOwned]. +/// +/// Useful for storing values that may be either a reference, or an owned value, +/// but are only ever used as a reference. +/// +/// [Cow]: std::borrow::Cow +/// [ToOwned]: std::borrow::ToOwned +pub enum MaybeOwned<'a, T> { + Owned(T), + Borrowed(&'a T), +} + +impl<'a, T> Deref for MaybeOwned<'a, T> +where + T: Deref, +{ + type Target = T::Target; + + fn deref(&self) -> &Self::Target { + match self { + MaybeOwned::Owned(v) => v, + MaybeOwned::Borrowed(v) => v, + } + } +} + #[cfg(test)] #[macro_use] pub mod test_utils { From 637a7679fbc9e3298cf372a9d4ca5134d5d93e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Gonz=C3=A1lez=20Calder=C3=B3n?= Date: Fri, 3 Oct 2025 12:12:17 -0300 Subject: [PATCH 2/2] Add set_hint_data function --- vm/src/vm/runners/cairo_runner.rs | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 2a0ecfe964..73aa505926 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -59,6 +59,9 @@ use super::{ }; use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; +#[cfg(not(feature = "extensive_hints"))] +use crate::{stdlib::sync::Arc, utils::MaybeOwned}; + #[derive(Clone, Debug, Eq, PartialEq)] pub enum CairoArg { Single(MaybeRelocatable), @@ -159,6 +162,8 @@ pub struct CairoRunner { pub relocated_memory: Vec>, pub exec_scopes: ExecutionScopes, pub relocated_trace: Option>, + #[cfg(not(feature = "extensive_hints"))] + compiled_hints: Option>>>, } #[derive(Clone, Debug, PartialEq)] @@ -220,6 +225,8 @@ impl CairoRunner { None }, relocated_trace: None, + #[cfg(not(feature = "extensive_hints"))] + compiled_hints: None, }) } @@ -672,6 +679,28 @@ impl CairoRunner { &self.program.builtins } + /// Sets the compiled hints to be used when executing the program. + /// + /// If this function is not called, all the hints are compiled on the + /// fly when running the program. This implies that the same hints are + /// recomputed even if the same program is called multiple times. With this + /// function we allow the hints to be compiled once, and reused each time + /// the same program is run. + /// + /// Only available without the `extensive_hints` feature as that feature + /// requires to modify the hint data vector, so adding support for a + /// read-only hint cache doesn't make sense. + /// + /// ## Safety + /// + /// The hint processor used when compiling this hints must be the same as + /// the hint processor used when running the program. Othewise, the compiled + /// hints may be invalid. + #[cfg(not(feature = "extensive_hints"))] + pub fn set_hint_data(&mut self, compiled_hints: Arc>>) { + self.compiled_hints = Some(compiled_hints) + } + pub fn run_until_pc( &mut self, address: Relocatable, @@ -679,7 +708,10 @@ impl CairoRunner { ) -> Result<(), VirtualMachineError> { let references = &self.program.shared_program_data.reference_manager; #[cfg(not(feature = "extensive_hints"))] - let hint_data = self.get_hint_data(references, hint_processor)?; + let hint_data = match self.compiled_hints.as_ref() { + Some(hint_data) => MaybeOwned::Borrowed(hint_data.as_ref()), + None => MaybeOwned::Owned(self.get_hint_data(references, hint_processor)?), + }; #[cfg(feature = "extensive_hints")] let mut hint_data = self.get_hint_data(references, hint_processor)?; #[cfg(feature = "extensive_hints")]