summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dump.c2
-rw-r--r--ext/B/B.xs21
-rw-r--r--ext/B/B/Concise.pm11
-rw-r--r--ext/Opcode/Opcode.pm2
-rw-r--r--lib/B/Deparse.pm14
-rw-r--r--lib/B/Op_private.pm2
-rw-r--r--op.c40
-rw-r--r--op.h7
-rw-r--r--opcode.h16
-rw-r--r--opnames.h366
-rw-r--r--pp_hot.c75
-rw-r--r--pp_proto.h2
-rw-r--r--regen/opcodes2
13 files changed, 350 insertions, 210 deletions
diff --git a/dump.c b/dump.c
index 2781ada637..5f2b07e770 100644
--- 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 */
diff --git a/ext/B/B.xs b/ext/B/B.xs
index d08750c4bf..da05cc18f2 100644
--- a/ext/B/B.xs
+++ b/ext/B/B.xs
@@ -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 {
diff --git a/ext/B/B/Concise.pm b/ext/B/B/Concise.pm
index dcca4af4ef..5e068b72e2 100644
--- a/ext/B/B/Concise.pm
+++ b/ext/B/B/Concise.pm
@@ -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} = "";
}
}
diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm
index f22f97701c..b1813e072c 100644
--- a/ext/Opcode/Opcode.pm
+++ b/ext/Opcode/Opcode.pm
@@ -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
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index 0e26aca6c7..7feb52be9c 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -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) = @_;
diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm
index 55ca8b60dc..e8e63a2e32 100644
--- a/lib/B/Op_private.pm
+++ b/lib/B/Op_private.pm
@@ -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 27198913a6..476d1544c1 100644
--- 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 1392fd2945..161c1a5eea 100644
--- 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)
diff --git a/opcode.h b/opcode.h
index 82b35199e3..e67318ffc8 100644
--- 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),
diff --git a/opnames.h b/opnames.h
index a0b77857f0..dce44f19e9 100644
--- 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
diff --git a/pp_hot.c b/pp_hot.c
index 48cc1cbea7..35493eb1b4 100644
--- 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);
diff --git a/pp_proto.h b/pp_proto.h
index 781050a865..6959357dd2 100644
--- a/pp_proto.h
+++ b/pp_proto.h
@@ -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);
diff --git a/regen/opcodes b/regen/opcodes
index f46264d2e1..62c3b45e70 100644
--- a/regen/opcodes
+++ b/regen/opcodes
@@ -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