diff options
author | jimc <jim.cromie@gmail.com> | 2016-03-14 22:02:52 -0600 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2016-05-17 16:37:49 +1000 |
commit | 0927ade08b4a98671d253366f66b984dc77ed512 (patch) | |
tree | 481a97824455f0da40ff1362efe5c0d5353ba8cd /regen | |
parent | 38c8d7b116b8e618c4f230cd34234e218e5eb6c8 (diff) | |
download | perl-0927ade08b4a98671d253366f66b984dc77ed512.tar.gz |
better glibc i_modulo bug handling
pp-i-modulo code currently detects a glibc bug at runtime, at the 1st
exec of each I_MODULO op. This is suboptimal; the bug should be
detectable early, and PL_ppaddr[I_MODULO] updated just once, before
any optrees are built.
Then, because we avoid the need to fixup I_MODULO ops in already built
optrees, we can drop the !PERL_DEBUG_READONLY_OPS limitation on the
alternative/workaround I_MODULO implementation that avoids the bug.
perl.c:
bug detection code is copied from PP(i_modulo),
into S_fixup_platform_bugs(), and called from perl_construct().
It patches Perl_pp_i_modulo_1() into PL_ppaddr[I_MODULO] when needed.
pp.c:
PP(i_modulo_0), the original implementation, is renamed to PP(i_modulo)
PP(i_modulo_1), the bug-fix workaround, is renamed _glibc_bugfix
it is #ifdefd as before, but dropping !PERL_DEBUG_READONLY_OPS
PP(i_modulo) - the 1st-exec switcher code, is dropped
ocode.pl:
Two i_modulo entries are added to @raw_alias.
- 1st alias: Perl_pp_i_modulo => 'i_modulo'
- 2nd alt: Perl_pp_i_modulo_glibc_bugfix => 'i_modulo'
1st is a restatement of the default alias/mapping that would be
created without the line. 2nd line is then seen as alternative to the
explicit mapping set by 1st.
Alternative functions are written to pp_proto.h after the standard
Perl_pp_* list, and include #if-cond, #endif wrappings, as was
specified by 2nd @raw_alias addition.
Changes tested by inserting '1 ||' into the 3 ifdefs and bug-detection code.
TODO:
In pp_proto.h generation, the #ifdef wrapping code which handles the
alternative functions looks like it should also be used for the
non-alternate functions. In particular, there are a handful of
pp-function prototypes that should be wrapped with #ifdef HAS_SOCKET.
That said, there have been no problem reports, so I left it alone.
TonyC: make S_fixup_platform_bugs static, porting/libperl.t was failing.
Diffstat (limited to 'regen')
-rwxr-xr-x | regen/opcode.pl | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/regen/opcode.pl b/regen/opcode.pl index 82454bbb48..edb9f4d7c1 100755 --- a/regen/opcode.pl +++ b/regen/opcode.pl @@ -71,9 +71,9 @@ while (<OPS>) { $args{$key} = $args; } -# Set up aliases +# Set up aliases, and alternative funcs -my %alias; +my (%alias, %alts); # Format is "this function" => "does these op names" my @raw_alias = ( @@ -139,16 +139,25 @@ my @raw_alias = ( Perl_pp_shostent => [qw(snetent sprotoent sservent)], Perl_pp_aelemfast => ['aelemfast_lex'], Perl_pp_grepstart => ['mapstart'], + + # 2 i_modulo mappings: 2nd is alt, needs 1st (explicit default) to not override the default + Perl_pp_i_modulo => ['i_modulo'], + Perl_pp_i_modulo_glibc_bugfix => { + 'i_modulo' => + '#if defined(__GLIBC__) && IVSIZE == 8 '. + ' && ( __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))' }, ); while (my ($func, $names) = splice @raw_alias, 0, 2) { if (ref $names eq 'ARRAY') { foreach (@$names) { - $alias{$_} = [$func, '']; + defined $alias{$_} + ? $alts{$_} : $alias{$_} = [$func, '']; } } else { while (my ($opname, $cond) = each %$names) { - $alias{$opname} = [$func, $cond]; + defined $alias{$opname} + ? $alts{$opname} : $alias{$opname} = [$func, $cond]; } } } @@ -1251,6 +1260,14 @@ my $pp = open_new('pp_proto.h', '>', ++$funcs{$name}; } print $pp "PERL_CALLCONV OP *$_(pTHX);\n" foreach sort keys %funcs; + + print $pp "\n/* alternative functions */\n" if keys %alts; + for my $fn (sort keys %alts) { + my ($x, $cond) = @{$alts{$fn}}; + print $pp "$cond\n" if $cond; + print $pp "PERL_CALLCONV OP *$x(pTHX);\n"; + print $pp "#endif\n" if $cond; + } } print $oc "\n\n"; |