Skip to content

Commit 99b8614

Browse files
nielsdosGirgias
authored andcommitted
Introduce convenience macros for copying flags that hold when concatenating two strings
This abstracts away, and cleans up, the flag handling for properties of strings that hold when concatenating two strings if they both hold that property. (These macros also work with simply copies of strings because a copy of a string can be considered a concatenation with the empty string.) This gets rid of some branches and some repetitive code, and leaves room for adding more flags like these in the future.
1 parent a5f27fd commit 99b8614

File tree

6 files changed

+57
-150
lines changed

6 files changed

+57
-150
lines changed

Zend/zend_operators.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -1981,11 +1981,7 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
19811981
size_t op2_len = Z_STRLEN_P(op2);
19821982
size_t result_len = op1_len + op2_len;
19831983
zend_string *result_str;
1984-
uint32_t flags = 0;
1985-
1986-
if (ZSTR_IS_VALID_UTF8(Z_STR_P(op1)) && ZSTR_IS_VALID_UTF8(Z_STR_P(op2))) {
1987-
flags = IS_STR_VALID_UTF8;
1988-
}
1984+
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(Z_STR_P(op1), Z_STR_P(op2));
19891985

19901986
if (UNEXPECTED(op1_len > ZSTR_MAX_LEN - op2_len)) {
19911987
zend_throw_error(NULL, "String size overflow");

Zend/zend_string.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,9 @@ ZEND_API zend_string* ZEND_FASTCALL zend_interned_string_find_permanent(zend_str
191191
return zend_interned_string_ht_lookup(str, &interned_strings_permanent);
192192
}
193193

194-
static zend_string* ZEND_FASTCALL zend_init_string_for_interning(zend_string *str, bool persistent) {
195-
uint32_t flags = 0;
196-
if (ZSTR_IS_VALID_UTF8(str)) {
197-
flags = IS_STR_VALID_UTF8;
198-
}
194+
static zend_string* ZEND_FASTCALL zend_init_string_for_interning(zend_string *str, bool persistent)
195+
{
196+
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(str);
199197
zend_ulong h = ZSTR_H(str);
200198
zend_string_delref(str);
201199
str = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), persistent);

Zend/zend_string.h

+21
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,27 @@ END_EXTERN_C()
8282
#define ZSTR_IS_INTERNED(s) (GC_FLAGS(s) & IS_STR_INTERNED)
8383
#define ZSTR_IS_VALID_UTF8(s) (GC_FLAGS(s) & IS_STR_VALID_UTF8)
8484

85+
/* These are properties, encoded as flags, that will hold on the resulting string
86+
* after concatenating two strings that have these property.
87+
* Example: concatenating two UTF-8 strings yields another UTF-8 string. */
88+
#define ZSTR_COPYABLE_CONCAT_PROPERTIES (IS_STR_VALID_UTF8)
89+
90+
#define ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(s) (GC_FLAGS(s) & ZSTR_COPYABLE_CONCAT_PROPERTIES)
91+
/* This macro returns the copyable concat properties which hold on both strings. */
92+
#define ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(s1, s2) (GC_FLAGS(s1) & GC_FLAGS(s2) & ZSTR_COPYABLE_CONCAT_PROPERTIES)
93+
94+
#define ZSTR_COPY_CONCAT_PROPERTIES(out, in) do { \
95+
zend_string *_out = (out); \
96+
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES((in)); \
97+
GC_ADD_FLAGS(_out, properties); \
98+
} while (0)
99+
100+
#define ZSTR_COPY_CONCAT_PROPERTIES_BOTH(out, in1, in2) do { \
101+
zend_string *_out = (out); \
102+
uint32_t properties = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH((in1), (in2)); \
103+
GC_ADD_FLAGS(_out, properties); \
104+
} while (0)
105+
85106
#define ZSTR_EMPTY_ALLOC() zend_empty_string
86107
#define ZSTR_CHAR(c) zend_one_char_string[c]
87108
#define ZSTR_KNOWN(idx) zend_known_strings[idx]

Zend/zend_vm_def.h

+3-13
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
384384
zend_string *op1_str = Z_STR_P(op1);
385385
zend_string *op2_str = Z_STR_P(op2);
386386
zend_string *str;
387-
uint32_t flags = 0;
388-
389-
if (ZSTR_IS_VALID_UTF8(op1_str) && ZSTR_IS_VALID_UTF8(op2_str)) {
390-
flags = IS_STR_VALID_UTF8;
391-
}
387+
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str);
392388

393389
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) {
394390
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) {
@@ -3147,11 +3143,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
31473143
zend_string *op1_str = Z_STR_P(op1);
31483144
zend_string *op2_str = Z_STR_P(op2);
31493145
zend_string *str;
3150-
uint32_t flags = 0;
3151-
3152-
if (ZSTR_IS_VALID_UTF8(op1_str) && ZSTR_IS_VALID_UTF8(op2_str)) {
3153-
flags = IS_STR_VALID_UTF8;
3154-
}
3146+
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str);
31553147

31563148
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) {
31573149
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) {
@@ -3248,9 +3240,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
32483240
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
32493241
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
32503242

3251-
if (ZSTR_IS_VALID_UTF8(op1_str) && ZSTR_IS_VALID_UTF8(op2_str)) {
3252-
GC_ADD_FLAGS(str, IS_STR_VALID_UTF8);
3253-
}
3243+
ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str);
32543244
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
32553245
if (OP1_TYPE != IS_CONST) {
32563246
zend_string_release_ex(op1_str, 0);

0 commit comments

Comments
 (0)