8000 Deduplicate side exits · github/ruby@f723c5f · GitHub
[go: up one dir, main page]

Skip to content

Commit f723c5f

Browse files
committed
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.
1 parent aab2060 commit f723c5f

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

yjit_codegen.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ jit_prepare_routine_call(jitstate_t *jit, ctx_t *ctx, x86opnd_t scratch_reg)
193193
}
194194

195195
// Record the current codeblock write position for rewriting into a jump into
196-
// the outline block later. Used to implement global code invalidation.
196+
// the outlined block later. Used to implement global code invalidation.
197197
static void
198198
record_global_inval_patch(const codeblock_t *cb, uint32_t outline_block_target_pos)
199199
{
@@ -355,7 +355,7 @@ yjit_gen_exit(VALUE *exit_pc, ctx_t *ctx, codeblock_t *cb)
355355
// Update the CFP on the EC
356356
mov(cb, member_opnd(REG_EC, rb_execution_context_t, cfp), REG_CFP);
357357

358-
// Put PC into the return register, which the post call bytes dispatches to
358+
// Update CFP->PC
359359
mov(cb, RAX, const_ptr_opnd(exit_pc));
360360
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
361361

@@ -398,12 +398,27 @@ yjit_gen_leave_exit(codeblock_t *cb)
398398
return code_ptr;
399399
}
400400

401-
// A shorthand for generating an exit in the outline block
401+
// :side-exit:
402+
// Get an exit for the current instruction in the outlined block. The code
403+
// for each instruction often begins with several guards before proceeding
404+
// to do work. When guards fail, an option we have is to exit to the
405+
// interpreter at an instruction boundary. The piece of code that takes
406+
// care of reconstructing interpreter state and exiting out of generated
407+
// code is called the side exit.
408+
//
409+
// No guards change the logic for reconstructing interpreter state at the
410+
// moment, so there is one unique side exit for each context. Note that
411+
// it's incorrect to jump to the side exit after any ctx stack push/pop operations
412+
// since they change the logic required for reconstructing interpreter state.
402413
static uint8_t *
403414
yjit_side_exit(jitstate_t *jit, ctx_t *ctx)
404415
{
405-
uint32_t pos = yjit_gen_exit(jit->pc, ctx, ocb);
406-
return cb_get_ptr(ocb, pos);
416+
if (!jit->side_exit_for_pc) {
417+
uint32_t pos = yjit_gen_exit(jit->pc, ctx, ocb);
418+
jit->side_exit_for_pc = cb_get_ptr(ocb, pos);
419+
}
420+
421+
return jit->side_exit_for_pc;
407422
}
408423

409424
// 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)
638653

639654
// Set the current instruction
640655
jit.insn_idx = insn_idx;
641-
jit.pc = pc;
642656
jit.opcode = opcode;
657+
jit.pc = pc;
658+
jit.side_exit_for_pc = NULL;
643659

644660
// If previous instruction requested to record the boundary
645661
if (jit.record_boundary_patch_point) {

yjit_codegen.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern uint32_t yjit_codepage_frozen_bytes;
1313
typedef struct JITState
1414
{
1515
// Block version being compiled
16-
block_t* block;
16+
block_t *block;
1717

1818
// Instruction sequence this is associated with
1919
const rb_iseq_t *iseq;
@@ -27,9 +27,12 @@ typedef struct JITState
2727
// PC of the instruction being compiled
2828
VALUE *pc;
2929

30+
// Side exit to the instruction being compiled. See :side-exit:.
31+
uint8_t *side_exit_for_pc;
32+
3033
// Execution context when compilation started
3134
// This allows us to peek at run-time values
32-
rb_execution_context_t* ec;
35+
rb_execution_context_t *ec;
3336

3437
// Whether we need to record the code address at
3538
// the end of this bytecode instruction for global invalidation

0 commit comments

Comments
 (0)
0