-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
correct __send__ routing of native methods when it has overloads #5067
base: master
Are you sure you want to change the base?
Conversation
suppose a method is implemented in block-less form in native code e.g. ``` static civil(ThreadContext context, IRubyObject self) static civil(ThreadContext context, IRubyObject self, IRubyObject[] args) ``` doing a `Date.civil` will properly route to `civil(context, self)` while a `Date.send(:civil)` ends up being routed through args case
obviously (even with the proposed change) still won't work for |
@kares I believe anno binding will work with block and non-block signatures. I might be missing something but if we can do that I would prefer it over an if in all block accepting signatures (I guess we also need callsites to properly call those versions too -- is that the issue?). I would like to ultimately have n call paths with little to no actual extra logic to keep methods smaller/simpler for inlining potential. |
@enebo ok - makes sense, callsites are fine and dispatch is all good for the normal method call. |
Are you saying that 3-argument calls aren't going to 3-argument overrides now?
Yes, I agree this should be addressed. I'll have a look at the patch. |
Ok thoughts.
I realize as I type this that this introduces a new problem: calling a method with no block that is set up to receive a block will start routing through args boxing. The problem just gets moved to the other side. Now...I have generally tried to make sure all my args[] methods do check arity; they can be called from Java, after all, and there's no guarantee on the size of the incoming array. So with that in mind I'm wondering if we really should fix this. If we always route 0-3 args to appropriate overloads, and stop checking the args array length, we're going to have a lot of methods that are poisonous to call from Java without the right size array. But maybe we can compromise...should we bite the bullet and try to expand the number of arities we can directly pass? |
confirmed (as @headius) noted we can not have block and block-less form at the same time for binder e.g. @JRubyMethod(name = "send", omit = true)
public static IRubyObject send(ThreadContext context, IRubyObject self, IRubyObject arg0) {
...
}
@JRubyMethod(name = "send", omit = true)
public static IRubyObject send(ThreadContext context, IRubyObject self, IRubyObject arg0, Block block) {
...
} thus exactly :
yeah - I looked at JavaMethod first but quickly realized that it already routes non-block to block (if it exists). so while I can easily fix my problem by always having block forms I'd still like to not be run down later again.
point taken (although polished for core still easy to get 'ugly' bugs in user-exts -
yep that's the case at least in interpreter as there's only |
So we could fix this but we would need to redo all those types in order to handle both. My question is which is a better long-term outcome? Maybe we do not need to address all issues today but it might be a time to redo those types (or deprecate and make a new hierarchy) if it would be nicer to just have all paths in a single hierarchy. I am just asking the question though :) |
managed to hit 2 issues while implementing over-loaded native method matching, the above case is simplified, the full case (date.rb -> RubyDate.java soon to land in a PR) looks as follows :
as mentioned in the TODO above compared to JRuby 1.7.x
9K does no longer route the (arg1, arg2, arg3) case as before
(so far this turned out to be non-critical as we only hit it with AR-JDBC and adjusted accordingly)
still it was quite annoying and ugly - not sure how much time it needs to have a proper IR instr
case addressed here is that
Date.send(:civil)
will not take the same path asDate.civil
due (native)
send
having the(ThreadContext, ..., Block)
version signature implementedthe
send(:civil)
version ends up callingcivil(context, IRubyObject self, IRubyObject[] args)
... this is something I would really like to address as its even more annoying than 1.
while I do not like the additional if+check this is the simplest change-set I can come up with
could move the check down to generated invokers (would need to generate Block forms routing block-less)
... or also implement non-block versions of
Kernel.send
andBasicObject.__send__
not sure if that will work (the populator/binding if I recall right can not handle this) but if working that should route properlyrelated invoker, so far, looks like this :
... while
JavaMethodN
(super) routessend()
(with a NULL_BLOCK) as :