]> granicus.if.org Git - php/commitdiff
Fixed nested init fcall guards.
authorDmitry Stogov <dmitry@zend.com>
Tue, 1 Sep 2020 09:24:11 +0000 (12:24 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 1 Sep 2020 09:24:11 +0000 (12:24 +0300)
ext/opcache/jit/zend_jit_internal.h
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_vm_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index 0254c0daf8af7a9f4e25a4429ffdac65d084d88a..f471321991fbdc17c1559e7e47d6c52fd0485478 100644 (file)
@@ -256,6 +256,15 @@ typedef enum _zend_jit_trace_op {
 #define ZEND_JIT_TRACE_MAX_SSA_VAR       0x7ffffe
 #define ZEND_JIT_TRACE_SSA_VAR_SHIFT     9
 
+#define ZEND_JIT_TRACE_FAKE_LEVEL_MASK   0xffff0000
+#define ZEND_JIT_TRACE_FAKE_LEVEL_SHIFT  16
+
+#define ZEND_JIT_TRACE_FAKE_LEVEL(info) \
+       (((info) & ZEND_JIT_TRACE_FAKE_LEVEL_MASK) >> ZEND_JIT_TRACE_FAKE_LEVEL_SHIFT)
+
+#define ZEND_JIT_TRACE_FAKE_INFO(level) \
+       (((level) << ZEND_JIT_TRACE_FAKE_LEVEL_SHIFT) | ZEND_JIT_TRACE_FAKE_INIT_CALL)
+
 #define ZEND_JIT_TRACE_SET_FIRST_SSA_VAR(_info, var) do { \
                _info |= (var << ZEND_JIT_TRACE_SSA_VAR_SHIFT); \
        } while (0)
index f5553d71be466cdad0b839fc652abe3404308680..d8ee688f0f5aae70aac5bf507c8bb62127c582b5 100644 (file)
@@ -4506,7 +4506,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                        goto jit_failure;
                                                }
                                                if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) {
-                                                       if (!zend_jit_init_fcall_guard(&dasm_state, (p+1)->func, opline+1)) {
+                                                       if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
                                                                goto jit_failure;
                                                        }
                                                }
@@ -4518,7 +4518,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                if ((opline->op1_type != IS_CONST
                                                  || opline->op2_type != IS_CONST)
                                                 && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) {
-                                                       if (!zend_jit_init_fcall_guard(&dasm_state, (p+1)->func, opline+1)) {
+                                                       if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
                                                                goto jit_failure;
                                                        }
                                                }
@@ -4529,7 +4529,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                }
                                                if (opline->op2_type != IS_CONST
                                                 && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) {
-                                                       if (!zend_jit_init_fcall_guard(&dasm_state, (p+1)->func, opline+1)) {
+                                                       if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
                                                                goto jit_failure;
                                                        }
                                                }
@@ -4541,7 +4541,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                if (opline->op1_type != IS_CONST
                                                 && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) {
                                                        SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_OBJECT);
-                                                       if (!zend_jit_init_fcall_guard(&dasm_state, (p+1)->func, opline+1)) {
+                                                       if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) {
                                                                goto jit_failure;
                                                        }
                                                }
@@ -4946,7 +4946,8 @@ done:
                                                        opline = q->opline;
                                                        ZEND_ASSERT(opline != NULL);
                                                }
-                                               if (!zend_jit_init_fcall_guard(&dasm_state, p->func, opline)) {
+                                               if (!zend_jit_init_fcall_guard(&dasm_state,
+                                                               ZEND_JIT_TRACE_FAKE_LEVEL(p->info), p->func, opline)) {
                                                        goto jit_failure;
                                                }
                                        }
index dca5f97f04b4217acf1c8ecd67024f4ca99e6027..729c64073d5e82b3d06cddc89b702fd4df5fde61 100644 (file)
@@ -467,7 +467,7 @@ static int zend_jit_trace_bad_loop_exit(const zend_op *opline)
        return 0;
 }
 
