diff --git a/inline.h b/inline.h index 80a7b76878..6e3efedee6 100644 --- a/inline.h +++ b/inline.h @@ -1040,9 +1040,9 @@ Indicates whether the stacked SV C (assumed to be not yet popped off the stack) is only kept alive due to a single reference from the argument stack and/or and the temps stack. -This can used for example to decide whether the copying of return values in rvalue -context can be skipped, or whether it shouldn't be assigned to in lvalue -context. +This can used for example to decide whether the copying of return values +in rvalue context can be skipped, or whether it shouldn't be assigned to +in lvalue context. =cut */ @@ -1063,6 +1063,7 @@ Perl_rpp_is_lone(pTHX_ SV *sv) return SvREFCNT(sv) <= cBOOL(SvTEMP(sv)) #ifdef PERL_RC_STACK + 1 + && !SvIMMORTAL(sv) /* PL_sv_undef etc are never stealable */ #endif ; } diff --git a/sv.h b/sv.h index 2cd4ea2593..53b310eac3 100644 --- a/sv.h +++ b/sv.h @@ -2415,7 +2415,17 @@ that already have a PV buffer allocated, but no SvTHINKFIRST. #ifdef DEBUGGING /* exercise the immortal resurrection code in sv_free2() */ -# define SvREFCNT_IMMORTAL 1000 +# ifdef PERL_RC_STACK + /* When the stack is ref-counted, the code tends to take a lot of + * short cuts with immortals, such as skipping the bump of the ref + * count of PL_sv_undef when pushing it on the stack. Exercise that + * this doesn't cause problems, especially on code which + * special-cases RC==1 etc. + */ +# define SvREFCNT_IMMORTAL 10 +# else +# define SvREFCNT_IMMORTAL 1000 +# endif #else # define SvREFCNT_IMMORTAL ((~(U32)0)/2) #endif diff --git a/t/op/hash.t b/t/op/hash.t index 0ad4890824..ee4ff903df 100644 --- a/t/op/hash.t +++ b/t/op/hash.t @@ -259,6 +259,27 @@ package Magic { ::is(join( ':', %inner), "x:y", "magic keys"); } +# Make sure PL_sv_undef is copied, and not stored directly, when assigning +# to a hash. This failed on DEBUGGING + PERL_RC_STACK builds because the +# test for a lone SV assumed that an SV on the stack with a ref count of 1 +# could be used directly rather than copied. However, PL_sv_undef and +# friends could reach a ref count of 1 but still not be stealable. +# +# A DEBUGGING build sets the initial ref count of the immortals to 1000 +# rather than I32_MAX, making such problems easier to reproduce. + +{ + my $bad = 0; + for (1..1001) { + # Each iteration may leave the RC of PL_sv_undef one lower. + my %h = ('a', undef); + # this could fail with + # "Modification of non-creatable hash value attempted ..." + eval { $h{a} = 1; }; + $bad = 1 if $@ ne ""; + } + ok(!$bad, "PL_sv_undef RC 1"); +} done_testing();