Skip to content

Commit 164bd8e

Browse files
aidenfoxiveyk0kubun
authored andcommitted
Add codegen support for ArrayDup
1 parent 0e766c9 commit 164bd8e

File tree

3 files changed

+48
-18
lines changed

3 files changed

+48
-18
lines changed

test/ruby/test_zjit.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ def test(a, b) = a >= b
187187
}, call_threshold: 2
188188
end
189189

190+
def test_array_dup
191+
assert_compiles '[1, 2, 3]', %q{
192+
def test = [1,2,3]
193+
test
194+
}
195+
end
196+
190197
def test_if
191198
assert_compiles '[0, nil]', %q{
192199
def test(n)

zjit/src/codegen.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ fn gen_insn(jit: &mut JITState, asm: &mut Assembler, function: &Function, insn_i
182182
let out_opnd = match insn {
183183
Insn::PutSelf => gen_putself(),
184184
Insn::Const { val: Const::Value(val) } => gen_const(*val),
185+
Insn::ArrayDup { val, state } => gen_array_dup(asm, opnd!(val), &function.frame_state(*state)),
185186
Insn::Param { idx } => unreachable!("block.insns should not have Insn::Param({idx})"),
186187
Insn::Snapshot { .. } => return Some(()), // we don't need to do anything for this instruction at the moment
187188
Insn::Jump(branch) => return gen_jump(jit, asm, branch),
@@ -396,6 +397,23 @@ fn gen_send_without_block(
396397
Some(ret)
397398
}
398399

400+
/// Compile an array duplication instruction
401+
fn gen_array_dup(
402+
asm: &mut Assembler,
403+
val: lir::Opnd,
404+
state: &FrameState,
405+
) -> lir::Opnd {
406+
asm_comment!(asm, "call rb_ary_resurrect");
407+
408+
// Save PC
409+
gen_save_pc(asm, state);
410+
411+
asm.ccall(
412+
rb_ary_resurrect as *const u8,
413+
vec![val],
414+
)
415+
}
416+
399417
/// Compile code that exits from JIT code with a return value
400418
fn gen_return(asm: &mut Assembler, val: lir::Opnd) -> Option<()> {
401419
// Pop the current frame (ec->cfp++)

zjit/src/hir.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ pub enum Insn {
300300

301301
NewArray { elements: Vec<InsnId> },
302302
ArraySet { array: InsnId, idx: usize, val: InsnId },
303-
ArrayDup { val: InsnId },
303+
ArrayDup { val: InsnId, state: InsnId },
304304

305305
// Check if the value is truthy and "return" a C boolean. In reality, we will likely fuse this
306306
// with IfTrue/IfFalse in the backend to generate jcc.
@@ -433,7 +433,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
433433
Ok(())
434434
}
435435
Insn::ArraySet { array, idx, val } => { write!(f, "ArraySet {array}, {idx}, {val}") }
436-
Insn::ArrayDup { val } => { write!(f, "ArrayDup {val}") }
436+
Insn::ArrayDup { val, .. } => { write!(f, "ArrayDup {val}") }
437437
Insn::StringCopy { val } => { write!(f, "StringCopy {val}") }
438438
Insn::Test { val } => { write!(f, "Test {val}") }
439439
Insn::Jump(target) => { write!(f, "Jump {target}") }
@@ -789,7 +789,7 @@ impl Function {
789789
state: *state,
790790
},
791791
ArraySet { array, idx, val } => ArraySet { array: find!(*array), idx: *idx, val: find!(*val) },
792-
ArrayDup { val } => ArrayDup { val: find!(*val) },
792+
ArrayDup { val , state } => ArrayDup { val: find!(*val), state: *state },
793793
CCall { cfun, args, name, return_type } => CCall { cfun: *cfun, args: args.iter().map(|arg| find!(*arg)).collect(), name: *name, return_type: *return_type },
794794
Defined { .. } => todo!("find(Defined)"),
795795
}
@@ -1196,7 +1196,6 @@ impl Function {
11961196
| Insn::GetConstantPath { .. } =>
11971197
{}
11981198
Insn::StringCopy { val }
1199-
| Insn::ArrayDup { val }
12001199
| Insn::StringIntern { val }
12011200
| Insn::Return { val }
12021201
| Insn::Defined { v: val, .. }
@@ -1240,6 +1239,10 @@ impl Function {
12401239
worklist.push_back(val);
12411240
worklist.extend(args);
12421241
}
1242+
Insn::ArrayDup { val , state } => {
1243+
worklist.push_back(val);
1244+
worklist.push_back(state);
1245+
}
12431246
Insn::Send { self_val, args, state, .. }
12441247
| Insn::SendWithoutBlock { self_val, args, state, .. }
12451248
| Insn::SendWithoutBlockDirect { self_val, args, state, .. } => {
@@ -1639,7 +1642,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
16391642
}
16401643
YARVINSN_duparray => {
16411644
let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
1642-
let insn_id = fun.push_insn(block, Insn::ArrayDup { val });
1645+
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state.clone() });
1646+
let insn_id = fun.push_insn(block, Insn::ArrayDup { val, state: exit_id });
16431647
state.stack_push(insn_id);
16441648
}
16451649
YARVINSN_putobject_INT2FIX_0_ => {
@@ -2050,7 +2054,8 @@ mod infer_tests {
20502054
fn arraydup() {
20512055
let mut function = Function::new(std::ptr::null());
20522056
let arr = function.push_insn(function.entry_block, Insn::NewArray { elements: vec![] });
2053-
let val = function.push_insn(function.entry_block, Insn::ArrayDup { val: arr });
2057+
// Fake FrameState index of 0usize
2058+
let val = function.push_insn(function.entry_block, Insn::ArrayDup { val: arr, state: InsnId(0usize) });
20542059
assert_bit_equal(function.infer_type(val), types::ArrayExact);
20552060
}
20562061

@@ -2197,8 +2202,8 @@ mod tests {
21972202
fn test:
21982203
bb0():
21992204
v1:ArrayExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
2200-
v2:ArrayExact = ArrayDup v1
2201-
Return v2
2205+
v3:ArrayExact = ArrayDup v1
2206+
Return v3
22022207
"#]]);
22032208
}
22042209

@@ -2657,16 +2662,16 @@ mod tests {
26572662
bb0():
26582663
v1:BasicObject = PutSelf
26592664
v2:ArrayExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
2660-
v3:ArrayExact = ArrayDup v2
2661-
v4:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
2662-
v5:ArrayExact = ArrayDup v4
2663-
v6:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
2664-
v7:StringExact = StringCopy v6
2665+
v4:ArrayExact = ArrayDup v2
2666+
v5:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
2667+
v7:ArrayExact = ArrayDup v5
26652668
v8:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
26662669
v9:StringExact = StringCopy v8
2667-
v11:BasicObject = SendWithoutBlock v1, :unknown_method, v3, v5, v7, v9
2668-
PatchPoint CalleeModifiedLocals(v11)
2669-
Return v11
2670+
v10:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
2671+
v11:StringExact = StringCopy v10
2672+
v13:BasicObject = SendWithoutBlock v1, :unknown_method, v4, v7, v9, v11
2673+
PatchPoint CalleeModifiedLocals(v13)
2674+
Return v13
26702675
"#]]);
26712676
}
26722677
}
@@ -3018,8 +3023,8 @@ mod opt_tests {
30183023
assert_optimized_method_hir("test", expect![[r#"
30193024
fn test:
30203025
bb0():
3021-
v4:Fixnum[5] = Const Value(5)
3022-
Return v4
3026+
v5:Fixnum[5] = Const Value(5)
3027+
Return v5
30233028
"#]]);
30243029
}
30253030

0 commit comments

Comments
 (0)