diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index 7a675d3b7b..b4d059e805 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -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 diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 8cd02ce4dc..8895204308 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -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) = @_; diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm index df34dff846..01931ed94f 100644 --- a/lib/B/Op_private.pm +++ b/lib/B/Op_private.pm @@ -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]; diff --git a/opcode.h b/opcode.h index dc52549ff4..616d0c9eea 100644 --- a/opcode.h +++ b/opcode.h @@ -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), diff --git a/opnames.h b/opnames.h index 24c0245ea2..3e1751006d 100644 --- a/opnames.h +++ b/opnames.h @@ -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 diff --git a/peep.c b/peep.c index 9e558e4186..c18a305dd9 100644 --- a/peep.c +++ b/peep.c @@ -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; } diff --git a/pp_hot.c b/pp_hot.c index cb76dda568..e64dbd093d 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -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; diff --git a/pp_proto.h b/pp_proto.h index c89828a56b..759545152a 100644 --- a/pp_proto.h +++ b/pp_proto.h @@ -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"); diff --git a/regen/op_private b/regen/op_private index 0773626c3f..4f2afe2174 100644 --- a/regen/op_private +++ b/regen/op_private @@ -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', diff --git a/regen/opcodes b/regen/opcodes index 80fbe149c3..f6b68ec61b 100644 --- a/regen/opcodes +++ b/regen/opcodes @@ -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 diff --git a/t/perf/benchmarks b/t/perf/benchmarks index 8a822e3cc1..7b457abff3 100644 --- a/t/perf/benchmarks +++ b/t/perf/benchmarks @@ -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', diff --git a/t/perf/opcount.t b/t/perf/opcount.t index 0388cb6e98..ffb878220e 100644 --- a/t/perf/opcount.t +++ b/t/perf/opcount.t @@ -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();