diff options
author | Nobuyoshi Nakada <[email protected]> | 2024-05-23 11:23:26 -0700 |
---|---|---|
committer | Aaron Patterson <[email protected]> | 2024-05-23 12:11:50 -0700 |
commit | 49fcd33e136ee2fe8720183b63a41bb6ef8d615c (patch) | |
tree | e089550455a8116beb379eb1e8b6f4e87652879b /yjit/src | |
parent | e5e079e70f8b07697f7cc3f64736f993755500cb (diff) |
Introduce a specialize instruction for Array#pack
Instructions for this code:
```ruby
# frozen_string_literal: true
[a].pack("C")
```
Before this commit:
```
== disasm: #<ISeq:<main>@test.rb:1 (1,0)-(3,13)>
0000 putself ( 3)[Li]
0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0003 newarray 1
0005 putobject "C"
0007 opt_send_without_block <calldata!mid:pack, argc:1, ARGS_SIMPLE>
0009 leave
```
After this commit:
```
== disasm: #<ISeq:<main>@test.rb:1 (1,0)-(3,13)>
0000 putself ( 3)[Li]
0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0003 putobject "C"
0005 opt_newarray_send 2, :pack
0008 leave
```
Co-authored-by: Maxime Chevalier-Boisvert <[email protected]>
Co-authored-by: Aaron Patterson <[email protected]>
Diffstat (limited to 'yjit/src')
-rw-r--r-- | yjit/src/codegen.rs | 39 | ||||
-rw-r--r-- | yjit/src/cruby.rs | 1 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 3 |
3 files changed, 42 insertions, 1 deletions
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 072d96f1b0..747fa1769d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4235,11 +4235,50 @@ fn gen_opt_newarray_send( gen_opt_newarray_max(jit, asm, _ocb) } else if method == ID!(hash) { gen_opt_newarray_hash(jit, asm, _ocb) + } else if method == ID!(pack) { + gen_opt_newarray_pack(jit, asm, _ocb) } else { None } } +fn gen_opt_newarray_pack( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option<CodegenStatus> { + // num == 4 ( for this code ) + let num = jit.get_arg(0).as_u32(); + + // Save the PC and SP because we may call #pack + jit_prepare_non_leaf_call(jit, asm); + + extern "C" { + fn rb_vm_opt_newarray_pack(ec: EcPtr, num: u32, elts: *const VALUE, fmt: VALUE) -> VALUE; + } + + let values_opnd = asm.ctx.sp_opnd(-(num as i32)); + let values_ptr = asm.lea(values_opnd); + + let fmt_string = asm.ctx.sp_opnd(-1); + + let val_opnd = asm.ccall( + rb_vm_opt_newarray_pack as *const u8, + vec![ + EC, + (num - 1).into(), + values_ptr, + fmt_string + ], + ); + + asm.stack_pop(num.as_usize()); + let stack_ret = asm.stack_push(Type::CString); + asm.mov(stack_ret, val_opnd); + + Some(KeepCompiling) +} + fn gen_opt_newarray_hash( jit: &mut JITState, asm: &mut Assembler, diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index 68c0304b06..53586cb4f4 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -802,6 +802,7 @@ pub(crate) mod ids { name: min content: b"min" name: max content: b"max" name: hash content: b"hash" + name: pack content: b"pack" name: respond_to_missing content: b"respond_to_missing?" name: to_ary content: b"to_ary" name: eq content: b"==" diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index a03c2d0f00..d53e630a4a 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -342,7 +342,8 @@ pub const BOP_AND: ruby_basic_operators = 28; pub const BOP_OR: ruby_basic_operators = 29; pub const BOP_CMP: ruby_basic_operators = 30; pub const BOP_DEFAULT: ruby_basic_operators = 31; -pub const BOP_LAST_: ruby_basic_operators = 32; +pub const BOP_PACK: ruby_basic_operators = 32; +pub const BOP_LAST_: ruby_basic_operators = 33; pub type ruby_basic_operators = u32; pub type rb_serial_t = ::std::os::raw::c_ulonglong; pub const imemo_env: imemo_type = 0; |