Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion vm/src/utils.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
34 changes: 33 additions & 1 deletion vm/src/vm/runners/cairo_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -159,6 +162,8 @@ pub struct CairoRunner {
pub relocated_memory: Vec<Option<Felt252>>,
pub exec_scopes: ExecutionScopes,
pub relocated_trace: Option<Vec<RelocatedTraceEntry>>,
#[cfg(not(feature = "extensive_hints"))]
compiled_hints: Option<Arc<Vec<Box<dyn Any>>>>,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -220,6 +225,8 @@ impl CairoRunner {
None
},
relocated_trace: None,
#[cfg(not(feature = "extensive_hints"))]
compiled_hints: None,
})
}

Expand Down Expand Up @@ -672,14 +679,39 @@ 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<Vec<Box<dyn Any>>>) {
self.compiled_hints = Some(compiled_hints)
}

pub fn run_until_pc(
&mut self,
address: Relocatable,
hint_processor: &mut dyn HintProcessor,
) -> 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")]
Expand Down
Loading