Skip to content

Commit 25ed7f7

Browse files
committed
ext/standard/array.c: simplify DEFINE_SORT_VARIANTS macro
- Remove DEFINE_SORT_VARIANTS_USING macro layer - Inline the implementation directly in DEFINE_SORT_VARIANTS - Move enum helper functions after DEFINE_SORT_VARIANTS usage
1 parent 9026917 commit 25ed7f7

File tree

1 file changed

+74
-77
lines changed

1 file changed

+74
-77
lines changed

ext/standard/array.c

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -110,94 +110,20 @@ static zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b
110110
static int php_array_compare_transitive(zval *op1, zval *op2);
111111

112112
/* Generate inlined unstable and stable variants, and non-inlined reversed variants. */
113-
#define DEFINE_SORT_VARIANTS_USING(name, impl) \
113+
#define DEFINE_SORT_VARIANTS(name) \
114114
static zend_never_inline int php_array_##name##_unstable(Bucket *a, Bucket *b) { \
115-
return (impl)(a, b); \
115+
return php_array_##name##_unstable_i(a, b); \
116116
} \
117117
static zend_never_inline int php_array_##name(Bucket *a, Bucket *b) { \
118-
RETURN_STABLE_SORT(a, b, (impl)(a, b)); \
118+
RETURN_STABLE_SORT(a, b, php_array_##name##_unstable_i(a, b)); \
119119
} \
120120
static zend_never_inline int php_array_reverse_##name##_unstable(Bucket *a, Bucket *b) { \
121121
return php_array_##name##_unstable(a, b) * -1; \
122122
} \
123123
static zend_never_inline int php_array_reverse_##name(Bucket *a, Bucket *b) { \
124124
RETURN_STABLE_SORT(a, b, php_array_reverse_##name##_unstable(a, b)); \
125-
} \
126-
127-
#define DEFINE_SORT_VARIANTS(name) \
128-
DEFINE_SORT_VARIANTS_USING(name, php_array_##name##_unstable_i)
129-
130-
static zend_always_inline bool php_array_is_enum_zval(zval *zv)
131-
{
132-
return Z_TYPE_P(zv) == IS_OBJECT && (Z_OBJCE_P(zv)->ce_flags & ZEND_ACC_ENUM);
133-
}
134-
135-
static zend_always_inline int php_array_compare_enum_zvals(zval *lhs, zval *rhs)
136-
{
137-
const bool lhs_enum = php_array_is_enum_zval(lhs);
138-
const bool rhs_enum = php_array_is_enum_zval(rhs);
139-
140-
if (lhs_enum && rhs_enum) {
141-
zend_object *lhs_obj = Z_OBJ_P(lhs);
142-
zend_object *rhs_obj = Z_OBJ_P(rhs);
143-
144-
if (lhs_obj == rhs_obj) {
145-
return 0;
146-
}
147-
148-
if (lhs_obj->ce != rhs_obj->ce) {
149-
return zend_compare_non_numeric_strings(lhs_obj->ce->name, rhs_obj->ce->name);
150-
}
151-
152-
if (lhs_obj->ce->enum_backing_type != IS_UNDEF) {
153-
zval *lhs_value = zend_enum_fetch_case_value(lhs_obj);
154-
zval *rhs_value = zend_enum_fetch_case_value(rhs_obj);
155-
156-
if (lhs_obj->ce->enum_backing_type == IS_LONG) {
157-
zend_long lhs_long = Z_LVAL_P(lhs_value);
158-
zend_long rhs_long = Z_LVAL_P(rhs_value);
159-
if (lhs_long != rhs_long) {
160-
return lhs_long < rhs_long ? -1 : 1;
161-
}
162-
} else {
163-
ZEND_ASSERT(lhs_obj->ce->enum_backing_type == IS_STRING);
164-
zend_string *lhs_str = Z_STR_P(lhs_value);
165-
zend_string *rhs_str = Z_STR_P(rhs_value);
166-
if (lhs_str != rhs_str) {
167-
zend_ulong lhs_hash = ZSTR_HASH(lhs_str);
168-
zend_ulong rhs_hash = ZSTR_HASH(rhs_str);
169-
if (lhs_hash != rhs_hash) {
170-
return lhs_hash < rhs_hash ? -1 : 1;
171-
}
172-
int cmp = zend_compare_non_numeric_strings(lhs_str, rhs_str);
173-
if (cmp != 0) {
174-
return cmp;
175-
}
176-
}
177-
}
178-
}
179-
180-
zend_string *lhs_case = Z_STR_P(zend_enum_fetch_case_name(lhs_obj));
181-
zend_string *rhs_case = Z_STR_P(zend_enum_fetch_case_name(rhs_obj));
182-
if (lhs_case != rhs_case) {
183-
zend_ulong lhs_hash = ZSTR_HASH(lhs_case);
184-
zend_ulong rhs_hash = ZSTR_HASH(rhs_case);
185-
if (lhs_hash != rhs_hash) {
186-
return lhs_hash < rhs_hash ? -1 : 1;
187-
}
188-
int cmp = zend_compare_non_numeric_strings(lhs_case, rhs_case);
189-
if (cmp != 0) {
190-
return cmp;
191-
}
192-
}
193-
194-
/* Should not happen for userland enums, but keep ordering deterministic for transitivity. */
195-
return lhs_obj->handle < rhs_obj->handle ? -1 : 1;
196125
}
197126

198-
return lhs_enum ? 1 : -1;
199-
}
200-
201127
static zend_always_inline int php_array_key_compare_numeric_unstable_i(Bucket *f, Bucket *s) /* {{{ */
202128
{
203129
if (f->key == NULL && s->key == NULL) {
@@ -399,6 +325,77 @@ DEFINE_SORT_VARIANTS(data_compare_string_locale);
399325
DEFINE_SORT_VARIANTS(natural_compare);
400326
DEFINE_SORT_VARIANTS(natural_case_compare);
401327

328+
static zend_always_inline bool php_array_is_enum_zval(zval *zv)
329+
{
330+
return Z_TYPE_P(zv) == IS_OBJECT && (Z_OBJCE_P(zv)->ce_flags & ZEND_ACC_ENUM);
331+
}
332+
333+
static zend_always_inline int php_array_compare_enum_zvals(zval *lhs, zval *rhs)
334+
{
335+
const bool lhs_enum = php_array_is_enum_zval(lhs);
336+
const bool rhs_enum = php_array_is_enum_zval(rhs);
337+
338+
if (lhs_enum && rhs_enum) {
339+
zend_object *lhs_obj = Z_OBJ_P(lhs);
340+
zend_object *rhs_obj = Z_OBJ_P(rhs);
341+
342+
if (lhs_obj == rhs_obj) {
343+
return 0;
344+
}
345+
346+
if (lhs_obj->ce != rhs_obj->ce) {
347+
return zend_compare_non_numeric_strings(lhs_obj->ce->name, rhs_obj->ce->name);
348+
}
349+
350+
if (lhs_obj->ce->enum_backing_type != IS_UNDEF) {
351+
zval *lhs_value = zend_enum_fetch_case_value(lhs_obj);
352+
zval *rhs_value = zend_enum_fetch_case_value(rhs_obj);
353+
354+
if (lhs_obj->ce->enum_backing_type == IS_LONG) {
355+
zend_long lhs_long = Z_LVAL_P(lhs_value);
356+
zend_long rhs_long = Z_LVAL_P(rhs_value);
357+
if (lhs_long != rhs_long) {
358+
return lhs_long < rhs_long ? -1 : 1;
359+
}
360+
} else {
361+
ZEND_ASSERT(lhs_obj->ce->enum_backing_type == IS_STRING);
362+
zend_string *lhs_str = Z_STR_P(lhs_value);
363+
zend_string *rhs_str = Z_STR_P(rhs_value);
364+
if (lhs_str != rhs_str) {
365+
zend_ulong lhs_hash = ZSTR_HASH(lhs_str);
366+
zend_ulong rhs_hash = ZSTR_HASH(rhs_str);
367+
if (lhs_hash != rhs_hash) {
368+
return lhs_hash < rhs_hash ? -1 : 1;
369+
}
370+
int cmp = zend_compare_non_numeric_strings(lhs_str, rhs_str);
371+
if (cmp != 0) {
372+
return cmp;
373+
}
374+
}
375+
}
376+
}
377+
378+
zend_string *lhs_case = Z_STR_P(zend_enum_fetch_case_name(lhs_obj));
379+
zend_string *rhs_case = Z_STR_P(zend_enum_fetch_case_name(rhs_obj));
380+
if (lhs_case != rhs_case) {
381+
zend_ulong lhs_hash = ZSTR_HASH(lhs_case);
382+
zend_ulong rhs_hash = ZSTR_HASH(rhs_case);
383+
if (lhs_hash != rhs_hash) {
384+
return lhs_hash < rhs_hash ? -1 : 1;
385+
}
386+
int cmp = zend_compare_non_numeric_strings(lhs_case, rhs_case);
387+
if (cmp != 0) {
388+
return cmp;
389+
}
390+
}
391+
392+
/* Should not happen for userland enums, but keep ordering deterministic for transitivity. */
393+
return lhs_obj->handle < rhs_obj->handle ? -1 : 1;
394+
}
395+
396+
return lhs_enum ? 1 : -1;
397+
}
398+
402399
static int php_array_hash_compare_transitive(zval *zv1, zval *zv2) /* {{{ */
403400
{
404401
return php_array_compare_transitive(zv1, zv2);

0 commit comments

Comments
 (0)