Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions majit/examples/braininterp/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Interpreter for Brainfuck — direct translation of rpython/jit/tl/braininterp.py.
///
/// Tape-based interpreter with 30000 cells, byte-sized values.
/// Operations: > < + - . , [ ]
//! Interpreter for Brainfuck — direct translation of rpython/jit/tl/braininterp.py.
//!
//! Tape-based interpreter with 30000 cells, byte-sized values.
//! Operations: > < + - . , [ ]

const TAPE_SIZE: usize = 30000;

Expand Down
12 changes: 3 additions & 9 deletions majit/examples/braininterp/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,18 @@ const MANDELBROT: &[u8] = b"+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--
/// BF: set cell0=N via repeated +, then loop: [-]
fn countdown_bf(n: usize) -> Vec<u8> {
let mut prog = Vec::with_capacity(n + 3);
for _ in 0..n {
prog.push(b'+');
}
prog.extend(std::iter::repeat_n(b'+', n));
prog.extend_from_slice(b"[-]");
prog
}

/// Multiply: cell1 = a * b via nested loop.
fn multiply_bf(a: u8, b: u8) -> Vec<u8> {
let mut prog = Vec::new();
for _ in 0..a {
prog.push(b'+');
}
prog.extend(std::iter::repeat_n(b'+', usize::from(a)));
prog.push(b'[');
prog.push(b'>');
for _ in 0..b {
prog.push(b'+');
}
prog.extend(std::iter::repeat_n(b'+', usize::from(b)));
prog.extend_from_slice(b"<-]");
prog
}
Expand Down
6 changes: 3 additions & 3 deletions majit/examples/cel/src/colscalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
//!
//! The `column` probe proved base-in-REGISTER compiles (13-16x). This isolates the
//! VirtualStatesCantMatch root cause: base-in-SCALAR-FIELD. Two programs,
//! identical except one re-writes the scalar field each iteration:
//! * RDONLY `state.col_base` set once at init, only READ in the loop.
//! * WRITTEN — `state.col_base` re-assigned from a register every iteration.
//! identical except one re-writes the scalar field each iteration.
//! RDONLY keeps `state.col_base` read-only after initialization; WRITTEN
//! reassigns it from a register every iteration.
//! Prints compiles/aborts for each. RELEASE ONLY.

use crate::common::*;
Expand Down
18 changes: 9 additions & 9 deletions majit/examples/dualtape/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/// Reference interpreter for a two-tape Brainfuck-like language.
///
/// Two independent tapes `a` and `b`, each with its own pointer:
/// `>` `<` `+` `-` move/mutate tape `a`
/// `}` `{` `*` `/` move/mutate tape `b`
/// `[` `]` loop on tape `a`'s current cell
///
/// `interpret` returns the sum of every cell across both tapes so the JIT
/// result can be compared against this oracle with a single integer.
//! Reference interpreter for a two-tape Brainfuck-like language.
//!
//! Two independent tapes `a` and `b`, each with its own pointer:
//! `>` `<` `+` `-` move/mutate tape `a`
//! `}` `{` `*` `/` move/mutate tape `b`
//! `[` `]` loop on tape `a`'s current cell
//!
//! `interpret` returns the sum of every cell across both tapes so the JIT
//! result can be compared against this oracle with a single integer.

pub const TAPE_SIZE: usize = 8;

Expand Down
27 changes: 15 additions & 12 deletions majit/examples/tiny2/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/// Interpreter for tiny2_hotpath — direct translation of rpython/jit/tl/tiny2_hotpath.py.
///
/// A word-based language: the program is a list of space-separated words.
/// Most words push themselves on a stack; some words have special actions.
///
/// 6 7 ADD => 13
/// { #1 #1 1 SUB ->#1 #1 } => with arg 5: pushes 5 4 3 2 1
///
/// Boxed values: IntBox (known integers) and StrBox (symbolic/string values).
/// In the Rust port we simplify to i64 for the integer path and String for symbolic.
//! Interpreter for tiny2_hotpath — direct translation of rpython/jit/tl/tiny2_hotpath.py.
//!
//! A word-based language: the program is a list of space-separated words.
//! Most words push themselves on a stack; some words have special actions.
//!
//! 6 7 ADD => 13
//! { #1 #1 1 SUB ->#1 #1 } => with arg 5: pushes 5 4 3 2 1
//!
//! Boxed values: IntBox (known integers) and StrBox (symbolic/string values).
//! In the Rust port we simplify to i64 for the integer path and String for symbolic.

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ParseBoxIntError;

