[前][次][番号順一覧][スレッド一覧]

ruby-changes:73247

From: Takashi <ko1@a...>
Date: Tue, 30 Aug 2022 01:04:59 +0900 (JST)
Subject: [ruby-changes:73247] 4539c21367 (master): Port gen_send_cfunc to the new backend (https://github.com/Shopify/ruby/pull/357)

https://git.ruby-lang.org/ruby.git/commit/?id=4539c21367

From 4539c21367cf63e34afe4f14656779d33883647b Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Thu, 4 Aug 2022 11:47:53 -0700
Subject: Port gen_send_cfunc to the new backend
 (https://github.com/Shopify/ruby/pull/357)

* Port gen_send_cfunc to the new backend

* Remove an obsoleted test

* Add more cfunc tests

* Use csel_e instead and more into()

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@g...>

* Add a missing lea for build_kwargs

* Split cfunc test cases

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@g...>
---
 bootstraptest/test_yjit.rb |  32 +++++++++
 yjit/src/codegen.rs        | 162 ++++++++++++++++++++-------------------------
 2 files changed, 103 insertions(+), 91 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 2409306106..16eda7fa84 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -3111,3 +3111,35 @@ assert_equal '9001', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L3111
     end
     foo()
 }
+
+# opt_send_without_block (VM_METHOD_TYPE_CFUNC)
+assert_equal 'nil', %q{
+    def foo
+      nil.inspect # argc: 0
+    end
+    foo
+}
+assert_equal '4', %q{
+    def foo
+      2.pow(2) # argc: 1
+    end
+    foo
+}
+assert_equal 'aba', %q{
+    def foo
+      "abc".tr("c", "a") # argc: 2
+    end
+    foo
+}
+assert_equal 'true', %q{
+    def foo
+      respond_to?(:inspect) # argc: -1
+    end
+    foo
+}
+assert_equal '["a", "b"]', %q{
+    def foo
+      "a\nb".lines(chomp: true) # kwargs
+    end
+    foo
+}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index f08b073e34..c89cfc366f 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -1881,10 +1881,10 @@ pub const GET_IVAR_MAX_DEPTH: i32 = 10; https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1881
 /*
 // hashes and arrays
 pub const OPT_AREF_MAX_CHAIN_DEPTH: i32 = 2;
+*/
 
 // up to 5 different classes
 pub const SEND_MAX_DEPTH: i32 = 5;
-*/
 
 // Codegen for setting an instance variable.
 // Preconditions:
@@ -2221,7 +2221,7 @@ fn gen_checktype( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L2221
     // Only three types are emitted by compile.c at the moment
     if let RUBY_T_STRING | RUBY_T_ARRAY | RUBY_T_HASH = type_val {
         let val_type = ctx.get_opnd_type(StackOpnd(0));
-        let val = ctx.stack_pop(1);
+        let val = asm.load(ctx.stack_pop(1));
 
         // Check if we know from type information
         match val_type.known_value_type() {
@@ -2253,7 +2253,7 @@ fn gen_checktype( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L2253
             Opnd::mem(64, val, RUBY_OFFSET_RBASIC_FLAGS),
             Opnd::UImm(RUBY_T_MASK.into()));
         asm.cmp(object_type, Opnd::UImm(type_val.into()));
-        let ret_opnd = asm.csel_e(Opnd::UImm(Qfalse.into()), Opnd::UImm(Qtrue.into()));
+        let ret_opnd = asm.csel_e(Qtrue.into(), Qfalse.into());
 
         asm.write_label(ret);
         let stack_ret = ctx.stack_push(Type::UnknownImm);
@@ -3851,6 +3851,7 @@ fn jit_thread_s_current( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3851
     mov(cb, stack_ret, REG0);
     true
 }
+*/
 
 // Check if we know how to codegen for a particular cfunc method
 fn lookup_cfunc_codegen(def: *const rb_method_definition_t) -> Option<MethodGenFn> {
@@ -3858,7 +3859,6 @@ fn lookup_cfunc_codegen(def: *const rb_method_definition_t) -> Option<MethodGenF https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3859
 
     CodegenGlobals::look_up_codegen_method(method_serial)
 }
-*/
 
 // Is anyone listening for :c_call and :c_return event currently?
 fn c_method_tracing_currently_enabled(jit: &JITState) -> bool {
@@ -3868,7 +3868,6 @@ fn c_method_tracing_currently_enabled(jit: &JITState) -> bool { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3868
     }
 }
 
-/*
 // Similar to args_kw_argv_to_hash. It is called at runtime from within the
 // generated assembly to build a Ruby hash of the passed keyword arguments. The
 // keys are the Symbol objects associated with the keywords and the values are
@@ -3889,7 +3888,7 @@ unsafe extern "C" fn build_kwhash(ci: *const rb_callinfo, sp: *const VALUE) -> V https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3888
 fn gen_send_cfunc(
     jit: &mut JITState,
     ctx: &mut Context,
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     ocb: &mut OutlinedCb,
     ci: *const rb_callinfo,
     cme: *const rb_callable_method_entry_t,
@@ -3902,7 +3901,7 @@ fn gen_send_cfunc( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3901
 
     // If the function expects a Ruby array of arguments
     if cfunc_argc < 0 && cfunc_argc != -1 {
-        gen_counter_incr!(cb, send_cfunc_ruby_array_varg);
+        gen_counter_incr!(asm, send_cfunc_ruby_array_varg);
         return CantCompile;
     }
 
@@ -3923,19 +3922,19 @@ fn gen_send_cfunc( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3922
 
     // If the argument count doesn't match
     if cfunc_argc >= 0 && cfunc_argc != passed_argc {
-        gen_counter_incr!(cb, send_cfunc_argc_mismatch);
+        gen_counter_incr!(asm, send_cfunc_argc_mismatch);
         return CantCompile;
     }
 
     // Don't JIT functions that need C stack arguments for now
-    if cfunc_argc >= 0 && passed_argc + 1 > (C_ARG_REGS.len() as i32) {
-        gen_counter_incr!(cb, send_cfunc_toomany_args);
+    if cfunc_argc >= 0 && passed_argc + 1 > (C_ARG_OPNDS.len() as i32) {
+        gen_counter_incr!(asm, send_cfunc_toomany_args);
         return CantCompile;
     }
 
     if c_method_tracing_currently_enabled(jit) {
         // Don't JIT if tracing c_call or c_return
-        gen_counter_incr!(cb, send_cfunc_tracing);
+        gen_counter_incr!(asm, send_cfunc_tracing);
         return CantCompile;
     }
 
@@ -3943,6 +3942,7 @@ fn gen_send_cfunc( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3942
     if kw_arg.is_null() {
         let codegen_p = lookup_cfunc_codegen(unsafe { (*cme).def });
         if let Some(known_cfunc_codegen) = codegen_p {
+            return CantCompile; /*
             let start_pos = cb.get_write_ptr().raw_ptr() as usize;
             if known_cfunc_codegen(jit, ctx, cb, ocb, ci, cme, block, argc, recv_known_klass) {
                 let written_bytes = cb.get_write_ptr().raw_ptr() as usize - start_pos;
@@ -3955,6 +3955,7 @@ fn gen_send_cfunc( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3955
                 jump_to_next_insn(jit, ctx, cb, ocb);
                 return EndBlock;
             }
+            */
         }
     }
 
@@ -3962,57 +3963,49 @@ fn gen_send_cfunc( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L3963
     let side_exit = get_side_exit(jit, ocb, ctx);
 
     // Check for interrupts
-    gen_check_ints(cb, side_exit);
+    gen_check_ints(asm, side_exit);
 
     // Stack overflow check
     // #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
     // REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
-    add_comment(cb, "stack overflow check");
-    lea(
-        cb,
-        REG0,
-        ctx.sp_opnd((SIZEOF_VALUE * 4 + 2 * RUBY_SIZEOF_CONTROL_FRAME) as isize),
-    );
-    cmp(cb, REG_CFP, REG0);
-    jle_ptr(cb, counted_exit!(ocb, side_exit, send_se_cf_overflow));
+    asm.comment("stack overflow check");
+    let stack_limit = asm.lea(ctx.sp_opnd((SIZEOF_VALUE * 4 + 2 * RUBY_SIZEOF_CONTROL_FRAME) as isize));
+    asm.cmp(CFP, stack_limit);
+    asm.jbe(counted_exit!(ocb, side_exit, send_se_cf_overflow).into());
 
     // Points to the receiver operand on the stack
     let recv = ctx.stack_opnd(argc);
 
     // Store incremented PC into current control frame in case callee raises.
-    jit_save_pc(jit, cb, REG0);
+    jit_save_pc(jit, asm);
 
     if let Some(block_iseq) = block {
         // Change cfp->block_code in the current frame. See vm_caller_setup_arg_block().
         // VM_CFP_TO_CAPTURED_BLOCK does &cfp->self, rb_captured_block->code.iseq aliases
         // with cfp->block_code.
-        jit_mov_gc_ptr(jit, cb, REG0, VALUE(block_iseq as usize));
-        let block_code_opnd = mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_BLOCK_CODE);
-        mov(cb, block_code_opnd, REG0);
+        asm.mov(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_BLOCK_CODE), Opnd::UImm(block_iseq as u64));
     }
 
     // Increment the stack pointer by 3 (in the callee)
     // sp += 3
-    lea(cb, REG0, ctx.sp_opnd((SIZEOF_VALUE as isize) * 3));
+    let sp = asm.lea(ctx.sp_opnd((SIZEOF_VALUE as isize) * 3));
 
     // Write method entry at sp[-3]
     // sp[-3] = me;
     // Put compile time cme into REG1. It's assumed to be valid because we are notified when
     // any cme we depend on become outdated. See yjit_method_lookup_change().
-    jit_mov_gc_ptr(jit, cb, REG1, VALUE(cme as usize));
-    mov(cb, mem_opnd(64, REG0, 8 * -3), REG1);
+    asm.mov(Opnd::mem(64, sp, 8 * -3), Opnd::UImm(cme as u64));
 
     // Write block handler at sp[-2]
     // sp[-2] = block_handler;
     if let Some(_block_iseq) = block {
         // reg1 = VM_BH_FROM_ISEQ_BLOCK(VM_CFP_TO_CAPTURED_BLOCK(reg_cfp));
-        let cfp_self = mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_SELF);
-        lea(cb, REG1, cfp_self);
-        or(cb, REG1, imm_opnd(1));
-        mov(cb, mem_opnd(64, REG0, 8 * -2), REG1);
+        let cfp_self = asm.lea(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF));
+        let block_handler = asm.or(cfp_self, Opnd::Imm(1));
+        asm.mov(Opnd::mem(64, sp, 8 * -2), block_handler);
     } else {
-        let dst_opnd = mem_opnd(64, REG0, 8 * -2);
-        mov(cb, dst_opnd, uimm_opnd(VM_BLOCK_HANDLER_NONE.into()));
+        let dst_opnd = Opnd::mem(64, sp, 8 * -2);
+        asm.mov(dst_opnd, Opnd::UImm(VM_BLOCK_HANDLER_NONE.into()));
     }
 
     // Write env flags at sp[-1]
@@ -4021,11 +4014,12 @@ fn gen_send_cfunc( https://github.com/ruby/r (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]