Skip to content

JIT (tracing) return wrong float value after some times #18839

Open
@marcimat

Description

@marcimat

Description

In a (pretty old) PHP projet, is used a non-typed function moins (minus in french) with this simple following code:

<?php
function moins($a, $b) {
	return $a - $b;
}

We wanted to activate JIT (tracing) on PHP 8.4 (now with PHP 8.4.8), and after some unpredictable minutes or hours (depending of the website traffic ?) , the result of this function moins becomes wrong :

<?php
echo 'Moins:' . PHP_EOL;
echo moins(1, 1) . PHP_EOL;
echo moins(2, 1) . PHP_EOL;
echo moins(3, 1) . PHP_EOL;
echo PHP_EOL;

echo "with string:" . PHP_EOL;
echo moins('1', '1') . PHP_EOL;
echo moins('2', '1') . PHP_EOL;
echo moins('3', '1') . PHP_EOL;

Resulted in this output:

Moins:
0
4.9406564584125E-324
9.8813129168249E-324

with string:
0
4.9406564584125E-324
9.8813129168249E-324

But we expected this output instead:

Moins:
0
1
2

with string:
0
1
2

We didn’t test JIT before on previous PHP branches, so I don’t know if the result is the same on PHP 8.3 or before. This bug doesn’t appear without JIT enabled.

As you can see, some float with exponent is returned, and it seems related with floating point IEEE 754 64-bit binary format ; these numbers are the same as

<?php
(2 - 1)*2**-1074; // 4.9406564584125E-324
(3 - 1)*2**-1074; // 9.8813129168249E-324

And with all that, I was unable to reproduce that in CLI with JIT tracing on (we show that with FPM), nor in my local (DDEV) environment (and with different JIT configuration option).

The bug disapear (for some time) as soon as we reload that PHP version.

We show that at least on 2 different servers, with intel CPU

  • BIOS Model name: Intel(R) Xeon(R) E-2136 CPU @ 3.30GHz To Be Filled By O.E.M. CPU @ 3.3GHz
  • BIOS Model name: Intel(R) Xeon(R) E-2288G CPU @ 3.70GHz To Be Filled By O.E.M. CPU @ 3.7GHz

Opcache.jit* FPM configuration:

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	128M	128M
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_max_trace_length	1024	1024
opcache.jit_prof_threshold	0.005

Is it something that talk to someone ?

Obviously, this moins function is used in a more complex context, in a web templating system notably, that function may also be call inside an eval() (I don’t know if that the cause of the problem) ; but for now I’m not able to reproduce a systematic small file code which trigger the bug, outside the full web project.

But from the moment the function bugs, it bugs in whatever script the function is called (that includes the file with the function declaration).

One example tried among other in CLI to reproduce vainly

php8.4 -d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.jit=tracing -d opcache.jit_buffer_size=1G -d opcache.jit_max_root_traces=1000000 -d opcache.jit_max_side_traces=1000000 -d opcache.jit_max_exit_counters=1000000 -d opcache.jit_hot_loop=0 -d opcache.jit_hot_func=0 -d opcache.jit_hot_return=0 -d opcache.jit_hot_side_exit=0 -d memory_limit=-1 test.php 
  • Is there some open or closed bugs with JIT that are similar to that ?

Note: I’m not so familiar with php-src, please apologize if I’m not write things the rigth way.

PHP Version

php-fpm8.4 -v
PHP 8.4.8 (fpm-fcgi) (built: Jun  9 2025 13:42:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.8, Copyright (c), by Zend Technologies

php8.4 -v
PHP 8.4.8 (cli) (built: Jun  9 2025 13:42:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.4.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.8, Copyright (c), by Zend Technologies

Operating System

Debian GNU/Linux 12 (bookworm)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions