This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
"Sub declaration cost reduced from ~500 to ~100 bytes"
authorIlya Zakharevich <ilya@math.ohio-state.edu>
Thu, 14 May 1998 16:00:11 +0000 (16:00 +0000)
committerTim Bunce <TimBunce@ig.ac.uk>
Thu, 14 May 1998 16:00:11 +0000 (16:00 +0000)
Msg-ID:  <199805050607.CAA02050@monk.mps.ohio-state.edu>
 Files:  gv.h gv.c op.c

p4raw-id: //depot/maint-5.004/perl@965

gv.c
gv.h
op.c

diff --git a/gv.c b/gv.c
index 3061705..fc12847 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -93,10 +93,18 @@ STRLEN len;
 int multi;
 {
     register GP *gp;
+    bool doproto = SvTYPE(gv) > SVt_NULL;
+    char *proto = (doproto && SvPOK(gv)) ? SvPVX(gv) : NULL;
 
     sv_upgrade((SV*)gv, SVt_PVGV);
-    if (SvLEN(gv))
-       Safefree(SvPVX(gv));
+    if (SvLEN(gv)) {
+       if (proto) {
+           SvPVX(gv) = NULL;
+           SvLEN(gv) = 0;
+           SvPOK_off(gv);
+       } else
+           Safefree(SvPVX(gv));
+    }
     Newz(602, gp, 1, GP);
     GvGP(gv) = gp_ref(gp);
     GvSV(gv) = NEWSV(72,0);
@@ -109,6 +117,27 @@ int multi;
     GvNAMELEN(gv) = len;
     if (multi)
        GvMULTI_on(gv);
+    if (doproto) {                     /* Replicate part of newSUB here. */
+       ENTER;
+       start_subparse(0,0);            /* Create CV in compcv. */
+       GvCV(gv) = compcv;
+       LEAVE;
+
+       GvCVGEN(gv) = 0;
+       sub_generation++;
+       CvGV(GvCV(gv)) = (GV*)SvREFCNT_inc(gv);
+       CvFILEGV(GvCV(gv)) = curcop->cop_filegv;
+       CvSTASH(GvCV(gv)) = curstash;
+#ifdef USE_THREADS
+       CvOWNER(GvCV(gv)) = 0;
+       New(666, CvMUTEXP(GvCV(gv)), 1, perl_mutex);
+       MUTEX_INIT(CvMUTEXP(GvCV(gv)));
+#endif /* USE_THREADS */
+       if (proto) {
+           sv_setpv((SV*)GvCV(gv), proto);
+           Safefree(proto);
+       }
+    }
 }
 
 static void
@@ -593,13 +622,15 @@ I32 sv_type;
            gv_init_sv(gv, sv_type);
        }
        return gv;
+    } else if (add & GV_NOINIT) {
+       return gv;
     }
 
     /* Adding a new symbol */
 
-    if (add & 4)
+    if (add & GV_ADDWARN)
        warn("Had to create %s unexpectedly", nambeg);
-    gv_init(gv, stash, name, len, add & 2);
+    gv_init(gv, stash, name, len, add & GV_ADDMULTI);
     gv_init_sv(gv, sv_type);
     GvFLAGS(gv) |= add_gvflags;
 
@@ -625,7 +656,7 @@ I32 sv_type;
            AV* av = GvAVn(gv);
            GvMULTI_on(gv);
            sv_magic((SV*)av, (SV*)gv, 'I', Nullch, 0);
-           if (add & 2 && strEQ(nambeg,"AnyDBM_File::ISA") && AvFILL(av) == -1)
+           if ((add & GV_ADDMULTI) && strEQ(nambeg,"AnyDBM_File::ISA") && AvFILL(av) == -1)
            {
                char *pname;
                av_push(av, newSVpv(pname = "NDBM_File",0));
@@ -871,7 +902,7 @@ HV* stash;
            }
            else if (isALPHA(*HeKEY(entry))) {
                gv = (GV*)HeVAL(entry);
-               if (GvMULTI(gv))
+               if (SvTYPE(gv) != SVt_PVGV || GvMULTI(gv))
                    continue;
                curcop->cop_line = GvLINE(gv);
                filegv = GvFILEGV(gv);
diff --git a/gv.h b/gv.h
index 8040075..2cb2438 100644 (file)
--- a/gv.h
+++ b/gv.h
@@ -130,3 +130,4 @@ HV *GvHVn();
 #define GV_ADD         0x01
 #define GV_ADDMULTI    0x02
 #define GV_ADDWARN     0x04
+#define GV_NOINIT      0x10    /* 8 is used without a symbolic constant */
diff --git a/op.c b/op.c
index c8098fb..70378d0 100644 (file)
--- a/op.c
+++ b/op.c
@@ -3328,7 +3328,8 @@ OP *proto;
 OP *block;
 {
     char *name = o ? SvPVx(cSVOPo->op_sv, na) : Nullch;
-    GV *gv = gv_fetchpv(name ? name : "__ANON__", GV_ADDMULTI, SVt_PVCV);
+    GV *gv = gv_fetchpv(name ? name : "__ANON__",
+                       GV_ADDMULTI | (block ? 0 : GV_NOINIT), SVt_PVCV);
     char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, na) : Nullch;
     register CV *cv;
     I32 ix;
@@ -3338,6 +3339,23 @@ OP *block;
     if (proto)
        SAVEFREEOP(proto);
 
+    if (SvTYPE(gv) != SVt_PVGV) {      /* Prototype now, and had
+                                          maximum a prototype before. */
+       if (SvTYPE(gv) > SVt_NULL) {
+           if (!SvPOK((SV*)gv) && !(SvIOK((SV*)gv) && SvIVX((SV*)gv) == -1))
+               warn("Runaway prototype");
+           cv_ckproto((CV*)gv, NULL, ps);
+       }
+       if (ps)
+           sv_setpv((SV*)gv, ps);
+       else
+           sv_setiv((SV*)gv, -1);
+       SvREFCNT_dec(compcv);
+       compcv = NULL;
+       sub_generation++;
+       goto noblock;
+    }
+
     if (!name || GvCVGEN(gv))
        cv = Nullcv;
     else if (cv = GvCV(gv)) {
@@ -3414,6 +3432,7 @@ OP *block;
        }
     }
     if (!block) {
+      noblock:
        copline = NOLINE;
        LEAVE_SCOPE(floor);
        return cv;