summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2008-01-21 19:10:25 +0000
committerDmitry Stogov <dmitry@php.net>2008-01-21 19:10:25 +0000
commit7390459e2664346c17d10c2347a0f3b766b6ab83 (patch)
tree9365952d2a6112d6e0aac192392137e5463159c1 /Zend/zend_operators.c
parent13be31db35b74b38d8680aea4b08b4d3831d9092 (diff)
downloadphp-git-7390459e2664346c17d10c2347a0f3b766b6ab83.tar.gz
Yet another comparison optimisation for usual cases
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c99
1 files changed, 51 insertions, 48 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 415cdd1a00..d80dcffe3c 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1359,74 +1359,70 @@ static inline void zend_free_obj_get_result(zval *op)
}
}
-#define COMPARE_RETURN_AND_FREE(retval) \
- if (op1_free) {zend_free_obj_get_result(op1_free);} \
- if (op2_free) {zend_free_obj_get_result(op2_free);} \
- return retval;
-
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
+ int ret;
int converted = 0;
zval op1_copy, op2_copy;
- zval *op1_free = NULL, *op2_free = NULL;
+ zval *op_free;
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));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_LONG):
ZVAL_LONG(result, Z_DVAL_P(op1)>((double)Z_LVAL_P(op2))?1:(Z_DVAL_P(op1)<((double)Z_LVAL_P(op2))?-1:0));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_LONG, IS_DOUBLE):
ZVAL_LONG(result, ((double)Z_LVAL_P(op1))>Z_DVAL_P(op2)?1:(((double)Z_LVAL_P(op1))<Z_DVAL_P(op2)?-1:0));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
ZVAL_LONG(result, Z_DVAL_P(op1)>Z_DVAL_P(op2)?1:(Z_DVAL_P(op1)<Z_DVAL_P(op2)?-1:0));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
zend_compare_arrays(result, op1, op2 TSRMLS_CC);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_NULL):
ZVAL_LONG(result, 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_BOOL):
ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_BOOL, IS_NULL):
ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_BOOL, IS_BOOL):
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_STRING, IS_STRING):
zendi_smart_strcmp(result, op1, op2);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_STRING):
ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_STRING, IS_NULL):
ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_OBJECT, IS_NULL):
ZVAL_LONG(result, 1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_OBJECT):
ZVAL_LONG(result, -1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
/* If both are objects sharing the same comparision handler then use is */
@@ -1434,62 +1430,69 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
/* object handles are identical, apprently this is the same object */
ZVAL_LONG(result, 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
}
ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
}
/* break missing intentionally */
default:
- if (Z_TYPE_P(op1) == IS_OBJECT && !op1_free) {
+ if (Z_TYPE_P(op1) == IS_OBJECT) {
if (Z_OBJ_HT_P(op1)->get) {
- op1 = op1_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
- continue;
+ op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
+ ret = compare_function(result, op_free, op2 TSRMLS_CC);
+ zend_free_obj_get_result(op_free);
+ return ret;
} else if (Z_TYPE_P(op2) != IS_OBJECT &&
Z_OBJ_HT_P(op1)->cast_object) {
- ALLOC_INIT_ZVAL(op1_free);
- if (Z_OBJ_HT_P(op1)->cast_object(op1, op1_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
- op2_free = NULL;
+ ALLOC_INIT_ZVAL(op_free);
+ if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
ZVAL_LONG(result, 1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ zend_free_obj_get_result(op_free);
+ return SUCCESS;
}
- op1 = op1_free;
- continue;
+ ret = compare_function(result, op_free, op2 TSRMLS_CC);
+ zend_free_obj_get_result(op_free);
+ return ret;
}
}
- if (Z_TYPE_P(op2) == IS_OBJECT && !op2_free) {
+ if (Z_TYPE_P(op2) == IS_OBJECT) {
if (Z_OBJ_HT_P(op2)->get) {
- op2 = op2_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
- continue;
+ op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
+ ret = compare_function(result, op1, op_free TSRMLS_CC);
+ zend_free_obj_get_result(op_free);
+ return ret;
} else if (Z_TYPE_P(op1) != IS_OBJECT &&
Z_OBJ_HT_P(op2)->cast_object) {
- ALLOC_INIT_ZVAL(op2_free);
- if (Z_OBJ_HT_P(op2)->cast_object(op2, op2_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
+ ALLOC_INIT_ZVAL(op_free);
+ if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
ZVAL_LONG(result, -1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ zend_free_obj_get_result(op_free);
+ return SUCCESS;
}
- op2 = op2_free;
- continue;
+ ret = compare_function(result, op1, op_free TSRMLS_CC);
+ zend_free_obj_get_result(op_free);
+ return ret;
}
}
if (!converted) {
if (Z_TYPE_P(op1) == IS_NULL) {
zendi_convert_to_boolean(op2, op2_copy, result);
ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_NULL) {
zendi_convert_to_boolean(op1, op1_copy, result);
ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op1) == IS_BOOL) {
zendi_convert_to_boolean(op2, op2_copy, result);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_BOOL) {
zendi_convert_to_boolean(op1, op1_copy, result);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else {
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
@@ -1497,19 +1500,19 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
} else if (Z_TYPE_P(op1)==IS_ARRAY) {
ZVAL_LONG(result, 1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op2)==IS_ARRAY) {
ZVAL_LONG(result, -1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op1)==IS_OBJECT) {
ZVAL_LONG(result, 1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else if (Z_TYPE_P(op2)==IS_OBJECT) {
ZVAL_LONG(result, -1);
- COMPARE_RETURN_AND_FREE(SUCCESS);
+ return SUCCESS;
} else {
ZVAL_LONG(result, 0);
- COMPARE_RETURN_AND_FREE(FAILURE);
+ return FAILURE;
}
}
}