optimizer

 view release on metacpan or  search on metacpan

optimizer.pm  view on Meta::CPAN

}

require DynaLoader;
our $VERSION = '0.08';
our @ISA = q(DynaLoader);
our %callbacks;
bootstrap optimizer $VERSION;

my ($file, $line) = ("unknown", "unknown");

{
sub _preparewarn {
    my $args = join '', @_;
    $args = "Something's wrong " unless $args;
    $args .= " at $file line $line.\n" unless substr($args, length($args) -1) eq "\n";
}

sub _update {
    my $cop = shift; $file = $cop->file; $line = $cop->line;
}

sub _die (@) { CORE::die(preparewarn(@_)) }
sub _warn (@) { CORE::warn(preparewarn(@_)) }
}

sub import {
    my ($class,$type) = (shift, shift);
    if (!defined $type) {
        CORE::warn("Must pass an action to ${class}'s importer");
        return
    }
    if ($type eq 'C' or $type eq 'c') {
        optimizer::uninstall();
    } elsif ($type =~ /^Perl$/i) {
        optimizer::install( sub { optimizer::peepextend($_[0], sub {}) });
    } elsif ($type eq "callback" or $type eq "extend" or $type eq "mine") {
        my $subref = shift;
        croak "Supplied callback was not a subref" unless ref $subref eq "CODE";
        optimizer::install( sub { callbackoptimizer($_[0], $subref) }) if $type eq "callback";
        optimizer::install( sub { optimizer::peepextend($_[0], $subref) }) if $type eq "extend";
        optimizer::install( $subref ) if $type eq "mine";
    } elsif ($type eq 'extend-c') {
      optimizer::c_extend_install(shift);
    } elsif ($type eq 'sub-detect') {
      my ($package, $filename, $line) = caller;
      $callbacks{$package} = shift;
      optimizer::c_sub_detect_install();
    } else { croak "Unknown optimizer option '$type'"; }
}

sub unimport {
    optimizer::install(sub {callbackoptimizer($_[0], sub{})});
}

sub callbackoptimizer {
    my ($op, $callback) = @_;
    while ($$op) {
	$op->seq(optimizer::op_seqmax_inc());
        _update($op) if $op->isa("B::COP");
	# crashes: wrong op_sv, strange cv
        #_relocatetopad($op, $op->find_cv()) if $op->name eq "const"; # For thread safety

        $callback->($op);
        $op = $op->next;
        last unless $op->can("next"); # Shouldn't get here
    }
}

