From: Dmitry Stogov Date: Tue, 20 Oct 2020 17:29:33 +0000 (+0300) Subject: Improve JIT for fetching character form string X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ac810bbc542aff06db75832a100640a0efb39d4;p=php Improve JIT for fetching character form string --- 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