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:
2
NEWS
2
NEWS
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
22
ext/opcache/tests/jit/gh16879.phpt
Normal file
22
ext/opcache/tests/jit/gh16879.phpt
Normal 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
|
||||
Reference in New Issue
Block a user