Skip to content

Commit

Permalink
JIT: Eliminate useless EG(exception) checks after FETCH_DIM_*
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Oct 4, 2021
1 parent 493c91c commit 2c95c94
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 39 deletions.
7 changes: 2 additions & 5 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3689,8 +3689,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
}
if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op,
OP1_INFO(), OP1_REG_ADDR(), 0,
OP2_INFO(), RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
OP2_INFO(), RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
goto jit_failure;
}
goto done;
Expand All @@ -3705,9 +3704,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
break;
}
if (!zend_jit_fetch_dim(&dasm_state, opline,
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_REG_ADDR(), IS_UNKNOWN,
zend_may_throw_ex(opline, ssa_op, op_array, ssa, OP1_INFO(),
OP2_INFO()))) {
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_REG_ADDR(), IS_UNKNOWN)) {
goto jit_failure;
}
goto done;
Expand Down
44 changes: 38 additions & 6 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -10977,15 +10977,15 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
uint32_t op2_info,
uint32_t res_info,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
uint8_t dim_type)
{
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;
bool result_avoid_refcounting = 0;
uint32_t may_be_string = (opline->opcode != ZEND_FETCH_LIST_R) ? MAY_BE_STRING : 0;
int may_throw = 0;

orig_op1_addr = OP1_ADDR();
op2_addr = OP2_ADDR();
Expand Down Expand Up @@ -11079,6 +11079,10 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
}
| GET_ZVAL_LVAL ZREG_FCARG1, op1_addr, TMP1
if ((op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) ||
(opline->opcode != ZEND_FETCH_DIM_IS && JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE)) {
may_throw = 1;
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, (opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS, op1_info, op2_info, dim_type, res_exit_addr, not_found_exit_addr, exit_addr)) {
return 0;
}
Expand All @@ -11091,6 +11095,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (opline->opcode != ZEND_FETCH_LIST_R && (op1_info & MAY_BE_STRING)) {
may_throw = 1;
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_STRING))) {
if (exit_addr && !(op1_info & MAY_BE_OBJECT)) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_STRING, &exit_addr, ZREG_TMP1
Expand Down Expand Up @@ -11123,6 +11128,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (op1_info & MAY_BE_OBJECT) {
may_throw = 1;
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) {
if (exit_addr) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_OBJECT, &exit_addr, ZREG_TMP1
Expand Down Expand Up @@ -11156,6 +11162,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) {
| SET_EX_OPLINE opline, REG0
if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) {
may_throw = 1;
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
| LOAD_32BIT_VAL FCARG1w, opline->op1.var
Expand All @@ -11164,6 +11171,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (op2_info & MAY_BE_UNDEF) {
may_throw = 1;
| IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1, ZREG_TMP1
| LOAD_32BIT_VAL FCARG1w, opline->op2.var
| EXT_CALL zend_jit_undefined_op_helper, REG0
Expand All @@ -11174,6 +11182,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))
&& (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_STRING)))) {
if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) {
may_throw = 1;
if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
| LOAD_ZVAL_ADDR FCARG1x, orig_op1_addr
} else {
Expand Down Expand Up @@ -11285,9 +11294,19 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
#endif

| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
if ((op2_info & MAY_HAVE_DTOR) && (op2_info & MAY_BE_RC1)) {
may_throw = 1;
}
| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
}
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting) {
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
if ((op1_info & MAY_HAVE_DTOR) && (op1_info & MAY_BE_RC1)) {
may_throw = 1;
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
}
}

