Skip to content

Commit

Permalink
Switch to trait based
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss committed Sep 23, 2023
1 parent 54050c0 commit 58ca1b2
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 113 deletions.
30 changes: 9 additions & 21 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ pub use maybe_shared::MaybeShared;
pub use std::marker::PhantomData;
use std::{io::Read, path::Path, rc::Rc};

#[cfg(feature = "trace")]
use crate::vm::trace;

use crate::{
builtins,
class::{Class, ClassBuilder},
Expand Down Expand Up @@ -380,38 +383,23 @@ impl<'host> Context<'host> {
#[inline]
/// Initializes a `Vm` trace from the context
pub fn init_trace(&mut self) {
let trace = crate::vm::trace::VmTrace::default();
let trace = trace::VmTrace::default();
self.vm.set_trace(trace);
}

#[cfg(feature = "trace")]
#[inline]
/// Initializes a partial `Vm` trace from the context.
pub fn init_partial_trace(&mut self) {
let trace = crate::vm::trace::VmTrace::partial();
self.vm.set_trace(trace);
}

#[cfg(feature = "trace")]
/// Initialize a provided custom trace
pub fn set_custom_trace(&mut self, trace: crate::vm::trace::VmTrace) {
let trace = trace::VmTrace::partial();
self.vm.set_trace(trace);
}

#[cfg(feature = "trace")]
/// Sets custom handling of compilation trace output
pub fn set_custom_compile_trace(&mut self, f: Box<dyn Fn(&str)>) {
if let Some(trace) = &mut self.vm.trace {
trace.set_compiled_action(f);
}
}

#[cfg(feature = "trace")]
/// Sets custom handling of trace action.
pub fn set_custom_runtime_trace(&mut self, f: Box<dyn Fn(&str)>) {
if let Some(trace) = &mut self.vm.trace {
trace.set_trace_action(f);
}
/// Sets custom handling of trace messages.
pub fn set_tracer_implementation(&mut self, tracer: Box<dyn trace::Tracer>) {
let trace = trace::VmTrace::default().with_tracer(tracer);
self.vm.trace = Some(trace);
}

/// Get optimizer options.
Expand Down
5 changes: 4 additions & 1 deletion boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ bitflags! {
}
}

#[cfg(feature = "trace")]
bitflags! {
/// Trace specific flags for [`CodeBlock`]
#[derive(Clone, Copy, Debug, Finalize)]
#[cfg(feature = "trace")]
pub(crate) struct TraceFlags: u8 {
/// Trace instruction execution to `stdout`.
const TRACEABLE = 0b0000_0001;
Expand Down Expand Up @@ -133,6 +133,7 @@ pub struct CodeBlock {
#[unsafe_ignore_trace]
pub(crate) flags: Cell<CodeBlockFlags>,

#[cfg(feature = "trace")]
#[unsafe_ignore_trace]
pub(crate) trace_flags: Cell<TraceFlags>,

Expand Down Expand Up @@ -182,8 +183,10 @@ impl CodeBlock {
pub fn new(name: JsString, length: u32, strict: bool) -> Self {
let mut flags = CodeBlockFlags::empty();
flags.set(CodeBlockFlags::STRICT, strict);

#[cfg(feature = "trace")]
let t_flags = TraceFlags::empty();

Self {
bytecode: Box::default(),
literals: Box::default(),
Expand Down
4 changes: 3 additions & 1 deletion boa_engine/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ mod runtime_limits;
#[cfg(feature = "flowgraph")]
pub mod flowgraph;

#[cfg(feature = "trace")]
use trace::VmTrace;

pub use runtime_limits::RuntimeLimits;

use self::vm_trace::VmTrace;
pub use {
call_frame::{CallFrame, GeneratorResumeKind},
code_block::CodeBlock,
Expand Down
128 changes: 59 additions & 69 deletions boa_engine/src/vm/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,41 @@ use boa_interner::{Interner, ToInternedString};

use super::Vm;

// TODO: Build out further, maybe provide more element visiblity and events/outputs
/// The `Tracer` trait is a customizable trait that can be provided to `Boa`
/// for customizing output.
pub trait Tracer {
/// The output from tracing a `CodeBlock`'s bytecode.
fn emit_bytecode_trace(&self, msg: &str);
/// The output from entering a `CallFrame`.
fn emit_call_frame_entrance_trace(&self, msg: &str);
/// The trace output from an execution.
fn emit_instruction_trace(&self, msg: &str);
/// Trace output from exiting a `CallFrame`.
fn emit_call_frame_exit_trace(&self, msg: &str);
}

#[derive(Debug)]
pub(crate) struct DefaultTracer;

impl Tracer for DefaultTracer {
fn emit_bytecode_trace(&self, msg: &str) {
println!("{msg}");
}

fn emit_call_frame_entrance_trace(&self, msg: &str) {
println!("{msg}");
}

fn emit_instruction_trace(&self, msg: &str) {
println!("{msg}");
}

fn emit_call_frame_exit_trace(&self, msg: &str) {
println!("{msg}");
}
}

bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TraceOptions: u8 {
Expand All @@ -28,16 +63,12 @@ impl Vm {
impl Default for VmTrace {
fn default() -> Self {
Self {
compiled_action: None,
trace_action: None,
options: Cell::new(TraceOptions::FULL_TRACE),
tracer: Box::new(DefaultTracer),
}
}
}

// Action function provided by the user.
type ActionFunction = Box<dyn Fn(&str)>;

/// `VmTrace` is a boa spcific structure for running Boa's Virtual Machine trace.
///
/// The struct provides options for a user to set customized actions for handling
Expand All @@ -52,9 +83,8 @@ type ActionFunction = Box<dyn Fn(&str)>;
/// After the Global callframe is initially provided. It searches
/// for all possible compiled output
pub struct VmTrace {
compiled_action: Option<ActionFunction>,
trace_action: Option<ActionFunction>,
options: Cell<TraceOptions>,
tracer: Box<dyn Tracer>,
}

// ==== Public API ====
Expand All @@ -64,34 +94,21 @@ impl VmTrace {
/// Create a partial `VmTrace`.
pub fn partial() -> Self {
Self {
compiled_action: None,
trace_action: None,
options: Cell::new(TraceOptions::empty()),
tracer: Box::new(DefaultTracer),
}
}

#[must_use]
/// Method for adding a compiled action on initialization.
pub fn with_compiled_action(mut self, f: ActionFunction) -> Self {
self.set_compiled_action(f);
pub fn with_tracer(mut self, tracer: Box<dyn Tracer>) -> Self {
self.set_tracer(tracer);
self
}

#[must_use]
/// Method for adding a trace action on initialization.
pub fn with_trace_action(mut self, f: ActionFunction) -> Self {
self.set_trace_action(f);
self
}

/// Sets the `compiled_action` of `VmTrace` to a custom user-defined action.
pub fn set_compiled_action(&mut self, f: ActionFunction) {
self.compiled_action = Some(f);
}

/// Sets the `trace_action` of `VmTrace` to a custom user-defined action.
pub fn set_trace_action(&mut self, f: ActionFunction) {
self.trace_action = Some(f);
/// Sets the current `Tracer` of `VmTrace`.
pub fn set_tracer(&mut self, tracer: Box<dyn Tracer>) {
self.tracer = tracer;
}
}

Expand Down Expand Up @@ -133,32 +150,15 @@ impl VmTrace {
}
}

// ---- Trace Event/Action Methods ----
// ==== Trace Event/Action Methods ====

impl VmTrace {
const COLUMN_WIDTH: usize = 26;
const TIME_COLUMN_WIDTH: usize = Self::COLUMN_WIDTH / 2;
const OPCODE_COLUMN_WIDTH: usize = Self::COLUMN_WIDTH;
const OPERAND_COLUMN_WIDTH: usize = Self::COLUMN_WIDTH;
const NUMBER_OF_COLUMNS: usize = 4;

pub(crate) fn trigger_compiled_output_action(&self, msg: &str) {
if let Some(action) = &self.compiled_action {
action(&format!("{msg}\n"));
} else {
println!("{msg}");
}
}

pub(crate) fn trigger_trace_action(&self, msg: &str) {
if let Some(action) = &self.trace_action {
action(&format!("{msg}\n"));
} else {
println!("{msg}");
}
}
}

impl VmTrace {
/// Trace the current `CallFrame` according to current state
pub(crate) fn trace_call_frame(&self, vm: &Vm, interner: &Interner) {
if self.is_full_trace() {
Expand Down Expand Up @@ -187,7 +187,7 @@ impl VmTrace {
"{msg:-^width$}",
width = Self::COLUMN_WIDTH * Self::NUMBER_OF_COLUMNS - 10
);
self.trigger_trace_action(&frame_header);
self.tracer.emit_call_frame_entrance_trace(&frame_header);

if vm.frames.len() == 1 {
let column_headers = format!(
Expand All @@ -200,7 +200,7 @@ impl VmTrace {
OPERAND_COLUMN_WIDTH = Self::OPERAND_COLUMN_WIDTH,
);

self.trigger_trace_action(&column_headers);
self.tracer.emit_call_frame_entrance_trace(&column_headers);
}
}

Expand All @@ -216,26 +216,31 @@ impl VmTrace {

queue.extend(block.functions.iter().cloned());

self.trigger_compiled_output_action(&block.to_interned_string(interner));
self.tracer
.emit_bytecode_trace(&block.to_interned_string(interner));
}
}
}

/// Searches and traces for only current frame's `CodeBlock`.
pub(crate) fn trace_current_bytecode(&self, vm: &Vm, interner: &Interner) {
self.trigger_compiled_output_action(&vm.frame().code_block().to_interned_string(interner));
self.tracer
.emit_bytecode_trace(&vm.frame().code_block().to_interned_string(interner));
}

/// Emits an exit message for the current `CallFrame`.
pub(crate) fn trace_frame_end(&self, vm: &Vm, return_msg: &str) {
if self.should_trace() {
let msg = format!(" Call Frame -- <Exiting {} via {return_msg}> ", vm.frame().code_block().name.to_std_string_escaped());
let msg = format!(
" Call Frame -- <Exiting {} via {return_msg}> ",
vm.frame().code_block().name.to_std_string_escaped()
);
let frame_footer = format!(
"{msg:-^width$}",
width = Self::COLUMN_WIDTH * Self::NUMBER_OF_COLUMNS - 10
);

self.trigger_trace_action(&frame_footer);
self.tracer.emit_call_frame_exit_trace(&frame_footer);
}

self.inactivate();
Expand All @@ -253,7 +258,7 @@ impl VmTrace {
OPERAND_COLUMN_WIDTH = Self::OPERAND_COLUMN_WIDTH,
);

self.trigger_trace_action(&instruction_trace);
self.tracer.emit_instruction_trace(&instruction_trace);
}

#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -273,27 +278,12 @@ impl VmTrace {
OPERAND_COLUMN_WIDTH = Self::OPERAND_COLUMN_WIDTH,
);

self.trigger_trace_action(&instruction_trace);
self.tracer.emit_instruction_trace(&instruction_trace);
}
}

impl fmt::Debug for VmTrace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let compiled_action_val = if self.compiled_action.is_none() {
"None"
} else {
"User Defined Fn"
};

let trace_action_val = if self.trace_action.is_none() {
"None"
} else {
"User Defined Fn"
};

f.debug_struct("VmTrace")
.field("Compiled Action", &compiled_action_val)
.field("Runtime Trace Action", &trace_action_val)
.finish()
write!(f, "Current Active Tracer")
}
}
Loading

0 comments on commit 58ca1b2

Please sign in to comment.