This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Speed up method calls like $o->Other::method() and $o->Other::SUPER::method().
authorsyber <syber@crazypanda.ru>
Mon, 1 Dec 2014 20:20:27 +0000 (23:20 +0300)
committerFather Chrysostomos <sprout@cpan.org>
Wed, 3 Dec 2014 01:56:48 +0000 (17:56 -0800)
It was done by adding new OP_METHOD_REDIR and OP_METHOD_REDIR_SUPER optypes.
Class name to redirect is saved into METHOP as a shared hash string.
Method name is changed (class name removed) an saved into op_meth_sv as
a shared string hash.

So there is no need now to scan for '::' and calculate class and method names
at runtime (in gv_fetchmethod_*) and searching cache HV without precomputed hash.

B::* modules are changed to support new op types.
method_redir is now printed by Concise like (for threaded perl)
$obj->AAA::meth
5        <.> method_redir[PACKAGE "AAA", PV "meth"] ->6

13 files changed:
dump.c
ext/B/B.xs
ext/B/B/Concise.pm
ext/Opcode/Opcode.pm
lib/B/Deparse.pm
lib/B/Op_private.pm
op.c
op.h
opcode.h
opnames.h
pp_hot.c
pp_proto.h
regen/opcodes

diff --git a/dump.c b/dump.c
index 2781ada..5f2b07e 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -956,6 +956,8 @@ Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o)
     case OP_HINTSEVAL:
     case OP_METHOD_NAMED:
     case OP_METHOD_SUPER:
+    case OP_METHOD_REDIR:
+    case OP_METHOD_REDIR_SUPER:
 #ifndef USE_ITHREADS
        /* with ITHREADS, consts are stored in the pad, and the right pad
         * may not be active here, so skip */
index d08750c..da05cc1 100644 (file)
@@ -751,6 +751,11 @@ struct OP_methods {
   { STR_WITH_LEN("first"),   op_offset_special, 0,                     },/*53*/
   { STR_WITH_LEN("meth_sv"), op_offset_special, 0,                     },/*54*/
   { STR_WITH_LEN("pmregexp"),op_offset_special, 0,                     },/*55*/
+#  ifdef USE_ITHREADS
+  { STR_WITH_LEN("rclass"),  op_offset_special, 0,                     },/*56*/
+#  else
+  { STR_WITH_LEN("rclass"),  op_offset_special, 0,                     },/*56*/
+#  endif
 #endif
 };
 
@@ -1032,6 +1037,7 @@ next(o)
        B::METHOP::first     = 53
        B::METHOP::meth_sv   = 54
        B::PMOP::pmregexp    = 55
+       B::METHOP::rclass    = 56
     PREINIT:
        SV *ret;
     PPCODE:
@@ -1250,6 +1256,21 @@ next(o)
            case 55: /* B::PMOP::pmregexp */
                ret = make_sv_object(aTHX_ (SV *)PM_GETRE(cPMOPo));
                break;
+           case 56: /* B::METHOP::rclass */
+#ifdef USE_ITHREADS
+               ret = sv_2mortal(newSVuv(
+                   (o->op_type == OP_METHOD_REDIR ||
+                    o->op_type == OP_METHOD_REDIR_SUPER) ?
+                     cMETHOPx(o)->op_rclass_targ : 0
+               ));
+#else
+               ret = make_sv_object(aTHX_
+                   (o->op_type == OP_METHOD_REDIR ||
+                    o->op_type == OP_METHOD_REDIR_SUPER) ?
+                     cMETHOPx(o)->op_rclass_sv : NULL
+               );
+#endif
+               break;
            default:
                croak("method %s not implemented", op_methods[ix].name);
        } else {
index dcca4af..5e068b7 100644 (file)
@@ -898,12 +898,19 @@ sub concise_op {
        }
     }
     elsif ($h{class} eq "METHOP") {
+        my $prefix = '';
+        if ($h{name} eq 'method_redir' or $h{name} eq 'method_redir_super') {
+            my $rclass_sv = $op->rclass;
+            $rclass_sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$rclass_sv]
+                unless ref $rclass_sv;
+            $prefix .= 'PACKAGE "'.$rclass_sv->PV.'", ';
+        }
         if ($h{name} ne "method") {
             if (${$op->meth_sv}) {
-                $h{arg} = "(" . concise_sv($op->meth_sv, \%h, 1) . ")";
+                $h{arg} = "($prefix" . concise_sv($op->meth_sv, \%h, 1) . ")";
             } else {
                 my $sv = (($curcv->PADLIST->ARRAY)[1]->ARRAY)[$op->targ];
-                $h{arg} = "[" . concise_sv($sv, \%h, 1) . "]";
+                $h{arg} = "[$prefix" . concise_sv($sv, \%h, 1) . "]";
                 $h{targarglife} = $h{targarg} = "";
             }
         }
