summaryrefslogtreecommitdiff
path: root/t/mro
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-11-20 11:33:59 -0800
committerFather Chrysostomos <sprout@cpan.org>2010-11-20 18:15:14 -0800
commit745edda6f1b4ede54e0225b4d1528e96dc0217a0 (patch)
tree46beee2506a78623adaa057176519956408dfbb6 /t/mro
parent8581adba64260d29041e9d7dc923a10b2ab2424f (diff)
downloadperl-745edda6f1b4ede54e0225b4d1528e96dc0217a0.tar.gz
Make hv_undef leave HvENAME alone
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.
Diffstat (limited to 't/mro')
-rw-r--r--t/mro/package_aliases.t21
1 files changed, 20 insertions, 1 deletions
diff --git a/t/mro/package_aliases.t b/t/mro/package_aliases.t
index 29c0a9593d..1622251c1f 100644
--- a/t/mro/package_aliases.t
+++ b/t/mro/package_aliases.t
@@ -10,7 +10,7 @@ BEGIN {
use strict;
use warnings;
-plan(tests => 21);
+plan(tests => 23);
{
package New;
@@ -288,3 +288,22 @@ pass("mro_package_moved and self-referential packages");
is $accum, 'aoeaa-<undef>',
'Deleting globs whose loc in the symtab differs from gv_fullname'
}
+
+# Pathological test for undeffing a stash that has an alias.
+*Ghelp:: = *Neen::;
+@Subclass::ISA = 'Ghelp';
+undef %Ghelp::;
+sub Frelp::womp { "clumpren" }
+eval '
+ $Neen::whatever++;
+ @Neen::ISA = "Frelp";
+';
+is eval { 'Subclass'->womp }, 'clumpren',
+ 'Changes to @ISA after undef via original name';
+undef %Ghelp::;
+eval '
+ $Ghelp::whatever++;
+ @Ghelp::ISA = "Frelp";
+';
+is eval { 'Subclass'->womp }, 'clumpren',
+ 'Changes to @ISA after undef via alias';