Skip to content

Commit f6f60ec

Browse files
committed
Create viral value magic
Adds a new SVs_VMG flag + associated macros; use the SvVMAGICAL flag to fast-path sv_has_valuemagic() if appropriate Use the sv_has_valuemagic() function to know whether to call mg_propagate() in sv_setsv_flags()
1 parent 2a5e776 commit f6f60ec

19 files changed

Lines changed: 868 additions & 15 deletions

File tree

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5183,6 +5183,7 @@ ext/XS-APItest/t/magic.t test attaching, finding, and removing magic
51835183
ext/XS-APItest/t/magic_chain.t test low-level MAGIC chain handling
51845184
ext/XS-APItest/t/magicv2.t XS::APItest: tests for Magic-v2 related APIs
51855185
ext/XS-APItest/t/magicv2-threads.t XS::APItest: tests for Magic-v2 related APIs across multiple threads
5186+
ext/XS-APItest/t/magicv2-viral.t XS::APItest: tests for Magic-v2 related APIs on viral SCALARVALUE
51865187
ext/XS-APItest/t/Markers.pm Helper for ./blockhooks.t
51875188
ext/XS-APItest/t/mortal_destructor.t Test mortal_destructor api.
51885189
ext/XS-APItest/t/mro.t Test mro plugin api

doop.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,8 @@ Perl_do_join(pTHX_ SV *sv, SV *delim, SV **mark, SV **sp)
715715

716716
if (TAINTING_get && SvMAGICAL(sv))
717717
SvTAINTED_off(sv);
718+
if(SvMAGICAL(sv)) /* TODO: need more flags */
719+
mg_unpropagate(sv);
718720

719721
if (items-- > 0) {
720722
if (*mark)

dump.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,8 @@ Perl_do_magicv2_dump(pTHX_ I32 level, PerlIO *file, const MAGIC *mg, I32 nest, I
19991999
case MGv2s_SCALARVAR: shapename = "SCALARVAR"; break;
20002000
case MGv2s_ARRAYVAR: shapename = "ARRAYVAR"; break;
20012001
case MGv2s_HASHVAR: shapename = "HASHVAR"; break;
2002+
case MGv2s_SCALARVALUE:
2003+
shapename = "SCALARVALUE"; break;
20022004
}
20032005
if(shapename)
20042006
dump_indent(level, file, " SHAPE = %s\n", shapename);
@@ -2039,6 +2041,13 @@ Perl_do_magicv2_dump(pTHX_ I32 level, PerlIO *file, const MAGIC *mg, I32 nest, I
20392041
dump_indent(level, file, " CLEAR\n");
20402042
break;
20412043
}
2044+
case MGv2s_SCALARVALUE:
2045+
{
2046+
const struct ScalarValueMagicFunctions *funcs = MgSCALARVALUEFUNCS(mg);
2047+
if(funcs->propagate)
2048+
Perl_dump_indent(aTHX_ level, file, " PROPAGATE\n");
2049+
break;
2050+
}
20422051
}
20432052
}
20442053

@@ -2536,7 +2545,10 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
25362545
/* FALLTHROUGH */
25372546
case SVt_PVMG:
25382547
default:
2539-
if (SvIsUV(sv) && !(flags & SVf_ROK)) sv_catpvs(d, "IsUV,");
2548+
if (type <= SVt_PVMG && SvVMAGICAL(sv))
2549+
sv_catpvs(d, "VMG,");
2550+
if (SvIsUV(sv) && !(flags & SVf_ROK))
2551+
sv_catpvs(d, "IsUV,");
25402552
break;
25412553

25422554
case SVt_PVAV:

