]> granicus.if.org Git - php/commitdiff
Fix type recording and side exit information for FE_FETCH_* instructions
authorDmitry Stogov <dmitry@zend.com>
Tue, 21 Jul 2020 12:39:13 +0000 (15:39 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 21 Jul 2020 12:39:13 +0000 (15:39 +0300)
ext/opcache/jit/zend_jit_vm_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index 7668f47f2a9a2d3b6bef4184caedb4b81da951f2..0703d9e805d849e449b39318f6b00467e5201b4a 100644 (file)
@@ -655,8 +655,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
                if (opline->op2_type & (IS_TMP_VAR|IS_VAR|IS_CV)
                 && opline->opcode != ZEND_INSTANCEOF
                 && opline->opcode != ZEND_UNSET_STATIC_PROP
-                && opline->opcode != ZEND_FE_FETCH_R
-                && opline->opcode != ZEND_FE_FETCH_RW) {
+                && (opline->op2_type == IS_CV
+                 || (opline->opcode != ZEND_FE_FETCH_R
+                  && opline->opcode != ZEND_FE_FETCH_RW))) {
                        zval *zv = EX_VAR(opline->op2.var);
                        uint8_t flags = 0;
 
index 8e8ec5694a748082b47d517b1a6bac0dfbe235fc..9bf9f895409d186575eefff6c74fb0f0cc3cca52 100644 (file)
@@ -3277,6 +3277,8 @@ static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_arra
                        const zend_op *exit_opline = NULL;
                        uint32_t exit_point;
                        const void *exit_addr;
+                       uint32_t old_info = 0;
+                       zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
 
                        if (zend_is_smart_branch(opline)) {
                                zend_bool exit_if_true = 0;
@@ -3302,6 +3304,10 @@ static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_arra
                                                break;
                                        case ZEND_FE_FETCH_R:
                                        case ZEND_FE_FETCH_RW:
+                                               if (opline->op2_type == IS_CV) {
+                                                       old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op2.var));
+                                                       SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var), IS_UNKNOWN);
+                                               }
                                                exit_opline = (trace->opline == opline + 1) ?
                                                        ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) :
                                                        opline + 1;
@@ -3313,6 +3319,15 @@ static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_arra
                        exit_point = zend_jit_trace_get_exit_point(opline, exit_opline, trace, 0);
                        exit_addr = zend_jit_trace_get_exit_addr(exit_point);
 
+                       switch (opline->opcode) {
+                               case ZEND_FE_FETCH_R:
+                               case ZEND_FE_FETCH_RW:
+                                       if (opline->op2_type == IS_CV) {
+                                               SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op2.var), old_info);
+                                       }
+                                       break;
+                       }
+
                        if (!exit_addr) {
                                return 0;
                        }