Try doing the inner call from package DB:
eval {
package DB;
@ret = &$sub(@args);
};
There's a few other issues:
- You're making a copy of @_ and passing that copy, but perl passes by reference, and some code uses that (using the &$sub; form of function call fixes this)
- The way you handle $IN_TRACE means you'll never capture inner calls (like if your x() called z()).
- Your inner call is always in list context.
I played with it a bit:
package Devel::TobyLite;
use strict;
use warnings;
use Time::HiRes ();
our $IN_TRACE = 0;
sub DB::DB {}
sub DB::sub {
goto &$DB::sub if $IN_TRACE;
my $start;
my $sub = $DB::sub;
{
local $IN_TRACE = 1;
print STDERR ">> entering $sub\n";
$start = Time::HiRes::time;
}
my (@ret, $ret);
#package DB {
if (wantarray) {
no strict "refs";
eval { package DB; @ret = &$sub; };
}
elsif (defined wantarray) {
no strict "refs";
eval { package DB; $ret = &$sub; };
}
else {
no strict "refs";
eval { package DB; &$sub; };
}
#}
{
local $IN_TRACE = 1;
my $end = Time::HiRes::time();
print STDERR "<< leaving $sub ", $end - $start, "\n";
die +(caller), $@, "@_" if $@;
}
if (wantarray) {
@ret;
}
else {
$ret;
}
}
1;
Output:
$ ./perl -Ilib -I.. -d:TobyLite -e 'sub x { print qq(ok\n); } sub z {
+x() } z()'
>> entering UNIVERSAL::import
<< leaving UNIVERSAL::import 1.40666961669922e-05
>> entering main::z
>> entering main::x
ok
<< leaving main::x 3.29017639160156e-05
<< leaving main::z 8.48770141601562e-05