diff options
author | Takashi Kokubun <[email protected]> | 2024-01-25 13:45:58 -0800 |
---|---|---|
committer | GitHub <[email protected]> | 2024-01-25 21:45:58 +0000 |
commit | 2034e6ad5a22fa1dcde428751ae97a29ba434d7e (patch) | |
tree | 52183e2cd056c405423714863aa56060a703357b | |
parent | f0224adf2f6ec5c1a9c77001bfbfdae9eb93f5fc (diff) |
YJIT: Support concattoarray and pushtoarray (#9708)
-rw-r--r-- | bootstraptest/test_yjit.rb | 14 | ||||
-rw-r--r-- | vm_insnhelper.c | 6 | ||||
-rw-r--r-- | yjit/bindgen/src/main.rs | 1 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 50 | ||||
-rw-r--r-- | yjit/src/cruby.rs | 1 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 1 |
6 files changed, 73 insertions, 0 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 6832a0d76c..a981ba150b 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4459,3 +4459,17 @@ assert_equal '[[{:a=>1}], {}]', %q{ body } + +# concatarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [2] + foo(*[1], *arr) +} + +# pushtoarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [1] + foo(*arr, 2) +} diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 55e79acdd8..edce1fbe41 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5237,6 +5237,12 @@ rb_vm_concat_array(VALUE ary1, VALUE ary2st) return vm_concat_array(ary1, ary2st); } +VALUE +rb_vm_concat_to_array(VALUE ary1, VALUE ary2st) +{ + return vm_concat_to_array(ary1, ary2st); +} + static VALUE vm_splat_array(VALUE flag, VALUE ary) { diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 45874f28a1..df9bb4d727 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -133,6 +133,7 @@ fn main() { .allowlist_function("rb_ary_new_capa") .allowlist_function("rb_ary_store") .allowlist_function("rb_ary_resurrect") + .allowlist_function("rb_ary_cat") .allowlist_function("rb_ary_clear") .allowlist_function("rb_ary_dup") .allowlist_function("rb_ary_push") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 06adbe8553..2bec0cf6d4 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1459,6 +1459,54 @@ fn gen_concatarray( Some(KeepCompiling) } +// concat second array to first array. +// first argument must already be an array. +// attempts to convert second object to array using to_a. +fn gen_concattoarray( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option<CodegenStatus> { + // Save the PC and SP because the callee may allocate + jit_prepare_routine_call(jit, asm); + + // Get the operands from the stack + let ary2_opnd = asm.stack_opnd(0); + let ary1_opnd = asm.stack_opnd(1); + + let ary = asm.ccall(rb_vm_concat_to_array as *const u8, vec![ary1_opnd, ary2_opnd]); + asm.stack_pop(2); // Keep them on stack during ccall for GC + + let stack_ret = asm.stack_push(Type::TArray); + asm.mov(stack_ret, ary); + + Some(KeepCompiling) +} + +// push given number of objects to array directly before. +fn gen_pushtoarray( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option<CodegenStatus> { + let num = jit.get_arg(0).as_u64(); + + // Save the PC and SP because the callee may allocate + jit_prepare_routine_call(jit, asm); + + // Get the operands from the stack + let ary_opnd = asm.stack_opnd(num as i32); + let objp_opnd = asm.lea(asm.ctx.sp_opnd(-(num as isize) * SIZEOF_VALUE as isize)); + + let ary = asm.ccall(rb_ary_cat as *const u8, vec![ary_opnd, objp_opnd, num.into()]); + asm.stack_pop(num as usize + 1); // Keep it on stack during ccall for GC + + let stack_ret = asm.stack_push(Type::TArray); + asm.mov(stack_ret, ary); + + Some(KeepCompiling) +} + // new range initialized from top 2 values fn gen_newrange( jit: &mut JITState, @@ -8904,6 +8952,8 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { YARVINSN_opt_newarray_send => Some(gen_opt_newarray_send), YARVINSN_splatarray => Some(gen_splatarray), YARVINSN_concatarray => Some(gen_concatarray), + YARVINSN_concattoarray => Some(gen_concattoarray), + YARVINSN_pushtoarray => Some(gen_pushtoarray), 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 9f289e93dd..dda9f6ecd0 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -114,6 +114,7 @@ pub use autogened::*; 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_concat_to_array(ary1: VALUE, ary2st: VALUE) -> VALUE; pub fn rb_vm_defined( ec: EcPtr, reg_cfp: CfpPtr, diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 01f0cca280..2f965059d8 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -936,6 +936,7 @@ extern "C" { pub fn rb_ary_store(ary: VALUE, key: ::std::os::raw::c_long, val: VALUE); pub fn rb_ary_dup(ary: VALUE) -> VALUE; pub fn rb_ary_resurrect(ary: VALUE) -> VALUE; + pub fn rb_ary_cat(ary: VALUE, train: *const VALUE, len: ::std::os::raw::c_long) -> VALUE; pub fn rb_ary_push(ary: VALUE, elem: VALUE) -> VALUE; pub fn rb_ary_clear(ary: VALUE) -> VALUE; pub fn rb_hash_new() -> VALUE; |