OP_AELEMFASTLEX_STORE - combined sassign/aelemfast_lex

This commit introduces a new OP to replace simple cases of OP_SASSIGN
and OP_AELEMFAST_LEX. (Similar concept to GH #19943)

For example, `my @ary; $ary[0] = "boo"` is currently implemented as:
    7     <2> sassign vKS/2 ->8
    5        <$> const[PV "boo"] s ->6
    -        <1> ex-aelem sKRM*/2 ->7
    6           <0> aelemfast_lex[@ary:1,2] sRM ->7
    -           <0> ex-const s ->-

But now will be turned into:
    6     <1> aelemfastlex_store[@ary:1,2] vKS ->7
    5        <$> const(PV "boo") s ->6
    -        <1> ex-aelem sKRM*/2 ->6
    -           <0> ex-aelemfast_lex sRM ->6
    -           <0> ex-const s ->-

This is intended to be a transparent performance optimization.
It should be applicable for RHS optrees of varying complexity.
This commit is contained in:
Richard Leach 2022-08-06 21:55:28 +00:00
parent ec18fac000
commit aafefcb901
12 changed files with 451 additions and 282 deletions

View File

@ -305,7 +305,7 @@ invert_opset function.
rv2sv sassign padsv_store
rv2av aassign aelem aelemfast aelemfast_lex aslice kvaslice
av2arylen
av2arylen aelemfastlex_store
rv2hv helem hslice kvhslice each values keys exists delete
aeach akeys avalues multideref argelem argdefelem argcheck

View File

@ -4305,6 +4305,17 @@ sub pp_gv {
return $self->maybe_qualify("", $self->gv_name($gv));
}
sub pp_aelemfastlex_store {
my $self = shift;
my($op, $cx) = @_;
my $name = $self->padname($op->targ);
$name =~ s/^@/\$/;
my $i = $op->private;
$i -= 256 if $i > 127;
my $val = $self->deparse($op->first, 7);
return $self->maybe_parens("${name}[$i] = $val", $cx, 7);
}
sub pp_aelemfast_lex {
my $self = shift;
my($op, $cx) = @_;

View File

@ -254,6 +254,7 @@ $bits{aeach}{0} = $bf[0];
@{$bits{aelem}}{5,4,1,0} = ($bf[8], $bf[8], $bf[1], $bf[1]);
@{$bits{aelemfast}}{7,6,5,4,3,2,1,0} = ($bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6]);
@{$bits{aelemfast_lex}}{7,6,5,4,3,2,1,0} = ($bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6]);
@{$bits{aelemfastlex_store}}{7,6,5,4,3,2,1,0} = ($bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6], $bf[6]);
$bits{akeys}{0} = $bf[0];
$bits{alarm}{0} = $bf[0];
$bits{and}{0} = $bf[0];

View File

