Skip to content

Commit 761d0d1

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 cf69abe commit 761d0d1

File tree

1 file changed

+36
-15
lines changed

1 file changed

+36
-15
lines changed

yjit_codegen.c

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

30+
// Code for exiting back to the interpreter
31+
static void *interp_exit;
32+
3033
// Print the current source location for debugging purposes
3134
RBIMPL_ATTR_MAYBE_UNUSED()
3235
static void
@@ -137,7 +140,7 @@ yjit_load_regs(codeblock_t* cb)
137140
static uint8_t *
138141
yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
139142
{
140-
uint8_t *code_ptr = cb_get_ptr(ocb, ocb->write_pos);
143+
uint8_t *code_ptr = cb_get_ptr(cb, cb->write_pos);
141144

142145
VALUE *exit_pc = jit->pc;
143146

@@ -184,6 +187,26 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
184187
return code_ptr;
185188
}
186189

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

188211
// A shorthand for generating an exit in the outline block
189212
static uint8_t *
@@ -251,7 +274,7 @@ yjit_comment_array_t yjit_code_comments;
251274
Compile an interpreter entry block to be inserted into an iseq
252275
Returns `NULL` if compilation fails.
253276
*/
254-
uint8_t*
277+
uint8_t *
255278
yjit_entry_prologue(void)
256279
{
257280
RUBY_ASSERT(cb != NULL);
@@ -271,6 +294,11 @@ yjit_entry_prologue(void)
271294
// Load the current SP from the CFP into REG_SP
272295
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
273296

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

@@ -2076,21 +2104,9 @@ gen_leave(jitstate_t* jit, ctx_t* ctx)
20762104
mov(cb, REG_SP, member_opnd(REG_CFP, rb_control_frame_t, sp));
20772105
mov(cb, mem_opnd(64, REG_SP, -SIZEOF_VALUE), REG0);
20782106

2079-
// If the return address is NULL, fall back to the interpreter
2080-
ADD_COMMENT(cb, "check for jit return");
2081-
int FALLBACK_LABEL = cb_new_label(cb, "FALLBACK");
2082-
test(cb, REG1, REG1);
2083-
jz_label(cb, FALLBACK_LABEL);
2084-
20852107
// Jump to the JIT return address
20862108
jmp_rm(cb, REG1);
20872109

2088-
// Fall back to the interpreter
2089-
cb_write_label(cb, FALLBACK_LABEL);
2090-
cb_link_labels(cb);
2091-
GEN_COUNTER_INC(cb, leave_interp_return);
2092-
cb_write_post_call_bytes(cb);
2093-
20942110
return YJIT_END_BLOCK;
20952111
}
20962112

@@ -2151,12 +2167,17 @@ yjit_init_codegen(void)
21512167
{
21522168
// Initialize the code blocks
21532169
uint32_t mem_size = 128 * 1024 * 1024;
2154-
uint8_t* mem_block = alloc_exec_mem(mem_size);
2170+
uint8_t *mem_block = alloc_exec_mem(mem_size);
2171+
21552172
cb = █
21562173
cb_init(cb, mem_block, mem_size/2);
2174+
21572175
ocb = &outline_block;
21582176
cb_init(ocb, mem_block + mem_size/2, mem_size/2);
21592177

2178+
// Generate interp_exit
2179+
interp_exit = yjit_gen_context_free_exit(cb);
2180+
21602181
// Map YARV opcodes to the corresponding codegen functions
21612182
yjit_reg_op(BIN(dup), gen_dup);
21622183
yjit_reg_op(BIN(nop), gen_nop);

0 commit comments

Comments
 (0)