Skip to content

Tracing JIT: side-exit SNAPSHOT omits a loop-PHI register, interpreter resumes #22115

@wilaak

Description

@wilaak

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions