From 27dc5986dfad5f1b59581d654ade52457cd116ba Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 11 Dec 2014 13:18:40 +0300 Subject: [PATCH] Moved zend_is_true() from zend_execute.h/zend_execute_API.c into zend_operators.h/zend_operators.c. Splited the most expensive part of inline i_zend_is_true() into a separate zend_object_is_true(). Replaced zendi_convert_to_long() with cals to zend_is_true(). --- Zend/zend_execute.h | 67 ----------------------------- Zend/zend_execute_API.c | 6 --- Zend/zend_operators.c | 94 +++++++++++++++-------------------------- Zend/zend_operators.h | 56 +++++++++++++++++++++++- 4 files changed, 88 insertions(+), 135 deletions(-) diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d4a46db043..f13624be47 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -40,7 +40,6 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC); ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC); ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value TSRMLS_DC); -ZEND_API int zend_is_true(zval *op TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class(zend_string *name TSRMLS_DC); ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload TSRMLS_DC); ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC); @@ -52,72 +51,6 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC); ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC); -static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC) -{ - int result; - -again: - switch (Z_TYPE_P(op)) { - case IS_UNDEF: - case IS_NULL: - case IS_FALSE: - result = 0; - break; - case IS_TRUE: - result = 1; - break; - case IS_LONG: - result = (Z_LVAL_P(op)?1:0); - break; - case IS_RESOURCE: - result = (Z_RES_HANDLE_P(op)?1:0); - break; - case IS_DOUBLE: - result = (Z_DVAL_P(op) ? 1 : 0); - break; - case IS_STRING: - if (Z_STRLEN_P(op) == 0 - || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { - result = 0; - } else { - result = 1; - } - break; - case IS_ARRAY: - result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); - break; - case IS_OBJECT: - if (Z_OBJ_HT_P(op)->cast_object) { - zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { - result = Z_TYPE(tmp) == IS_TRUE; - break; - } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); - } else if (Z_OBJ_HT_P(op)->get) { - zval rv; - zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); - if (Z_TYPE_P(tmp) != IS_OBJECT) { - /* for safety - avoid loop */ - convert_to_boolean(tmp); - result = Z_TYPE_P(tmp) == IS_TRUE; - zval_ptr_dtor(tmp); - break; - } - } - result = 1; - break; - case IS_REFERENCE: - op = Z_REFVAL_P(op); - goto again; - break; - default: - result = 0; - break; - } - return result; -} - static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type TSRMLS_DC) { do { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 7d5af4e9aa..2496f59136 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -501,12 +501,6 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ * } /* }}} */ -ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */ -{ - return i_zend_is_true(op TSRMLS_CC); -} -/* }}} */ - #define IS_VISITED_CONSTANT 0x80 #define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT) #define MARK_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index c045086520..5576937e61 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -259,49 +259,6 @@ try_again: /* }}} */ -/* {{{ zendi_convert_to_boolean */ -#define zendi_convert_to_boolean(op, holder, result) \ - if (op==result) { \ - convert_to_boolean(op); \ - } else if (Z_TYPE_P(op) != IS_FALSE && \ - Z_TYPE_P(op) != IS_TRUE) { \ - switch (Z_TYPE_P(op)) { \ - case IS_NULL: \ - ZVAL_BOOL(&holder, 0); \ - break; \ - case IS_RESOURCE: \ - ZVAL_BOOL(&holder, Z_RES_HANDLE_P(op) ? 1 : 0); \ - break; \ - case IS_LONG: \ - ZVAL_BOOL(&holder, Z_LVAL_P(op) ? 1 : 0); \ - break; \ - case IS_DOUBLE: \ - ZVAL_BOOL(&holder, Z_DVAL_P(op) ? 1 : 0); \ - break; \ - case IS_STRING: \ - if (Z_STRLEN_P(op) == 0 \ - || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \ - ZVAL_BOOL(&holder, 0); \ - } else { \ - ZVAL_BOOL(&holder, 1); \ - } \ - break; \ - case IS_ARRAY: \ - ZVAL_BOOL(&holder, zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \ - break; \ - case IS_OBJECT: \ - ZVAL_DUP(&(holder), (op)); \ - convert_to_boolean(&(holder)); \ - break; \ - default: \ - ZVAL_BOOL(&holder, 0); \ - break; \ - } \ - (op) = &(holder); \ - } - -/* }}} */ - /* {{{ convert_object_to_type */ #define convert_object_to_type(op, dst, ctype, conv_func) \ ZVAL_UNDEF(dst); \ @@ -1263,8 +1220,7 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) } } ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function); - zendi_convert_to_boolean(op1, op1_copy, result); - op1_val = (Z_TYPE_P(op1) == IS_TRUE); + op1_val = zval_is_true(op1); } } while (0); do { @@ -1284,8 +1240,7 @@ ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) } } ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR); - zendi_convert_to_boolean(op2, op2_copy, result); - op2_val = (Z_TYPE_P(op2) == IS_TRUE); + op2_val = zval_is_true(op2); } } while (0); @@ -1315,9 +1270,7 @@ ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */ } ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT); - zendi_convert_to_boolean(op1, op1_copy, result); - - ZVAL_BOOL(result, Z_TYPE_P(op1) == IS_FALSE); + ZVAL_BOOL(result, !zval_is_true(op1)); } return SUCCESS; } @@ -1953,20 +1906,16 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* { } if (!converted) { if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) { - zendi_convert_to_boolean(op2, op2_copy, result); - ZVAL_LONG(result, (Z_TYPE_P(op2) == IS_TRUE) ? -1 : 0); + ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) { - zendi_convert_to_boolean(op1, op1_copy, result); - ZVAL_LONG(result, (Z_TYPE_P(op1) == IS_TRUE) ? 1 : 0); + ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0); return SUCCESS; } else if (Z_TYPE_P(op1) == IS_TRUE) { - zendi_convert_to_boolean(op2, op2_copy, result); - ZVAL_LONG(result, (Z_TYPE_P(op2) == IS_TRUE) ? 0 : 1); + ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_TRUE) { - zendi_convert_to_boolean(op1, op1_copy, result); - ZVAL_LONG(result, (Z_TYPE_P(op1) == IS_TRUE) ? 0 : -1); + ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1); return SUCCESS; } else { zendi_convert_scalar_to_number(op1, op1_copy, result); @@ -2384,10 +2333,33 @@ try_again: } /* }}} */ -ZEND_API int zval_is_true(zval *op) /* {{{ */ +ZEND_API int zend_is_true(zval *op TSRMLS_DC) /* {{{ */ { - convert_to_boolean(op); - return (Z_TYPE_P(op) == IS_TRUE ? 1 : 0); + return i_zend_is_true(op TSRMLS_CC); +} +/* }}} */ + +ZEND_API int zend_object_is_true(zval *op TSRMLS_DC) /* {{{ */ +{ + if (Z_OBJ_HT_P(op)->cast_object) { + zval tmp; + if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL TSRMLS_CC) == SUCCESS) { + return Z_TYPE(tmp) == IS_TRUE; + } + zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", Z_OBJ_P(op)->ce->name->val); + } else if (Z_OBJ_HT_P(op)->get) { + int result; + zval rv; + zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv TSRMLS_CC); + + if (Z_TYPE_P(tmp) != IS_OBJECT) { + /* for safety - avoid loop */ + result = i_zend_is_true(tmp TSRMLS_CC); + zval_ptr_dtor(tmp); + return result; + } + } + return 1; } /* }}} */ diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index f95e856e68..d7967c458a 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -252,7 +252,61 @@ ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2 #define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); } #define convert_to_string(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_string((op) ZEND_FILE_LINE_CC); } -ZEND_API int zval_is_true(zval *op); + +ZEND_API int zend_is_true(zval *op TSRMLS_DC); +ZEND_API int zend_object_is_true(zval *op TSRMLS_DC); + +#define zval_is_true(op) \ + zend_is_true(op TSRMLS_CC) + +static zend_always_inline int i_zend_is_true(zval *op TSRMLS_DC) +{ + int result; + +again: + switch (Z_TYPE_P(op)) { + case IS_UNDEF: + case IS_NULL: + case IS_FALSE: + result = 0; + break; + case IS_TRUE: + result = 1; + break; + case IS_LONG: + result = (Z_LVAL_P(op)?1:0); + break; + case IS_RESOURCE: + result = (Z_RES_HANDLE_P(op)?1:0); + break; + case IS_DOUBLE: + result = (Z_DVAL_P(op) ? 1 : 0); + break; + case IS_STRING: + if (Z_STRLEN_P(op) == 0 + || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { + result = 0; + } else { + result = 1; + } + break; + case IS_ARRAY: + result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); + break; + case IS_OBJECT: + result = zend_object_is_true(op TSRMLS_CC); + break; + case IS_REFERENCE: + op = Z_REFVAL_P(op); + goto again; + break; + default: + result = 0; + break; + } + return result; +} + ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC); -- 2.40.0