Skip to content

Commit

Permalink
JIT: Allow register allocation for result of STRLEN and COUNT instruc…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
dstogov committed Sep 30, 2021
1 parent 80860ba commit 7be7ec3
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 38 deletions.
4 changes: 2 additions & 2 deletions ext/opcache/jit/zend_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -3827,7 +3827,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
break;
}
if (!zend_jit_strlen(&dasm_state, opline, op1_info, OP1_REG_ADDR())) {
if (!zend_jit_strlen(&dasm_state, opline, op1_info, OP1_REG_ADDR(), RES_REG_ADDR())) {
goto jit_failure;
}
goto done;
Expand All @@ -3836,7 +3836,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
break;
}
if (!zend_jit_count(&dasm_state, opline, op1_info, OP1_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) {
if (!zend_jit_count(&dasm_state, opline, op1_info, OP1_REG_ADDR(), RES_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
goto done;
Expand Down
63 changes: 46 additions & 17 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -13563,10 +13563,8 @@ static int zend_jit_echo(dasm_State **Dst, const zend_op *opline, uint32_t op1_i
return 1;
}

static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr)
static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr)
{
zend_jit_addr res_addr = RES_ADDR();

if (opline->op1_type == IS_CONST) {
zval *zv;
size_t len;
Expand All @@ -13576,23 +13574,33 @@ static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1
len = Z_STRLEN_P(zv);

| SET_ZVAL_LVAL res_addr, len, TMP1, TMP2
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);

| GET_ZVAL_PTR REG0, op1_addr, TMP1
| ldr REG0, [REG0, #offsetof(zend_string, len)]
| SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
if (Z_MODE(res_addr) == IS_REG) {
| GET_ZVAL_PTR Rx(Z_REG(res_addr)), op1_addr, TMP1
| ldr Rx(Z_REG(res_addr)), [Rx(Z_REG(res_addr)), #offsetof(zend_string, len)]
if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
| GET_ZVAL_PTR REG0, op1_addr, TMP1
| ldr REG0, [REG0, #offsetof(zend_string, len)]
| SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
}
return 1;
}

static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, int may_throw)
static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr, int may_throw)
{
zend_jit_addr res_addr = RES_ADDR();

if (opline->op1_type == IS_CONST) {
zval *zv;
zend_long count;
Expand All @@ -13602,16 +13610,29 @@ static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_
count = zend_hash_num_elements(Z_ARRVAL_P(zv));

| SET_ZVAL_LVAL res_addr, count, TMP1, TMP2
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY);
// Note: See the implementation of ZEND_COUNT in Zend/zend_vm_def.h - arrays do not contain IS_UNDEF starting in php 8.1+.

| GET_ZVAL_PTR REG0, op1_addr, TMP1
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| ldr REG0w, [REG0, #offsetof(HashTable, nNumOfElements)]
| SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
if (Z_MODE(res_addr) == IS_REG) {
| GET_ZVAL_PTR Rx(Z_REG(res_addr)), op1_addr, TMP1
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| ldr Rw(Z_REG(res_addr)), [Rx(Z_REG(res_addr)), #offsetof(HashTable, nNumOfElements)]
if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
| GET_ZVAL_PTR REG0, op1_addr, TMP1
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| ldr REG0w, [REG0, #offsetof(HashTable, nNumOfElements)]
| SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
}

Expand Down Expand Up @@ -14686,6 +14707,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
return opline->op1_type == IS_CV
&& !(op1_info & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - MAY_BE_LONG))
&& (op2_info & MAY_BE_LONG);
case ZEND_STRLEN:
op1_info = OP1_INFO();
return (opline->op1_type & (IS_CV|IS_CONST))
&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_STRING;
case ZEND_COUNT:
op1_info = OP1_INFO();
return (opline->op1_type & (IS_CV|IS_CONST))
&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_ARRAY;
case ZEND_BOOL:
case ZEND_BOOL_NOT:
case ZEND_JMPZ:
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/jit/zend_jit_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -5731,7 +5731,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
break;
}
}
if (!zend_jit_strlen(&dasm_state, opline, op1_info, op1_addr)) {
if (!zend_jit_strlen(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR())) {
goto jit_failure;
}
goto done;
Expand All @@ -5753,7 +5753,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
break;
}
}
if (!zend_jit_count(&dasm_state, opline, op1_info, op1_addr, zend_may_throw(opline, ssa_op, op_array, ssa))) {
if (!zend_jit_count(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR(), zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
goto done;
Expand Down
63 changes: 46 additions & 17 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -14412,10 +14412,8 @@ static int zend_jit_echo(dasm_State **Dst, const zend_op *opline, uint32_t op1_i
return 1;
}

static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr)
static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr)
{
zend_jit_addr res_addr = RES_ADDR();

if (opline->op1_type == IS_CONST) {
zval *zv;
size_t len;
Expand All @@ -14425,23 +14423,33 @@ static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t op1
len = Z_STRLEN_P(zv);

| SET_ZVAL_LVAL res_addr, len
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);

| GET_ZVAL_PTR r0, op1_addr
| mov r0, aword [r0 + offsetof(zend_string, len)]
| SET_ZVAL_LVAL res_addr, r0
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
if (Z_MODE(res_addr) == IS_REG) {
| GET_ZVAL_PTR Ra(Z_REG(res_addr)), op1_addr
| mov Ra(Z_REG(res_addr)), aword [Ra(Z_REG(res_addr))+offsetof(zend_string, len)]
if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
| GET_ZVAL_PTR r0, op1_addr
| mov r0, aword [r0 + offsetof(zend_string, len)]
| SET_ZVAL_LVAL res_addr, r0
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
}
return 1;
}

static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, int may_throw)
static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr, int may_throw)
{
zend_jit_addr res_addr = RES_ADDR();

if (opline->op1_type == IS_CONST) {
zval *zv;
zend_long count;
Expand All @@ -14451,16 +14459,29 @@ static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_
count = zend_hash_num_elements(Z_ARRVAL_P(zv));

| SET_ZVAL_LVAL res_addr, count
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY);
// Note: See the implementation of ZEND_COUNT in Zend/zend_vm_def.h - arrays do not contain IS_UNDEF starting in php 8.1+.

| GET_ZVAL_PTR r0, op1_addr
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| mov eax, dword [r0 + offsetof(HashTable, nNumOfElements)]
| SET_ZVAL_LVAL res_addr, r0
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
if (Z_MODE(res_addr) == IS_REG) {
| GET_ZVAL_PTR Ra(Z_REG(res_addr)), op1_addr
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| mov Rd(Z_REG(res_addr)), dword [Ra(Z_REG(res_addr))+offsetof(HashTable, nNumOfElements)]
if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, MAY_BE_LONG)) {
return 0;
}
} else {
| GET_ZVAL_PTR r0, op1_addr
// Sign-extend the 32-bit value to a potentially 64-bit zend_long
| mov eax, dword [r0 + offsetof(HashTable, nNumOfElements)]
| SET_ZVAL_LVAL res_addr, r0
| SET_ZVAL_TYPE_INFO res_addr, IS_LONG
}
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
}

Expand Down Expand Up @@ -15552,6 +15573,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
return opline->op1_type == IS_CV
&& !(op1_info & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - MAY_BE_LONG))
&& (op2_info & MAY_BE_LONG);
case ZEND_STRLEN:
op1_info = OP1_INFO();
return (opline->op1_type & (IS_CV|IS_CONST))
&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_STRING;
case ZEND_COUNT:
op1_info = OP1_INFO();
return (opline->op1_type & (IS_CV|IS_CONST))
&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_ARRAY;
case ZEND_BOOL:
case ZEND_BOOL_NOT:
case ZEND_JMPZ:
Expand Down

0 comments on commit 7be7ec3

Please sign in to comment.