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

ruby-changes:73174

From: Maxime <ko1@a...>
Date: Tue, 30 Aug 2022 00:58:00 +0900 (JST)
Subject: [ruby-changes:73174] 65019ed60c (master): Get codegen for deferred compilation working

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

From 65019ed60c635b34337ea35978e931d09ab0181b Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Thu, 7 Jul 2022 10:49:59 -0400
Subject: Get codegen for deferred compilation working

---
 yjit/src/codegen.rs | 42 +++++++++++++++++++++++------------
 yjit/src/core.rs    | 63 +++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 72 insertions(+), 33 deletions(-)

diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 656fc63c0c..6c8fd950a6 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -34,9 +34,10 @@ pub use crate::virtualmem::CodePtr; https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L34
 /// Status returned by code generation functions
 #[derive(PartialEq, Debug)]
 enum CodegenStatus {
-    EndBlock,
     KeepCompiling,
     CantCompile,
+    EndBlock,
+    DeferCompilation,
 }
 
 /// Code generation function signature
@@ -734,6 +735,9 @@ pub fn gen_single_block( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L735
     // Create a backend assembler instance
     let mut asm = Assembler::new();
 
+    // Codegen status for the last instruction compiled
+    let mut status = CantCompile;
+
     // For each instruction to compile
     // NOTE: could rewrite this loop with a std::iter::Iterator
     while insn_idx < iseq_size {
@@ -759,16 +763,12 @@ pub fn gen_single_block( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L763
 
         // If previous instruction requested to record the boundary
         if jit.record_boundary_patch_point {
-
             // FIXME: is this sound with the new assembler?
 
             // Generate an exit to this instruction and record it
             let exit_pos = gen_outlined_exit(jit.pc, &ctx, ocb);
             record_global_inval_patch(cb, exit_pos);
             jit.record_boundary_patch_point = false;
-
-
-
         }
 
         // In debug mode, verify our existing assumption
@@ -777,7 +777,7 @@ pub fn gen_single_block( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L777
         }
 
         // Lookup the codegen function for this instruction
-        let mut status = CantCompile;
+        status = CantCompile;
         if let Some(gen_fn) = get_gen_fn(VALUE(opcode)) {
             // :count-placement:
             // Count bytecode instructions that execute in generated code.
@@ -820,6 +820,11 @@ pub fn gen_single_block( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L820
             break;
         }
 
+        // If we are deferring compilation for this instruction
+        if status == DeferCompilation {
+            break;
+        }
+
         // For now, reset the chain depth after each instruction as only the
         // first instruction in the block can concern itself with the depth.
         ctx.reset_chain_depth();
@@ -850,10 +855,25 @@ pub fn gen_single_block( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L855
         block.set_end_idx(insn_idx);
     }
 
+    // If we are deferring compilation for the current instruction
+    if status == DeferCompilation {
+        defer_compilation(&jit.block, insn_idx, &ctx, cb, ocb);
+
+        // Mark the end position of the block
+        let mut block = jit.block.borrow_mut();
+        block.set_end_addr(cb.get_write_ptr());
+    }
+
+
+
     // We currently can't handle cases where the request is for a block that
     // doesn't go to the next instruction.
     //assert!(!jit.record_boundary_patch_point);
 
+
+
+
+
     // If code for the block doesn't fit, fail
     if cb.has_dropped_bytes() || ocb.unwrap().has_dropped_bytes() {
         return Err(());
@@ -1100,8 +1120,6 @@ fn gen_adjuststack( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1120
     KeepCompiling
 }
 
-
-/*
 fn gen_opt_plus(
     jit: &mut JITState,
     ctx: &mut Context,
@@ -1109,8 +1127,7 @@ fn gen_opt_plus( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1127
     ocb: &mut OutlinedCb,
 ) -> CodegenStatus {
     if !jit_at_current_insn(jit) {
-        defer_compilation(jit, ctx, cb, ocb);
-        return EndBlock;
+        return DeferCompilation;
     }
 
     let comptime_a = jit_peek_at_stack(jit, ctx, 1);
@@ -1147,9 +1164,6 @@ fn gen_opt_plus( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1164
         //gen_opt_send_without_block(jit, ctx, cb, ocb)
     }
 }
-*/
-
-
 
 // new array initialized from top N values
 fn gen_newarray(
@@ -5969,7 +5983,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5983
         //YARVINSN_setlocal => Some(gen_setlocal),
         //YARVINSN_setlocal_WC_0 => Some(gen_setlocal_wc0),
         //YARVINSN_setlocal_WC_1 => Some(gen_setlocal_wc1),
-        //YARVINSN_opt_plus => Some(gen_opt_plus),
+        YARVINSN_opt_plus => Some(gen_opt_plus),
         /*
         YARVINSN_opt_minus => Some(gen_opt_minus),
         YARVINSN_opt_and => Some(gen_opt_and),
diff --git a/yjit/src/core.rs b/yjit/src/core.rs
index a2659b55fd..1b90260248 100644
--- a/yjit/src/core.rs
+++ b/yjit/src/core.rs
@@ -255,7 +255,7 @@ pub enum InsnOpnd { https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L255
 /// Code generation context
 /// Contains information we can use to specialize/optimize code
 /// There are a lot of context objects so we try to keep the size small.
-#[derive(Copy, Clone, Default, Debug)]
+#[derive(Copy, Clone, Default, PartialEq, Debug)]
 pub struct Context {
     // Number of values currently on the temporary stack
     stack_size: u16,
@@ -301,7 +301,7 @@ pub enum BranchShape { https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L301
 
 // Branch code generation function signature
 type BranchGenFn =
-    fn(cb: &mut CodeBlock, target0: CodePtr, target1: Option<CodePtr>, shape: BranchShape) -> ();
+    fn(cb: &mut Assembler, target0: CodePtr, target1: Option<CodePtr>, shape: BranchShape) -> ();
 
 /// Store info about an outgoing branch in a code segment
 /// Note: care must be taken to minimize the size of branch objects
@@ -1511,12 +1511,18 @@ fn regenerate_branch(cb: &mut CodeBlock, branch: &mut Branch) { https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1511
     // Rewrite the branch
     assert!(branch.dst_addrs[0].is_some());
     cb.set_write_ptr(branch.start_addr.unwrap());
+
+    let mut asm = Assembler::new();
+
     (branch.gen_fn)(
-        cb,
+        &mut asm,
         branch.dst_addrs[0].unwrap(),
         branch.dst_addrs[1],
         branch.shape,
     );
+
+    asm.compile(cb);
+
     branch.end_addr = Some(cb.get_write_ptr());
 
     // The block may have shrunk after the branch is rewritten
@@ -1542,7 +1548,7 @@ fn regenerate_branch(cb: &mut CodeBlock, branch: &mut Branch) { https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1548
 }
 
 /// Create a new outgoing branch entry for a block
-fn make_branch_entry(block: BlockRef, src_ctx: &Context, gen_fn: BranchGenFn) -> BranchRef {
+fn make_branch_entry(block: &BlockRef, src_ctx: &Context, gen_fn: BranchGenFn) -> BranchRef {
     let branch = Branch {
         // Block this is attached to
         block: block.clone(),
@@ -1591,6 +1597,10 @@ extern "sysv64" fn branch_stub_hit( https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1597
 /// Called by the generated code when a branch stub is executed
 /// Triggers compilation of branches and code patching
 fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) -> *const u8 {
+    if get_option!(dump_insns) {
+        println!("branch_stub_hit");
+    }
+
     assert!(!branch_ptr.is_null());
 
     //branch_ptr is actually:
@@ -1770,13 +1780,13 @@ fn get_branch_target( https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1780
 
     let mut asm = Assembler::new();
 
-    // Call branch_stub_hit(branch_idx, target_idx, ec)
+    // Call branch_stub_hit(branch_ptr, target_idx, ec)
     let jump_addr = asm.ccall(
         branch_stub_hit as *mut u8,
         vec![
-            EC,
+            Opnd::const_ptr(branch_ptr as *const u8),
             Opnd::UImm(target_idx as u64),
-            Opnd::const_ptr(branch_ptr as *const u8)
+            EC,
         ]
     );
 
@@ -1804,7 +1814,7 @@ pub fn gen_branch( https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1814
     ctx1: Option<&Context>,
     gen_fn: BranchGenFn,
 ) {
-    let branchref = make_branch_entry(jit.get_block(), src_ctx, gen_fn);
+    let branchref = make_branch_entry(&jit.get_block(), src_ctx, gen_fn);
 
     // Get the branch targets or stubs
     let dst_addr0 = get_branch_target(target0, ctx0, &branchref, 0, ocb);
@@ -1835,7 +1845,7 @@ pub fn gen_branch( https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1845
 }
 
 fn gen_jump_branch(
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     target0: CodePtr,
     _target1: Option<CodePtr>,
     shape: BranchShape,
@@ -1845,13 +1855,12 @@ fn gen_jump_branch( https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1855
     }
 
     if shape == BranchShape::Default {
-        //jmp_ptr(cb, target0);
-        todo!("jmp_ptr with new assembler");
+        asm.jmp(target0.into());
     }
 }
 
 pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, cb: &mut CodeBlock) {
-    let branchref = make_branch_entry(jit.get_block(), ctx, gen_jump_branch);
+    let branchref = make_branch_entry(&jit.get_block(), ctx, gen_jump_branch);
     let mut branch = branchref.borrow_mut();
 
     branch.targets[0] = Some(target0);
@@ -1869,10 +1878,25 @@ pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, cb: &mut https://github.com/ruby/ruby/blob/trunk/yjit/src/core.rs#L1878
         branch.blocks[0] = Some(blockref.clone());
         branch.shape = BranchShape::Default;
 
+
+
+        todo!("convert gen_direct_jump to using new asm");
+
+
+        // TODO: could we use regenerate_branch logic here?
+
+        /*
         // Call t (... truncated)

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

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