Skip to content

Improve inlining of varargs path for split methods#6633

Merged
headius merged 4 commits intojruby:masterfrom
headius:split_varargs_indy_better
Mar 26, 2021
Merged

Improve inlining of varargs path for split methods#6633
headius merged 4 commits intojruby:masterfrom
headius:split_varargs_indy_better

Conversation

@headius
Copy link
Member

@headius headius commented Mar 26, 2021

When we generate the invoker class for arity-split methods, we
only generate overrides of (DynamicMethod subtype) JavaMethod.call
signatures that align with the split signatures, including whether
or not they receive a block. This allows the base JavaMethod to
maintain a minimal set of base implementations, with unimplemented
arities and block paths falling back on default implementations.

Unfortunately due to our indy dispatch logic only being smart
enough to directly bind the lowest specific arity, this can break
inlining for all other arities if the block/no-block signatures
do not match, falling back on the base implementations in
JavaMethod.

This patch improves the "generic" DynamicMethod.call binding to
avoid passing a block when the target methods is backed by a
direct native handle and that handle wants a block. Because we
only allow homogeneous block/no-block signatures for arity-split
methods, omitting the block allows inlining straight through the
JavaMethod invoker even when calling the other arities.

@headius
Copy link
Member Author

headius commented Mar 26, 2021

This improves the performance of the dig benchmark in #6628 even more: #6628 (comment)

But I am seeing some peculiar errors locally I will need to investigate before this is merged:

$ jruby -Xcompile.invokedynamic -J-XX:+UseParallelGC -X+C -Xjit.threshold=0 -Xfixnum.cache=false bench_dig.rb 
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/scanf-1.0.0.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/io-console-0.5.9-java.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/ipaddr-1.2.0.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/jar-dependencies-0.4.1.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/racc-1.5.2-java.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/fileutils-1.1.0.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/jruby-readline-1.3.7-java.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/cmath-1.0.0.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/rake-ant-1.0.4.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/json-2.5.1-java.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/rdoc-6.1.2.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/jruby-openssl-0.10.5-java.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/csv-1.0.0.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/default/webrick-1.6.1.gemspec]: wrong number of arguments (given 1, expected 0)
Invalid gemspec in [/Users/headius/projects/jruby-9.2/lib/ruby/gems/shared/specifications/did_you_mean-1.2.0.gemspec]: wrong number of arguments (given 1, expected 0)

@headius headius marked this pull request as draft March 26, 2021 06:20
@headius headius force-pushed the split_varargs_indy_better branch from e19b533 to 0ceb25e Compare March 26, 2021 06:53
@headius
Copy link
Member Author

headius commented Mar 26, 2021

Silly bug in my original code. Worrisome that it was not picked up by testing. 🤔

This is fine now.

@headius headius marked this pull request as ready for review March 26, 2021 07:14
@headius headius force-pushed the split_varargs_indy_better branch 2 times, most recently from 2e87c61 to 557e713 Compare March 26, 2021 08:30
@headius
Copy link
Member Author

headius commented Mar 26, 2021

Rebasing on master to reduce risk for 9.2.x.

@headius headius changed the base branch from jruby-9.2 to master March 26, 2021 21:23
headius added 4 commits March 26, 2021 16:30
When we generate the invoker class for arity-split methods, we
only generate overrides of (DynamicMethod subtype) JavaMethod.call
signatures that align with the split signatures, including whether
or not they receive a block. This allows the base JavaMethod to
maintain a minimal set of base implementations, with unimplemented
arities and block paths falling back on default implementations.

Unfortunately due to our indy dispatch logic only being smart
enough to directly bind the lowest specific arity, this can break
inlining for all other arities if the block/no-block signatures
do not match, falling back on the base implementations in
JavaMethod.

This patch improves the "generic" DynamicMethod.call binding to
avoid passing a block when the target methods is backed by a
direct native handle and that handle wants a block. Because we
only allow homogeneous block/no-block signatures for arity-split
methods, omitting the block allows inlining straight through the
JavaMethod invoker even when calling the other arities.
I will do some separate work to reduce or eliminate null
NativeCall from methods that implement NativeCallMethod.
Since compiled Ruby bodies always receive block, this will mostly
help native method_missing impls that do not receive block
(for example, our Java package modules.
@headius headius force-pushed the split_varargs_indy_better branch from 588efc9 to 13153a9 Compare March 26, 2021 21:41
@headius headius merged commit 1a84b7f into jruby:master Mar 26, 2021
@headius headius deleted the split_varargs_indy_better branch March 26, 2021 22:06
@headius headius modified the milestones: JRuby 9.2.17.0, JRuby 9.3.0.0 Mar 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant