Skip to content

Commit c6e7077

Browse files
Add support for caching instructions, and improve documentation
1 parent 9728017 commit c6e7077

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

vm/src/vm/runners/cairo_runner.rs

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ use crate::{
1010
prelude::*,
1111
rc::Rc,
1212
},
13-
types::{builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName},
13+
types::{
14+
builtin_name::BuiltinName, instruction::Instruction, layout::CairoLayoutParams,
15+
layout_name::LayoutName,
16+
},
1417
vm::{
1518
runners::builtin_runner::SegmentArenaBuiltinRunner,
1619
trace::trace_entry::{relocate_trace_register, RelocatedTraceEntry, TraceEntry},
20+
vm_core::VirtualMachineBuilder,
1721
vm_memory::memory_segments::MemorySegmentManager,
1822
},
1923
Felt252,
@@ -162,8 +166,8 @@ pub struct CairoRunnerBuilder {
162166
loaded_program: bool,
163167
// Set after compiling hints.
164168
hints: Option<Vec<Rc<Box<dyn Any>>>>,
165-
// TODO: Set after loading instruction cache.
166-
// instructions: Vec<Option<Instruction>>,
169+
// Set after loading instruction cache.
170+
instructions: Vec<Option<Instruction>>,
167171
}
168172

169173
impl CairoRunnerBuilder {
@@ -207,6 +211,7 @@ impl CairoRunnerBuilder {
207211
memory: MemorySegmentManager::new(),
208212
loaded_program: false,
209213
hints: None,
214+
instructions: Vec::new(),
210215
})
211216
}
212217

@@ -229,8 +234,15 @@ impl CairoRunnerBuilder {
229234
self.memory.add()
230235
}
231236

