diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2020-10-20 20:29:33 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2020-10-20 20:29:33 +0300 |
| commit | 0ac810bbc542aff06db75832a100640a0efb39d4 (patch) | |
| tree | 4c80ec29f658ed02e51c3b8aa417b61e51d2a2ac | |
| parent | edd8bd64ba78ac2a22da0fbc04559d9d55d30fa8 (diff) | |
| download | php-git-0ac810bbc542aff06db75832a100640a0efb39d4.tar.gz | |
Improve JIT for fetching character form string
| -rw-r--r-- | ext/opcache/jit/zend_jit_disasm_x86.c | 1 | ||||
| -rw-r--r-- | ext/opcache/jit/zend_jit_helpers.c | 60 | ||||
| -rw-r--r-- | ext/opcache/jit/zend_jit_x86.dasc | 34 |
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 |
