Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:103609 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 25646 invoked from network); 15 Dec 2018 22:33:32 -0000 Received: from unknown (HELO xdebug.org) (82.113.146.227) by pb1.pair.com with SMTP; 15 Dec 2018 22:33:32 -0000 Received: from localhost (localhost [IPv6:::1]) by xdebug.org (Postfix) with ESMTPS id 1C92110C035; Sat, 15 Dec 2018 19:01:37 +0000 (GMT) Date: Sat, 15 Dec 2018 19:01:37 +0000 (GMT) X-X-Sender: derick@singlemalt.home.derickrethans.nl To: Dmitry Stogov cc: Nikita Popov , PHP Developers Mailing List Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="8323329-1542546121-1544900503=:10999" Subject: Changes to when OPcache initialises From: derick@php.net (Derick Rethans) --8323329-1542546121-1544900503=:10999 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Hi! I am working on making Xdebug work properly with PHP 7.3, and over the=20 last week I have been tearing my hair out as to why Xdebug's view of=20 opcodes was no longer showing the opcodes that OPcache had=20 modified/optimised. In PHP 7.2, the order in which you load Xdebug and=20 OPcache made a difference.=20 OPcache optimises out line 6, which has dead code: 1 derick@singlemalt:~/dev/php/derickr-xdebug $ /usr/local/php/7.2.13/bin/php = -n -dzend_extension=3Dopcache.so -d "zend_extension=3Dxdebug.so" -d "opca= che.enable=3D1" -d "opcache.enable_cli=3D1" -d "xdebug.extended_info=3D1" -= dvld.active=3D1 -f "/home/derick/dev/php/derickr-xdebug/tests/bug00213-php7= 3-opcache.php"=20 48 /home/derick/dev/php/derickr-xdebug/tests/bug00213-php73-opcache.php:7: array(4) { [5] =3D> int(1) [8] =3D> int(1) [12] =3D> int(1) [14] =3D> int(1) } [GIT: issue1598-no-code-coverage-with-opcache][PHP: 7.2.13 ] derick@singlemalt:~/dev/php/derickr-xdebug $ /usr/local/php/7.2.13/bin/php = -n -d "zend_extension=3Dxdebug.so" -dzend_extension=3Dopcache.so -d "opca= che.enable=3D1" -d "opcache.enable_cli=3D1" -d "xdebug.extended_info=3D1" -= dvld.active=3D1 -f "/home/derick/dev/php/derickr-xdebug/tests/bug00213-php7= 3-opcache.php"=20 48 /home/derick/dev/php/derickr-xdebug/tests/bug00213-php73-opcache.php:7: array(5) { [5] =3D> int(1) [6] =3D> int(-2) [8] =3D> int(1) [12] =3D> int(1) [14] =3D> int(1) } Where as with PHP 7.3.0, they both show the *unoptimised* version: derick@singlemalt:~/dev/php/derickr-xdebug $ /usr/local/php/7.3.0/bin/php = -n -dzend_extension=3Dopcache.so -d "zend_extension=3Dxdebug.so" -d "opcac= he.enable=3D1" -d "opcache.enable_cli=3D1" -d "xdebug.extended_info=3D1" -d= vld.active=3D1 -f "/home/derick/dev/php/derickr-xdebug/tests/bug00213-php73= -opcache.php" 48 /home/derick/dev/php/derickr-xdebug/tests/bug00213-php73-opcache.php:7: array(5) { [5] =3D> int(1) [6] =3D> int(-2) [8] =3D> int(1) [12] =3D> int(1) [14] =3D> int(1) } [GIT: issue1598-no-code-coverage-with-opcache][PHP: 7.2.13 ] derick@singlemalt:~/dev/php/derickr-xdebug $ /usr/local/php/7.3.0/bin/php = -n -d "zend_extension=3Dxdebug.so" -dzend_extension=3Dopcache.so -d "opcac= he.enable=3D1" -d "opcache.enable_cli=3D1" -d "xdebug.extended_info=3D1" -d= vld.active=3D1 -f "/home/derick/dev/php/derickr-xdebug/tests/bug00213-php73= -opcache.php" 48 /home/derick/dev/php/derickr-xdebug/tests/bug00213-php73-opcache.php:7: array(5) { [5] =3D> int(1) [6] =3D> int(-2) [8] =3D> int(1) [12] =3D> int(1) [14] =3D> int(1) } Curiously, vld, would always show the right (optimised) opcodes: filename: /home/derick/dev/php/derickr-xdebug/tests/bug00213.inc function name: (null) number of ops: 12 compiled vars: !0 =3D $e line #* E I O op fetch ext return = operands ---------------------------------------------------------------------------= ---------- 5 0 E > EXT_STMT 1 NEW $1 = :-5 2 EXT_FCALL_BEGIN 3 DO_FCALL 0 4 EXT_FCALL_END 5 > THROW 0 = $1 8 6 E > > CATCH = 'Exception', !0 12 7 > EXT_STMT 8 ECHO = 48 9 EXT_STMT 10 ECHO = '%0A' 14 11 > RETURN = 1 branch: # 0; line: 5- 5; sop: 0; eop: 5; out0: -2 branch: # 6; line: 8- 8; sop: 6; eop: 6; out0: 7; out1: = -2 branch: # 7; line: 12- 14; sop: 7; eop: 11; out0: -2 path #1: 0, path #2: 6, 7, So I did some digging and found out that OPcache in PHP 7.3 has had a chang= e to the loading order. This was done in: https://github.com/php/php-src/commit/b4903aef16ec215f2095ff0a3615524656401= 660: =09commit b4903aef16ec215f2095ff0a3615524656401660 =09Author: Dmitry Stogov =09Date: Wed Oct 18 17:18:54 2017 +0300 =09=09Move a part of opcache initialization into post_startup phase (when a= ll extensions already loaded). Both Xdebug and OPcache hook into zend_compile. In PHP 7.2, when as per=20 documentation, OPcache was loaded after Xdebug, OPcache's zend_compile=20 (accel_startup) was run *first*, so that Xdebug sees the optimised=20 opcodes. In PHP 7.3, after the above commit, Xdebug's zend_compile hook=20 (xdebug_compile_file) is run before OPcache's =E2=80=94 *no matter which=20 extension is loaded first*. Due to this, Xdebug can not properly do code=20 coverage anymore when OPcache is also present, as it can only see=20 *unoptimised* oparrays during its zend_compile hook. Because opcodes may now differ between when Xdebug analyses oparrays=20 (zend_compile stage) and when it uses it (zend_execute stage) the=20 results can be inconsistent in OPcache has optimised things away, and/or=20 rearranged branches. Right now, I don't think I have a choice but to disallow code coverage=20 analysis when OPcache is present, but I would prefer finding a solution=20 to this so that OPcache and Xdebug work together again, as it did for=20 PHP versions before 7.3. cheers, Derick --=20 https://derickrethans.nl | https://xdebug.org | https://dram.io Like Xdebug? Consider a donation: https://xdebug.org/donate.php, or become my Patron: https://www.patreon.com/derickr twitter: @derickr and @xdebug --8323329-1542546121-1544900503=:10999--