diff options
Diffstat (limited to 'tvix/eval/src/observer.rs')
-rw-r--r-- | tvix/eval/src/observer.rs | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs index bf05295ac356..5aeb344ee954 100644 --- a/tvix/eval/src/observer.rs +++ b/tvix/eval/src/observer.rs @@ -4,9 +4,15 @@ //! This can be used to gain insights from compilation, to trace the //! runtime, and so on. -use crate::value::Lambda; - +use codemap::CodeMap; +use std::io::Write; use std::rc::Rc; +use tabwriter::TabWriter; + +use crate::chunk::Chunk; +use crate::disassembler::disassemble_op; +use crate::opcode::CodeIdx; +use crate::value::Lambda; /// Implemented by types that wish to observe internal happenings of /// Tvix. @@ -34,3 +40,59 @@ pub trait Observer { pub struct NoOpObserver {} impl Observer for NoOpObserver {} + +/// An observer that prints disassembled chunk information to its +/// internal writer whenwever the compiler emits a toplevel function, +/// closure or thunk. +pub struct DisassemblingObserver<W: Write> { + codemap: Rc<CodeMap>, + writer: TabWriter<W>, +} + +impl<W: Write> DisassemblingObserver<W> { + pub fn new(codemap: Rc<CodeMap>, writer: W) -> Self { + Self { + codemap, + writer: TabWriter::new(writer), + } + } + + fn lambda_header(&mut self, kind: &str, lambda: &Rc<Lambda>) { + let _ = writeln!( + &mut self.writer, + "=== compiled {} @ {:p} ({} ops) ===", + kind, + lambda, + lambda.chunk.code.len() + ); + } + + fn disassemble_chunk(&mut self, chunk: &Chunk) { + // calculate width of the widest address in the chunk + let width = format!("{:#x}", chunk.code.len() - 1).len(); + + for (idx, _) in chunk.code.iter().enumerate() { + disassemble_op(&mut self.writer, &self.codemap, chunk, width, CodeIdx(idx)); + } + } +} + +impl<W: Write> Observer for DisassemblingObserver<W> { + fn observe_compiled_toplevel(&mut self, lambda: &Rc<Lambda>) { + self.lambda_header("toplevel", lambda); + self.disassemble_chunk(&lambda.chunk); + let _ = self.writer.flush(); + } + + fn observe_compiled_lambda(&mut self, lambda: &Rc<Lambda>) { + self.lambda_header("lambda", lambda); + self.disassemble_chunk(&lambda.chunk); + let _ = self.writer.flush(); + } + + fn observe_compiled_thunk(&mut self, lambda: &Rc<Lambda>) { + self.lambda_header("thunk", lambda); + self.disassemble_chunk(&lambda.chunk); + let _ = self.writer.flush(); + } +} |