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

ruby-changes:69220

From: Alan <ko1@a...>
Date: Thu, 21 Oct 2021 08:24:06 +0900 (JST)
Subject: [ruby-changes:69220] cbb0271dd6 (master): Deduplicate side exits

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

From cbb0271dd6256601aa6aea669ceac4f82fdb75fe Mon Sep 17 00:00:00 2001
From: Alan Wu <XrXr@u...>
Date: Fri, 10 Sep 2021 11:22:36 -0400
Subject: Deduplicate side exits

Send instructions currently generate the exact same side exit twice.
Cache the exit the first time we generate it. Also add a comment
explaining what side exits do.

Closes GH-117.
---
 yjit_codegen.c | 28 ++++++++++++++++++++++------
 yjit_codegen.h |  7 +++++--
 2 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/yjit_codegen.c b/yjit_codegen.c
index 015e97bb73..9fd70917d2 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -193,7 +193,7 @@ jit_prepare_routine_call(jitstate_t *jit, ctx_t *ctx, x86opnd_t scratch_reg) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L193
 }
 
 // Record the current codeblock write position for rewriting into a jump into
-// the outline block later. Used to implement global code invalidation.
+// the outlined block later. Used to implement global code invalidation.
 static void
 record_global_inval_patch(const codeblock_t *cb, uint32_t outline_block_target_pos)
 {
@@ -355,7 +355,7 @@ yjit_gen_exit(VALUE *exit_pc, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L355
     // 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
+    // Update CFP->PC
     mov(cb, RAX, const_ptr_opnd(exit_pc));
     mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
 
@@ -398,12 +398,27 @@ yjit_gen_leave_exit(codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L398
     return code_ptr;
 }
 
-// A shorthand for generating an exit in the outline block
+// :side-exit:
+// Get an exit for the current instruction in the outlined block. The code
+// for each instruction often begins with several guards before proceeding
+// to do work. When guards fail, an option we have is to exit to the
+// interpreter at an instruction boundary. The piece of code that takes
+// care of reconstructing interpreter state and exiting out of generated
+// code is called the side exit.
+//
+// No guards change the logic for reconstructing interpreter state at the
+// moment, so there is one unique side exit for each context. Note that
+// it's incorrect to jump to the side exit after any ctx stack push/pop operations
+// since they change the logic required for reconstructing interpreter state.
 static uint8_t *
 yjit_side_exit(jitstate_t *jit, ctx_t *ctx)
 {
-    uint32_t pos = yjit_gen_exit(jit->pc, ctx, ocb);
-    return cb_get_ptr(ocb, pos);
+    if (!jit->side_exit_for_pc) {
+        uint32_t pos = yjit_gen_exit(jit->pc, ctx, ocb);
+        jit->side_exit_for_pc = cb_get_ptr(ocb, pos);
+    }
+
+    return jit->side_exit_for_pc;
 }
 
 // Generate a runtime guard that ensures the PC is at the start of the iseq,
@@ -638,8 +653,9 @@ yjit_gen_block(block_t *block, rb_execution_context_t *ec) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L653
 
         // Set the current instruction
         jit.insn_idx = insn_idx;
-        jit.pc = pc;
         jit.opcode = opcode;
+        jit.pc = pc;
+        jit.side_exit_for_pc = NULL;
 
         // If previous instruction requested to record the boundary
         if (jit.record_boundary_patch_point) {
diff --git a/yjit_codegen.h b/yjit_codegen.h
index 66740a30f5..16c2211656 100644
--- a/yjit_codegen.h
+++ b/yjit_codegen.h
@@ -13,7 +13,7 @@ extern uint32_t yjit_codepage_frozen_bytes; https://github.com/ruby/ruby/blob/trunk/yjit_codegen.h#L13
 typedef struct JITState
 {
     // Block version being compiled
-    block_t* block;
+    block_t *block;
 
     // Instruction sequence this is associated with
     const rb_iseq_t *iseq;
@@ -27,9 +27,12 @@ typedef struct JITState https://github.com/ruby/ruby/blob/trunk/yjit_codegen.h#L27
     // PC of the instruction being compiled
     VALUE *pc;
 
+    // Side exit to the instruction being compiled. See :side-exit:.
+    uint8_t *side_exit_for_pc;
+
     // Execution context when compilation started
     // This allows us to peek at run-time values
-    rb_execution_context_t* ec;
+    rb_execution_context_t *ec;
 
     // Whether we need to record the code address at
     // the end of this bytecode instruction for global invalidation
-- 
cgit v1.2.1


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

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