Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit e384950

Browse files
author
Reini Urban
committed
mderef_u: always lval run-time uoob
analog to av_fetch(,,1). i.e. return newSV(0) and store it into the av, just faster than with av_fetch. add mderef tests with the right aelem types, ref vs scalar, and add t/perf/opcount.t better diagnostics.
1 parent 0847e74 commit e384950

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

op.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14181,7 +14181,7 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
1418114181

1418214182
while (!is_last) {
1418314183
/* look for another (rv2av/hv; get index;
14184-
* aelem/helem/exists/delele) sequence */
14184+
* aelem/helem/exists/delete) sequence */
1418514185

1418614186
OP *kid;
1418714187
bool is_deref;
@@ -14305,7 +14305,7 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
1430514305
&& iv <= 127
1430614306
&& ( action == MDEREF_AV_padav_aelem
1430714307
|| action == MDEREF_AV_gvav_aelem)
14308-
)
14308+
) /* but still need to check for valid op_private */
1430914309
maybe_aelemfast = TRUE;
1431014310

1431114311
if (PASS2) {
@@ -14393,7 +14393,6 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
1439314393

1439414394
action |= index_type;
1439514395

14396-
1439714396
/* at this point we have either:
1439814397
* * detected what looks like a simple index expression,
1439914398
* and expect the next op to be an [ah]elem, or
@@ -14415,10 +14414,10 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
1441514414
if ( o->op_type == OP_AELEM && PL_check[o->op_type] != Perl_ck_aelem)
1441614415
return;
1441714416

14418-
if ( o->op_type != OP_AELEM
14419-
|| (o->op_private &
14420-
(OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB))
14421-
)
14417+
/* skip aelemfast if private cannot hold all bits */
14418+
if ( o->op_type != OP_AELEM
14419+
|| (o->op_private &
14420+
(OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)))
1442214421
maybe_aelemfast = FALSE;
1442314422

1442414423
/* look for aelem/helem/exists/delete. If it's not the last elem
@@ -15229,7 +15228,8 @@ Perl_rpeep(pTHX_ OP *o)
1522915228
&& strEQ(aname, PAD_COMPNAME_PV(o2->op_targ))) {
1523015229
DEBUG_k(Perl_deb(aTHX_ "nyi multideref[%s] => MDEREF_INDEX_uoob\n",
1523115230
aname));
15232-
/* TODO: find this padsv item and set MDEREF_INDEX_uoob */
15231+
/* TODO: find this padsv item (the first)
15232+
and set MDEREF_INDEX_uoob */
1523315233
} else if (type == OP_AELEMFAST && SvPOK(kSVOP_sv)
1523415234
&& strEQ(aname, SvPVX(kSVOP_sv))) {
1523515235
/* TODO no magic in array allowed, array must be typed */

pp_hot.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,10 +2451,10 @@ PP(pp_multideref)
24512451

24522452
if (!(actions & MDEREF_FLAG_last)) {
24532453
if (UNLIKELY((actions & MDEREF_INDEX_uoob) && !SvRMAGICAL(sv))) {
2454-
sv = AvARRAY(sv)[elem];
2455-
if (!sv) {
2456-
const U32 lval = (PL_op->op_flags & OPf_MOD) || LVRET;
2457-
sv = lval ? newSV(0) : &PL_sv_undef;
2454+
SV* av = sv;
2455+
sv = AvARRAY(av)[elem];
2456+
if (!sv) { /* always lval */
2457+
AvARRAY(av)[elem] = sv = newSV(0);
24582458
}
24592459
} else {
24602460
SV** svp = av_fetch((AV*)sv, elem, 1);

t/op/aelem_u.t

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ BEGIN {
55
chdir 't' if -d 't';
66
require './test.pl';
77
}
8-
plan( tests => 16 );
8+
plan( tests => 22 );
99
use coretypes;
1010
use cperl;
1111
use v5.22;
@@ -43,17 +43,37 @@ like ($@, qr/^Invalid modification of shaped array: unshift \@a/, "invalid unshi
4343
eval { splice @a; };
4444
like ($@, qr/^Invalid modification of shaped array: splice/, "invalid splice (run-time)");
4545

46+
# aelemfast_lex_u
4647
$a[0] = 1;
4748
is($a[0], 1, "set const w/o read-only");
4849
$a[-1] = 2; # compile-time changed to 4
4950
is($a[4], 2, "negative constant index");
51+
52+
# mderef_u:
5053
my $i = 0;
5154
$a[$i] = 1;
5255
is($a[$i], 1, "set");
5356
$i = -1;
5457
$a[$i] = 2; # run-time logic
5558
is($a[4], 2, "negative run-time index");
5659

60+
# multi mderef_u
61+
$a[1]->[5] = 1;
62+
is($a[1]->[5], 1, "set mderef_u");
63+
$a[-2]->[0] = 2;
64+
is($a[3]->[0], 2, "negative mderef_u");
65+
eval '$a[5]->[1];';
66+
like ($@, qr/^Array index out of bounds \@a\[5\]/, "compile-time mderef oob");
67+
68+
# multidim mderef_u
69+
$a[2][5] = 1;
70+
is($a[2][5], 1, "set multi mderef_u");
71+
$a[-2][0] = 2;
72+
is($a[3][0], 2, "negative multi mderef_u");
73+
74+
eval '$a[5][1];';
75+
like ($@, qr/^Array index out of bounds \@a\[5\]/, "compile-time mderef oob");
76+
5777
# eliminating loop out-of-bounds:
5878
my @b = (0..4);
5979
for (0..$#b) { $b[$_] }; # _u
@@ -67,10 +87,3 @@ for (0..$#b) { $b[$_+1] }; # wrong index: expr
6787
for $k (0..$#b) { $b[$k] }; # _u
6888
for $k (0..$#b) { $b[$j] }; # wrong index: glob
6989
}
70-
71-
# TODO mderef_u
72-
73-
# $a[0][1]; # set MDEREF_INDEX_noob to first index
74-
75-
#eval '$a[5][1];'
76-
#like ($@, qr/^Array index out of bounds \@a\[5\]/, "compile-time mderef oob");

t/perf/opcount.t

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use B ();
4949
# op counts for the sub.
5050

5151
sub test_opcount {
52-
my ($debug, $desc, $coderef, $expected_counts) = @_;
52+
my ($debug, $desc, $coderef, $expected_counts, $code) = @_;
5353

5454
%counts = ();
5555
B::walkoptree(B::svref_2object($coderef)->ROOT,
@@ -68,7 +68,8 @@ use B ();
6868
}
6969
ok(!@exp, $desc);
7070
if (@exp) {
71-
diag($_) for @exp;
71+
diag($code);
72+
diag($_) for @exp; 0
7273
}
7374
}
7475
}
@@ -182,7 +183,7 @@ test_opcount(0, "basic aelemfast",
182183
$c{$top} = 1
183184
}
184185

185-
::test_opcount(0, $sub, $coderef, \%c);
186+
::test_opcount(0, $sub, $coderef, \%c, $sub);
186187
}
187188
}
188189
}

0 commit comments

Comments
 (0)