diff options
author | Vincent Ambo <mail@tazj.in> | 2022-09-04T13·56+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-09T21·10+0000 |
commit | 8ee4d6d5db44d93c0fff67db87dcb4ae9f885351 (patch) | |
tree | 070d533eb3f1c775011695dc25a96c55aad05a8c /tvix/eval/src/observer.rs | |
parent | 7ae45342df28c7f3feb50334aee535a1d36e2bec (diff) |
feat(tvix/eval): implement DisassemblingObserver for compiler r/4775
This type implements an observer that is called whenever the compiler emits a chunk (after the toplevel, thunks, or lambdas) and prints the output of the disassembler to its internal writer. This replaces half of the uses of the `disassembler` feature, which has been removed from the Cargo configuration. Note that at this commit runtime tracing is not yet implemented as an observer. Change-Id: I7894ca1ba445761aba4ad51d98e4a7b6445f1aea Reviewed-on: https://cl.tvl.fyi/c/depot/+/6449 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
Diffstat (limited to '')
-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(); + } +} |