Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preallocate space for Win64 shadow args #17095

Merged
merged 11 commits into from
Dec 12, 2024
8 changes: 0 additions & 8 deletions Zend/tests/bug54268.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ $zend_mm_enabled = getenv("USE_ZEND_ALLOC");
if ($zend_mm_enabled === "0") {
die("skip Zend MM disabled");
}
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/issues/15709";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php
Expand Down
11 changes: 0 additions & 11 deletions Zend/tests/gh16509.phpt
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
--TEST--
GH-16509: Incorrect lineno reported for function redeclaration
--SKIPIF--
<?php
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php

Expand Down
11 changes: 0 additions & 11 deletions Zend/tests/gh8841.phpt
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
--TEST--
GH-8841 (php-cli core dump calling a badly formed function)
--SKIPIF--
<?php
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php
register_shutdown_function(function() {
Expand Down
11 changes: 0 additions & 11 deletions Zend/tests/gh9407.phpt
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
--TEST--
GH-9407: LSP error in eval'd code refers to wrong class for static type
--SKIPIF--
<?php
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php

Expand Down
8 changes: 0 additions & 8 deletions Zend/tests/stack_limit/stack_limit_014.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ Stack limit 014 - Fuzzer
<?php
if (!function_exists('zend_test_zend_call_stack_get')) die("skip zend_test_zend_call_stack_get() is not available");
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--EXTENSIONS--
zend_test
Expand Down
11 changes: 0 additions & 11 deletions Zend/tests/traits/bugs/gh13177.phpt
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
--TEST--
GH-13177 (PHP 8.3.2: final private constructor not allowed when used in trait)
--SKIPIF--
<?php
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/issues/15709";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php

Expand Down
6 changes: 4 additions & 2 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3628,9 +3628,11 @@ void zend_jit_startup(void *buf, size_t size, bool reattached)
}

zend_jit_unprotect();
zend_jit_setup();
zend_jit_setup(reattached);
zend_jit_protect();
zend_jit_init_handlers();
if (!reattached) {
zend_jit_init_handlers();
}

zend_jit_trace_startup(reattached);

Expand Down
129 changes: 125 additions & 4 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
(1<<(16+6)) | (1<<(16+7)) | (1<<(16+8)) | (1<<(16+9)) | (1<<(16+10)) | \
(1<<(16+11)) | (1<<(16+12)) | (1<<(16+13)) | (1<<(16+14)) | (1<<(16+15)))
*/
# define IR_SHADOW_ARGS 32
# else
# define IR_REGSET_PRESERVED ((1<<3) | (1<<5) | (1<<12) | (1<<13) | (1<<14) | (1<<15)) /* all preserved registers */
# endif
Expand Down Expand Up @@ -2709,7 +2710,11 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
// jit->ctx.fixed_save_regset &= 0xffff; // TODO: don't save FP registers ???
//#endif
}
#ifdef _WIN64
jit->ctx.fixed_call_stack_size = 16 + IR_SHADOW_ARGS;
#else
jit->ctx.fixed_call_stack_size = 16;
#endif
} else {
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
jit->ctx.fixed_stack_red_zone = ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE;
Expand Down Expand Up @@ -3208,7 +3213,93 @@ static zend_never_inline void zend_jit_set_sp_adj_vm(void)
}
#endif

static void zend_jit_setup(void)
#ifdef _WIN64
/*
* We use a single unwind entry for the whole JIT buffer.
* This works, because all the JIT-ed PHP functions have the same "fixed stack frame".
*/
static PRUNTIME_FUNCTION zend_jit_uw_func = NULL;

#ifdef ZEND_JIT_RT_UNWINDER
static PRUNTIME_FUNCTION zend_jit_unwind_callback(DWORD64 pc, PVOID context)
{
return zend_jit_uw_func;
}
#endif

