Open theseer opened 1 year ago
I can reproduce this:
$ cat /etc/os-release
NAME="Fedora Linux"
VERSION="38 (Workstation Edition)"
ID=fedora
VERSION_ID=38
VERSION_CODENAME=""
PLATFORM_ID="platform:f38"
PRETTY_NAME="Fedora Linux 38 (Workstation Edition)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:38"
DEFAULT_HOSTNAME="fedora"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f38/system-administrators-guide/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=38
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=38
SUPPORT_END=2024-05-14
VARIANT="Workstation Edition"
VARIANT_ID=workstation
$ dnf info php-cli
Installed Packages
Name : php-cli
Version : 8.2.8
Release : 1.fc38.remi
Architecture : x86_64
Size : 24 M
Source : php-8.2.8-1.fc38.remi.src.rpm
Repository : @System
From repo : remi-modular
Summary : Command-line interface for PHP
URL : http://www.php.net/
License : PHP-3.01 AND Zend-2.0 AND BSD-2-Clause AND MIT AND Apache-1.0 AND NCSA AND PostgreSQL
Description : The php-cli package contains the command-line interface
: executing PHP scripts, /usr/bin/php, and the CGI interface.
$ dnf info php-opcache
Installed Packages
Name : php-opcache
Version : 8.2.8
Release : 1.fc38.remi
Architecture : x86_64
Size : 2.0 M
Source : php-8.2.8-1.fc38.remi.src.rpm
Repository : @System
From repo : remi-modular
Summary : The Zend OPcache
URL : http://www.php.net/
License : PHP-3.01
Description : The Zend OPcache provides faster PHP execution through opcode caching and
: optimization. It improves PHP performance by storing precompiled script
: bytecode in the shared memory. This eliminates the stages of reading code from
: the disk and compiling it on future access. In addition, it applies a few
: bytecode optimization patterns that make code execution faster.
$ php -i | grep opcache
Additional .ini files parsed => /etc/php.d/10-opcache.ini,
opcache.blacklist_filename => /etc/php.d/opcache*.blacklist => /etc/php.d/opcache*.blacklist
opcache.consistency_checks => 0 => 0
opcache.dups_fix => Off => Off
opcache.enable => On => On
opcache.enable_cli => On => On
opcache.enable_file_override => Off => Off
opcache.error_log => no value => no value
opcache.file_cache => no value => no value
opcache.file_cache_consistency_checks => On => On
opcache.file_cache_only => Off => Off
opcache.file_update_protection => 2 => 2
opcache.force_restart_timeout => 180 => 180
opcache.huge_code_pages => Off => Off
opcache.interned_strings_buffer => 8 => 8
opcache.jit => tracing => tracing
opcache.jit_bisect_limit => 0 => 0
opcache.jit_blacklist_root_trace => 16 => 16
opcache.jit_blacklist_side_trace => 8 => 8
opcache.jit_buffer_size => 0 => 0
opcache.jit_debug => 0 => 0
opcache.jit_hot_func => 127 => 127
opcache.jit_hot_loop => 64 => 64
opcache.jit_hot_return => 8 => 8
opcache.jit_hot_side_exit => 8 => 8
opcache.jit_max_exit_counters => 8192 => 8192
opcache.jit_max_loop_unrolls => 8 => 8
opcache.jit_max_polymorphic_calls => 2 => 2
opcache.jit_max_recursive_calls => 2 => 2
opcache.jit_max_recursive_returns => 2 => 2
opcache.jit_max_root_traces => 1024 => 1024
opcache.jit_max_side_traces => 128 => 128
opcache.jit_prof_threshold => 0.005 => 0.005
opcache.lockfile_path => /tmp => /tmp
opcache.log_verbosity_level => 1 => 1
opcache.max_accelerated_files => 10000 => 10000
opcache.max_file_size => 0 => 0
opcache.max_wasted_percentage => 5 => 5
opcache.memory_consumption => 128 => 128
opcache.opt_debug_level => 0 => 0
opcache.optimization_level => 0x7FFEBFFF => 0x7FFEBFFF
opcache.preferred_memory_model => no value => no value
opcache.preload => no value => no value
opcache.preload_user => no value => no value
opcache.protect_memory => Off => Off
opcache.record_warnings => Off => Off
opcache.restrict_api => no value => no value
opcache.revalidate_freq => 2 => 2
opcache.revalidate_path => Off => Off
opcache.save_comments => On => On
opcache.use_cwd => On => On
opcache.validate_permission => Off => Off
opcache.validate_root => Off => Off
opcache.validate_timestamps => On => On
Disabling just OpCache's optimizer works around the issue just as disabling OpCache entirely does.
We cannot reproduce this with Xdebug. According to @derickr, this is because "Xdebug sets the ZEND_COMPILE_EXTENDED_STMT
compiler options flag, which makes things emit EXT_STMT
and hence opcache can't optimise in this specific case".
The patch shown below fixes the problem for me:
diff --git a/pcov.c b/pcov.c
index f04ba9c..c354f72 100644
--- a/pcov.c
+++ b/pcov.c
@@ -441,6 +441,8 @@ PHP_RINIT_FUNCTION(pcov)
CG(compiler_options) |= ZEND_COMPILE_NO_JUMPTABLES;
#endif
+ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_STMT;
+
if (!zend_compile_file_function) {
zend_compile_file_function = zend_compile_file;
zend_compile_file = php_pcov_compile_file;
The patch looks sensible to me. However, ZEND_COMPILE_EXTENDED_STMT
is only available as of PHP 7.4.0, while pcov is still supposed to support PHP 7.1+. As such either that line would need to be enclosed in #if PHP_VERSION_ID >= 70400 … #endif
, or the version requirements of pcov would need to be bumped. Probably the latter.
It appears that code coverage information changes whether or not opcache is enabled. That's at least true for a line containing
continue
in the reproducer sample code.I created a selfcontained repo here: https://github.com/theseer/infection-bug. (It's named infection bug because i originally believed that to be an issue with infection)
Having PHP 8.2.8 / PCOV 1.0.11 with all the other extension loaded that phpunit requires + opcache on Fedora 38 x86_64. The reproducer uses PHPUnit 10.2.6
With opcache effectively disabled:
With opcache enabled, also for CLI:
I believe this to be wrong.