{
PERL_ARGS_ASSERT_SV_SETUV;
- /* With these two if statements:
+ /* With the if statement to ensure that integers are stored as IVs whenever
+ possible:
u=1.49 s=0.52 cu=72.49 cs=10.64 scripts=270 tests=20865
without
u=1.35 s=0.47 cu=73.45 cs=11.43 scripts=270 tests=20865
- If you wish to remove them, please benchmark to see what the effect is
+ If you wish to remove the following if statement, so that this routine
+ (and its callers) always return UVs, please benchmark to see what the
+ effect is. Modern CPUs may be different. Or may not :-)
*/
if (u <= (UV)IV_MAX) {
sv_setiv(sv, (IV)u);
if (!referent) {
len = 7;
retval = buffer = savepvn("NULLREF", len);
- } else if (SvTYPE(referent) == SVt_REGEXP) {
+ } else if (SvTYPE(referent) == SVt_REGEXP && (
+ !(PL_curcop->cop_hints & HINT_NO_AMAGIC)
+ || amagic_is_enabled(string_amg)
+ )) {
REGEXP * const re = (REGEXP *)MUTABLE_PTR(referent);
I32 seen_evals = 0;
*/
char *
-Perl_sv_2pvbyte(pTHX_ register SV *const sv, STRLEN *const lp)
+Perl_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *const lp)
{
PERL_ARGS_ASSERT_SV_2PVBYTE;
- SvGETMAGIC(sv);
+ if ((SvTHINKFIRST(sv) && !SvIsCOW(sv)) || isGV_with_GP(sv)) {
+ SV *sv2 = sv_newmortal();
+ sv_copypv(sv2,sv);
+ sv = sv2;
+ }
+ else SvGETMAGIC(sv);
sv_utf8_downgrade(sv,0);
return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv);
}
*/
char *
-Perl_sv_2pvutf8(pTHX_ register SV *const sv, STRLEN *const lp)
+Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *const lp)
{
PERL_ARGS_ASSERT_SV_2PVUTF8;
+ if ((SvTHINKFIRST(sv) && !SvIsCOW(sv)) || isGV_with_GP(sv))
+ sv = sv_mortalcopy(sv);
sv_utf8_upgrade(sv);
- return lp ? SvPV(sv,*lp) : SvPV_nolen(sv);
+ if (SvGMAGICAL(sv)) SvFLAGS(sv) &= ~SVf_POK;
+ assert(SvPOKp(sv));
+ return lp ? SvPV_nomg(sv,*lp) : SvPV_nomg_nolen(sv);
}
{
PERL_ARGS_ASSERT_SV_UTF8_ENCODE;
- if (SvIsCOW(sv)) {
- sv_force_normal_flags(sv, 0);
- }
if (SvREADONLY(sv)) {
- Perl_croak_no_modify(aTHX);
+ sv_force_normal_flags(sv, 0);
}
(void) sv_utf8_upgrade(sv);
SvUTF8_off(sv);
* we want to make sure everything inside is valid utf8 first.
*/
c = start = (const U8 *) SvPVX_const(sv);
- if (!is_utf8_string(c, SvCUR(sv)+1))
+ if (!is_utf8_string(c, SvCUR(sv)))
return FALSE;
e = (const U8 *) SvEND(sv);
while (c < e) {
{
const char * const type = sv_reftype(sstr,0);
if (PL_op)
+ /* diag_listed_as: Bizarre copy of %s */
Perl_croak(aTHX_ "Bizarre copy of %s in %s", type, OP_DESC(PL_op));
else
Perl_croak(aTHX_ "Bizarre copy of %s", type);
/* len is STRLEN which is unsigned, need to copy to signed */
const IV iv = len;
if (iv < 0)
- Perl_croak(aTHX_ "panic: sv_setpvn called with negative strlen");
+ Perl_croak(aTHX_ "panic: sv_setpvn called with negative strlen %"
+ IVdf, iv);
}
SvUPGRADE(sv, SVt_PV);
}
#else
if (SvREADONLY(sv)) {
- if (SvFAKE(sv) && !isGV_with_GP(sv)) {
+ if (SvIsCOW(sv)) {
const char * const pvx = SvPVX_const(sv);
const STRLEN len = SvCUR(sv);
SvFAKE_off(sv);
if (SvREADONLY(sv)) {
if (
/* its okay to attach magic to shared strings */
- (!SvFAKE(sv) || isGV_with_GP(sv))
+ !SvIsCOW(sv)
&& IN_PERL_RUNTIME
&& !PERL_MAGIC_TYPE_READONLY_ACCEPTABLE(how)
if (SvOOK(tsv))
svp = (SV**)Perl_hv_backreferences_p(aTHX_ MUTABLE_HV(tsv));
}
+ else if (SvIS_FREED(tsv) && PL_phase == PERL_PHASE_DESTRUCT) {
+ /* It's possible for the the last (strong) reference to tsv to have
+ become freed *before* the last thing holding a weak reference.
+ If both survive longer than the backreferences array, then when
+ the referent's reference count drops to 0 and it is freed, it's
+ not able to chase the backreferences, so they aren't NULLed.
+
+ For example, a CV holds a weak reference to its stash. If both the
+ CV and the stash survive longer than the backreferences array,
+ and the CV gets picked for the SvBREAK() treatment first,
+ *and* it turns out that the stash is only being kept alive because
+ of an our variable in the pad of the CV, then midway during CV
+ destruction the stash gets freed, but CvSTASH() isn't set to NULL.
+ It ends up pointing to the freed HV. Hence it's chased in here, and
+ if this block wasn't here, it would hit the !svp panic just below.
+
+ I don't believe that "better" destruction ordering is going to help
+ here - during global destruction there's always going to be the
+ chance that something goes out of order. We've tried to make it
+ foolproof before, and it only resulted in evolutionary pressure on
+ fools. Which made us look foolish for our hubris. :-(
+ */
+ return;
+ }
else {
MAGIC *const mg
= SvMAGICAL(tsv) ? mg_find(tsv, PERL_MAGIC_backref) : NULL;
svp = mg ? &(mg->mg_obj) : NULL;
}
- if (!svp || !*svp)
- Perl_croak(aTHX_ "panic: del_backref");
+ if (!svp)
+ Perl_croak(aTHX_ "panic: del_backref, svp=0");
+ if (!*svp) {
+ /* It's possible that sv is being freed recursively part way through the
+ freeing of tsv. If this happens, the backreferences array of tsv has
+ already been freed, and so svp will be NULL. If this is the case,
+ we should not panic. Instead, nothing needs doing, so return. */
+ if (PL_phase == PERL_PHASE_DESTRUCT && SvREFCNT(tsv) == 0)
+ return;
+ Perl_croak(aTHX_ "panic: del_backref, *svp=%p phase=%s refcnt=%" UVuf,
+ *svp, PL_phase_names[PL_phase], (UV)SvREFCNT(tsv));
+ }
if (SvTYPE(*svp) == SVt_PVAV) {
#ifdef DEBUGGING
assert(count ==1);
AvFILLp(av) = fill-1;
}
+ else if (SvIS_FREED(*svp) && PL_phase == PERL_PHASE_DESTRUCT) {
+ /* freed AV; skip */
+ }
else {
/* optimisation: only a single backref, stored directly */
if (*svp != sv)
- Perl_croak(aTHX_ "panic: del_backref");
+ Perl_croak(aTHX_ "panic: del_backref, *svp=%p, sv=%p", *svp, sv);
*svp = NULL;
}
PERL_ARGS_ASSERT_SV_INSERT_FLAGS;
if (!bigstr)
- Perl_croak(aTHX_ "Can't modify non-existent substring");
+ Perl_croak(aTHX_ "Can't modify nonexistent substring");
SvPV_force_flags(bigstr, curlen, flags);
(void)SvPOK_only_UTF8(bigstr);
if (offset + len > curlen) {
bigend = big + SvCUR(bigstr);
if (midend > bigend)
- Perl_croak(aTHX_ "panic: sv_insert");
+ Perl_croak(aTHX_ "panic: sv_insert, midend=%p, bigend=%p",
+ midend, bigend);
if (mid - big > bigend - midend) { /* faster to shorten from end */
if (littlelen) {
Safefree(IoTOP_NAME(sv));
Safefree(IoFMT_NAME(sv));
Safefree(IoBOTTOM_NAME(sv));
+ if ((const GV *)sv == PL_statgv)
+ PL_statgv = NULL;
goto freescalar;
case SVt_REGEXP:
/* FIXME for plugins */
SvSTASH(sv) = (HV*)iter_sv;
iter_sv = sv;
- /* XXX ideally we should save the old value of hash_index
- * too, but I can't think of any place to hide it. The
- * effect of not saving it is that for freeing hashes of
- * hashes, we become quadratic in scanning the HvARRAY of
- * the top hash looking for new entries to free; but
- * hopefully this will be dwarfed by the freeing of all
- * the nested hashes. */
+ /* save old hash_index in unused SvMAGIC field */
+ assert(!SvMAGICAL(sv));
+ assert(!SvMAGIC(sv));
+ ((XPVMG*) SvANY(sv))->xmg_u.xmg_hash_index = hash_index;
hash_index = 0;
+
next_sv = Perl_hfree_next_entry(aTHX_ (HV*)sv, &hash_index);
goto get_next_sv; /* process this new sv */
}
/* See also S_sv_unglob, which does the same thing. */
if ((const GV *)sv == PL_last_in_gv)
PL_last_in_gv = NULL;
+ else if ((const GV *)sv == PL_statgv)
+ PL_statgv = NULL;
case SVt_PVMG:
case SVt_PVNV:
case SVt_PVIV:
&& !(SvTYPE(sv) == SVt_PVIO
&& !(IoFLAGS(sv) & IOf_FAKE_DIRP)))
Safefree(SvPVX_mutable(sv));
- else if (SvPVX_const(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
+ else if (SvPVX_const(sv) && SvIsCOW(sv)) {
unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
SvFAKE_off(sv);
}
/* no more elements of current HV to free */
sv = iter_sv;
type = SvTYPE(sv);
- /* Restore previous value of iter_sv, squirrelled away */
+ /* Restore previous values of iter_sv and hash_index,
+ * squirrelled away */
assert(!SvOBJECT(sv));
iter_sv = (SV*)SvSTASH(sv);
-
- /* ideally we should restore the old hash_index here,
- * but we don't currently save the old value */
- hash_index = 0;
+ assert(!SvMAGICAL(sv));
+ hash_index = ((XPVMG*) SvANY(sv))->xmg_u.xmg_hash_index;
/* free any remaining detritus from the hash struct */
Perl_hv_undef_flags(aTHX_ MUTABLE_HV(sv), HV_NAME_SETALL);
s = (const U8*)SvPV_const(sv, blen);
if (blen < byte)
- Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset");
+ Perl_croak(aTHX_ "panic: sv_pos_b2u: bad byte offset, blen=%"UVuf
+ ", byte=%"UVuf, (UV)blen, (UV)byte);
send = s + byte;
const NV was = SvNVX(sv);
if (NV_OVERFLOWS_INTEGERS_AT &&
was >= NV_OVERFLOWS_INTEGERS_AT) {
+ /* diag_listed_as: Lost precision when %s %f by 1 */
Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
"Lost precision when incrementing %" NVff " by 1",
was);
const NV was = SvNVX(sv);
if (NV_OVERFLOWS_INTEGERS_AT &&
was <= -NV_OVERFLOWS_INTEGERS_AT) {
+ /* diag_listed_as: Lost precision when %s %f by 1 */
Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
"Lost precision when decrementing %" NVff " by 1",
was);
/*
=for apidoc newSVpvn
-Creates a new SV and copies a string into it. The reference count for the
-SV is set to 1. Note that if C<len> is zero, Perl will create a zero length
-string. You are responsible for ensuring that the source string is at least
-C<len> bytes long. If the C<s> argument is NULL the new SV will be undefined.
+Creates a new SV and copies a buffer into it, which may contain NUL characters
+(C<\0>) and other binary data. The reference count for the SV is set to 1.
+Note that if C<len> is zero, Perl will create a zero length (Perl) string. You
+are responsible for ensuring that the source buffer is at least
+C<len> bytes long. If the C<buffer> argument is NULL the new SV will be
+undefined.
=cut
*/
SV *
-Perl_newSVpvn(pTHX_ const char *const s, const STRLEN len)
+Perl_newSVpvn(pTHX_ const char *const buffer, const STRLEN len)
{
dVAR;
register SV *sv;
new_SV(sv);
- sv_setpvn(sv,s,len);
+ sv_setpvn(sv,buffer,len);
return sv;
}
if ((const GV *)sv == PL_last_in_gv)
PL_last_in_gv = NULL;
+ else if ((const GV *)sv == PL_statgv)
+ PL_statgv = NULL;
}
/*
}
}
else
- sv_setuv_mg(argsv, (UV)i);
+ sv_setuv_mg(argsv, has_utf8 ? (UV)sv_len_utf8(sv) : (UV)i);
continue; /* not "break" */
/* UNKNOWN */
return dstr;
}
}
+ else if (SvTYPE(sstr) == SVt_PVGV && !SvFAKE(sstr)) {
+ HV *stash = GvSTASH(sstr);
+ const HEK * hvname;
+ if (stash && (hvname = HvNAME_HEK(stash))) {
+ /** don't clone GVs if they already exist **/
+ SV **svp;
+ stash = gv_stashpvn(HEK_KEY(hvname), HEK_LEN(hvname),
+ HEK_UTF8(hvname) ? SVf_UTF8 : 0);
+ svp = hv_fetch(
+ stash, GvNAME(sstr),
+ GvNAMEUTF8(sstr)
+ ? -GvNAMELEN(sstr)
+ : GvNAMELEN(sstr),
+ 0
+ );
+ if (svp && *svp && SvTYPE(*svp) == SVt_PVGV) {
+ ptr_table_store(PL_ptr_table, sstr, *svp);
+ return *svp;
+ }
+ }
+ }
}
/* create anew and remember what it is */
ncx->blk_eval.old_namesv = sv_dup_inc(ncx->blk_eval.old_namesv,
param);
ncx->blk_eval.cur_text = sv_dup(ncx->blk_eval.cur_text, param);
+ ncx->blk_eval.cv = cv_dup(ncx->blk_eval.cv, param);
break;
case CXt_LOOP_LAZYSV:
ncx->blk_loop.state_u.lazysv.end
break;
case CXt_BLOCK:
case CXt_NULL:
+ case CXt_WHEN:
+ case CXt_GIVEN:
break;
}
}
PL_in_clean_objs = proto_perl->Iin_clean_objs;
PL_in_clean_all = proto_perl->Iin_clean_all;
- PL_uid = proto_perl->Iuid;
- PL_euid = proto_perl->Ieuid;
- PL_gid = proto_perl->Igid;
- PL_egid = proto_perl->Iegid;
+ PL_delaymagic_uid = proto_perl->Idelaymagic_uid;
+ PL_delaymagic_euid = proto_perl->Idelaymagic_euid;
+ PL_delaymagic_gid = proto_perl->Idelaymagic_gid;
+ PL_delaymagic_egid = proto_perl->Idelaymagic_egid;
PL_nomemok = proto_perl->Inomemok;
PL_an = proto_perl->Ian;
PL_evalseq = proto_perl->Ievalseq;
PL_globhook = proto_perl->Iglobhook;
-#ifdef THREADS_HAVE_PIDS
- PL_ppid = proto_perl->Ippid;
-#endif
-
/* swatch cache */
PL_last_swash_hv = NULL; /* reinits on demand */
PL_last_swash_klen = 0;
PL_numeric_radix_sv = sv_dup_inc(proto_perl->Inumeric_radix_sv, param);
#endif /* !USE_LOCALE_NUMERIC */
- /* utf8 character classes */
+ /* Unicode inversion lists */
+ PL_ASCII = sv_dup_inc(proto_perl->IASCII, param);
+ PL_Latin1 = sv_dup_inc(proto_perl->ILatin1, param);
+
+ PL_PerlSpace = sv_dup_inc(proto_perl->IPerlSpace, param);
+ PL_XPerlSpace = sv_dup_inc(proto_perl->IXPerlSpace, param);
+
+ PL_L1PosixAlnum = sv_dup_inc(proto_perl->IL1PosixAlnum, param);
+ PL_PosixAlnum = sv_dup_inc(proto_perl->IPosixAlnum, param);
+
+ PL_L1PosixAlpha = sv_dup_inc(proto_perl->IL1PosixAlpha, param);
+ PL_PosixAlpha = sv_dup_inc(proto_perl->IPosixAlpha, param);
+
+ PL_PosixBlank = sv_dup_inc(proto_perl->IPosixBlank, param);
+ PL_XPosixBlank = sv_dup_inc(proto_perl->IXPosixBlank, param);
+
+ PL_L1Cased = sv_dup_inc(proto_perl->IL1Cased, param);
+
+ PL_PosixCntrl = sv_dup_inc(proto_perl->IPosixCntrl, param);
+ PL_XPosixCntrl = sv_dup_inc(proto_perl->IXPosixCntrl, param);
+
+ PL_PosixDigit = sv_dup_inc(proto_perl->IPosixDigit, param);
+
+ PL_L1PosixGraph = sv_dup_inc(proto_perl->IL1PosixGraph, param);
+ PL_PosixGraph = sv_dup_inc(proto_perl->IPosixGraph, param);
+
+ PL_L1PosixLower = sv_dup_inc(proto_perl->IL1PosixLower, param);
+ PL_PosixLower = sv_dup_inc(proto_perl->IPosixLower, param);
+
+ PL_L1PosixPrint = sv_dup_inc(proto_perl->IL1PosixPrint, param);
+ PL_PosixPrint = sv_dup_inc(proto_perl->IPosixPrint, param);
+
+ PL_L1PosixPunct = sv_dup_inc(proto_perl->IL1PosixPunct, param);
+ PL_PosixPunct = sv_dup_inc(proto_perl->IPosixPunct, param);
+
+ PL_PosixSpace = sv_dup_inc(proto_perl->IPosixSpace, param);
+ PL_XPosixSpace = sv_dup_inc(proto_perl->IXPosixSpace, param);
+
+ PL_L1PosixUpper = sv_dup_inc(proto_perl->IL1PosixUpper, param);
+ PL_PosixUpper = sv_dup_inc(proto_perl->IPosixUpper, param);
+
+ PL_L1PosixWord = sv_dup_inc(proto_perl->IL1PosixWord, param);
+ PL_PosixWord = sv_dup_inc(proto_perl->IPosixWord, param);
+
+ PL_PosixXDigit = sv_dup_inc(proto_perl->IPosixXDigit, param);
+ PL_XPosixXDigit = sv_dup_inc(proto_perl->IXPosixXDigit, param);
+
+ PL_VertSpace = sv_dup_inc(proto_perl->IVertSpace, param);
+
+ /* utf8 character class swashes */
PL_utf8_alnum = sv_dup_inc(proto_perl->Iutf8_alnum, param);
PL_utf8_alpha = sv_dup_inc(proto_perl->Iutf8_alpha, param);
PL_utf8_space = sv_dup_inc(proto_perl->Iutf8_space, param);
PL_utf8_idcont = sv_dup_inc(proto_perl->Iutf8_idcont, param);
PL_utf8_xidcont = sv_dup_inc(proto_perl->Iutf8_xidcont, param);
PL_utf8_foldable = sv_dup_inc(proto_perl->Iutf8_foldable, param);
+ PL_utf8_quotemeta = sv_dup_inc(proto_perl->Iutf8_quotemeta, param);
+ PL_ASCII = sv_dup_inc(proto_perl->IASCII, param);
+ PL_AboveLatin1 = sv_dup_inc(proto_perl->IAboveLatin1, param);
+ PL_Latin1 = sv_dup_inc(proto_perl->ILatin1, param);
if (proto_perl->Ipsig_pend) {
{
SV * const name = sv_newmortal();
- if (gv) {
+ if (gv && isGV(gv)) {
char buffer[2];
buffer[0] = gvtype;
buffer[1] = 0;
}
}
else {
- CV * const cv = find_runcv(NULL);
+ CV * const cv = gv ? (CV *)gv : find_runcv(NULL);
SV *sv;
AV *av;
+ assert(!cv || SvTYPE(cv) == SVt_PVCV);
+
if (!cv || !CvPADLIST(cv))
return NULL;
av = MUTABLE_AV((*av_fetch(CvPADLIST(cv), 0, FALSE)));
SV * const sv = newSV(0);
*SvPVX(name) = '$';
Perl_sv_catpvf(aTHX_ name, "{%s}",
- pv_display(sv,SvPVX_const(keyname), SvCUR(keyname), 0, 32));
+ pv_pretty(sv, SvPVX_const(keyname), SvCUR(keyname), 32, NULL, NULL,
+ PERL_PV_PRETTY_DUMP | PERL_PV_ESCAPE_UNI_DETECT ));
SvREFCNT_dec(sv);
}
else if (subscript_type == FUV_SUBSCRIPT_ARRAY) {