#endif /* A_WORKAROUND_REQUIRE_PROPAGATION */
-#if !A_HAS_RPEEP
-
#define PTABLE_NAME ptable_seen
#define PTABLE_VAL_FREE(V) NOOP
#define ptable_seen_clear(T) ptable_seen_clear(aPTBLMS_ (T))
#define ptable_seen_free(T) ptable_seen_free(aPTBLMS_ (T))
-#endif /* !A_HAS_RPEEP */
-
-#define A_NEED_CXT ((A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION) || !A_HAS_RPEEP)
-
-#if A_NEED_CXT
-
#define MY_CXT_KEY __PACKAGE__ "::_guts" XS_VERSION
typedef struct {
ptable *tbl; /* It really is a ptable_hints */
tTHX owner;
#endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */
-#if !A_HAS_RPEEP
ptable *seen; /* It really is a ptable_seen */
-#endif /* !A_HAS_RPEEP */
} my_cxt_t;
START_MY_CXT
#if A_WORKAROUND_REQUIRE_PROPAGATION
ptable_hints_free(MY_CXT.tbl);
#endif /* A_WORKAROUND_REQUIRE_PROPAGATION */
-#if !A_HAS_RPEEP
ptable_seen_free(MY_CXT.seen);
-#endif /* !A_HAS_RPEEP */
}
#endif /* A_THREADSAFE */
-#endif /* A_NEED_CXT */
-
#if A_WORKAROUND_REQUIRE_PROPAGATION
STATIC IV a_require_tag(pTHX) {
STATIC peep_t a_old_peep = 0; /* This is actually the rpeep past 5.13.5 */
-#if !A_HAS_RPEEP
-# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen)
-#else /* !A_HAS_RPEEP */
-# define A_PEEP_REC_PROTO STATIC void a_peep_rec(pTHX_ OP *o)
-#endif /* A_HAS_RPEEP */
-
-A_PEEP_REC_PROTO;
-A_PEEP_REC_PROTO {
-#if !A_HAS_RPEEP
-# define a_peep_rec(O) a_peep_rec(aTHX_ (O), seen)
-#else /* !A_HAS_RPEEP */
-# define a_peep_rec(O) a_peep_rec(aTHX_ (O))
-#endif /* A_HAS_RPEEP */
- dA_MAP_THX;
-
-#if !A_HAS_RPEEP
- if (ptable_fetch(seen, o))
- return;
-#endif
+STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen);
+STATIC void a_peep_rec(pTHX_ OP *o, ptable *seen) {
+#define a_peep_rec(O) a_peep_rec(aTHX_ (O), seen)
for (; o; o = o->op_next) {
+ dA_MAP_THX;
const a_op_info *oi = NULL;
UV flags = 0;
-#if !A_HAS_RPEEP
+ if (ptable_fetch(seen, o))
+ break;
ptable_seen_store(seen, o, o);
-#endif
+
switch (o->op_type) {
case OP_PADSV:
if (o->op_ppaddr != a_pp_deref) {
}
STATIC void a_peep(pTHX_ OP *o) {
-#if !A_HAS_RPEEP
dMY_CXT;
ptable *seen = MY_CXT.seen;
- ptable_seen_clear(seen);
-#endif /* !A_HAS_RPEEP */
-
a_old_peep(aTHX_ o);
+
+ ptable_seen_clear(seen);
a_peep_rec(o);
+ ptable_seen_clear(seen);
}
/* --- Interpreter setup/teardown ------------------------------------------ */
return;
#endif
-#if A_NEED_CXT
{
dMY_CXT;
# if A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION
ptable_hints_free(MY_CXT.tbl);
# endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */
-# if !A_HAS_RPEEP
ptable_seen_free(MY_CXT.seen);
-# endif /* !A_HAS_RPEEP */
}
-#endif /* A_NEED_CXT */
PL_check[OP_PADANY] = MEMBER_TO_FPTR(a_old_ck_padany);
a_old_ck_padany = 0;
if (a_initialized)
return;
-#if A_NEED_CXT
{
MY_CXT_INIT;
# if A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION
MY_CXT.tbl = ptable_new();
MY_CXT.owner = aTHX;
# endif /* A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION */
-# if !A_HAS_RPEEP
MY_CXT.seen = ptable_new();
-# endif /* !A_RPEEP */
}
-#endif /* A_NEED_CXT */
a_old_ck_padany = PL_check[OP_PADANY];
PL_check[OP_PADANY] = MEMBER_TO_FPTR(a_ck_padany);
a_setup();
}
-#if A_THREADSAFE && (A_WORKAROUND_REQUIRE_PROPAGATION || !A_HAS_RPEEP)
+#if A_THREADSAFE
void
CLONE(...)
#if A_WORKAROUND_REQUIRE_PROPAGATION
ptable *t;
#endif
-#if !A_HAS_RPEEP
ptable *s;
-#endif
PPCODE:
{
dMY_CXT;
a_ptable_clone_ud_deinit(ud);
}
#endif
-#if !A_HAS_RPEEP
s = ptable_new();
-#endif
}
{
MY_CXT_CLONE;
MY_CXT.tbl = t;
MY_CXT.owner = aTHX;
#endif
-#if !A_HAS_RPEEP
MY_CXT.seen = s;
-#endif
}
reap(3, a_thread_cleanup, NULL);
XSRETURN(0);
-#endif
+#endif /* A_THREADSAFE */
SV *
_tag(SV *hint)
--- /dev/null
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 11 + 6 * 3;
+
+{
+ my $desc = 'peephole optimization of conditionals';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ if ($_[0]) {
+ my $z = $x->{a};
+ return 1;
+ } elsif ($_[1] || $_[2]) {
+ my $z = $x->{b};
+ return 2;
+ } elsif ($_[3] && $_[4]) {
+ my $z = $x->{c};
+ return 3;
+ } elsif ($_[5] ? $_[6] : 0) {
+ my $z = $x->{d};
+ return 4;
+ } else {
+ my $z = $x->{e};
+ return 5;
+ }
+ return 0;
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->(1);
+ is_deeply $x, undef, "$desc : first branch did not autovivify";
+ is $ret, 1, "$desc : first branch returned 1";
+
+ $ret = $code->(0, 1);
+ is_deeply $x, undef, "$desc : second branch did not autovivify";
+ is $ret, 2, "$desc : second branch returned 2";
+
+ $ret = $code->(0, 0, 0, 1, 1);
+ is_deeply $x, undef, "$desc : third branch did not autovivify";
+ is $ret, 3, "$desc : third branch returned 3";
+
+ $ret = $code->(0, 0, 0, 0, 0, 1, 1);
+ is_deeply $x, undef, "$desc : fourth branch did not autovivify";
+ is $ret, 4, "$desc : fourth branch returned 4";
+
+ $ret = $code->();
+ is_deeply $x, undef, "$desc : fifth branch did not autovivify";
+ is $ret, 5, "$desc : fifth branch returned 5";
+}
+
+{
+ my $desc = 'peephole optimization of C-style loops';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ my $ret = 0;
+ for (
+ my ($z, $i) = ($x->[100], 0)
+ ;
+ do { my $z = $x->[200]; $i < 4 }
+ ;
+ do { my $z = $x->[300]; ++$i }
+ ) {
+ my $z = $x->[$i];
+ $ret += $i;
+ }
+ return $ret;
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->();
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, 6, "$desc returned 0+1+2+3";
+}
+
+{
+ my $desc = 'peephole optimization of range loops';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ my $ret = 0;
+ for ((do { my $z = $x->[100]; 0 }) .. (do { my $z = $x->[200]; 3 })) {
+ my $z = $x->[$_];
+ $ret += $_;
+ }
+ return $ret;
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->();
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, 6, "$desc returned 0+1+2+3";
+}
+
+{
+ my $desc = 'peephole optimization of empty loops (RT #64435)';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ my $ret = 0;
+ for (;;) {
+ ++$ret;
+ return $ret;
+ }
+ return $ret;
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->();
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, 1, "$desc returned 1";
+}
+
+{
+ my $desc = 'peephole optimization of map';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ join ':', map {
+ my $z = $x->[$_];
+ "x${_}y"
+ } @_
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->(1, 2);
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, 'x1y:x2y', "$desc returned the right value";
+}
+
+{
+ my $desc = 'peephole optimization of grep';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ join ':', grep {
+ my $z = $x->[$_];
+ $_ <= 3
+ } @_
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->(1 .. 5);
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, '1:2:3', "$desc returned the right value";
+}
+
+{
+ my $desc = 'peephole optimization of substitutions';
+ my $x;
+
+ local $@;
+ my $code = eval <<' TESTCASE';
+ no autovivification;
+ sub {
+ my $str = $_[0];
+ $str =~ s{
+ ([0-9])
+ }{
+ my $z = $x->[$1];
+ 9 - $1;
+ }xge;
+ $str;
+ }
+ TESTCASE
+ is $@, '', "$desc compiled fine";
+
+ my $ret = $code->('0123456789');
+ is_deeply $x, undef, "$desc did not autovivify";
+ is $ret, '9876543210', "$desc returned the right value";
+}