index f22f977..b1813e0 100644 (file)
@@ -340,7 +340,7 @@ invert_opset function.
     rv2cv anoncode prototype coreargs
 
     entersub leavesub leavesublv return method method_named
-    method_super
+    method_super method_redir method_redir_super
      -- XXX loops via recursion?
 
     leaveeval -- needed for Safe to operate, is safe
index 0e26aca..7feb52b 100644 (file)
@@ -3946,6 +3946,11 @@ sub _method {
        $meth = $self->meth_sv($meth)->PV;
     } elsif ($meth->name eq "method_super") {
        $meth = "SUPER::".$self->meth_sv($meth)->PV;
+    } elsif ($meth->name eq "method_redir") {
+        $meth = $self->meth_rclass_sv($meth)->PV.'::'.$self->meth_sv($meth)->PV;
+    } elsif ($meth->name eq "method_redir_super") {
+        $meth = $self->meth_rclass_sv($meth)->PV.'::SUPER::'.
+                $self->meth_sv($meth)->PV;
     } else {
        $meth = $meth->first;
        if ($meth->name eq "const") {
@@ -4586,6 +4591,15 @@ sub meth_sv {
     return $sv;
 }
 
+sub meth_rclass_sv {
+    my $self = shift;
+    my $op = shift;
+    my $sv = $op->rclass;
+    # the constant could be in the pad (under useithreads)
+    $sv = $self->padval($sv) unless ref $sv;
+    return $sv;
+}
+
 sub pp_const {
     my $self = shift;
     my($op, $cx) = @_;
index 55ca8b6..e8e63a2 100644 (file)
@@ -406,6 +406,8 @@ $bits{lvavref}{0} = $bf[0];
 $bits{mapwhile}{0} = $bf[0];
 $bits{method}{0} = $bf[0];
 $bits{method_named}{0} = $bf[0];
+$bits{method_redir}{0} = $bf[0];
+$bits{method_redir_super}{0} = $bf[0];
 $bits{method_super}{0} = $bf[0];
 @{$bits{mkdir}}{3,2,1,0} = ($bf[3], $bf[3], $bf[3], $bf[3]);
 @{$bits{modulo}}{1,0} = ($bf[1], $bf[1]);
diff --git a/op.c b/op.c
index 2719891..476d154 100644 (file)
--- a/op.c
+++ b/op.c
@@ -852,6 +852,17 @@ Perl_op_clear(pTHX_ OP *o)
            }
        }
        break;
+    case OP_METHOD_REDIR:
+    case OP_METHOD_REDIR_SUPER:
+#ifdef USE_ITHREADS
+       if (cMETHOPx(o)->op_rclass_targ) {
+           pad_swipe(cMETHOPx(o)->op_rclass_targ, 1);
+           cMETHOPx(o)->op_rclass_targ = 0;
+       }
+#else
+       SvREFCNT_dec(cMETHOPx(o)->op_rclass_sv);
+       cMETHOPx(o)->op_rclass_sv = NULL;
+#endif
     case OP_METHOD_NAMED:
     case OP_METHOD_SUPER:
         SvREFCNT_dec(cMETHOPx(o)->op_u.op_meth_sv);
@@ -2234,6 +2245,8 @@ S_finalize_op(pTHX_ OP* o)
     /* Relocate all the METHOP's SVs to the pad for thread safety. */
     case OP_METHOD_NAMED:
     case OP_METHOD_SUPER:
+    case OP_METHOD_REDIR:
+    case OP_METHOD_REDIR_SUPER:
         op_relocate_sv(&cMETHOPx(o)->op_u.op_meth_sv, &o->op_targ);
         break;
 #endif
@@ -4692,6 +4705,12 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth
         methop->op_next = (OP*)methop;
     }
 
+#ifdef USE_ITHREADS
+    methop->op_rclass_targ = 0;
+#else
+    methop->op_rclass_sv = NULL;
+#endif
+
     CHANGE_TYPE(methop, type);
     methop = (METHOP*) CHECKOP(type, methop);
 
@@ -10307,11 +10326,12 @@ Perl_ck_match(pTHX_ OP *o)
 OP *
 Perl_ck_method(pTHX_ OP *o)
 {
-    SV *sv, *methsv;
+    SV *sv, *methsv, *rclass;
     const char* method;
     char* compatptr;
     int utf8;
     STRLEN len, nsplit = 0, i;
+    OP* new_op;
     OP * const kid = cUNOPo->op_first;
 
     PERL_ARGS_ASSERT_CK_METHOD;
@@ -10346,7 +10366,21 @@ Perl_ck_method(pTHX_ OP *o)
         return newMETHOP_named(OP_METHOD_SUPER, 0, methsv);
     }
 
