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

ruby-changes:73282

From: Takashi <ko1@a...>
Date: Tue, 30 Aug 2022 01:07:33 +0900 (JST)
Subject: [ruby-changes:73282] df84832c75 (master): Port getblockparamproxy and getblockparam (https://github.com/Shopify/ruby/pull/394)

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

From df84832c758e3dcb360f18335c2c93dcc90344aa Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Wed, 10 Aug 2022 13:29:01 -0700
Subject: Port getblockparamproxy and getblockparam
 (https://github.com/Shopify/ruby/pull/394)

---
 bootstraptest/test_yjit.rb |  16 ++++++
 yjit/src/codegen.rs        | 132 +++++++++++++++++++--------------------------
 2 files changed, 70 insertions(+), 78 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 7aed5ac43c..d44fe25800 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -3220,3 +3220,19 @@ assert_equal 'foo', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L3220
   Foo = Struct.new(:bar)
   Foo.new("foo").bar
 }
+
+# getblockparamproxy
+assert_equal 'foo', %q{
+  def foo(&block)
+    block.call
+  end
+  foo { "foo" }
+}
+
+# getblockparam
+assert_equal 'foo', %q{
+  def foo(&block)
+    block
+  end
+  foo { "foo" }.call
+}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 1ac4f54952..b5b145790c 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -5556,6 +5556,7 @@ fn gen_opt_getinlinecache( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5556
     );
     EndBlock
 }
+*/
 
 // Push the explicit block parameter onto the temporary stack. Part of the
 // interpreter's scheme for avoiding Proc allocations when delegating