232-
// TODO: Cloning the builder after calling this function leads to bad
233-
// behaviour (transactions revert). Why?
237+
/// *Initializes* all the builtin supported by the current layout, but only
238+
/// *includes* the builtins required by the program.
239+
///
240+
/// Note that *initializing* a builtin implies creating a runner for it,
241+
/// and *including* a builtin refers to enabling the builtin runner flag:
242+
/// `included`.
243+
///
244+
/// TODO: Cloning the builder after calling this function leads to bad
245+
/// behaviour (transactions revert). Why?
234246
pub fn initialize_builtin_runners_for_layout(&mut self) -> Result<(), RunnerError> {
235247
let builtin_ordered_list = vec![
236248
BuiltinName::output,
@@ -363,21 +375,49 @@ impl CairoRunnerBuilder {
363375
self.execution_base = Some(self.add_memory_segment());
364376
}
365377

378+
/// Initializing the builtin segments.
379+
///
380+
/// Depends on:
381+
/// - [initialize_base_segments](Self::initialize_base_segments)
382+
/// - [initialize_builtin_runners_for_layout](Self::initialize_builtin_runners_for_layout)
366383
pub fn initialize_builtin_segments(&mut self) {
367384
for builtin_runner in self.builtin_runners.iter_mut() {
368385
builtin_runner.initialize_segments(&mut self.memory);
369386
}
370387
}
371388

389+
/// Loads the program into the program segment.
390+
///
391+
/// If this function is not called, the program will be loaded
392+
/// automataically when initializing the entrypoint.
372393
pub fn load_program(&mut self) -> Result<(), RunnerError> {
373394
let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?;
395+
let program_data = &self.program.shared_program_data.data;
374396
self.memory
375-
.load_data(program_base, &self.program.shared_program_data.data)
397+
.load_data(program_base, program_data)
376398
.map_err(RunnerError::MemoryInitializationError)?;
377399
for i in 0..self.program.shared_program_data.data.len() {
378400
self.memory.memory.mark_as_accessed((program_base + i)?);
379401
}
380402
self.loaded_program = true;
403+
self.instructions.resize(program_data.len(), None);
404+
Ok(())
405+
}
406+
407+
/// Predecodes the program's instructions.
408+
///
409+
/// # Safety
410+
///
411+
/// The decoded instructions must belong the the associated program. To
412+
/// obtain them, call [VirtualMachine::take_instruction_cache] at the end of
413+
/// the execution.
414+
///
415+
/// [VirtualMachine::take_instruction_cache]: crate::vm::vm_core::VirtualMachine::take_instruction_cache
416+
pub fn load_cached_instructions(
417+
&mut self,
418+
instructions: Vec<Option<Instruction>>,
419+
) -> Result<(), RunnerError> {
420+
self.instructions = instructions;
381421
Ok(())
382422
}
383423

@@ -423,10 +463,11 @@ impl CairoRunnerBuilder {
423463
}
424464

425465
pub fn build(self) -> Result<CairoRunner, RunnerError> {
426-
let mut vm = VirtualMachine::new(self.enable_trace, self.disable_trace_padding);
427-
428-
vm.builtin_runners = self.builtin_runners;
429-
vm.segments = self.memory;
466+
let vm = VirtualMachineBuilder::default()
467+
.builtin_runners(self.builtin_runners)
468+
.segments(self.memory)
469+
.instruction_cache(self.instructions)
470+
.build();
430471

431472
Ok(CairoRunner {
432473
vm,

vm/src/vm/vm_core.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::math_utils::signed_felt;
2-
use crate::stdlib::{any::Any, borrow::Cow, collections::HashMap, prelude::*, rc::Rc};
2+
use crate::stdlib::{any::Any, borrow::Cow, collections::HashMap, mem, prelude::*, rc::Rc};
33
use crate::types::builtin_name::BuiltinName;
44
#[cfg(feature = "extensive_hints")]
55
use crate::types::program::HintRange;
@@ -1326,6 +1326,10 @@ impl VirtualMachine {
13261326
.finalize(Some(info.size), info.index as usize, None)
13271327
}
13281328
}
1329+
1330+
pub fn take_instruction_cache(&mut self) -> Vec<Option<Instruction>> {
1331+
mem::take(&mut self.instruction_cache)
1332+
}
13291333
}
13301334

13311335
pub struct VirtualMachineBuilder {
@@ -1334,6 +1338,7 @@ pub struct VirtualMachineBuilder {
13341338
pub(crate) segments: MemorySegmentManager,
13351339
pub(crate) trace: Option<Vec<TraceEntry>>,
13361340
pub(crate) current_step: usize,
1341+
instruction_cache: Vec<Option<Instruction>>,
13371342
skip_instruction_execution: bool,
13381343
run_finished: bool,
13391344
#[cfg(feature = "test_utils")]
@@ -1358,6 +1363,7 @@ impl Default for VirtualMachineBuilder {
13581363
run_finished: false,
13591364
#[cfg(feature = "test_utils")]
13601365
hooks: Default::default(),
1366+
instruction_cache: Vec::new(),
13611367
}
13621368
}
13631369
}
@@ -1407,6 +1413,14 @@ impl VirtualMachineBuilder {
14071413
self
14081414
}
14091415

1416+
pub fn instruction_cache(
1417+
mut self,
1418+
instruction_cache: Vec<Option<Instruction>>,
1419+
) -> VirtualMachineBuilder {
1420+
self.instruction_cache = instruction_cache;
1421+
self
1422+
}
1423+
14101424
pub fn build(self) -> VirtualMachine {
14111425
VirtualMachine {
14121426
run_context: self.run_context,
@@ -1418,7 +1432,7 @@ impl VirtualMachineBuilder {
14181432
segments: self.segments,
14191433
rc_limits: None,
14201434
run_finished: self.run_finished,
1421-
instruction_cache: Vec::new(),
1435+
instruction_cache: self.instruction_cache,
14221436
#[cfg(feature = "test_utils")]
14231437
hooks: self.hooks,
14241438
relocation_table: None,

0 commit comments

Comments
 (0)