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 = █ 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/