]> granicus.if.org Git - php/commitdiff
Improve JIT for fetching character form string
authorDmitry Stogov <dmitry@zend.com>
Tue, 20 Oct 2020 17:29:33 +0000 (20:29 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 20 Oct 2020 17:29:33 +0000 (20:29 +0300)
ext/opcache/jit/zend_jit_disasm_x86.c
ext/opcache/jit/zend_jit_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index 730a5d13196f8ccb36fb50ceecefb90f95f9ef74..afd830e89f1aabd4f052736e570dcfd6bb1143fe 100644 (file)
@@ -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);
index c366e6274a01162e78047c9a4ae0ce8ab20c4502..11912e3a70a615fc3066d627544ad20eaf243236 100644 (file)
@@ -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]);
        }
 }
 
index ee998a69e4c1e5d133155d14b86d24da1b370c98..53dbb9b225af57e1be2fe0ca729a7b94f1069720 100644 (file)
@@ -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