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

ruby-changes:73244

From: Takashi <ko1@a...>
Date: Tue, 30 Aug 2022 01:04:58 +0900 (JST)
Subject: [ruby-changes:73244] fe172aac04 (master): Convert getinstancevariable to new backend IR (https://github.com/Shopify/ruby/pull/352)

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

From fe172aac0465160ec5a02c687ab1dc6ade2c090a Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Thu, 4 Aug 2022 09:02:09 -0700
Subject: Convert  getinstancevariable to new backend IR
 (https://github.com/Shopify/ruby/pull/352)

* Convert getinstancevariable to new backend IR

* Support mem-based mem

* Use more into()

* Add tests for getivar

* Just load obj_opnd to a register

* Apply another into()

* Flip the nil-out condition

* Fix duplicated counts of side_exit
---
 yjit/src/backend/ir.rs |   9 +-
 yjit/src/codegen.rs    | 315 ++++++++++++++++++++++++-------------------------
 2 files changed, 160 insertions(+), 164 deletions(-)

diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 99a084ff02..41842c9704 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -340,7 +340,14 @@ impl Target https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L340
     pub fn unwrap_label_idx(&self) -> usize {
         match self {
             Target::Label(idx) => *idx,
-            _ => unreachable!()
+            _ => unreachable!("trying to unwrap {:?} into label", self)
+        }
+    }
+
+    pub fn unwrap_code_ptr(&self) -> CodePtr {
+        match self {
+            Target::CodePtr(ptr) => *ptr,
+            _ => unreachable!("trying to unwrap {:?} into code ptr", self)
         }
     }
 }
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index ef7ccf9a65..f08b073e34 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -213,7 +213,7 @@ macro_rules! gen_counter_incr { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L213
             let counter_opnd = Opnd::mem(64, ptr_reg, 0);
 
             // Increment and store the updated value
-            $asm.incr_counter(counter_opnd, 1.into());
+            $asm.incr_counter(counter_opnd, Opnd::UImm(1));
         }
     };
 }