@ -288,6 +288,7 @@ EXTCONST char* const PL_op_name[] = {
"rv2av",
"aelemfast",
"aelemfast_lex",
"aelemfastlex_store",
"aelem",
"aslice",
"kvaslice",
@ -712,6 +713,7 @@ EXTCONST char* const PL_op_desc[] = {
"array dereference",
"constant array element",
"constant lexical array element",
"const lexical array element store",
"array element",
"array slice",
"index/value array slice",
@ -1139,6 +1141,7 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
Perl_pp_rv2av,
Perl_pp_aelemfast,
Perl_pp_aelemfast_lex, /* implemented by Perl_pp_aelemfast */
Perl_pp_aelemfastlex_store,
Perl_pp_aelem,
Perl_pp_aslice,
Perl_pp_kvaslice,
@ -1562,6 +1565,7 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */
Perl_ck_rvconst, /* rv2av */
Perl_ck_null, /* aelemfast */
Perl_ck_null, /* aelemfast_lex */
Perl_ck_null, /* aelemfastlex_store */
Perl_ck_null, /* aelem */
Perl_ck_null, /* aslice */
Perl_ck_null, /* kvaslice */
@ -1986,6 +1990,7 @@ EXTCONST U32 PL_opargs[] = {
0x00000148, /* rv2av */
0x00013644, /* aelemfast */
0x00013040, /* aelemfast_lex */
0x00013140, /* aelemfastlex_store */
0x00013204, /* aelem */
0x00023401, /* aslice */
0x00023401, /* kvaslice */
@ -2671,6 +2676,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = {
118, /* rv2av */
125, /* aelemfast */
125, /* aelemfast_lex */
125, /* aelemfastlex_store */
126, /* aelem */
131, /* aslice */
134, /* kvaslice */
@ -3003,7 +3009,7 @@ EXTCONST U16 PL_op_private_bitdefs[] = {
0x32cc, 0x0067, /* vec */
0x3438, 0x05b4, 0x4730, 0x018f, /* index, rindex */
0x31dc, 0x3858, 0x05b4, 0x32cc, 0x40a8, 0x4384, 0x0003, /* rv2av */
0x025f, /* aelemfast, aelemfast_lex */
0x025f, /* aelemfast, aelemfast_lex, aelemfastlex_store */
0x31dc, 0x30d8, 0x03d6, 0x32cc, 0x0067, /* aelem, helem */
0x31dc, 0x32cc, 0x40a9, /* aslice, hslice */
0x32cd, /* kvaslice, kvhslice */
@ -3187,6 +3193,7 @@ EXTCONST U8 PL_op_private_valid[] = {
/* RV2AV */ (OPpARG1_MASK|OPpHINT_STRICT_REFS|OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpTRUEBOOL|OPpOUR_INTRO|OPpLVAL_INTRO),
/* AELEMFAST */ (255),
/* AELEMFAST_LEX */ (255),
/* AELEMFASTLEX_STORE */ (255),
/* AELEM */ (OPpARG2_MASK|OPpMAYBE_LVSUB|OPpDEREF|OPpLVAL_DEFER|OPpLVAL_INTRO),
/* ASLICE */ (OPpSLICEWARNING|OPpMAYBE_LVSUB|OPpLVAL_INTRO),
/* KVASLICE */ (OPpMAYBE_LVSUB),

557
opnames.h
View File

@ -153,287 +153,288 @@ typedef enum opcode {
OP_RV2AV = 136,
OP_AELEMFAST = 137,
OP_AELEMFAST_LEX = 138,
OP_AELEM = 139,
OP_ASLICE = 140,
OP_KVASLICE = 141,
OP_AEACH = 142,
OP_AVALUES = 143,
OP_AKEYS = 144,
OP_EACH = 145,
OP_VALUES = 146,
OP_KEYS = 147,
OP_DELETE = 148,
OP_EXISTS = 149,
OP_RV2HV = 150,
OP_HELEM = 151,
OP_HSLICE = 152,
OP_KVHSLICE = 153,
OP_MULTIDEREF = 154,
OP_UNPACK = 155,
OP_PACK = 156,
OP_SPLIT = 157,
OP_JOIN = 158,
OP_LIST = 159,
OP_LSLICE = 160,
OP_ANONLIST = 161,
OP_ANONHASH = 162,
OP_SPLICE = 163,
OP_PUSH = 164,
OP_POP = 165,
OP_SHIFT = 166,
OP_UNSHIFT = 167,
OP_SORT = 168,
OP_REVERSE = 169,
OP_GREPSTART = 170,
OP_GREPWHILE = 171,
OP_MAPSTART = 172,
OP_MAPWHILE = 173,
OP_RANGE = 174,
OP_FLIP = 175,
OP_FLOP = 176,
OP_AND = 177,
OP_OR = 178,
OP_XOR = 179,
OP_DOR = 180,
OP_COND_EXPR = 181,
OP_ANDASSIGN = 182,
OP_ORASSIGN = 183,
OP_DORASSIGN = 184,
OP_ENTERSUB = 185,
OP_LEAVESUB = 186,
OP_LEAVESUBLV = 187,
OP_ARGCHECK = 188,
OP_ARGELEM = 189,
OP_ARGDEFELEM = 190,
OP_CALLER = 191,
OP_WARN = 192,
OP_DIE = 193,
OP_RESET = 194,
OP_LINESEQ = 195,
OP_NEXTSTATE = 196,
OP_DBSTATE = 197,
OP_UNSTACK = 198,
OP_ENTER = 199,
OP_LEAVE = 200,
OP_SCOPE = 201,
OP_ENTERITER = 202,
OP_ITER = 203,
OP_ENTERLOOP = 204,
OP_LEAVELOOP = 205,
OP_RETURN = 206,
OP_LAST = 207,
OP_NEXT = 208,
OP_REDO = 209,
OP_DUMP = 210,
OP_GOTO = 211,
OP_EXIT = 212,
OP_METHOD = 213,
OP_METHOD_NAMED = 214,
OP_METHOD_SUPER = 215,
OP_METHOD_REDIR = 216,
OP_METHOD_REDIR_SUPER = 217,
OP_ENTERGIVEN = 218,
OP_LEAVEGIVEN = 219,
OP_ENTERWHEN = 220,
OP_LEAVEWHEN = 221,
OP_BREAK = 222,
OP_CONTINUE = 223,
OP_OPEN = 224,
OP_CLOSE = 225,
OP_PIPE_OP = 226,
OP_FILENO = 227,
OP_UMASK = 228,
OP_BINMODE = 229,
OP_TIE = 230,
OP_UNTIE = 231,
OP_TIED = 232,
OP_DBMOPEN = 233,
OP_DBMCLOSE = 234,
OP_SSELECT = 235,
OP_SELECT = 236,
OP_GETC = 237,
OP_READ = 238,
OP_ENTERWRITE = 239,
OP_LEAVEWRITE = 240,
OP_PRTF = 241,
OP_PRINT = 242,
OP_SAY = 243,
OP_SYSOPEN = 244,
OP_SYSSEEK = 245,
OP_SYSREAD = 246,
OP_SYSWRITE = 247,
OP_EOF = 248,
OP_TELL = 249,
OP_SEEK = 250,
OP_TRUNCATE = 251,
OP_FCNTL = 252,
OP_IOCTL = 253,
OP_FLOCK = 254,
OP_SEND = 255,
OP_RECV = 256,
OP_SOCKET = 257,
OP_SOCKPAIR = 258,
OP_BIND = 259,
OP_CONNECT = 260,
OP_LISTEN = 261,
OP_ACCEPT = 262,
OP_SHUTDOWN = 263,
OP_GSOCKOPT = 264,
OP_SSOCKOPT = 265,
OP_GETSOCKNAME = 266,
OP_GETPEERNAME = 267,
OP_LSTAT = 268,
OP_STAT = 269,
OP_FTRREAD = 270,
OP_FTRWRITE = 271,
OP_FTREXEC = 272,
OP_FTEREAD = 273,
OP_FTEWRITE = 274,
OP_FTEEXEC = 275,
OP_FTIS = 276,
OP_FTSIZE = 277,
OP_FTMTIME = 278,
OP_FTATIME = 279,
OP_FTCTIME = 280,
OP_FTROWNED = 281,
OP_FTEOWNED = 282,
OP_FTZERO = 283,
OP_FTSOCK = 284,
OP_FTCHR = 285,
OP_FTBLK = 286,
OP_FTFILE = 287,
OP_FTDIR = 288,
OP_FTPIPE = 289,
OP_FTSUID = 290,
OP_FTSGID = 291,
OP_FTSVTX = 292,
OP_FTLINK = 293,
OP_FTTTY = 294,
OP_FTTEXT = 295,
OP_FTBINARY = 296,
OP_CHDIR = 297,
OP_CHOWN = 298,
OP_CHROOT = 299,
OP_UNLINK = 300,
OP_CHMOD = 301,
OP_UTIME = 302,
OP_RENAME = 303,
OP_LINK = 304,
OP_SYMLINK = 305,
OP_READLINK = 306,
OP_MKDIR = 307,
OP_RMDIR = 308,
OP_OPEN_DIR = 309,
OP_READDIR = 310,
OP_TELLDIR = 311,
OP_SEEKDIR = 312,
OP_REWINDDIR = 313,
OP_CLOSEDIR = 314,
OP_FORK = 315,
OP_WAIT = 316,
OP_WAITPID = 317,
OP_SYSTEM = 318,
OP_EXEC = 319,
OP_KILL = 320,
OP_GETPPID = 321,
OP_GETPGRP = 322,
OP_SETPGRP = 323,
OP_GETPRIORITY = 324,
OP_SETPRIORITY = 325,
OP_TIME = 326,
OP_TMS = 327,
OP_LOCALTIME = 328,
OP_GMTIME = 329,
OP_ALARM = 330,
OP_SLEEP = 331,
OP_SHMGET = 332,
OP_SHMCTL = 333,
OP_SHMREAD = 334,
OP_SHMWRITE = 335,
OP_MSGGET = 336,
OP_MSGCTL = 337,
OP_MSGSND = 338,
OP_MSGRCV = 339,
OP_SEMOP = 340,
OP_SEMGET = 341,
OP_SEMCTL = 342,
OP_REQUIRE = 343,
OP_DOFILE = 344,
OP_HINTSEVAL = 345,
OP_ENTEREVAL = 346,
OP_LEAVEEVAL = 347,
OP_ENTERTRY = 348,
OP_LEAVETRY = 349,
OP_GHBYNAME = 350,
OP_GHBYADDR = 351,
OP_GHOSTENT = 352,
OP_GNBYNAME = 353,
OP_GNBYADDR = 354,
OP_GNETENT = 355,
OP_GPBYNAME = 356,
OP_GPBYNUMBER = 357,
OP_GPROTOENT = 358,
OP_GSBYNAME = 359,
OP_GSBYPORT = 360,
OP_GSERVENT = 361,
OP_SHOSTENT = 362,
OP_SNETENT = 363,
OP_SPROTOENT = 364,
OP_SSERVENT = 365,
OP_EHOSTENT = 366,
OP_ENETENT = 367,
OP_EPROTOENT = 368,
OP_ESERVENT = 369,
OP_GPWNAM = 370,
OP_GPWUID = 371,
OP_GPWENT = 372,
OP_SPWENT = 373,
OP_EPWENT = 374,
OP_GGRNAM = 375,
OP_GGRGID = 376,
OP_GGRENT = 377,
OP_SGRENT = 378,
OP_EGRENT = 379,
OP_GETLOGIN = 380,
OP_SYSCALL = 381,
OP_LOCK = 382,
OP_ONCE = 383,
OP_CUSTOM = 384,
OP_COREARGS = 385,
OP_AVHVSWITCH = 386,
OP_RUNCV = 387,
OP_FC = 388,
OP_PADCV = 389,
OP_INTROCV = 390,
OP_CLONECV = 391,
OP_PADRANGE = 392,
OP_REFASSIGN = 393,
OP_LVREF = 394,
OP_LVREFSLICE = 395,
OP_LVAVREF = 396,
OP_ANONCONST = 397,
OP_ISA = 398,
OP_CMPCHAIN_AND = 399,
OP_CMPCHAIN_DUP = 400,
OP_ENTERTRYCATCH = 401,
OP_LEAVETRYCATCH = 402,
OP_POPTRY = 403,
OP_CATCH = 404,
OP_PUSHDEFER = 405,
OP_IS_BOOL = 406,
OP_IS_WEAK = 407,
OP_WEAKEN = 408,
OP_UNWEAKEN = 409,
OP_BLESSED = 410,
OP_REFADDR = 411,
OP_REFTYPE = 412,
OP_CEIL = 413,
OP_FLOOR = 414,
OP_IS_TAINTED = 415,
OP_AELEMFASTLEX_STORE = 139,
OP_AELEM = 140,
OP_ASLICE = 141,
OP_KVASLICE = 142,
OP_AEACH = 143,
OP_AVALUES = 144,
OP_AKEYS = 145,
OP_EACH = 146,
OP_VALUES = 147,
OP_KEYS = 148,
OP_DELETE = 149,
OP_EXISTS = 150,
OP_RV2HV = 151,
OP_HELEM = 152,
OP_HSLICE = 153,
OP_KVHSLICE = 154,
OP_MULTIDEREF = 155,
OP_UNPACK = 156,
OP_PACK = 157,
OP_SPLIT = 158,
OP_JOIN = 159,
OP_LIST = 160,
OP_LSLICE = 161,
OP_ANONLIST = 162,
OP_ANONHASH = 163,
OP_SPLICE = 164,
OP_PUSH = 165,
OP_POP = 166,
OP_SHIFT = 167,
OP_UNSHIFT = 168,
OP_SORT = 169,
OP_REVERSE = 170,
OP_GREPSTART = 171,
OP_GREPWHILE = 172,
OP_MAPSTART = 173,
OP_MAPWHILE = 174,
OP_RANGE = 175,
OP_FLIP = 176,
OP_FLOP = 177,
OP_AND = 178,
OP_OR = 179,
OP_XOR = 180,
OP_DOR = 181,
OP_COND_EXPR = 182,
OP_ANDASSIGN = 183,
OP_ORASSIGN = 184,
OP_DORASSIGN = 185,
OP_ENTERSUB = 186,
OP_LEAVESUB = 187,
OP_LEAVESUBLV = 188,
OP_ARGCHECK = 189,
OP_ARGELEM = 190,
OP_ARGDEFELEM = 191,
OP_CALLER = 192,
OP_WARN = 193,
OP_DIE = 194,
OP_RESET = 195,
OP_LINESEQ = 196,
OP_NEXTSTATE = 197,
OP_DBSTATE = 198,
OP_UNSTACK = 199,
OP_ENTER = 200,
OP_LEAVE = 201,
OP_SCOPE = 202,
OP_ENTERITER = 203,
OP_ITER = 204,
OP_ENTERLOOP = 205,
OP_LEAVELOOP = 206,
OP_RETURN = 207,
OP_LAST = 208,
OP_NEXT = 209,
OP_REDO = 210,
OP_DUMP = 211,
OP_GOTO = 212,
OP_EXIT = 213,
OP_METHOD = 214,
OP_METHOD_NAMED = 215,
OP_METHOD_SUPER = 216,
OP_METHOD_REDIR = 217,
OP_METHOD_REDIR_SUPER = 218,
OP_ENTERGIVEN = 219,
OP_LEAVEGIVEN = 220,
OP_ENTERWHEN = 221,
OP_LEAVEWHEN = 222,
OP_BREAK = 223,
OP_CONTINUE = 224,
OP_OPEN = 225,
OP_CLOSE = 226,
OP_PIPE_OP = 227,
OP_FILENO = 228,
OP_UMASK = 229,
OP_BINMODE = 230,
OP_TIE = 231,
OP_UNTIE = 232,
OP_TIED = 233,
OP_DBMOPEN = 234,
OP_DBMCLOSE = 235,
OP_SSELECT = 236,
OP_SELECT = 237,
OP_GETC = 238,
OP_READ = 239,
OP_ENTERWRITE = 240,
OP_LEAVEWRITE = 241,
OP_PRTF = 242,
OP_PRINT = 243,
OP_SAY = 244,
OP_SYSOPEN = 245,
OP_SYSSEEK = 246,
OP_SYSREAD = 247,
OP_SYSWRITE = 248,
OP_EOF = 249,
OP_TELL = 250,
OP_SEEK = 251,
OP_TRUNCATE = 252,
OP_FCNTL = 253,
OP_IOCTL = 254,
OP_FLOCK = 255,
OP_SEND = 256,
OP_RECV = 257,
OP_SOCKET = 258,
OP_SOCKPAIR = 259,
OP_BIND = 260,
OP_CONNECT = 261,
OP_LISTEN = 262,
OP_ACCEPT = 263,
OP_SHUTDOWN = 264,
OP_GSOCKOPT = 265,
OP_SSOCKOPT = 266,
OP_GETSOCKNAME = 267,
OP_GETPEERNAME = 268,
OP_LSTAT = 269,
OP_STAT = 270,
OP_FTRREAD = 271,
OP_FTRWRITE = 272,
OP_FTREXEC = 273,
OP_FTEREAD = 274,
OP_FTEWRITE = 275,
OP_FTEEXEC = 276,
OP_FTIS = 277,
OP_FTSIZE = 278,
OP_FTMTIME = 279,
OP_FTATIME = 280,
OP_FTCTIME = 281,
OP_FTROWNED = 282,
OP_FTEOWNED = 283,
OP_FTZERO = 284,
OP_FTSOCK = 285,
OP_FTCHR = 286,
OP_FTBLK = 287,
OP_FTFILE = 288,
OP_FTDIR = 289,
OP_FTPIPE = 290,
OP_FTSUID = 291,
OP_FTSGID = 292,
OP_FTSVTX = 293,
OP_FTLINK = 294,
OP_FTTTY = 295,
OP_FTTEXT = 296,
OP_FTBINARY = 297,
OP_CHDIR = 298,
OP_CHOWN = 299,
OP_CHROOT = 300,
OP_UNLINK = 301,
OP_CHMOD = 302,
OP_UTIME = 303,
OP_RENAME = 304,
OP_LINK = 305,
OP_SYMLINK = 306,
OP_READLINK = 307,
OP_MKDIR = 308,
OP_RMDIR = 309,
OP_OPEN_DIR = 310,
OP_READDIR = 311,
OP_TELLDIR = 312,
OP_SEEKDIR = 313,
OP_REWINDDIR = 314,
OP_CLOSEDIR = 315,
OP_FORK = 316,
OP_WAIT = 317,
OP_WAITPID = 318,
OP_SYSTEM = 319,
OP_EXEC = 320,
OP_KILL = 321,
OP_GETPPID = 322,
OP_GETPGRP = 323,
OP_SETPGRP = 324,
OP_GETPRIORITY = 325,
OP_SETPRIORITY = 326,
OP_TIME = 327,
OP_TMS = 328,
OP_LOCALTIME = 329,
OP_GMTIME = 330,
OP_ALARM = 331,
OP_SLEEP = 332,
OP_SHMGET = 333,
OP_SHMCTL = 334,
OP_SHMREAD = 335,
OP_SHMWRITE = 336,
OP_MSGGET = 337,
OP_MSGCTL = 338,
OP_MSGSND = 339,
OP_MSGRCV = 340,
OP_SEMOP = 341,
OP_SEMGET = 342,
OP_SEMCTL = 343,
OP_REQUIRE = 344,
OP_DOFILE = 345,
OP_HINTSEVAL = 346,
OP_ENTEREVAL = 347,
OP_LEAVEEVAL = 348,
OP_ENTERTRY = 349,
OP_LEAVETRY = 350,
OP_GHBYNAME = 351,
OP_GHBYADDR = 352,
OP_GHOSTENT = 353,
OP_GNBYNAME = 354,
OP_GNBYADDR = 355,
OP_GNETENT = 356,
OP_GPBYNAME = 357,
OP_GPBYNUMBER = 358,
OP_GPROTOENT = 359,
OP_GSBYNAME = 360,
OP_GSBYPORT = 361,
OP_GSERVENT = 362,
OP_SHOSTENT = 363,
OP_SNETENT = 364,
OP_SPROTOENT = 365,
OP_SSERVENT = 366,
OP_EHOSTENT = 367,
OP_ENETENT = 368,
OP_EPROTOENT = 369,
OP_ESERVENT = 370,
OP_GPWNAM = 371,
OP_GPWUID = 372,
OP_GPWENT = 373,
OP_SPWENT = 374,
OP_EPWENT = 375,
OP_GGRNAM = 376,
OP_GGRGID = 377,
OP_GGRENT = 378,
OP_SGRENT = 379,
OP_EGRENT = 380,
OP_GETLOGIN = 381,
OP_SYSCALL = 382,
OP_LOCK = 383,
OP_ONCE = 384,
OP_CUSTOM = 385,
OP_COREARGS = 386,
OP_AVHVSWITCH = 387,
OP_RUNCV = 388,
OP_FC = 389,
OP_PADCV = 390,
OP_INTROCV = 391,
OP_CLONECV = 392,
OP_PADRANGE = 393,
OP_REFASSIGN = 394,
OP_LVREF = 395,
OP_LVREFSLICE = 396,
OP_LVAVREF = 397,
OP_ANONCONST = 398,
OP_ISA = 399,
OP_CMPCHAIN_AND = 400,
OP_CMPCHAIN_DUP = 401,
OP_ENTERTRYCATCH = 402,
OP_LEAVETRYCATCH = 403,
OP_POPTRY = 404,
OP_CATCH = 405,
OP_PUSHDEFER = 406,
OP_IS_BOOL = 407,
OP_IS_WEAK = 408,
OP_WEAKEN = 409,
OP_UNWEAKEN = 410,
OP_BLESSED = 411,
OP_REFADDR = 412,
OP_REFTYPE = 413,
OP_CEIL = 414,
OP_FLOOR = 415,
OP_IS_TAINTED = 416,
OP_max
} opcode;
#define MAXO 416
#define MAXO 417
#define OP_FREED MAXO
/* the OP_IS_* macros are optimized to a simple range check because

49
peep.c
View File

@ -3951,6 +3951,55 @@ Perl_rpeep(pTHX_ OP *o)
/* NULL the previous op ptrs, so rpeep can continue */
oldoldop = NULL; oldop = NULL;
}
/* Combine a simple SASSIGN OP with an AELEMFAST_LEX lvalue
* into a single OP. This optimization covers arbitrarily
* complicated RHS OP trees. */
if (!(o->op_private & (OPpASSIGN_BACKWARDS|OPpASSIGN_CV_TO_GV))
&& (lval->op_type == OP_NULL) && (lval->op_private == 2) &&
(cBINOPx(lval)->op_first->op_type == OP_AELEMFAST_LEX) &&
((I8)(cBINOPx(lval)->op_first->op_private) >= 0)
) {
OP * lex = cBINOPx(lval)->op_first;
/* SASSIGN's bitfield flags, such as op_moresib and
* op_slabbed, will be carried over unchanged. */
OpTYPE_set(o, OP_AELEMFASTLEX_STORE);
/* Explicitly craft the new OP's op_flags, carrying
* some bits over from the SASSIGN */
o->op_flags = (
OPf_KIDS | OPf_STACKED |
(o->op_flags & (OPf_WANT|OPf_PARENS))
);
/* Copy the AELEMFAST_LEX op->private, which contains
* the key index. */
o->op_private = lex->op_private;
/* Take the targ from the AELEMFAST_LEX */
o->op_targ = lex->op_targ; lex->op_targ = 0;
assert(oldop->op_type == OP_AELEMFAST_LEX);
/* oldoldop can be arbitrarily deep in the RHS OP tree */
oldoldop->op_next = o;
/* Even when (rhs != oldoldop), rhs might still have a
* relevant op_next ptr to lex. (Updating it here can
* also cause other ops in the RHS to get the desired
* op_next pointer, presumably thanks to the finalizer.)
* This is definitely truewhen rhs is OP_NULL with a
* LOGOP kid (e.g. orassign). There may be other cases. */
if (rhs->op_next == lex)
rhs->op_next = o;
/* Now null-out the AELEMFAST_LEX */
op_null(lex);
/* NULL the previous op ptrs, so rpeep can continue */
oldop = oldoldop; oldoldop = NULL;
}
break;
}

View File

@ -169,6 +169,56 @@ PP(pp_padsv_store)
RETURN;
}
/* A mashup of simplified AELEMFAST_LEX + SASSIGN OPs */
PP(pp_aelemfastlex_store)
{
dSP;
OP * const op = PL_op;
SV* const val = TOPs; /* RHS value to assign */
AV * const av = MUTABLE_AV(PAD_SV(op->op_targ));
const I8 key = (I8)PL_op->op_private;
SV * targ = NULL;
/* !OPf_STACKED is not handled by this OP */
assert(op->op_flags & OPf_STACKED);
/* Inlined, simplified pp_aelemfast here */
assert(SvTYPE(av) == SVt_PVAV);
assert(key >= 0);
/* inlined av_fetch() for simple cases ... */
if (!SvRMAGICAL(av) && key <= AvFILLp(av)) {
targ = AvARRAY(av)[key];
}
/* ... else do it the hard way */
if (!targ) {
SV **svp = av_fetch(av, key, 1);
if (svp)
targ = *svp;
else
DIE(aTHX_ PL_no_aelem, (int)key);
}
/* Inlined, simplified pp_sassign from here */
assert(TAINTING_get || !TAINT_get);
if (UNLIKELY(TAINT_get) && !SvTAINTED(val))
TAINT_NOT;
if (
UNLIKELY(SvTEMP(targ)) && !SvSMAGICAL(targ) && SvREFCNT(targ) == 1 &&
(!isGV_with_GP(targ) || SvFAKE(targ)) && ckWARN(WARN_MISC)
)
Perl_warner(aTHX_
packWARN(WARN_MISC), "Useless assignment to a temporary"
);
SvSetMagicSV(targ, val);
SETs(targ);
RETURN;
}
PP(pp_sassign)
{
dSP;

View File

@ -12,6 +12,7 @@ PERL_CALLCONV OP *Perl_pp_add(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_aeach(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_aelem(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_aelemfast(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_aelemfastlex_store(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_akeys(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_alarm(pTHX) __attribute__visibility__("hidden");
PERL_CALLCONV OP *Perl_pp_and(pTHX) __attribute__visibility__("hidden");

View File

@ -199,7 +199,7 @@ use strict;
# find which ops use 0,1,2,3 or 4 bits of op_private for arg count info
$args0{$_} = 1 for qw(entersub avhvswitch
rv2hv); # UNOPs that usurp bit 0
rv2hv aelemfastlex_store); # UNOPs that usurp bit 0
# Historically, bit ops used bit 0 to indicate 'use integer' in scope;
# For now, ban use of bits 0..1 as an arg count, in order to detect
@ -627,7 +627,7 @@ addbits('padrange',
for (qw(aelemfast aelemfast_lex)) {
for (qw(aelemfast aelemfast_lex aelemfastlex_store)) {
addbits($_,
'0..7' => {
label => 'key',

View File

@ -223,6 +223,7 @@ quotemeta quotemeta ck_fun fstu% S?
rv2av array dereference ck_rvconst dt1
aelemfast constant array element ck_null ds$ A S
aelemfast_lex constant lexical array element ck_null d0 A S
aelemfastlex_store const lexical array element store ck_null d1 A S
aelem array element ck_null s2 A S
aslice array slice ck_null m@ A L
kvaslice index/value array slice ck_null m@ A L

View File

@ -1402,6 +1402,22 @@
code => '$r = []; $r = $r1;',
},
'expr::sassign::aelemfast_lex_assign' => {
desc => 'lexical $x[0] = 1',
setup => 'my @x',
code => '$x[0] = 1',
},
'expr::sassign::aelemfast_lex_assign_ref' => {
desc => 'lexical $x[0] = []',
setup => 'my @x',
code => '$x[0] = []',
},
'expr::sassign::aelemfast_lex_assign_deref' => {
desc => 'lexical $x[0][1]',
setup => 'my @x = ([1,2])',
code => '$x[0][1] = 1',
},
'func::grep::bool0' => {
desc => 'grep returning 0 items in boolean context',

View File

@ -886,4 +886,36 @@ test_opcount(0, 'my $y= 1; my @x= \($y= undef);',
srefgen => 1,
});
# aelemfast_lex + sassign are replaced by a combined OP
test_opcount(0, "simple aelemfast_lex + sassign replacement",
sub { my @x; $x[0] = "foo" },
{
aelemfast_lex => 0,
aelemfastlex_store => 1,
padav => 1,
sassign => 0,
});
# aelemfast_lex + sassign are not replaced by a combined OP
# when key <0 (not handled, to keep the pp_ function simple
test_opcount(0, "no aelemfast_lex + sassign replacement with neg key",
sub { my @x = (1,2); $x[-1] = 7 },
{
aelemfast_lex => 1,
aelemfastlex_store => 0,
padav => 1,
sassign => 1,
});
# aelemfast_lex + sassign optimization does not disrupt multideref
test_opcount(0, "no aelemfast_lex + sassign replacement with multideref",
sub { my @x = ([1,2]); $x[0][1] = 1; },
{
aelemfast_lex => 0,
aelemfastlex_store => 0,
multideref => 1,
padav => 1,
sassign => 1,
});
done_testing();