Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -6305,6 +6305,7 @@ t/op/cproto.t Check builtin prototypes
t/op/crypt.t See if crypt works
t/op/current_sub.t __SUB__ tests
t/op/dbm.t See if dbmopen/dbmclose work
t/op/debug.t Test mechanisms used by the debugger
t/op/decl-refs.t See if my \$foo works
t/op/defer.t See if defer blocks work
t/op/defined.t See if defined() edge cases work
Expand Down
11 changes: 10 additions & 1 deletion pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,16 @@ manager will later use a regex to expand these into links.

=item *

XXX
In some cases an C<eval> would not add integer parts to the source
lines saved by the debugger. [GH #23151]

=item *

Save debugger lines as C<PVIV> SVs rather than as C<PVMG> SVs as they
don't need magic, aren't blessed and don't need to store a floating
point part. This should save 24 bytes per stored line for 64-bit
systems, more for C<-Duselongdouble> or C<-Dusequadmath> builds.
Discussed in [GH #23171].

=back

Expand Down
5 changes: 4 additions & 1 deletion pp_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3735,7 +3735,7 @@ S_save_lines(pTHX_ AV *array, SV *sv)

while (s && s < send) {
const char *t;
SV * const tmpstr = newSV_type(SVt_PVMG);
SV * const tmpstr = newSV_type(SVt_PVIV);

t = (const char *)memchr(s, '\n', send - s);
if (t)
Expand All @@ -3744,6 +3744,9 @@ S_save_lines(pTHX_ AV *array, SV *sv)
t = send;

sv_setpvn_fresh(tmpstr, s, t - s);
/* not breakable until we compile a COP for it */
SvIV_set(tmpstr, 0);
SvIOK_on(tmpstr);
av_store(array, line++, tmpstr);
s = t;
}
Expand Down
124 changes: 124 additions & 0 deletions t/op/debug.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!./perl

# intended for testing language mechanisms that debuggers use not for
# testing the debugger itself

BEGIN {
chdir 't' if -d 't';
require "./test.pl";
set_up_inc( qw(. ../lib) );
}

use strict;
use warnings;

SKIP:
{
skip_if_miniperl("need XS", 1);
# github 23151
# trivial debugger
local $ENV{PERL5DB} = 'sub DB::DB {}';
# eval code trimmed from code generated by Sub::Quote
fresh_perl_is(<<'CODE', <<'EXPECT',
use B qw(SVf_IOK);

sub _do_eval {
eval $_[0] or die $!;
}

_do_eval(<<'EVAL');
{
sub table {
}
}
1;
EVAL

# look for lines that don't have an IV set
my ($f) = grep /\(eval/, keys %::;
my $x = $::{$f};
my $lineno = 0;
for my $l (@$x) {
if ($l) {
my $b = B::svref_2object(\$l);
if (!($b->FLAGS & SVf_IOK)) {
print "No IV for $f line $lineno: $l\n";
last
}
}
++$lineno;
}

print "Done\n";
CODE
Done
EXPECT
{
switches => [ '-d' ],
stderr => 1,
},
"saved lines all have an IV"
);
}

SKIP:
{
# Historically lines were stored as PVMG, but we don't need
# magic on these lines.
#
# This checks that none of these lines get upgraded, ie. that
# we don't need them to be PVMG
#
# If this test fails perhaps we do need to make them PVMG
# and toke.c:S_update_debugger_info and pp_ctl.c:S_save_lines
# can be switched back to using SVt_PVMG and this test
# removed.
#
# See https://github.com/Perl/perl5/pull/23171#issuecomment-2780007725
skip_if_miniperl("need B");
local $ENV{PERL5DB} = 'sub DB::DB {}';
fresh_perl_is(<<'CODE', <<'EXPECT',
use B;

sub _do_eval {
eval $_[0] or die $!;
}

_do_eval(<<'EVAL');

sub some_code {
print "Hello";
}

1;
EVAL

# check if any lines have been upgraded from PVIV
my @files = grep /^_</, keys %::;
for my $f (@files) {
my $lineno = 0;

for my $l (@{$f}) {
if ($l) {
my $b = B::svref_2object(\$l);
if (ref $b ne "B::PVIV") {
print "Not PVIV for $f:$lineno: $l\n";
last
}
}
++$lineno;
}
}
print "Done\n";
CODE
Done
EXPECT
{
switches => [ '-d' ],
stderr => 1,
},
"saved lines are all PVIV"
);
}

done_testing();
5 changes: 3 additions & 2 deletions toke.c
Original file line number Diff line number Diff line change
Expand Up @@ -2012,10 +2012,11 @@ S_update_debugger_info(pTHX_ SV *orig_sv, const char *const buf, STRLEN len)
AV *av = CopFILEAVx(PL_curcop);
if (av) {
SV * sv;
if (PL_parser->preambling == NOLINE) sv = newSV_type(SVt_PVMG);
if (PL_parser->preambling == NOLINE)
sv = newSV_type(SVt_PVIV);
else {
sv = *av_fetch(av, 0, 1);
SvUPGRADE(sv, SVt_PVMG);
SvUPGRADE(sv, SVt_PVIV);
}
if (!SvPOK(sv)) SvPVCLEAR(sv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unroll SvUPGRADE(), add {} to SvPVCLEAR(sv);, add 2 goto skipping if(!SvPOK(sv)) test and jump right into the branch, if was < SVt_PV or we did a newSV_type(SVt_PVIV);. We know the SV* is undef and/or doesn't have POK_on, so we can skip the if(!SvPOK(sv)) conditional jump CPU opcode/opcodes.

if (orig_sv)
Expand Down
Loading