Skip to content

Commit 945c0ba

Browse files
committed
RC1 optimisation for strto{lower,upper}
We can't unconditionally allow inplace modification in zend_string_toupper_ex and zend_string_tolower_ex because their API contract expects a copy.
1 parent 0b036b5 commit 945c0ba

File tree

3 files changed

+36
-14
lines changed

3 files changed

+36
-14
lines changed

Diff for: Zend/zend_operators.c

+30-10
Original file line numberDiff line numberDiff line change
@@ -2877,7 +2877,21 @@ ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup_ex(const char *source, size_t
28772877
}
28782878
/* }}} */
28792879

2880-
ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, bool persistent) /* {{{ */
2880+
static zend_string* ZEND_FASTCALL zend_string_alloc_or_partial_dup(zend_string *str, bool persistent, bool inplace, const unsigned char *p)
2881+
{
2882+
if (inplace) {
2883+
ZEND_ASSERT(!persistent);
2884+
zend_string_forget_hash_val(str);
2885+
GC_ADDREF(str);
2886+
return str;
2887+
} else {
2888+
zend_string *res = zend_string_alloc(ZSTR_LEN(str), persistent);
2889+
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
2890+
return res;
2891+
}
2892+
}
2893+
2894+
ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex_maybe_inplace(zend_string *str, bool persistent, bool inplace) /* {{{ */
28812895
{
28822896
size_t length = ZSTR_LEN(str);
28832897
unsigned char *p = (unsigned char *) ZSTR_VAL(str);
@@ -2888,8 +2902,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
28882902
while (p + BLOCKCONV_STRIDE <= end) {
28892903
BLOCKCONV_LOAD(p);
28902904
if (BLOCKCONV_FOUND()) {
2891-
zend_string *res = zend_string_alloc(length, persistent);
2892-
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
2905+
zend_string *res = zend_string_alloc_or_partial_dup(str, persistent, inplace, p);
28932906
unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
28942907

28952908
/* Lowercase the chunk we already compared. */
@@ -2909,8 +2922,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
29092922

29102923
while (p < end) {
29112924
if (*p != zend_tolower_ascii(*p)) {
2912-
zend_string *res = zend_string_alloc(length, persistent);
2913-
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str));
2925+
zend_string *res = zend_string_alloc_or_partial_dup(str, persistent, inplace, p);
29142926

29152927
unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
29162928
while (p < end) {
@@ -2926,7 +2938,12 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
29262938
}
29272939
/* }}} */
29282940

2929-
ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, bool persistent) /* {{{ */
2941+
ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, bool persistent)
2942+
{
2943+
return zend_string_tolower_ex_maybe_inplace(str, persistent, false);
2944+
}
2945+
2946+
ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex_maybe_inplace(zend_string *str, bool persistent, bool inplace) /* {{{ */
29302947
{
29312948
size_t length = ZSTR_LEN(str);
29322949
unsigned char *p = (unsigned char *) ZSTR_VAL(str);
@@ -2937,8 +2954,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, boo
29372954
while (p + BLOCKCONV_STRIDE <= end) {
29382955
BLOCKCONV_LOAD(p);
29392956
if (BLOCKCONV_FOUND()) {
2940-
zend_string *res = zend_string_alloc(length, persistent);
2941-
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
2957+
zend_string *res = zend_string_alloc_or_partial_dup(str, persistent, inplace, p);
29422958
unsigned char *q = (unsigned char *) ZSTR_VAL(res) + (p - (unsigned char *) ZSTR_VAL(str));
29432959

29442960
/* Uppercase the chunk we already compared. */
@@ -2958,8 +2974,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, boo
29582974

29592975
while (p < end) {
29602976
if (*p != zend_toupper_ascii(*p)) {
2961-
zend_string *res = zend_string_alloc(length, persistent);
2962-
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str));
2977+
zend_string *res = zend_string_alloc_or_partial_dup(str, persistent, inplace, p);
29632978

29642979
unsigned char *q = (unsigned char *) ZSTR_VAL(res) + (p - (unsigned char *) ZSTR_VAL(str));
29652980
while (p < end) {
@@ -2975,6 +2990,11 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, boo
29752990
}
29762991
/* }}} */
29772992

2993+
ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, bool persistent)
2994+
{
2995+
return zend_string_toupper_ex_maybe_inplace(str, persistent, false);
2996+
}
2997+
29782998
ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
29792999
{
29803000
int retval;

Diff for: Zend/zend_operators.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -438,13 +438,15 @@ ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup(const char *source, siz
438438
ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length);
439439
ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup_ex(const char *source, size_t length);
440440
ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, bool persistent);
441+
ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex_maybe_inplace(zend_string *str, bool persistent, bool inplace);
441442
ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, bool persistent);
443+
ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex_maybe_inplace(zend_string *str, bool persistent, bool inplace);
442444

443445
static zend_always_inline zend_string* zend_string_tolower(zend_string *str) {
444-
return zend_string_tolower_ex(str, false);
446+
return zend_string_tolower_ex_maybe_inplace(str, false, false);
445447
}
446448
static zend_always_inline zend_string* zend_string_toupper(zend_string *str) {
447-
return zend_string_toupper_ex(str, false);
449+
return zend_string_toupper_ex_maybe_inplace(str, false, false);
448450
}
449451

450452
ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2);

Diff for: ext/standard/string.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ PHP_FUNCTION(strtoupper)
11601160
Z_PARAM_STR(arg)
11611161
ZEND_PARSE_PARAMETERS_END();
11621162

1163-
RETURN_STR(zend_string_toupper(arg));
1163+
RETURN_STR(zend_string_toupper_ex_maybe_inplace(arg, false, zend_may_modify_string_in_place(arg)));
11641164
}
11651165
/* }}} */
11661166

@@ -1188,7 +1188,7 @@ PHP_FUNCTION(strtolower)
11881188
Z_PARAM_STR(str)
11891189
ZEND_PARSE_PARAMETERS_END();
11901190

1191-
RETURN_STR(zend_string_tolower(str));
1191+
RETURN_STR(zend_string_tolower_ex_maybe_inplace(str, false, zend_may_modify_string_in_place(str)));
11921192
}
11931193
/* }}} */
11941194

0 commit comments

Comments
 (0)