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

ruby-changes:73127

From: Maxime <ko1@a...>
Date: Tue, 30 Aug 2022 00:53:43 +0900 (JST)
Subject: [ruby-changes:73127] ea9abe547d (master): Add cpush and cpop IR instructions

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

From ea9abe547da383f30bd0afe73c6693ed1ff68765 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Wed, 8 Jun 2022 16:09:16 -0400
Subject: Add cpush and cpop IR instructions

---
 yjit/src/backend/ir.rs         |  6 ++++
 yjit/src/backend/x86_64/mod.rs | 20 +++++++-----
 yjit/src/codegen.rs            | 74 ++++++++++++++++++++----------------------
 3 files changed, 54 insertions(+), 46 deletions(-)

diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index e5bcd78932..514ac4a67e 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -82,6 +82,10 @@ pub enum Op https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L82
     Je,
     Jnz,
 
+    // Push and pop registers to/from the C stack
+    CPush,
+    CPop,
+
     // C function call with N arguments (variadic)
     CCall,
 
@@ -710,6 +714,8 @@ def_push_jcc!(jnz, Op::Jnz); https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L714
 def_push_2_opnd!(add, Op::Add);
 def_push_2_opnd!(sub, Op::Sub);
 def_push_2_opnd!(and, Op::And);
+def_push_1_opnd_no_out!(cpush, Op::CPush);
+def_push_1_opnd_no_out!(cpop, Op::CPop);
 def_push_1_opnd_no_out!(cret, Op::CRet);
 def_push_1_opnd!(load, Op::Load);
 def_push_1_opnd!(lea, Op::Lea);
diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index 2d425c2fe0..a40bc2a980 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -136,14 +136,9 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L136
                 // Load effective address
                 Op::Lea => lea(cb, insn.out.into(), insn.opnds[0].into()),
 
-                // Test and set flags
-                Op::Test => test(cb, insn.opnds[0].into(), insn.opnds[1].into()),
-
-                /*
-                Cmp,
-                Jnz,
-                Jbe,
-                */
+                // Push and pop to the C stack
+                Op::CPush => push(cb, insn.opnds[0].into()),
+                Op::CPop => pop(cb, insn.opnds[0].into()),
 
                 // C function call
                 Op::CCall => {
@@ -165,6 +160,15 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L160
                     ret(cb);
                 }
 
+                // Test and set flags
+                Op::Test => test(cb, insn.opnds[0].into(), insn.opnds[1].into()),
+
+                /*
+                Cmp,
+                Jnz,
+                Jbe,
+                */
+
                 _ => panic!("unsupported instruction passed to x86 backend: {:?}", insn.op)
             };
         }
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 59c6773fcc..be051c39a6 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -499,38 +499,6 @@ pub fn jit_ensure_block_entry_exit(jit: &mut JITState, ocb: &mut OutlinedCb) { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L499
     }
 }
 
-// Generate a runtime guard that ensures the PC is at the expected
-// instruction index in the iseq, otherwise takes a side-exit.
-// This is to handle the situation of optional parameters.
-// When a function with optional parameters is called, the entry
-// PC for the method isn't necessarily 0.
-fn gen_pc_guard(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) {
-    let pc_opnd = mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_PC);
-    let expected_pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx) };
-    let expected_pc_opnd = const_ptr_opnd(expected_pc as *const u8);
-
-    mov(cb, REG0, pc_opnd);
-    mov(cb, REG1, expected_pc_opnd);
-    cmp(cb, REG0, REG1);
-
-    let pc_match = cb.new_label("pc_match".to_string());
-    je_label(cb, pc_match);
-
-    // We're not starting at the first PC, so we need to exit.
-    gen_counter_incr!(cb, leave_start_pc_non_zero);
-
-    pop(cb, REG_SP);
-    pop(cb, REG_EC);
-    pop(cb, REG_CFP);
-
-    mov(cb, RAX, imm_opnd(Qundef.into()));
-    ret(cb);
-
-    // PC should match the expected insn_idx
-    cb.write_label(pc_match);
-    cb.link_labels();
-}
-
 // Landing code for when c_return tracing is enabled. See full_cfunc_return().
 fn gen_full_cfunc_return(ocb: &mut OutlinedCb) -> CodePtr {
     let cb = ocb.unwrap();
@@ -579,6 +547,38 @@ fn gen_leave_exit(ocb: &mut OutlinedCb) -> CodePtr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L547
     return code_ptr;
 }
 
+// Generate a runtime guard that ensures the PC is at the expected
+// instruction index in the iseq, otherwise takes a side-exit.
+// This is to handle the situation of optional parameters.
+// When a function with optional parameters is called, the entry
+// PC for the method isn't necessarily 0.
+fn gen_pc_guard(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) {
+    let pc_opnd = mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_PC);
+    let expected_pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx) };
+    let expected_pc_opnd = const_ptr_opnd(expected_pc as *const u8);
+
+    mov(cb, REG0, pc_opnd);
+    mov(cb, REG1, expected_pc_opnd);
+    cmp(cb, REG0, REG1);
+
+    let pc_match = cb.new_label("pc_match".to_string());
+    je_label(cb, pc_match);
+
+    // We're not starting at the first PC, so we need to exit.
+    gen_counter_incr!(cb, leave_start_pc_non_zero);
+
+    pop(cb, REG_SP);
+    pop(cb, REG_EC);
+    pop(cb, REG_CFP);
+
+    mov(cb, RAX, imm_opnd(Qundef.into()));
+    ret(cb);
+
+    // PC should match the expected insn_idx
+    cb.write_label(pc_match);
+    cb.link_labels();
+}
+
 /// Compile an interpreter entry block to be inserted into an iseq
 /// Returns None if compilation fails.
 pub fn gen_entry_prologue(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) -> Option<CodePtr> {
@@ -600,12 +600,10 @@ pub fn gen_entry_prologue(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) -> O https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L600
 
     let mut asm = Assembler::new();
 
-    // TODO: on arm, we need to push the return address here?
-
-    // FIXME
-    //push(cb, REG_CFP);
-    //push(cb, REG_EC);
-    //push(cb, REG_SP);
+    // Save the CFP, EC, SP registers to the C stack
+    asm.cpush(CFP);
+    asm.cpush(EC);
+    asm.cpush(SP);
 
     // We are passed EC and CFP as arguments
     asm.mov(EC, C_ARG_REGS[0].into());
-- 
cgit v1.2.1


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

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