sub peepextend {
    # Oh boy
    my ($o, $callback) = @_;
    my $oldop = 0;

    return if !$$o or $o->seq;

    op_seqmax_inc() unless op_seqmax();
    while ($$o) {
        #warn ("Trying op $o ($$o) -> ".$o->name."\n");
        if ($o->isa("B::COP")) {
            $o->seq(optimizer::op_seqmax_inc());
            _update($o); # For warnings

        } elsif ($o->name eq "const") {
            optimizer::_die("Bareword ",$o->sv->sv, " not allowed while \"strict subs\" in use")
                if ($o->private & 8);
	    # crashes: wrong op_sv, strange cv
            #_relocatetopad($o, $o->find_cv());
            $o->seq(optimizer::op_seqmax_inc());
        } elsif ($o->name eq "concat") {
            if ($o->next && $o->next->name eq "stringify" and !($o->flags &64)) {
                if ($o->next->private & 16) {
                    $o->targ($o->next->targ);
                    $o->next->targ(0);
                }
                #$o->null;
            }
            $o->seq(optimizer::op_seqmax_inc());
        #} elsif ($o->name eq "stub") {
        #    CORE::die "Eep.";
        #} elsif ($o->name eq "null") {
        #   CORE::die "Eep.";
        } elsif ($o->name eq "scalar" or $o->name eq "lineseq" or $o->name eq "scope") {
            if ($$oldop and ${$o->next}) {
                $oldop->next($o->next);
                $o=$o->next;
                next;
            }
            $o->seq(optimizer::op_seqmax_inc());
        #} elsif ($o->name eq "gv") {
        #    CORE::die "Eep.";
        } elsif ($o->name =~ /^((map|grep)while|(and|or)(assign)?|cond_expr|range)$/) {
            $o->seq(optimizer::op_seqmax_inc());
            $o->other($o->other->next) while $o->other->name eq "null";
            peepextend($o->other, $callback); # Weee.
        } elsif ($o->name =~ /^enter(loop|iter|given|when)/) {
            $o->seq(optimizer::op_seqmax_inc());
            $o->redoop($o->redoop->next) while $o->redoop->name eq "null";
	    peepextend($o->redoop, $callback);
            $o->nextop($o->nextop->next) while $o->nextop->name eq "null";
	    peepextend($o->nextop, $callback);
            $o->lastop($o->lastop->next) while $o->lastop->name eq "null";
	    peepextend($o->lastop, $callback);
        } elsif ($o->name eq "qr" or $o->name eq "match" or $o->name eq "subst") {
            $o->seq(optimizer::op_seqmax_inc());
            $o->pmreplstart($o->pmreplstart->next)
	      while ${$o->pmreplstart} and $o->pmreplstart->name eq "null";
            peepextend($o->pmreplstart, $callback);
        } elsif ($o->name eq "exec") {
            $o->seq(optimizer::op_seqmax_inc());
            if (${$o->next} and $o->next->name eq "nextstate" and
                ${$o->next->sibling} and $o->next->sibling->type !~ /exit|warn|die/) {
                optimizer::_warn("Statement unlikely to be reached");
                optimizer::_warn("\t(Maybe you meant system() when you said exec()?)\n");
            }
        } else {
            # Screw pseudohashes.
            $o->seq(optimizer::op_seqmax_inc());
        }
        my $plop = $o;

        $callback->($o);
        $oldop = $o;
        $o = $o->next;
        last unless $o->can("next"); # Shouldn't get here
    }
}

optimizer.pm  view on Meta::CPAN


Completely implement your own optimizer. You have to provide your own walker and peep.

  use optimizer mine => sub { ... }

=item extend-c

Use the standard optimizer with an extra callback.
This is the most compatible optimizer version.

  use optimizer 'extend-c' => sub { print $_[0]->name() };

=item sub-detect

Don't provide a peep optimizer, rather get a callback
after we are finished with every code block (I<sub>).
You will be passed LEAVE* ops after the standard
peep optimizer has been run, this minimises the risk
for bugs as we use the standard one.

  use optimizer 'sub-detect' => sub { print $_[0]->name() };

=back

=head1 HELPER FUNCTIONS

=over 4

=item callbackoptimizer (this, callback)

The helper function for the option B<callback>.

=item peepextend (this, callback)

The helper function for the option B<extend>.

->import('perl') uses B<peepextend> with an empty callback.

=item c_extend_install

The helper function for the option B<extend-c>.
It uses the longish XS function C<c_extend_peep> as
experimental peeper, and calls the user-side perl callback
for each OP.

=item c_sub_detect_install

The XS helper function for the option B<sub-detect>.
It installs C<c_sub_detect> as C<PL_peep>.
B<c_sub_detect> calls all perl-side callbacks at any LEAVE op.

=item unimport

Override with an empty B<callbackoptimizer>, effectively disabling any
installed optimizer.

=back

=head1 STATUS

relocatetopad fails with threaded perls.

=head1 5.10 Changes

Since Perl 5.10 there are no op_seqmax and op_seq numbers in CORE
anymore, so we add a package global op_seqmax for the op-tree
numbering, for $B::OP::seq also. This is not thread-safe.

=head1 AUTHOR

  Simon Cozens, C<simon@cpan.org>

Extended functionality:

  Artur Bergman, C<abergman@cpan.org>

5.10 support and current maintainer Reini Urban:

  Reini Urban, C<rurban@cpan.org>

=head1 SEE ALSO

L<B::Generate>, L<optimize>

=cut



( run in 0.790 second using v1.01-cache-2.11-cpan-5511b514fd6 )