feat(tvix/eval): add generator-related functions to RuntimeObserver
These functions will be used by the changes in the VM to observe the runtime execution of generator frames, and provide a more linear view of the execution of the Tvix VM. Change-Id: I10b1b1933dedc065e7c61d5d6062f0aaeee0097e Reviewed-on: https://cl.tvl.fyi/c/depot/+/8240 Tested-by: BuildkiteCI Reviewed-by: Adam Joseph <adam@westernsemico.com>
This commit is contained in:
		
							parent
							
								
									d00229753d
								
							
						
					
					
						commit
						cd447e1859
					
				
					 2 changed files with 89 additions and 7 deletions
				
			
		| 
						 | 
					@ -13,6 +13,7 @@ use tabwriter::TabWriter;
 | 
				
			||||||
use crate::chunk::Chunk;
 | 
					use crate::chunk::Chunk;
 | 
				
			||||||
use crate::opcode::{CodeIdx, OpCode};
 | 
					use crate::opcode::{CodeIdx, OpCode};
 | 
				
			||||||
use crate::value::Lambda;
 | 
					use crate::value::Lambda;
 | 
				
			||||||
 | 
					use crate::vm::generators::GeneratorRequest;
 | 
				
			||||||
use crate::SourceCode;
 | 
					use crate::SourceCode;
 | 
				
			||||||
