10 Sub::Op - Install subroutines as opcodes.
20 sub dl_load_flags { 0x01 }
25 push @ISA, 'DynaLoader';
26 __PACKAGE__->bootstrap($VERSION);
35 STATIC OP *scalar_util_reftype(pTHX) {
42 PUSHs(sv_reftype(SvRV(sv), 0));
48 MODULE = Scalar::Util::Ops PACKAGE = Scalar::Util::Ops
55 c.namelen = sizeof("reftype")-1;
57 c.protolen = sizeof("$")-1;
58 c.pp = scalar_util_reftype;
61 sub_op_register(aTHX_ &c, 0);
64 In your Perl module file :
66 package Scalar::Util::Ops;
73 use Sub::Op; # Before loading our own shared library
78 push @ISA, 'DynaLoader';
79 __PACKAGE__->bootstrap($VERSION);
82 sub import { Sub::Op::enable(reftype => scalar caller) }
84 sub unimport { Sub::Op::disable(reftype => scalar caller) }
88 In your F<Makefile.PL> :
90 use ExtUtils::Depends;
92 my $ed = ExtUtils::Depends->new('Scalar::Util::Ops' => 'Sub::Op');
95 $ed->get_makefile_vars,
101 This module provides a C and Perl API for replacing subroutine calls by custom opcodes.
102 This has two main advantages :
108 it gets rid of the overhead of a normal subroutine call ;
112 there's no symbol table entry defined for the subroutine.
116 Subroutine calls with and without parenthesis are handled.
117 Ampersand calls are B<not> replaced, and as such will still allow to call a subroutine with same name defined earlier.
118 This may or may not be considered as a bug, but it gives the same semantics as Perl keywords, so I believe it's reasonable.
120 When L<B> and L<B::Deparse> are loaded, they get automatically monkeypatched so that introspecting modules like L<B::Concise> and L<B::Deparse> still produce a valid output.
126 use B::Hooks::EndOfScope;
127 use Variable::Magic 0.08;
131 $placeholder = sub { require Carp; Carp::croak('PLACEHOLDER') };
132 _placeholder($placeholder);
135 my $sw = Variable::Magic::wizard(
136 data => sub { +{ guard => 0, pkg => $_[1], map => $_[2] } },
138 my ($var, $data, $name) = @_;
140 return if $data->{guard};
141 local $data->{guard} = 1;
143 return unless $data->{map}->{$name};
145 my $pkg = $data->{pkg};
146 my $fqn = join '::', $pkg, $name;
149 local $SIG{__WARN__} = sub {
150 CORE::warn(@_) unless $_[0] =~ /^Constant subroutine.*redefined/;
151 } if _constant_sub(do { no strict 'refs'; \&$fqn });
153 no warnings qw/prototype redefine/;
154 *$fqn = $placeholder;
158 my $proto = _get_prototype($name);
160 Scalar::Util::set_prototype(\&$fqn, $proto);
168 my ($pkg, $name) = @_;
170 my $fqn = join '::', $pkg, $name;
173 old => _defined_sub($fqn) ? \&$fqn : undef,
174 proto => prototype($fqn),
183 Variable::Magic::getdata(%{"${pkg}::"}, $sw);
186 defined $data ? $data->{map} : undef;
190 my ($pkg, $name) = @_;
192 my $map = { $name => _tag(@_) };
196 Variable::Magic::cast(%{"${pkg}::"}, $sw, $pkg, $map);
206 Variable::Magic::dispell(%{"${pkg}::"}, $sw);
211 =head2 C<sub_op_config_t>
213 A typedef'd struct that configures how L<Sub::Op> should handle a given subroutine name.
214 It has the following members :
222 The name of the subroutine you want to replace.
223 Allowed to be static.
229 C<name>'s length, in bytes.
235 The prototype you want to apply to the subroutine, or C<NULL> if none.
236 Allowed to be static.
242 C<proto>'s length, in bytes.
248 The pp function that will be called instead of the subroutine.
249 C<Perl_ppaddr_t> is a typedef'd function pointer defined by perl as :
251 typedef OP *(*Perl_ppaddr_t)(pTHX);
255 C<sub_op_check_t check>
257 An optional callback that will be called each time a call to C<name> is replaced.
258 You can use it to attach extra info to those ops (e.g. with a pointer table) or to perform more optimizations to the optree.
259 C<sub_op_check_t> is a typedef'd function pointer defined by :
261 typedef OP *(*sub_op_check_t)(pTHX_ OP *, void *);
267 An optional user data passed to the C<check> callback.
271 =head2 C<void sub_op_init(sub_op_config_t *c)>
273 Initializes the fields of the C<sub_op_config_t> object.
274 For future compatibility, it is required to call this function with your config object before storing your actual values.
275 It will store safe defaults for members you won't set.
277 =head2 C<void sub_op_register(pTHX_ const sub_op_config_t *c, U32 flags)>
279 Registers a name and its configuration into L<Sub::Op>.
280 The caller is responsible for allocating and freeing the C<sub_op_config_t> object.
281 No pointer to it or to its members is kept, except if you pass the flag C<SUB_OP_REGISTER_STEAL> in which case the configuration object will be stolen to be stored into L<Sub::Op>'s internal datastructure.
283 =head2 C<sub_op_config_t *sub_op_dup(pTHX_ const sub_op_config_t *orig)>
285 Deeply clones the specified C<sub_op_config_t> object.
287 =head2 C<void sub_op_free(pTHX_ sub_op_config_t *c)>
289 Free the memory associated with the specified C<sub_op_config_t> object.
293 =head2 C<enable $name, [ $pkg ]>
295 Enable the replacement with a custom opcode of calls to the C<$name> subroutine of the C<$pkg> package in the current lexical scope.
296 A pp callback must have been registered for C<$name> by calling the C function C<sub_op_register> in the XS section of your module.
298 When C<$pkg> is not set, it defaults to the caller package.
305 my $pkg = @_ > 0 ? $_[0] : caller;
306 my $map = _map($pkg);
309 $map->{$name} = _tag($pkg, $name);
311 $map = _cast($pkg, $name);
314 my $proto = $map->{$name}->{proto};
315 if (defined $proto) {
317 Scalar::Util::set_prototype(\&{"${pkg}::$name"}, undef);
321 $^H{+(__PACKAGE__)} = 1;
323 on_scope_end { disable($name, $pkg) };
328 =head2 C<disable $name, [ $pkg ]>
330 Disable the replacement for calls to C<$name> in the package C<$pkg>.
332 When C<$pkg> is not set, it defaults to the caller package.
339 my $pkg = @_ > 0 ? $_[0] : caller;
340 my $map = _map($pkg);
342 my $fqn = join '::', $pkg, $name;
345 my $tag = $map->{$name};
347 my $old = $tag->{old};
350 no warnings 'redefine';
354 my $proto = $tag->{proto};
355 if (defined $proto) {
357 Scalar::Util::set_prototype(\&$fqn, $proto);
360 delete $map->{$name};
361 unless (keys %$map) {
370 my ($pkg, $inject) = @_;
372 my $stash = do { no strict 'refs'; \%{"${pkg}::"} };
374 while (my ($meth, $code) = each %$inject) {
375 next if exists $stash->{$meth} and (*{$stash->{$meth}}{CODE} // 0) == $code;
377 *{"${pkg}::$meth"} = $code;
383 my @parts = split /::/, $fqn;
384 my $name = pop @parts;
388 return 0 unless do { no strict 'refs'; %$pkg };
390 return do { no strict 'refs'; defined &{"$pkg$name"} };
396 $injector = Variable::Magic::wizard(
397 data => sub { +{ guard => 0, pkg => $_[1], subs => $_[2] } },
399 my ($stash, $data, $key) = @_;
401 return if $data->{guard};
402 local $data->{guard} = 1;
404 _inject($data->{pkg}, $data->{subs});
414 $B_OP_inject{first} = sub {
415 if (defined _custom_name($_[0])) {
416 $_[0] = bless $_[0], 'B::UNOP' unless $_[0]->isa('B::UNOP');
417 goto $_[0]->can('first') || die 'oops';
420 Carp::confess('Calling B::OP->first for something that isn\'t a custom op');
423 $B_OP_inject{can} = sub {
424 my ($obj, $meth) = @_;
425 if ($meth eq 'first') {
426 return undef unless $obj->isa('B::UNOP') or defined _custom_name($obj);
428 $obj->SUPER::can($meth);
431 if (_defined_sub('B::OP::type')) {
432 _inject('B::OP', \%B_OP_inject);
435 Variable::Magic::cast %{'B::OP::'}, $injector, 'B::OP', \%B_OP_inject;
438 my $B_Deparse_inject = {
440 my ($self, $op, $cx) = @_;
441 my $name = _custom_name($op);
442 die 'unhandled custom op' unless defined $name;
443 if ($op->flags & do { no strict 'refs'; &{'B::OPf_STACKED'}() }) {
444 my $kid = $op->first;
445 $kid = $kid->first->sibling; # skip ex-list, pushmark
447 while (not do { no strict 'refs'; &{'B::Deparse::null'}($kid) }) {
448 push @exprs, $self->deparse($kid, 6);
449 $kid = $kid->sibling;
451 my $args = join(", ", @exprs);
452 return "$name($args)";
459 if (_defined_sub('B::Deparse::pp_entersub')) {
460 _inject('B::Deparse', $B_Deparse_inject);
463 Variable::Magic::cast %{'B::Deparse::'}, $injector, 'B::Deparse', $B_Deparse_inject;
468 BEGIN { _monkeypatch() }
472 See the F<t/Sub-Op-LexicalSub> directory that implements a complete example.
476 Preexistent definitions of a sub whose name is handled by L<Sub::Op> are restored at the end of the lexical scope in which the module is used.
477 But if you define a sub in the scope of action of L<Sub::Op> with a name that is currently being replaced, the new declaration will be obliterated at the scope end.
479 Function calls without parenthesis inside an C<eval STRING> in the scope of the pragma won't be replaced.
480 I know a few ways of fixing this, but I've not yet decided on which.
486 L<Variable::Magic>, L<B::Hooks::EndOfScope>.
488 L<ExtUtils::Depends>.
494 L<B::Hooks::XSUB::CallAsOp> provides a C API to declare XSUBs that effectively call a specific PP function.
495 Thus, it allows you to write XSUBs with the PP stack conventions used for implementing perl core keywords.
496 There's no opcode replacement and no parsing hacks.
498 L<B::Hooks::OP::Check::EntersubForCV>.
502 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
504 You can contact me by mail or on C<irc.perl.org> (vincent).
508 Please report any bugs or feature requests to C<bug-sub-op at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Sub-Op>.
509 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
513 You can find documentation for this module with the perldoc command.
517 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Sub-Op>.
519 =head1 COPYRIGHT & LICENSE
521 Copyright 2010 Vincent Pit, all rights reserved.
523 This program is free software; you can redistribute it and/or modify it
524 under the same terms as Perl itself.