From 26d1aa40292b33c3dc35f4ce8ccca10f1efbd5a1 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Thu, 6 Feb 2025 11:29:23 -0500 Subject: [PATCH] Add Intern opcode --- zjit/src/ir.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/zjit/src/ir.rs b/zjit/src/ir.rs index e39ca8bfcc..20f2f17663 100644 --- a/zjit/src/ir.rs +++ b/zjit/src/ir.rs @@ -18,6 +18,7 @@ enum Insn { // SSA block parameter. Also used for function parameters in the function's entry block. Param { idx: usize }, StringCopy { val: Opnd }, + StringIntern { val: Opnd }, // Control flow instructions Return { val: Opnd }, @@ -68,6 +69,7 @@ enum RubyOpcode { Putnil, Putobject(VALUE), Putstring(VALUE), + Intern, Setlocal(usize), Getlocal(usize), Leave, @@ -119,8 +121,13 @@ fn to_ssa(opcodes: &Vec) -> Function { RubyOpcode::Putnil => { state.push(Opnd::Const(Qnil)); }, RubyOpcode::Putobject(val) => { state.push(Opnd::Const(*val)); }, RubyOpcode::Putstring(val) => { - let insn_id = Opnd::Insn(result.push_insn(block, Insn::StringCopy { val: Opnd::Const(*val) })); - state.push(insn_id); + let insn_id = result.push_insn(block, Insn::StringCopy { val: Opnd::Const(*val) }); + state.push(Opnd::Insn(insn_id)); + } + RubyOpcode::Intern => { + let val = state.pop(); + let insn_id = result.push_insn(block, Insn::StringIntern { val }); + state.push(Opnd::Insn(insn_id)); } RubyOpcode::Setlocal(idx) => { let val = state.pop(); @@ -159,4 +166,25 @@ mod tests { ], }); } + + #[test] + fn test_intern() { + let opcodes = vec![ + RubyOpcode::Putstring(Qnil), + RubyOpcode::Intern, + RubyOpcode::Leave, + ]; + let function = to_ssa(&opcodes); + assert_eq!(function, Function { + entry_block: BlockId(0), + insns: vec![ + Insn::StringCopy { val: Opnd::Const(Qnil) }, + Insn::StringIntern { val: Opnd::Insn(InsnId(0)) }, + Insn::Return { val: Opnd::Insn(InsnId(1)) } + ], + blocks: vec![ + Block { params: vec![], insns: vec![InsnId(0), InsnId(1), InsnId(2)] } + ], + }); + } }