@@ -236,11 +236,14 @@ macro_rules! counted_exit { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L236
             let ocb = $ocb.unwrap();
             let code_ptr = ocb.get_write_ptr();
 
+            let mut ocb_asm = Assembler::new();
+
             // Increment the counter
-            gen_counter_incr!(ocb, $counter_name);
+            gen_counter_incr!(ocb_asm, $counter_name);
 
             // Jump to the existing side exit
-            jmp_ptr(ocb, $existing_side_exit);
+            ocb_asm.jmp($existing_side_exit.into());
+            ocb_asm.compile(ocb);
 
             // Pointer to the side-exit code
             code_ptr
@@ -1805,40 +1808,39 @@ fn gen_checkkeyword( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1808
     KeepCompiling
 }
 
-/*
 fn gen_jnz_to_target0(
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     target0: CodePtr,
     _target1: Option<CodePtr>,
     shape: BranchShape,
 ) {
     match shape {
         BranchShape::Next0 | BranchShape::Next1 => unreachable!(),
-        BranchShape::Default => jnz_ptr(cb, target0),
+        BranchShape::Default => asm.jnz(target0.into()),
     }
 }
 
 fn gen_jz_to_target0(
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     target0: CodePtr,
     _target1: Option<CodePtr>,
     shape: BranchShape,
 ) {
     match shape {
         BranchShape::Next0 | BranchShape::Next1 => unreachable!(),
-        BranchShape::Default => jz_ptr(cb, target0),
+        BranchShape::Default => asm.jz(Target::CodePtr(target0)),
     }
 }
 
 fn gen_jbe_to_target0(
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     target0: CodePtr,
     _target1: Option<CodePtr>,
     shape: BranchShape,
 ) {
     match shape {
         BranchShape::Next0 | BranchShape::Next1 => unreachable!(),
-        BranchShape::Default => jbe_ptr(cb, target0),
+        BranchShape::Default => asm.jbe(Target::CodePtr(target0)),
     }
 }
 
@@ -1848,7 +1850,7 @@ fn jit_chain_guard( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1850
     jcc: JCCKinds,
     jit: &JITState,
     ctx: &Context,
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     ocb: &mut OutlinedCb,
     depth_limit: i32,
     side_exit: CodePtr,
@@ -1867,15 +1869,16 @@ fn jit_chain_guard( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1869
             idx: jit.insn_idx,
         };
 
-        gen_branch(jit, ctx, cb, ocb, bid, &deeper, None, None, target0_gen_fn);
+        gen_branch(jit, ctx, asm, ocb, bid, &deeper, None, None, target0_gen_fn);
     } else {
-        target0_gen_fn(cb, side_exit, None, BranchShape::Default);
+        target0_gen_fn(asm, side_exit, None, BranchShape::Default);
     }
 }
 
 // up to 5 different classes, and embedded or not for each
 pub const GET_IVAR_MAX_DEPTH: i32 = 10;
 
+/*
 // hashes and arrays
 pub const OPT_AREF_MAX_CHAIN_DEPTH: i32 = 2;
 
@@ -1921,26 +1924,33 @@ fn gen_set_ivar( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1924
     KeepCompiling
 }
 
-/*
+
+
 // Codegen for getting an instance variable.
 // Preconditions:
-//   - receiver is in REG0
 //   - receiver has the same class as CLASS_OF(comptime_receiver)
 //   - no stack push or pops to ctx since the entry to the codegen of the instruction being compiled
 fn gen_get_ivar(
     jit: &mut JITState,
     ctx: &mut Context,
-    cb: &mut CodeBlock,
+    asm: &mut Assembler,
     ocb: &mut OutlinedCb,
     max_chain_depth: i32,
     comptime_receiver: VALUE,
     ivar_name: ID,
-    reg0_opnd: InsnOpnd,
+    recv: Opnd,
+    recv_opnd: InsnOpnd,
     side_exit: CodePtr,
 ) -> CodegenStatus {
     let comptime_val_klass = comptime_receiver.class_of();
     let starting_context = *ctx; // make a copy for use with jit_chain_guard
 
+    // If recv isn't already a register, load it.
+    let recv = match recv {
+        Opnd::Reg(_) => recv,
+        _ => asm.load(recv),
+    };
+
     // Check if the comptime class uses a custom allocator
     let custom_allocator = unsafe { rb_get_alloc_func(comptime_val_klass) };
     let uses_custom_allocator = match custom_allocator {
@@ -1961,46 +1971,26 @@ fn gen_get_ivar( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1971
     if !receiver_t_object || uses_custom_allocator {
         // General case. Call rb_ivar_get().
         // VALUE rb_ivar_get(VALUE obj, ID id)
-        add_comment(cb, "call rb_ivar_get()");
+        asm.comment("call rb_ivar_get()");
 
         // The function could raise exceptions.
-        jit_prepare_routine_call(jit, ctx, cb, REG1);
+        jit_prepare_routine_call(jit, ctx, asm);
 
-        mov(cb, C_ARG_REGS[0], REG0);
-        mov(cb, C_ARG_REGS[1], uimm_opnd(ivar_name));
-        call_ptr(cb, REG1, rb_ivar_get as *const u8);
+        let ivar_val = asm.ccall(rb_ivar_get as *const u8, vec![recv, Opnd::UImm(ivar_name)]);
 
-        if reg0_opnd != SelfOpnd {
+        if recv_opnd != SelfOpnd {
             ctx.stack_pop(1);
         }
+
         // Push the ivar on the stack
         let out_opnd = ctx.stack_push(Type::Unknown);
-        mov(cb, out_opnd, RAX);
+        asm.mov(out_opnd, ivar_val);
 
         // Jump to next instruction. This allows guard chains to share the same successor.
-        jump_to_next_insn(jit, ctx, cb, ocb);
+        jump_to_next_insn(jit, ctx, asm, ocb);
         return EndBlock;
     }
 
-    /*
-    // FIXME:
-    // This check was added because of a failure in a test involving the
-    // Nokogiri Document class where we see a T_DATA that still has the default
-    // allocator.
-    // Aaron Patterson argues that this is a bug in the C extension, because
-    // people could call .allocate() on the class and still get a T_OBJECT
-    // For now I added an extra dynamic check that the receiver is T_OBJECT
-    // so we can safely pass all the tests in Shopify Core.
-    //
-    // Guard that the receiver is T_OBJECT
-    // #define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK)
-    add_comment(cb, "guard receiver is T_OBJECT");
-    mov(cb, REG1, member_opnd(REG0, struct RBasic, flags));
-    and(cb, REG1, imm_opnd(RUBY_T_MASK));
-    cmp(cb, REG1, imm_opnd(T_OBJECT));
-    jit_chain_guard(JCC_JNE, jit, &starting_context, cb, ocb, max_chain_depth, side_exit);
-    */
-
     // FIXME: Mapping the index could fail when there is too many ivar names. If we're
     // compiling for a branch stub that can cause the exception to be thrown from the
     // wrong PC.
@@ -2008,16 +1998,16 @@ fn gen_get_ivar( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L1998
         unsafe { rb_obj_ensure_iv_index_mapping(comptime_receiver, ivar_name) }.as_usize();
 
     // Pop receiver if it's on the temp stack
-    if reg0_opnd != SelfOpnd {
+    if recv_opnd != SelfOpnd {
         ctx.stack_pop(1);
     }
 
     if USE_RVARGC != 0 {
         // Check that the ivar table is big enough
         // Check that the slot is inside the ivar table (num_slots > index)
-        let num_slots = mem_opnd(32, REG0, ROBJECT_OFFSET_NUMIV);
-        cmp(cb, num_slots, uimm_opnd(ivar_index as u64));
-        jle_ptr(cb, counted_exit!(ocb, side_exit, getivar_idx_out_of_range));
+        let num_slots = Opnd::mem(32, recv, ROBJECT_OFFSET_NUMIV);
+        asm.cmp(num_slots, Opnd::UImm(ivar_index as u64));
+        asm.jbe(counted_exit!(ocb, side_exit, getivar_idx_out_of_range).into());
     }
 
     // Compile time self is embedded and the ivar index lands within the object
@@ -2027,15 +2017,15 @@ fn gen_get_ivar( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L2017
 
         // Guard that self is embedded
         // TODO: BT and JC is shorter
-        add_comment(cb, "guard embedded getivar");
-        let flags_opnd = mem_opnd(64, REG0, RUBY_OFFSET_RBASIC_FLAGS);
-        test(cb, flags_opnd, uimm_opnd(ROBJECT_EMBED as u64));
+        asm.comment("guard embedded getivar");
+        let flags_opnd = Opnd::mem(64, recv, RUBY_OFFSET_RBASIC_FLAGS);
+        asm.test(flags_opnd, Opnd::UImm(ROBJECT_EMBED as u64));
         let side_exit = counted_exit!(ocb, side_exit,  (... truncated)

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

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