develooper Front page | perl.perl5.porters | Postings from May 2010

Re: [perl #68192] Tied scalar numeric FETCH corruption afterSTORE()ing a reference

Thread Previous | Thread Next
Dave Mitchell
May 21, 2010 06:44
Re: [perl #68192] Tied scalar numeric FETCH corruption afterSTORE()ing a reference
Message ID:
On Mon, May 17, 2010 at 12:03:41PM +0100, Dave Mitchell wrote:
> On Sun, May 16, 2010 at 12:00:55PM -0700, Father Chrysostomos wrote:
> > OK, let’s try this again:
> >
> > sv_2num doesn’t take get-magic into account, so a tied scalar containing 
> > a reference is not treated as tied, at least not by numeric ops.
> >
> > In trying to fix this, I found that most ops check for overloading  
> > before get-magic, which causes the wrong overload methods to be used.  
> > Fixing this problem fixes the original bug ‘for free’, so I followed  
> > this approach.
> Urgh. I've just spent the last week working in a similar area, although
> I've been working and making all overloadable ops respect magic, not just
> numeric ones. I've also been reorganising things to reduce the binary and
> size and make things faster. I'm not sure yet how much overlap there is
> between our two efforts :-(. I'll look into this soon.

I've now applied my commit shown below. Its a more general fix than
yours, since it deals with all overloaded ops not just the basic numeric
ones. However, your suggested patch was very useful, since it hadn't
occurred to me to include checks for how many times FETCH was called, and
it also showed me some ones I'd missed (like dPOPnv). So thanks!

The other main thing I did was to take the opportunity to make the code
more efficient. The macros formerly at the start of each op, such as
tryAMAGICbin(add,opASSIGN) incorporated a big blob of similar code into
each function. I've now put most of that into separate helper functions,
with a simple "are any of the args ROK/GMG" test on whether to call the
helper function:

    #define tryAMAGICbin_MG(method, flags) STMT_START { \
	    if ( ((SvFLAGS(TOPm1s)|SvFLAGS(TOPs)) & (SVf_ROK|SVs_GMG)) \
		    && Perl_try_amagic_bin(aTHX_ method, flags)) \
		return NORMAL; \

This means that simple data (not tied, not overloaded etc)
will take a quicker code path. As a demonstration, the code below (which
heavily tests pp_add with simple args) is reduced from (lowest time of 5




a saving of 15%.

    #!/usr/bin/perl -w

    use Time::HiRes qw(gettimeofday tv_interval);

    $t0 = [gettimeofday];
    my $x = 0;
    for (1..5_000_000) {
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;
	$x+= 1;

    printf "elapsed=%f\n", tv_interval($t0);

commit 6f1401dc2acd2a2b85df22b0a74e5f7e6e0a33aa
Author:     David Mitchell <>
AuthorDate: Fri May 21 14:18:21 2010 +0100
Commit:     David Mitchell <>
CommitDate: Fri May 21 14:18:21 2010 +0100

    make overload respect get magic
    In most places, ops checked their args for overload *before* doing
    mg_get(). This meant that, among other issues, tied vars that
    returned overloaded objects wouldn't trigger calling the
    overloaded method.  (Actually, for tied and arrays and hashes, it
    still often would since mg_get gets called beforehand in rvalue
    This patch does the following:
    Makes sure get magic is called first.
    Moves most of the overload code formerly included by macros at the
    start of each pp function into the separate helper functions
    Perl_try_amagic_bin, Perl_try_amagic_un, S_try_amagic_ftest,
    with 3 new wrapper macros:
    tryAMAGICbin_MG, tryAMAGICun_MG, tryAMAGICftest_MG.
    This made the code 3800 bytes smaller.
    Makes sure that FETCH is not called multiple times. Much of this
    bit was helped by some earlier work from Father Chrysostomos.
    Added new functions and macros sv_inc_nomg(), sv_dec_nomg(),
    dPOPnv_nomg, dPOPXiirl_ul_nomg, dPOPTOPnnrl_nomg, dPOPTOPiirl_ul_nomg
    dPOPTOPiirl_nomg, SvIV_please_nomg, SvNV_nomg (again, some of
    these were based on Father Chrysostomos's work).
    Fixed the list version of the repeat operator (x): it now only
    calls overloaded methods for the scalar version:
        (1,2,$overloaded) x 10
    no longer erroneously calls
    The only thing I haven't checked/fixed yet is overloading the
    iterator operator, <>.

Affected files ...
    M	embed.fnc
    M	embed.h
    M	global.sym
    M	gv.c
    M	lib/overload.t
    M	pp.c
    M	pp.h
    M	pp_ctl.c
    M	pp_hot.c
    M	pp_sys.c
    M	proto.h
    M	sv.c
    M	sv.h

Never work with children, animals, or actors.

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About