static void zend_jit_setup_unwinder(void)
{
/* Hardcoded SEH unwinf data for JIT-ed PHP functions with "fixed stack frame" */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Hardcoded SEH unwinf data for JIT-ed PHP functions with "fixed stack frame" */
/* Hardcoded SEH unwind data for JIT-ed PHP functions with "fixed stack frame" */

static const unsigned char uw_data[] = {
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
0x10, // UBYTE Size of prolog
0x09, // UBYTE Count of unwind codes
0x00, // UBYTE: 4 Frame Register, UBYTE: 4 Frame Register offset (scaled)
// USHORT * n Unwind codes array
0x10, 0x82, // c: subq $0x48, %rsp
0x0c, 0xf0, // a: pushq %r15
0x0a, 0xe0, // 8: pushq %r14
0x08, 0xd0, // 6: pushq %r13
0x06, 0xc0, // 4: pushq %r12
0x04, 0x70, // 3: pushq %rdi
0x03, 0x60, // 2: pushq %rsi
0x02, 0x50, // 1: pushq %rbp
0x01, 0x30, // 0: pushq %rbx
0x00, 0x00,
};
static const unsigned char uw_data_exitcall[] = {
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
0x10, // UBYTE Size of prolog
0x0a, // UBYTE Count of unwind codes
0x00, // UBYTE: 4 Frame Register, UBYTE: 4 Frame Register offset (scaled)
// USHORT * n Unwind codes array
0x10, 0x01, 0x2f, 0x00, // c: subq 376, %rsp ; 0x48 + 32+16*8+16*8+8+8
0x0c, 0xf0, // a: pushq %r15
0x0a, 0xe0, // 8: pushq %r14
0x08, 0xd0, // 6: pushq %r13
0x06, 0xc0, // 4: pushq %r12
0x04, 0x70, // 3: pushq %rdi
0x03, 0x60, // 2: pushq %rsi
0x02, 0x50, // 1: pushq %rbp
0x01, 0x30, // 0: pushq %rbx
};

zend_jit_uw_func = (PRUNTIME_FUNCTION)*dasm_ptr;
*dasm_ptr = (char*)*dasm_ptr + ZEND_MM_ALIGNED_SIZE_EX(sizeof(RUNTIME_FUNCTION) * 4 +
sizeof(uw_data) + sizeof(uw_data_exitcall) + sizeof(uw_data), 16);

zend_jit_uw_func[0].BeginAddress = 0;
zend_jit_uw_func[1].BeginAddress = (uintptr_t)zend_jit_stub_handlers[jit_stub_trace_exit] - (uintptr_t)dasm_buf;
zend_jit_uw_func[2].BeginAddress = (uintptr_t)zend_jit_stub_handlers[jit_stub_undefined_offset] - (uintptr_t)dasm_buf;

zend_jit_uw_func[0].EndAddress = zend_jit_uw_func[1].BeginAddress;
zend_jit_uw_func[1].EndAddress = zend_jit_uw_func[2].BeginAddress;
zend_jit_uw_func[2].EndAddress = (uintptr_t)dasm_end - (uintptr_t)dasm_buf;

zend_jit_uw_func[0].UnwindData = (uintptr_t)zend_jit_uw_func - (uintptr_t)dasm_buf + sizeof(RUNTIME_FUNCTION) * 4;
zend_jit_uw_func[1].UnwindData = zend_jit_uw_func[0].UnwindData + sizeof(uw_data);
zend_jit_uw_func[2].UnwindData = zend_jit_uw_func[1].UnwindData + sizeof(uw_data_exitcall);

memcpy((char*)dasm_buf + zend_jit_uw_func[0].UnwindData, uw_data, sizeof(uw_data));
memcpy((char*)dasm_buf + zend_jit_uw_func[1].UnwindData, uw_data_exitcall, sizeof(uw_data_exitcall));
memcpy((char*)dasm_buf + zend_jit_uw_func[2].UnwindData, uw_data, sizeof(uw_data));

#ifdef ZEND_JIT_RT_UNWINDER
RtlInstallFunctionTableCallback(
(uintptr_t)dasm_buf | 3,
(uintptr_t) dasm_buf,
(uintptr_t)dasm_end - (uintptr_t)dasm_buf,
zend_jit_unwind_callback,
NULL,
NULL);
#else
RtlAddFunctionTable(zend_jit_uw_func, 3, (uintptr_t)dasm_buf);
#endif
}
#endif


static void zend_jit_setup(bool reattached)
{
#if defined(IR_TARGET_X86)
if (!zend_cpu_supports_sse2()) {
Expand Down Expand Up @@ -3413,8 +3504,14 @@ static void zend_jit_setup(void)
}

zend_jit_calc_trace_prologue_size();
zend_jit_setup_stubs();
if (!reattached) {
zend_jit_setup_stubs();
}
JIT_G(debug) = debug;

#ifdef _WIN64
zend_jit_setup_unwinder();
#endif
}

