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

ruby-changes:73135

From: Maxime <ko1@a...>
Date: Tue, 30 Aug 2022 00:55:20 +0900 (JST)
Subject: [ruby-changes:73135] e72dab304e (master): Add atomic counter increment instruction

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

From e72dab304e423ad8c98656c146d52f6a8fa4a2c2 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Tue, 14 Jun 2022 15:45:41 -0400
Subject: Add atomic counter increment instruction

---
 yjit/src/backend/ir.rs         |  4 ++++
 yjit/src/backend/x86_64/mod.rs |  7 +++++++
 yjit/src/codegen.rs            | 29 +++++++----------------------
 3 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index a077eb1945..10e04c8e2b 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -98,6 +98,9 @@ pub enum Op https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L98
     // C function return
     CRet,
 
+    // Atomically increment a counter
+    IncrCounter,
+
     // Trigger a debugger breakpoint
     Breakpoint,
 }
@@ -688,6 +691,7 @@ def_push_2_opnd_no_out!(mov, Op::Mov); https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L691
 def_push_2_opnd_no_out!(cmp, Op::Cmp);
 def_push_2_opnd_no_out!(test, Op::Test);
 def_push_0_opnd_no_out!(breakpoint, Op::Breakpoint);
+def_push_2_opnd_no_out!(incr_counter, Op::IncrCounter);
 
 // NOTE: these methods are temporary and will likely move
 // to context.rs later
diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index 748bf5aea0..17571dd45b 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -183,6 +183,13 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L183
 
                 Op::Je => je_label(cb, insn.target.unwrap().unwrap_label_idx()),
 
+                // Atomically increment a counter at a given memory location
+                Op::IncrCounter => {
+                    assert!(matches!(insn.opnds[0], Opnd::Mem(_)));
+                    write_lock_prefix(cb);
+                    add(cb, insn.opnds[0].into(), insn.opnds[1].into());
+                },
+
                 Op::Breakpoint => int3(cb),
 
                 _ => panic!("unsupported instruction passed to x86 backend: {:?}", insn.op)
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 3589aaf579..580595d499 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -223,12 +223,8 @@ macro_rules! gen_counter_incr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L223
             let ptr_reg = $asm.load(Opnd::const_ptr(ptr as *const u8));
             let counter_opnd = Opnd::mem(64, ptr_reg, 0);
 
-            // FIXME: do we want an atomic add, or an atomic store or swap for arm?
-            //write_lock_prefix($cb); // for ractors.
-
             // Increment and store the updated value
-            let incr_opnd = $asm.add(counter_opnd, 1.into());
-            $asm.store(counter_opnd, incr_opnd);
+            $asm.incr_counter(counter_opnd, 1.into() );
         }
     };
 }
@@ -408,7 +404,7 @@ fn gen_code_for_exit_from_stub(ocb: &mut OutlinedCb) -> CodePtr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L404
     todo!();
 
     /*
-    gen_counter_incr!(ocb, exit_from_branch_stub);
+    gen_counter_incr!(asm, exit_from_branch_stub);
 
     cpop(ocb, REG_SP);
     cpop(ocb, REG_EC);
@@ -541,7 +537,7 @@ fn gen_full_cfunc_return(ocb: &mut OutlinedCb) -> CodePtr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L537
     call_ptr(cb, REG0, rb_full_cfunc_return as *const u8);
 
     // Count the exit
-    gen_counter_incr!(cb, traced_cfunc_return);
+    gen_counter_incr!(asm, traced_cfunc_return);
 
     // Return to the interpreter
     pop(cb, REG_SP);
@@ -562,26 +558,16 @@ fn gen_leave_exit(ocb: &mut OutlinedCb) -> CodePtr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L558
     let code_ptr = ocb.get_write_ptr();
     let mut asm = Assembler::new();
 
-    // Note, gen_leave() fully reconstructs interpreter state and leaves the
-    // return value in RAX before coming here.
+    // NOTE: gen_leave() fully reconstructs interpreter state and leaves the
+    // return value in C_RET_OPND before coming here.
 
-    // FIXME
     // Every exit to the interpreter should be counted
-    //gen_counter_incr!(ocb, leave_interp_return);
+    gen_counter_incr!(asm, leave_interp_return);
 
     asm.cpop(SP);
     asm.cpop(EC);
     asm.cpop(CFP);
 
-    // FIXME: we're currently assuming that the return value is in RAX,
-    // left there by gen_leave() ...
-    //
-    // What are our options?
-    // We could put the return value in C_RET_REG?
-    // Then call asm.ret with C_RET_REG?
-
-
-
     asm.cret(C_RET_OPND);
 
     asm.compile(ocb);
@@ -604,9 +590,8 @@ fn gen_pc_guard(asm: &mut Assembler, iseq: IseqPtr, insn_idx: u32) { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L590
     let pc_match = asm.new_label("pc_match");
     asm.je(pc_match);
 
-    // FIXME
     // We're not starting at the first PC, so we need to exit.
-    //gen_counter_incr!(cb, leave_start_pc_non_zero);
+    gen_counter_incr!(asm, leave_start_pc_non_zero);
 
     asm.cpop(SP);
     asm.cpop(EC);
-- 
cgit v1.2.1


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

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