-
-
Notifications
You must be signed in to change notification settings - Fork 601
Expand file tree
/
Copy pathtrace.rs
More file actions
126 lines (113 loc) · 4.36 KB
/
trace.rs
File metadata and controls
126 lines (113 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::time::Duration;
/// The call frame name
///
/// This will have the name of the call frame provided or `Global` it's
/// the global call frame.
#[derive(Debug, Clone)]
pub enum CallFrameName {
Global,
Name(String),
}
/// A message that is emitted at the beginning of execution
#[derive(Debug, Clone)]
pub struct ExecutionStartMessage {
pub call_frame_name: CallFrameName,
}
/// A message that emits details about a call frame
#[derive(Debug, Clone)]
pub struct CallFrameMessage {
pub bytecode: String,
}
/// A message that emits instruction execution details about a call frame
#[derive(Debug, Clone)]
pub struct OpcodeExecutionMessage {
pub opcode: &'static str,
pub duration: Duration,
pub operands: String,
pub stack: String,
}
/// The various events that are emitted from Boa's virtual machine.
#[derive(Debug, Clone)]
pub enum VirtualMachineEvent {
/// This event is the first event triggered.
///
/// It emits information about the call frame.
CallFrameTrace(CallFrameMessage),
/// This event is triggered when the execution of a call frame is starting.
ExecutionStart(ExecutionStartMessage),
/// This event is triggered when executing an operation.
///
/// It provides information about the opcode execution
ExecutionTrace(OpcodeExecutionMessage),
/// This event is triggered when a opcode that calls is reached.
///
/// It signals that we about about to switch call frames.
ExecutionCallEvent,
}
/// A trait to define a tracer that plugs into Boa's `Vm`
pub trait VirtualMachineTracer: std::fmt::Debug {
/// Emits `VirtualMachineEvent`s from the virtual machine during execution
fn emit_event(&self, _event: VirtualMachineEvent) {}
}
/// A default empty virtual machine tracer that drops events submitted to it.
#[derive(Debug, Clone, Copy)]
pub struct EmptyTracer;
impl VirtualMachineTracer for EmptyTracer {}
/// `StdoutTracer` is a `VirtualMachineTracer` implementation that prints the events
/// to stdout in a specific format.
#[derive(Debug, Clone, Copy)]
pub struct StdoutTracer;
impl StdoutTracer {
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;
}
#[allow(clippy::print_stdout)]
impl VirtualMachineTracer for StdoutTracer {
fn emit_event(&self, event: VirtualMachineEvent) {
match event {
VirtualMachineEvent::ExecutionStart(start_message) => {
let msg = match start_message.call_frame_name {
CallFrameName::Global => " VM Start ".to_string(),
CallFrameName::Name(name) => {
format!(" Call Frame -- {name} ")
}
};
println!(
"{msg:-^width$}",
width = Self::COLUMN_WIDTH * Self::NUMBER_OF_COLUMNS - 10
);
println!(
"{:<TIME_COLUMN_WIDTH$} {:<OPCODE_COLUMN_WIDTH$} {:<OPERAND_COLUMN_WIDTH$} Stack\n",
"Time",
"Opcode",
"Operands",
TIME_COLUMN_WIDTH = Self::TIME_COLUMN_WIDTH,
OPCODE_COLUMN_WIDTH = Self::OPCODE_COLUMN_WIDTH,
OPERAND_COLUMN_WIDTH = Self::OPERAND_COLUMN_WIDTH,
);
}
VirtualMachineEvent::ExecutionCallEvent => println!(),
VirtualMachineEvent::CallFrameTrace(call_frame_message) => {
println!("{}", call_frame_message.bytecode);
}
VirtualMachineEvent::ExecutionTrace(execution_message) => {
let OpcodeExecutionMessage {
opcode,
duration,
operands,
stack,
} = execution_message;
println!(
"{:<TIME_COLUMN_WIDTH$} {opcode:<OPCODE_COLUMN_WIDTH$} {operands:<OPERAND_COLUMN_WIDTH$} {stack}",
format!("{}μs", duration.as_micros()),
TIME_COLUMN_WIDTH = Self::TIME_COLUMN_WIDTH,
OPCODE_COLUMN_WIDTH = Self::OPCODE_COLUMN_WIDTH,
OPERAND_COLUMN_WIDTH = Self::OPERAND_COLUMN_WIDTH,
);
}
}
}
}