Optimize reversing an array in-place
[p5sagit/p5-mst-13.2.git] / pad.c
diff --git a/pad.c b/pad.c
index 715d361..d80679a 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -355,17 +355,28 @@ If fake, it means we're cloning an existing entry
 */
 
 PADOFFSET
-Perl_pad_add_name(pTHX_ const char *name, HV* typestash, HV* ourstash, bool fake, bool state)
+Perl_pad_add_name(pTHX_ const char *name, const STRLEN len, const U32 flags,
+                 HV *typestash, HV *ourstash)
 {
     dVAR;
     const PADOFFSET offset = pad_alloc(OP_PADSV, SVs_PADMY);
-    SV* const namesv
-       = newSV_type((ourstash || typestash) ? SVt_PVMG : SVt_PVNV);
+    SV *namesv;
 
     PERL_ARGS_ASSERT_PAD_ADD_NAME;
 
     ASSERT_CURPAD_ACTIVE("pad_add_name");
 
+    if (flags & ~(pad_add_STATE|pad_add_FAKE))
+       Perl_croak(aTHX_ "panic: pad_add_name illegal flag bits 0x%" UVxf,
+                  (UV)flags);
+
+    namesv = newSV_type((ourstash || typestash) ? SVt_PVMG : SVt_PVNV);
+
+    /* Until we're using the length for real, cross check that we're being told
+       the truth.  */
+    PERL_UNUSED_ARG(len);
+    assert(strlen(name) == len);
+
     sv_setpv(namesv, name);
 
     if (typestash) {
@@ -378,12 +389,12 @@ Perl_pad_add_name(pTHX_ const char *name, HV* typestash, HV* ourstash, bool fake
        SvOURSTASH_set(namesv, ourstash);
        SvREFCNT_inc_simple_void_NN(ourstash);
     }
-    else if (state) {
+    else if (flags & pad_add_STATE) {
        SvPAD_STATE_on(namesv);
     }
 
     av_store(PL_comppad_name, offset, namesv);
-    if (fake) {
+    if (flags & pad_add_FAKE) {
        SvFAKE_on(namesv);
        DEBUG_Xv(PerlIO_printf(Perl_debug_log,
            "Pad addname: %ld \"%s\" FAKE\n", (long)offset, name));
@@ -540,15 +551,27 @@ C<is_our> indicates that the name to check is an 'our' declaration
 /* XXX DAPM integrate this into pad_add_name ??? */
 
 void
-Perl_pad_check_dup(pTHX_ const char *name, bool is_our, const HV *ourstash)
+Perl_pad_check_dup(pTHX_ const char *name, const STRLEN len, const U32 flags,
+                  const HV *ourstash)
 {
     dVAR;
     SV         **svp;
     PADOFFSET  top, off;
+    const U32  is_our = flags & pad_add_OUR;
 
     PERL_ARGS_ASSERT_PAD_CHECK_DUP;
 
     ASSERT_CURPAD_ACTIVE("pad_check_dup");
+
+    if (flags & ~pad_add_OUR)
+       Perl_croak(aTHX_ "panic: pad_check_dup illegal flag bits 0x%" UVxf,
+                  (UV)flags);
+
+    /* Until we're using the length for real, cross check that we're being told
+       the truth.  */
+    PERL_UNUSED_ARG(len);
+    assert(strlen(name) == len);
+
     if (AvFILLp(PL_comppad_name) < 0 || !ckWARN(WARN_MISC))
        return; /* nothing to check */
 
@@ -568,9 +591,9 @@ Perl_pad_check_dup(pTHX_ const char *name, bool is_our, const HV *ourstash)
            if (is_our && (SvPAD_OUR(sv)))
                break; /* "our" masking "our" */
            Perl_warner(aTHX_ packWARN(WARN_MISC),
-               "\"%s\" variable %s masks earlier declaration in same %s",
+               "\"%s\" variable %"SVf" masks earlier declaration in same %s",
                (is_our ? "our" : PL_parser->in_my == KEY_my ? "my" : "state"),
-               name,
+               sv,
                (COP_SEQ_RANGE_HIGH(sv) == PAD_MAX ? "scope" : "statement"));
            --off;
            break;
@@ -588,7 +611,7 @@ Perl_pad_check_dup(pTHX_ const char *name, bool is_our, const HV *ourstash)
                && strEQ(name, SvPVX_const(sv)))
            {
                Perl_warner(aTHX_ packWARN(WARN_MISC),
-                   "\"our\" variable %s redeclared", name);
+                   "\"our\" variable %"SVf" redeclared", sv);
                if ((I32)off <= PL_comppad_name_floor)
                    Perl_warner(aTHX_ packWARN(WARN_MISC),
                        "\t(Did you mean \"local\" instead of \"our\"?)\n");
@@ -612,7 +635,7 @@ Returns the offset in the current pad, or NOT_IN_PAD on failure.
 */
 
 PADOFFSET
-Perl_pad_findmy(pTHX_ const char *name)
+Perl_pad_findmy(pTHX_ const char *name, STRLEN len, U32 flags)
 {
     dVAR;
     SV *out_sv;
@@ -624,6 +647,22 @@ Perl_pad_findmy(pTHX_ const char *name)
     PERL_ARGS_ASSERT_PAD_FINDMY;
 
     pad_peg("pad_findmy");
+
+    if (flags)
+       Perl_croak(aTHX_ "panic: pad_findmy illegal flag bits 0x%" UVxf,
+                  (UV)flags);
+
+    /* Yes, it is a bug (read work in progress) that we're not really using this
+       length parameter, and instead relying on strlen() later on. But I'm not
+       comfortable about changing the pad API piecemeal to use and rely on
+       lengths. This only exists to avoid an "unused parameter" warning.  */
+    if (len < 2) 
+       return NOT_IN_PAD;
+
+    /* But until we're using the length for real, cross check that we're being
+       told the truth.  */
+    assert(strlen(name) == len);
+
     offset = pad_findlex(name, PL_compcv, PL_cop_seqmax, 1,
                NULL, &out_sv, &out_flags);
     if ((PADOFFSET)offset != NOT_IN_PAD) 
@@ -781,9 +820,9 @@ S_pad_findlex(pTHX_ const char *name, const CV* cv, U32 seq, int warn,
                        ? CvANON(cv) && CvCLONE(cv) && !CvCLONED(cv)
                        : *out_flags & PAD_FAKELEX_ANON)
                {
-                   if (warn && ckWARN(WARN_CLOSURE))
-                       Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
-                           "Variable \"%s\" is not available", name);
+                   if (warn)
+                       Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
+                                      "Variable \"%s\" is not available", name);
                    *out_capture = NULL;
                }
 
@@ -823,9 +862,8 @@ S_pad_findlex(pTHX_ const char *name, const CV* cv, U32 seq, int warn,
                    if (SvPADSTALE(*out_capture)
                        && !SvPAD_STATE(name_svp[offset]))
                    {
-                       if (ckWARN(WARN_CLOSURE))
-                           Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
-                               "Variable \"%s\" is not available", name);
+                       Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
+                                      "Variable \"%s\" is not available", name);
                        *out_capture = NULL;
                    }
                }
@@ -875,11 +913,12 @@ S_pad_findlex(pTHX_ const char *name, const CV* cv, U32 seq, int warn,
 
        new_offset = pad_add_name(
            SvPVX_const(*out_name_sv),
+           SvCUR(*out_name_sv),
+           /* state variable ? */
+           pad_add_FAKE | (SvPAD_STATE(*out_name_sv) ? pad_add_STATE : 0),
            SvPAD_TYPED(*out_name_sv)
                    ? SvSTASH(*out_name_sv) : NULL,
-           SvOURSTASH(*out_name_sv),
-           1,  /* fake */
-           SvPAD_STATE(*out_name_sv) ? 1 : 0 /* state variable ? */
+           SvOURSTASH(*out_name_sv)
        );
 
        new_namesv = AvARRAY(PL_comppad_name)[new_offset];
@@ -1066,11 +1105,10 @@ Perl_pad_leavemy(pTHX)
     if (PL_min_intro_pending && PL_comppad_name_fill < PL_min_intro_pending) {
        for (off = PL_max_intro_pending; off >= PL_min_intro_pending; off--) {
            const SV * const sv = svp[off];
-           if (sv && sv != &PL_sv_undef
-                   && !SvFAKE(sv) && ckWARN_d(WARN_INTERNAL))
-               Perl_warner(aTHX_ packWARN(WARN_INTERNAL),
-                           "%"SVf" never introduced",
-                           SVfARG(sv));
+           if (sv && sv != &PL_sv_undef && !SvFAKE(sv))
+               Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL),
+                                "%"SVf" never introduced",
+                                SVfARG(sv));
        }
     }
     /* "Deintroduce" my variables that are leaving with this scope. */
@@ -1150,7 +1188,7 @@ Mark all the current temporaries for reuse
  * to  a shared TARG.  Such an alias will change randomly and unpredictably.
  * We avoid doing this until we can think of a Better Way.
  * GSAR 97-10-29 */
-void
+static void
 S_pad_reset(pTHX)
 {
     dVAR;
@@ -1310,13 +1348,7 @@ Perl_pad_free(pTHX_ PADOFFSET po)
        SvPADTMP_off(PL_curpad[po]);
 #ifdef USE_ITHREADS
        /* SV could be a shared hash key (eg bugid #19022) */
-       if (
-#ifdef PERL_OLD_COPY_ON_WRITE
-           !SvIsCOW(PL_curpad[po])
-#else
-           !SvFAKE(PL_curpad[po])
-#endif
-           )
+       if (!SvIsCOW(PL_curpad[po]))
            SvREADONLY_off(PL_curpad[po]);      /* could be a freed constant */
 #endif
     }
@@ -1533,9 +1565,8 @@ Perl_cv_clone(pTHX_ CV *proto)
                   while my $x if $false can leave an active var marked as
                   stale. And state vars are always available */
                if (SvPADSTALE(sv) && !SvPAD_STATE(namesv)) {
-                   if (ckWARN(WARN_CLOSURE))
-                       Perl_warner(aTHX_ packWARN(WARN_CLOSURE),
-                           "Variable \"%s\" is not available", SvPVX_const(namesv));
+                   Perl_ck_warner(aTHX_ packWARN(WARN_CLOSURE),
+                                  "Variable \"%s\" is not available", SvPVX_const(namesv));
                    sv = NULL;
                }
                else