diff options
author | Nicholas Clark <nick@ccl4.org> | 2006-10-07 22:06:19 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2006-10-07 22:06:19 +0000 |
commit | fafee734dd1789ab8d2c4d54e0089d2894535aeb (patch) | |
tree | 4331b683ab5d7fecade97cd6d7ffed121d2336f7 | |
parent | e52c0e5ac309b0c21b42bc1225acdeaa1ca6b14a (diff) | |
download | perl-fafee734dd1789ab8d2c4d54e0089d2894535aeb.tar.gz |
Make reference stringification (blessed and unblessed) about as fast as
is possible, because I'm told it's used quite frequently.
p4raw-id: //depot/perl@28961
-rw-r--r-- | sv.c | 72 |
1 files changed, 60 insertions, 12 deletions
@@ -2729,12 +2729,15 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags) } } { - SV *tsv; + STRLEN len; + char *retval; + char *buffer; MAGIC *mg; const SV *const referent = (SV*)SvRV(sv); if (!referent) { - tsv = sv_2mortal(newSVpvs("NULLREF")); + len = 7; + retval = buffer = savepvn("NULLREF", len); } else if (SvTYPE(referent) == SVt_PVMG && ((SvFLAGS(referent) & (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG)) @@ -2743,21 +2746,66 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags) return stringify_regexp(sv, mg, lp); } else { const char *const typestr = sv_reftype(referent, 0); + const STRLEN typelen = strlen(typestr); + UV addr = PTR2UV(referent); + const char *stashname = NULL; + STRLEN stashnamelen = 0; /* hush, gcc */ + const char *buffer_end; - tsv = sv_newmortal(); if (SvOBJECT(referent)) { - const char *const name = HvNAME_get(SvSTASH(referent)); - Perl_sv_setpvf(aTHX_ tsv, "%s=%s(0x%"UVxf")", - name ? name : "__ANON__" , typestr, - PTR2UV(referent)); + const HEK *const name = HvNAME_HEK(SvSTASH(referent)); + + if (name) { + stashname = HEK_KEY(name); + stashnamelen = HEK_LEN(name); + + if (HEK_UTF8(name)) { + SvUTF8_on(sv); + } else { + SvUTF8_off(sv); + } + } else { + stashname = "__ANON__"; + stashnamelen = 8; + } + len = stashnamelen + 1 /* = */ + typelen + 3 /* (0x */ + + 2 * sizeof(UV) + 2 /* )\0 */; + } else { + len = typelen + 3 /* (0x */ + + 2 * sizeof(UV) + 2 /* )\0 */; } - else - Perl_sv_setpvf(aTHX_ tsv, "%s(0x%"UVxf")", typestr, - PTR2UV(referent)); + + Newx(buffer, len, char); + buffer_end = retval = buffer + len; + + /* Working backwards */ + *--retval = '\0'; + *--retval = ')'; + do { + *--retval = PL_hexdigit[addr & 15]; + } while (addr >>= 4); + *--retval = 'x'; + *--retval = '0'; + *--retval = '('; + + retval -= typelen; + memcpy(retval, typestr, typelen); + + if (stashname) { + *--retval = '='; + retval -= stashnamelen; + memcpy(retval, stashname, stashnamelen); + } + /* retval may not neccesarily have reached the start of the + buffer here. */ + assert (retval >= buffer); + + len = buffer_end - retval - 1; /* -1 for that \0 */ } if (lp) - *lp = SvCUR(tsv); - return SvPVX(tsv); + *lp = len; + SAVEFREEPV(buffer); + return retval; } } if (SvREADONLY(sv) && !SvOK(sv)) { |