Skip to content

Commit

Permalink
Move private method dispatch to the dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Jun 12, 2020
1 parent 370d1c8 commit 049536c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
15 changes: 7 additions & 8 deletions src/Perl6/Optimizer.nqp
Expand Up @@ -2392,19 +2392,18 @@ class Perl6::Optimizer {
}

# If resolution didn't work out this way, and we're on the MoarVM
# backend, use a spesh plugin to help speed it up.
# backend, use a dispatcher to speed it up. Give it the package and
# name ahead of the invocant, as this makes the calling far more
# optimal.
if nqp::getcomp('Raku').backend.name eq 'moar' {
my $inv := $op.shift;
my $name := $op.shift;
my $pkg := $op.shift;
$op.unshift($inv);
$op.unshift(QAST::Op.new(
:op('speshresolve'),
QAST::SVal.new( :value('privmeth') ),
$pkg,
$name
));
$op.op('call');
$op.unshift($name_node);
$op.unshift($pkg);
$op.unshift(QAST::SVal.new( :value('raku-meth-private') ));
$op.op('dispatch');
$op.name(NQPMu);
return 1;
}
Expand Down
31 changes: 31 additions & 0 deletions src/vm/moar/dispatchers.nqp
Expand Up @@ -337,6 +337,37 @@ nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-meth-call-me-maybe',
}
});

# Private method dispatch. This is actually a fallback, since in the best
# case we can resolve the private method into a constant at code-gen time
# and just invoke that. This happens with private methods in roles.
nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-meth-private', -> $capture {
# Find the private method.
my $type := nqp::captureposarg($capture, 0);
my str $name := nqp::captureposarg_s($capture, 1);
my $meth := $type.HOW.find_private_method($type, $name);

# If it's found, then we drop the first two arguments, insert the
# resolved callee, and invoke it. This goes directly to invoke, as
# there's no deferral (due to no inheritance relationship) or multi
# dispatch for private methods.
if nqp::isconcrete($meth) {
nqp::dispatch('boot-syscall', 'dispatcher-guard-type',
nqp::dispatch('boot-syscall', 'dispatcher-track-arg', $capture, 0));
my $capture_delegate := nqp::dispatch('boot-syscall',
'dispatcher-insert-arg-literal-obj',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $capture, 0),
0),
0, $meth);
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-invoke',
$capture_delegate);
}
else {
# TODO typed exception
nqp::die("No such private method '$name' on " ~ $type.HOW.name($type));
}
});

# Resolved method call dispatcher. This is used to call a method, once we have
# already resolved it to a callee. Its first arg is the callee, the second is
# the method name (used in a continued dispatch), and the rest are the args to
Expand Down
11 changes: 0 additions & 11 deletions src/vm/moar/spesh-plugins.nqp
@@ -1,14 +1,3 @@
## Method plugins
## Only used when the name is a constant at the use site!

# Private method resolution can be specialized based on invocant type. This is
# used for speeding up resolution of private method calls in roles; those in
# classes can be resolved by static optimization.
nqp::speshreg('Raku', 'privmeth', -> $obj, str $name {
nqp::speshguardtype($obj, $obj.WHAT);
$obj.HOW.find_private_method($obj, $name)
});

## Return value decontainerization plugin

# Often we have nothing at all to do, in which case we can make it a no-op.
Expand Down

0 comments on commit 049536c

Please sign in to comment.