Skip to content

Conversation

@st0012
Copy link
Member

@st0012 st0012 commented Nov 26, 2025

  • Add recv field to CCall and CCallWithFrame so now all method dispatch related instructions have recv field, separate from args field. This ensures consistent pointer arithmetic when generating code for these instructions.
  • Standardize recv field's display position in send related instructions.

@matzbot matzbot requested a review from a team November 26, 2025 20:21
@st0012 st0012 changed the title ZJIT: Standardize C call related insn fields ZJIT: Standardize method dispatch insns' recv field Nov 26, 2025
@XrXr
Copy link
Member

XrXr commented Nov 26, 2025

lobsters assert failures look relevant.

assertion failed: opnds.len() <= C_ARG_OPNDS.len()

@st0012
Copy link
Member Author

st0012 commented Nov 26, 2025

@XrXr Fixed!

@st0012 st0012 force-pushed the zjit-standardize-ccall-hir-fields branch from 528f57d to 7f98741 Compare November 27, 2025 15:26
Insn::CCallWithFrame { cd, state, args, .. } if args.len() > C_ARG_OPNDS.len() =>
Insn::CCall { cfunc, recv, args, name, return_type: _, elidable: _ } => gen_ccall(asm, *cfunc, *name, opnd!(recv), opnds!(args)),
// Give up CCallWithFrame for 6+ args since asm.ccall() supports at most 6 args (recv + args count).
Insn::CCallWithFrame { cd, state, args, .. } if args.len() + 1 > C_ARG_OPNDS.len() =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More experienced people than I should probably confirm that I'm on the right track - but maybe a test to show this behaviour for > 6 args could be useful.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Ruby core itself, there's no method that take 6 parameters that can trigger this AFAIK. Fiber::Scheduler has methods that take up to 5, but they're not enough either.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checks out!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good call tho. I'll add a comment to explain this 🙂

Copy link
Contributor

@aidenfoxivey aidenfoxivey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gave it a look over, seems like a reasonable change to me. I added a comment.

@st0012 st0012 force-pushed the zjit-standardize-ccall-hir-fields branch from 7f98741 to 7831770 Compare November 27, 2025 20:14
@launchable-app

This comment has been minimized.

@st0012 st0012 force-pushed the zjit-standardize-ccall-hir-fields branch from 7831770 to 91bb08f Compare December 1, 2025 17:12
- Add `recv` field to `CCall` and `CCallWithFrame` so now all method dispatch
  related instructions have `recv` field, separate from `args` field.
  This ensures consistent pointer arithmetic when generating code for these
  instructions.
- Standardize `recv` field's display position in send related instructions.
@st0012 st0012 force-pushed the zjit-standardize-ccall-hir-fields branch from 91bb08f to 0efa8ba Compare December 1, 2025 17:27
@st0012 st0012 enabled auto-merge (squash) December 1, 2025 17:35
@tekknolagi
Copy link
Contributor

I don't think this is a good idea as-is. CCall is a general-purpose utility to call a C function. If we want to have IR for "call a Ruby C method without pushing a frame" then we should make that a separate IR instruction that has a recv. I think there are some non-method CCalls floating around and it doesn't make sense to hallucinate a recv for them.

So:

  • CCall
  • CallCMethodWithoutFrame
  • CallCMethod

or instead,

  • CCall
  • PushFrame
  • PopFrame

@st0012 st0012 merged commit 5f92d6d into ruby:master Dec 1, 2025
102 of 107 checks passed
@st0012 st0012 deleted the zjit-standardize-ccall-hir-fields branch December 1, 2025 18:01
@st0012
Copy link
Member Author

st0012 commented Dec 1, 2025

I think there are some non-method CCalls floating around and it doesn't make sense to hallucinate a recv for them.

Do you have examples of those?
As far as I can see, we currently use CCall for:

  • Specializing SendWithoutBlock, which definitely are method calls
  • Inlining String#==, which is a method call too

In both cases, we already have receivers. So I don't see the hallucination you mentioned.

@tekknolagi
Copy link
Contributor

@eregon is adding some in his getivar specialization PR, I think. But if we truly don't have this problem right now, then ok, fine.

In general I think we should move toward PushFrame/PopFrame but less urgent

@eregon
Copy link
Member

eregon commented Dec 1, 2025

For the ref, #15327 uses rb_ivar_get_at_no_ractor_check which is not a C method.

| Insn::Send { recv, ref args, .. }
| Insn::SendForward { recv, ref args, .. }
| Insn::InvokeSuper { recv, ref args, .. }
| Insn::CCall { recv, ref args, .. }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents calling rb_ivar_get_at_no_ractor_check(VALUE obj, attr_index_t index), so Insn::CCall* should probably not check the types of the args

tagomoris pushed a commit to tagomoris/ruby that referenced this pull request Dec 2, 2025
ZJIT: Standardize C call related insn fields

- Add `recv` field to `CCall` and `CCallWithFrame` so now all method dispatch
  related instructions have `recv` field, separate from `args` field.
  This ensures consistent pointer arithmetic when generating code for these
  instructions.
- Standardize `recv` field's display position in send related instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants