From: Nicholas Clark Date: Fri, 4 Jan 2008 23:12:01 +0000 (+0000) Subject: Re-implement the SvOOK() hack to store the offset as a BER encoded X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7a4bba223aa750dd886fe6a2fddef224e59c717f;p=p5sagit%2Fp5-mst-13.2.git Re-implement the SvOOK() hack to store the offset as a BER encoded number in the part of the PVX that is being released. (It will always fit, as chopping off 1 byte gives just enough space for recording a delta of up to 127). This allows SvOOK() to co-exist with SvIOK_on(), which means all the calls to SvOOK_off() [with the possibility of a call to sv_backoff()] in SvIOK_on() can be removed. This ought to make a lot of straight line code a little bit simpler. OOK()d scalars can now be SVt_PV, as the IVX isn't needed. p4raw-id: //depot/perl@32836 --- diff --git a/dump.c b/dump.c index 90f44ee..9312bf4 100644 --- a/dump.c +++ b/dump.c @@ -1539,8 +1539,6 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo Perl_dump_indent(aTHX_ level, file, " UV = %"UVuf, (UV)SvUVX(sv)); else Perl_dump_indent(aTHX_ level, file, " IV = %"IVdf, (IV)SvIVX(sv)); - if (SvOOK(sv)) - PerlIO_printf(file, " (OFFSET)"); #ifdef PERL_OLD_COPY_ON_WRITE if (SvIsCOW_shared_hash(sv)) PerlIO_printf(file, " (HASH)"); @@ -1578,9 +1576,17 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo } if (type <= SVt_PVLV && !isGV_with_GP(sv)) { if (SvPVX_const(sv)) { + UV delta = SvOOK(sv) ? sv_read_offset(sv) : 0; + if (SvOOK(sv)) { + Perl_dump_indent(aTHX_ level, file," OFFSET = %"UVuf"\n", + delta); + } Perl_dump_indent(aTHX_ level, file," PV = 0x%"UVxf" ", PTR2UV(SvPVX_const(sv))); - if (SvOOK(sv)) - PerlIO_printf(file, "( %s . ) ", pv_display(d, SvPVX_const(sv)-SvIVX(sv), SvIVX(sv), 0, pvlim)); + if (SvOOK(sv)) { + PerlIO_printf(file, "( %s . ) ", + pv_display(d, SvPVX_const(sv) - delta, delta, 0, + pvlim)); + } PerlIO_printf(file, "%s", pv_display(d, SvPVX_const(sv), SvCUR(sv), SvLEN(sv), pvlim)); if (SvUTF8(sv)) /* the 6? \x{....} */ PerlIO_printf(file, " [UTF8 \"%s\"]", sv_uni_display(d, sv, 6 * SvCUR(sv), UNI_DISPLAY_QQ)); diff --git a/embed.fnc b/embed.fnc index d36e2fd..2ae0c3b 100644 --- a/embed.fnc +++ b/embed.fnc @@ -881,6 +881,7 @@ Apd |void |sv_pos_b2u |NULLOK SV* sv|NN I32* offsetp Amdb |char* |sv_pvn_force |NN SV* sv|NULLOK STRLEN* lp Apd |char* |sv_pvutf8n_force|NN SV* sv|NULLOK STRLEN* lp Apd |char* |sv_pvbyten_force|NN SV* sv|NULLOK STRLEN* lp +Ap |UV |sv_read_offset |NN const SV *const sv Apd |char* |sv_recode_to_utf8 |NN SV* sv|NN SV *encoding Apd |bool |sv_cat_decode |NN SV* dsv|NN SV *encoding|NN SV *ssv|NN int *offset \ |NN char* tstr|int tlen diff --git a/embed.h b/embed.h index 377266a..72b4640 100644 --- a/embed.h +++ b/embed.h @@ -899,6 +899,7 @@ #define sv_pos_b2u Perl_sv_pos_b2u #define sv_pvutf8n_force Perl_sv_pvutf8n_force #define sv_pvbyten_force Perl_sv_pvbyten_force +#define sv_read_offset Perl_sv_read_offset #define sv_recode_to_utf8 Perl_sv_recode_to_utf8 #define sv_cat_decode Perl_sv_cat_decode #define sv_reftype Perl_sv_reftype @@ -3190,6 +3191,7 @@ #define sv_pos_b2u(a,b) Perl_sv_pos_b2u(aTHX_ a,b) #define sv_pvutf8n_force(a,b) Perl_sv_pvutf8n_force(aTHX_ a,b) #define sv_pvbyten_force(a,b) Perl_sv_pvbyten_force(aTHX_ a,b) +#define sv_read_offset(a) Perl_sv_read_offset(aTHX_ a) #define sv_recode_to_utf8(a,b) Perl_sv_recode_to_utf8(aTHX_ a,b) #define sv_cat_decode(a,b,c,d,e,f) Perl_sv_cat_decode(aTHX_ a,b,c,d,e,f) #define sv_reftype(a,b) Perl_sv_reftype(aTHX_ a,b) diff --git a/global.sym b/global.sym index 021d86b..e5f9d66 100644 --- a/global.sym +++ b/global.sym @@ -539,6 +539,7 @@ Perl_sv_pos_b2u Perl_sv_pvn_force Perl_sv_pvutf8n_force Perl_sv_pvbyten_force +Perl_sv_read_offset Perl_sv_recode_to_utf8 Perl_sv_cat_decode Perl_sv_reftype diff --git a/proto.h b/proto.h index 5bbb593..d276e3a 100644 --- a/proto.h +++ b/proto.h @@ -2355,6 +2355,9 @@ PERL_CALLCONV char* Perl_sv_pvutf8n_force(pTHX_ SV* sv, STRLEN* lp) PERL_CALLCONV char* Perl_sv_pvbyten_force(pTHX_ SV* sv, STRLEN* lp) __attribute__nonnull__(pTHX_1); +PERL_CALLCONV UV Perl_sv_read_offset(pTHX_ const SV *const sv) + __attribute__nonnull__(pTHX_1); + PERL_CALLCONV char* Perl_sv_recode_to_utf8(pTHX_ SV* sv, SV *encoding) __attribute__nonnull__(pTHX_1) __attribute__nonnull__(pTHX_2); diff --git a/sv.c b/sv.c index b514753..883b97f 100644 --- a/sv.c +++ b/sv.c @@ -1397,27 +1397,16 @@ wrapper instead. int Perl_sv_backoff(pTHX_ register SV *sv) { + UV delta = sv_read_offset(sv); + const char * const s = SvPVX_const(sv); PERL_UNUSED_CONTEXT; assert(SvOOK(sv)); assert(SvTYPE(sv) != SVt_PVHV); assert(SvTYPE(sv) != SVt_PVAV); - if (SvIVX(sv)) { - const char * const s = SvPVX_const(sv); -#ifdef DEBUGGING - /* Validate the preceding buffer's sentinels to verify that no-one is - using it. */ - const U8 *p = (const U8*) s; - const U8 *const real_start = p - SvIVX(sv); - while (p > real_start) { - --p; - assert (*p == (U8)PTR2UV(p)); - } -#endif - SvLEN_set(sv, SvLEN(sv) + SvIVX(sv)); - SvPV_set(sv, SvPVX(sv) - SvIVX(sv)); - SvIV_set(sv, 0); - Move(s, SvPVX(sv), SvCUR(sv)+1, char); - } + + SvLEN_set(sv, SvLEN(sv) + delta); + SvPV_set(sv, SvPVX(sv) - delta); + Move(s, SvPVX(sv), SvCUR(sv)+1, char); SvFLAGS(sv) &= ~SVf_OOK; return 0; } @@ -3779,7 +3768,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags) SvNV_set(dstr, SvNVX(sstr)); } if (sflags & SVp_IOK) { - SvOOK_off(dstr); SvIV_set(dstr, SvIVX(sstr)); /* Must do this otherwise some other overloaded use of 0x80000000 gets confused. I guess SVpbm_VALID */ @@ -4202,6 +4190,43 @@ Perl_sv_force_normal_flags(pTHX_ register SV *sv, U32 flags) sv_unglob(sv); } +UV +Perl_sv_read_offset(pTHX_ const SV *const sv) { + U8 *p; + UV delta = 0; + U8 c; + + if (!SvOOK(sv)) + return 0; + p = (U8*)SvPVX_const(sv); + if (!p) + return 0; + + c = *--p; + delta = c & 0x7F; + while ((c & 0x80)) { + UV const last_delta = delta; + delta <<= 7; + if (delta < last_delta) + Perl_croak(aTHX_ "panic: overflow in sv_read_offset from %"UVuf + " to %"UVuf, last_delta, delta); + c = *--p; + delta |= c & 0x7F; + } +#ifdef DEBUGGING + { + /* Validate the preceding buffer's sentinels to verify that no-one is + using it. */ + const U8 *const real_start = (U8 *) SvPVX_const(sv) - delta; + while (p > real_start) { + --p; + assert (*p == (U8)PTR2UV(p)); + } + } +#endif + return delta; +} + /* =for apidoc sv_chop @@ -4219,6 +4244,12 @@ void Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr) { register STRLEN delta; + UV old_delta; + U8 *p; +#ifdef DEBUGGING + const U8 *real_start; +#endif + if (!ptr || !SvPOKp(sv)) return; delta = ptr - SvPVX_const(sv); @@ -4228,8 +4259,6 @@ Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr) } assert(ptr > SvPVX_const(sv)); SV_CHECK_THINKFIRST(sv); - if (SvTYPE(sv) < SVt_PVIV) - sv_upgrade(sv,SVt_PVIV); if (!SvOOK(sv)) { if (!SvLEN(sv)) { /* make copy of shared string */ @@ -4239,27 +4268,47 @@ Perl_sv_chop(pTHX_ register SV *sv, register const char *ptr) Move(pvx,SvPVX(sv),len,char); *SvEND(sv) = '\0'; } - SvIV_set(sv, 0); - /* Same SvOOK_on but SvOOK_on does a SvIOK_off - and we do that anyway inside the SvNIOK_off - */ SvFLAGS(sv) |= SVf_OOK; + old_delta = 0; + } else { + old_delta = sv_read_offset(sv); } - SvNIOK_off(sv); SvLEN_set(sv, SvLEN(sv) - delta); SvCUR_set(sv, SvCUR(sv) - delta); SvPV_set(sv, SvPVX(sv) + delta); - SvIV_set(sv, SvIVX(sv) + delta); + + p = (U8 *)SvPVX_const(sv); + + delta += old_delta; + #ifdef DEBUGGING - { - /* Fill the preceding buffer with sentinals to verify that no-one is - using it. */ - U8 *p = (U8*) SvPVX(sv); - const U8 *const real_start = p - SvIVX(sv); - while (p > real_start) { - --p; - *p = (U8)PTR2UV(p); - } + real_start = p - delta; +#endif + + if (delta < 0x80) { + *--p = (U8) delta; + } else { + /* Code lovingly ripped from pp_pack.c: */ + U8 buf[(sizeof(UV)*CHAR_BIT)/7+1]; + U8 *in = buf; + STRLEN len; + do { + *in++ = (U8)((delta & 0x7f) | 0x80); + delta >>= 7; + } while (delta); + buf[0] &= 0x7f; /* clear continue bit */ + + len = in - buf; + p -= len; + Copy(buf, p, len, U8); + } + +#ifdef DEBUGGING + /* Fill the preceding buffer with sentinals to verify that no-one is + using it. */ + while (p > real_start) { + --p; + *p = (U8)PTR2UV(p); } #endif } @@ -5278,13 +5327,13 @@ Perl_sv_clear(pTHX_ register SV *sv) case SVt_PVMG: case SVt_PVNV: case SVt_PVIV: + case SVt_PV: freescalar: /* Don't bother with SvOOK_off(sv); as we're only going to free it. */ if (SvOOK(sv)) { - SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv)); + SvPV_set(sv, SvPVX_mutable(sv) - sv_read_offset(sv)); /* Don't even bother with turning off the OOK flag. */ } - case SVt_PV: if (SvROK(sv)) { SV * const target = SvRV(sv); if (SvWEAKREF(sv)) diff --git a/sv.h b/sv.h index 960a059..afa18dc 100644 --- a/sv.h +++ b/sv.h @@ -761,7 +761,7 @@ Set the actual length of the string which is in the SV. See C. #define SvOKp(sv) (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) #define SvIOKp(sv) (SvFLAGS(sv) & SVp_IOK) -#define SvIOKp_on(sv) (assert_not_glob(sv) SvRELEASE_IVX(sv), \ +#define SvIOKp_on(sv) (assert_not_glob(sv) SvRELEASE_IVX_(sv) \ SvFLAGS(sv) |= SVp_IOK) #define SvNOKp(sv) (SvFLAGS(sv) & SVp_NOK) #define SvNOKp_on(sv) (assert_not_glob(sv) SvFLAGS(sv) |= SVp_NOK) @@ -770,7 +770,7 @@ Set the actual length of the string which is in the SV. See C. SvFLAGS(sv) |= SVp_POK) #define SvIOK(sv) (SvFLAGS(sv) & SVf_IOK) -#define SvIOK_on(sv) (assert_not_glob(sv) SvRELEASE_IVX(sv), \ +#define SvIOK_on(sv) (assert_not_glob(sv) SvRELEASE_IVX_(sv) \ SvFLAGS(sv) |= (SVf_IOK|SVp_IOK)) #define SvIOK_off(sv) (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK|SVf_IVisUV)) #define SvIOK_only(sv) (SvOK_off(sv), \ @@ -1240,7 +1240,8 @@ the scalar's value cannot change unless written to. if (SvLEN(sv)) { \ assert(!SvROK(sv)); \ if(SvOOK(sv)) { \ - SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv)); \ + SvPV_set(sv, SvPVX_mutable(sv) \ + - sv_read_offset(sv)); \ SvFLAGS(sv) &= ~SVf_OOK; \ } \ Safefree(SvPVX(sv)); \ @@ -1714,10 +1715,16 @@ Like C but doesn't process magic. #ifdef PERL_OLD_COPY_ON_WRITE #define SvRELEASE_IVX(sv) \ - ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), SvOOK_off(sv)) + ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), 0) # define SvIsCOW_normal(sv) (SvIsCOW(sv) && SvLEN(sv)) +# define SvRELEASE_IVX_(sv) SvRELEASE_IVX(sv), #else -# define SvRELEASE_IVX(sv) SvOOK_off(sv) +# define SvRELEASE_IVX(sv) 0 +/* This little game brought to you by the need to shut this warning up: +mg.c: In function `Perl_magic_get': +mg.c:1024: warning: left-hand operand of comma expression has no effect +*/ +# define SvRELEASE_IVX_(sv) /**/ #endif /* PERL_OLD_COPY_ON_WRITE */ #define CAN_COW_MASK (SVs_OBJECT|SVs_GMG|SVs_SMG|SVs_RMG|SVf_IOK|SVf_NOK| \