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

ruby-changes:69023

From: Alan <ko1@a...>
Date: Thu, 21 Oct 2021 08:18:28 +0900 (JST)
Subject: [ruby-changes:69023] 1610dc0864 (master): YJIT: use a context-free landing pad to optimize `leave`

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

From 1610dc0864a330006085ac9e9d6428b89d6c0ccd Mon Sep 17 00:00:00 2001
From: Alan Wu <XrXr@u...>
Date: Mon, 19 Apr 2021 18:23:07 -0400
Subject: YJIT: use a context-free landing pad to optimize `leave`

This allows gen_leave to always do an indirect to cfp->jit_return.
---
 yjit_codegen.c | 51 ++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/yjit_codegen.c b/yjit_codegen.c
index 4d4f182b6d..39a2667f5d 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -27,6 +27,9 @@ codeblock_t* cb = NULL; https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L27
 static codeblock_t outline_block;
 codeblock_t* ocb = NULL;
 
+// Code for exiting back to the interpreter
+static void *interp_exit;
+
 // Print the current source location for debugging purposes
 RBIMPL_ATTR_MAYBE_UNUSED()
 static void
@@ -137,7 +140,7 @@ yjit_load_regs(codeblock_t* cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L140
 static uint8_t *
 yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
 {
-    uint8_t *code_ptr = cb_get_ptr(ocb, ocb->write_pos);
+    uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
 
     VALUE *exit_pc = jit->pc;
 
@@ -184,6 +187,26 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L187
     return code_ptr;
 }
 
+// Generate an interpreter to REG_CFP->pc.
+static uint8_t *
+yjit_gen_context_free_exit(codeblock_t *cb)
+{
+    uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
+
+    // Update the CFP on the EC
+    mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP);
+
+    // Put PC into the return register, which the post call bytes dispatches to
+    mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, pc));
+
+    cb_write_post_call_bytes(cb);
+
+    // Note, not incrementing stats here since this exit is the natural end to
+    // executing output code.
+
+    return code_ptr;
+}
+
 
 // A shorthand for generating an exit in the outline block
 static uint8_t *
@@ -251,7 +274,7 @@ yjit_comment_array_t yjit_code_comments; https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L274
 Compile an interpreter entry block to be inserted into an iseq
 Returns `NULL` if compilation fails.
 */
-uint8_t*
+uint8_t *
 yjit_entry_prologue(void)
 {
     RUBY_ASSERT(cb != NULL);
@@ -271,6 +294,11 @@ yjit_entry_prologue(void) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L294
     // Load the current SP from the CFP into REG_SP
     mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
 
+    // Setup cfp->jit_return
+    // TODO: this could use a IP relative LEA instead of an 8 byte immediate
+    mov(cb, REG0, const_ptr_opnd(interp_exit));
+    mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0);
+
     return code_ptr;
 }
 
@@ -2076,21 +2104,9 @@ gen_leave(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2104
     mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
     mov(cb, mem_opnd(64, REG_SP, -SIZEOF_VALUE), REG0);
 
-    // If the return address is NULL, fall back to the interpreter
-    ADD_COMMENT(cb, "check for jit return");
-    int FALLBACK_LABEL = cb_new_label(cb, "FALLBACK");
-    test(cb, REG1, REG1);
-    jz_label(cb, FALLBACK_LABEL);
-
     // Jump to the JIT return address
     jmp_rm(cb, REG1);
 
-    // Fall back to the interpreter
-    cb_write_label(cb, FALLBACK_LABEL);
-    cb_link_labels(cb);
-    GEN_COUNTER_INC(cb, leave_interp_return);
-    cb_write_post_call_bytes(cb);
-
     return YJIT_END_BLOCK;
 }
 
@@ -2151,12 +2167,17 @@ yjit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2167
 {
     // Initialize the code blocks
     uint32_t mem_size = 128 * 1024 * 1024;
-    uint8_t* mem_block = alloc_exec_mem(mem_size);
+    uint8_t *mem_block = alloc_exec_mem(mem_size);
+
     cb = &block;
     cb_init(cb, mem_block, mem_size/2);
+
     ocb = &outline_block;
     cb_init(ocb, mem_block + mem_size/2, mem_size/2);
 
+    // Generate interp_exit
+    interp_exit = yjit_gen_context_free_exit(cb);
+
     // Map YARV opcodes to the corresponding codegen functions
     yjit_reg_op(BIN(dup), gen_dup);
     yjit_reg_op(BIN(nop), gen_nop);
-- 
cgit v1.2.1


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

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