@@ -5563,11 +5564,11 @@ fn gen_opt_getinlinecache( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5564
 fn gen_getblockparamproxy(
     jit: &mut JITState,
     ctx: &mut Context,
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     ocb: &mut OutlinedCb,
 ) -> CodegenStatus {
     if !jit_at_current_insn(jit) {
-        defer_compilation(jit, ctx, cb, ocb);
+        defer_compilation(jit, ctx, asm, ocb);
         return EndBlock;
     }
 
@@ -5590,79 +5591,64 @@ fn gen_getblockparamproxy( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5591
     }
 
     // Load environment pointer EP from CFP
-    gen_get_ep(cb, REG0, level);
+    let ep_opnd = gen_get_ep(asm, level);
 
     // Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
-    let flag_check = mem_opnd(
+    let flag_check = Opnd::mem(
         64,
-        REG0,
+        ep_opnd,
         (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_FLAGS as i32),
     );
-    test(
-        cb,
-        flag_check,
-        uimm_opnd(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into()),
-    );
-    jnz_ptr(cb, counted_exit!(ocb, side_exit, gbpp_block_param_modified));
+    asm.test(flag_check, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into());
+    asm.jnz(counted_exit!(ocb, side_exit, gbpp_block_param_modified).into());
 
     // Load the block handler for the current frame
     // note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
-    mov(
-        cb,
-        REG0,
-        mem_opnd(
-            64,
-            REG0,
-            (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_SPECVAL as i32),
-        ),
+    let block_handler = asm.load(
+        Opnd::mem(64, ep_opnd, (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_SPECVAL as i32))
     );
 
     // Specialize compilation for the case where no block handler is present
     if comptime_handler.as_u64() == 0 {
         // Bail if there is a block handler
-        cmp(cb, REG0, uimm_opnd(0));
+        asm.cmp(block_handler, Opnd::UImm(0));
 
         jit_chain_guard(
             JCC_JNZ,
             jit,
             &starting_context,
-            cb,
+            asm,
             ocb,
             SEND_MAX_DEPTH,
             side_exit,
         );
 
-        jit_putobject(jit, ctx, cb, Qnil);
+        jit_putobject(jit, ctx, asm, Qnil);
     } else {
         // Block handler is a tagged pointer. Look at the tag. 0x03 is from VM_BH_ISEQ_BLOCK_P().
-        and(cb, REG0_8, imm_opnd(0x3));
+        let block_handler = asm.and(block_handler, 0x3.into());
 
         // Bail unless VM_BH_ISEQ_BLOCK_P(bh). This also checks for null.
-        cmp(cb, REG0_8, imm_opnd(0x1));
+        asm.cmp(block_handler, 0x1.into());
 
         jit_chain_guard(
             JCC_JNZ,
             jit,
             &starting_context,
-            cb,
+            asm,
             ocb,
             SEND_MAX_DEPTH,
             side_exit,
         );
 
         // Push rb_block_param_proxy. It's a root, so no need to use jit_mov_gc_ptr.
-        mov(
-            cb,
-            REG0,
-            const_ptr_opnd(unsafe { rb_block_param_proxy }.as_ptr()),
-        );
         assert!(!unsafe { rb_block_param_proxy }.special_const_p());
 
         let top = ctx.stack_push(Type::Unknown);
-        mov(cb, top, REG0);
+        asm.mov(top, Opnd::const_ptr(unsafe { rb_block_param_proxy }.as_ptr()));
     }
 
-    jump_to_next_insn(jit, ctx, cb, ocb);
+    jump_to_next_insn(jit, ctx, asm, ocb);
 
     EndBlock
 }
@@ -5670,95 +5656,85 @@ fn gen_getblockparamproxy( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5656
 fn gen_getblockparam(
     jit: &mut JITState,
     ctx: &mut Context,
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     ocb: &mut OutlinedCb,
 ) -> CodegenStatus {
     // EP level
     let level = jit_get_arg(jit, 1).as_u32();
 
     // Save the PC and SP because we might allocate
-    jit_prepare_routine_call(jit, ctx, cb, REG0);
+    jit_prepare_routine_call(jit, ctx, asm);
 
     // A mirror of the interpreter code. Checking for the case
     // where it's pushing rb_block_param_proxy.
     let side_exit = get_side_exit(jit, ocb, ctx);
 
     // Load environment pointer EP from CFP
-    gen_get_ep(cb, REG1, level);
+    let ep_opnd = gen_get_ep(asm, level);
 
     // Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
-    let flag_check = mem_opnd(
-        64,
-        REG1,
-        (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_FLAGS as i32),
-    );
+    let flag_check = Opnd::mem(64, ep_opnd, (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_FLAGS as i32));
     // FIXME: This is testing bits in the same place that the WB check is testing.
     // We should combine these at some point
-    test(
-        cb,
-        flag_check,
-        uimm_opnd(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into()),
-    );
+    asm.test(flag_check, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into());
 
     // If the frame flag has been modified, then the actual proc value is
     // already in the EP and we should just use the value.
-    let frame_flag_modified = cb.new_label("frame_flag_modified".to_string());
-    jnz_label(cb, frame_flag_modified);
+    let frame_flag_modified = asm.new_label("frame_flag_modified");
+    asm.jnz(frame_flag_modified);
 
     // This instruction writes the block handler to the EP.  If we need to
     // fire a write barrier for the write, then exit (we'll let the
     // interpreter handle it so it can fire the write barrier).
     // flags & VM_ENV_FLAG_WB_REQUIRED
-    let flags_opnd = mem_opnd(
+    let flags_opnd = Opnd::mem(
         64,
-        REG1,
+        ep_opnd,
         SIZEOF_VALUE as i32 * VM_ENV_DATA_INDEX_FLAGS as i32,
     );
-    test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED.into()));
+    asm.test(flags_opnd, VM_ENV_FLAG_WB_REQUIRED.into());
 
     // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
-    jnz_ptr(cb, side_exit);
-
-    // Load the block handler for the current frame
-    // note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
-    mov(
-        cb,
-        C_ARG_REGS[1],
-        mem_opnd(
-            64,
-            REG1,
-            (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_SPECVAL as i32),
-        ),
-    );
+    asm.jnz(side_exit.into());
 
     // Convert the block handler in to a proc
     // call rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler)
-    mov(cb, C_ARG_REGS[0], REG_EC);
-    call_ptr(cb, REG0, rb_vm_bh_to_procval as *const u8);
+    let proc = asm.ccall(
+        rb_vm_bh_to_procval as *const u8,
+        vec![
+            EC,
+            // The block handler for the current frame
+            // note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
+            Opnd::mem(
+                64,
+                ep_opnd,
+                (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_SPECVAL as i32),
+            ),
+        ]
+    );
 
     // Load environment pointer EP from CFP (again)
-    gen_get_ep(cb, REG1, level);
-
-    // Set the frame modified flag
-    or(cb, flag_check, uimm_opnd(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into()));
+    let ep_opnd = gen_get_ep(asm, level);
 
     // Write the value at the environment pointer
     let idx = jit_get_arg(jit, 0).as_i32();
     let offs = -(SIZEOF_VALUE as i32 * idx);
-    mov(cb, mem_opnd(64, REG1, offs), RAX);
+    asm.mov(Opnd::mem(64, ep_opnd, offs), proc);
+
+    // Set the frame modified flag
+    let flag_check = Opnd::mem(64, ep_opnd, (SIZEOF_VALUE as i32) * (VM_ENV_DATA_INDEX_FLAGS as i32));
+    let modified_flag = asm.or(flag_check, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into());
+    asm.store(flag_check, modified_flag);
 
-    cb.write_label(frame_flag_modified);
+    asm.write_label(frame_flag_modified);
 
     // Push the proc on the stack
     let stack_ret = ctx.stack_push(Type::Unknown);
-    mov(cb, RAX, mem_opnd(64, REG1, offs));
-    mov(cb, stack_ret, RAX);
-
-    cb.link_labels();
+    let ep_opnd = gen_get_ep(asm, level);
+    asm.mov(stack_ret, Opnd::mem(64, ep_opnd, offs));
 
     KeepCompiling
 }
-*/
 
 fn gen_invokebuiltin(
     jit: &mut JITState,
@@ -5919,8 +5895,8 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5895
         YARVINSN_branchnil => Some(gen_branchnil),
         YARVINSN_jump => Some(gen_jump),
 
-        //YARVINSN_getblockparamproxy => Some(gen_getblockparamproxy),
-        //YARVINSN_getblockparam => Some(gen_getblockparam),
+        YARVINSN_getblockparamproxy => Some(gen_getblockparamproxy),
+        YARVINSN_getblockparam => Some(gen_getblockparam),
          (... truncated)

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

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