@@ -27,7 +27,7 @@ use crate::{
2727
2828#[ allow( dead_code) ]
2929pub struct CairoRunner2 {
30- virtual_machine : VirtualMachine ,
30+ vm : VirtualMachine ,
3131 program_base : Relocatable ,
3232 execution_base : Relocatable ,
3333 final_pc : Relocatable ,
@@ -56,66 +56,37 @@ impl CairoRunner2 {
5656 identifiers : HashMap < String , Identifier > ,
5757 reference_manager : Vec < HintReference > ,
5858 ) -> Result < Self , RunnerError > {
59- let entrypoint = executable
60- . entrypoints
61- . iter ( )
62- . find ( |entrypoint| {
63- // TODO: Use `Eq` once implemented on `EntryPointKind`.
64- std:: mem:: discriminant ( & entrypoint. kind ) == std:: mem:: discriminant ( & entrypoint_kind)
65- } )
66- . expect ( "executable had no entrypoint of required kind" ) ;
59+ let entrypoint = find_entrypoint_of_kind ( & executable. entrypoints , entrypoint_kind. clone ( ) ) ;
6760
6861 let builtins = get_entrypoint_builtins ( entrypoint) ;
6962
7063 check_builtin_order ( & builtins) ?;
64+ let mut builtin_runners = initialize_builtin_runners ( & layout, & builtins, true , true ) ?;
7165
72- let builtins_set: HashSet < BuiltinName > = builtins. clone ( ) . into_iter ( ) . collect ( ) ;
73- let mut builtin_runners = initialize_builtin_runners ( & layout, builtins_set, true , true ) ?;
74-
75- let mut memory_segment_manager = MemorySegmentManager :: new ( ) ;
76- let program_base = memory_segment_manager. add ( ) ;
77- let execution_base = memory_segment_manager. add ( ) ;
66+ let mut segments = MemorySegmentManager :: new ( ) ;
67+ let program_base = segments. add ( ) ;
68+ let execution_base = segments. add ( ) ;
7869
79- for builtin_runner in & mut builtin_runners {
80- builtin_runner. initialize_segments ( & mut memory_segment_manager) ;
81- }
70+ initialize_builtin_runner_segments ( & mut builtin_runners, & mut segments) ;
8271
83- for builtin_runner in & mut builtin_runners {
84- if let BuiltinRunner :: Mod ( runner) = builtin_runner {
85- runner. initialize_zero_segment ( & mut memory_segment_manager) ;
86- }
87- }
88-
89- let mut virtual_machine = VirtualMachineBuilder :: default ( )
72+ let mut vm = VirtualMachineBuilder :: default ( )
9073 . builtin_runners ( builtin_runners)
91- . segments ( memory_segment_manager )
74+ . segments ( segments )
9275 . build ( ) ;
9376
94- let builtin_runner_map: HashMap < BuiltinName , & BuiltinRunner > = virtual_machine
95- . builtin_runners
96- . iter ( )
97- . map ( |builtin_runner| ( builtin_runner. name ( ) , builtin_runner) )
98- . collect ( ) ;
9977 let mut stack = Vec :: new ( ) ;
100- for builtin in builtins {
101- if let Some ( builtin_runner) = builtin_runner_map. get ( & builtin) {
102- stack. append ( & mut builtin_runner. initial_stack ( ) ) ;
103- } else {
104- stack. push ( Felt252 :: ZERO . into ( ) )
105- }
106- }
78+ extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
10779
108- let return_fp = virtual_machine . add_memory_segment ( ) ;
109- let return_pc = virtual_machine . add_memory_segment ( ) ;
80+ let return_fp = vm . add_memory_segment ( ) ;
81+ let return_pc = vm . add_memory_segment ( ) ;
11082 stack. push ( MaybeRelocatable :: RelocatableValue ( return_fp) ) ;
11183 stack. push ( MaybeRelocatable :: RelocatableValue ( return_pc) ) ;
11284
11385 let initial_pc = ( program_base + entrypoint. offset ) ?;
11486 let initial_fp = ( execution_base + stack. len ( ) ) ?;
11587 let initial_ap = initial_fp;
116-
11788 let run_context = RunContext :: new ( initial_pc, initial_ap. offset , initial_fp. offset ) ;
118- virtual_machine . set_run_context ( run_context) ;
89+ vm . set_run_context ( run_context) ;
11990
12091 let bytecode = executable
12192 . program
@@ -124,28 +95,19 @@ impl CairoRunner2 {
12495 . map ( Felt252 :: from)
12596 . map ( MaybeRelocatable :: from)
12697 . collect :: < Vec < _ > > ( ) ;
127-
128- virtual_machine
129- . load_data ( program_base, & bytecode)
98+ vm. load_data ( program_base, & bytecode)
13099 . map_err ( RunnerError :: MemoryInitializationError ) ?;
131-
132100 for i in 0 ..bytecode. len ( ) {
133- virtual_machine
134- . segments
135- . memory
136- . mark_as_accessed ( ( program_base + i) ?) ;
101+ vm. segments . memory . mark_as_accessed ( ( program_base + i) ?) ;
137102 }
138103
139- virtual_machine
140- . load_data ( execution_base, & stack)
104+ vm. load_data ( execution_base, & stack)
141105 . map_err ( RunnerError :: MemoryInitializationError ) ?;
142106
143- for builtin_runner in & mut virtual_machine . builtin_runners {
144- builtin_runner. add_validation_rule ( & mut virtual_machine . segments . memory )
107+ for builtin_runner in & mut vm . builtin_runners {
108+ builtin_runner. add_validation_rule ( & mut vm . segments . memory )
145109 }
146-
147- virtual_machine
148- . segments
110+ vm. segments
149111 . memory
150112 . validate_existing_memory ( )
151113 . map_err ( RunnerError :: MemoryValidationError ) ?;
@@ -157,7 +119,7 @@ impl CairoRunner2 {
157119
158120 Ok ( Self {
159121 executable,
160- virtual_machine ,
122+ vm ,
161123 program_base,
162124 execution_base,
163125 final_pc,
@@ -177,6 +139,52 @@ impl CairoRunner2 {
177139 }
178140}
179141
142+ fn find_entrypoint_of_kind (
143+ entrypoints : & [ ExecutableEntryPoint ] ,
144+ entrypoint_kind : EntryPointKind ,
145+ ) -> & ExecutableEntryPoint {
146+ entrypoints
147+ . iter ( )
148+ . find ( |entrypoint| {
149+ // TODO: Use `Eq` once implemented on `EntryPointKind`.
150+ std:: mem:: discriminant ( & entrypoint. kind ) == std:: mem:: discriminant ( & entrypoint_kind)
151+ } )
152+ . expect ( "executable had no entrypoint of required kind" )
153+ }
154+
155+ fn extend_stack_with_builtins (
156+ stack : & mut Vec < MaybeRelocatable > ,
157+ builtins : & [ BuiltinName ] ,
158+ runners : & [ BuiltinRunner ] ,
159+ ) {
160+ let runner_map: HashMap < BuiltinName , & BuiltinRunner > = runners
161+ . iter ( )
162+ . map ( |builtin_runner| ( builtin_runner. name ( ) , builtin_runner) )
163+ . collect ( ) ;
164+ for builtin in builtins {
165+ if let Some ( builtin_runner) = runner_map. get ( & builtin) {
166+ stack. append ( & mut builtin_runner. initial_stack ( ) ) ;
167+ } else {
168+ stack. push ( Felt252 :: ZERO . into ( ) )
169+ }
170+ }
171+ }
172+
173+ fn initialize_builtin_runner_segments (
174+ builtin_runners : & mut [ BuiltinRunner ] ,
175+ segments : & mut MemorySegmentManager ,
176+ ) {
177+ for builtin_runner in builtin_runners. iter_mut ( ) {
178+ builtin_runner. initialize_segments ( segments) ;
179+ }
180+
181+ for builtin_runner in builtin_runners. iter_mut ( ) {
182+ if let BuiltinRunner :: Mod ( mod_builtin_runner) = builtin_runner {
183+ mod_builtin_runner. initialize_zero_segment ( segments) ;
184+ }
185+ }
186+ }
187+
180188// TODO: Remove this once cyclic dependency is fixed.
181189// It should not be necessary, but cargo treats executable BuiltinName as a separate type
182190// which is why I had to create this adapter function.
@@ -215,12 +223,14 @@ pub fn check_builtin_order(builtins: &[BuiltinName]) -> Result<(), RunnerError>
215223
216224pub fn initialize_builtin_runners (
217225 layout : & CairoLayout ,
218- mut builtins : HashSet < BuiltinName > ,
226+ builtins : & [ BuiltinName ] ,
219227 allow_missing_builtins : bool ,
220228 create_all_builtins : bool ,
221229) -> Result < Vec < BuiltinRunner > , RunnerError > {
222230 let mut builtin_runners = Vec :: new ( ) ;
223231
232+ let mut builtins: HashSet < BuiltinName > = builtins. into_iter ( ) . map ( ToOwned :: to_owned) . collect ( ) ;
233+
224234 if layout. builtins . output {
225235 let included = builtins. remove ( & BuiltinName :: output) ;
226236 if included || create_all_builtins {
0 commit comments