| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
XS::APItest isn't available under -Uusedl
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
local *foo=sub{} is done in two stages:
• First the local *foo localises the GP (the glob pointer, or list of
slots), setting a flag on the GV.
• Then scalar assignment sees the flag on the GV on the LHS and loca-
lises a single slot.
The slot localisation only stores on the savestack a pointer into the
GP struct and the old value. There is no reference to the GV.
To restore a method properly, we have to have a reference to the GV
when the slot localisation is undone.
So in this commit I have added a new save type, SAVEt_GVSLOT. It is
like SAVEt_GENERIC_SV, except it pushes the GV as well. Currently
it is used only for CVs, but I will need it for HVs and maybe
AVs as well.
It is possible for the unwinding of the slot localisation to affect
only a GV other than the one that is pushed, if glob assignments have
taken place since the local *foo. So we have to check whether the
pointer is inside the GP and use PL_sub_generation++ if it is not.
|
|
|
|
| |
This stops $::TODO from producing a used-only-once warning.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It was already working for those cases where *foo contained a sub
before and after localisation. For those cases where *foo had no sub
but localised assignment gave it one, method caches were not being
reset on scope exit.
case SAVEt_GP in scope.c:leave_scope needs to look at both GPs (glob
pointer, or list of glob slots), both from before and after the unlo-
calisation. If either has a sub, method caches need to be cleared.
This does not yet fix local *foo = sub {}, but I added a to-do
test for it. (This is more complicated, as localisation happens in
two seperate steps, the glob slot localisation storing no pointers to
the glob itself on the savestack.)
|
|
|
|
|
|
|
|
|
|
| |
These are regressions from 5.8.
local *ISA was not updating isa caches. local *ISA = [] was updating
caches, but scope unwinding was not.
Both save_gp and leave_scope/SAVEt_GP need to check whether the glob
is named ISA and call mro_isa_changed_in if appropriate.
|
|
|
|
|
|
|
| |
save_gp was trying to call mro_method_changed_in even if the stash had
been detached.
This is a regression from 5.12.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The new MRO stuff in 5.10 made PL_sub_generation++ mostly unnecessary,
and almost all uses of it were replaced with mro_method_changed_in.
There is only one problem: That doesn’t actually work properly. After
glob-to-glob assignment (*foo = *bar), both globs share the same GP
(glob pointer, or list of glob slots). But there is no list of GVs
associated with any GP. So there is no way, given a GV whose GP
is shared, to find out what other classes might need their method
caches reset.
sub B::b { "b" }
*A::b = *B::b;
@C::ISA = "A";
print C->b, "\n"; # should print "b"
eval 'sub B::b { "c" }';
print C->b, "\n"; # should print "c"
__END__
$ perl5.8.9 foo
b
c
$ perl5.10.0 foo
b
b
And it continues up to 5.16.x.
If a GP is shared, then those places where mro_method_changed_in is
called after the GP has been modified must do PL_sub_generation++
instead if the GP is shared, which can be detected through its refer-
ence count.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
These are combined into one patch because it is hard to fix one with-
out fixing the other.
local *glob = $ref was ignoring the clobbered reference and not
accounting for when updating ISA caches, resulting in two bugs:
*Foo::ISA = *Bar::ISA;
@Foo::ISA = "Baz";
sub Baz::ook { "Baz" }
sub L::ook { "See" }
warn Bar->ook; # Baz
local *Foo::ISA = ["L"];
warn Bar->ook; # Baz
@Baz::ISA = @Baz::ISA; # should have no effect
warn Bar->ook; # See
@Baz::ISA = "Foo::bar";
sub Foo::bar::ber { 'baz' }
sub UNIVERSAL::ber { "black sheep" }
warn Baz->ber; # baz
local *Foo:: = \%Bar::;
warn Baz->ber; # baz
@Baz::ISA = @Baz::ISA; # should have no effect
warn Baz->ber; # black sheep
The dref variable in sv.c:S_glob_assign_ref holds the SV that needs to
be freed. So during localisation it is NULL.
When I was fixing up isa and mro bugs in perl 5.14, I misunderstood
its purpose and thought it always contained the reference on the left.
Since we need to have access to what was assigned over after the
assignment, this commit changes dref always to hold the clobbered SV,
and makes the SvREFCNT_dec conditional.
|
| |
|
|
|
|
|
| |
It was not attaching magic to the array, preventing subsequent changes
to the array from updating isa caches.
|
|
|
|
|
|
|
|
|
|
| |
I broke this in 5.14 with commit 6624142a.
In trying to make *ISA = *Other::ISA work, I added logic to make
@Other::ISA’s existing magic now point to *ISA’s stash. I skipped
that logic if *Other::ISA did not contain an array. But in so
doing, I inadvertently skipped the call to mro_isa_changed_in at the
same time.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Change every existing instance of isa_ok() to use object_ok(). This is safe because
before this point, t/test.pl's isa_ok() only worked on objects. lib/dbmt_common.pl is
the last hold out because it uses Test::More.
These are like isa_ok() but they also check if it's a class or an object.
This lets the core tests defend against outlandish bugs while allowing
t/test.pl to retain feature parity with Test::More.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This patch also duplicates existing mro tests with copies that use
Unicode in identifiers, to test the mro code.
Since those tests trigger it, it also fixes a bug in the parsing
of *{...}: If the first character inside the braces is a non-ASCII
Unicode identifier character, the inside is now implicitly quoted
if it is just an identifier (just as it is with ASCII identifiers),
instead of being parsed as a bareword that would violate strict subs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Commit 088225f was not sufficient to fix the regression. It still
exists for packages whose names end with a single colon.
I discovered this when trying to determine why RDF::Trine was crashing
with 5.14-to-be.
In trying to write tests for it, I ended up triggering the same crash
that RDF::Trine is having, but in a different way.
In the end, it was easier to fix about three or four bugs (depending
on how you count them), rather than try to fix only the regression
that #88132 deals with (isa caches not updating when packages ending
with colons are aliased), as they are all intertwined.
The changes are as follows:
Concerning the if (!(flags & ~GV_NOADD_MASK)...) statement in
gv_stashpvn: Normally, gv_fetchpvn_flags (which it calls and whose
retval is assigned to tmpgv) returns NULL if it has not been told
to add anything and if the gv requested looks like a stash gv (ends
with ::). If the number of colons is odd (foo:::), that code path is
bypassed, so gv_stashpvn returns a GV without a hash. So gv_stashpvn
tries to used that NULL hash and crashes. It should instead return
NULL, to be consistent with the two-colon case.
Blindly assigning a name to a stash does not work if the stash has
multiple effective names. A call to mro_package_moved is required as
well. So what gv_stashpvn was doing was insufficient.
The parts of the mro code that check for globs or stash elems that
contain stashes by looking for :: at the end of the name now take into
account that the name might consist of a single : instead.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
gv_fetchpvn_flags did not always assign a name to a return HV ending
with ::. This would result in code in various places skipping certain
‘stashes’ (in quotes because nameless HVs are technically not stashes)
because they were nameless when they should not have been.
So sometimes ISA caches would end up being out of date, as in the test
cases posted with [perl #88132] (and incorporated into this patch).
This commit fixes that by changing the parsing of glob names.
Formerly, a :: was not considered a package separator if it came imme-
diately after a ::. So foo:::: would become foo::/:: (with the final
:: considered a regular stash entry, not a ‘stash’ stash entry) and
foo:::::: would become foo::/:::/:.
Now a :: is always a package separator. So *foo::::bar is accessible
via $foo::{"::"}{bar} and *$foo:::::: via $foo::{"::"}{"::"}.
This happens to fix [perl #88134] as well.
|
|
|
|
|
|
|
| |
# New Ticket Created by (Peter J. Acklam)
# Please include the string: [perl #81916]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=81916 >
|
|
|
|
| |
This reverts commit a5cd004dbd757df2bcf9e17aab6a8ed1272157d7.
|
|
|
|
| |
This reverts commit 1726bc11330f7a943b1e12c6dd5fa5454b90abd6.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If
@UNIVERSAL::ISA = "a";
and
@a::ISA = "b";
then methods are searched for in these orders:
main UNIVERSAL a b
UNIVERSAL a b UNIVERSAL a b
a b UNIVERSAL a b
b UNIVERSAL a b
For method lookup, looking at a stash twice causes no problems (except
for a SUPER bug I’ve just found--to be dealt with separately).
My fix to next::method in a5cd004 which made it do a second pass with
UNIVERSAL the way gv_fetchmeth does did not take into account that it
might return its caller (sub a::foo { return shift->next::can }),
causing an infinite loop.
This patch makes it check, on the second pass, whether each stash is
the stash at the start of the MRO list and breaks if that is the case,
so the MROs are effectively:
main UNIVERSAL a b
UNIVERSAL a b
a b UNIVERSAL
b UNIVERSAL a
(which is what they are effectively already for method lookup).
|
|
|
|
|
| |
This commit makes next::method retry with UNIVERSAL if it reaches the
end of the MRO list.
|
|
|
|
|
| |
This makes ./perl -Ilib t/mro/next_edgecases.t work and also
allows test functions to be called without parentheses.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
See the test case in the commit. It passes in 5.8.x and blead (as of
this commit), but not 5.10-5.13.7.
In every case the name to be passed to mro_gather_and_rename is cre-
ated using an SV, so we might as well pass that instead of extracting
the char array and length from it.
That allows us to pass an AV instead, if there are multiple names to
take into account.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
unless called from sv_clear.
This is necessary as and undeffed stash, though it nominally becomes
just a plain hash and is not a stash any more, is still to be found
in the symbol table. It may even be in multiple places. HvENAME’s
raison d’être is to keep track of this. If the effective name is
deleted, then things can get out of sync as the test in the commit
demonstrates. This can cause problems if the hash is turned back
into a stash.
This does not change the deletion of the HvNAME, which is the only
difference between hv_clear and hv_undef on stashes that is visible
from Perl. caller still returns (unknown) or __ANON__::....
I tried to make this into several small commits, but each part of it
breaks things without the other parts, so this is one big commit.
These are the various parts:
• hv_undef no longer calls mro_package_named directly, as it deletes
the effective name of the stash. It must only be called on sub-
stashes, so hfreeentries has been modified to do that.
• hv_name_set, which has erased the HvENAME when passed a null arg
for the value ever since effective names were added (a special case
put it just for hv_undef), now leaves the HvENAME alone, unless the
new HV_NAME_SETALL flag (set to 2 to allow for UTF8 in future)
is passed.
• hv_undef does not delete the name before the call to hfreeentries
during global destruction. That extra name deletion was added when
hfreeentries stopped hiding the name, as CVs won’t be anonymised
properly if they see it. It does not matter where the CVs point if
they are to be freed shortly. This is just a speed optimisation, as
it allows the name and effective name to be deleted in one fell
swoop. Deleting just the name (not the effective name) can require a
memory allocation.
• hv_undef calls mro_isa_changed_in as it used to (before it started
using mro_package_moved), but now it happens after the entries are
freed. Calling it first, as 5.13.6 and earlier versions did, was
simply wrong.
• Both names are deleted from PL_stashcache. I inadvertently switched
it back and forth between the two names in previous commits. Since
it needed to be accounted for, it made no omit it, as that would
just complicate things. (I think PL_stashcache is buggy, though I
have yet to come up with a test case.)
• sv_clear now calls Perl_hv_undef_flags with the HV_NAME_SETALL
flag, which is passed through to the second hv_name_set call,
after hfreeentries. That determines whether the effective names
are deleted.
• The changes at the end of hv_undef consist of pussyfooting to avoid
unnecessary work. They make sure that everything is freed that needs
to be and nothing is freed that must not be.
|
|
|
|
|
|
|
| |
This stops S_hv_delete_common from skipping the call to
mro_package_moved if the HvNAME of the stash containing the deleted
glob is no longer valid, but the stash is still attached to some other
part of the symbol table.
|
|
|
|
|
|
|
| |
This allows it to delete PL_isarev entries.
mro_isa_changed_in only deletes items mentioned in HvMROMETA(hv)->isa,
so it must be present.
|
|
|
|
|
|
|
|
|
|
| |
This is a follow-up to 6624142.
Ref-to-glob assignment was not working after an *ISA-to-*ISA
assignment.
It needs to copy into mg_obj all the items in the mg_obj of the array
that is being replaced.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This is something I think I broke with 80ebaca, which made sure
that isa linearisations were cached on subclasses after calls
to mro_isa_changed_in (so the data could be used to delete
isarev entries).
The result is that hv_undef, which calls mro_isa_changed_in before
deleting everything, was updating the subclasses’ isa caches while its
own @ISA was still visible.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes a case that mro_package_moved did not take into account:
If a class with multiple levels of subclasses was assigned over, then,
depending on the order in which the subclasses were processed in the
second loop in mro_package_moved, the subclasses might not be removed
from the isarev hashes of superclasses of the clobbered class.
This was because a call to mro_isa_changed_in on one class could call
mro_get_linear_isa on another class in the list, overwriting its
meta->isa hash, which is used to determine what to delete from
PL_isarev.
E.g., if D isa C isa B isa A, this assignment:
*B:: = *something::;
would cause B, C and D to be iterated over, but not in any particular
order. The order could be D, C, B, in which case mro_isa_changed_in(D)
would overwrite the meta->isa hash in C with one that did not list A.
So mro_isa_changed_in(C) would not see A in meta->isa and would not
delete PL_isarev->{A}{C}.
This commit stores the meta->isa hash as the value in the ‘big list’,
instead of the stash. The stash itself can be retrieved from the key,
since it is already a memory address (a pointer cast to a char array).
The recorded isa hash in inserted into each stash before the call to
mro_isa_changed_in.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This commit fixes package assignments like *foo:: = *bar:: when both
foo and bar contain nested stashes that are aliases of each other.
mro_package_moved (actually, its auxiliary routine) need to keep a
list of stashes that have been seen as a separate list from those that
are going to have mro_isa_changed_in called on them. Otherwise, some
stashes will simply not be iterated through.
See the test that this adds and its comments. @ISA = @ISA should never
have any effect visible to Perl (with a capital), but it does in that
test case, prior to this commit.
This also fixes another bug that the test case triggered:
riter was not being reset before the second iteration in
mro_gather_and_rename.
Also, the stashes HV (aka the ‘big list’) now holds refcounts on its
elements, as that makes the code simpler as a result of the changes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Commit 80ebaca actually exposed an existing bug that Class::Trait was
really close to triggering already:
undef *ISA; # @ISA no longer magical
Class::Trait’s tests just happened not to call ->isa before making any
changes to @ISA.
Now that the meta->isa cache is created immediately,
Class::Trait fails.
This bug can be reproduced in earlier perls by putting an ->isa call
right after the undef:
undef *{"Extra::TSpouse::ISA"};
'Extra::TSpouse'->isa('Class::Trait::Base');
unshift @{"Extra::TSpouse::ISA"}, Class::Trait::Base;
warn Extra::TSpouse->isa('Class::Trait::Base'); # something's wrong
This commit modifies gv_fetchpvn_flags to magicalise @ISA whenever it
is fetched.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
with package::ISA
This commit makes @ISA changes and package aliasing update PL_isarev
properly, removing old, unnecessary entries in addition to adding new
entries. So now it is capable of shrinking, not just growing.
------------
Gory Details
------------
There is a chicken-and-egg problem when it comes to calling
mro_isa_changed_in on the affected classes: When an isa linearisation
is recalculated, it uses the existing linearisations of the super-
classes (if any) (or at least the DFS implementation does). Since an
assigned package (e.g., the *b:: in *a:: = *b::) can contain nested
packages that inherit from each other in any order (b::c isa b::c::d
or b::c::e isa b::c), this means that mro_isa_changed_in *must not* be
called on any stash while another stash contains stale data.
So mro_package_moved has been restructured. It is no longer recurs-
ive. The recursive code for iterating through nested stashes has been
moved into a separate, static routine: mro_gather_and_rename. Instead
of calling mro_isa_changed_in during the iteration, it adds all the
classes to ‘the big hash’, which mro_package_moved holds a pointer to.
When mro_gather_and_rename returns, mro_package_moved iterates through
the big hash twice: the first time to wipe caches; the second to call
mro_isa_changed_in on all the stashes.
This ‘big hash’ is now used in place of the seen_stashes that
mro_package_moved used before.
Both mro_package_moved and mro_isa_changed_in now use the existing
mrometa->isa hash to determine which classes used to be superclasses
of the stash in question. A separate routine, S_mro_clean_isarev,
deletes entries mention in isa, except for those that still exist in
the new isa hash.
mro_isa_changed_in now does two iterations through isarev, just like
mro_package_moved. It has to call get_linear_isa on the subclasses so
that it can see what is in the new meta->isa hash created thereby.
Consequently, it has to make sure that all the subclasses have their
caches deleted before it can update anything. It makes the same
changes to isarev for each subclass that are made further down on the
class for which mro_isa_changed_in was called. Yes, it is repetitive.
But calling mro_isa_changed_in recursively has more overhead and would
do more unnecessary work. (Maybe we could make some macros for this
repetitive code.)
The loop through the superclasses near the end of mro_isa_changed_in
no longer adds the subclasses to all the superclasses’ isarev hashes,
because that is taken care of further up.
------------
Side Effects
------------
One result of this change is that mro::is_universal no longer
returns true for classes that are no longer universal. I consider
that a bug fix.
-------------
Miscellaneous
-------------
This also removes obsolete comments in mro_isa_changed_in, concerning
fake and universal flags on stashes, that have been invalid since
dd69841bebe.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
In mro_package_moved, I was calling mro_isa_changed_in, instead
of mro_package_moved, for a deleted package. So its subpackages
were ignored.
Exempli gratia, delete $::{'Cur::'} would call mro_isa_changed_in on
Cur::Cur, but ignore Cur::Cur::Cur.
I probably added this bug (or reinstated it, as it was in 5.13.5) in
d056e33c1.
|
|
|
|
|
| |
The existence of main::main::... caused mro_package_moved to break
Text::Template, and probably Acme::Meta as well.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes the problem of isa cache linearisations’ and method caches’
not being reset on nonexistent packages when they are replaced with
real packages as a result of parent stashes’ being moved. This can
happen in cases like this:
@left::ISA = 'outer::inner';
@right::ISA = 'clone::inner';
{package outer::inner}
*clone:: = \%outer::;
print "ok 1", "\n" if left->isa("clone::inner");
print "ok 2", "\n" if right->isa("outer::inner");
This changes mro_package_moved’s parameter list as documented in the
diff for mro.c. See also the new comments in that function.
|
| |
|
|
|
|
|
|
|
|
| |
This makes string-to-glob assignment and hashref-to-glob assignment
reset isa caches by calling mro_package_moved, if the glob’s name
ends with ::.
Related to [perl #75176].
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
This only applies to glob-to-glob assignments and deletions of stash
elements. Other types of stash manipulation are dealt with by subse-
quent patches.
It adds mro_package_moved, a private function that iterates through
subpackages, calling mro_isa_changed_in on each.
This is related to [perl #75176], but is not the same bug. It simply
got in the way of fixing [perl #75176].
|
|
|
|
|
| |
Stop magic applied to $!, %SIG, et al. from applying to similarly-
named variables in other packages.
|
|
|
|
|
| |
It seems that Dylan Reference Book has been relocated, so included is
the small patch for the vulcan_* test files with the new link.
|