From: Dmitry Stogov Date: Mon, 13 Jul 2020 09:04:08 +0000 (+0300) Subject: JIT for array merging X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d4fdf79add800b4c529e6a31f2a0ff665b8b97ce;p=php JIT for array merging --- diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d0c1178d69..e8c82f3886 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2274,6 +2274,14 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { break; } + if (opline->opcode == ZEND_ADD && + (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && + (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { + if (!zend_jit_add_arrays(&dasm_state, opline, op_array, op1_info, op2_info)) { + goto jit_failure; + } + goto done; + } if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) { break; diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index 039efa5f8c..47292f675d 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -460,6 +460,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_check_constant); REGISTER_HELPER(zend_jit_array_free); REGISTER_HELPER(zend_jit_zval_array_dup); + REGISTER_HELPER(zend_jit_add_arrays_helper); #undef REGISTER_HELPER #ifndef _WIN32 diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index ad26607fd6..681b095a18 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1858,3 +1858,11 @@ static HashTable *ZEND_FASTCALL zend_jit_zval_array_dup(zval *arr) ZVAL_ARR(arr, ht); return ht; } + +static zend_array *ZEND_FASTCALL zend_jit_add_arrays_helper(zend_array *op1, zend_array *op2) +{ + zend_array *res; + res = zend_array_dup(op1); + zend_hash_merge(res, op2, zval_add_ref, 0); + return res; +} diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 278b3e6151..7109c69032 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3077,6 +3077,14 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { break; } + if (opline->opcode == ZEND_ADD && + (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && + (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) { + if (!zend_jit_add_arrays(&dasm_state, opline, op_array, op1_info, op2_info)) { + goto jit_failure; + } + goto done; + } if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) || !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) { break; diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 00a29f5ee5..ffc85b1f02 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4357,6 +4357,22 @@ static int zend_jit_math(dasm_State **Dst, const zend_op *opline, const zend_op_ return 1; } +static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, uint32_t op2_info) +{ + zend_jit_addr op1_addr = OP1_ADDR(); + zend_jit_addr op2_addr = OP2_ADDR(); + zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var); + + | GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr + | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr + | EXT_CALL zend_jit_add_arrays_helper, r0 + | SET_ZVAL_PTR res_addr, r0 + | SET_ZVAL_TYPE_INFO res_addr, IS_ARRAY_EX + | FREE_OP opline->op1_type, opline->op1, op1_info, 0, op_array, opline + | FREE_OP opline->op2_type, opline->op2, op2_info, 0, op_array, opline + return 1; +} + static int zend_jit_long_math_helper(dasm_State **Dst, const zend_op *opline, zend_uchar opcode,