if (may_throw) {
Expand All @@ -11305,14 +11324,15 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
zend_jit_addr op1_addr,
uint32_t op2_info,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
uint8_t dim_type)
{
zend_jit_addr op2_addr;
int may_throw = 0;

op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;

if (op1_info & MAY_BE_REF) {
may_throw = 1;
| LOAD_ZVAL_ADDR FCARG1x, op1_addr
| IF_NOT_Z_TYPE FCARG1x, IS_REFERENCE, >1, TMP1w
| GET_Z_PTR FCARG2x, FCARG1x
Expand Down Expand Up @@ -11354,6 +11374,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}
if ((op1_info & MAY_BE_UNDEF)
&& opline->opcode == ZEND_FETCH_DIM_RW) {
may_throw = 1;
if (op1_info & MAY_BE_NULL) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1
}
Expand Down Expand Up @@ -11381,6 +11402,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) {
|6:
if (opline->op2_type == IS_UNUSED) {
may_throw = 1;
| // var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
| LOAD_ADDR_ZTS FCARG2x, executor_globals, uninitialized_zval
| EXT_CALL zend_hash_next_index_insert, REG0
Expand All @@ -11405,6 +11427,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
type = BP_VAR_W;
break;
case ZEND_FETCH_DIM_RW:
may_throw = 1;
type = BP_VAR_RW;
break;
case ZEND_FETCH_DIM_UNSET:
Expand All @@ -11414,6 +11437,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
ZEND_UNREACHABLE();
}

if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) {
may_throw = 1;
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, dim_type, NULL, NULL, NULL)) {
return 0;
}
Expand All @@ -11433,6 +11459,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}

if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_ARRAY))) {
may_throw = 1;
if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) {
|.cold_code
|7:
Expand Down Expand Up @@ -11479,6 +11506,11 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}
#endif

if ((opline->op2_type & (IS_TMP_VAR|IS_VAR))
&& (op2_info & MAY_HAVE_DTOR)
&& (op2_info & MAY_BE_RC1)) {
may_throw = 1;
}
|8:
| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2

Expand Down
24 changes: 2 additions & 22 deletions ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -5405,20 +5405,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
}
if (!zend_jit_fetch_dim_read(&dasm_state, opline, ssa, ssa_op,
op1_info, op1_addr, avoid_refcounting,
op2_info, res_info, RES_REG_ADDR(), val_type,
(
(op1_info & MAY_BE_ANY) != MAY_BE_ARRAY ||
(op2_info & (MAY_BE_ANY - (MAY_BE_LONG|MAY_BE_STRING))) != 0 ||
((op1_info & MAY_BE_UNDEF) != 0 &&
opline->opcode != ZEND_FETCH_DIM_IS) ||
(opline->opcode != ZEND_FETCH_LIST_R &&
(opline->op1_type & (IS_TMP_VAR|IS_VAR)) != 0 &&
(op1_info & MAY_BE_RC1) &&
(op1_info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) != 0) ||
(op2_info & MAY_BE_UNDEF) != 0 ||
((opline->op2_type & (IS_TMP_VAR|IS_VAR)) != 0 &&
(op2_info & MAY_BE_RC1) &&
(op2_info & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) != 0)))) {
op2_info, res_info, RES_REG_ADDR(), val_type)) {
goto jit_failure;
}
goto done;
Expand Down Expand Up @@ -5461,14 +5448,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
CHECK_OP2_TRACE_TYPE();
op1_def_info = OP1_DEF_INFO();
if (!zend_jit_fetch_dim(&dasm_state, opline,
op1_info, op1_addr, op2_info, RES_REG_ADDR(), val_type,
(opline->opcode == ZEND_FETCH_DIM_RW
|| opline->op2_type == IS_UNUSED
|| (op1_info & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
|| (op2_info & (MAY_BE_UNDEF|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_OBJECT))
|| (opline->op1_type == IS_VAR
&& (op1_info & MAY_BE_UNDEF)
&& !ssa->var_info[ssa_op->op1_use].indirect_reference)))) {
op1_info, op1_addr, op2_info, RES_REG_ADDR(), val_type)) {
goto jit_failure;
}
if (ssa_op->result_def > 0
Expand Down
44 changes: 38 additions & 6 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -11631,15 +11631,15 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
uint32_t op2_info,
uint32_t res_info,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
uint8_t dim_type)
{
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;
bool result_avoid_refcounting = 0;
uint32_t may_be_string = (opline->opcode != ZEND_FETCH_LIST_R) ? MAY_BE_STRING : 0;
int may_throw = 0;

orig_op1_addr = OP1_ADDR();
op2_addr = OP2_ADDR();
Expand Down Expand Up @@ -11733,6 +11733,10 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
}
| GET_ZVAL_LVAL ZREG_FCARG1, op1_addr
if ((op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) ||
(opline->opcode != ZEND_FETCH_DIM_IS && JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE)) {
may_throw = 1;
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, (opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS, op1_info, op2_info, dim_type, res_exit_addr, not_found_exit_addr, exit_addr)) {
return 0;
}
Expand All @@ -11745,6 +11749,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (opline->opcode != ZEND_FETCH_LIST_R && (op1_info & MAY_BE_STRING)) {
may_throw = 1;
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_STRING))) {
if (exit_addr && !(op1_info & MAY_BE_OBJECT)) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_STRING, &exit_addr
Expand Down Expand Up @@ -11785,6 +11790,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (op1_info & MAY_BE_OBJECT) {
may_throw = 1;
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) {
if (exit_addr) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_OBJECT, &exit_addr
Expand Down Expand Up @@ -11826,6 +11832,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) {
| SET_EX_OPLINE opline, r0
if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) {
may_throw = 1;
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
| mov FCARG1d, opline->op1.var
Expand All @@ -11834,6 +11841,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}

if (op2_info & MAY_BE_UNDEF) {
may_throw = 1;
| IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1
| mov FCARG1d, opline->op2.var
| EXT_CALL zend_jit_undefined_op_helper, r0
Expand All @@ -11844,6 +11852,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))
&& (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_STRING)))) {
if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) {
may_throw = 1;
if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
| LOAD_ZVAL_ADDR FCARG1a, orig_op1_addr
} else {
Expand Down Expand Up @@ -11954,9 +11963,19 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
#endif

| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
if ((op2_info & MAY_HAVE_DTOR) && (op2_info & MAY_BE_RC1)) {
may_throw = 1;
}
| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
}
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting) {
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
if ((op1_info & MAY_HAVE_DTOR) && (op1_info & MAY_BE_RC1)) {
may_throw = 1;
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
}
}

