From 8ab1b4ba5222678b0aea6ee8374836ed3d882ffd Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Tue, 2 Aug 2022 21:48:26 +0000 Subject: [PATCH 1/2] OP_EMPTYAVHV - optimized empty ANONLIST/ANONHASH This commit introduces a new OP to replace cases of OP_ANONLIST and OP_ANONHASH where there are zero elements, which is very common in Perl code. As an example, `my $x = {}` is currently implemented like this: ... 6 <2> sassign vKS/2 ->7 4 <@> anonhash sK* ->5 3 <0> pushmark s ->4 5 <0> padsv[$x:1,2] sRM*/LVINTRO ->6 The pushmark serves no meaningful purpose when there are zero elements and the anonhash, besides undoing the pushmark, performs work that is unnecessary for this special case. The peephole optimizer, which also checks for applicability of a related TARGMY optimization, transforms this example into: ... - <1> ex-sassign vKS/2 ->4 3 <@> emptyavhv[$x:1,2] vK*/LVINTRO,ANONHASH,TARGMY ->4 - <0> ex-pushmark s ->3 - <0> ex-padsv sRM*/LVINTRO ->- --- ext/Opcode/Opcode.pm | 1 + lib/B/Deparse.pm | 19 +- lib/B/Op_private.pm | 16 +- opcode.h | 282 ++++++++++++------------ opnames.h | 509 ++++++++++++++++++++++--------------------- peep.c | 56 +++++ pp.c | 45 ++++ pp_proto.h | 1 + regen/op_private | 11 +- regen/opcodes | 1 + t/perf/benchmarks | 29 +++ t/perf/opcount.t | 96 +++++++- 12 files changed, 665 insertions(+), 401 deletions(-) diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index f81a6a22165c..f8615eef0f3c 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -336,6 +336,7 @@ invert_opset function. warn die lineseq nextstate scope enter leave rv2cv anoncode prototype coreargs avhvswitch anonconst + emptyavhv entersub leavesub leavesublv return method method_named method_super method_redir method_redir_super diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 3afaba25cd6e..d84d2a2709f1 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -7,14 +7,14 @@ # This is based on the module of the same name by Malcolm Beattie, # but essentially none of his code remains. -package B::Deparse 1.70; +package B::Deparse 1.71; use strict; use Carp; use B qw(class main_root main_start main_cv svref_2object opnumber perlstring OPf_WANT OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL OPf_MOD OPf_PARENS OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpKVSLICE - OPpCONST_BARE + OPpCONST_BARE OPpEMPTYAVHV_IS_HV OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER OPpREPEAT_DOLIST OPpSORT_REVERSE OPpMULTIDEREF_EXISTS OPpMULTIDEREF_DELETE @@ -2785,6 +2785,21 @@ sub pp_anonlist { *pp_anonhash = \&pp_anonlist; +sub pp_emptyavhv { + my $self = shift; + my ($op, $cx, $forbid_parens) = @_; + my $val = ($op->private & OPpEMPTYAVHV_IS_HV) ? '{}' : '[]'; + if ($op->private & OPpTARGET_MY) { + my $targ = $op->targ; + my $var = $self->maybe_my($op, $cx, $self->padname($targ), + $self->padname_sv($targ), + $forbid_parens); + return $self->maybe_parens("$var = $val", $cx, 7); + } else { + return $val; + } +} + sub pp_refgen { my $self = shift; my($op, $cx) = @_; diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm index 8dc37a26145f..bf7528fd1c0e 100644 --- a/lib/B/Op_private.pm +++ b/lib/B/Op_private.pm @@ -134,7 +134,7 @@ $bits{$_}{6} = 'OPpINDEX_BOOLNEG' for qw(index rindex); $bits{$_}{1} = 'OPpITER_REVERSED' for qw(enteriter iter); $bits{$_}{7} = 'OPpLVALUE' for qw(leave leaveloop); $bits{$_}{6} = 'OPpLVAL_DEFER' for qw(aelem helem multideref); -$bits{$_}{7} = 'OPpLVAL_INTRO' for qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multiconcat multideref padav padhv padrange padsv padsv_store pushmark refassign rv2av rv2gv rv2hv rv2sv split undef); +$bits{$_}{7} = 'OPpLVAL_INTRO' for qw(aelem aslice cond_expr delete emptyavhv enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multiconcat multideref padav padhv padrange padsv padsv_store pushmark refassign rv2av rv2gv rv2hv rv2sv split undef); $bits{$_}{2} = 'OPpLVREF_ELEM' for qw(lvref refassign); $bits{$_}{3} = 'OPpLVREF_ITER' for qw(lvref refassign); $bits{$_}{3} = 'OPpMAYBE_LVSUB' for qw(aassign aelem akeys aslice av2arylen avhvswitch helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr values vec); @@ -145,11 +145,11 @@ $bits{$_}{4} = 'OPpOPEN_IN_RAW' for qw(backtick open); $bits{$_}{7} = 'OPpOPEN_OUT_CRLF' for qw(backtick open); $bits{$_}{6} = 'OPpOPEN_OUT_RAW' for qw(backtick open); $bits{$_}{6} = 'OPpOUR_INTRO' for qw(enteriter gvsv rv2av rv2hv rv2sv split); -$bits{$_}{6} = 'OPpPAD_STATE' for qw(lvavref lvref padav padhv padsv padsv_store pushmark refassign undef); +$bits{$_}{6} = 'OPpPAD_STATE' for qw(emptyavhv lvavref lvref padav padhv padsv padsv_store pushmark refassign undef); $bits{$_}{7} = 'OPpPV_IS_UTF8' for qw(dump goto last next redo); $bits{$_}{6} = 'OPpREFCOUNTED' for qw(leave leaveeval leavesub leavesublv leavewrite); $bits{$_}{2} = 'OPpSLICEWARNING' for qw(aslice hslice padav padhv rv2av rv2hv); -$bits{$_}{4} = 'OPpTARGET_MY' for qw(abs add atan2 ceil chdir chmod chomp chown chr chroot concat cos crypt divide exec exp flock floor getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiconcat multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand refaddr reftype rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time undef unlink unshift utime wait waitpid); +$bits{$_}{4} = 'OPpTARGET_MY' for qw(abs add atan2 ceil chdir chmod chomp chown chr chroot concat cos crypt divide emptyavhv exec exp flock floor getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiconcat multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand refaddr reftype rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time undef unlink unshift utime wait waitpid); $bits{$_}{0} = 'OPpTRANS_CAN_FORCE_UTF8' for qw(trans transr); $bits{$_}{5} = 'OPpTRANS_COMPLEMENT' for qw(trans transr); $bits{$_}{7} = 'OPpTRANS_DELETE' for qw(trans transr); @@ -306,6 +306,7 @@ $bits{dor}{0} = $bf[0]; $bits{dorassign}{0} = $bf[0]; $bits{dump}{0} = $bf[0]; $bits{each}{0} = $bf[0]; +@{$bits{emptyavhv}}{5,3,2,1,0} = ('OPpEMPTYAVHV_IS_HV', $bf[4], $bf[4], $bf[4], $bf[4]); @{$bits{entereval}}{5,4,3,2,1,0} = ('OPpEVAL_RE_REPARSING', 'OPpEVAL_COPHH', 'OPpEVAL_BYTES', 'OPpEVAL_UNICODE', 'OPpEVAL_HAS_HH', $bf[0]); $bits{entergiven}{0} = $bf[0]; $bits{enteriter}{3} = 'OPpITER_DEF'; @@ -623,6 +624,7 @@ our %defines = ( OPpDEREF_SV => 48, OPpDONT_INIT_GV => 4, OPpEARLY_CV => 32, + OPpEMPTYAVHV_IS_HV => 32, OPpENTERSUB_AMPER => 8, OPpENTERSUB_DB => 64, OPpENTERSUB_HASTARG => 4, @@ -730,6 +732,7 @@ our %labels = ( OPpDEREF_SV => 'DREFSV', OPpDONT_INIT_GV => 'NOINIT', OPpEARLY_CV => 'EARLYCV', + OPpEMPTYAVHV_IS_HV => 'ANONHASH', OPpENTERSUB_AMPER => 'AMPER', OPpENTERSUB_DB => 'DBG', OPpENTERSUB_HASTARG => 'TARG', @@ -817,6 +820,7 @@ our %ops_using = ( OPpCOREARGS_DEREF1 => [qw(coreargs)], OPpDEFER_FINALLY => [qw(pushdefer)], OPpEARLY_CV => [qw(gv)], + OPpEMPTYAVHV_IS_HV => [qw(emptyavhv)], OPpENTERSUB_AMPER => [qw(entersub rv2cv)], OPpENTERSUB_INARGS => [qw(entersub)], OPpENTERSUB_NOPAREN => [qw(rv2cv)], @@ -834,7 +838,7 @@ our %ops_using = ( OPpLIST_GUESSED => [qw(list)], OPpLVALUE => [qw(leave leaveloop)], OPpLVAL_DEFER => [qw(aelem helem multideref)], - OPpLVAL_INTRO => [qw(aelem aslice cond_expr delete enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multiconcat multideref padav padhv padrange padsv padsv_store pushmark refassign rv2av rv2gv rv2hv rv2sv split undef)], + OPpLVAL_INTRO => [qw(aelem aslice cond_expr delete emptyavhv enteriter entersub gvsv helem hslice list lvavref lvref lvrefslice multiconcat multideref padav padhv padrange padsv padsv_store pushmark refassign rv2av rv2gv rv2hv rv2sv split undef)], OPpLVREF_ELEM => [qw(lvref refassign)], OPpMAYBE_LVSUB => [qw(aassign aelem akeys aslice av2arylen avhvswitch helem hslice keys kvaslice kvhslice multideref padav padhv pos rv2av rv2gv rv2hv substr values vec)], OPpMAYBE_TRUEBOOL => [qw(blessed padhv ref rv2hv)], @@ -844,7 +848,7 @@ our %ops_using = ( OPpOPEN_IN_CRLF => [qw(backtick open)], OPpOUR_INTRO => [qw(enteriter gvsv rv2av rv2hv rv2sv split)], OPpPADHV_ISKEYS => [qw(padhv)], - OPpPAD_STATE => [qw(lvavref lvref padav padhv padsv padsv_store pushmark refassign undef)], + OPpPAD_STATE => [qw(emptyavhv lvavref lvref padav padhv padsv padsv_store pushmark refassign undef)], OPpPV_IS_UTF8 => [qw(dump goto last next redo)], OPpREFCOUNTED => [qw(leave leaveeval leavesub leavesublv leavewrite)], OPpREPEAT_DOLIST => [qw(repeat)], @@ -854,7 +858,7 @@ our %ops_using = ( OPpSORT_DESCEND => [qw(sort)], OPpSPLIT_ASSIGN => [qw(split)], OPpSUBSTR_REPL_FIRST => [qw(substr)], - OPpTARGET_MY => [qw(abs add atan2 ceil chdir chmod chomp chown chr chroot concat cos crypt divide exec exp flock floor getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiconcat multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand refaddr reftype rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time undef unlink unshift utime wait waitpid)], + OPpTARGET_MY => [qw(abs add atan2 ceil chdir chmod chomp chown chr chroot concat cos crypt divide emptyavhv exec exp flock floor getpgrp getppid getpriority hex i_add i_divide i_modulo i_multiply i_subtract index int kill left_shift length link log mkdir modulo multiconcat multiply nbit_and nbit_or nbit_xor ncomplement oct ord pow push rand refaddr reftype rename right_shift rindex rmdir schomp scomplement setpgrp setpriority sin sleep sqrt srand stringify subtract symlink system time undef unlink unshift utime wait waitpid)], OPpTRANS_CAN_FORCE_UTF8 => [qw(trans transr)], OPpTRUEBOOL => [qw(blessed grepwhile index length padav padhv pos ref rindex rv2av rv2hv subst)], OPpUNDEF_KEEP_PV => [qw(undef)], diff --git a/opcode.h b/opcode.h index 616d0c9eeaa7..55b44de68c61 100644 --- a/opcode.h +++ b/opcode.h @@ -313,6 +313,7 @@ EXTCONST char* const PL_op_name[] = { "lslice", "anonlist", "anonhash", + "emptyavhv", "splice", "push", "pop", @@ -738,6 +739,7 @@ EXTCONST char* const PL_op_desc[] = { "list slice", "anonymous array ([])", "anonymous hash ({})", + "empty anon hash/array", "splice", "push", "pop", @@ -1166,6 +1168,7 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */ Perl_pp_lslice, Perl_pp_anonlist, Perl_pp_anonhash, + Perl_pp_emptyavhv, Perl_pp_splice, Perl_pp_push, Perl_pp_pop, /* implemented by Perl_pp_shift */ @@ -1590,6 +1593,7 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */ Perl_ck_null, /* lslice */ Perl_ck_fun, /* anonlist */ Perl_ck_fun, /* anonhash */ + Perl_ck_fun, /* emptyavhv */ Perl_ck_fun, /* splice */ Perl_ck_fun, /* push */ Perl_ck_shift, /* pop */ @@ -2015,6 +2019,7 @@ EXTCONST U32 PL_opargs[] = { 0x00224200, /* lslice */ 0x00002405, /* anonlist */ 0x00002405, /* anonhash */ + 0x0000241c, /* emptyavhv */ 0x02993401, /* splice */ 0x0002341d, /* push */ 0x0000bb04, /* pop */ @@ -2339,6 +2344,7 @@ END_EXTERN_C #define OPpASSIGN_COMMON_RC1 0x20 #define OPpDEREF_HV 0x20 #define OPpEARLY_CV 0x20 +#define OPpEMPTYAVHV_IS_HV 0x20 #define OPpEVAL_RE_REPARSING 0x20 #define OPpHUSH_VMSISH 0x20 #define OPpKVSLICE 0x20 @@ -2410,6 +2416,7 @@ EXTCONST char PL_op_private_labels[] = { '+','1','\0', '-','\0', 'A','M','P','E','R','\0', + 'A','N','O','N','H','A','S','H','\0', 'A','P','P','E','N','D','\0', 'A','S','S','I','G','N','\0', 'A','V','\0', @@ -2521,14 +2528,14 @@ EXTCONST char PL_op_private_labels[] = { EXTCONST I16 PL_op_private_bitfields[] = { 0, 8, -1, 0, 8, -1, - 0, 604, -1, + 0, 613, -1, 0, 8, -1, 0, 8, -1, - 0, 611, -1, - 0, 600, -1, - 1, -1, 0, 561, 1, 30, 2, 303, -1, - 4, -1, 1, 176, 2, 183, 3, 190, -1, - 4, -1, 0, 561, 1, 30, 2, 303, 3, 122, -1, + 0, 620, -1, + 0, 609, -1, + 1, -1, 0, 570, 1, 39, 2, 312, -1, + 4, -1, 1, 185, 2, 192, 3, 199, -1, + 4, -1, 0, 570, 1, 39, 2, 312, 3, 131, -1, }; @@ -2701,55 +2708,56 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 12, /* lslice */ 55, /* anonlist */ 55, /* anonhash */ + 163, /* emptyavhv */ 55, /* splice */ 101, /* push */ 0, /* pop */ 0, /* shift */ 101, /* unshift */ - 163, /* sort */ - 168, /* reverse */ + 168, /* sort */ + 173, /* reverse */ 0, /* grepstart */ - 170, /* grepwhile */ + 175, /* grepwhile */ 0, /* mapstart */ 0, /* mapwhile */ 0, /* range */ - 172, /* flip */ - 172, /* flop */ + 177, /* flip */ + 177, /* flop */ 0, /* and */ 0, /* or */ 12, /* xor */ 0, /* dor */ - 174, /* cond_expr */ + 179, /* cond_expr */ 0, /* andassign */ 0, /* orassign */ 0, /* dorassign */ - 176, /* entersub */ - 183, /* leavesub */ - 183, /* leavesublv */ + 181, /* entersub */ + 188, /* leavesub */ + 188, /* leavesublv */ 0, /* argcheck */ - 185, /* argelem */ + 190, /* argelem */ 0, /* argdefelem */ - 187, /* caller */ + 192, /* caller */ 55, /* warn */ 55, /* die */ 55, /* reset */ -1, /* lineseq */ - 189, /* nextstate */ - 189, /* dbstate */ + 194, /* nextstate */ + 194, /* dbstate */ -1, /* unstack */ -1, /* enter */ - 190, /* leave */ + 195, /* leave */ -1, /* scope */ - 192, /* enteriter */ - 196, /* iter */ + 197, /* enteriter */ + 201, /* iter */ -1, /* enterloop */ - 197, /* leaveloop */ + 202, /* leaveloop */ -1, /* return */ - 199, /* last */ - 199, /* next */ - 199, /* redo */ - 199, /* dump */ - 199, /* goto */ + 204, /* last */ + 204, /* next */ + 204, /* redo */ + 204, /* dump */ + 204, /* goto */ 55, /* exit */ 0, /* method */ 0, /* method_named */ @@ -2762,7 +2770,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* leavewhen */ -1, /* break */ -1, /* continue */ - 201, /* open */ + 206, /* open */ 55, /* close */ 55, /* pipe_op */ 55, /* fileno */ @@ -2778,7 +2786,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 55, /* getc */ 55, /* read */ 55, /* enterwrite */ - 183, /* leavewrite */ + 188, /* leavewrite */ -1, /* prtf */ -1, /* print */ -1, /* say */ @@ -2808,33 +2816,33 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* getpeername */ 0, /* lstat */ 0, /* stat */ - 206, /* ftrread */ - 206, /* ftrwrite */ - 206, /* ftrexec */ - 206, /* fteread */ - 206, /* ftewrite */ - 206, /* fteexec */ - 211, /* ftis */ - 211, /* ftsize */ - 211, /* ftmtime */ - 211, /* ftatime */ - 211, /* ftctime */ - 211, /* ftrowned */ - 211, /* fteowned */ - 211, /* ftzero */ - 211, /* ftsock */ - 211, /* ftchr */ - 211, /* ftblk */ - 211, /* ftfile */ - 211, /* ftdir */ - 211, /* ftpipe */ - 211, /* ftsuid */ - 211, /* ftsgid */ - 211, /* ftsvtx */ - 211, /* ftlink */ - 211, /* fttty */ - 211, /* fttext */ - 211, /* ftbinary */ + 211, /* ftrread */ + 211, /* ftrwrite */ + 211, /* ftrexec */ + 211, /* fteread */ + 211, /* ftewrite */ + 211, /* fteexec */ + 216, /* ftis */ + 216, /* ftsize */ + 216, /* ftmtime */ + 216, /* ftatime */ + 216, /* ftctime */ + 216, /* ftrowned */ + 216, /* fteowned */ + 216, /* ftzero */ + 216, /* ftsock */ + 216, /* ftchr */ + 216, /* ftblk */ + 216, /* ftfile */ + 216, /* ftdir */ + 216, /* ftpipe */ + 216, /* ftsuid */ + 216, /* ftsgid */ + 216, /* ftsvtx */ + 216, /* ftlink */ + 216, /* fttty */ + 216, /* fttext */ + 216, /* ftbinary */ 101, /* chdir */ 101, /* chown */ 78, /* chroot */ @@ -2854,17 +2862,17 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* rewinddir */ 0, /* closedir */ -1, /* fork */ - 215, /* wait */ + 220, /* wait */ 101, /* waitpid */ 101, /* system */ 101, /* exec */ 101, /* kill */ - 215, /* getppid */ + 220, /* getppid */ 101, /* getpgrp */ 101, /* setpgrp */ 101, /* getpriority */ 101, /* setpriority */ - 215, /* time */ + 220, /* time */ -1, /* tms */ 0, /* localtime */ 55, /* gmtime */ @@ -2884,8 +2892,8 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* require */ 0, /* dofile */ -1, /* hintseval */ - 216, /* entereval */ - 183, /* leaveeval */ + 221, /* entereval */ + 188, /* leaveeval */ 0, /* entertry */ -1, /* leavetry */ 0, /* ghbyname */ @@ -2923,17 +2931,17 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* lock */ 0, /* once */ -1, /* custom */ - 222, /* coreargs */ - 226, /* avhvswitch */ + 227, /* coreargs */ + 231, /* avhvswitch */ 3, /* runcv */ 0, /* fc */ -1, /* padcv */ -1, /* introcv */ -1, /* clonecv */ - 228, /* padrange */ - 230, /* refassign */ - 236, /* lvref */ - 242, /* lvrefslice */ + 233, /* padrange */ + 235, /* refassign */ + 241, /* lvref */ + 247, /* lvrefslice */ 16, /* lvavref */ 0, /* anonconst */ 12, /* isa */ @@ -2943,7 +2951,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { -1, /* leavetrycatch */ -1, /* poptry */ 0, /* catch */ - 243, /* pushdefer */ + 248, /* pushdefer */ 0, /* is_bool */ 0, /* is_weak */ 0, /* weaken */ @@ -2973,79 +2981,80 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { EXTCONST U16 PL_op_private_bitdefs[] = { 0x0003, /* scalar, prototype, refgen, srefgen, readline, regcmaybe, regcreset, regcomp, substcont, chop, schop, defined, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, negate, i_negate, not, ucfirst, lcfirst, uc, lc, quotemeta, aeach, avalues, each, pop, shift, grepstart, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, argcheck, argdefelem, 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, fc, anonconst, cmpchain_and, cmpchain_dup, entertrycatch, catch, is_bool, is_weak, weaken, unweaken, is_tainted */ - 0x31dc, 0x42d9, /* pushmark */ + 0x32fc, 0x43f9, /* pushmark */ 0x00bd, /* wantarray, runcv */ - 0x0438, 0x1a50, 0x438c, 0x3f28, 0x3705, /* const */ - 0x31dc, 0x3859, /* gvsv */ - 0x18b5, /* gv */ + 0x0558, 0x1b70, 0x44ac, 0x4048, 0x3825, /* const */ + 0x32fc, 0x3979, /* gvsv */ + 0x19d5, /* gv */ 0x0067, /* gelem, lt, i_lt, gt, i_gt, le, i_le, ge, i_ge, eq, i_eq, ne, i_ne, ncmp, i_ncmp, slt, sgt, sle, sge, seq, sne, scmp, smartmatch, lslice, xor, isa */ - 0x31dc, 0x42d8, 0x03d7, /* padsv */ - 0x31dc, 0x42d8, 0x0003, /* padsv_store, lvavref */ - 0x31dc, 0x42d8, 0x05b4, 0x32cc, 0x40a9, /* padav */ - 0x31dc, 0x42d8, 0x05b4, 0x0650, 0x32cc, 0x40a8, 0x2d41, /* padhv */ - 0x31dc, 0x1c38, 0x03d6, 0x32cc, 0x3628, 0x4384, 0x0003, /* rv2gv */ - 0x31dc, 0x3858, 0x03d6, 0x4384, 0x0003, /* rv2sv */ - 0x32cc, 0x0003, /* av2arylen, akeys, values, keys */ - 0x359c, 0x1078, 0x0dd4, 0x014c, 0x4688, 0x4384, 0x0003, /* rv2cv */ - 0x05b4, 0x0650, 0x0003, /* ref, blessed */ + 0x32fc, 0x43f8, 0x03d7, /* padsv */ + 0x32fc, 0x43f8, 0x0003, /* padsv_store, lvavref */ + 0x32fc, 0x43f8, 0x06d4, 0x33ec, 0x41c9, /* padav */ + 0x32fc, 0x43f8, 0x06d4, 0x0770, 0x33ec, 0x41c8, 0x2e61, /* padhv */ + 0x32fc, 0x1d58, 0x03d6, 0x33ec, 0x3748, 0x44a4, 0x0003, /* rv2gv */ + 0x32fc, 0x3978, 0x03d6, 0x44a4, 0x0003, /* rv2sv */ + 0x33ec, 0x0003, /* av2arylen, akeys, values, keys */ + 0x36bc, 0x1198, 0x0ef4, 0x014c, 0x47a8, 0x44a4, 0x0003, /* rv2cv */ + 0x06d4, 0x0770, 0x0003, /* ref, blessed */ 0x018f, /* bless, glob, sprintf, formline, unpack, pack, join, anonlist, anonhash, splice, warn, die, reset, exit, close, pipe_op, fileno, umask, binmode, tie, dbmopen, sselect, select, getc, read, enterwrite, sysopen, sysseek, sysread, syswrite, eof, tell, seek, truncate, fcntl, ioctl, send, recv, socket, sockpair, bind, connect, listen, accept, shutdown, gsockopt, ssockopt, open_dir, seekdir, gmtime, shmget, shmctl, shmread, shmwrite, msgget, msgctl, msgsnd, msgrcv, semop, semget, semctl, ghbyaddr, gnbyaddr, gpbynumber, gsbyname, gsbyport, syscall */ - 0x3a3c, 0x3958, 0x2994, 0x28d0, 0x0003, /* backtick */ - 0x05b5, /* subst */ - 0x117c, 0x22b8, 0x09b4, 0x41ec, 0x2648, 0x4964, 0x07c1, /* trans, transr */ - 0x0fbc, 0x04d8, 0x0067, /* sassign */ - 0x0c78, 0x0b74, 0x0a70, 0x32cc, 0x05a8, 0x0067, /* aassign */ - 0x4730, 0x0003, /* chomp, schomp, scomplement, sin, cos, exp, log, sqrt, int, hex, oct, abs, ord, chr, chroot, rmdir, refaddr, reftype, ceil, floor */ - 0x31dc, 0x42d8, 0x2c54, 0x4730, 0x0003, /* undef */ - 0x05b4, 0x32cc, 0x0003, /* pos */ - 0x4730, 0x0067, /* pow, multiply, i_multiply, divide, i_divide, modulo, i_modulo, add, i_add, subtract, i_subtract */ - 0x1538, 0x0067, /* repeat */ - 0x34b8, 0x4730, 0x0067, /* concat */ - 0x31dc, 0x0218, 0x1c34, 0x4730, 0x446c, 0x0003, /* multiconcat */ - 0x4730, 0x018f, /* stringify, atan2, rand, srand, crypt, push, unshift, flock, chdir, chown, unlink, chmod, utime, rename, link, symlink, mkdir, waitpid, system, exec, kill, getpgrp, setpgrp, getpriority, setpriority, sleep */ - 0x4730, 0x4889, /* left_shift, right_shift, nbit_and, nbit_xor, nbit_or, ncomplement */ - 0x4889, /* bit_and, bit_xor, bit_or, sbit_and, sbit_xor, sbit_or, complement */ - 0x05b4, 0x4730, 0x0003, /* length */ - 0x3c90, 0x32cc, 0x012b, /* substr */ - 0x32cc, 0x0067, /* vec */ - 0x3438, 0x05b4, 0x4730, 0x018f, /* index, rindex */ - 0x31dc, 0x3858, 0x05b4, 0x32cc, 0x40a8, 0x4384, 0x0003, /* rv2av */ + 0x3b5c, 0x3a78, 0x2ab4, 0x29f0, 0x0003, /* backtick */ + 0x06d5, /* subst */ + 0x129c, 0x23d8, 0x0ad4, 0x430c, 0x2768, 0x4a84, 0x08e1, /* trans, transr */ + 0x10dc, 0x05f8, 0x0067, /* sassign */ + 0x0d98, 0x0c94, 0x0b90, 0x33ec, 0x06c8, 0x0067, /* aassign */ + 0x4850, 0x0003, /* chomp, schomp, scomplement, sin, cos, exp, log, sqrt, int, hex, oct, abs, ord, chr, chroot, rmdir, refaddr, reftype, ceil, floor */ + 0x32fc, 0x43f8, 0x2d74, 0x4850, 0x0003, /* undef */ + 0x06d4, 0x33ec, 0x0003, /* pos */ + 0x4850, 0x0067, /* pow, multiply, i_multiply, divide, i_divide, modulo, i_modulo, add, i_add, subtract, i_subtract */ + 0x1658, 0x0067, /* repeat */ + 0x35d8, 0x4850, 0x0067, /* concat */ + 0x32fc, 0x0338, 0x1d54, 0x4850, 0x458c, 0x0003, /* multiconcat */ + 0x4850, 0x018f, /* stringify, atan2, rand, srand, crypt, push, unshift, flock, chdir, chown, unlink, chmod, utime, rename, link, symlink, mkdir, waitpid, system, exec, kill, getpgrp, setpgrp, getpriority, setpriority, sleep */ + 0x4850, 0x49a9, /* left_shift, right_shift, nbit_and, nbit_xor, nbit_or, ncomplement */ + 0x49a9, /* bit_and, bit_xor, bit_or, sbit_and, sbit_xor, sbit_or, complement */ + 0x06d4, 0x4850, 0x0003, /* length */ + 0x3db0, 0x33ec, 0x012b, /* substr */ + 0x33ec, 0x0067, /* vec */ + 0x3558, 0x06d4, 0x4850, 0x018f, /* index, rindex */ + 0x32fc, 0x3978, 0x06d4, 0x33ec, 0x41c8, 0x44a4, 0x0003, /* rv2av */ 0x025f, /* aelemfast, aelemfast_lex, aelemfastlex_store */ - 0x31dc, 0x30d8, 0x03d6, 0x32cc, 0x0067, /* aelem, helem */ - 0x31dc, 0x32cc, 0x40a9, /* aslice, hslice */ - 0x32cd, /* kvaslice, kvhslice */ - 0x31dc, 0x3ff8, 0x2df4, 0x0003, /* delete */ - 0x45b8, 0x0003, /* exists */ - 0x31dc, 0x3858, 0x05b4, 0x0650, 0x32cc, 0x40a8, 0x4384, 0x2d41, /* rv2hv */ - 0x31dc, 0x30d8, 0x11f4, 0x1b50, 0x32cc, 0x4384, 0x0003, /* multideref */ - 0x31dc, 0x3858, 0x02f0, 0x2eec, 0x2709, /* split */ - 0x31dc, 0x2379, /* list */ - 0x1490, 0x2a2c, 0x3d88, 0x2b24, 0x37c1, /* sort */ - 0x2a2c, 0x0003, /* reverse */ - 0x05b4, 0x0003, /* grepwhile */ - 0x2f78, 0x0003, /* flip, flop */ - 0x31dc, 0x0003, /* cond_expr */ - 0x31dc, 0x1078, 0x03d6, 0x014c, 0x4688, 0x4384, 0x27e1, /* entersub */ - 0x3af8, 0x0003, /* leavesub, leavesublv, leavewrite, leaveeval */ + 0x32fc, 0x31f8, 0x03d6, 0x33ec, 0x0067, /* aelem, helem */ + 0x32fc, 0x33ec, 0x41c9, /* aslice, hslice */ + 0x33ed, /* kvaslice, kvhslice */ + 0x32fc, 0x4118, 0x2f14, 0x0003, /* delete */ + 0x46d8, 0x0003, /* exists */ + 0x32fc, 0x3978, 0x06d4, 0x0770, 0x33ec, 0x41c8, 0x44a4, 0x2e61, /* rv2hv */ + 0x32fc, 0x31f8, 0x1314, 0x1c70, 0x33ec, 0x44a4, 0x0003, /* multideref */ + 0x32fc, 0x3978, 0x0410, 0x300c, 0x2829, /* split */ + 0x32fc, 0x2499, /* list */ + 0x32fc, 0x43f8, 0x0214, 0x4850, 0x018f, /* emptyavhv */ + 0x15b0, 0x2b4c, 0x3ea8, 0x2c44, 0x38e1, /* sort */ + 0x2b4c, 0x0003, /* reverse */ + 0x06d4, 0x0003, /* grepwhile */ + 0x3098, 0x0003, /* flip, flop */ + 0x32fc, 0x0003, /* cond_expr */ + 0x32fc, 0x1198, 0x03d6, 0x014c, 0x47a8, 0x44a4, 0x2901, /* entersub */ + 0x3c18, 0x0003, /* leavesub, leavesublv, leavewrite, leaveeval */ 0x02aa, 0x0003, /* argelem */ 0x00bc, 0x018f, /* caller */ - 0x2555, /* nextstate, dbstate */ - 0x307c, 0x3af9, /* leave */ - 0x31dc, 0x3858, 0x10ec, 0x3e05, /* enteriter */ - 0x3e05, /* iter */ - 0x307c, 0x0067, /* leaveloop */ - 0x4a9c, 0x0003, /* last, next, redo, dump, goto */ - 0x3a3c, 0x3958, 0x2994, 0x28d0, 0x018f, /* open */ - 0x1ef0, 0x214c, 0x2008, 0x1dc4, 0x0003, /* ftrread, ftrwrite, ftrexec, fteread, ftewrite, fteexec */ - 0x1ef0, 0x214c, 0x2008, 0x0003, /* ftis, ftsize, ftmtime, ftatime, ftctime, ftrowned, fteowned, ftzero, ftsock, ftchr, ftblk, ftfile, ftdir, ftpipe, ftsuid, ftsgid, ftsvtx, ftlink, fttty, fttext, ftbinary */ - 0x4731, /* wait, getppid, time */ - 0x3b94, 0x0e90, 0x070c, 0x4808, 0x2464, 0x0003, /* entereval */ - 0x339c, 0x0018, 0x13a4, 0x12c1, /* coreargs */ - 0x32cc, 0x00c7, /* avhvswitch */ - 0x31dc, 0x01fb, /* padrange */ - 0x31dc, 0x42d8, 0x04f6, 0x2bac, 0x19a8, 0x0067, /* refassign */ - 0x31dc, 0x42d8, 0x04f6, 0x2bac, 0x19a8, 0x0003, /* lvref */ - 0x31dd, /* lvrefslice */ - 0x1cdc, 0x0003, /* pushdefer */ + 0x2675, /* nextstate, dbstate */ + 0x319c, 0x3c19, /* leave */ + 0x32fc, 0x3978, 0x120c, 0x3f25, /* enteriter */ + 0x3f25, /* iter */ + 0x319c, 0x0067, /* leaveloop */ + 0x4bbc, 0x0003, /* last, next, redo, dump, goto */ + 0x3b5c, 0x3a78, 0x2ab4, 0x29f0, 0x018f, /* open */ + 0x2010, 0x226c, 0x2128, 0x1ee4, 0x0003, /* ftrread, ftrwrite, ftrexec, fteread, ftewrite, fteexec */ + 0x2010, 0x226c, 0x2128, 0x0003, /* ftis, ftsize, ftmtime, ftatime, ftctime, ftrowned, fteowned, ftzero, ftsock, ftchr, ftblk, ftfile, ftdir, ftpipe, ftsuid, ftsgid, ftsvtx, ftlink, fttty, fttext, ftbinary */ + 0x4851, /* wait, getppid, time */ + 0x3cb4, 0x0fb0, 0x082c, 0x4928, 0x2584, 0x0003, /* entereval */ + 0x34bc, 0x0018, 0x14c4, 0x13e1, /* coreargs */ + 0x33ec, 0x00c7, /* avhvswitch */ + 0x32fc, 0x01fb, /* padrange */ + 0x32fc, 0x43f8, 0x04f6, 0x2ccc, 0x1ac8, 0x0067, /* refassign */ + 0x32fc, 0x43f8, 0x04f6, 0x2ccc, 0x1ac8, 0x0003, /* lvref */ + 0x32fd, /* lvrefslice */ + 0x1dfc, 0x0003, /* pushdefer */ }; @@ -3218,6 +3227,7 @@ EXTCONST U8 PL_op_private_valid[] = { /* LSLICE */ (OPpARG2_MASK), /* ANONLIST */ (OPpARG4_MASK), /* ANONHASH */ (OPpARG4_MASK), + /* EMPTYAVHV */ (OPpARG4_MASK|OPpTARGET_MY|OPpEMPTYAVHV_IS_HV|OPpPAD_STATE|OPpLVAL_INTRO), /* SPLICE */ (OPpARG4_MASK), /* PUSH */ (OPpARG4_MASK|OPpTARGET_MY), /* POP */ (OPpARG1_MASK), diff --git a/opnames.h b/opnames.h index 3e1751006d4a..b86f00b7f2da 100644 --- a/opnames.h +++ b/opnames.h @@ -178,263 +178,264 @@ typedef enum opcode { 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_EMPTYAVHV = 164, + OP_SPLICE = 165, + OP_PUSH = 166, + OP_POP = 167, + OP_SHIFT = 168, + OP_UNSHIFT = 169, + OP_SORT = 170, + OP_REVERSE = 171, + OP_GREPSTART = 172, + OP_GREPWHILE = 173, + OP_MAPSTART = 174, + OP_MAPWHILE = 175, + OP_RANGE = 176, + OP_FLIP = 177, + OP_FLOP = 178, + OP_AND = 179, + OP_OR = 180, + OP_XOR = 181, + OP_DOR = 182, + OP_COND_EXPR = 183, + OP_ANDASSIGN = 184, + OP_ORASSIGN = 185, + OP_DORASSIGN = 186, + OP_ENTERSUB = 187, + OP_LEAVESUB = 188, + OP_LEAVESUBLV = 189, + OP_ARGCHECK = 190, + OP_ARGELEM = 191, + OP_ARGDEFELEM = 192, + OP_CALLER = 193, + OP_WARN = 194, + OP_DIE = 195, + OP_RESET = 196, + OP_LINESEQ = 197, + OP_NEXTSTATE = 198, + OP_DBSTATE = 199, + OP_UNSTACK = 200, + OP_ENTER = 201, + OP_LEAVE = 202, + OP_SCOPE = 203, + OP_ENTERITER = 204, + OP_ITER = 205, + OP_ENTERLOOP = 206, + OP_LEAVELOOP = 207, + OP_RETURN = 208, + OP_LAST = 209, + OP_NEXT = 210, + OP_REDO = 211, + OP_DUMP = 212, + OP_GOTO = 213, + OP_EXIT = 214, + OP_METHOD = 215, + OP_METHOD_NAMED = 216, + OP_METHOD_SUPER = 217, + OP_METHOD_REDIR = 218, + OP_METHOD_REDIR_SUPER = 219, + OP_ENTERGIVEN = 220, + OP_LEAVEGIVEN = 221, + OP_ENTERWHEN = 222, + OP_LEAVEWHEN = 223, + OP_BREAK = 224, + OP_CONTINUE = 225, + OP_OPEN = 226, + OP_CLOSE = 227, + OP_PIPE_OP = 228, + OP_FILENO = 229, + OP_UMASK = 230, + OP_BINMODE = 231, + OP_TIE = 232, + OP_UNTIE = 233, + OP_TIED = 234, + OP_DBMOPEN = 235, + OP_DBMCLOSE = 236, + OP_SSELECT = 237, + OP_SELECT = 238, + OP_GETC = 239, + OP_READ = 240, + OP_ENTERWRITE = 241, + OP_LEAVEWRITE = 242, + OP_PRTF = 243, + OP_PRINT = 244, + OP_SAY = 245, + OP_SYSOPEN = 246, + OP_SYSSEEK = 247, + OP_SYSREAD = 248, + OP_SYSWRITE = 249, + OP_EOF = 250, + OP_TELL = 251, + OP_SEEK = 252, + OP_TRUNCATE = 253, + OP_FCNTL = 254, + OP_IOCTL = 255, + OP_FLOCK = 256, + OP_SEND = 257, + OP_RECV = 258, + OP_SOCKET = 259, + OP_SOCKPAIR = 260, + OP_BIND = 261, + OP_CONNECT = 262, + OP_LISTEN = 263, + OP_ACCEPT = 264, + OP_SHUTDOWN = 265, + OP_GSOCKOPT = 266, + OP_SSOCKOPT = 267, + OP_GETSOCKNAME = 268, + OP_GETPEERNAME = 269, + OP_LSTAT = 270, + OP_STAT = 271, + OP_FTRREAD = 272, + OP_FTRWRITE = 273, + OP_FTREXEC = 274, + OP_FTEREAD = 275, + OP_FTEWRITE = 276, + OP_FTEEXEC = 277, + OP_FTIS = 278, + OP_FTSIZE = 279, + OP_FTMTIME = 280, + OP_FTATIME = 281, + OP_FTCTIME = 282, + OP_FTROWNED = 283, + OP_FTEOWNED = 284, + OP_FTZERO = 285, + OP_FTSOCK = 286, + OP_FTCHR = 287, + OP_FTBLK = 288, + OP_FTFILE = 289, + OP_FTDIR = 290, + OP_FTPIPE = 291, + OP_FTSUID = 292, + OP_FTSGID = 293, + OP_FTSVTX = 294, + OP_FTLINK = 295, + OP_FTTTY = 296, + OP_FTTEXT = 297, + OP_FTBINARY = 298, + OP_CHDIR = 299, + OP_CHOWN = 300, + OP_CHROOT = 301, + OP_UNLINK = 302, + OP_CHMOD = 303, + OP_UTIME = 304, + OP_RENAME = 305, + OP_LINK = 306, + OP_SYMLINK = 307, + OP_READLINK = 308, + OP_MKDIR = 309, + OP_RMDIR = 310, + OP_OPEN_DIR = 311, + OP_READDIR = 312, + OP_TELLDIR = 313, + OP_SEEKDIR = 314, + OP_REWINDDIR = 315, + OP_CLOSEDIR = 316, + OP_FORK = 317, + OP_WAIT = 318, + OP_WAITPID = 319, + OP_SYSTEM = 320, + OP_EXEC = 321, + OP_KILL = 322, + OP_GETPPID = 323, + OP_GETPGRP = 324, + OP_SETPGRP = 325, + OP_GETPRIORITY = 326, + OP_SETPRIORITY = 327, + OP_TIME = 328, + OP_TMS = 329, + OP_LOCALTIME = 330, + OP_GMTIME = 331, + OP_ALARM = 332, + OP_SLEEP = 333, + OP_SHMGET = 334, + OP_SHMCTL = 335, + OP_SHMREAD = 336, + OP_SHMWRITE = 337, + OP_MSGGET = 338, + OP_MSGCTL = 339, + OP_MSGSND = 340, + OP_MSGRCV = 341, + OP_SEMOP = 342, + OP_SEMGET = 343, + OP_SEMCTL = 344, + OP_REQUIRE = 345, + OP_DOFILE = 346, + OP_HINTSEVAL = 347, + OP_ENTEREVAL = 348, + OP_LEAVEEVAL = 349, + OP_ENTERTRY = 350, + OP_LEAVETRY = 351, + OP_GHBYNAME = 352, + OP_GHBYADDR = 353, + OP_GHOSTENT = 354, + OP_GNBYNAME = 355, + OP_GNBYADDR = 356, + OP_GNETENT = 357, + OP_GPBYNAME = 358, + OP_GPBYNUMBER = 359, + OP_GPROTOENT = 360, + OP_GSBYNAME = 361, + OP_GSBYPORT = 362, + OP_GSERVENT = 363, + OP_SHOSTENT = 364, + OP_SNETENT = 365, + OP_SPROTOENT = 366, + OP_SSERVENT = 367, + OP_EHOSTENT = 368, + OP_ENETENT = 369, + OP_EPROTOENT = 370, + OP_ESERVENT = 371, + OP_GPWNAM = 372, + OP_GPWUID = 373, + OP_GPWENT = 374, + OP_SPWENT = 375, + OP_EPWENT = 376, + OP_GGRNAM = 377, + OP_GGRGID = 378, + OP_GGRENT = 379, + OP_SGRENT = 380, + OP_EGRENT = 381, + OP_GETLOGIN = 382, + OP_SYSCALL = 383, + OP_LOCK = 384, + OP_ONCE = 385, + OP_CUSTOM = 386, + OP_COREARGS = 387, + OP_AVHVSWITCH = 388, + OP_RUNCV = 389, + OP_FC = 390, + OP_PADCV = 391, + OP_INTROCV = 392, + OP_CLONECV = 393, + OP_PADRANGE = 394, + OP_REFASSIGN = 395, + OP_LVREF = 396, + OP_LVREFSLICE = 397, + OP_LVAVREF = 398, + OP_ANONCONST = 399, + OP_ISA = 400, + OP_CMPCHAIN_AND = 401, + OP_CMPCHAIN_DUP = 402, + OP_ENTERTRYCATCH = 403, + OP_LEAVETRYCATCH = 404, + OP_POPTRY = 405, + OP_CATCH = 406, + OP_PUSHDEFER = 407, + OP_IS_BOOL = 408, + OP_IS_WEAK = 409, + OP_WEAKEN = 410, + OP_UNWEAKEN = 411, + OP_BLESSED = 412, + OP_REFADDR = 413, + OP_REFTYPE = 414, + OP_CEIL = 415, + OP_FLOOR = 416, + OP_IS_TAINTED = 417, OP_max } opcode; -#define MAXO 417 +#define MAXO 418 #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 1319745b9acd..0e3a81f019fd 100644 --- a/peep.c +++ b/peep.c @@ -3147,6 +3147,62 @@ Perl_rpeep(pTHX_ OP *o) } } + /* If the pushmark is associated with an empty anonhash + * or anonlist, null out the pushmark and swap in a + * specialised op for the parent. + * 4 <@> anonhash sK* ->5 + * 3 <0> pushmark s ->4 + * becomes: + * 3 <@> emptyavhv sK* ->4 + * - <0> pushmark s ->3 + */ + if (!OpHAS_SIBLING(o) && (o->op_next == o->op_sibparent) && ( + (o->op_next->op_type == OP_ANONHASH) || + (o->op_next->op_type == OP_ANONLIST) ) && + (o->op_next->op_flags & OPf_SPECIAL) ) { + + OP* anon = o->op_next; + /* These next two are _potentially_ a padsv and an sassign */ + OP* padsv = anon->op_next; + OP* sassign = (padsv) ? padsv->op_next: NULL; + + anon->op_private = (anon->op_type == OP_ANONLIST) ? + 0 : OPpEMPTYAVHV_IS_HV; + OpTYPE_set(anon, OP_EMPTYAVHV); + op_null(o); + o = anon; + if (oldop) /* A previous optimization may have NULLED it */ + oldop->op_next = anon; + + /* Further optimise scalar assignment of an empty anonhash + * or anonlist by subsuming the padsv & sassign OPs. */ + if ((padsv->op_type == OP_PADSV) && + !(padsv->op_private & OPpDEREF) && + sassign && (sassign->op_type == OP_SASSIGN) ){ + + /* Take some public flags from the sassign */ + anon->op_flags = OPf_KIDS | OPf_SPECIAL | + (anon->op_flags & OPf_PARENS) | + (sassign->op_flags & (OPf_WANT|OPf_PARENS)); + + /* Take some private flags from the padsv */ + anon->op_private |= OPpTARGET_MY | + (padsv->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)); + + /* Take the targ slot from the padsv*/ + anon->op_targ = padsv->op_targ; + padsv->op_targ = 0; + + /* Clean up */ + anon->op_next = sassign->op_next; + op_null(padsv); + op_null(sassign); + } + break; + + } + + /* Convert a series of PAD ops for my vars plus support into a * single padrange op. Basically * diff --git a/pp.c b/pp.c index f06f282de6d8..5b4c1efe64b4 100644 --- a/pp.c +++ b/pp.c @@ -5572,6 +5572,51 @@ PP(pp_anonlist) RETURN; } +/* When an anonlist or anonhash will (1) be empty and (2) return an RV + * pointing to the new AV/HV, the peephole optimizer can swap in this + * simpler function and op_null the originally associated PUSHMARK. */ +PP(pp_emptyavhv) +{ + dSP; + OP * const op = PL_op; + SV * rv; + SV * const sv = MUTABLE_SV( newSV_type( + (op->op_private & OPpEMPTYAVHV_IS_HV) ? + SVt_PVHV : + SVt_PVAV ) ); + + /* Is it an assignment, just a stack push, or both?*/ + if (op->op_private & OPpTARGET_MY) { + SV** const padentry = &PAD_SVl(op->op_targ); + rv = *padentry; + /* Since the op_targ is very likely to be an undef SVt_IV from + * a previous iteration, converting it to a live RV can + * typically be special-cased.*/ + if (SvTYPE(rv) == SVt_IV && !SvOK(rv)) { + SvFLAGS(rv) = (SVt_IV | SVf_ROK); + SvRV_set(rv, sv); + } else { + sv_setrv_noinc_mg(rv, sv); + } + if ((op->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)) == OPpLVAL_INTRO) { + save_clearsv(padentry); + } + if (GIMME_V == G_VOID) { + RETURN; /* skip extending and pushing */ + } + } else { + /* Inlined newRV_noinc */ + SV * refsv = newSV_type_mortal(SVt_IV); + SvRV_set(refsv, sv); + SvROK_on(refsv); + + rv = refsv; + } + + XPUSHs(rv); + RETURN; +} + PP(pp_anonhash) { dSP; dMARK; dORIGMARK; diff --git a/pp_proto.h b/pp_proto.h index 759545152add..7963abb8853e 100644 --- a/pp_proto.h +++ b/pp_proto.h @@ -63,6 +63,7 @@ PERL_CALLCONV OP *Perl_pp_die(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_divide(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_each(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_ehostent(pTHX) __attribute__visibility__("hidden"); +PERL_CALLCONV OP *Perl_pp_emptyavhv(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_enter(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_entereval(pTHX) __attribute__visibility__("hidden"); PERL_CALLCONV OP *Perl_pp_entergiven(pTHX) __attribute__visibility__("hidden"); diff --git a/regen/op_private b/regen/op_private index 4f2afe217430..7150f20cc846 100644 --- a/regen/op_private +++ b/regen/op_private @@ -318,7 +318,7 @@ addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) for qw(gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice split hslice delete padsv padav padhv enteriter entersub padrange pushmark cond_expr refassign lvref lvrefslice lvavref multideref - multiconcat padsv_store undef), + multiconcat padsv_store undef emptyavhv), 'list', # this gets set in my_attrs() for some reason ; @@ -500,7 +500,7 @@ addbits($_, 7 => qw(OPpPV_IS_UTF8 UTF)) for qw(last redo next goto dump); addbits($_, 6 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv lvavref lvref refassign pushmark - padsv_store undef); + padsv_store undef emptyavhv); # NB: both sassign and aassign use the 'OPpASSIGN' naming convention # for their private flags @@ -860,6 +860,13 @@ addbits('undef', 5 => qw(OPpUNDEF_KEEP_PV KEEP_PV), ); +addbits('emptyavhv', + # 7 OPpLVAL_INTRO + # 6 OPpPAD_STATE + 5 => qw(OPpEMPTYAVHV_IS_HV ANONHASH), + # 4 OPpTARGET_MY +); + 1; # ex: set ts=8 sts=4 sw=4 et: diff --git a/regen/opcodes b/regen/opcodes index f6b68ec61b63..c48c337076c2 100644 --- a/regen/opcodes +++ b/regen/opcodes @@ -261,6 +261,7 @@ list list ck_null m@ L lslice list slice ck_null 2 H L L anonlist anonymous array ([]) ck_fun ms@ L anonhash anonymous hash ({}) ck_fun ms@ L +emptyavhv empty anon hash/array ck_fun sT@ L splice splice ck_fun m@ A S? S? L push push ck_fun imsT@ A L diff --git a/t/perf/benchmarks b/t/perf/benchmarks index 7b457abff3f8..92f946bbce9e 100644 --- a/t/perf/benchmarks +++ b/t/perf/benchmarks @@ -1367,6 +1367,31 @@ code => 'undef my $x', }, + 'expr::sassign::anonlist' => { + setup => '', + code => '$x = []' + }, + 'expr::sassign::anonlist_lex' => { + setup => 'my $x', + code => '$x = []' + }, + 'expr::sassign::my_anonlist_lex' => { + setup => '', + code => 'my $x = []' + }, + 'expr::sassign::anonhash' => { + setup => '', + code => '$x = {}' + }, + 'expr::sassign::anonhash_lex' => { + setup => 'my $x', + code => '$x = {}' + }, + 'expr::sassign::my_anonhash_lex' => { + setup => '', + code => 'my $x = {}' + }, + 'expr::sassign::my_conststr' => { setup => '', code => 'my $x = "abc"', @@ -1418,6 +1443,10 @@ code => '$x[0][1] = 1', }, + 'expr::sassign::bless_lex' => { + setup => 'my $x', + code => '$x = bless {}, "X"' + }, 'func::grep::bool0' => { desc => 'grep returning 0 items in boolean context', diff --git a/t/perf/opcount.t b/t/perf/opcount.t index cca8dec39778..4651f2442e16 100644 --- a/t/perf/opcount.t +++ b/t/perf/opcount.t @@ -868,9 +868,10 @@ test_opcount(0, 'my $h= {}; my @k= keys %{($h=undef)||{}};', { undef => 1, aassign => 1, + emptyavhv => 2, padav => 1, padsv => 0, - padsv_store => 1, + padsv_store => 0, sassign => 0, }); @@ -918,4 +919,97 @@ test_opcount(0, "no aelemfast_lex + sassign replacement with multideref", sassign => 1, }); +# emptyavhv optimizations + +test_opcount(0, "Empty anonlist", + sub { [] }, + { + anonlist => 0, + emptyavhv => 1, + sassign => 0, + }); +test_opcount(0, "Empty anonlist with global assignment", + sub { our $x; $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + gvsv => 1, + pushmark => 0, + sassign => 1, + }); +test_opcount(0, "Empty anonlist and lexical assignment", + sub { my $x; $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 1, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonlist and direct lexical assignment", + sub { my $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 0, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonlist ref and direct lexical assignment", + sub { my $x = \[] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 0, + padsv_store => 1, + pushmark => 0, + sassign => 0, + srefgen => 1, + }); +test_opcount(0, "Empty anonhash", + sub { {} }, + { + anonhash => 0, + emptyavhv => 1, + sassign => 0, + }); +test_opcount(0, "Empty anonhash with global assignment", + sub { our $x; $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + gvsv => 1, + pushmark => 0, + sassign => 1, + }); +test_opcount(0, "Empty anonhash and lexical assignment", + sub { my $x; $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 1, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonhash and direct lexical assignment", + sub { my $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 0, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonhash ref and direct lexical assignment", + sub { my $x = \{} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 0, + padsv_store => 1, + pushmark => 0, + sassign => 0, + srefgen => 1, + }); + done_testing(); From b1b67a39e021036acdc0a6470d5291ba2a3cc386 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Sun, 23 Oct 2022 21:43:14 +0000 Subject: [PATCH 2/2] version bump to squash --- ext/Opcode/Opcode.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm index f8615eef0f3c..9f28f900bfde 100644 --- a/ext/Opcode/Opcode.pm +++ b/ext/Opcode/Opcode.pm @@ -1,4 +1,4 @@ -package Opcode 1.61; +package Opcode 1.62; use strict;