Skip to content

Commit 439744d

Browse files
committed
YJIT: use a context-free landing pad to optimize leave
This allows gen_leave to always do an indirect to cfp->jit_return.
1 parent 5642279 commit 439744d

1 file changed

Lines changed: 36 additions & 15 deletions

File tree

yjit_codegen.c

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ codeblock_t* cb = NULL;
2626
static codeblock_t outline_block;
2727
codeblock_t* ocb = NULL;
2828

29+
// Code for exiting back to the interpreter
30+
static void *interp_exit;
31+
2932
// Print the current source location for debugging purposes
3033
RBIMPL_ATTR_MAYBE_UNUSED()
3134
static void
@@ -136,7 +139,7 @@ yjit_load_regs(codeblock_t* cb)
136139
static uint8_t *
137140
yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
138141
{
139-
uint8_t *code_ptr = cb_get_ptr(ocb, ocb->write_pos);
142+
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
140143

141144
VALUE *exit_pc = jit->pc;
142145

@@ -183,6 +186,26 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
183186
return code_ptr;
184187
}
185188

189+
// Generate an interpreter to REG_CFP->pc.
190+
static uint8_t *
191+
yjit_gen_context_free_exit(codeblock_t *cb)
192+
{
193+
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
194+
195+
// Update the CFP on the EC
196+
mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP);
197+
198+
// Put PC into the return register, which the post call bytes dispatches to
199+
mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, pc));
200+
201+
cb_write_post_call_bytes(cb);
202+
203+
// Note, not incrementing stats here since this exit is the natural end to
204+
// executing output code.
205+
206+
return code_ptr;
207+
}
208+
186209

187210
// A shorthand for generating an exit in the outline block
188211
static uint8_t *
@@ -250,7 +273,7 @@ yjit_comment_array_t yjit_code_comments;
250273
Compile an interpreter entry block to be inserted into an iseq
251274
Returns `NULL` if compilation fails.
252275
*/
253-
uint8_t*
276+
uint8_t *
254277
yjit_entry_prologue(void)
255278
{
256279
RUBY_ASSERT(cb != NULL);
@@ -270,6 +293,11 @@ yjit_entry_prologue(void)
270293
// Load the current SP from the CFP into REG_SP
271294
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
272295

296+
// Setup cfp->jit_return
297+
// TODO: this could use a IP relative LEA instead of an 8 byte immediate
298+
mov(cb, REG0, const_ptr_opnd(interp_exit));
299+
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, jit_return), REG0);
300+
273301
return code_ptr;
274302
}
275303

@@ -2005,21 +2033,9 @@ gen_leave(jitstate_t* jit, ctx_t* ctx)
20052033
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
20062034
mov(cb, mem_opnd(64, REG_SP, -SIZEOF_VALUE), REG0);
20072035

2008-
// If the return address is NULL, fall back to the interpreter
2009-
ADD_COMMENT(cb, "check for jit return");
2010-
int FALLBACK_LABEL = cb_new_label(cb, "FALLBACK");
2011-
test(cb, REG1, REG1);
2012-
jz_label(cb, FALLBACK_LABEL);
2013-
20142036
// Jump to the JIT return address
20152037
jmp_rm(cb, REG1);
20162038

2017-
// Fall back to the interpreter
2018-
cb_write_label(cb, FALLBACK_LABEL);
2019-
cb_link_labels(cb);
2020-
GEN_COUNTER_INC(cb, leave_interp_return);
2021-
cb_write_post_call_bytes(cb);
2022-
20232039
return YJIT_END_BLOCK;
20242040
}
20252041

@@ -2080,12 +2096,17 @@ yjit_init_codegen(void)
20802096
{
20812097
// Initialize the code blocks
20822098
uint32_t mem_size = 128 * 1024 * 1024;
2083-
uint8_t* mem_block = alloc_exec_mem(mem_size);
2099+
uint8_t *mem_block = alloc_exec_mem(mem_size);
2100+
20842101
cb = █
20852102
cb_init(cb, mem_block, mem_size/2);
2103+
20862104
ocb = &outline_block;
20872105
cb_init(ocb, mem_block + mem_size/2, mem_size/2);
20882106

2107+
// Generate interp_exit
2108+
interp_exit = yjit_gen_context_free_exit(cb);
2109+
20892110
// Map YARV opcodes to the corresponding codegen functions
20902111
yjit_reg_op(BIN(dup), gen_dup);
20912112
yjit_reg_op(BIN(nop), gen_nop);

0 commit comments

Comments
 (0)