Skip to content

Commit

Permalink
Moved zend_is_true() from zend_execute.h/zend_execute_API.c into zend…
Browse files Browse the repository at this point in the history
…_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().
  • Loading branch information
dstogov committed Dec 11, 2014
1 parent 634448e commit 27dc598
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 135 deletions.
67 changes: 0 additions & 67 deletions Zend/zend_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 {
Expand Down
6 changes: 0 additions & 6 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
94 changes: 33 additions & 61 deletions Zend/zend_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,49 +259,6 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */

/* }}} */

/* {{{ 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); \
Expand Down Expand Up @@ -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 {
Expand All @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -2384,10 +2333,33 @@ ZEND_API int decrement_function(zval *op1) /* {{{ */
}
/* }}} */

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;
}
/* }}} */

Expand Down
56 changes: 55 additions & 1 deletion Zend/zend_operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 27dc598

Please sign in to comment.