Change 31770 by [EMAIL PROTECTED] on 2007/08/31 09:07:51

        Subject: Re: optimize push @ISA, (was Re: parent.pm at 
http://corion.net/perl-dev)
        From: "Brandon Black" <[EMAIL PROTECTED]>
        Date: Sun, 12 Aug 2007 13:36:14 -0700
        Message-ID: <[EMAIL PROTECTED]>

Affected files ...

... //depot/perl/av.c#120 edit
... //depot/perl/embedvar.h#255 edit
... //depot/perl/gv.h#74 edit
... //depot/perl/intrpvar.h#215 edit
... //depot/perl/lib/mro.pm#7 edit
... //depot/perl/mg.c#499 edit
... //depot/perl/perlapi.h#177 edit
... //depot/perl/pp.c#597 edit
... //depot/perl/pp_hot.c#524 edit
... //depot/perl/sv.c#1420 edit

Differences ...

==== //depot/perl/av.c#120 (text) ====
Index: perl/av.c
--- perl/av.c#119~31473~        2007-06-26 09:12:27.000000000 -0700
+++ perl/av.c   2007-08-31 02:07:51.000000000 -0700
@@ -342,11 +342,14 @@
        SvREFCNT_dec(ary[key]);
     ary[key] = val;
     if (SvSMAGICAL(av)) {
+       const MAGIC* const mg = SvMAGIC(av);
        if (val != &PL_sv_undef) {
-           const MAGIC* const mg = SvMAGIC(av);
            sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
        }
-       mg_set((SV*)av);
+       if (PL_delaymagic && mg->mg_type == PERL_MAGIC_isa)
+           PL_delaymagic |= DM_ARRAY;
+       else
+          mg_set((SV*)av);
     }
     return &ary[key];
 }
@@ -428,8 +431,13 @@
        Perl_croak(aTHX_ PL_no_modify);
 
     /* Give any tie a chance to cleanup first */
-    if (SvRMAGICAL(av))
-       mg_clear((SV*)av); 
+    if (SvRMAGICAL(av)) {
+       const MAGIC* const mg = SvMAGIC(av);
+       if (PL_delaymagic && mg->mg_type == PERL_MAGIC_isa)
+           PL_delaymagic |= DM_ARRAY;
+        else
+           mg_clear((SV*)av); 
+    }
 
     if (AvMAX(av) < 0)
        return;

==== //depot/perl/embedvar.h#255 (text+w) ====
Index: perl/embedvar.h
--- perl/embedvar.h#254~31280~  2007-05-25 16:26:33.000000000 -0700
+++ perl/embedvar.h     2007-08-31 02:07:51.000000000 -0700
@@ -116,7 +116,6 @@
 #define PL_defgv               (vTHX->Idefgv)
 #define PL_defoutgv            (vTHX->Idefoutgv)
 #define PL_defstash            (vTHX->Idefstash)
-#define PL_delayedisa          (vTHX->Idelayedisa)
 #define PL_delaymagic          (vTHX->Idelaymagic)
 #define PL_diehook             (vTHX->Idiehook)
 #define PL_dirty               (vTHX->Idirty)
@@ -431,7 +430,6 @@
 #define PL_Idefgv              PL_defgv
 #define PL_Idefoutgv           PL_defoutgv
 #define PL_Idefstash           PL_defstash
-#define PL_Idelayedisa         PL_delayedisa
 #define PL_Idelaymagic         PL_delaymagic
 #define PL_Idiehook            PL_diehook
 #define PL_Idirty              PL_dirty

==== //depot/perl/gv.h#74 (text) ====
Index: perl/gv.h
--- perl/gv.h#73~31396~ 2007-06-15 23:10:19.000000000 -0700
+++ perl/gv.h   2007-08-31 02:07:51.000000000 -0700
@@ -181,6 +181,7 @@
 #define DM_UID   0x003
 #define DM_RUID   0x001
 #define DM_EUID   0x002
+#define DM_ARRAY 0x004
 #define DM_GID   0x030
 #define DM_RGID   0x010
 #define DM_EGID   0x020

==== //depot/perl/intrpvar.h#215 (text) ====
Index: perl/intrpvar.h
--- perl/intrpvar.h#214~31280~  2007-05-25 16:26:33.000000000 -0700
+++ perl/intrpvar.h     2007-08-31 02:07:51.000000000 -0700
@@ -180,8 +180,6 @@
 PERLVARI(Iregmatch_slab, regmatch_slab *,      NULL)
 PERLVAR(Iregmatch_state, regmatch_state *)
 
-PERLVARI(Idelayedisa,  HV*,    NULL)   /* stash for PL_delaymagic for 
magic_setisa */
-
 /* Put anything new that is pointer aligned here. */
 
 PERLVAR(Idelaymagic,   U16)            /* ($<,$>) = ... */

==== //depot/perl/lib/mro.pm#7 (text) ====
Index: perl/lib/mro.pm
--- perl/lib/mro.pm#6~31332~    2007-06-04 01:04:13.000000000 -0700
+++ perl/lib/mro.pm     2007-08-31 02:07:51.000000000 -0700
@@ -319,8 +319,8 @@
 
 Specifying the mro type of a class before setting C<@ISA> will
 be faster than the other way around.  Also, making all of your
