summaryrefslogtreecommitdiff
path: root/ext/B
diff options
context:
space:
mode:
Diffstat (limited to 'ext/B')
-rw-r--r--ext/B/B.xs100
-rw-r--r--ext/B/B/Concise.pm2
-rw-r--r--ext/B/t/OptreeCheck.pm4
-rw-r--r--ext/B/t/concise-xs.t30
-rw-r--r--ext/B/t/f_sort.t52
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