if (may_throw) {
Expand All @@ -11974,14 +11993,15 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
zend_jit_addr op1_addr,
uint32_t op2_info,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
uint8_t dim_type)
{
zend_jit_addr op2_addr;
int may_throw = 0;

op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;

if (op1_info & MAY_BE_REF) {
may_throw = 1;
| LOAD_ZVAL_ADDR FCARG1a, op1_addr
| IF_NOT_Z_TYPE FCARG1a, IS_REFERENCE, >1
| GET_Z_PTR FCARG2a, FCARG1a
Expand Down Expand Up @@ -12022,6 +12042,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}
if ((op1_info & MAY_BE_UNDEF)
&& opline->opcode == ZEND_FETCH_DIM_RW) {
may_throw = 1;
if (op1_info & MAY_BE_NULL) {
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1
}
Expand All @@ -12048,6 +12069,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) {
|6:
if (opline->op2_type == IS_UNUSED) {
may_throw = 1;
| // var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
| LOAD_ADDR_ZTS FCARG2a, executor_globals, uninitialized_zval
| EXT_CALL zend_hash_next_index_insert, r0
Expand All @@ -12073,6 +12095,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
type = BP_VAR_W;
break;
case ZEND_FETCH_DIM_RW:
may_throw = 1;
type = BP_VAR_RW;
break;
case ZEND_FETCH_DIM_UNSET:
Expand All @@ -12082,6 +12105,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
ZEND_UNREACHABLE();
}

if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) {
may_throw = 1;
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, dim_type, NULL, NULL, NULL)) {
return 0;
}
Expand All @@ -12101,6 +12127,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}

if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_ARRAY))) {
may_throw = 1;
if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) {
|.cold_code
|7:
Expand Down Expand Up @@ -12155,6 +12182,11 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
}
#endif

if ((opline->op2_type & (IS_TMP_VAR|IS_VAR))
&& (op2_info & MAY_HAVE_DTOR)
&& (op2_info & MAY_BE_RC1)) {
may_throw = 1;
}
|8:
| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline

Expand Down

0 comments on commit 2c95c94

Please sign in to comment.