From: Dmitry Stogov Date: Tue, 1 Sep 2020 09:24:11 +0000 (+0300) Subject: Fixed nested init fcall guards. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91d7e872e03ef7e7dbe7cbaf5d211cb52945b126;p=php Fixed nested init fcall guards. --- diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 0254c0daf8..f471321991 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -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) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index f5553d71be..d8ee688f0f 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -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; } } diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index dca5f97f04..729c64073d 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -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) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index dc01ce0c8d..e6a46ad09f 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -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)