1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-16879: JIT dead code skipping does not update call_level

We intend to execute `MATCH_ERROR` in the VM and return to trace a hot
function in BB1. We generate a tail handler and skip all remaining
oplines of BB0. That means the `INIT_FCALL` in BB0 is missed and
`call_level` is not increased to 1. This leads to the assertion
failure.
This patch fixes the issue by updating the `call_level` for the skipped
oplines.

Closes GH-16939.
This commit is contained in:
Niels Dossche
2024-11-25 22:02:49 +01:00
parent 8fdcd9f051
commit de30ba5042
3 changed files with 52 additions and 1 deletions

2
NEWS
View File

@@ -19,6 +19,8 @@ PHP NEWS
. Fixed bug GH-16851 (JIT_G(enabled) not set correctly on other threads).
(dktapps)
. Fixed bug GH-16902 (Set of opcache tests fail zts+aarch64). (nielsdos)
. Fixed bug GH-16879 (JIT dead code skipping does not update call_level).
(nielsdos)
- Windows:
. Fixed bug GH-16849 (Error dialog causes process to hang). (cmb)

View File

@@ -2576,7 +2576,34 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
}
/* THROW and EXIT may be used in the middle of BB */
/* don't generate code for the rest of BB */
i = end;
/* Skip current opline for call_level computation
* Don't include last opline because end of loop already checks call level of last opline */
i++;
for (; i < end; i++) {
opline = op_array->opcodes + i;
switch (opline->opcode) {
case ZEND_INIT_FCALL:
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
case ZEND_INIT_METHOD_CALL:
case ZEND_INIT_DYNAMIC_CALL:
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
case ZEND_INIT_USER_CALL:
case ZEND_NEW:
call_level++;
break;
case ZEND_DO_FCALL:
case ZEND_DO_ICALL:
case ZEND_DO_UCALL:
case ZEND_DO_FCALL_BY_NAME:
case ZEND_CALLABLE_CONVERT:
call_level--;
break;
}
}
opline = op_array->opcodes + i;
break;
/* stackless execution */
case ZEND_INCLUDE_OR_EVAL:

View File

@@ -0,0 +1,22 @@
--TEST--
GH-16879 (JIT dead code skipping does not update call_level)
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.jit_buffer_size=32M
opcache.jit=1235
opcache.jit_hot_func=1
--FILE--
<?php
match(0){};
var_dump(new stdClass);
var_dump(3);
?>
--EXPECTF--
Fatal error: Uncaught UnhandledMatchError: Unhandled match case 0 in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d