summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2020-07-13 12:04:08 +0300
committerDmitry Stogov <dmitry@zend.com>2020-07-13 12:04:08 +0300
commitd4fdf79add800b4c529e6a31f2a0ff665b8b97ce (patch)
tree2f3ce6381f87b7e799401ac61ab669d20092e51a
parent6f48ccf51cbf944901334d0757d2ef0d8dce5842 (diff)
downloadphp-git-d4fdf79add800b4c529e6a31f2a0ff665b8b97ce.tar.gz
JIT for array merging
-rw-r--r--ext/opcache/jit/zend_jit.c8
-rw-r--r--ext/opcache/jit/zend_jit_disasm_x86.c1
-rw-r--r--ext/opcache/jit/zend_jit_helpers.c8
-rw-r--r--ext/opcache/jit/zend_jit_trace.c8
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc16
5 files changed, 41 insertions, 0 deletions
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,