Skip to content

Commit f7317f5

Browse files
committed
scope.c - add mortal_destructor_sv() and mortal_destructor_x()
This implements a mortal version of SAVEDESTRUCTOR_X() which executes at the end of the current statement instead of the end of the current psuedo block. This requires implementing a mortal SV with free magic that triggers the destructor behavior. There is a version for executing a Perl function or a C function, and relevant additional macros that correspond to the existing SAVEDESTRUCTOR_X() save SAVEMORTALSV() type naming convention. Documentation is provided. This is cribbed from Leon's Variable-OnDestruct. See: https://metacpan.org/dist/Variable-OnDestruct/source/lib/Variable/OnDestruct.xs#L6-17 I am very grateful to him for his help on this.
1 parent 2b42bae commit f7317f5

File tree

11 files changed

+234
-6
lines changed

11 files changed

+234
-6
lines changed

embed.fnc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,9 @@ p |int |magic_existspack \
18081808
p |int |magic_freearylen_p \
18091809
|NN SV *sv \
18101810
|NN MAGIC *mg
1811+
p |int |magic_freedestruct \
1812+
|NN SV *sv \
1813+
|NN MAGIC *mg
18111814
p |int |magic_freemglob|NN SV *sv \
18121815
|NN MAGIC *mg
18131816
p |int |magic_freeovrld|NN SV *sv \
@@ -1970,6 +1973,12 @@ Cop |void * |more_bodies |const svtype sv_type \
19701973
|const size_t arena_size
19711974
Cp |const char *|moreswitches \
19721975
|NN const char *s
1976+
Ap |void |mortal_destructor_sv \
1977+
|NN SV *coderef \
1978+
|NULLOK SV *args
1979+
Cp |void |mortal_destructor_x \
1980+
|DESTRUCTORFUNC_t f \
1981+
|NULLOK void *p
19731982
CRTXip |char * |mortal_getenv |NN const char *str
19741983
Adop |const struct mro_alg *|mro_get_from_name \
19751984
|NN SV *name

embed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@
359359
# define mg_size(a) Perl_mg_size(aTHX_ a)
360360
# define mini_mktime Perl_mini_mktime
361361
# define moreswitches(a) Perl_moreswitches(aTHX_ a)
362+
# define mortal_destructor_sv(a,b) Perl_mortal_destructor_sv(aTHX_ a,b)
363+
# define mortal_destructor_x(a,b) Perl_mortal_destructor_x(aTHX_ a,b)
362364
# define mortal_getenv Perl_mortal_getenv
363365
# define mro_get_linear_isa(a) Perl_mro_get_linear_isa(aTHX_ a)
364366
# define mro_method_changed_in(a) Perl_mro_method_changed_in(aTHX_ a)
@@ -961,6 +963,7 @@
961963
# define magic_copycallchecker(a,b,c,d,e) Perl_magic_copycallchecker(aTHX_ a,b,c,d,e)
962964
# define magic_existspack(a,b) Perl_magic_existspack(aTHX_ a,b)
963965
# define magic_freearylen_p(a,b) Perl_magic_freearylen_p(aTHX_ a,b)
966+
# define magic_freedestruct(a,b) Perl_magic_freedestruct(aTHX_ a,b)
964967
# define magic_freemglob(a,b) Perl_magic_freemglob(aTHX_ a,b)
965968
# define magic_freeovrld(a,b) Perl_magic_freeovrld(aTHX_ a,b)
966969
# define magic_freeutf8(a,b) Perl_magic_freeutf8(aTHX_ a,b)

mg_names.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
{ PERL_MAGIC_vstring, "vstring(V)" },
4545
{ PERL_MAGIC_vec, "vec(v)" },
4646
{ PERL_MAGIC_utf8, "utf8(w)" },
47+
{ PERL_MAGIC_destruct, "destruct(X)" },
4748
{ PERL_MAGIC_substr, "substr(x)" },
4849
{ PERL_MAGIC_nonelem, "nonelem(Y)" },
4950
{ PERL_MAGIC_defelem, "defelem(y)" },