use crate::Value;
 | 
					use crate::Value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,10 +40,25 @@ pub trait CompilerObserver {
 | 
				
			||||||
/// the Tvix virtual machine at runtime.
 | 
					/// the Tvix virtual machine at runtime.
 | 
				
			||||||
pub trait RuntimeObserver {
 | 
					pub trait RuntimeObserver {
 | 
				
			||||||
    /// Called when the runtime enters a new call frame.
 | 
					    /// Called when the runtime enters a new call frame.
 | 
				
			||||||
    fn observe_enter_frame(&mut self, _arg_count: usize, _: &Rc<Lambda>, _call_depth: usize) {}
 | 
					    fn observe_enter_call_frame(&mut self, _arg_count: usize, _: &Rc<Lambda>, _call_depth: usize) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the runtime exits a call frame.
 | 
					    /// Called when the runtime exits a call frame.
 | 
				
			||||||
    fn observe_exit_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
					    fn observe_exit_call_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when the runtime suspends a call frame.
 | 
				
			||||||
 | 
					    fn observe_suspend_call_frame(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when the runtime enters a generator frame.
 | 
				
			||||||
 | 
					    fn observe_enter_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when the runtime exits a generator frame.
 | 
				
			||||||
 | 
					    fn observe_exit_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when the runtime suspends a generator frame.
 | 
				
			||||||
 | 
					    fn observe_suspend_generator(&mut self, _frame_at: usize, _stack: &[Value]) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Called when a generator requests an action from the VM.
 | 
				
			||||||
 | 
					    fn observe_generator_request(&mut self, _msg: &GeneratorRequest) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Called when the runtime replaces the current call frame for a
 | 
					    /// Called when the runtime replaces the current call frame for a
 | 
				
			||||||
    /// tail call.
 | 
					    /// tail call.
 | 
				
			||||||
| 
						 | 
					@ -136,7 +152,12 @@ impl<W: Write> TracingObserver<W> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<W: Write> RuntimeObserver for TracingObserver<W> {
 | 
					impl<W: Write> RuntimeObserver for TracingObserver<W> {
 | 
				
			||||||
    fn observe_enter_frame(&mut self, arg_count: usize, lambda: &Rc<Lambda>, call_depth: usize) {
 | 
					    fn observe_enter_call_frame(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        arg_count: usize,
 | 
				
			||||||
 | 
					        lambda: &Rc<Lambda>,
 | 
				
			||||||
 | 
					        call_depth: usize,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
        let _ = write!(&mut self.writer, "=== entering ");
 | 
					        let _ = write!(&mut self.writer, "=== entering ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let _ = if arg_count == 0 {
 | 
					        let _ = if arg_count == 0 {
 | 
				
			||||||
| 
						 | 
					@ -156,7 +177,8 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn observe_exit_frame(&mut self, frame_at: usize, stack: &[Value]) {
 | 
					    /// Called when the runtime exits a call frame.
 | 
				
			||||||
 | 
					    fn observe_exit_call_frame(&mut self, frame_at: usize, stack: &[Value]) {
 | 
				
			||||||
        let _ = write!(&mut self.writer, "=== exiting frame {} ===\t[ ", frame_at);
 | 
					        let _ = write!(&mut self.writer, "=== exiting frame {} ===\t[ ", frame_at);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for val in stack {
 | 
					        for val in stack {
 | 
				
			||||||
| 
						 | 
					@ -166,6 +188,66 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
 | 
				
			||||||
        let _ = writeln!(&mut self.writer, "]");
 | 
					        let _ = writeln!(&mut self.writer, "]");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn observe_suspend_call_frame(&mut self, frame_at: usize, stack: &[Value]) {
 | 
				
			||||||
 | 
					        let _ = write!(
 | 
				
			||||||
 | 
					            &mut self.writer,
 | 
				
			||||||
 | 
					            "=== suspending frame {} ===\t[ ",
 | 
				
			||||||
 | 
					            frame_at
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for val in stack {
 | 
				
			||||||
 | 
					            let _ = write!(&mut self.writer, "{} ", val);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let _ = writeln!(&mut self.writer, "]");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn observe_enter_generator(&mut self, frame_at: usize, stack: &[Value]) {
 | 
				
			||||||
 | 
					        let _ = write!(
 | 
				
			||||||
 | 
					            &mut self.writer,
 | 
				
			||||||
 | 
					            "=== entering generator frame {} ===\t[ ",
 | 
				
			||||||
 | 
					            frame_at
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for val in stack {
 | 
				
			||||||
 | 
					            let _ = write!(&mut self.writer, "{} ", val);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let _ = writeln!(&mut self.writer, "]");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn observe_exit_generator(&mut self, frame_at: usize, stack: &[Value]) {
 | 
				
			||||||
 | 
					        let _ = write!(
 | 
				
			||||||
 | 
					            &mut self.writer,
 | 
				
			||||||
 | 
					            "=== exiting generator {} ===\t[ ",
 | 
				
			||||||
 | 
					            frame_at
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for val in stack {
 | 
				
			||||||
 | 
					            let _ = write!(&mut self.writer, "{} ", val);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let _ = writeln!(&mut self.writer, "]");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn observe_suspend_generator(&mut self, frame_at: usize, stack: &[Value]) {
 | 
				
			||||||
 | 
					        let _ = write!(
 | 
				
			||||||
 | 
					            &mut self.writer,
 | 
				
			||||||
 | 
					            "=== suspending generator {} ===\t[ ",
 | 
				
			||||||
 | 
					            frame_at
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for val in stack {
 | 
				
			||||||
 | 
					            let _ = write!(&mut self.writer, "{} ", val);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let _ = writeln!(&mut self.writer, "]");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn observe_generator_request(&mut self, msg: &GeneratorRequest) {
 | 
				
			||||||
 | 
					        let _ = writeln!(&mut self.writer, "=== generator requested {} ===", msg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn observe_enter_builtin(&mut self, name: &'static str) {
 | 
					    fn observe_enter_builtin(&mut self, name: &'static str) {
 | 
				
			||||||
        let _ = writeln!(&mut self.writer, "=== entering builtin {} ===", name);
 | 
					        let _ = writeln!(&mut self.writer, "=== entering builtin {} ===", name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -184,7 +266,7 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> {
 | 
				
			||||||
        let _ = writeln!(
 | 
					        let _ = writeln!(
 | 
				
			||||||
            &mut self.writer,
 | 
					            &mut self.writer,
 | 
				
			||||||
            "=== tail-calling {:p} in frame[{}] ===",
 | 
					            "=== tail-calling {:p} in frame[{}] ===",
 | 
				
			||||||
            lambda, frame_at
 | 
					            *lambda, frame_at
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -436,7 +436,7 @@ impl<'o> VM<'o> {
 | 
				
			||||||
        arg_count: usize,
 | 
					        arg_count: usize,
 | 
				
			||||||
    ) -> EvalResult<()> {
 | 
					    ) -> EvalResult<()> {
 | 
				
			||||||
        self.observer
 | 
					        self.observer
 | 
				
			||||||
            .observe_enter_frame(arg_count, &lambda, self.frames.len() + 1);
 | 
					            .observe_enter_call_frame(arg_count, &lambda, self.frames.len() + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let frame = CallFrame {
 | 
					        let frame = CallFrame {
 | 
				
			||||||
            lambda,
 | 
					            lambda,
 | 
				
			||||||
| 
						 | 
					@ -472,7 +472,7 @@ impl<'o> VM<'o> {
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.observer
 | 
					        self.observer
 | 
				
			||||||
            .observe_exit_frame(self.frames.len() + 1, &self.stack);
 | 
					            .observe_exit_call_frame(self.frames.len() + 1, &self.stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        result
 | 
					        result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue