summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yjit_codegen.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 3b83a474be..9e37dd8a09 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -1350,10 +1350,10 @@ jit_guard_known_klass(jitstate_t *jit, const ctx_t *recompile_context, VALUE kno
return true;
}
+// Generate ancestry guard for protected callee.
static void
-jit_protected_guard(jitstate_t *jit, codeblock_t *cb, const rb_callable_method_entry_t *cme, uint8_t *side_exit)
+jit_protected_callee_ancestry_guard(jitstate_t *jit, codeblock_t *cb, const rb_callable_method_entry_t *cme, uint8_t *side_exit)
{
- // Callee is protected. Generate ancestry guard.
// See vm_call_method().
yjit_save_regs(cb);
mov(cb, C_ARG_REGS[0], member_opnd(REG_CFP, rb_control_frame_t, self));
@@ -1411,11 +1411,6 @@ gen_oswb_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const
mov(cb, REG0, const_ptr_opnd(jit->pc + insn_len(BIN(opt_send_without_block))));
mov(cb, mem_opnd(64, REG_CFP, offsetof(rb_control_frame_t, pc)), REG0);
- if (METHOD_ENTRY_VISI(cme) == METHOD_VISI_PROTECTED) {
- // Generate ancestry guard for protected callee.
- jit_protected_guard(jit, cb, cme, side_exit);
- }
-
// If this function needs a Ruby stack frame
if (cfunc_needs_frame(cfunc)) {
// Stack overflow check
@@ -1606,11 +1601,6 @@ gen_oswb_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r
// Points to the receiver operand on the stack
x86opnd_t recv = ctx_stack_opnd(ctx, argc);
- if (METHOD_ENTRY_VISI(cme) == METHOD_VISI_PROTECTED) {
- // Generate ancestry guard for protected callee.
- jit_protected_guard(jit, cb, cme, side_exit);
- }
-
// Store the updated SP on the current frame (pop arguments and receiver)
lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * -(argc + 1)));
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG0);
@@ -1720,6 +1710,9 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx)
// rb_callinfo : vm_callinfo.h
// rb_callable_method_entry_t : method.h
// vm_call_cfunc_with_frame : vm_insnhelper.c
+ //
+ // For a general overview for how the interpreter calls methods,
+ // see vm_call_method().
struct rb_call_data *cd = (struct rb_call_data *)jit_get_arg(jit, 0);
const struct rb_callinfo *ci = cd->ci; // info about the call site
@@ -1765,6 +1758,25 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx)
return YJIT_CANT_COMPILE;
}
+ switch (METHOD_ENTRY_VISI(cme)) {
+ case METHOD_VISI_PUBLIC:
+ // Can always call public methods
+ break;
+ case METHOD_VISI_PRIVATE:
+ if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
+ // Can only call private methods with FCALL callsites.
+ // (at the moment they are callsites without a receiver or an explicit `self` receiver)
+ return YJIT_CANT_COMPILE;
+ }
+ break;
+ case METHOD_VISI_PROTECTED:
+ jit_protected_callee_ancestry_guard(jit, cb, cme, side_exit);
+ break;
+ case METHOD_VISI_UNDEF:
+ RUBY_ASSERT(false && "cmes should always have a visibility");
+ break;
+ }
+
// Register block for invalidation
RUBY_ASSERT(cme->called_id == mid);
assume_method_lookup_stable(comptime_recv_klass, cme, jit->block);