Description
Tracing jit gives wrong return value on a hot loop. Function JIT and JIT=Off are fine so it's a tracing thing.
The following code:
<?php
declare(strict_types=1);
function lookup(string $tape, array $meta, array $state_meta, string $path): int
{
$length = \strlen($path);
$state_offset = 0;
$cursor = 1;
while ($cursor < $length) {
$run = \strcspn($tape, $path[$cursor], $state_offset, 1);
if ($run < 1) {
$m = (int) $meta[$state_offset];
$edge_length = $m & 0xFF;
if ($edge_length === 1
|| \substr_compare($path, "c", $cursor + 1, 1) === 0) {
$cursor += $edge_length;
$state_offset = ($m >> 32) & 0xFFFFFF;
continue;
}
}
return (int) $state_meta[$state_offset];
}
return (int) $state_meta[$state_offset];
}
$tape = "ab";
$meta = [0 => 1 | (1 << 32), 1 => 2 | (2 << 32)];
$state_meta = [0 => 100, 1 => 200, 2 => 300];
for ($w = 0; $w < 2000; $w++) {
lookup($tape, $meta, $state_meta, '/abc');
lookup($tape, $meta, $state_meta, '/abx');
}
var_dump(lookup($tape, $meta, $state_meta, '/abx'));
Resulted in this output:
$ php -d opcache.enable_cli=1 -d opcache.jit_buffer_size=64M -d opcache.jit=tracing repro.php
int(100)
But I expected this output instead:
$ php -d opcache.enable_cli=1 -d opcache.jit_buffer_size=64M -d opcache.jit=function repro.php
int(200)
Probable cause
There are some very specific things that need to align for this to occur, so likely just your typical edge case scenario that didn't get a test written for it.
php -d opcache.enable_cli=1 -d opcache.jit=tracing \
-d opcache.jit_buffer_size=64M \
-d opcache.jit_debug=$((0xFFFFFFFF)) repro.php 2>&1 | less
You see that exit_8 is the bad one, CV5($state_offset):int with no (r12).
Environment
PHP 8.5.6 cli, linux wsl2, gcc 14. master at fcc29c8.
PHP Version
This was also tested and reproduced on latest master commit.
PHP 8.5.6 (cli) (built: May 14 2026 16:01:51) (NTS)
Copyright (c) The PHP Group
Built by Ubuntu
Zend Engine v4.5.6, Copyright (c) Zend Technologies
with Zend OPcache v8.5.6, Copyright (c), by Zend Technologies
Operating System
Ubuntu 24.04.1 LTS (Noble Numbat) on WSL2, kernel 6.6.
Description
Tracing jit gives wrong return value on a hot loop. Function JIT and JIT=Off are fine so it's a tracing thing.
The following code:
Resulted in this output:
But I expected this output instead:
Probable cause
There are some very specific things that need to align for this to occur, so likely just your typical edge case scenario that didn't get a test written for it.
You see that exit_8 is the bad one, CV5($state_offset):int with no (r12).
Environment
PHP 8.5.6 cli, linux wsl2, gcc 14. master at fcc29c8.
PHP Version
This was also tested and reproduced on latest master commit.
Operating System
Ubuntu 24.04.1 LTS (Noble Numbat) on WSL2, kernel 6.6.