process xhv_backreferences early in S_hfreeentries
authorDavid Mitchell <davem@iabyn.com>
Sun, 4 Jul 2010 19:51:35 +0000 (20:51 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 14 Jul 2010 22:06:16 +0000 (23:06 +0100)
commit044d8c24fa9214cf0fe9c6fc8a44e03f3f5374d7
treefb7c4f1cf47a56b809c8e3be0d96e72b5e6d1cf8
parentfd2c61bcfdb4c097be4d3934b00729bb46787824
process xhv_backreferences early in S_hfreeentries

When deleting a stash, make the algorithm
    GvSTASH($_) = NULL for (@xhv_backreferences);
    delete xhv_backreferences;
    free each stash entry;

Previously the algorithm was

    hide xhv_backreferences as ordinary backref magic;
    free each stash entry:
this may trigger a sv_del_backref() for each GV being freed
    delete @xhv_backreferences

The new method is:

* more efficient: one scan through @xhv_backreferences rather than lots of
calls to sv_del_backref(), removing elements one by one;

* makes the code simpler; the 'hide xhv_backreferences as backref magic'
hack no longer needs to be done

* removes a bug whereby GVs that had a refcnt > 1 (the usual case) were
left with a GvSTASH pointing to the freed stash; it's now NULL instead. I
couldn't think of a test for this.

There are two drawbacks:

* If the GV gets freed at the same time as the stash, the freeing code
sees the GV with a GVSTASH of NULL rather than still pointing to the
stash.

* As far as I can see, the only difference this currently makes is that
mro_method_changed_in() is no longer called by sv_clear(), but since we're
blowing away the whole stash anyway, method resolution doesn't really
bother us any more.

At some point in the future I might set GvSTASH to %__ANON__ rather than
NULL.
embed.fnc
embed.h
hv.c
proto.h
sv.c