@@ -17,6 +17,8 @@ use std::path::{Path, PathBuf};
1717use std:: sync:: { Arc , Mutex } ;
1818use std:: thread;
1919use wasi_common:: sync:: { Dir , TcpListener , WasiCtxBuilder , ambient_authority} ;
20+ #[ cfg( feature = "rr" ) ]
21+ use wasmtime:: ReplayEnvironment ;
2022use wasmtime:: { Engine , Func , Module , Store , StoreLimits , Val , ValType } ;
2123use wasmtime_wasi:: { WasiCtxView , WasiView } ;
2224
@@ -100,7 +102,16 @@ impl RunCommand {
100102 self . run . common . init_logging ( ) ?;
101103
102104 let mut config = self . run . common . config ( None ) ?;
105+ #[ cfg( not( feature = "rr" ) ) ]
103106 config. async_support ( true ) ;
107+ #[ cfg( feature = "rr" ) ]
108+ if replay_opts. is_some ( ) {
109+ // Replay does not support async yet
110+ config. async_support ( false ) ;
111+ config. rr ( wasmtime:: RRConfig :: Replaying ) ;
112+ } else {
113+ config. async_support ( true ) ;
114+ }
104115
105116 if self . run . common . wasm . timeout . is_some ( ) {
106117 config. epoch_interruption ( true ) ;
@@ -116,11 +127,6 @@ impl RunCommand {
116127 None => { }
117128 }
118129
119- #[ cfg( feature = "rr" ) ]
120- if replay_opts. is_some ( ) {
121- config. replaying ( true ) ;
122- }
123-
124130 let engine = Engine :: new ( & config) ?;
125131
126132 // Read the wasm module binary either as `*.wat` or a raw binary.
@@ -167,7 +173,13 @@ impl RunCommand {
167173 } ;
168174
169175 let mut store = Store :: new ( & engine, host) ;
176+ #[ cfg( not( feature = "rr" ) ) ]
170177 self . populate_with_wasi ( & mut linker, & mut store, & main) ?;
178+ // For replay, we don't populate WASI
179+ #[ cfg( feature = "rr" ) ]
180+ if !replay_opts. is_some ( ) {
181+ self . populate_with_wasi ( & mut linker, & mut store, & main) ?;
182+ }
171183
172184 store. data_mut ( ) . limits = self . run . store_limits ( ) ;
173185 store. limiter ( |t| & mut t. limits ) ;
@@ -180,6 +192,33 @@ impl RunCommand {
180192
181193 #[ cfg( feature = "rr" ) ]
182194 {
195+ // If this is a replay run, skip to replay setup and run to completion
196+ //
197+ // Note: Right now, replay doesn't inherit any store settings listed
198+ // above. This will have to change in the future. In general, replays will
199+ // need an "almost exact" superset of the run configurations, but with
200+ // certain different options (e.g. fuel consumption).
201+ if let Some ( opts) = replay_opts {
202+ let settings = ReplaySettings {
203+ validate : opts. validate ,
204+ deser_buffer_size : opts. deser_buffer_size ,
205+ ..Default :: default ( )
206+ } ;
207+
208+ let mut renv = ReplayEnvironment :: new ( & engine, settings) ;
209+ match main {
210+ RunTarget :: Core ( m) => {
211+ renv. add_module ( m) ;
212+ }
213+ RunTarget :: Component ( c) => {
214+ renv. add_component ( c) ;
215+ }
216+ }
217+ let mut instance = renv. instantiate ( BufReader :: new ( fs:: File :: open ( opts. trace ) ?) ) ?;
218+ return instance. run_to_completion ( ) ;
219+ }
220+
221+ // Recording settings for this execution's store
183222 let record = & self . run . common . record ;
184223 if let Some ( path) = & record. path {
185224 let default_settings = RecordSettings :: default ( ) ;
@@ -197,18 +236,6 @@ impl RunCommand {
197236 store. init_recording ( fs:: File :: create ( & path) ?, settings) ?;
198237 }
199238 }
200-
201- if let Some ( opts) = replay_opts {
202- let settings = ReplaySettings {
203- validate : opts. validate ,
204- deser_buffer_size : opts. deser_buffer_size ,
205- ..Default :: default ( )
206- } ;
207- store. init_replaying (
208- BufReader :: new ( fs:: File :: open ( opts. trace ) . unwrap ( ) ) ,
209- settings,
210- ) ?;
211- }
212239 }
213240
214241 // Always run the module asynchronously to ensure that the module can be
0 commit comments