/// A boxed value — either a known integer or a symbolic string.
#[derive(Clone, Debug)]
Expand All @@ -17,10 +20,10 @@ pub enum Box {
}

impl Box {
pub fn as_int(&self) -> Result<i64, ()> {
pub fn as_int(&self) -> Result<i64, ParseBoxIntError> {
match self {
Box::Int(v) => Ok(*v),
Box::Str(s) => parse_int(s, 0).ok_or(()),
Box::Str(s) => parse_int(s, 0).ok_or(ParseBoxIntError),
}
}

Expand Down
28 changes: 14 additions & 14 deletions majit/examples/tiny2/src/jit_interp.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/// JIT-enabled tiny2 interpreter via `#[jit_interp]` proc macro with `state_fields`.
///
/// TODO: `rpython/jit/tl/tiny2_hotpath.py:90` models the
/// operand stack as a linked-list `Stack(value, next)`; each push allocates
/// one cons cell that RPython's JIT peels as a chain of virtuals. pyre's
/// `state_fields = { stackpos, stack: [int; virt] }` does not express
/// linked-list stacks — it requires a contiguous virtualizable array. The
/// array backing is a source-shape deviation; post-optimization the trace
/// shape is equivalent to RPython's peeled virtuals for the shallow,
/// constant-height stacks the tinybench exercises. Porting a linked-list
/// state kind to #[jit_interp] is a separate, larger port.
///
/// Greens: [bytecode (env), pc]
/// Reds: [stackpos, stack] (tracked via state_fields)
//! JIT-enabled tiny2 interpreter via `#[jit_interp]` proc macro with `state_fields`.
//!
//! TODO: `rpython/jit/tl/tiny2_hotpath.py:90` models the
//! operand stack as a linked-list `Stack(value, next)`; each push allocates
//! one cons cell that RPython's JIT peels as a chain of virtuals. pyre's
//! `state_fields = { stackpos, stack: [int; virt] }` does not express
//! linked-list stacks — it requires a contiguous virtualizable array. The
//! array backing is a source-shape deviation; post-optimization the trace
//! shape is equivalent to RPython's peeled virtuals for the shallow,
//! constant-height stacks the tinybench exercises. Porting a linked-list
//! state kind to #[jit_interp] is a separate, larger port.
//!
//! Greens: [bytecode (env), pc]
//! Reds: [stackpos, stack] (tracked via state_fields)

// ── Bytecode opcodes ──

Expand Down
16 changes: 8 additions & 8 deletions majit/examples/tiny3/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/// Interpreter for tiny3_hotpath — direct translation of rpython/jit/tl/tiny3_hotpath.py.
///
/// A word-based language identical to tiny2 but with IntBox/FloatBox instead of
/// IntBox/StrBox. Arithmetic on mixed int/float types automatically casts to float.
///
/// 6 7 ADD => 13
/// 3.8 1 ADD => 4.8
/// 3.8 => 3.8
//! Interpreter for tiny3_hotpath — direct translation of rpython/jit/tl/tiny3_hotpath.py.
//!
//! A word-based language identical to tiny2 but with IntBox/FloatBox instead of
//! IntBox/StrBox. Arithmetic on mixed int/float types automatically casts to float.
//!
//! 6 7 ADD => 13
//! 3.8 1 ADD => 4.8
//! 3.8 => 3.8

/// A boxed value — either a known integer or a float.
#[derive(Clone, Debug)]
Expand Down
36 changes: 16 additions & 20 deletions majit/examples/tiny3/src/jit_interp.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/// JIT-enabled tiny3 interpreter via `#[jit_interp]` proc macro with `state_fields`.
///
/// TODO: `rpython/jit/tl/tiny3_hotpath.py:96` models the
/// operand stack as a linked-list `Stack(value, next)`, identical shape to
/// tiny2_hotpath.py. pyre's `state_fields = { stackpos, stack: [int; virt] }`
/// does not express linked-list stacks — see the same adaptation note on
/// `majit/examples/tiny2/src/jit_interp.rs`.
///
/// Greens: [pc]
/// Reds: [stackpos, stack] (args at bottom, computation stack on top)
///
/// The JIT traces the integer-only path. Float arithmetic falls back to the
/// plain interpreter. This matches RPython's promote(y.__class__) strategy.
//! JIT-enabled tiny3 interpreter via `#[jit_interp]` proc macro with `state_fields`.
//!
//! TODO: `rpython/jit/tl/tiny3_hotpath.py:96` models the
//! operand stack as a linked-list `Stack(value, next)`, identical shape to
//! tiny2_hotpath.py. pyre's `state_fields = { stackpos, stack: [int; virt] }`
//! does not express linked-list stacks — see the same adaptation note on
//! `majit/examples/tiny2/src/jit_interp.rs`.
//!
//! Greens: [pc]
//! Reds: [stackpos, stack] (args at bottom, computation stack on top)
//!
//! The JIT traces the integer-only path. Float arithmetic falls back to the
//! plain interpreter. This matches RPython's promote(y.__class__) strategy.

// ── Bytecode opcodes ──

Expand Down Expand Up @@ -246,7 +246,7 @@ impl JitTiny3Interp {
}

/// Run a word-based program with integer args.
pub fn run(&mut self, bytecode: &[&str], args: &mut Vec<i64>) -> i64 {
pub fn run(&mut self, bytecode: &[&str], args: &mut [i64]) -> i64 {
let code = compile(bytecode);
let num_args = args.len();
let has_result_on_stack = program_has_result(bytecode, num_args);
Expand Down Expand Up @@ -297,7 +297,7 @@ impl JitTiny3Interp {
pub fn run_typed(
&mut self,
bytecode: &[&str],
args: &mut Vec<crate::interp::Box>,
args: &mut [crate::interp::Box],
) -> crate::interp::Box {
// For typed runs, use the plain interpreter.
// The JIT only traces the integer-only path.
Expand All @@ -321,12 +321,8 @@ fn program_has_result(words: &[&str], num_args: usize) -> bool {
loop_depth -= 1;
depth -= 1;
} else if loop_depth == 0 {
if *w == "ADD" || *w == "SUB" || *w == "MUL" {
if matches!(*w, "ADD" | "SUB" | "MUL") || w.starts_with("->#") {
depth -= 1;
} else if w.starts_with("->#") {
depth -= 1;
} else if w.starts_with('#') {
depth += 1;
} else {
depth += 1;
}
Expand Down
8 changes: 4 additions & 4 deletions majit/examples/tl/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Interpreter for TL — direct translation of rpython/jit/tl/tl.py.
///
/// Stack-based interpreter with integer values and virtualizable stack.
//! Interpreter for TL — direct translation of rpython/jit/tl/tl.py.
//!
//! Stack-based interpreter with integer values and virtualizable stack.

const NOP: u8 = 1;
const PUSH: u8 = 2;
Expand Down Expand Up @@ -144,7 +144,7 @@ pub fn interpret_at(code: &[u8], mut pc: usize, inputarg: i64) -> i64 {
stack.pop().unwrap()
}

fn roll(stack: &mut Vec<i64>, r: i64) {
fn roll(stack: &mut [i64], r: i64) {
let len = stack.len();
if r < -1 {
let i = (len as i64 + r) as usize;
Expand Down
8 changes: 4 additions & 4 deletions majit/examples/tla/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Interpreter for TLA — direct translation of rpython/jit/tl/tla/tla.py.
///
/// Object-oriented stack machine with wrapped values (W_IntObject, W_StringObject).
/// The frame is virtualizable in RPython: `_virtualizable_ = ['stackpos', 'stack[*]']`.
//! Interpreter for TLA — direct translation of rpython/jit/tl/tla/tla.py.
//!
//! Object-oriented stack machine with wrapped values (W_IntObject, W_StringObject).
//! The frame is virtualizable in RPython: `_virtualizable_ = ['stackpos', 'stack[*]']`.

const CONST_INT: u8 = 0;
const POP: u8 = 1;
Expand Down
6 changes: 3 additions & 3 deletions majit/examples/tlr/src/interp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Interpreter for TLR — direct translation of rpython/jit/tl/tlr.py:interpret().
///
/// Bytecode format is identical: &[u8] with single-byte opcodes and args.
//! Interpreter for TLR — direct translation of rpython/jit/tl/tlr.py:interpret().
//!
//! Bytecode format is identical: &[u8] with single-byte opcodes and args.

const MOV_A_R: u8 = 1;
const MOV_R_A: u8 = 2;
Expand Down
Loading
Loading