summaryrefslogtreecommitdiff
path: root/mro.c
Commit message (Collapse)AuthorAgeFilesLines
* Followup to 088225f/[perl #88132]: packages ending with :Father Chrysostomos2011-04-151-18/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Fix typos (spelling errors) in Perl sources.Peter J. Acklam) (via RT2011-01-071-1/+1
| | | | | | | | | # New Ticket Created by (Peter J. Acklam) # Please include the string: [perl #81904] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=81904 > Signed-off-by: Abigail <abigail@abigail.be>
* Fix uninit compiler warning in mro.cJerry D. Hedden2010-12-011-1/+1
|
* mro.c: Assert that the previous commit is correctFather Chrysostomos2010-11-271-0/+1
|
* Avoid a redundant check in mro.cFather Chrysostomos2010-11-271-6/+10
| | | | | | | | | | This code is never reached if oldstash is a hash without an HvENAME. So instead of checking oldstash in the ?:, then hvename in the if(), we can do one check. If oldstash is no longer in the symbol table, then this code is never reached, because of the if(!fetched_isarev) guard.
* Fix a warning (that spotted a potential mro bug that I could not produce)Rafael Garcia-Suarez2010-11-271-8/+7
|
* Use newSVpvs_flags() instead of sv_2mortal(newSVpvs())Nicholas Clark2010-11-251-1/+1
| | | | And similarly for newSVpvn() for a known length.
* Convert xhv_name in struct xpvhv_aux to be a union of HEK* and HEK**Nicholas Clark2010-11-241-3/+3
| | | | | This avoids a lot of casting. Nothing outside the perl core code is accessing that member directly.
* Remove redundant checkFather Chrysostomos2010-11-221-4/+0
| | | | | There is a similar check about fifty lines back. And it is silly to check HvARRAY on a named hash.
* mro_package_moved must act on all effective namesFather Chrysostomos2010-11-221-63/+186
| | | | | | | | | | | | 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.
* Add flags param to hv_ename_*Father Chrysostomos2010-11-201-2/+2
| | | | | We will need this for making the API UTF8-aware in 5.16 or whenever.
* Eliminate the newname param from mro_package_movedFather Chrysostomos2010-11-201-19/+13
| | | | Nothing is using this any more, as of the previous commit.
* Remove unnecessary check in mro_package_movedFather Chrysostomos2010-11-161-1/+0
| | | | | This was supposed to have been removed by 80ebaca, when negative val- ues for the newname_len argument stopped being used.
* Don’t skip mro_package_moved if the parent stash is renamedFather Chrysostomos2010-11-161-2/+8
| | | | | | | 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.
* mro_package_moved only needs one loopFather Chrysostomos2010-11-121-15/+5
| | | | | | | | | | We can avoid the double iteration by doing the first iteration’s job (to clear the linearisations) inside gather_and_rename as the items are added to the stash. The important thing is that they all be cleared before *any* calls to mro_isa_changed_in, which will still be the case. Maybe ‘gather_and_rename’ is not such a good name any more....
* Macro for freeing meta->mro_linear_*Father Chrysostomos2010-11-121-30/+17
|
* Remove redundant call to mro_get_linear_isaFather Chrysostomos2010-11-121-5/+0
| | | | added by 80ebaca, like most of my recent mistakes.
* Update isarev when clobbered class has subsubclassesFather Chrysostomos2010-11-121-8/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* mro_isa_changed_in3 is no longer necessaryFather Chrysostomos2010-11-111-37/+18
| | | | | | | | as of 80ebaca. It was nice while it lasted. This reverts 6f86b615fa.
* Fix package assignment with nested aliased packagesFather Chrysostomos2010-11-111-29/+59
| | | | | | | | | | | | | | | | | | | | | 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.
* Correct comment in mro_isa_changed_inFather Chrysostomos2010-11-111-3/+2
| | | | It was describing an intermediate version of what became 80ebaca.
* Fix memory leaks in mro_package_movedFather Chrysostomos2010-11-101-3/+3
| | | | | | | | | | | | This commit adds a new HV_FETCH_EMPTY_HE flag for hv_common. It is to be used in conjunction with HV_FETCH_LVALUE. It just stops the newly- created HE from having a new undef scalar assigned to it. This allows code to call hv_common just once instead of an hv_exists/ hv_store pair. It was such a double hv_common call that I was trying to avoid with HV_FETCH_LVALUE, without realising that it was leaking.
* [perl #75176] Symbol::delete_package does not free certain memory associated ↵Father Chrysostomos2010-11-081-89/+303
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* [perl #77358] ISA warnings after aliasing packagesFather Chrysostomos2010-10-301-1/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit makes mro_package_moved call mro_isa_changed_in on the stash that has been assigned if it did not have an effective name (HvENAME) before the assignment. This is what was happening: {package Right} # autovivify it @thing::ISA = qw[Left]; *Left:: = delete $::{"Right::"}; When Right is deleted, it is not attached to the symbol table any more, so it has no effective name. mro_isa_changed_in3 is called on it, which resets the caches and then proceeds to cache a new isa linearisation. The new linearisation, of course, does not use the name ‘Left’. When Right is assigned over the top of Left, Right is given an HvENAME of ‘Left’. Then mro_isa_changed_is3 is called on the original Left, which, in turn, calls mro_isa_changed on its sub- classes. So thing’s isa linearisation is calculated, which is just ‘thing’ + get_linear_isa(Left) (where ‘Left’ now refers to what was previously called Right). This ends up using the bad linearisation. So the linearisation of a heretofore effectively nameless stash must be recalculated, but after it has been given a name. If it has an effective name already, then it appears elsewhere in the symbol table, and its effective name does not change. (The name added simply becomes an alternative to switch to should the HvENAME become invalid.) So the existing isa cache is fine and we do not need to call mro_isa_changed_in. (That is a rather lengthy commit message, is it not?)
* Set stash names before calling mro_isa_changed_in3Father Chrysostomos2010-10-301-10/+9
| | | | | mro_isa_changed_in3 cannot update isa caches properly if it only sees an intermediate state.
* Comment typoFather Chrysostomos2010-10-301-1/+1
|
* Move the meta->isa code from UNIVERSAL::isa to mro_get_linear_isaFather Chrysostomos2010-10-301-1/+27
| | | | | | | | This is so that it can be used for PL_isarev bookkeeping as well. This will have no effect on the speed of DFS classes. C3 classes on which ->isa is never called will have a slight slowdown. (We could always add an API for setting meta->isa if we want to avoid that.)
* Switch the core MRO code over to HvENAMEFather Chrysostomos2010-10-291-7/+11
| | | | | | | | | | | | | | | | | | | | | | This has the side-effect of fixing these one-liners: $ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = *a' Bus error $ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = []' Bus error $ perl5.13.6 -le'sub baz; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;' Bus error $ perl5.13.6 -le'sub foo::bar; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;' Bus error In the first two cases the crash was inadvertently fixed (isn’t it nice when that happens?) in 5.13.6 (by 6f86b615fa7), but there was still a fatal error: Can't call mro_isa_changed_in() on anonymous symbol table at -e line 1. Because sv_clear calls ->DESTROY, if an object’s stash has been detached from the symbol table, mro_get_linear_isa can be called on a hash with no HvENAME. So HvNAME is used as a fallback for those cases.
* Renaming of stashes should not be visible from PerlFather Chrysostomos2010-10-271-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | Change 35759254 made stashes get renamed when moved around. This had an unintended consequence: Typeglobs, ref() return values, stringifi- cation of blessed references and __PACKAGE__ are all affected by this. This commit makes a new distinction between stashes’ names and effect- ive names. Stash names are now unaffected when the stashes move around. Only the effective names are affected. (The apparent presence of any puns in the previous sentence is purely incidental and most likely the result of the reader’s inferential propensity.) To this end a new HvENAME_get macro is introduced, returning the first effective name (what HvNAME_get was returning). (Only one effective name needs to be in effect at a time.) hv_add_name and hv_delete_name have been renamed hv_add_ename and hv_delete_ename. hv_name_set is modified to leave the effective names in place unless the name is being set to NULL. These names are now stored in HvAUX as follows: When xhv_name_count is 0, xhv_name is a HEK pointer, containing the name which is also the effective name. When xhv_name_count is not zero, then xhv_name is a pointer to an array of HEK pointers. If xhv_name_count is positive, the first HEK is the name *and* one of the effective names. When xhv_name_count is negative, the first HEK is the name and subsequent HEKs are the effective names.
* Rename stashes when they move aroundFather Chrysostomos2010-10-241-32/+87
| | | | | | | | | | | | | | | | | | | | | | This is yet another patch in preparation for [perl #75176] (I keep saying that.). It uses the recently-added functions hv_name_add and hv_name_delete, to add and remove names when mro_package_moved is called. mro_package_moved’s calling convention needed to change to make this work, which is the bulk of the patch. Code that was calling mro_package_moved was also doing it sometimes when it was unnecessary. If the stash being assigned over had no name, then there was no possibiiity of its being in the symbol table. This probably fixes [perl #77358] (isa warnings), though I have not tested that yet. One user-visible change this introduces is that a detached glob whose stash loses its name will no longer stringify the same way (a bit like a glob that loses its stash pointer; except that it becomes *__ANON__::foo instead of "").
* Make mro_package_moved use a mortal in case mro_isa_changed_in3 croaksFather Chrysostomos2010-10-241-2/+1
|
* Fix a nested package deletion bugFather Chrysostomos2010-10-211-1/+3
| | | | | | | | | | | | 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.
* [perl #78362] Make mro_package_moved check for recursionFather Chrysostomos2010-10-121-6/+25
| | | | | The existence of main::main::... caused mro_package_moved to break Text::Template, and probably Acme::Meta as well.
* Reset isa caches on nonexistent substashes when stash trees are movedFather Chrysostomos2010-10-121-10/+109
| | | | | | | | | | | | | | | | | 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.
* Allow mro_isa_changed_in to be called on nonexistent packagesFather Chrysostomos2010-10-111-17/+36
| | | | | | | | | | | | | | | | | This is necessary for an upcoming bug fix. (For this bug: @left::ISA = 'outer::inner'; @right::ISA = 'clone::inner'; *clone:: = \%outer::; print left->isa('clone::inner'),"\n"; print right->isa('outer::inner'),"\n"; ) This commit actually replaces mro_isa_changed_in with mro_isa_changed_in3. See the docs for it in the diff for mro.c.
* Reset isa on stash manipulationFather Chrysostomos2010-10-091-0/+50
| | | | | | | | | | | | 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].
* Convert Perl_sv_dup_inc() from a macro to a real function.Nicholas Clark2010-05-241-5/+4
|
* Fix build warning in mro.cJerry D. Hedden2009-08-211-1/+1
|
* Optimise S_mro_get_linear_isa_dfs() when dealing with the first parent class.Nicholas Clark2009-08-201-33/+69
| | | | Benchmarking with single inheritance suggests that this is 10% faster.
* When resetting our children, wipe out the isa cache too.Nicholas Clark2009-07-251-1/+5
| | | | (Fix to change 34354, which introduced a cached hash to make ->isa O(1))
* Following change 34356, which decoupled get_isa_hash() fromNicholas Clark2009-01-031-35/+0
| | | | S_mro_get_linear_isa_dfs(), we can move get_isa_hash() to any other source file.
* Add casts to gain C++ compatibility, as spotted by Yves.Nicholas Clark2008-12-281-5/+5
|
* Move all mro:: XS functions from mro.c to ext/mro/mro.xs, except forNicholas Clark2008-12-271-185/+0
| | | | mro::method_changed_in(), which is used by constant.
* In struct mro_meta, rename mro_linear_dfs to mro_linear_all, and change it fromNicholas Clark2008-12-271-14/+14
| | | | AV * to HV *.
* In struct mro_meta, rename mro_linear_c3 to mro_linear_current, and change itNicholas Clark2008-12-271-20/+21
| | | | from AV * to SV *.
* Break out the set-the-MRO logic from the XS_mro_set_mro into Perl_mro_set_mro(),Nicholas Clark2008-12-271-21/+29
| | | | which can be called from C code (such as the guts of extensions).
* Optimisation of the use of the meta structure - don't create a hash if all weNicholas Clark2008-12-271-18/+65
| | | | | are dealing with is data for the current MRO. Instead the direct pointer "owns" the (reference to the) data, with the hash pointer left as NULL to signal this.
* Proper pluggable Method Resolution Orders. 'c3' is now implemented outside theNicholas Clark2008-12-271-442/+0
| | | | | | core, in ext/mro/mro.xs. Also move mro::_nextcan() to mro.xs. It needs direct access to S_mro_get_linear_isa_c3(), and nothing on CPAN calls it, except via methods defined in mro.pm. Hence all users already require mro;
* Add Perl_mro_register() to register Method Resolution Orders,Nicholas Clark2008-12-271-29/+44
| | | | | | Perl_mro_get_from_name() to retrieve MROs by name, and PL_registered_mros to store them in. Abolish the static array of mros, and instead register the dfs and c3 MRO structures.
* Add MRO_GET_PRIVATE_DATA() to use the cached mro private data where possible.Nicholas Clark2008-12-271-2/+2
|