diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-08-03 09:23:15 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-09-15 22:45:05 -0700 |
commit | 6d5c21479838db78689e08afd075ef4e9100ef0d (patch) | |
tree | 44db00c7bbbae895f1e3208ffcd3a43b719373cb /proto.h | |
parent | fead5351141134064bc3069932e04930bd96eb0e (diff) | |
download | perl-6d5c21479838db78689e08afd075ef4e9100ef0d.tar.gz |
Clone my subs on scope entry
The pad slot for a my sub now holds a stub with a prototype CV
attached to it by proto magic.
The prototype is cloned on scope entry. The stub in the pad is used
when cloning, so any code that references the sub before scope entry
will be able to see that stub become defined, making these behave
similarly:
our $x;
BEGIN { $x = \&foo }
sub foo { }
our $x;
my sub foo { }
BEGIN { $x = \&foo }
Constants are currently not cloned, but that may cause bugs in
pad_push. I’ll have to look into that.
On scope exit, lexical CVs go through leave_scope’s SAVEt_CLEARSV sec-
tion, like lexical variables. If the sub is referenced elsewhere, it
is abandoned, and its proto magic is stolen and attached to a new stub
stored in the pad. If the sub is not referenced elsewhere, it is
undefined via cv_undef.
To clone my subs on scope entry, we create a sequence of introcv and
clonecv ops. See the huge comment in block_end that explains why we
need two separate ops for each CV.
To allow my subs to be defined in inner subs (my sub foo; sub { sub
foo {} }), pad_add_name_pvn and S_pad_findlex now upgrade the entry
for a my sub to a CV to begin with, so that fake entries added to pads
(fake entries are those that reference outer pads) can share the same
CV. Otherwise newMYSUB would have to add the CV to every pad that
closes over the ‘my sub’ declaration. newMYSUB no longer throws away
the initial value replacing it with a new one.
Prototypes are not currently visible to sub calls at compile time,
because the lexer sees the empty stub. A future commit will
solve that.
When I added name heks to CV’s I made mistakes in a few places, by not
turning on the CVf_NAMED flag, or by not clearing the field when free-
ing the hek. Those code paths were not exercised enough by state
subs, so the problems did not show up till now. So this commit fixes
those, too.
One of the tests in lexsub.t, involving foreach loops, was incorrect,
and has been fixed. Another test has been added to the end for a par-
ticular case of state subs closing over my subs that I broke when ini-
tially trying to get sibling my subs to close over each other, before
I had separate introcv and clonecv ops.
Diffstat (limited to 'proto.h')
-rw-r--r-- | proto.h | 8 |
1 files changed, 7 insertions, 1 deletions
@@ -691,6 +691,12 @@ PERL_CALLCONV CV* Perl_cv_clone(pTHX_ CV* proto) #define PERL_ARGS_ASSERT_CV_CLONE \ assert(proto) +PERL_CALLCONV CV* Perl_cv_clone_into(pTHX_ CV* proto, CV *target) + __attribute__nonnull__(pTHX_1) + __attribute__nonnull__(pTHX_2); +#define PERL_ARGS_ASSERT_CV_CLONE_INTO \ + assert(proto); assert(target) + PERL_CALLCONV SV* Perl_cv_const_sv(pTHX_ const CV *const cv) __attribute__warn_unused_result__; @@ -2974,7 +2980,7 @@ PERL_CALLCONV void Perl_pad_fixup_inner_anons(pTHX_ PADLIST *padlist, CV *old_cv assert(padlist); assert(old_cv); assert(new_cv) PERL_CALLCONV void Perl_pad_free(pTHX_ PADOFFSET po); -PERL_CALLCONV void Perl_pad_leavemy(pTHX); +PERL_CALLCONV OP * Perl_pad_leavemy(pTHX); PERL_CALLCONV PADLIST* Perl_pad_new(pTHX_ int flags) __attribute__malloc__ __attribute__warn_unused_result__; |