-    return o;
+    /* $proto->MyClass::method() and $proto->MyClass::SUPER::method() */
+    if (nsplit >= 9 && strnEQ(method+nsplit-9, "::SUPER::", 9)) {
+        rclass = newSVpvn_share(method, utf8*(nsplit-9), 0);
+        new_op = newMETHOP_named(OP_METHOD_REDIR_SUPER, 0, methsv);
+    } else {
+        rclass = newSVpvn_share(method, utf8*(nsplit-2), 0);
+        new_op = newMETHOP_named(OP_METHOD_REDIR, 0, methsv);
+    }
+#ifdef USE_ITHREADS
+    op_relocate_sv(&rclass, &cMETHOPx(new_op)->op_rclass_targ);
+#else
+    cMETHOPx(new_op)->op_rclass_sv = rclass;
+#endif
+    op_free(o);
+    return new_op;
 }
 
 OP *
@@ -11644,6 +11678,8 @@ Perl_ck_subr(pTHX_ OP *o)
        case OP_METHOD:
        case OP_METHOD_NAMED:
        case OP_METHOD_SUPER:
+       case OP_METHOD_REDIR:
+       case OP_METHOD_REDIR_SUPER:
            if (aop->op_type == OP_CONST) {
                aop->op_private &= ~OPpCONST_STRICT;
                const_class = &cSVOPx(aop)->op_sv;
diff --git a/op.h b/op.h
index 1392fd2..161c1a5 100644 (file)
--- a/op.h
+++ b/op.h
@@ -202,6 +202,11 @@ struct methop {
         OP* op_first;   /* optree for method name */
         SV* op_meth_sv; /* static method name */
     } op_u;
+#ifdef USE_ITHREADS
+    PADOFFSET op_rclass_targ; /* pad index for redirect class */
+#else
+    SV*       op_rclass_sv;   /* static redirect class $o->A::meth() */
+#endif
 };
 
 struct pmop {
@@ -441,6 +446,7 @@ struct loop {
                                 ? cSVOPx(v)->op_sv : PAD_SVl((v)->op_targ))
 #  define      cSVOPx_svp(v)   (cSVOPx(v)->op_sv \
                                 ? &cSVOPx(v)->op_sv : &PAD_SVl((v)->op_targ))
+#  define      cMETHOPx_rclass(v) PAD_SVl(cMETHOPx(v)->op_rclass_targ)
 #else
 #  define      cGVOPx_gv(o)    ((GV*)cSVOPx(o)->op_sv)
 #  ifndef PERL_CORE