mg_raw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
"/* vec 'v' vec() lvalue */" },
7777
{ 'w', "want_vtbl_utf8 | PERL_MAGIC_VALUE_MAGIC",
7878
"/* utf8 'w' Cached UTF-8 information */" },
79+
{ 'X', "want_vtbl_destruct | PERL_MAGIC_VALUE_MAGIC",
80+
"/* destruct 'X' destruct callback */" },
7981
{ 'x', "want_vtbl_substr | PERL_MAGIC_VALUE_MAGIC",
8082
"/* substr 'x' substr() lvalue */" },
8183
{ 'Y', "want_vtbl_nonelem | PERL_MAGIC_VALUE_MAGIC",

mg_vtable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#define PERL_MAGIC_vstring 'V' /* SV was vstring literal */
5252
#define PERL_MAGIC_vec 'v' /* vec() lvalue */
5353
#define PERL_MAGIC_utf8 'w' /* Cached UTF-8 information */
54+
#define PERL_MAGIC_destruct 'X' /* destruct callback */
5455
#define PERL_MAGIC_substr 'x' /* substr() lvalue */
5556
#define PERL_MAGIC_nonelem 'Y' /* Array element that does not exist */
5657
#define PERL_MAGIC_defelem 'y' /* Shadow "foreach" iterator variable /
@@ -69,6 +70,7 @@ enum { /* pass one of these to get_vtbl */
6970
want_vtbl_dbline,
7071
want_vtbl_debugvar,
7172
want_vtbl_defelem,
73+
want_vtbl_destruct,
7274
want_vtbl_env,
7375
want_vtbl_envelem,
7476
want_vtbl_hints,
@@ -107,6 +109,7 @@ EXTCONST char * const PL_magic_vtable_names[magic_vtable_max] = {
107109
"dbline",
108110
"debugvar",
109111
"defelem",
112+
"destruct",
110113
"env",
111114
"envelem",
112115
"hints",
@@ -168,6 +171,7 @@ EXT_MGVTBL PL_magic_vtables[magic_vtable_max] = {
168171
{ 0, Perl_magic_setdbline, 0, 0, 0, 0, 0, 0 },
169172
{ Perl_magic_getdebugvar, Perl_magic_setdebugvar, 0, 0, 0, 0, 0, 0 },
170173
{ Perl_magic_getdefelem, Perl_magic_setdefelem, 0, 0, 0, 0, 0, 0 },
174+
{ 0, 0, 0, 0, Perl_magic_freedestruct, 0, 0, 0 },
171175
{ 0, Perl_magic_set_all_env, 0, Perl_magic_clear_all_env, 0, 0, 0, 0 },
172176
{ 0, Perl_magic_setenv, 0, Perl_magic_clearenv, 0, 0, 0, 0 },
173177
{ 0, 0, 0, Perl_magic_clearhints, 0, 0, 0, 0 },
@@ -214,6 +218,7 @@ EXT_MGVTBL PL_magic_vtables[magic_vtable_max];
214218
#define PL_vtbl_dbline PL_magic_vtables[want_vtbl_dbline]
215219
#define PL_vtbl_debugvar PL_magic_vtables[want_vtbl_debugvar]
216220
#define PL_vtbl_defelem PL_magic_vtables[want_vtbl_defelem]
221+
#define PL_vtbl_destruct PL_magic_vtables[want_vtbl_destruct]
217222
#define PL_vtbl_env PL_magic_vtables[want_vtbl_env]
218223
#define PL_vtbl_envelem PL_magic_vtables[want_vtbl_envelem]
219224
#define PL_vtbl_fm PL_magic_vtables[want_vtbl_fm]

pod/perldiag.pod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,14 @@ a C<given> block. You probably meant to use C<next> or C<last>.
832832

833833
(F) You called C<break>, but you're not inside a C<given> block.
834834

835+
=item Can't call destructor for 0x%p in global destruction
836+
837+
(S) This should not happen. Internals code has set up a destructor
838+
using C<mortal_destructor_sv> or C<mortal_destructor_x> which is firing
839+
during global destruction. Please attempt to reduce the code that triggers
840+
this warning down to a small an example as possible and then report the
841+
problem to L<https://github.com/Perl/perl5/issues/new/choose>
842+
835843
=item Can't call method "%s" on an undefined value
836844

837845
(F) You used the syntax of a method call, but the slot filled by the

pod/perlguts.pod

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,17 +1510,17 @@ will be lost.
15101510
tables
15111511
< PERL_MAGIC_backref vtbl_backref For weak ref data
15121512
@ PERL_MAGIC_arylen_p (none) To move arylen out of XPVAV
1513-
B PERL_MAGIC_bm vtbl_regexp Boyer-Moore
1513+
B PERL_MAGIC_bm vtbl_regexp Boyer-Moore
15141514
(fast string search)
1515-
c PERL_MAGIC_overload_table vtbl_ovrld Holds overload table
1515+
c PERL_MAGIC_overload_table vtbl_ovrld Holds overload table
15161516
(AMT) on stash
1517-
D PERL_MAGIC_regdata vtbl_regdata Regex match position data
1517+
D PERL_MAGIC_regdata vtbl_regdata Regex match position data
15181518
(@+ and @- vars)
15191519
d PERL_MAGIC_regdatum vtbl_regdatum Regex match position data
15201520
element
15211521
E PERL_MAGIC_env vtbl_env %ENV hash
15221522
e PERL_MAGIC_envelem vtbl_envelem %ENV hash element
1523-
f PERL_MAGIC_fm vtbl_regexp Formline
1523+
f PERL_MAGIC_fm vtbl_regexp Formline
15241524
('compiled' format)
15251525
g PERL_MAGIC_regex_global vtbl_mglob m//g target
15261526
H PERL_MAGIC_hints vtbl_hints %^H hash
@@ -1548,6 +1548,7 @@ will be lost.
15481548
V PERL_MAGIC_vstring (none) SV was vstring literal
15491549
v PERL_MAGIC_vec vtbl_vec vec() lvalue
15501550
w PERL_MAGIC_utf8 vtbl_utf8 Cached UTF-8 information
1551+
X PERL_MAGIC_destruct vtbl_destruct destruct callback
15511552
x PERL_MAGIC_substr vtbl_substr substr() lvalue
15521553
Y PERL_MAGIC_nonelem vtbl_nonelem Array element that does not
15531554
exist
@@ -1575,6 +1576,7 @@ will be lost.
15751576
=for apidoc_item ||PERL_MAGIC_dbline
15761577
=for apidoc_item ||PERL_MAGIC_debugvar
15771578
=for apidoc_item ||PERL_MAGIC_defelem
1579+
=for apidoc_item ||PERL_MAGIC_destruct
15781580
=for apidoc_item ||PERL_MAGIC_env
15791581
=for apidoc_item ||PERL_MAGIC_envelem
15801582
=for apidoc_item ||PERL_MAGIC_ext
@@ -1978,19 +1980,49 @@ this:
19781980
=item C<SAVEDESTRUCTOR(DESTRUCTORFUNC_NOCONTEXT_t f, void *p)>
19791981

19801982
At the end of I<pseudo-block> the function C<f> is called with the
1981-
only argument C<p>.
1983+
only argument C<p> which may be NULL.
19821984

19831985
=for apidoc Ayh||DESTRUCTORFUNC_NOCONTEXT_t
19841986
=for apidoc Amh||SAVEDESTRUCTOR|DESTRUCTORFUNC_NOCONTEXT_t f|void *p
19851987

19861988
=item C<SAVEDESTRUCTOR_X(DESTRUCTORFUNC_t f, void *p)>
19871989

19881990
At the end of I<pseudo-block> the function C<f> is called with the
1989-
implicit context argument (if any), and C<p>.
1991+
implicit context argument (if any), and C<p> which may be NULL.
1992+
1993+
Note the I<end of the current pseudo-block> may occur much later than
1994+
the the I<end of the current statement>. You may wish to look at the
1995+
C<SAVEMORTALDESTRUCTOR_X()> macro instead.
19901996

19911997
=for apidoc Ayh||DESTRUCTORFUNC_t
19921998
=for apidoc Amh||SAVEDESTRUCTOR_X|DESTRUCTORFUNC_t f|void *p
19931999

2000+
=item C<SAVEMORTALDESTRUCTOR_X(DESTRUCTORFUNC_t f, void *p)>
2001+
2002+
At the end of I<the current statement> the function C<f> is called with
2003+
the implicit context argument (if any), and C<p> which may be NULL.
2004+
2005+
Note the I<end of the current statement> may occur much before the
2006+
the I<end of the current pseudo-block>. You may wish to look at the
2007+
C<SAVEDESTRUCTOR_X()> macro instead.
2008+
2009+
=for apidoc Amh||SAVEMORTALDESTRUCTOR_X|DESTRUCTORFUNC_t f|void *p
2010+
2011+
=item C<SAVEMORTALDESTRUCTOR_SV(SV *coderef, SV *args)>
2012+
2013+
At the end of I<the current statement> the Perl function contained in
2014+
C<coderef> is called with the arguments provided (if any) in C<args>.
2015+
See the documentation for C<mortal_destructor_sv()> for details on
2016+
the C<args> parameter is handled.
2017+
2018+
Note the I<end of the current statement> may occur much before the
2019+
the I<end of the current pseudo-block>. If you wish to call a perl
2020+
function at the end of the current pseudo block you should use the
2021+
C<SAVEDESTRUCTOR_X()> API instead, which will require you create a
2022+
C wrapper to call the Perl function.
2023+
2024+
=for apidoc Amh||SAVEMORTALDESTRUCTOR_X|DESTRUCTORFUNC_t f|void *p
2025+
19942026
=item C<SAVESTACK_POS()>
19952027

19962028
The current offset on the Perl internal stack (cf. C<SP>) is restored

proto.h

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

regen/mg_vtable.pl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ BEGIN
212212
vtable => 'debugvar' },
213213
lvref => { char => '\\', vtable => 'lvref',
214214
desc => "Lvalue reference constructor" },
215+
destruct => {
216+
char => "X",
217+
vtable => 'destruct',
218+
desc => "destruct callback",
219+
value_magic => 1,
220+
},
215221
);
216222

217223

@@ -288,6 +294,7 @@ BEGIN
288294
'checkcall' => {copy => 'copycallchecker'},
289295
'debugvar' => { set => 'setdebugvar', get => 'getdebugvar' },
290296
'lvref' => {set => 'setlvref'},
297+
'destruct' => {free => 'freedestruct'},
291298
);
292299

293300

@@ -428,6 +435,7 @@ BEGIN
428435
($desc, @cont) = $desc =~ /(.{1,$desc_wrap})(?: |\z)/g
429436
}
430437
}
438+
s/\s+\z// for $desc, @cont;
431439
printf $format, $type, $vtbl, $desc;
432440
printf $format, '', '', $_ foreach @cont;
433441
}

0 commit comments

Comments
 (0)