summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2020-10-20 20:29:33 +0300
committerDmitry Stogov <dmitry@zend.com>2020-10-20 20:29:33 +0300
commit0ac810bbc542aff06db75832a100640a0efb39d4 (patch)
tree4c80ec29f658ed02e51c3b8aa417b61e51d2a2ac
parentedd8bd64ba78ac2a22da0fbc04559d9d55d30fa8 (diff)
downloadphp-git-0ac810bbc542aff06db75832a100640a0efb39d4.tar.gz
Improve JIT for fetching character form string
-rw-r--r--ext/opcache/jit/zend_jit_disasm_x86.c1
-rw-r--r--ext/opcache/jit/zend_jit_helpers.c60
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc34
3 files changed, 58 insertions, 37 deletions
diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c
index 730a5d1319..afd830e89f 100644
--- a/ext/opcache/jit/zend_jit_disasm_x86.c
+++ b/ext/opcache/jit/zend_jit_disasm_x86.c
@@ -421,6 +421,7 @@ static int zend_jit_disasm_init(void)
REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
+ REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c
index c366e6274a..11912e3a70 100644
--- a/ext/opcache/jit/zend_jit_helpers.c
+++ b/ext/opcache/jit/zend_jit_helpers.c
@@ -834,7 +834,30 @@ try_again:
return _zval_get_long_func(dim);
}
-static void ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zval *container, zval *dim, zval *result)
+static zend_always_inline zend_string* zend_jit_fetch_dim_str_offset(zend_string *str, zend_long offset)
+{
+ if (UNEXPECTED((zend_ulong)offset >= (zend_ulong)ZSTR_LEN(str))) {
+ if (EXPECTED(offset < 0)) {
+ /* Handle negative offset */
+ zend_long real_offset = (zend_long)ZSTR_LEN(str) + offset;
+
+ if (EXPECTED(real_offset >= 0)) {
+ return ZSTR_CHAR((zend_uchar)ZSTR_VAL(str)[real_offset]);
+ }
+ }
+ zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
+ return ZSTR_EMPTY_ALLOC();
+ } else {
+ return ZSTR_CHAR((zend_uchar)ZSTR_VAL(str)[offset]);
+ }
+}
+
+static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_offset_r_helper(zend_string *str, zend_long offset)
+{
+ return zend_jit_fetch_dim_str_offset(str, offset);
+}
+
+static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zend_string *str, zval *dim)
{
zend_long offset;
@@ -843,22 +866,10 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zval *container, zval
} else {
offset = Z_LVAL_P(dim);
}
-
- if (UNEXPECTED(Z_STRLEN_P(container) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
- zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
- ZVAL_EMPTY_STRING(result);
- } else {
- zend_uchar c;
- zend_long real_offset;
-
- real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
- ? (zend_long)Z_STRLEN_P(container) + offset : offset;
- c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
- ZVAL_CHAR(result, c);
- }
+ return zend_jit_fetch_dim_str_offset(str, offset);
}
-static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zval *container, zval *dim, zval *result)
+static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zval *dim, zval *result)
{
zend_long offset;
@@ -892,16 +903,19 @@ try_string_offset:
offset = Z_LVAL_P(dim);
}
- if (UNEXPECTED(Z_STRLEN_P(container) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
+ if ((zend_ulong)offset >= (zend_ulong)ZSTR_LEN(str)) {
+ if (offset < 0) {
+ /* Handle negative offset */
+ zend_long real_offset = (zend_long)ZSTR_LEN(str) + offset;
+
+ if (real_offset >= 0) {
+ ZVAL_CHAR(result, (zend_uchar)ZSTR_VAL(str)[real_offset]);
+ return;
+ }
+ }
ZVAL_NULL(result);
} else {
- zend_uchar c;
- zend_long real_offset;
-
- real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
- ? (zend_long)Z_STRLEN_P(container) + offset : offset;
- c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
- ZVAL_CHAR(result, c);
+ ZVAL_CHAR(result, (zend_uchar)ZSTR_VAL(str)[offset]);
}
}
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index ee998a69e4..53dbb9b225 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -11623,24 +11623,30 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
}
}
| SET_EX_OPLINE opline, r0
- if (Z_REG(op1_addr) != ZREG_FCARG1a || Z_OFFSET(op1_addr) != 0) {
- | LOAD_ZVAL_ADDR FCARG1a, op1_addr
- }
- | LOAD_ZVAL_ADDR FCARG2a, op2_addr
- |.if X64
- | LOAD_ZVAL_ADDR CARG3, res_addr
- |.else
- | sub r4, 12
- | PUSH_ZVAL_ADDR res_addr, r0
- |.endif
+ | GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr
if (opline->opcode != ZEND_FETCH_DIM_IS) {
- | EXT_CALL zend_jit_fetch_dim_str_r_helper, r0
+ if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG) {
+ | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
+ | EXT_CALL zend_jit_fetch_dim_str_offset_r_helper, r0
+ } else {
+ | LOAD_ZVAL_ADDR FCARG2a, op2_addr
+ | EXT_CALL zend_jit_fetch_dim_str_r_helper, r0
+ }
+ | SET_ZVAL_PTR res_addr, r0
+ | SET_ZVAL_TYPE_INFO res_addr, IS_STRING
} else {
+ | LOAD_ZVAL_ADDR FCARG2a, op2_addr
+ |.if X64
+ | LOAD_ZVAL_ADDR CARG3, res_addr
+ |.else
+ | sub r4, 12
+ | PUSH_ZVAL_ADDR res_addr, r0
+ |.endif
| EXT_CALL zend_jit_fetch_dim_str_is_helper, r0
+ |.if not(X64)
+ | add r4, 12
+ |.endif
}
- |.if not(X64)
- | add r4, 12
- |.endif
if ((op1_info & MAY_BE_ARRAY) ||
(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_STRING)))) {
| jmp >9 // END