Skip to content

Commit

Permalink
JIT: Move unusual checks for IS_REFERENCE to cold paths.
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Sep 20, 2021
1 parent 1dcc0ff commit ac1dd73
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 27 deletions.
6 changes: 3 additions & 3 deletions ext/opcache/jit/zend_jit.c
Expand Up @@ -3684,7 +3684,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(),
OP2_INFO(), RES_INFO(), RES_REG_ADDR(), IS_UNKNOWN,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
Expand All @@ -3700,7 +3700,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(),
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()))) {
goto jit_failure;
Expand Down Expand Up @@ -3731,7 +3731,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
}
if (!zend_jit_isset_isempty_dim(&dasm_state, opline,
OP1_INFO(), OP1_REG_ADDR(), 0,
OP2_INFO(),
OP2_INFO(), IS_UNKNOWN,
zend_may_throw(opline, ssa_op, op_array, ssa),
smart_branch_opcode, target_label, target_label2,
NULL)) {
Expand Down
57 changes: 46 additions & 11 deletions ext/opcache/jit/zend_jit_arm64.dasc
Expand Up @@ -10895,6 +10895,7 @@ 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)
{
zend_jit_addr orig_op1_addr, op2_addr;
Expand Down Expand Up @@ -10996,7 +10997,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
}
| GET_ZVAL_LVAL ZREG_FCARG1, op1_addr, TMP1
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, IS_UNKNOWN, res_exit_addr, not_found_exit_addr, exit_addr)) {
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 Down Expand Up @@ -11120,15 +11121,47 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
|8:
if (res_exit_addr) {
uint32_t type = concrete_type(res_info);
if (op1_info & MAY_BE_ARRAY_OF_REF) {
| ZVAL_DEREF REG0, MAY_BE_REF, TMP1w
}
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, &res_exit_addr, ZREG_TMP1
if ((op1_info & MAY_BE_ARRAY_OF_REF)
&& dim_type != IS_UNKNOWN
&& dim_type != IS_REFERENCE) {
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, >1, ZREG_TMP1
|.cold_code
|1:
| IF_NOT_ZVAL_TYPE val_addr, IS_REFERENCE, &res_exit_addr, ZREG_TMP1
| GET_Z_PTR REG0, REG0
| add REG0, REG0, #offsetof(zend_reference, val)
| IF_ZVAL_TYPE val_addr, type, >1, ZREG_TMP1
| b &res_exit_addr
|.code
|1:
} else {
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
| GET_LOW_8BITS TMP1w, REG2w
| IF_NOT_TYPE TMP1w, type, >1
|.cold_code
|1:
| IF_NOT_TYPE TMP1w, IS_REFERENCE, &res_exit_addr
| GET_Z_PTR REG0, REG0
| add REG0, REG0, #offsetof(zend_reference, val)
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
| GET_LOW_8BITS TMP1w, REG2w
| IF_TYPE TMP1w, type, >1
| b &res_exit_addr
|.code
|1:
}
} else {
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
| GET_LOW_8BITS TMP1w, REG2w
| IF_NOT_TYPE TMP1w, type, &res_exit_addr
if (op1_info & MAY_BE_ARRAY_OF_REF) {
| ZVAL_DEREF REG0, MAY_BE_REF, TMP1w
}
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, &res_exit_addr, ZREG_TMP1
} else {
| GET_ZVAL_TYPE_INFO REG2w, val_addr, TMP1
| GET_LOW_8BITS TMP1w, REG2w
| IF_NOT_TYPE TMP1w, type, &res_exit_addr
}
}
| // ZVAL_COPY
|7:
Expand Down Expand Up @@ -11190,6 +11223,7 @@ 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)
{
zend_jit_addr op2_addr;
Expand Down Expand Up @@ -11298,7 +11332,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
ZEND_UNREACHABLE();
}

if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, IS_UNKNOWN, NULL, NULL, NULL)) {
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, dim_type, NULL, NULL, NULL)) {
return 0;
}

Expand Down Expand Up @@ -11380,6 +11414,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
zend_jit_addr op1_addr,
bool op1_avoid_refcounting,
uint32_t op2_info,
uint8_t dim_type,
int may_throw,
zend_uchar smart_branch_opcode,
uint32_t target_label,
Expand Down Expand Up @@ -11419,7 +11454,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
not_found_exit_addr = exit_addr;
}
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_JIT_IS, op1_info, op2_info, IS_UNKNOWN, found_exit_addr, not_found_exit_addr, NULL)) {
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_JIT_IS, op1_info, op2_info, dim_type, found_exit_addr, not_found_exit_addr, NULL)) {
return 0;
}

