Thanks MarkM for pointing me in the right direction here. Now I'm gonna bug you a little further with some off-the-cuff source diving... I hope you don't mind.

The relevant part of pp.c for a hash seems to be the following

if (SvTYPE(hv) == SVt_PVHV) { if (hv_exists_ent(hv, tmpsv, 0)) RETPUSHYES; }

Which leads us to hv.c:hv_exists_ent() as you pointed out. The relevant part (ignoring for the moment magical and %ENV variations) seems to be:

entry = ((HE**)xhv->xhv_array)[hash & (I32) xhv->xhv_max]; for (; entry; entry = HeNEXT(entry)) { if (HeHASH(entry) != hash) /* strings can't be equal */ + continue; if (HeKLEN(entry) != klen) continue; * if (memNE(HeKEY(entry),key,klen)) /* is this it? */ * continue; * return TRUE; }

With the salient bit being the three lines I've *'d. If I'm reading that correctly it saying

If the memory for the KEY for this entry is NotEqual to the key we've been passed, continue looking.

Otherwise we found it so return TRUE.

Now, if we return TRUE the calling code (pp.c:PP(pp_exists)) does a RETPUSHYES.

Unwinding that macro we find

pp.h:#define RETPUSHYES RETURNX(PUSHs(&PL_sv_yes)) pp.h:#define RETURNX(x) return x, PUTBACK, NORMAL pp.h:#define PUSHs(s) (*++sp = (s)) perlapi.h:#define PL_sv_yes (*Perl_Isv_yes_ptr(aTHXo)) pp.h:#define NORMAL PL_op->op_next pp.h:#define PUTBACK PL_stack_sp = sp

Which preprocesses to

return ( *++sp = ( &( *Perl_Isv_yes_ptr( aTHXo ) ) ) ) , PL_stack_sp = sp , PL_op->op_next;

I think that we can ignore the last two lines which are just setting up the stack and returning the next op-code.

The relevant part here is the address of something located as an offset in the aTHXo struct is being pushed onto the stack.

Now given that at the point in hv_exists_ent() where TRUE is returned, we have access to the entry for the hash entity being tested, and that given this we can use the HeVAL macro to obtain the address of the associated value.

#define HeVAL(he)          (he)->hent_val

If instead of returning TRUE from hv_exists_ent(), if we returned HeVAL(entry), and the code in pp.c:PP(pp_exists) became:

if (SvTYPE(hv) == SVt_PVHV) { SV* sv; if (sv = hv_exists_ent(hv, tmpsv, 0)) RETURNX(sv); }

Then the exists function would return a reference to the value as JMD wanted without any great overhead.

I realised I've only described the exists( hash_element ) case here, but without going into it to far, it looks as though similar changes would take care of the array element case as well. I git lost trying to look at the other cases.

I also realise that I am quite likely to have missed something trying to unwind this. If I have, I really like someone to point out what it is:^)

On a somewhat related note: Can anyone tell me why the indentation on the source modules is so... erm... ecclectic?


Examine what is said, not who speaks.

The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.


In reply to Re: Re: Re: Re: optimization - exists should return a reference by BrowserUk
in thread optimization - exists should return a reference by John M. Dlugosz

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.