From d3845378591869e781b8b9c4c1b8e0823c402799 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 25 Aug 2020 11:37:30 +0300 Subject: [PATCH] Move AVOID_REFCOUNTING type info flag into a separate bit --- ext/opcache/Optimizer/zend_inference.h | 1 - ext/opcache/Optimizer/zend_ssa.h | 1 + ext/opcache/jit/zend_jit.c | 8 +-- ext/opcache/jit/zend_jit_trace.c | 15 ++++-- ext/opcache/jit/zend_jit_x86.dasc | 71 +++++++++++++++++++------- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/ext/opcache/Optimizer/zend_inference.h b/ext/opcache/Optimizer/zend_inference.h index 3d8a0a0dcf..0708d5df94 100644 --- a/ext/opcache/Optimizer/zend_inference.h +++ b/ext/opcache/Optimizer/zend_inference.h @@ -26,7 +26,6 @@ /* Bitmask for type inference (zend_ssa_var_info.type) */ #include "zend_type_info.h" -#define AVOID_REFCOUNTING (1<<26) /* avoid reference counting */ #define MAY_BE_CLASS_GUARD (1<<27) /* needs class guard */ #define MAY_BE_GUARD (1<<28) /* needs type guard */ #define MAY_BE_IN_REG (1<<29) /* value allocated in CPU register */ diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h index 7d065ac42a..e7190da3f8 100644 --- a/ext/opcache/Optimizer/zend_ssa.h +++ b/ext/opcache/Optimizer/zend_ssa.h @@ -128,6 +128,7 @@ typedef struct _zend_ssa_var_info { unsigned int recursive : 1; unsigned int use_as_double : 1; unsigned int delayed_fetch_this : 1; + unsigned int avoid_refcounting : 1; } zend_ssa_var_info; typedef struct _zend_ssa { diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 2956591490..5073894dbe 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2817,7 +2817,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op, - OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_INFO(), RES_REG_ADDR(), + OP1_INFO(), OP1_REG_ADDR(), 0, + OP2_INFO(), RES_INFO(), RES_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } @@ -2846,7 +2847,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op target_label = target_label2 = (uint32_t)-1; } if (!zend_jit_isset_isempty_dim(&dasm_state, opline, - OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), + OP1_INFO(), OP1_REG_ADDR(), 0, + OP2_INFO(), zend_may_throw(opline, ssa_op, op_array, ssa), smart_branch_opcode, target_label, target_label2, NULL)) { @@ -2886,7 +2888,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } } if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op, - op1_info, op1_addr, 0, ce, ce_is_instanceof, 0, NULL, + op1_info, op1_addr, 0, ce, ce_is_instanceof, 0, 0, NULL, zend_may_throw(opline, ssa_op, op_array, ssa))) { goto jit_failure; } diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 6ad0800036..9e40661b0c 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -2895,6 +2895,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par zend_class_entry *ce; zend_bool ce_is_instanceof; zend_bool delayed_fetch_this = 0; + zend_bool avoid_refcounting = 0; uint32_t i; zend_jit_trace_stack_frame *frame, *top, *call; zend_jit_trace_stack *stack; @@ -4011,7 +4012,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par CHECK_OP2_TRACE_TYPE(); res_info = RES_INFO(); if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op, - op1_info, op1_addr, op2_info, res_info, RES_REG_ADDR(), + op1_info, op1_addr, ssa->var_info[ssa_op->op1_use].avoid_refcounting, + op2_info, res_info, RES_REG_ADDR(), ( (op1_info & MAY_BE_ANY) != MAY_BE_ARRAY || (op2_info & (MAY_BE_ANY - (MAY_BE_LONG|MAY_BE_STRING))) != 0 || @@ -4052,7 +4054,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (ra) { zend_jit_trace_clenup_stack(stack, opline, ssa_op, ssa, ra); } - if (op1_info & AVOID_REFCOUNTING) { + if (ssa->var_info[ssa_op->op1_use].avoid_refcounting) { /* Temporary reset ZREG_ZVAL_TRY_ADDREF */ zend_jit_trace_stack *stack = JIT_G(current_frame)->stack; uint32_t old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var)); @@ -4073,7 +4075,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par exit_addr = NULL; } if (!zend_jit_isset_isempty_dim(&dasm_state, opline, - op1_info, op1_addr, op2_info, + op1_info, op1_addr, ssa->var_info[ssa_op->op1_use].avoid_refcounting, + op2_info, zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info), smart_branch_opcode, -1, -1, exit_addr)) { @@ -4092,6 +4095,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par case ZEND_FETCH_OBJ_IS: case ZEND_FETCH_OBJ_W: delayed_fetch_this = 0; + avoid_refcounting = 0; if (opline->op2_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { @@ -4140,11 +4144,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } if (ssa_op->op1_use >= 0) { delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this; + avoid_refcounting = ssa->var_info[ssa_op->op1_use].avoid_refcounting; } } if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op, op1_info, op1_addr, op1_indirect, ce, ce_is_instanceof, - delayed_fetch_this, op1_ce, + delayed_fetch_this, avoid_refcounting, op1_ce, zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, MAY_BE_STRING))) { goto jit_failure; } @@ -4353,7 +4358,7 @@ done: if (opline->opcode == ZEND_FETCH_THIS && delayed_fetch_this) { SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_THIS); - } else if (ssa->var_info[ssa_op->result_def].type & AVOID_REFCOUNTING) { + } else if (ssa->var_info[ssa_op->result_def].avoid_refcounting) { SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_ZVAL_TRY_ADDREF); } else if (ra && ra[ssa_op->result_def]) { SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ra[ssa_op->result_def]->reg); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 49459267e7..84c7c09128 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -10479,12 +10479,23 @@ static zend_bool zend_jit_may_avoid_refcounting(const zend_op *opline) return 0; } -static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t res_info, zend_jit_addr res_addr, int may_throw) +static int zend_jit_fetch_dim_read(dasm_State **Dst, + const zend_op *opline, + zend_ssa *ssa, + const zend_ssa_op *ssa_op, + uint32_t op1_info, + zend_jit_addr op1_addr, + zend_bool op1_avoid_refcounting, + uint32_t op2_info, + uint32_t res_info, + zend_jit_addr res_addr, + int may_throw) { zend_jit_addr orig_op1_addr, op2_addr; const void *exit_addr = NULL; const void *not_found_exit_addr = NULL; const void *res_exit_addr = NULL; + zend_bool result_avoid_refcounting = 0; orig_op1_addr = OP1_ADDR(); op2_addr = OP2_ADDR(); @@ -10498,7 +10509,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend } } - if (op1_info & AVOID_REFCOUNTING) { + if (op1_avoid_refcounting) { SET_STACK_REG(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE); } @@ -10512,7 +10523,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend int32_t exit_point; if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) - && !(op1_info & AVOID_REFCOUNTING)) { + && !op1_avoid_refcounting) { flags |= ZEND_JIT_EXIT_FREE_OP1; } if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) @@ -10524,8 +10535,8 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend && (ssa_op+1)->op1_use == ssa_op->result_def && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG))) && zend_jit_may_avoid_refcounting(opline+1)) { - res_info |= AVOID_REFCOUNTING; - ssa->var_info[ssa_op->result_def].type |= AVOID_REFCOUNTING; + result_avoid_refcounting = 1; + ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } if (!(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG)))) { @@ -10722,7 +10733,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend | SET_ZVAL_TYPE_INFO res_addr, type } else { | SET_ZVAL_TYPE_INFO res_addr, edx - if (!(res_info & AVOID_REFCOUNTING)) { + if (!result_avoid_refcounting) { | TRY_ADDREF res_info, dh, r1 } } @@ -10751,7 +10762,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend #endif | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline - if (!(op1_info & AVOID_REFCOUNTING)) { + if (!op1_avoid_refcounting) { | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline } @@ -10764,7 +10775,17 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, const zend_op *opline, zend return 1; } -static int zend_jit_isset_isempty_dim(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, int may_throw, zend_uchar smart_branch_opcode, uint32_t target_label, uint32_t target_label2, const void *exit_addr) +static int zend_jit_isset_isempty_dim(dasm_State **Dst, + const zend_op *opline, + uint32_t op1_info, + zend_jit_addr op1_addr, + zend_bool op1_avoid_refcounting, + uint32_t op2_info, + int may_throw, + zend_uchar smart_branch_opcode, + uint32_t target_label, + uint32_t target_label2, + const void *exit_addr) { zend_jit_addr op2_addr, res_addr; @@ -10791,7 +10812,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst, const zend_op *opline, u if (exit_addr && !(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_ARRAY)) && !may_throw - && (!(opline->op1_type & (IS_TMP_VAR|IS_VAR)) || (op1_info & AVOID_REFCOUNTING)) + && (!(opline->op1_type & (IS_TMP_VAR|IS_VAR)) || op1_avoid_refcounting) && (!(opline->op2_type & (IS_TMP_VAR|IS_VAR)) || !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_LONG)))) { if (smart_branch_opcode == ZEND_JMPNZ) { found_exit_addr = exit_addr; @@ -10859,7 +10880,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst, const zend_op *opline, u |8: | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline - if (!(op1_info & AVOID_REFCOUNTING)) { + if (!op1_avoid_refcounting) { | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline } if (may_throw) { @@ -10895,7 +10916,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst, const zend_op *opline, u |9: // not found | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline - if (!(op1_info & AVOID_REFCOUNTING)) { + if (!op1_avoid_refcounting) { | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline } if (may_throw) { @@ -11320,7 +11341,20 @@ static int zend_jit_class_guard(dasm_State **Dst, const zend_op *opline, zend_cl return 1; } -static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, zend_bool op1_indirect, zend_class_entry *ce, zend_bool ce_is_instanceof, zend_bool use_this, zend_class_entry *trace_ce, int may_throw) +static int zend_jit_fetch_obj(dasm_State **Dst, + const zend_op *opline, + const zend_op_array *op_array, + zend_ssa *ssa, + const zend_ssa_op *ssa_op, + uint32_t op1_info, + zend_jit_addr op1_addr, + zend_bool op1_indirect, + zend_class_entry *ce, + zend_bool ce_is_instanceof, + zend_bool use_this, + zend_bool op1_avoid_refcounting, + zend_class_entry *trace_ce, + int may_throw) { zval *member; zend_property_info *prop_info; @@ -11494,7 +11528,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen } } } - if (op1_info & AVOID_REFCOUNTING) { + if (op1_avoid_refcounting) { SET_STACK_REG(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE); } @@ -11506,6 +11540,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen | SET_ZVAL_TYPE_INFO res_addr, IS_INDIRECT } else { uint32_t res_info = RES_INFO(); + zend_bool result_avoid_refcounting = 0; if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info) { uint32_t flags = 0; @@ -11518,7 +11553,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this - && !(op1_info & AVOID_REFCOUNTING)) { + && !op1_avoid_refcounting) { flags = ZEND_JIT_EXIT_FREE_OP1; } @@ -11528,8 +11563,8 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def && zend_jit_may_avoid_refcounting(opline+1)) { - res_info |= AVOID_REFCOUNTING; - ssa->var_info[ssa_op->result_def].type |= AVOID_REFCOUNTING; + result_avoid_refcounting = 1; + ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var)); @@ -11564,7 +11599,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen | SET_ZVAL_TYPE_INFO res_addr, type } else { | SET_ZVAL_TYPE_INFO res_addr, edx - if (!(res_info & AVOID_REFCOUNTING)) { + if (!result_avoid_refcounting) { | TRY_ADDREF res_info, dh, r1 } } @@ -11652,7 +11687,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen | SAVE_VALID_OPLINE opline, r0 | EXT_CALL zend_jit_extract_helper, r0 |1: - } else if (!(op1_info & AVOID_REFCOUNTING)) { + } else if (!op1_avoid_refcounting) { | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline } } -- 2.40.0