[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-modperl
Subject:    Re: getting rid of nested sub lexical problem
From:       Chris Nokleberg <cjn () rock ! pickem ! com>
Date:       2000-12-30 10:08:30
[Download RAW message or body]

On Thu, 21 Dec 2000, Doug MacEachern wrote:

> On Thu, 19 Oct 2000, Chris Nokleberg wrote:
> 
> > Following up on my post on this subject a couple of months ago, here is a
> > proof-of-concept drop-in replacement for Apache::Registry that eliminates
> > the "my() Scoped Variable in Nested Subroutine" problem.
> 
> nice hack!
>  
> > It requires PERL5OPT = "-d" and PERL5DB = "sub DB::DB {}" environment
> > variables set when starting the mod_perl-enabled httpd. This enables the
> > %DB::sub hash table that holds subroutine start and end line info. I
> > presume that this has some negative (marginal?) impact on performance. If
> > someone knows of a better way to reliably figure out where a subroutine
> > starts and ends, please let me know.
> 
> there is quite a bit of overhead when -d is enabled.  have a look at
> Apache::DB.xs, there's in init_debugger() function todo what -d does.  if
> another method was added to turn it off, after the registry script was
> compiled, the overhead would be reduced a great deal.

oooh, cool. I've added this to Apache::DB.xs:

int
stop_debugger()

    CODE:
    if (PL_perldb) {
        PL_perldb = 0;
        RETVAL = TRUE;
    }
    else
        RETVAL = FALSE;

    OUTPUT:
    RETVAL


It appears that setting PL_perldb to zero is all that's required to turn
off the debugger! I thought I might have to fiddle with the symbol tables
but this seems to work.

I've attached the latest version of Apache::NiceRegistry (suggestions
welcome) below. Not sure this is the right thing to do , but I call
Apache::DB::init_debugger directly because I need the return value (don't
want to stop_debugger if it was turned on outside of this handler), and I
don't want the warning that Apache::DB->init produces.

Also, why does Apache::DB unset $Apache::Registry::MarkLine?

Thanks,
Chris

--------------------------------------

package Apache::NiceRegistry;

use base Apache::RegistryNG;
use strict;
use Apache::DB ();

$Apache::Registry::MarkLine = 1;

my %skip_subs = map { $_ => 1 } qw( handler BEGIN END CHECK INIT );

sub compile {
    my ($pr, $eval) = @_;
    $eval ||= $pr->{'sub'};

    my $init_db = Apache::DB::init_debugger();
    $pr->SUPER::compile($eval);
    Apache::DB::stop_debugger() if $init_db;

    my $package = $pr->namespace;
    my @lines = split /\n/, $$eval;

    foreach my $sub (grep /^$\Qpackage\E/, keys %DB::sub) {
        my ($name) = $sub =~ /:([^:]+)$/;
        next if $skip_subs{$name};

        my ($start, $end) = $DB::sub{$sub} =~ /:(\d+)-(\d+)$/;
        $lines[$start + 1] =~ s:(sub[^\{]+\{):$1&\{sub\{:;
        $lines[$end + 1]   =~ s:\}(?!.*\})$:\}\}\}:;
    }

    $$eval = join "\n", @lines;
    $pr->flush_namespace($package);
    $pr->SUPER::compile($eval);
}

1;

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic