diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-11-20 11:33:59 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-11-20 18:15:14 -0800 |
commit | 745edda6f1b4ede54e0225b4d1528e96dc0217a0 (patch) | |
tree | 46beee2506a78623adaa057176519956408dfbb6 /hv.h | |
parent | 8581adba64260d29041e9d7dc923a10b2ab2424f (diff) | |
download | perl-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 'hv.h')
-rw-r--r-- | hv.h | 3 |
1 files changed, 3 insertions, 0 deletions
@@ -592,6 +592,9 @@ a string/length pair, and no precomputed hash. #define HV_DELETE 0x40 #define HV_FETCH_EMPTY_HE 0x80 /* Leave HeVAL null. */ +/* Must not conflict with HVhek_UTF8 */ +#define HV_NAME_SETALL 0x02 + /* =for apidoc newHV |