Skip to content

Commit e2f347e

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Improve JIT for fetching character form string
2 parents 9e95056 + 0ac810b commit e2f347e

File tree

3 files changed

+58
-37
lines changed

3 files changed

+58
-37
lines changed

ext/opcache/jit/zend_jit_disasm_x86.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ static int zend_jit_disasm_init(void)
421421
REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
422422
REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
423423
REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
424+
REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
424425
REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
425426
REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
426427
REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,30 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim/*, int typ
834834
return _zval_get_long_func(dim);
835835
}
836836

837-
static void ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zval *container, zval *dim, zval *result)
837+
static zend_always_inline zend_string* zend_jit_fetch_dim_str_offset(zend_string *str, zend_long offset)
838+
{
839+
if (UNEXPECTED((zend_ulong)offset >= (zend_ulong)ZSTR_LEN(str))) {
840+
if (EXPECTED(offset < 0)) {
841+
/* Handle negative offset */
842+
zend_long real_offset = (zend_long)ZSTR_LEN(str) + offset;
843+
844+
if (EXPECTED(real_offset >= 0)) {
845+
return ZSTR_CHAR((zend_uchar)ZSTR_VAL(str)[real_offset]);
846+
}
847+
}
848+
zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
849+
return ZSTR_EMPTY_ALLOC();
850+
} else {
851+
return ZSTR_CHAR((zend_uchar)ZSTR_VAL(str)[offset]);
852+
}
853+
}
854+
855+
static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_offset_r_helper(zend_string *str, zend_long offset)
856+
{
857+
return zend_jit_fetch_dim_str_offset(str, offset);
858+
}
859+
860+
static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zend_string *str, zval *dim)
838861
{
839862
zend_long offset;
840863

@@ -843,22 +866,10 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zval *container, zval
843866
} else {
844867
offset = Z_LVAL_P(dim);
845868
}
846-
847-
if (UNEXPECTED(Z_STRLEN_P(container) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
848-
zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
849-
ZVAL_EMPTY_STRING(result);
850-
} else {
851-
zend_uchar c;
852-
zend_long real_offset;
853-
854-
real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
855-
? (zend_long)Z_STRLEN_P(container) + offset : offset;
856-
c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
857-
ZVAL_CHAR(result, c);
858-
}
869+
return zend_jit_fetch_dim_str_offset(str, offset);
859870
}
860871

861-
static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zval *container, zval *dim, zval *result)
872+
static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zval *dim, zval *result)
862873
{
863874
zend_long offset;
864875

@@ -892,16 +903,19 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zval *container, zval
892903
offset = Z_LVAL_P(dim);
893904
}
894905

895-
if (UNEXPECTED(Z_STRLEN_P(container) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
906+
if ((zend_ulong)offset >= (zend_ulong)ZSTR_LEN(str)) {
907+
if (offset < 0) {
908+
/* Handle negative offset */
909+
zend_long real_offset = (zend_long)ZSTR_LEN(str) + offset;
910+
911+
if (real_offset >= 0) {
912+
ZVAL_CHAR(result, (zend_uchar)ZSTR_VAL(str)[real_offset]);
913+
return;
914+
}
915+
}
896916
ZVAL_NULL(result);
897917
} else {
898-
zend_uchar c;
899-
zend_long real_offset;
900-
901-
real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
902-
? (zend_long)Z_STRLEN_P(container) + offset : offset;
903-
c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
904-
ZVAL_CHAR(result, c);
918+
ZVAL_CHAR(result, (zend_uchar)ZSTR_VAL(str)[offset]);
905919
}
906920
}
907921

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11623,24 +11623,30 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
1162311623
}
1162411624
}
1162511625
| SET_EX_OPLINE opline, r0
11626-
if (Z_REG(op1_addr) != ZREG_FCARG1a || Z_OFFSET(op1_addr) != 0) {
11627-
| LOAD_ZVAL_ADDR FCARG1a, op1_addr
11628-
}
11629-
| LOAD_ZVAL_ADDR FCARG2a, op2_addr
11630-
|.if X64
11631-
| LOAD_ZVAL_ADDR CARG3, res_addr
11632-
|.else
11633-
| sub r4, 12
11634-
| PUSH_ZVAL_ADDR res_addr, r0
11635-
|.endif
11626+
| GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr
1163611627
if (opline->opcode != ZEND_FETCH_DIM_IS) {
11637-
| EXT_CALL zend_jit_fetch_dim_str_r_helper, r0
11628+
if ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG) {
11629+
| GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
11630+
| EXT_CALL zend_jit_fetch_dim_str_offset_r_helper, r0
11631+
} else {
11632+
| LOAD_ZVAL_ADDR FCARG2a, op2_addr
11633+
| EXT_CALL zend_jit_fetch_dim_str_r_helper, r0
11634+
}
11635+
| SET_ZVAL_PTR res_addr, r0
11636+
| SET_ZVAL_TYPE_INFO res_addr, IS_STRING
1163811637
} else {
11638+
| LOAD_ZVAL_ADDR FCARG2a, op2_addr
11639+
|.if X64
11640+
| LOAD_ZVAL_ADDR CARG3, res_addr
11641+
|.else
11642+
| sub r4, 12
11643+
| PUSH_ZVAL_ADDR res_addr, r0
11644+
|.endif
1163911645
| EXT_CALL zend_jit_fetch_dim_str_is_helper, r0
11646+
|.if not(X64)
11647+
| add r4, 12
11648+
|.endif
1164011649
}
11641-
|.if not(X64)
11642-
| add r4, 12
11643-
|.endif
1164411650
if ((op1_info & MAY_BE_ARRAY) ||
1164511651
(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_STRING)))) {
1164611652
| jmp >9 // END

0 commit comments

Comments
 (0)