]> granicus.if.org Git - php/commitdiff
Check for EG(exception) after leaving function frame
authorDmitry Stogov <dmitry@zend.com>
Tue, 28 Jul 2020 16:03:05 +0000 (19:03 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 28 Jul 2020 16:03:05 +0000 (19:03 +0300)
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 1968eff8d53f336200bdc5be4536337f8c20f355..7b7534fff6d0926b57358630452171c65d29f052 100644 (file)
@@ -2727,7 +2727,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                                        }
                                                                }
                                                        }
-                                                   if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL, NULL)) {
+                                                   if (!zend_jit_leave_func(&dasm_state, opline, op_array, NULL, NULL, 1)) {
                                                                goto jit_failure;
                                                    }
                                                }
index a018c31c2ee2ec3962fdbd83f4f5995e0cb11cf6..d894b50f1800ead60bacf3342c1394f582a88d23 100644 (file)
@@ -3724,6 +3724,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                        }
                                                } else {
                                                        int j;
+                                                       int may_throw = 0;
 
                                                        if (!zend_jit_return(&dasm_state, opline, op_array,
                                                                        op1_info, OP1_REG_ADDR())) {
@@ -3750,9 +3751,14 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                        if (!zend_jit_free_cv(&dasm_state, opline, op_array, info, j)) {
                                                                                goto jit_failure;
                                                                        }
+                                                                       if (info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_RESOURCE)) {
+                                                                               if (info & MAY_BE_RC1) {
+                                                                                       may_throw = 1;
+                                                                               }
+                                                                       }
                                                                }
                                                        }
-                                                       if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM])) {
+                                                       if (!zend_jit_leave_func(&dasm_state, opline, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM], may_throw)) {
                                                                goto jit_failure;
                                                        }
                                                }
index 0c8d847dec268e8e097623eb7f54596f008b15d7..a63db2ad9ae4ce1221dfbbf4c29696d0116a994a 100644 (file)
@@ -9986,7 +9986,7 @@ static int zend_jit_free_op(dasm_State **Dst, const zend_op *opline, /*const zen
        return 1;
 }
 
-static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info)
+static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info, int may_throw)
 {
        /* ZEND_CALL_FAKE_CLOSURE handled on slow path to eliminate check for ZEND_CALL_CLOSURE on fast path */
        |       mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)]
@@ -10055,13 +10055,20 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze
                 && (JIT_G(current_frame) && !TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) {
                        zend_jit_reset_opline(Dst, NULL);
                } else {
-                       // TODO: exception handling for tracing JIT ???
                        |       LOAD_OPLINE
                        |       ADD_IP sizeof(zend_op)
                }
 
                |8:
 
+               if ((trace->op != ZEND_JIT_TRACE_END ||
+                               trace->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) &&
+                                       may_throw) {
+                       |       // if (EG(exception))
+                       |       MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
+                       |       jne ->leave_throw_handler
+               }
+
                if (trace->op == ZEND_JIT_TRACE_BACK
                 && (!JIT_G(current_frame) || TRACE_FRAME_IS_UNKNOWN_RETURN(JIT_G(current_frame)))) {
                        const zend_op *next_opline = trace->opline;
@@ -10074,6 +10081,7 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze
                        } while (trace->op == ZEND_JIT_TRACE_INIT_CALL);
                        ZEND_ASSERT(trace->op == ZEND_JIT_TRACE_VM || trace->op == ZEND_JIT_TRACE_END);
                        next_opline = trace->opline;
+                       ZEND_ASSERT(next_opline != NULL);
                        current_frame = JIT_G(current_frame);
                        JIT_G(current_frame) = NULL;
                        exit_point = zend_jit_trace_get_exit_point(opline, NULL, trace, 0);
@@ -10082,7 +10090,6 @@ static int zend_jit_leave_func(dasm_State **Dst, const zend_op *opline, const ze
                        if (!exit_addr) {
                                return 0;
                        }
-                       |       // TODO: exception handling ???
                        if (trace->op == ZEND_JIT_TRACE_END
                         && trace->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) {
                                trace_info->flags |= ZEND_JIT_TRACE_LOOP;