summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-10-07 17:57:49 +0300
committerDmitry Stogov <dmitry@zend.com>2019-10-07 17:57:49 +0300
commitb02b81299ccef7de244bac7ffc605e3d2943fa88 (patch)
treef07036f89b7f4c8f3162f20702881061d59a13a3 /Zend
parente2100619ac064fdd4e7fe79e296a2ca087409e7d (diff)
downloadphp-git-b02b81299ccef7de244bac7ffc605e3d2943fa88.tar.gz
Comparison cleanup:
- introduce zend_compare() that returns -1,0,1 dirctly (without intermediate zval) - remove compare_objects() object handler, and keep only compare() handler
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_closures.c7
-rw-r--r--Zend/zend_iterators.c1
-rw-r--r--Zend/zend_object_handlers.c41
-rw-r--r--Zend/zend_object_handlers.h14
-rw-r--r--Zend/zend_operators.c191
-rw-r--r--Zend/zend_operators.h14
-rw-r--r--Zend/zend_vm_def.h35
-rw-r--r--Zend/zend_vm_execute.h50
8 files changed, 147 insertions, 206 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 68e698b626..4ed0b16b62 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -355,9 +355,10 @@ static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object
}
/* }}} */
-static int zend_closure_compare_objects(zval *o1, zval *o2) /* {{{ */
+static int zend_closure_compare(zval *o1, zval *o2) /* {{{ */
{
- return (Z_OBJ_P(o1) != Z_OBJ_P(o2));
+ ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
+ return Z_OBJ_P(o1) != Z_OBJ_P(o2);
}
/* }}} */
@@ -639,7 +640,7 @@ void zend_register_closure_ce(void) /* {{{ */
closure_handlers.get_property_ptr_ptr = zend_closure_get_property_ptr_ptr;
closure_handlers.has_property = zend_closure_has_property;
closure_handlers.unset_property = zend_closure_unset_property;
- closure_handlers.compare_objects = zend_closure_compare_objects;
+ closure_handlers.compare = zend_closure_compare;
closure_handlers.clone_obj = zend_closure_clone;
closure_handlers.get_debug_info = zend_closure_get_debug_info;
closure_handlers.get_closure = zend_closure_get_closure;
diff --git a/Zend/zend_iterators.c b/Zend/zend_iterators.c
index f09ff22763..c0bb418f3a 100644
--- a/Zend/zend_iterators.c
+++ b/Zend/zend_iterators.c
@@ -44,7 +44,6 @@ static const zend_object_handlers iterator_object_handlers = {
NULL, /* method get */
NULL, /* get ctor */
NULL, /* get class name */
- NULL, /* compare */
NULL, /* cast */
NULL, /* count */
NULL, /* get_debug_info */
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 8a1898c227..8c5ddf454a 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -1546,6 +1546,33 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
{
zend_object *zobj1, *zobj2;
+ if (Z_TYPE_P(o1) != Z_TYPE_P(o2)) {
+ /* Object and non-object */
+ zval casted;
+ if (Z_TYPE_P(o1) == IS_OBJECT) {
+ ZEND_ASSERT(Z_TYPE_P(o2) != IS_OBJECT);
+ if (Z_OBJ_HT_P(o1)->cast_object) {
+ if (Z_OBJ_HT_P(o1)->cast_object(Z_OBJ_P(o1), &casted, ((Z_TYPE_P(o2) == IS_FALSE || Z_TYPE_P(o2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o2))) == FAILURE) {
+ return 1;
+ }
+ int ret = zend_compare(&casted, o2);
+ zval_ptr_dtor(&casted);
+ return ret;
+ }
+ } else {
+ ZEND_ASSERT(Z_TYPE_P(o2) == IS_OBJECT);
+ if (Z_OBJ_HT_P(o2)->cast_object) {
+ if (Z_OBJ_HT_P(o2)->cast_object(Z_OBJ_P(o2), &casted, ((Z_TYPE_P(o1) == IS_FALSE || Z_TYPE_P(o1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(o1))) == FAILURE) {
+ return -1;
+ }
+ int ret = zend_compare(o1, &casted);
+ zval_ptr_dtor(&casted);
+ return ret;
+ }
+ }
+ return 1;
+ }
+
zobj1 = Z_OBJ_P(o1);
zobj2 = Z_OBJ_P(o2);
@@ -1582,15 +1609,12 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
if (Z_TYPE_P(p1) != IS_UNDEF) {
if (Z_TYPE_P(p2) != IS_UNDEF) {
- zval result;
+ int ret;
- if (compare_function(&result, p1, p2)==FAILURE) {
- Z_UNPROTECT_RECURSION_P(o1);
- return 1;
- }
- if (Z_LVAL(result) != 0) {
+ ret = zend_compare(p1, p2);
+ if (ret != 0) {
Z_UNPROTECT_RECURSION_P(o1);
- return Z_LVAL(result);
+ return ret;
}
} else {
Z_UNPROTECT_RECURSION_P(o1);
@@ -1850,13 +1874,12 @@ ZEND_API const zend_object_handlers std_object_handlers = {
zend_std_get_method, /* get_method */
zend_std_get_constructor, /* get_constructor */
zend_std_get_class_name, /* get_class_name */
- zend_std_compare_objects, /* compare_objects */
zend_std_cast_object_tostring, /* cast_object */
NULL, /* count_elements */
zend_std_get_debug_info, /* get_debug_info */
zend_std_get_closure, /* get_closure */
zend_std_get_gc, /* get_gc */
NULL, /* do_operation */
- NULL, /* compare */
+ zend_std_compare_objects, /* compare */
NULL, /* get_properties_for */
};
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index d8d7aca86c..713669f297 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -124,7 +124,6 @@ typedef zend_object* (*zend_object_clone_obj_t)(zend_object *object);
typedef zend_string *(*zend_object_get_class_name_t)(const zend_object *object);
typedef int (*zend_object_compare_t)(zval *object1, zval *object2);
-typedef int (*zend_object_compare_zvals_t)(zval *result, zval *op1, zval *op2);
/* Cast an object to some other type.
* readobj and retval must point to distinct zvals.
@@ -161,14 +160,13 @@ struct _zend_object_handlers {
zend_object_get_method_t get_method; /* required */
zend_object_get_constructor_t get_constructor; /* required */
zend_object_get_class_name_t get_class_name; /* required */
- zend_object_compare_t compare_objects; /* optional */
zend_object_cast_t cast_object; /* optional */
zend_object_count_elements_t count_elements; /* optional */
zend_object_get_debug_info_t get_debug_info; /* optional */
zend_object_get_closure_t get_closure; /* optional */
zend_object_get_gc_t get_gc; /* required */
zend_object_do_operation_t do_operation; /* optional */
- zend_object_compare_zvals_t compare; /* optional */
+ zend_object_compare_t compare; /* required */
zend_object_get_properties_for_t get_properties_for; /* optional */
};
@@ -241,6 +239,16 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose
} \
} while (0)
+/* Fallback to default comparison implementation if the arguments aren't both objects
+ * and have the same compare() handler. You'll likely want to use this unless you
+ * explicitly wish to support comparisons between objects and non-objects. */
+#define ZEND_COMPARE_OBJECTS_FALLBACK(op1, op2) \
+ if (Z_TYPE_P(op1) != IS_OBJECT || \
+ Z_TYPE_P(op2) != IS_OBJECT || \
+ Z_OBJ_HT_P(op1)->compare != Z_OBJ_HT_P(op2)->compare) { \
+ return zend_std_compare_objects(op1, op2); \
+ }
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 7b4db44de8..6f939c0401 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1977,97 +1977,69 @@ ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2) /* {{{
}
/* }}} */
-static zend_always_inline void zend_free_obj_get_result(zval *op) /* {{{ */
-{
- ZEND_ASSERT(!Z_REFCOUNTED_P(op) || Z_REFCOUNT_P(op) != 0);
- zval_ptr_dtor(op);
-}
-/* }}} */
-
-static void ZEND_FASTCALL convert_compare_result_to_long(zval *result) /* {{{ */
+ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if (Z_TYPE_P(result) == IS_DOUBLE) {
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- } else {
- convert_to_long(result);
- }
+ ZVAL_LONG(result, zend_compare(op1, op2));
+ return SUCCESS;
}
/* }}} */
-ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
+ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */
{
- int ret;
int converted = 0;
- zval op1_copy, op2_copy, tmp_free;
+ zval op1_copy, op2_copy;
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG):
- ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
- return SUCCESS;
+ return Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0);
case TYPE_PAIR(IS_DOUBLE, IS_LONG):
- Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- return SUCCESS;
+ return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - (double)Z_LVAL_P(op2));
case TYPE_PAIR(IS_LONG, IS_DOUBLE):
- Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
- return SUCCESS;
+ return ZEND_NORMALIZE_BOOL((double)Z_LVAL_P(op1) - Z_DVAL_P(op2));
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
- ZVAL_LONG(result, 0);
+ return 0;
} else {
- Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
- ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
+ return ZEND_NORMALIZE_BOOL(Z_DVAL_P(op1) - Z_DVAL_P(op2));
}
- return SUCCESS;
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
- ZVAL_LONG(result, zend_compare_arrays(op1, op2));
- return SUCCESS;
+ return zend_compare_arrays(op1, op2);
case TYPE_PAIR(IS_NULL, IS_NULL):
case TYPE_PAIR(IS_NULL, IS_FALSE):
case TYPE_PAIR(IS_FALSE, IS_NULL):
case TYPE_PAIR(IS_FALSE, IS_FALSE):
case TYPE_PAIR(IS_TRUE, IS_TRUE):
- ZVAL_LONG(result, 0);
- return SUCCESS;
+ return 0;
case TYPE_PAIR(IS_NULL, IS_TRUE):
- ZVAL_LONG(result, -1);
- return SUCCESS;
+ return -1;
case TYPE_PAIR(IS_TRUE, IS_NULL):
- ZVAL_LONG(result, 1);
- return SUCCESS;
+ return 1;
case TYPE_PAIR(IS_STRING, IS_STRING):
if (Z_STR_P(op1) == Z_STR_P(op2)) {
- ZVAL_LONG(result, 0);
- return SUCCESS;
+ return 0;
}
- ZVAL_LONG(result, zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2)));
- return SUCCESS;
+ return zendi_smart_strcmp(Z_STR_P(op1), Z_STR_P(op2));
case TYPE_PAIR(IS_NULL, IS_STRING):
- ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
- return SUCCESS;
+ return Z_STRLEN_P(op2) == 0 ? 0 : -1;
case TYPE_PAIR(IS_STRING, IS_NULL):
- ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
- return SUCCESS;
+ return Z_STRLEN_P(op1) == 0 ? 0 : 1;
case TYPE_PAIR(IS_OBJECT, IS_NULL):
- ZVAL_LONG(result, 1);
- return SUCCESS;
+ return 1;
case TYPE_PAIR(IS_NULL, IS_OBJECT):
- ZVAL_LONG(result, -1);
- return SUCCESS;
+ return -1;
default:
if (Z_ISREF_P(op1)) {
@@ -2078,97 +2050,41 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2)
continue;
}
- if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
- ret = Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2);
- if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
- convert_compare_result_to_long(result);
- }
- return ret;
- } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
- ret = Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2);
- if (UNEXPECTED(Z_TYPE_P(result) != IS_LONG)) {
- convert_compare_result_to_long(result);
- }
- return ret;
+ if (Z_TYPE_P(op1) == IS_OBJECT
+ && Z_TYPE_P(op2) == IS_OBJECT
+ && Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
+ return 0;
+ } else if (Z_TYPE_P(op1) == IS_OBJECT) {
+ return Z_OBJ_HANDLER_P(op1, compare)(op1, op2);
+ } else if (Z_TYPE_P(op2) == IS_OBJECT) {
+ return Z_OBJ_HANDLER_P(op2, compare)(op1, op2);
}
- if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
- if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
- /* object handles are identical, apparently this is the same object */
- ZVAL_LONG(result, 0);
- return SUCCESS;
- }
- if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
- ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2));
- return SUCCESS;
- }
- }
- if (Z_TYPE_P(op1) == IS_OBJECT) {
- if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
- ZVAL_UNDEF(&tmp_free);
- if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) {
- ZVAL_LONG(result, 1);
- zend_free_obj_get_result(&tmp_free);
- return SUCCESS;
- }
- ret = compare_function(result, &tmp_free, op2);
- zend_free_obj_get_result(&tmp_free);
- return ret;
- }
- }
- if (Z_TYPE_P(op2) == IS_OBJECT) {
- if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
- ZVAL_UNDEF(&tmp_free);
- if (Z_OBJ_HT_P(op2)->cast_object(Z_OBJ_P(op2), &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) {
- ZVAL_LONG(result, -1);
- zend_free_obj_get_result(&tmp_free);
- return SUCCESS;
- }
- ret = compare_function(result, op1, &tmp_free);
- zend_free_obj_get_result(&tmp_free);
- return ret;
- } else if (Z_TYPE_P(op1) == IS_OBJECT) {
- ZVAL_LONG(result, 1);
- return SUCCESS;
- }
- }
if (!converted) {
if (Z_TYPE_P(op1) < IS_TRUE) {
- ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
- return SUCCESS;
+ return zval_is_true(op2) ? -1 : 0;
} else if (Z_TYPE_P(op1) == IS_TRUE) {
- ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
- return SUCCESS;
+ return zval_is_true(op2) ? 0 : 1;
} else if (Z_TYPE_P(op2) < IS_TRUE) {
- ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
- return SUCCESS;
+ return zval_is_true(op1) ? 1 : 0;
} else if (Z_TYPE_P(op2) == IS_TRUE) {
- ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
- return SUCCESS;
+ return zval_is_true(op1) ? 0 : -1;
} else {
- op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 1);
- op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 1);
+ op1 = _zendi_convert_scalar_to_number(op1, &op1_copy);
+ op2 = _zendi_convert_scalar_to_number(op2, &op2_copy);
if (EG(exception)) {
- if (result != op1) {
- ZVAL_UNDEF(result);
- }
- return FAILURE;
+ return 1; /* to stop comparison of arrays */
}
converted = 1;
}
} else if (Z_TYPE_P(op1)==IS_ARRAY) {
- ZVAL_LONG(result, 1);
- return SUCCESS;
+ return 1;
} else if (Z_TYPE_P(op2)==IS_ARRAY) {
- ZVAL_LONG(result, -1);
- return SUCCESS;
+ return -1;
} else {
ZEND_ASSERT(0);
zend_throw_error(NULL, "Unsupported operand types");
- if (result != op1) {
- ZVAL_UNDEF(result);
- }
- return FAILURE;
+ return 1;
}
}
}
@@ -2233,40 +2149,28 @@ ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zv
ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if (compare_function(result, op1, op2) == FAILURE) {
- return FAILURE;
- }
- ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
+ ZVAL_BOOL(result, zend_compare(op1, op2) == 0);
return SUCCESS;
}
/* }}} */
ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if (compare_function(result, op1, op2) == FAILURE) {
- return FAILURE;
- }
- ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
+ ZVAL_BOOL(result, (zend_compare(op1, op2) != 0));
return SUCCESS;
}
/* }}} */
ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if (compare_function(result, op1, op2) == FAILURE) {
- return FAILURE;
- }
- ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
+ ZVAL_BOOL(result, (zend_compare(op1, op2) < 0));
return SUCCESS;
}
/* }}} */
ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if (compare_function(result, op1, op2) == FAILURE) {
- return FAILURE;
- }
- ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
+ ZVAL_BOOL(result, (zend_compare(op1, op2) <= 0));
return SUCCESS;
}
/* }}} */
@@ -2910,12 +2814,7 @@ string_cmp:
static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
{
- zval result;
-
- if (compare_function(&result, z1, z2)==FAILURE) {
- return 1;
- }
- return Z_LVAL(result);
+ return zend_compare(z1, z2);
}
/* }}} */
@@ -2937,10 +2836,10 @@ ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2) /* {{{ */
return 0;
}
- if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
+ if (Z_OBJ_HT_P(o1)->compare == NULL) {
return 1;
} else {
- return Z_OBJ_HT_P(o1)->compare_objects(o1, o2);
+ return Z_OBJ_HT_P(o1)->compare(o1, o2);
}
}
/* }}} */
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index e225e5eace..860d71b1d5 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -396,6 +396,8 @@ again:
return result;
}
+ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2);
+
ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2);
ZEND_API int ZEND_FASTCALL numeric_compare_function(zval *op1, zval *op2);
@@ -850,7 +852,6 @@ static zend_always_inline int zend_fast_equal_strings(zend_string *s1, zend_stri
static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2)
{
- zval result;
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
return Z_LVAL_P(op1) == Z_LVAL_P(op2);
@@ -868,28 +869,23 @@ static zend_always_inline int fast_equal_check_function(zval *op1, zval *op2)
return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
}
}
- compare_function(&result, op1, op2);
- return Z_LVAL(result) == 0;
+ return zend_compare(op1, op2) == 0;
}
static zend_always_inline int fast_equal_check_long(zval *op1, zval *op2)
{
- zval result;
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
return Z_LVAL_P(op1) == Z_LVAL_P(op2);
}
- compare_function(&result, op1, op2);
- return Z_LVAL(result) == 0;
+ return zend_compare(op1, op2) == 0;
}
static zend_always_inline int fast_equal_check_string(zval *op1, zval *op2)
{
- zval result;
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
return zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
}
- compare_function(&result, op1, op2);
- return Z_LVAL(result) == 0;
+ return zend_compare(op1, op2) == 0;
}
static zend_always_inline zend_bool fast_is_identical_function(zval *op1, zval *op2)
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 4d60feabd1..9680f4553a 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -478,6 +478,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON
ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -487,7 +488,7 @@ ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -495,9 +496,10 @@ ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ if (ret == 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -572,6 +574,7 @@ ZEND_VM_C_LABEL(is_equal_double):
ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -581,7 +584,7 @@ ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -589,9 +592,10 @@ ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) {
+ if (ret != 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -666,6 +670,7 @@ ZEND_VM_C_LABEL(is_not_equal_double):
ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -675,7 +680,7 @@ ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2)
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -683,9 +688,10 @@ ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2)
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) {
+ if (ret < 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -745,6 +751,7 @@ ZEND_VM_C_LABEL(is_smaller_double):
ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -754,7 +761,7 @@ ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -762,9 +769,10 @@ ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) {
+ if (ret <= 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -5252,6 +5260,7 @@ ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -5261,14 +5270,15 @@ ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2)
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ if (ret == 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -8498,13 +8508,12 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp, *val;
+ zval key_tmp, *val;
result = NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
- compare_function(&result_tmp, op1, &key_tmp);
- if (Z_LVAL(result_tmp) == 0) {
+ if (zend_compare(op1, &key_tmp) == 0) {
result = val;
break;
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2b29fb63bb..07bc67cfd6 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -578,6 +578,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_shift_right_
static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -587,7 +588,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -595,9 +596,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ if (ret == 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -610,6 +612,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_equal_hel
static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -619,7 +622,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -627,9 +630,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) {
+ if (ret != 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -642,6 +646,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_not_equal
static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -651,7 +656,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -659,9 +664,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) {
+ if (ret < 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -674,6 +680,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_h
static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_or_equal_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -683,7 +690,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_1);
}
@@ -691,9 +698,10 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_is_smaller_o
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) {
+ if (ret <= 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -2101,6 +2109,7 @@ send_array:
static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_SPEC(zval *op_1, zval *op_2 ZEND_OPCODE_HANDLER_ARGS_DC)
{
+ int ret;
USE_OPLINE
SAVE_OPLINE();
@@ -2110,14 +2119,15 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_case_helper_
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
op_2 = ZVAL_UNDEFINED_OP2();
}
- compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ ret = zend_compare(op_1, op_2);
if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
zval_ptr_dtor_nogc(op_2);
}
if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
- if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ if (ret == 0) {
ZEND_VM_SMART_BRANCH_TRUE();
ZVAL_TRUE(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -6591,13 +6601,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CON
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp, *val;
+ zval key_tmp, *val;
result = NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
- compare_function(&result_tmp, op1, &key_tmp);
- if (Z_LVAL(result_tmp) == 0) {
+ if (zend_compare(op1, &key_tmp) == 0) {
result = val;
break;
}
@@ -18889,13 +18898,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_TMP_CONST_HANDLE
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp, *val;
+ zval key_tmp, *val;
result = NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
- compare_function(&result_tmp, op1, &key_tmp);
- if (Z_LVAL(result_tmp) == 0) {
+ if (zend_compare(op1, &key_tmp) == 0) {
result = val;
break;
}
@@ -24143,13 +24151,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_VAR_CONST_HANDLE
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp, *val;
+ zval key_tmp, *val;
result = NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
- compare_function(&result_tmp, op1, &key_tmp);
- if (Z_LVAL(result_tmp) == 0) {
+ if (zend_compare(op1, &key_tmp) == 0) {
result = val;
break;
}
@@ -41935,13 +41942,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IN_ARRAY_SPEC_CV_CONST_HANDLER
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp, *val;
+ zval key_tmp, *val;
result = NULL;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
- compare_function(&result_tmp, op1, &key_tmp);
- if (Z_LVAL(result_tmp) == 0) {
+ if (zend_compare(op1, &key_tmp) == 0) {
result = val;
break;
}