Skip to content

Commit 658f070

Browse files
committed
Add additional check for custom array/hash access checking
PL_check[] can have customized checks for array/hash elements in the OP_AELEM, OP_EXISTS, and OP_DELETE elements. When these are set, the multideref optimization is turned off. It turns out that checking for this always shows that they are not the standard values on z/OS, because that platform's function pointers may point to a "function descriptor" and not the actual function, or it may not. It's not clear to me if this implementation conforms to the C Standard or not, but it is what it is. As a result our test suite fails some tests that are expecting non-custom entries in those slots. This commit builds upon some ideas from Dave Mitchell and Richard Leach to add 3 entries to the array of function pointers. These entries are initialized the same way the others are, so that a comparison against them when no customization has been done should succeed. The current comparisons are retained, so that it's likely on z/OS one or the other will succeed when no customization is currently in place.
1 parent 789e970 commit 658f070

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

opcode.h

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

peep.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,16 +2203,20 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
22032203
* OP_EXISTS or OP_DELETE */
22042204

22052205
/* if a custom array/hash access checker is in scope,
2206-
* abandon optimisation attempt */
2206+
* abandon optimisation attempt. Check two different ways because
2207+
* of z/OS (see comments in opcode.h) */
22072208
if ( (o->op_type == OP_AELEM || o->op_type == OP_HELEM)
2208-
&& PL_check[o->op_type] != Perl_ck_null)
2209+
&& PL_check[o->op_type] != Perl_ck_null
2210+
&& PL_check[o->op_type] != PL_check[PERL_CK_NULL])
22092211
return;
22102212
/* similarly for customised exists and delete */
22112213
if ( (o->op_type == OP_EXISTS)
2212-
&& PL_check[o->op_type] != Perl_ck_exists)
2214+
&& PL_check[o->op_type] != Perl_ck_exists
2215+
&& PL_check[o->op_type] != PL_check[PERL_CK_EXISTS])
22132216
return;
22142217
if ( (o->op_type == OP_DELETE)
2215-
&& PL_check[o->op_type] != Perl_ck_delete)
2218+
&& PL_check[o->op_type] != Perl_ck_delete
2219+
&& PL_check[o->op_type] != PL_check[PERL_CK_DELETE])
22162220
return;
22172221

22182222
if ( o->op_type != OP_AELEM

regen/opcode.pl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,13 +1114,39 @@ sub generate_opcode_h_pl_check {
11141114
INIT({
11151115
END
11161116

1117+
11171118
for (@ops) {
11181119
print "\t", tab(3, "Perl_$check{$_},"), "\t/* $_ */\n";
11191120
}
11201121

1122+
print <<~'END';
1123+
1124+
/* The final entries are function pointers not attached to an opcode.
1125+
* These are used to compare with function pointers in the earlier part of
1126+
* the array, since in some platforms (notably z/OS), it is undefined
1127+
* behavior to compare function pointers for equality, even though calling
1128+
* them will invoke the same function. This minimizes the risk of them
1129+
* being different by initializing them to the same values in the same
1130+
* array. */
1131+
END
1132+
my @perl_internal_extras = qw(ck_null ck_exists ck_delete);
1133+
for (@perl_internal_extras) {
1134+
print "\t", tab(3, "Perl_$_,\n");
1135+
}
1136+
11211137
print <<~'END';
11221138
});
1139+
1140+
/* Indexes into PL_check for the comparison function pointers */
1141+
#ifdef PERL_IN_PEEP_C
11231142
END
1143+
1144+
for (my $i = 0; $i < @perl_internal_extras; $i++) {
1145+
my $index = @ops + $i;
1146+
my $define = uc $perl_internal_extras[$i];
1147+
print " #define PERL_$define $index\n";
1148+
}
1149+
print "#endif\n";
11241150
}
11251151

11261152
sub generate_opcode_h_pl_opargs {

0 commit comments

Comments
 (0)