diff options
Diffstat (limited to 'ext/B')
-rw-r--r-- | ext/B/B.xs | 100 | ||||
-rw-r--r-- | ext/B/B/Concise.pm | 2 | ||||
-rw-r--r-- | ext/B/t/OptreeCheck.pm | 4 | ||||
-rw-r--r-- | ext/B/t/concise-xs.t | 30 | ||||
-rw-r--r-- | ext/B/t/f_sort.t | 52 |
5 files changed, 151 insertions, 37 deletions
diff --git a/ext/B/B.xs b/ext/B/B.xs index 937ef2c43f..14bd7163b7 100644 --- a/ext/B/B.xs +++ b/ext/B/B.xs @@ -8,6 +8,7 @@ */ #define PERL_NO_GET_CONTEXT +#define PERL_EXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" @@ -1342,6 +1343,9 @@ string(o, cv) SV *ret; PPCODE: switch (o->op_type) { + case OP_MULTIDEREF: + ret = unop_aux_stringify(o, cv); + break; default: ret = sv_2mortal(newSVpvn("", 0)); } @@ -1359,9 +1363,105 @@ aux_list(o, cv) B::OP o B::CV cv PPCODE: + PERL_UNUSED_VAR(cv); /* not needed on unthreaded builds */ switch (o->op_type) { default: XSRETURN(0); /* by default, an empty list */ + + case OP_MULTIDEREF: +#ifdef USE_ITHREADS +# define ITEM_SV(item) *av_fetch(comppad, (item)->pad_offset, FALSE); +#else +# define ITEM_SV(item) UNOP_AUX_item_sv(item) +#endif + { + UNOP_AUX_item *items = cUNOP_AUXo->op_aux; + UV actions = items->uv; + UV len = items[-1].uv; + SV *sv; + bool last = 0; + bool is_hash = FALSE; +#ifdef USE_ITHREADS + PADLIST * const padlist = CvPADLIST(cv); + PAD *comppad = comppad = PadlistARRAY(padlist)[1]; +#endif + + EXTEND(SP, len); + PUSHs(sv_2mortal(newSViv(actions))); + + while (!last) { + switch (actions & MDEREF_ACTION_MASK) { + + case MDEREF_reload: + actions = (++items)->uv; + PUSHs(sv_2mortal(newSVuv(actions))); + continue; + + case MDEREF_HV_padhv_helem: + is_hash = TRUE; + case MDEREF_AV_padav_aelem: + PUSHs(sv_2mortal(newSVuv((++items)->pad_offset))); + goto do_elem; + + case MDEREF_HV_gvhv_helem: + is_hash = TRUE; + case MDEREF_AV_gvav_aelem: + sv = ITEM_SV(++items); + PUSHs(make_sv_object(aTHX_ sv)); + goto do_elem; + + case MDEREF_HV_gvsv_vivify_rv2hv_helem: + is_hash = TRUE; + case MDEREF_AV_gvsv_vivify_rv2av_aelem: + sv = ITEM_SV(++items); + PUSHs(make_sv_object(aTHX_ sv)); + goto do_vivify_rv2xv_elem; + + case MDEREF_HV_padsv_vivify_rv2hv_helem: + is_hash = TRUE; + case MDEREF_AV_padsv_vivify_rv2av_aelem: + PUSHs(sv_2mortal(newSVuv((++items)->pad_offset))); + goto do_vivify_rv2xv_elem; + + case MDEREF_HV_pop_rv2hv_helem: + case MDEREF_HV_vivify_rv2hv_helem: + is_hash = TRUE; + do_vivify_rv2xv_elem: + case MDEREF_AV_pop_rv2av_aelem: + case MDEREF_AV_vivify_rv2av_aelem: + do_elem: + switch (actions & MDEREF_INDEX_MASK) { + case MDEREF_INDEX_none: + last = 1; + break; + case MDEREF_INDEX_const: + if (is_hash) { + sv = ITEM_SV(++items); + PUSHs(make_sv_object(aTHX_ sv)); + } + else + PUSHs(sv_2mortal(newSViv((++items)->iv))); + break; + case MDEREF_INDEX_padsv: + PUSHs(sv_2mortal(newSVuv((++items)->pad_offset))); + break; + case MDEREF_INDEX_gvsv: + sv = ITEM_SV(++items); + PUSHs(make_sv_object(aTHX_ sv)); + break; + } + if (actions & MDEREF_FLAG_last) + last = 1; + is_hash = FALSE; + + break; + } /* switch */ + + actions >>= MDEREF_SHIFT; + } /* while */ + XSRETURN(len); + + } /* OP_MULTIDEREF */ } /* switch */ diff --git a/ext/B/B/Concise.pm b/ext/B/B/Concise.pm index 381181e6d2..311e0e738a 100644 --- a/ext/B/B/Concise.pm +++ b/ext/B/B/Concise.pm @@ -916,7 +916,7 @@ sub concise_op { } } elsif ($h{class} eq "UNOP_AUX") { - $h{arg} = "(" . $op->string . ")"; + $h{arg} = "(" . $op->string($curcv) . ")"; } $h{seq} = $h{hyphseq} = seq($op); diff --git a/ext/B/t/OptreeCheck.pm b/ext/B/t/OptreeCheck.pm index 0537a8d7a8..eac73baa73 100644 --- a/ext/B/t/OptreeCheck.pm +++ b/ext/B/t/OptreeCheck.pm @@ -5,7 +5,7 @@ use warnings; use vars qw($TODO $Level $using_open); require "test.pl"; -our $VERSION = '0.11'; +our $VERSION = '0.12'; # now export checkOptree, and those test.pl functions used by tests our @EXPORT = qw( checkOptree plan skip skip_all pass is like unlike @@ -669,6 +669,8 @@ sub mkCheckRex { $tc->{wantstr} = $str; + # make UNOP_AUX flag type literal + $str =~ s/<\+>/<\\+>/; # make targ args wild $str =~ s/\[t\d+\]/[t\\d+]/msg; diff --git a/ext/B/t/concise-xs.t b/ext/B/t/concise-xs.t index 365951d0bc..289f909cc9 100644 --- a/ext/B/t/concise-xs.t +++ b/ext/B/t/concise-xs.t @@ -159,6 +159,7 @@ my $testpkgs = { constant => [qw/ ASSIGN CVf_LVALUE CVf_METHOD LIST_CONTEXT OP_CONST OP_LIST OP_RV2SV OP_AELEM OP_CUSTOM OP_NEXTSTATE OP_DBSTATE + OP_HELEM OP_RV2AV OP_RV2HV OP_STRINGIFY OPf_KIDS OPf_MOD OPf_REF OPf_SPECIAL OPf_PARENS OPf_STACKED OPf_WANT OPf_WANT_LIST OPf_WANT_SCALAR @@ -169,6 +170,8 @@ my $testpkgs = { OPpSORT_REVERSE OPpREVERSE_INPLACE OPpTARGET_MY OPpTRANS_COMPLEMENT OPpTRANS_DELETE OPpTRANS_SQUASH OPpREPEAT_DOLIST + OPpMULTIDEREF_EXISTS + OPpMULTIDEREF_DELETE PMf_CONTINUE PMf_EVAL PMf_EXTENDED PMf_EXTENDED_MORE PMf_FOLD PMf_GLOBAL PMf_KEEP PMf_NONDESTRUCT @@ -176,7 +179,32 @@ my $testpkgs = { POSTFIX SVf_FAKE SVf_IOK SVf_NOK SVf_POK SVf_ROK SVpad_STATE SVpad_OUR SVs_RMG SVs_SMG SWAP_CHILDREN OPpPAD_STATE - OPpCONST_ARYBASE RXf_SKIPWHITE SVpad_TYPED/, + OPpCONST_ARYBASE RXf_SKIPWHITE SVpad_TYPED + + MDEREF_reload + MDEREF_AV_pop_rv2av_aelem + MDEREF_AV_gvsv_vivify_rv2av_aelem + MDEREF_AV_padsv_vivify_rv2av_aelem + MDEREF_AV_vivify_rv2av_aelem + MDEREF_AV_padav_aelem + MDEREF_AV_gvav_aelem + MDEREF_HV_pop_rv2hv_helem + MDEREF_HV_gvsv_vivify_rv2hv_helem + MDEREF_HV_padsv_vivify_rv2hv_helem + MDEREF_HV_vivify_rv2hv_helem + MDEREF_HV_padhv_helem + MDEREF_HV_gvhv_helem + MDEREF_ACTION_MASK + MDEREF_INDEX_none + MDEREF_INDEX_const + MDEREF_INDEX_padsv + MDEREF_INDEX_gvsv + MDEREF_INDEX_MASK + MDEREF_FLAG_last + MDEREF_MASK + MDEREF_SHIFT + /, + $] >= 5.015 ? qw( OP_GLOB PMf_SKIPWHITE RXf_PMf_CHARSET RXf_PMf_KEEPCOPY OPpEVAL_BYTES OPpSUBSTR_REPL_FIRST) : (), diff --git a/ext/B/t/f_sort.t b/ext/B/t/f_sort.t index 7205a94e44..55811eda93 100644 --- a/ext/B/t/f_sort.t +++ b/ext/B/t/f_sort.t @@ -510,10 +510,8 @@ checkOptree(name => q{Compound sort/map Expression }, # 5 <0> pushmark s # 6 <#> gv[*old] s # 7 <1> rv2av[t19] lKM/1 -# 8 <@> mapstart lK* < 5.017002 -# 8 <@> mapstart lK >=5.017002 -# 9 <|> mapwhile(other->a)[t20] lK < 5.019002 -# 9 <|> mapwhile(other->a)[t20] lKM >=5.019002 +# 8 <@> mapstart lK +# 9 <|> mapwhile(other->a)[t20] lKM # a <0> enter l # b <;> nextstate(main 608 (eval 34):2) v:{ # c <0> pushmark s @@ -525,21 +523,15 @@ checkOptree(name => q{Compound sort/map Expression }, # i <@> leave lKP # goto 9 # j <@> sort lKMS* -# k <@> mapstart lK* < 5.017002 -# k <@> mapstart lK >=5.017002 +# k <@> mapstart lK # l <|> mapwhile(other->m)[t26] lK -# m <#> gv[*_] s -# n <1> rv2sv sKM/DREFAV,1 -# o <1> rv2av[t4] sKR/1 -# p <$> const[IV 0] s -# q <2> aelem sK/2 -# - <@> scope lK < 5.017002 +# m <+> multideref($_->[0]) sK # goto l -# r <0> pushmark s -# s <#> gv[*new] s -# t <1> rv2av[t2] lKRM*/1 -# u <2> aassign[t27] KS/COMMON -# v <1> leavesub[1 ref] K/REFC,1 +# n <0> pushmark s +# o <#> gv[*new] s +# p <1> rv2av[t2] lKRM*/1 +# q <2> aassign[t22] KS/COMMON +# r <1> leavesub[1 ref] K/REFC,1 EOT_EOT # 1 <;> nextstate(main 609 (eval 34):3) v:{ # 2 <0> pushmark s @@ -548,10 +540,8 @@ EOT_EOT # 5 <0> pushmark s # 6 <$> gv(*old) s # 7 <1> rv2av[t10] lKM/1 -# 8 <@> mapstart lK* < 5.017002 -# 8 <@> mapstart lK >=5.017002 -# 9 <|> mapwhile(other->a)[t11] lK < 5.019002 -# 9 <|> mapwhile(other->a)[t11] lKM >=5.019002 +# 8 <@> mapstart lK +# 9 <|> mapwhile(other->a)[t11] lKM # a <0> enter l # b <;> nextstate(main 608 (eval 34):2) v:{ # c <0> pushmark s @@ -563,21 +553,15 @@ EOT_EOT # i <@> leave lKP # goto 9 # j <@> sort lKMS* -# k <@> mapstart lK* < 5.017002 -# k <@> mapstart lK >=5.017002 +# k <@> mapstart lK # l <|> mapwhile(other->m)[t12] lK -# m <$> gv(*_) s -# n <1> rv2sv sKM/DREFAV,1 -# o <1> rv2av[t2] sKR/1 -# p <$> const(IV 0) s -# q <2> aelem sK/2 -# - <@> scope lK < 5.017002 +# m <+> multideref($_->[0]) sK # goto l -# r <0> pushmark s -# s <$> gv(*new) s -# t <1> rv2av[t1] lKRM*/1 -# u <2> aassign[t13] KS/COMMON -# v <1> leavesub[1 ref] K/REFC,1 +# n <0> pushmark s +# o <$> gv(*new) s +# p <1> rv2av[t1] lKRM*/1 +# q <2> aassign[t13] KS/COMMON +# r <1> leavesub[1 ref] K/REFC,1 EONT_EONT |