-static int zend_jit_trace_record_fake_init_call_ex(zend_execute_data *call, zend_jit_trace_rec *trace_buffer, int idx, zend_bool is_megamorphic, uint32_t *megamorphic, uint32_t level, uint32_t *call_level)
+static int zend_jit_trace_record_fake_init_call_ex(zend_execute_data *call, zend_jit_trace_rec *trace_buffer, int idx, zend_bool is_megamorphic, uint32_t *megamorphic, uint32_t level, uint32_t init_level, uint32_t *call_level)
 {
        zend_jit_trace_stop stop ZEND_ATTRIBUTE_UNUSED = ZEND_JIT_TRACE_STOP_ERROR;
 
@@ -476,7 +476,7 @@ static int zend_jit_trace_record_fake_init_call_ex(zend_execute_data *call, zend
                zend_jit_op_array_trace_extension *jit_extension;
 
                if (call->prev_execute_data) {
-                       idx = zend_jit_trace_record_fake_init_call_ex(call->prev_execute_data, trace_buffer, idx, is_megamorphic, megamorphic, level, call_level);
+                       idx = zend_jit_trace_record_fake_init_call_ex(call->prev_execute_data, trace_buffer, idx, is_megamorphic, megamorphic, level, init_level + 1, call_level);
                        if (idx < 0) {
                                return idx;
                        }
@@ -510,7 +510,7 @@ static int zend_jit_trace_record_fake_init_call_ex(zend_execute_data *call, zend
                        *megamorphic &= ~(1 << (level + *call_level));
                }
                (*call_level)++;
-               TRACE_RECORD(ZEND_JIT_TRACE_INIT_CALL, ZEND_JIT_TRACE_FAKE_INIT_CALL, func);
+               TRACE_RECORD(ZEND_JIT_TRACE_INIT_CALL, ZEND_JIT_TRACE_FAKE_INFO(init_level), func);
        } while (0);
        return idx;
 }
@@ -519,7 +519,7 @@ static int zend_jit_trace_record_fake_init_call(zend_execute_data *call, zend_ji
 {
        uint32_t call_level = 0;
 
-       return zend_jit_trace_record_fake_init_call_ex(call, trace_buffer, idx, is_megamorphic, megamorphic, level, &call_level);
+       return zend_jit_trace_record_fake_init_call_ex(call, trace_buffer, idx, is_megamorphic, megamorphic, level, 0, &call_level);
 }
 
 static int zend_jit_trace_call_level(const zend_execute_data *call)
index dc01ce0c8d9d825b491c05c893d5a4bfa0647803..e6a46ad09fb8c87bd927f1ac721c5dea6a69bc8a 100644 (file)
@@ -8474,7 +8474,7 @@ static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, cons
        }
 }
 
-static int zend_jit_init_fcall_guard(dasm_State **Dst, const zend_function *func, const zend_op *to_opline)
+static int zend_jit_init_fcall_guard(dasm_State **Dst, uint32_t level, const zend_function *func, const zend_op *to_opline)
 {
        int32_t exit_point;
        const void *exit_addr;
@@ -8500,14 +8500,19 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, const zend_function *func
                return 0;
        }
 
+       |       // call = EX(call);
+       |       mov r1, EX->call
+       while (level > 0) {
+               |       mov r1, EX:r1->prev_execute_data
+               level--;
+       }
+
        if (func->type == ZEND_USER_FUNCTION &&
            (!(func->common.fn_flags & ZEND_ACC_IMMUTABLE) ||
             (func->common.fn_flags & ZEND_ACC_CLOSURE) ||
             !func->common.function_name)) {
                const zend_op *opcodes = func->op_array.opcodes;
 
-               |       // call = EX(call);
-               |       mov r1, EX->call
                |       mov r1, aword EX:r1->func
                |   .if X64
                ||              if (!IS_SIGNED_32BIT(opcodes)) {
@@ -8521,8 +8526,6 @@ static int zend_jit_init_fcall_guard(dasm_State **Dst, const zend_function *func
                |       .endif
                |       jne &exit_addr
        } else {
-               |       // call = EX(call);
-               |       mov r1, EX->call
                |   .if X64
                ||              if (!IS_SIGNED_32BIT(func)) {
                |                       mov64 r0, ((ptrdiff_t)func)