From cd447e185989494200552c05b8b859fd72cefe95 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Fri, 10 Mar 2023 14:22:52 +0300 Subject: 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 --- tvix/eval/src/observer.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++--- tvix/eval/src/vm.rs | 4 +-- 2 files changed, 89 insertions(+), 7 deletions(-) (limited to 'tvix/eval/src') diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs index 6bd4609b0998..533182f09531 100644 --- a/tvix/eval/src/observer.rs +++ b/tvix/eval/src/observer.rs @@ -13,6 +13,7 @@ use tabwriter::TabWriter; use crate::chunk::Chunk; use crate::opcode::{CodeIdx, OpCode}; use crate::value::Lambda; +use crate::vm::generators::GeneratorRequest; use crate::SourceCode; use crate::Value; @@ -39,10 +40,25 @@ pub trait CompilerObserver { /// the Tvix virtual machine at runtime. pub trait RuntimeObserver { /// Called when the runtime enters a new call frame. - fn observe_enter_frame(&mut self, _arg_count: usize, _: &Rc, _call_depth: usize) {} + fn observe_enter_call_frame(&mut self, _arg_count: usize, _: &Rc, _call_depth: usize) {} /// 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 /// tail call. @@ -136,7 +152,12 @@ impl TracingObserver { } impl RuntimeObserver for TracingObserver { - fn observe_enter_frame(&mut self, arg_count: usize, lambda: &Rc, call_depth: usize) { + fn observe_enter_call_frame( + &mut self, + arg_count: usize, + lambda: &Rc, + call_depth: usize, + ) { let _ = write!(&mut self.writer, "=== entering "); let _ = if arg_count == 0 { @@ -156,7 +177,8 @@ impl RuntimeObserver for TracingObserver { ); } - 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); for val in stack { @@ -166,6 +188,66 @@ impl RuntimeObserver for TracingObserver { 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) { let _ = writeln!(&mut self.writer, "=== entering builtin {} ===", name); } @@ -184,7 +266,7 @@ impl RuntimeObserver for TracingObserver { let _ = writeln!( &mut self.writer, "=== tail-calling {:p} in frame[{}] ===", - lambda, frame_at + *lambda, frame_at ); } diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 3e3052555639..f5107f9ed738 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -436,7 +436,7 @@ impl<'o> VM<'o> { arg_count: usize, ) -> EvalResult<()> { 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 { lambda, @@ -472,7 +472,7 @@ impl<'o> VM<'o> { }; self.observer - .observe_exit_frame(self.frames.len() + 1, &self.stack); + .observe_exit_call_frame(self.frames.len() + 1, &self.stack); result } -- cgit 1.4.1