Merge branch 'PHP-8.4'

* PHP-8.4:
  Fix GH-18136: tracing JIT floating point register clobbering on Windows and ARM64
This commit is contained in:
Niels Dossche 2025-04-21 13:15:50 +02:00
commit 864ad1b5bb
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
5 changed files with 106 additions and 1 deletions

View file

@ -0,0 +1,43 @@
.code
; ZEND_API void execute_ex(zend_execute_data *ex)
PUBLIC execute_ex
EXTERN execute_ex_real:PROC
; Assembly wrapper around the real execute_ex function, so that we can
; save the preserved registers when re-entering the VM from JIT code.
; See GH-18136.
execute_ex PROC EXPORT FRAME
; 10 floating points numbers
; 32 bytes shadow space
; 8 bytes to align after the return address
sub rsp, 8*10 + 32 + 8
.allocstack 8*10 + 32 + 8
.endprolog
movsd qword ptr [rsp + 32 + 8*0], xmm6
movsd qword ptr [rsp + 32 + 8*1], xmm7
movsd qword ptr [rsp + 32 + 8*2], xmm8
movsd qword ptr [rsp + 32 + 8*3], xmm9
movsd qword ptr [rsp + 32 + 8*4], xmm10
movsd qword ptr [rsp + 32 + 8*5], xmm11
movsd qword ptr [rsp + 32 + 8*6], xmm12
movsd qword ptr [rsp + 32 + 8*7], xmm13
movsd qword ptr [rsp + 32 + 8*8], xmm14
movsd qword ptr [rsp + 32 + 8*9], xmm15
call execute_ex_real
movsd xmm6, qword ptr [rsp + 32 + 8*0]
movsd xmm7, qword ptr [rsp + 32 + 8*1]
movsd xmm8, qword ptr [rsp + 32 + 8*2]
movsd xmm9, qword ptr [rsp + 32 + 8*3]
movsd xmm10, qword ptr [rsp + 32 + 8*4]
movsd xmm11, qword ptr [rsp + 32 + 8*5]
movsd xmm12, qword ptr [rsp + 32 + 8*6]
movsd xmm13, qword ptr [rsp + 32 + 8*7]
movsd xmm14, qword ptr [rsp + 32 + 8*8]
movsd xmm15, qword ptr [rsp + 32 + 8*9]
add rsp, 8*10 + 32 + 8
ret
execute_ex ENDP
END

View file

@ -54953,10 +54953,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDL
# pragma GCC optimize("no-gcse")
# pragma GCC optimize("no-ivopts")
#endif
#ifdef _WIN64
/* See save_xmm_x86_64_ms_masm.asm */
void execute_ex_real(zend_execute_data *ex)
#else
ZEND_API void execute_ex(zend_execute_data *ex)
#endif
{
DCL_OPLINE
#if defined(__GNUC__) && defined(__aarch64__)
__asm__ __volatile__ (""::: "v8","v9","v10","v11","v12","v13","v14","v15");
#endif
#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_FP_GLOBAL_REG)
struct {
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE

View file

@ -7,10 +7,19 @@
# pragma GCC optimize("no-gcse")
# pragma GCC optimize("no-ivopts")
#endif
#ifdef _WIN64
/* See save_xmm_x86_64_ms_masm.asm */
void {%EXECUTOR_NAME%}_ex_real(zend_execute_data *ex)
#else
ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex)
#endif
{
DCL_OPLINE
#if defined(__GNUC__) && defined(__aarch64__)
__asm__ __volatile__ (""::: "v8","v9","v10","v11","v12","v13","v14","v15");
#endif
{%HELPER_VARS%}
{%INTERNAL_LABELS%}

View file

@ -0,0 +1,35 @@
--TEST--
GH-18136 (tracing JIT floating point register clobbering on Windows and ARM64)
--EXTENSIONS--
opcache
--INI--
opcache.jit=tracing
opcache.jit_buffer_size=64M
opcache.jit_hot_func=4
opcache.jit_hot_loop=4
--FILE--
<?php
namespace Foo;
function diff($point1, $point2)
{
$a = deg2rad($point1); // Prefixing these with \ also makes the issue go away
$b = deg2rad($point2);
return $a - $b;
}
function getRawDistance()
{
$distance = 0;
for ($p = 0; $p < 200; $p++) {
// Needs to be a namespaced call_user_func call to reproduce the issue (i.e. adding \ at front makes the issue go away)
$distance += call_user_func('Foo\diff', 0, $p);
}
return $distance;
}
var_dump(getRawDistance());
?>
--EXPECT--
float(-347.3205211468715)

View file

@ -267,7 +267,11 @@ if (TARGET_ARCH == 'arm64') {
DEFINE('FIBER_ASM_FLAGS', '/DBOOST_CONTEXT_EXPORT=EXPORT /nologo /c /Fo');
}
ADD_FLAG('ASM_OBJS', '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj $(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj');
var all_asm_objs = '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj $(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj';
if (TARGET_ARCH == 'x64') {
all_asm_objs += ' $(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj';
}
ADD_FLAG('ASM_OBJS', all_asm_objs);
MFO.WriteLine('$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\jump_' + FIBER_ASM_ABI + '.asm');
MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\jump_$(FIBER_ASM_ABI).obj Zend\\asm\\jump_$(FIBER_ASM_ABI).asm');
@ -275,6 +279,11 @@ MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\jump_$(
MFO.WriteLine('$(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\make_' + FIBER_ASM_ABI + '.asm');
MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\make_$(FIBER_ASM_ABI).obj Zend\\asm\\make_$(FIBER_ASM_ABI).asm');
if (TARGET_ARCH == 'x64') {
MFO.WriteLine('$(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj: Zend\\asm\\save_xmm_x86_64_ms_masm.asm');
MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\save_xmm_x86_64_ms_masm.obj Zend\\asm\\save_xmm_x86_64_ms_masm.asm');
}
ADD_FLAG("CFLAGS_BD_ZEND", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
if (VS_TOOLSET && VCVERS >= 1914) {
ADD_FLAG("CFLAGS_BD_ZEND", "/d2FuncCache1");