This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Store the BM table in mg_ptr instead of after SvCUR().
[perl5.git] / ext / B / B.xs
index b439236..44f8402 100644 (file)
@@ -258,7 +258,7 @@ make_sv_object(pTHX_ SV *sv)
     IV iv;
     dMY_CXT;
 
-    for (iv = 0; iv < sizeof(specialsv_list)/sizeof(SV*); iv++) {
+    for (iv = 0; iv < (IV)(sizeof(specialsv_list)/sizeof(SV*)); iv++) {
        if (sv == specialsv_list[iv]) {
            type = "B::SPECIAL";
            break;
@@ -959,6 +959,9 @@ next(o)
            ret = sv_2mortal(newSVpv(*((char **)ptr), 0));
            break;
 #endif
+       default:
+           croak("Illegal alias 0x%08x for B::*next", (unsigned)ix);
+
        }
        ST(0) = ret;
        XSRETURN(1);
@@ -1367,8 +1370,13 @@ MODULE = B       PACKAGE = B::IV
 #define PVMG_stash_ix  sv_SVp | offsetof(struct xpvmg, xmg_stash)
 
 #if PERL_VERSION >= 10
+#  if PERL_VERSION > 14
+#    define PVBM_useful_ix     sv_I32p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_useful)
+#    define PVBM_previous_ix   sv_UVp | offsetof(struct xpvuv, xuv_uv)
+#  else
 #define PVBM_useful_ix sv_I32p | offsetof(struct xpvgv, xiv_u.xivu_i32)
 #define PVBM_previous_ix    sv_U32p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_previous)
+#  endif
 #define PVBM_rare_ix   sv_U8p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_rare)
 #else
 #define PVBM_useful_ix sv_I32p | offsetof(struct xpvbm, xbm_useful)
@@ -1516,6 +1524,8 @@ IVX(sv)
        case (U8)(sv_U16p >> 16):
            ret = sv_2mortal(newSVuv(*((U16 *)ptr)));
            break;
+       default:
+           croak("Illegal alias 0x%08x for B::*IVX", (unsigned)ix);
        }
        ST(0) = ret;
        XSRETURN(1);
@@ -1609,20 +1619,42 @@ PV(sv)
        U32 utf8 = 0;
     CODE:
        if (ix == 3) {
+#ifndef PERL_FBM_TABLE_OFFSET
+           const MAGIC *const mg = mg_find(sv, PERL_MAGIC_bm);
+
+           if (!mg)
+                croak("argument to B::BM::TABLE is not a PVBM");
+           p = mg->mg_ptr;
+           len = mg->mg_len;
+#else
            p = SvPV(sv, len);
            /* Boyer-Moore table is just after string and its safety-margin \0 */
            p += len + PERL_FBM_TABLE_OFFSET;
            len = 256;
+#endif
        } else if (ix == 2) {
            /* This used to read 257. I think that that was buggy - should have
-              been 258. (The "\0", the flags byte, and 256 for the table.  Not
-              that anything anywhere calls this method.  NWC.  */
-           /* Also, the start pointer has always been SvPVX(sv). Surely it
-              should be SvPVX(sv) + SvCUR(sv)?  The code has faithfully been
-              refactored with this behaviour, since PVBM was added in
-              651aa52ea1faa806.  */
+              been 258. (The "\0", the flags byte, and 256 for the table.)
+              The only user of this method is B::Bytecode in B::PV::bsave.
+              I'm guessing that nothing tested the runtime correctness of
+              output of bytecompiled string constant arguments to index (etc).
+
+              Note the start pointer is and has always been SvPVX(sv), not
+              SvPVX(sv) + SvCUR(sv) PVBM was added in 651aa52ea1faa806, and
+              first used by the compiler in 651aa52ea1faa806. It's used to
+              get a "complete" dump of the buffer at SvPVX(), not just the
+              PVBM table. This permits the generated bytecode to "load"
+              SvPVX in "one" hit.
+
+              5.15 and later store the BM table via MAGIC, so the compiler
+              should handle this just fine without changes if PVBM now
+              always returns the SvPVX() buffer.  */
            p = SvPVX_const(sv);
+#ifdef PERL_FBM_TABLE_OFFSET
            len = SvCUR(sv) + (SvVALID(sv) ? 256 + PERL_FBM_TABLE_OFFSET : 0);
+#else
+           len = SvCUR(sv);
+#endif
        } else if (ix) {
            p = SvPVX(sv);
            len = strlen(p);
@@ -1636,7 +1668,7 @@ PV(sv)
               to avoid tripping up over variable names in the pads.  */
            if((SvLEN(sv) && len >= SvLEN(sv))) {
                /* It claims to be longer than the space allocated for it -
-                  presuambly it's a variable name in the pad  */
+                  presumably it's a variable name in the pad  */
                len = strlen(p);
            }
 #endif
@@ -1808,6 +1840,8 @@ SV(gv)
        case (U8)(line_tp >> 16):
            ret = sv_2mortal(newSVuv(*((line_t *)ptr)));
            break;
+       default:
+           croak("Illegal alias 0x%08x for B::*SV", (unsigned)ix);
        }
        ST(0) = ret;
        XSRETURN(1);
@@ -1952,12 +1986,12 @@ void
 HvARRAY(hv)
        B::HV   hv
     PPCODE:
-       if (HvKEYS(hv) > 0) {
+       if (HvUSEDKEYS(hv) > 0) {
            SV *sv;
            char *key;
            I32 len;
            (void)hv_iterinit(hv);
-           EXTEND(sp, HvKEYS(hv) * 2);
+           EXTEND(sp, HvUSEDKEYS(hv) * 2);
            while ((sv = hv_iternextsv(hv, &key, &len))) {
                mPUSHp(key, len);
                PUSHs(make_sv_object(aTHX_ sv));