Skip to content

Commit

Permalink
Optimize method calls made on roles
Browse files Browse the repository at this point in the history
We can pre-calculate and cache the pun in the callsite, rewriting the
call capture in the dispatcher to include it. This means that calls to
methods on a role (typically `.new`, which relies on punning) will now
no longer need to slurp/flatten arguments, will avoid an extra level of
invocation, and expose the target method in the pun for spesh linking
and/or inlining.
  • Loading branch information
jnthn committed Sep 6, 2021
1 parent 811bcc5 commit 3a35149
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/Perl6/Metamodel/RolePunning.nqp
Expand Up @@ -73,6 +73,10 @@ role Perl6::Metamodel::RolePunning {
$!pun."$name"(|@pos, |%named)
}
}

method is_method_call_punned($obj, $name) {
!nqp::existskey(%exceptions, $name)
}
}

# vim: expandtab sw=4
22 changes: 17 additions & 5 deletions src/vm/moar/dispatchers.nqp
Expand Up @@ -625,17 +625,29 @@ nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-call', -> $capture {
# the method name, and the the args (starting with the invocant including any
# container).
nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-meth-call', -> $capture {
# See if we're making the method lookup on a pun; if so, rewrite the args
# to do the call on the pun.
my $obj := nqp::captureposarg($capture, 0);
my str $name := nqp::captureposarg_s($capture, 1);
my $how := nqp::how_nd($obj);
if nqp::istype($how, Perl6::Metamodel::RolePunning) &&
$how.is_method_call_punned($obj, $name) {
$obj := $how.pun($obj);
$how := $obj.HOW;
$capture := nqp::dispatch('boot-syscall', 'dispatcher-insert-arg-literal-obj',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 0),
0, $obj);
$capture := nqp::dispatch('boot-syscall', 'dispatcher-insert-arg-literal-obj',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 2),
2, $obj);
}

# Try to resolve the method call.
# TODO Assorted optimizations are possible here later on to speed up some
# kinds of dispatch, including:
# * Using the dispatcher to directly rewrite args and invoke FALLBACK if
# needed
# * Rewriting the args to use a formed role pun, thus caching the lookup
# of the pun and an extra level of call
# * Handling some forms of delegation via the dispatcher mechanism
my $obj := nqp::captureposarg($capture, 0);
my str $name := nqp::captureposarg_s($capture, 1);
my $how := nqp::how_nd($obj);
my $meth := nqp::decont($how.find_method($obj, $name));

# Report an error if there is no such method.
Expand Down

0 comments on commit 3a35149

Please sign in to comment.