embed.fnc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,6 +4190,10 @@ Adp |void |vfatal_warner |U32 err \
41904190
|NULLOK va_list *args
41914191
Adp |char * |vform |NN const char *pat \
41924192
|NULLOK va_list *args
4193+
Cp |void |viralmagic_applyto \
4194+
|NN SV *dsv
4195+
Cp |void |viralmagic_clear
4196+
Cp |void |viralmagic_from|NN SV *ssv
41934197
: Used by Data::Alias
41944198
EXp |void |vivify_defelem |NN SV *sv
41954199
: Used in pp.c
@@ -4428,6 +4432,9 @@ Cpx |SV * |sv_setsv_cow |NULLOK SV *dsv \
44284432
|NN SV *ssv
44294433
#endif
44304434
#if defined(PERL_CORE)
4435+
p |void |mg_propagate |NN SV *ssv \
4436+
|NULLOK SV *dsv
4437+
p |void |mg_unpropagate |NN SV *sv
44314438
p |void |opslab_force_free \
44324439
|NN OPSLAB *slab
44334440
p |void |opslab_free |NN OPSLAB *slab
@@ -4437,6 +4444,8 @@ p |void |parser_free_nexttoke_ops \
44374444
|NN yy_parser *parser \
44384445
|NN OPSLAB *slab
44394446
RTi |bool |should_warn_nl |NN const char *pv
4447+
p |bool |sv_has_valuemagic \
4448+
|NN const SV *sv
44404449
# if defined(PERL_DEBUG_READONLY_OPS)
44414450
ep |void |Slab_to_ro |NN OPSLAB *slab
44424451
ep |void |Slab_to_rw |NN OPSLAB * const slab

embed.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/XS-APItest/APItest.xs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,42 @@ static const struct ArrayVarMagicFunctions magicfuncs_inc_after_clear_hash = {
348348
.clear = &magicfunc_inc,
349349
};
350350

351+
/* we can't make this one `static` because -Wc++-compat gets upset if we do */
352+
extern const struct ScalarValueMagicFunctions magicfuncs_viral;
353+
354+
static void
355+
magicfunc_propagate(pTHX_ SV *osv, MAGIC *omg, SV *nsv, MAGIC *nmg)
356+
{
357+
PERL_UNUSED_ARG(osv);
358+
359+
SV *auxsv = MgAUXSV(omg);
360+
361+
/* Only add this to nsv if it doesn't already have it
362+
* TODO: This is kinda inefficient. We could make it better by storing
363+
* all the annotations sorted in order of auxsv address, allowing us to
364+
* bail out on average twice as fast. Such a search also gives us the
365+
* right insert point to add if absent.
366+
* Such logic would involve more deep internal poking at the MAGIC
367+
* structure though. */
368+
369+
for(nmg = sv_magicv2_find_by_funcs(nsv, (const struct MagicFunctions *)&magicfuncs_viral);
370+
nmg;
371+
nmg = sv_magicv2_findnext_by_funcs(nsv, (const struct MagicFunctions *)&magicfuncs_viral, nmg)) {
372+
if(MgAUXSV(nmg) == auxsv)
373+
return;
374+
}
375+
376+
sv_magicv2_add(nsv, (const struct MagicFunctions *)&magicfuncs_viral, 0, SvREFCNT_inc(auxsv));
377+
}
378+
379+
const struct ScalarValueMagicFunctions magicfuncs_viral = {
380+
.ver = 2,
381+
.shape = MGv2s_SCALARVALUE,
382+
.debug_name = "XS::APItest/viral",
383+
384+
.propagate = magicfunc_propagate,
385+
};
386+
351387
static const struct MagicFunctions *S_magicfuncs_by_name(pTHX_ SV *name)
352388
{
353389
char *namepv = SvPV_nolen(name);
@@ -363,6 +399,7 @@ static const struct MagicFunctions *S_magicfuncs_by_name(pTHX_ SV *name)
363399
if(strEQ(namepv, "inc_after_set")) return (struct MagicFunctions *)&magicfuncs_inc_after_set;
364400
if(strEQ(namepv, "inc_after_clear_arr")) return (struct MagicFunctions *)&magicfuncs_inc_after_clear_arr;
365401
if(strEQ(namepv, "inc_after_clear_hash")) return (struct MagicFunctions *)&magicfuncs_inc_after_clear_hash;
402+
if(strEQ(namepv, "viral")) return (struct MagicFunctions *)&magicfuncs_viral;
366403
croak("Unrecognised magicfuncs name %" SVf, SVfARG(name));
367404
}
368405

0 commit comments

Comments
 (0)