static void zend_jit_shutdown_ir(void)
Expand Down Expand Up @@ -8978,7 +9075,11 @@ static int zend_jit_init_method_call(zend_jit_ctx *jit,
// JIT: alloca(sizeof(void*));
this_ref2 = ir_ALLOCA(ir_CONST_ADDR(0x10));
} else {
#ifdef _WIN64
this_ref2 = ir_HARD_COPY_A(jit_ADD_OFFSET(jit, ir_RLOAD_A(IR_REG_SP), IR_SHADOW_ARGS));
#else
this_ref2 = ir_HARD_COPY_A(ir_RLOAD_A(IR_REG_SP));
#endif
}
ir_STORE(this_ref2, this_ref);

Expand All @@ -8994,10 +9095,17 @@ static int zend_jit_init_method_call(zend_jit_ctx *jit,
this_ref2);
}

this_ref2 = ir_LOAD_A(ir_RLOAD_A(IR_REG_SP));

if (!jit->ctx.fixed_call_stack_size) {
this_ref2 = ir_LOAD_A(ir_RLOAD_A(IR_REG_SP));
// JIT: revert alloca
ir_AFREE(ir_CONST_ADDR(0x10));
} else {
#ifdef _WIN64
this_ref2 = ir_LOAD_A(jit_ADD_OFFSET(jit, ir_RLOAD_A(IR_REG_SP), IR_SHADOW_ARGS));
#else
this_ref2 = ir_LOAD_A(ir_RLOAD_A(IR_REG_SP));
#endif
}

ir_GUARD(ref2, jit_STUB_ADDR(jit, jit_stub_exception_handler));
Expand Down Expand Up @@ -10257,7 +10365,11 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
// JIT: alloca(sizeof(void*));
ptr = ir_ALLOCA(ir_CONST_ADDR(sizeof(zval)));
} else {
#ifdef _WIN64
ptr = ir_HARD_COPY_A(jit_ADD_OFFSET(jit, ir_RLOAD_A(IR_REG_SP), IR_SHADOW_ARGS));
#else
ptr = ir_HARD_COPY_A(ir_RLOAD_A(IR_REG_SP));
#endif
}
res_addr = ZEND_ADDR_REF_ZVAL(ptr);
}
Expand Down Expand Up @@ -10385,7 +10497,16 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
func_info |= MAY_BE_NULL;

if (func_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
ir_ref sp = ir_RLOAD_A(IR_REG_SP);
ir_ref sp;
if (!jit->ctx.fixed_call_stack_size) {
sp = ir_RLOAD_A(IR_REG_SP);
} else {
#ifdef _WIN64
sp = jit_ADD_OFFSET(jit, ir_RLOAD_A(IR_REG_SP), IR_SHADOW_ARGS);
#else
sp = ir_RLOAD_A(IR_REG_SP);
#endif
}
res_addr = ZEND_ADDR_REF_ZVAL(sp);
jit_ZVAL_PTR_DTOR(jit, res_addr, func_info, 1, opline);
}
Expand Down
8 changes: 0 additions & 8 deletions ext/spl/tests/gh14639.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ memory_limit=2M
if (getenv("USE_ZEND_ALLOC") === "0") {
die("skip Zend MM disabled");
}
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php
Expand Down
8 changes: 0 additions & 8 deletions tests/lang/bug45392.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ Bug #45392 (ob_start()/ob_end_clean() and memory_limit)
if (getenv("USE_ZEND_ALLOC") === "0") {
die("skip Zend MM disabled");
}
$tracing = extension_loaded("Zend OPcache")
&& ($conf = opcache_get_configuration()["directives"])
&& array_key_exists("opcache.jit", $conf)
&& $conf["opcache.jit"] === "tracing";
if (PHP_OS_FAMILY === "Windows" && PHP_INT_SIZE == 8 && $tracing) {
$url = "https://github.com/php/php-src/pull/14919#issuecomment-2259003979";
die("xfail Test fails on Windows x64 (VS17) and tracing JIT; see $url");
}
?>
--FILE--
<?php
Expand Down
Loading