-C<@ISA> manipulations in a single assignment statement will be
-faster that doing them one by one via C<push> (which is what
+C<@ISA> manipulations in a single assignment or push statement
+will be faster that doing them one by one (which is what
 C<use base> does currently).
 
 Examples:
@@ -330,23 +330,29 @@
   use base qw/A B C/;
   use mro 'c3';
 
+  # Equivalently slow
+  package Foo;
+  our @ISA;
+  require A; push(@ISA, 'A');
+  require B; push(@ISA, 'B');
+  require C; push(@ISA, 'C');
+  use mro 'c3';
+
   # The fastest way
   # (not exactly equivalent to above,
   #   as base.pm can do other magic)
+  package Foo;
   use mro 'c3';
-  use A ();
-  use B ();
-  use C ();
+  require A;
+  require B;
+  require C;
   our @ISA = qw/A B C/;
 
 Generally speaking, every time C<@ISA> is modified, the MRO
-of that class will be recalculated, because of the way array
-magic works.  Pushing multiple items onto C<@ISA> in one push
-statement still counts as multiple modifications.  However,
-assigning a list to C<@ISA> only counts as a single
-modification.  Thus if you really need to do C<push> as
-opposed to assignment, C<@ISA = (@ISA, qw/A B C/);>
-will still be faster than C<push(@ISA, qw/A B C/);>
+of that class will be recalculated because of the way array
+magic works.  Cutting down on unecessary recalculations is
+a win, especially with complex class hierarchies and/or
+the c3 mro.
 
 =head1 SEE ALSO
 

==== //depot/perl/mg.c#499 (text) ====
Index: perl/mg.c
--- perl/mg.c#498~31765~        2007-08-30 06:49:14.000000000 -0700
+++ perl/mg.c   2007-08-31 02:07:51.000000000 -0700
@@ -1528,6 +1528,10 @@
     /* Bail out if destruction is going on */
     if(PL_dirty) return 0;
 
+    /* Skip _isaelem because _isa will handle it shortly */
+    if (PL_delaymagic & DM_ARRAY && mg->mg_type == PERL_MAGIC_isaelem)
+       return 0;
+
     /* XXX Once it's possible, we need to
        detect that our @ISA is aliased in
        other stashes, and act on the stashes
@@ -1542,10 +1546,7 @@
             : (GV*)SvMAGIC(mg->mg_obj)->mg_obj
     );
 
-    if(PL_delaymagic)
-        PL_delayedisa = stash;
-    else
-        mro_isa_changed_in(stash);
+    mro_isa_changed_in(stash);
 
     return 0;
 }

==== //depot/perl/perlapi.h#177 (text+w) ====
Index: perl/perlapi.h
--- perl/perlapi.h#176~31280~   2007-05-25 16:26:33.000000000 -0700
+++ perl/perlapi.h      2007-08-31 02:07:51.000000000 -0700
@@ -268,8 +268,6 @@
 #define PL_defoutgv            (*Perl_Idefoutgv_ptr(aTHX))
 #undef  PL_defstash
 #define PL_defstash            (*Perl_Idefstash_ptr(aTHX))
-#undef  PL_delayedisa
-#define PL_delayedisa          (*Perl_Idelayedisa_ptr(aTHX))
 #undef  PL_delaymagic
 #define PL_delaymagic          (*Perl_Idelaymagic_ptr(aTHX))
 #undef  PL_diehook

==== //depot/perl/pp.c#597 (text) ====
Index: perl/pp.c
--- perl/pp.c#596~31765~        2007-08-30 06:49:14.000000000 -0700
+++ perl/pp.c   2007-08-31 02:07:51.000000000 -0700
@@ -4420,12 +4420,17 @@
        PUSHi( AvFILL(ary) + 1 );
     }
     else {
+       PL_delaymagic = DM_DELAY;
        for (++MARK; MARK <= SP; MARK++) {
            SV * const sv = newSV(0);
            if (*MARK)
                sv_setsv(sv, *MARK);
            av_store(ary, AvFILLp(ary)+1, sv);
        }
+       if (PL_delaymagic & DM_ARRAY)
+           mg_set((SV*)ary);
+
+       PL_delaymagic = 0;
        SP = ORIGMARK;
        PUSHi( AvFILLp(ary) + 1 );
     }

==== //depot/perl/pp_hot.c#524 (text) ====
Index: perl/pp_hot.c
--- perl/pp_hot.c#523~31508~    2007-06-30 09:19:33.000000000 -0700
+++ perl/pp_hot.c       2007-08-31 02:07:51.000000000 -0700
@@ -1122,6 +1122,9 @@
            PL_egid = PerlProc_getegid();
        }
        PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
+
+       if (PL_delaymagic & DM_ARRAY && SvMAGICAL((SV*)ary))
+           mg_set((SV*)ary);
     }
     PL_delaymagic = 0;
 
@@ -1152,14 +1155,6 @@
            *relem++ = (lelem <= lastlelem) ? *lelem++ : &PL_sv_undef;
     }
 
-    /* This is done at the bottom and in this order because
-       mro_isa_changed_in() can throw exceptions */
-    if(PL_delayedisa) {
-        HV* stash = PL_delayedisa;
-        PL_delayedisa = NULL;
-        mro_isa_changed_in(stash);
-    }
-
     RETURN;
 }
 

==== //depot/perl/sv.c#1420 (text) ====
Index: perl/sv.c
--- perl/sv.c#1419~31765~       2007-08-30 06:49:14.000000000 -0700
+++ perl/sv.c   2007-08-31 02:07:51.000000000 -0700
@@ -11167,7 +11167,6 @@
 
     PL_sub_generation  = proto_perl->Isub_generation;
     PL_isarev          = hv_dup_inc(proto_perl->Iisarev, param);
-    PL_delayedisa      = hv_dup_inc(proto_perl->Idelayedisa, param);
 
     /* funky return mechanisms */
     PL_forkprocess     = proto_perl->Iforkprocess;
End of Patch.

Reply via email to