diff options
-rw-r--r-- | bootstraptest/test_yjit.rb | 10 | ||||
-rw-r--r-- | vm_insnhelper.c | 10 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 25 | ||||
-rw-r--r-- | yjit/src/cruby.rs | 1 |
4 files changed, 46 insertions, 0 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 89d7c9a038..364ed7094b 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -3245,3 +3245,13 @@ assert_equal 'foo', %q{ end foo { "foo" }.call } + +assert_equal '[1, 2]', %q{ + def foo + x = [2] + [1, *x] + end + + foo + foo +} diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 3c41adcdc9..ab1394c7ca 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -4380,6 +4380,14 @@ vm_concat_array(VALUE ary1, VALUE ary2st) return rb_ary_concat(tmp1, tmp2); } +// YJIT implementation is using the C function +// and needs to call a non-static function +VALUE +rb_vm_concat_array(VALUE ary1, VALUE ary2st) +{ + return vm_concat_array(ary1, ary2st); +} + static VALUE vm_splat_array(VALUE flag, VALUE ary) { @@ -4395,6 +4403,8 @@ vm_splat_array(VALUE flag, VALUE ary) } } +// YJIT implementation is using the C function +// and needs to call a non-static function VALUE rb_vm_splat_array(VALUE flag, VALUE ary) { diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 3428466297..a6473842f8 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1256,6 +1256,30 @@ fn gen_splatarray( KeepCompiling } +// concat two arrays +fn gen_concatarray( + jit: &mut JITState, + ctx: &mut Context, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> CodegenStatus { + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, ctx, asm); + + // Get the operands from the stack + let ary2st_opnd = ctx.stack_pop(1); + let ary1_opnd = ctx.stack_pop(1); + + // Call rb_vm_concat_array(ary1, ary2st) + let ary = asm.ccall(rb_vm_concat_array as *const u8, vec![ary1_opnd, ary2st_opnd]); + + let stack_ret = ctx.stack_push(Type::Array); + asm.mov(stack_ret, ary); + + KeepCompiling +} + // new range initialized from top 2 values fn gen_newrange( jit: &mut JITState, @@ -5862,6 +5886,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { YARVINSN_opt_str_freeze => Some(gen_opt_str_freeze), YARVINSN_opt_str_uminus => Some(gen_opt_str_uminus), YARVINSN_splatarray => Some(gen_splatarray), + YARVINSN_concatarray => Some(gen_concatarray), YARVINSN_newrange => Some(gen_newrange), YARVINSN_putstring => Some(gen_putstring), YARVINSN_expandarray => Some(gen_expandarray), diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index 2cf5134e81..2f823e1b61 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -112,6 +112,7 @@ pub use autogened::*; #[cfg_attr(test, allow(unused))] // We don't link against C code when testing extern "C" { pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE; + pub fn rb_vm_concat_array(ary1: VALUE, ary2st: VALUE) -> VALUE; pub fn rb_vm_defined( ec: EcPtr, reg_cfp: CfpPtr, |