Expand Down
6 changes: 3 additions & 3 deletions ext/opcache/jit/zend_jit_trace.c
Expand Up @@ -5338,7 +5338,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(),
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 ||
Expand Down Expand Up @@ -5394,7 +5394,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(),
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))
Expand Down Expand Up @@ -5481,7 +5481,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
}
if (!zend_jit_isset_isempty_dim(&dasm_state, opline,
op1_info, op1_addr, avoid_refcounting,
op2_info,
op2_info, val_type,
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info),
smart_branch_opcode, -1, -1,
exit_addr)) {
Expand Down
54 changes: 44 additions & 10 deletions ext/opcache/jit/zend_jit_x86.dasc
Expand Up @@ -11532,6 +11532,7 @@ 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)
{
zend_jit_addr orig_op1_addr, op2_addr;
Expand Down Expand Up @@ -11633,7 +11634,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
}
| GET_ZVAL_LVAL ZREG_FCARG1, op1_addr
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, IS_UNKNOWN, res_exit_addr, not_found_exit_addr, exit_addr)) {
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 Down Expand Up @@ -11774,15 +11775,46 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
if (res_exit_addr) {
zend_uchar type = concrete_type(res_info);

if (op1_info & MAY_BE_ARRAY_OF_REF) {
| ZVAL_DEREF r0, MAY_BE_REF
}
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, &res_exit_addr
if ((op1_info & MAY_BE_ARRAY_OF_REF)
&& dim_type != IS_UNKNOWN
&& dim_type != IS_REFERENCE) {
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, >1
|.cold_code
|1:
| IF_NOT_ZVAL_TYPE val_addr, IS_REFERENCE, &res_exit_addr
| GET_Z_PTR r0, r0
| add r0, offsetof(zend_reference, val)
| IF_ZVAL_TYPE val_addr, type, >1
| jmp &res_exit_addr
|.code
|1:
} else {
| GET_ZVAL_TYPE_INFO edx, val_addr
| IF_NOT_TYPE dl, type, >1
|.cold_code
|1:
| IF_NOT_TYPE dl, IS_REFERENCE, &res_exit_addr
| GET_Z_PTR r0, r0
| add r0, offsetof(zend_reference, val)
| GET_ZVAL_TYPE_INFO edx, val_addr
| IF_TYPE dl, type, >1
| jmp &res_exit_addr
|.code
|1:
}
} else {
| GET_ZVAL_TYPE_INFO edx, val_addr
| IF_NOT_TYPE dl, type, &res_exit_addr
if (op1_info & MAY_BE_ARRAY_OF_REF) {
| ZVAL_DEREF r0, MAY_BE_REF
}
if (type < IS_STRING) {
| IF_NOT_ZVAL_TYPE val_addr, type, &res_exit_addr
} else {
| GET_ZVAL_TYPE_INFO edx, val_addr
| IF_NOT_TYPE dl, type, &res_exit_addr
}
}

| // ZVAL_COPY
|7:
| ZVAL_COPY_VALUE_V res_addr, -1, val_addr, res_info, ZREG_R0, ZREG_R1
Expand Down Expand Up @@ -11843,6 +11875,7 @@ 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)
{
zend_jit_addr op2_addr;
Expand Down Expand Up @@ -11950,7 +11983,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
ZEND_UNREACHABLE();
}

if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, IS_UNKNOWN, NULL, NULL, NULL)) {
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, type, op1_info, op2_info, dim_type, NULL, NULL, NULL)) {
return 0;
}

Expand Down Expand Up @@ -12041,6 +12074,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
zend_jit_addr op1_addr,
bool op1_avoid_refcounting,
uint32_t op2_info,
uint8_t dim_type,
int may_throw,
zend_uchar smart_branch_opcode,
uint32_t target_label,
Expand Down Expand Up @@ -12080,7 +12114,7 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
not_found_exit_addr = exit_addr;
}
}
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_JIT_IS, op1_info, op2_info, IS_UNKNOWN, found_exit_addr, not_found_exit_addr, NULL)) {
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_JIT_IS, op1_info, op2_info, dim_type, found_exit_addr, not_found_exit_addr, NULL)) {
return 0;
}

Expand Down

0 comments on commit ac1dd73

Please sign in to comment.