@@ -449,6 +455,7 @@ struct loop {
 #  endif
 #  define      cSVOPx_sv(v)    (cSVOPx(v)->op_sv)
 #  define      cSVOPx_svp(v)   (&cSVOPx(v)->op_sv)
+#  define      cMETHOPx_rclass(v) (cMETHOPx(v)->op_rclass_sv)
 #endif
 
 #  define      cMETHOPx_meth(v)        cSVOPx_sv(v)
index 82b3519..e67318f 100644 (file)
--- a/opcode.h
+++ b/opcode.h
@@ -351,6 +351,8 @@ EXTCONST char* const PL_op_name[] = {
        "exit",
        "method_named",
        "method_super",
+       "method_redir",
+       "method_redir_super",
        "entergiven",
        "leavegiven",
        "enterwhen",
@@ -743,6 +745,8 @@ EXTCONST char* const PL_op_desc[] = {
        "exit",
        "method with known name",
        "super with known name",
+       "redirect method with known name",
+       "redirect super method with known name",
        "given()",
        "leave given block",
        "when()",
@@ -1149,6 +1153,8 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
        Perl_pp_exit,
        Perl_pp_method_named,
        Perl_pp_method_super,
+       Perl_pp_method_redir,
+       Perl_pp_method_redir_super,
        Perl_pp_entergiven,
        Perl_pp_leavegiven,
        Perl_pp_enterwhen,
@@ -1551,6 +1557,8 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */
        Perl_ck_fun,            /* exit */
        Perl_ck_null,           /* method_named */
        Perl_ck_null,           /* method_super */
+       Perl_ck_null,           /* method_redir */
+       Perl_ck_null,           /* method_redir_super */
        Perl_ck_null,           /* entergiven */
        Perl_ck_null,           /* leavegiven */
        Perl_ck_null,           /* enterwhen */
@@ -1947,6 +1955,8 @@ EXTCONST U32 PL_opargs[] = {
        0x00009b04,     /* exit */
        0x00000e40,     /* method_named */
        0x00000e40,     /* method_super */
+       0x00000e40,     /* method_redir */
+       0x00000e40,     /* method_redir_super */
        0x00000340,     /* entergiven */
        0x00000100,     /* leavegiven */
        0x00000340,     /* enterwhen */
@@ -2569,6 +2579,8 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
       48, /* exit */
        0, /* method_named */
        0, /* method_super */
+       0, /* method_redir */
+       0, /* method_redir_super */
        0, /* entergiven */
        0, /* leavegiven */
        0, /* enterwhen */
@@ -2768,7 +2780,7 @@ EXTCONST I16  PL_op_private_bitdef_ix[] = {
  */
 
 EXTCONST U16  PL_op_private_bitdefs[] = {
-    0x0003, /* scalar, prototype, refgen, srefgen, ref, readline, regcmaybe, regcreset, regcomp, chop, schop, defined, undef, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, negate, i_negate, not, complement, ucfirst, lcfirst, uc, lc, quotemeta, aeach, akeys, avalues, each, values, pop, shift, range, and, or, dor, andassign, orassign, dorassign, method, method_named, method_super, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, reach, rvalues, fc */
+    0x0003, /* scalar, prototype, refgen, srefgen, ref, readline, regcmaybe, regcreset, regcomp, chop, schop, defined, undef, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, negate, i_negate, not, complement, ucfirst, lcfirst, uc, lc, quotemeta, aeach, akeys, avalues, each, values, pop, shift, range, and, or, dor, andassign, orassign, dorassign, method, method_named, method_super, method_redir, method_redir_super, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, reach, rvalues, fc */
     0x281c, 0x3a19, /* pushmark */
     0x00bd, /* wantarray, runcv */
     0x03b8, 0x1490, 0x3acc, 0x3588, 0x2be5, /* const */
@@ -3043,6 +3055,8 @@ EXTCONST U8 PL_op_private_valid[] = {
     /* EXIT       */ (OPpARG4_MASK),
     /* METHOD_NAMED */ (OPpARG1_MASK),
     /* METHOD_SUPER */ (OPpARG1_MASK),
+    /* METHOD_REDIR */ (OPpARG1_MASK),
+    /* METHOD_REDIR_SUPER */ (OPpARG1_MASK),
     /* ENTERGIVEN */ (OPpARG1_MASK),
     /* LEAVEGIVEN */ (OPpARG1_MASK),
     /* ENTERWHEN  */ (OPpARG1_MASK),
index a0b7785..dce44f1 100644 (file)
--- a/opnames.h
+++ b/opnames.h
@@ -217,191 +217,193 @@ typedef enum opcode {
        OP_EXIT          = 200,
        OP_METHOD_NAMED  = 201,
        OP_METHOD_SUPER  = 202,
-       OP_ENTERGIVEN    = 203,
-       OP_LEAVEGIVEN    = 204,
-       OP_ENTERWHEN     = 205,
-       OP_LEAVEWHEN     = 206,
-       OP_BREAK         = 207,
-       OP_CONTINUE      = 208,
-       OP_OPEN          = 209,
-       OP_CLOSE         = 210,
-       OP_PIPE_OP       = 211,
-       OP_FILENO        = 212,
-       OP_UMASK         = 213,
-       OP_BINMODE       = 214,
-       OP_TIE           = 215,
-       OP_UNTIE         = 216,
-       OP_TIED          = 217,
-       OP_DBMOPEN       = 218,
-       OP_DBMCLOSE      = 219,
-       OP_SSELECT       = 220,
-       OP_SELECT        = 221,
-       OP_GETC          = 222,
-       OP_READ          = 223,
-       OP_ENTERWRITE    = 224,
-       OP_LEAVEWRITE    = 225,
-       OP_PRTF          = 226,
-       OP_PRINT         = 227,
-       OP_SAY           = 228,
-       OP_SYSOPEN       = 229,
-       OP_SYSSEEK       = 230,
-       OP_SYSREAD       = 231,
-       OP_SYSWRITE      = 232,
-       OP_EOF           = 233,
-       OP_TELL          = 234,
-       OP_SEEK          = 235,
-       OP_TRUNCATE      = 236,
-       OP_FCNTL         = 237,
-       OP_IOCTL         = 238,
-       OP_FLOCK         = 239,
-       OP_SEND          = 240,
-       OP_RECV          = 241,
-       OP_SOCKET        = 242,
-       OP_SOCKPAIR      = 243,
-       OP_BIND          = 244,
-       OP_CONNECT       = 245,
-       OP_LISTEN        = 246,
-       OP_ACCEPT        = 247,
-       OP_SHUTDOWN      = 248,
-       OP_GSOCKOPT      = 249,
-       OP_SSOCKOPT      = 250,
-       OP_GETSOCKNAME   = 251,
-       OP_GETPEERNAME   = 252,
-       OP_LSTAT         = 253,
-       OP_STAT          = 254,
-       OP_FTRREAD       = 255,
-       OP_FTRWRITE      = 256,
-       OP_FTREXEC       = 257,
-       OP_FTEREAD       = 258,
-       OP_FTEWRITE      = 259,
-       OP_FTEEXEC       = 260,
-       OP_FTIS          = 261,
-       OP_FTSIZE        = 262,
-       OP_FTMTIME       = 263,
-       OP_FTATIME       = 264,
-       OP_FTCTIME       = 265,
-       OP_FTROWNED      = 266,
-       OP_FTEOWNED      = 267,
-       OP_FTZERO        = 268,
-       OP_FTSOCK        = 269,
-       OP_FTCHR         = 270,
-       OP_FTBLK         = 271,
-       OP_FTFILE        = 272,
-       OP_FTDIR         = 273,
-       OP_FTPIPE        = 274,
-       OP_FTSUID        = 275,
-       OP_FTSGID        = 276,
-       OP_FTSVTX        = 277,
-       OP_FTLINK        = 278,
-       OP_FTTTY         = 279,
-       OP_FTTEXT        = 280,
-       OP_FTBINARY      = 281,
-       OP_CHDIR         = 282,
-       OP_CHOWN         = 283,
-       OP_CHROOT        = 284,
-       OP_UNLINK        = 285,
-       OP_CHMOD         = 286,
-       OP_UTIME         = 287,
-       OP_RENAME        = 288,
-       OP_LINK          = 289,
-       OP_SYMLINK       = 290,
-       OP_READLINK      = 291,
-       OP_MKDIR         = 292,
-       OP_RMDIR         = 293,
-       OP_OPEN_DIR      = 294,
-       OP_READDIR       = 295,
-       OP_TELLDIR       = 296,
-       OP_SEEKDIR       = 297,
-       OP_REWINDDIR     = 298,
-       OP_CLOSEDIR      = 299,
-       OP_FORK          = 300,
-       OP_WAIT          = 301,
-       OP_WAITPID       = 302,
-       OP_SYSTEM        = 303,
-       OP_EXEC          = 304,
-       OP_KILL          = 305,
-       OP_GETPPID       = 306,
-       OP_GETPGRP       = 307,
-       OP_SETPGRP       = 308,
-       OP_GETPRIORITY   = 309,
-       OP_SETPRIORITY   = 310,
-       OP_TIME          = 311,
-       OP_TMS           = 312,
-       OP_LOCALTIME     = 313,
-       OP_GMTIME        = 314,
-       OP_ALARM         = 315,
-       OP_SLEEP         = 316,
-       OP_SHMGET        = 317,
-       OP_SHMCTL        = 318,
-       OP_SHMREAD       = 319,
-       OP_SHMWRITE      = 320,
-       OP_MSGGET        = 321,
-       OP_MSGCTL        = 322,
-       OP_MSGSND        = 323,
-       OP_MSGRCV        = 324,
-       OP_SEMOP         = 325,
-       OP_SEMGET        = 326,
-       OP_SEMCTL        = 327,
-       OP_REQUIRE       = 328,
-       OP_DOFILE        = 329,
-       OP_HINTSEVAL     = 330,
-       OP_ENTEREVAL     = 331,
-       OP_LEAVEEVAL     = 332,
-       OP_ENTERTRY      = 333,
-       OP_LEAVETRY      = 334,
-       OP_GHBYNAME      = 335,
-       OP_GHBYADDR      = 336,
-       OP_GHOSTENT      = 337,
-       OP_GNBYNAME      = 338,
-       OP_GNBYADDR      = 339,
-       OP_GNETENT       = 340,
-       OP_GPBYNAME      = 341,
-       OP_GPBYNUMBER    = 342,
-       OP_GPROTOENT     = 343,
-       OP_GSBYNAME      = 344,
-       OP_GSBYPORT      = 345,
-       OP_GSERVENT      = 346,
-       OP_SHOSTENT      = 347,
-       OP_SNETENT       = 348,
-       OP_SPROTOENT     = 349,
-       OP_SSERVENT      = 350,
-       OP_EHOSTENT      = 351,
-       OP_ENETENT       = 352,
-       OP_EPROTOENT     = 353,
-       OP_ESERVENT      = 354,
-       OP_GPWNAM        = 355,
-       OP_GPWUID        = 356,
-       OP_GPWENT        = 357,
-       OP_SPWENT        = 358,
-       OP_EPWENT        = 359,
-       OP_GGRNAM        = 360,
-       OP_GGRGID        = 361,
-       OP_GGRENT        = 362,
-       OP_SGRENT        = 363,
-       OP_EGRENT        = 364,
-       OP_GETLOGIN      = 365,
-       OP_SYSCALL       = 366,
-       OP_LOCK          = 367,
-       OP_ONCE          = 368,
-       OP_CUSTOM        = 369,
-       OP_REACH         = 370,
-       OP_RKEYS         = 371,
-       OP_RVALUES       = 372,
-       OP_COREARGS      = 373,
-       OP_RUNCV         = 374,
-       OP_FC            = 375,
-       OP_PADCV         = 376,
-       OP_INTROCV       = 377,
-       OP_CLONECV       = 378,
-       OP_PADRANGE      = 379,
-       OP_REFASSIGN     = 380,
-       OP_LVREF         = 381,
-       OP_LVREFSLICE    = 382,
-       OP_LVAVREF       = 383,
+       OP_METHOD_REDIR  = 203,
+       OP_METHOD_REDIR_SUPER = 204,
+       OP_ENTERGIVEN    = 205,
+       OP_LEAVEGIVEN    = 206,
+       OP_ENTERWHEN     = 207,
+       OP_LEAVEWHEN     = 208,
+       OP_BREAK         = 209,
+       OP_CONTINUE      = 210,
+       OP_OPEN          = 211,
+       OP_CLOSE         = 212,
+       OP_PIPE_OP       = 213,
+       OP_FILENO        = 214,
+       OP_UMASK         = 215,
+       OP_BINMODE       = 216,
+       OP_TIE           = 217,
+       OP_UNTIE         = 218,
+       OP_TIED          = 219,
+       OP_DBMOPEN       = 220,
+       OP_DBMCLOSE      = 221,
+       OP_SSELECT       = 222,
+       OP_SELECT        = 223,
+       OP_GETC          = 224,
+       OP_READ          = 225,
+       OP_ENTERWRITE    = 226,
+       OP_LEAVEWRITE    = 227,
+       OP_PRTF          = 228,
+       OP_PRINT         = 229,
+       OP_SAY           = 230,
+       OP_SYSOPEN       = 231,
+       OP_SYSSEEK       = 232,
+       OP_SYSREAD       = 233,
+       OP_SYSWRITE      = 234,
+       OP_EOF           = 235,
+       OP_TELL          = 236,
+       OP_SEEK          = 237,
+       OP_TRUNCATE      = 238,
+       OP_FCNTL         = 239,
+       OP_IOCTL         = 240,
+       OP_FLOCK         = 241,
+       OP_SEND          = 242,
+       OP_RECV          = 243,
+       OP_SOCKET        = 244,
+       OP_SOCKPAIR      = 245,
+       OP_BIND          = 246,
+       OP_CONNECT       = 247,
+       OP_LISTEN        = 248,
+       OP_ACCEPT        = 249,
+       OP_SHUTDOWN      = 250,
+       OP_GSOCKOPT      = 251,
+       OP_SSOCKOPT      = 252,
+       OP_GETSOCKNAME   = 253,
+       OP_GETPEERNAME   = 254,
+       OP_LSTAT         = 255,
+       OP_STAT          = 256,
+       OP_FTRREAD       = 257,
+       OP_FTRWRITE      = 258,
+       OP_FTREXEC       = 259,
+       OP_FTEREAD       = 260,
+       OP_FTEWRITE      = 261,
+       OP_FTEEXEC       = 262,
+       OP_FTIS          = 263,
+       OP_FTSIZE        = 264,
+       OP_FTMTIME       = 265,
+       OP_FTATIME       = 266,
+       OP_FTCTIME       = 267,
+       OP_FTROWNED      = 268,
+       OP_FTEOWNED      = 269,
+       OP_FTZERO        = 270,
+       OP_FTSOCK        = 271,
+       OP_FTCHR         = 272,
+       OP_FTBLK         = 273,
+       OP_FTFILE        = 274,
+       OP_FTDIR         = 275,
+       OP_FTPIPE        = 276,
+       OP_FTSUID        = 277,
+       OP_FTSGID        = 278,
+       OP_FTSVTX        = 279,
+       OP_FTLINK        = 280,
+       OP_FTTTY         = 281,
+       OP_FTTEXT        = 282,
+       OP_FTBINARY      = 283,
+       OP_CHDIR         = 284,
+       OP_CHOWN         = 285,
+       OP_CHROOT        = 286,
+       OP_UNLINK        = 287,
+       OP_CHMOD         = 288,
+       OP_UTIME         = 289,
+       OP_RENAME        = 290,
+       OP_LINK          = 291,
+       OP_SYMLINK       = 292,
+       OP_READLINK      = 293,
+       OP_MKDIR         = 294,
+       OP_RMDIR         = 295,
+       OP_OPEN_DIR      = 296,
+       OP_READDIR       = 297,
+       OP_TELLDIR       = 298,
+       OP_SEEKDIR       = 299,
+       OP_REWINDDIR     = 300,
+       OP_CLOSEDIR      = 301,
+       OP_FORK          = 302,
+       OP_WAIT          = 303,
+       OP_WAITPID       = 304,
+       OP_SYSTEM        = 305,
+       OP_EXEC          = 306,
+       OP_KILL          = 307,
+       OP_GETPPID       = 308,
+       OP_GETPGRP       = 309,
+       OP_SETPGRP       = 310,
+       OP_GETPRIORITY   = 311,
+       OP_SETPRIORITY   = 312,
+       OP_TIME          = 313,
+       OP_TMS           = 314,
+       OP_LOCALTIME     = 315,
+       OP_GMTIME        = 316,
+       OP_ALARM         = 317,
+       OP_SLEEP         = 318,
+       OP_SHMGET        = 319,
+       OP_SHMCTL        = 320,
+       OP_SHMREAD       = 321,
+       OP_SHMWRITE      = 322,
+       OP_MSGGET        = 323,
+       OP_MSGCTL        = 324,
+       OP_MSGSND        = 325,
+       OP_MSGRCV        = 326,
+       OP_SEMOP         = 327,
+       OP_SEMGET        = 328,
+       OP_SEMCTL        = 329,
+       OP_REQUIRE       = 330,
+       OP_DOFILE        = 331,
+       OP_HINTSEVAL     = 332,
+       OP_ENTEREVAL     = 333,
+       OP_LEAVEEVAL     = 334,
+       OP_ENTERTRY      = 335,
+       OP_LEAVETRY      = 336,
+       OP_GHBYNAME      = 337,
+       OP_GHBYADDR      = 338,
+       OP_GHOSTENT      = 339,
+       OP_GNBYNAME      = 340,
+       OP_GNBYADDR      = 341,
+       OP_GNETENT       = 342,
+       OP_GPBYNAME      = 343,
+       OP_GPBYNUMBER    = 344,
+       OP_GPROTOENT     = 345,
+       OP_GSBYNAME      = 346,
+       OP_GSBYPORT      = 347,
+       OP_GSERVENT      = 348,
+       OP_SHOSTENT      = 349,
+       OP_SNETENT       = 350,
+       OP_SPROTOENT     = 351,
+       OP_SSERVENT      = 352,
+       OP_EHOSTENT      = 353,
+       OP_ENETENT       = 354,
+       OP_EPROTOENT     = 355,
+       OP_ESERVENT      = 356,
+       OP_GPWNAM        = 357,
+       OP_GPWUID        = 358,
+       OP_GPWENT        = 359,
+       OP_SPWENT        = 360,
+       OP_EPWENT        = 361,
+       OP_GGRNAM        = 362,
+       OP_GGRGID        = 363,
+       OP_GGRENT        = 364,
+       OP_SGRENT        = 365,
+       OP_EGRENT        = 366,
+       OP_GETLOGIN      = 367,
+       OP_SYSCALL       = 368,
+       OP_LOCK          = 369,
+       OP_ONCE          = 370,
+       OP_CUSTOM        = 371,
+       OP_REACH         = 372,
+       OP_RKEYS         = 373,
+       OP_RVALUES       = 374,
+       OP_COREARGS      = 375,
+       OP_RUNCV         = 376,
+       OP_FC            = 377,
+       OP_PADCV         = 378,
+       OP_INTROCV       = 379,
+       OP_CLONECV       = 380,
+       OP_PADRANGE      = 381,
+       OP_REFASSIGN     = 382,
+       OP_LVREF         = 383,
+       OP_LVREFSLICE    = 384,
+       OP_LVAVREF       = 385,
        OP_max          
 } opcode;
 
-#define MAXO 384
+#define MAXO 386
 #define OP_FREED MAXO
 
 /* the OP_IS_* macros are optimized to a simple range check because
index 48cc1cb..35493eb 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -3083,6 +3083,18 @@ PP(pp_method)
     RETURN;
 }
 
+#define METHOD_CHECK_CACHE(stash,cache,meth)                           \
+    const HE* const he = hv_fetch_ent(cache, meth, 0, 0);              \
+    if (he) {                                                          \
+        gv = MUTABLE_GV(HeVAL(he));                                    \
+        if (isGV(gv) && GvCV(gv) && (!GvCVGEN(gv) || GvCVGEN(gv)       \
+             == (PL_sub_generation + HvMROMETA(stash)->cache_gen)))    \
+        {                                                              \
+            XPUSHs(MUTABLE_SV(GvCV(gv)));                              \
+            RETURN;                                                    \
+        }                                                              \
+    }                                                                  \
+
 PP(pp_method_named)
 {
     dSP;
@@ -3091,17 +3103,7 @@ PP(pp_method_named)
     HV* const stash = opmethod_stash(meth);
 
     if (LIKELY(SvTYPE(stash) == SVt_PVHV)) {
-        const HE* const he = hv_fetch_ent(stash, meth, 0, 0);
-        if (he) {
-            gv = MUTABLE_GV(HeVAL(he));
-            if (isGV(gv) && GvCV(gv) &&
-                (!GvCVGEN(gv) || GvCVGEN(gv)
-                  == (PL_sub_generation + HvMROMETA(stash)->cache_gen)))
-            {
-                XPUSHs(MUTABLE_SV(GvCV(gv)));
-                RETURN;
-            }
-        }
+        METHOD_CHECK_CACHE(stash, stash, meth);
     }
 
     gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK);
@@ -3124,17 +3126,46 @@ PP(pp_method_super)
     opmethod_stash(meth);
 
     if ((cache = HvMROMETA(stash)->super)) {
-        const HE* const he = hv_fetch_ent(cache, meth, 0, 0);
-        if (he) {
-            gv = MUTABLE_GV(HeVAL(he));
-            if (isGV(gv) && GvCV(gv) &&
-                (!GvCVGEN(gv) || GvCVGEN(gv)
-                  == (PL_sub_generation + HvMROMETA(stash)->cache_gen)))
-            {
-                XPUSHs(MUTABLE_SV(GvCV(gv)));
-                RETURN;
-            }
-        }
+        METHOD_CHECK_CACHE(stash, cache, meth);
+    }
+
+    gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK|GV_SUPER);
+    assert(gv);
+
+    XPUSHs(isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv));
+    RETURN;
+}
+
+PP(pp_method_redir)
+{
+    dSP;
+    GV* gv;
+    SV* const meth = cMETHOPx_meth(PL_op);
+    HV* stash = gv_stashsv(cMETHOPx_rclass(PL_op), 0);
+    opmethod_stash(meth); /* not used but needed for error checks */
+
+    if (stash) { METHOD_CHECK_CACHE(stash, stash, meth); }
+    else stash = MUTABLE_HV(cMETHOPx_rclass(PL_op));
+
+    gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK);
+    assert(gv);
+
+    XPUSHs(isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv));
+    RETURN;
+}
+
+PP(pp_method_redir_super)
+{
+    dSP;
+    GV* gv;
+    HV* cache;
+    SV* const meth = cMETHOPx_meth(PL_op);
+    HV* stash = gv_stashsv(cMETHOPx_rclass(PL_op), 0);
+    opmethod_stash(meth); /* not used but needed for error checks */
+
+    if (UNLIKELY(!stash)) stash = MUTABLE_HV(cMETHOPx_rclass(PL_op));
+    else if ((cache = HvMROMETA(stash)->super)) {
+         METHOD_CHECK_CACHE(stash, cache, meth);
     }
 
     gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK|GV_SUPER);
index 781050a..6959357 100644 (file)
@@ -152,6 +152,8 @@ PERL_CALLCONV OP *Perl_pp_mapwhile(pTHX);
 PERL_CALLCONV OP *Perl_pp_match(pTHX);
 PERL_CALLCONV OP *Perl_pp_method(pTHX);
 PERL_CALLCONV OP *Perl_pp_method_named(pTHX);
+PERL_CALLCONV OP *Perl_pp_method_redir(pTHX);
+PERL_CALLCONV OP *Perl_pp_method_redir_super(pTHX);
 PERL_CALLCONV OP *Perl_pp_method_super(pTHX);
 PERL_CALLCONV OP *Perl_pp_mkdir(pTHX);
 PERL_CALLCONV OP *Perl_pp_modulo(pTHX);
index f46264d..62c3b45 100644 (file)
@@ -309,6 +309,8 @@ goto                goto                    ck_null         s}
 exit           exit                    ck_fun          s%      S?
 method_named   method with known name  ck_null         d.
 method_super   super with known name   ck_null         d.
+method_redir   redirect method with known name ck_null d.
+method_redir_super     redirect super method with known name   ck_null d.
 
 entergiven     given()                 ck_null         d|
 leavegiven     leave given block       ck_null         1