From: Dmitry Stogov Date: Wed, 10 Jan 2018 12:12:03 +0000 (+0300) Subject: Convert "sparse switch" statements into sequences of "if" with the most probable... X-Git-Tag: php-7.3.0alpha1~668 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9d7544aa1cdab4d5cb00643171d9d1a97fb558a1;p=php Convert "sparse switch" statements into sequences of "if" with the most probable conditions first --- diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 849163e2df..a8af4bf3f7 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -911,58 +911,60 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* { int converted = 0; while (1) { - switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { - case TYPE_PAIR(IS_LONG, IS_LONG): - fast_long_add_function(result, op1, op2); - return SUCCESS; - case TYPE_PAIR(IS_LONG, IS_DOUBLE): - ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2)); - return SUCCESS; + zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); - case TYPE_PAIR(IS_DOUBLE, IS_LONG): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2))); - return SUCCESS; + if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) { + fast_long_add_function(result, op1, op2); + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2)); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2)); + return SUCCESS; - case TYPE_PAIR(IS_ARRAY, IS_ARRAY): - if ((result == op1) && (result == op2)) { - /* $a += $a */ - return SUCCESS; - } - if (result != op1) { - ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1))); - } else { - SEPARATE_ARRAY(result); - } - zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0); + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) { + ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2)); + return SUCCESS; + + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2))); + return SUCCESS; + + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) { + if ((result == op1) && (result == op2)) { + /* $a += $a */ return SUCCESS; + } + if (result != op1) { + ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1))); + } else { + SEPARATE_ARRAY(result); + } + zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0); + return SUCCESS; - default: - if (Z_ISREF_P(op1)) { - op1 = Z_REFVAL_P(op1); - } else if (Z_ISREF_P(op2)) { - op2 = Z_REFVAL_P(op2); - } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function); + } else { + if (Z_ISREF_P(op1)) { + op1 = Z_REFVAL_P(op1); + } else if (Z_ISREF_P(op2)) { + op2 = Z_REFVAL_P(op2); + } else if (!converted) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function); - if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - op2 = op1; - } - converted = 1; + if (EXPECTED(op1 != op2)) { + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } else { - if (result != op1) { - ZVAL_UNDEF(result); - } - zend_throw_error(NULL, "Unsupported operand types"); - return FAILURE; /* unknown datatype */ + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op2 = op1; } + converted = 1; + } else { + if (result != op1) { + ZVAL_UNDEF(result); + } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ + } } } } @@ -974,45 +976,47 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* { int converted = 0; while (1) { - switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { - case TYPE_PAIR(IS_LONG, IS_LONG): - fast_long_sub_function(result, op1, op2); - return SUCCESS; - case TYPE_PAIR(IS_LONG, IS_DOUBLE): - ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2)); - return SUCCESS; + zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); - case TYPE_PAIR(IS_DOUBLE, IS_LONG): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2))); - return SUCCESS; + if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) { + fast_long_sub_function(result, op1, op2); + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2)); + return SUCCESS; - default: - if (Z_ISREF_P(op1)) { - op1 = Z_REFVAL_P(op1); - } else if (Z_ISREF_P(op2)) { - op2 = Z_REFVAL_P(op2); - } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function); + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) { + ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2)); + return SUCCESS; - if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - op2 = op1; - } - converted = 1; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2))); + return SUCCESS; + + } else { + if (Z_ISREF_P(op1)) { + op1 = Z_REFVAL_P(op1); + } else if (Z_ISREF_P(op2)) { + op2 = Z_REFVAL_P(op2); + } else if (!converted) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function); + + if (EXPECTED(op1 != op2)) { + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } else { - if (result != op1) { - ZVAL_UNDEF(result); - } - zend_throw_error(NULL, "Unsupported operand types"); - return FAILURE; /* unknown datatype */ + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op2 = op1; + } + converted = 1; + } else { + if (result != op1) { + ZVAL_UNDEF(result); } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ + } } } } @@ -1024,50 +1028,50 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* { int converted = 0; while (1) { - switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { - case TYPE_PAIR(IS_LONG, IS_LONG): { - zend_long overflow; + zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); - ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow); - Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; - return SUCCESS; + if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) { + zend_long overflow; - } - case TYPE_PAIR(IS_LONG, IS_DOUBLE): - ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2)); - return SUCCESS; + ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow); + Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_LONG): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2))); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2)); + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2)); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) { + ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2)); + return SUCCESS; - default: - if (Z_ISREF_P(op1)) { - op1 = Z_REFVAL_P(op1); - } else if (Z_ISREF_P(op2)) { - op2 = Z_REFVAL_P(op2); - } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function); + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) { + ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2))); + return SUCCESS; - if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - op2 = op1; - } - converted = 1; + } else { + if (Z_ISREF_P(op1)) { + op1 = Z_REFVAL_P(op1); + } else if (Z_ISREF_P(op2)) { + op2 = Z_REFVAL_P(op2); + } else if (!converted) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function); + + if (EXPECTED(op1 != op2)) { + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } else { - if (result != op1) { - ZVAL_UNDEF(result); - } - zend_throw_error(NULL, "Unsupported operand types"); - return FAILURE; /* unknown datatype */ + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op2 = op1; } + converted = 1; + } else { + if (result != op1) { + ZVAL_UNDEF(result); + } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ + } } } } @@ -1079,96 +1083,97 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { int converted = 0; while (1) { - switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { - case TYPE_PAIR(IS_LONG, IS_LONG): - if (Z_LVAL_P(op2) >= 0) { - zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2); + zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); - if (i == 0) { - ZVAL_LONG(result, 1L); - return SUCCESS; - } else if (l2 == 0) { - ZVAL_LONG(result, 0); - return SUCCESS; - } + if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) { + if (Z_LVAL_P(op2) >= 0) { + zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2); - while (i >= 1) { - zend_long overflow; - double dval = 0.0; - - if (i % 2) { - --i; - ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow); - if (overflow) { - ZVAL_DOUBLE(result, dval * pow(l2, i)); - return SUCCESS; - } - } else { - i /= 2; - ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow); - if (overflow) { - ZVAL_DOUBLE(result, (double)l1 * pow(dval, i)); - return SUCCESS; - } + if (i == 0) { + ZVAL_LONG(result, 1L); + return SUCCESS; + } else if (l2 == 0) { + ZVAL_LONG(result, 0); + return SUCCESS; + } + + while (i >= 1) { + zend_long overflow; + double dval = 0.0; + + if (i % 2) { + --i; + ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow); + if (overflow) { + ZVAL_DOUBLE(result, dval * pow(l2, i)); + return SUCCESS; + } + } else { + i /= 2; + ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow); + if (overflow) { + ZVAL_DOUBLE(result, (double)l1 * pow(dval, i)); + return SUCCESS; } } - /* i == 0 */ - ZVAL_LONG(result, l1); - } else { - ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2))); } - return SUCCESS; + /* i == 0 */ + ZVAL_LONG(result, l1); + } else { + ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2))); + } + return SUCCESS; - case TYPE_PAIR(IS_LONG, IS_DOUBLE): - ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2))); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) { + ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2))); + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_LONG): - ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2))); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) { + ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2))); + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2))); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) { + ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2))); + return SUCCESS; - default: - if (Z_ISREF_P(op1)) { - op1 = Z_REFVAL_P(op1); - } else if (Z_ISREF_P(op2)) { - op2 = Z_REFVAL_P(op2); - } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function); + } else { + if (Z_ISREF_P(op1)) { + op1 = Z_REFVAL_P(op1); + } else if (Z_ISREF_P(op2)) { + op2 = Z_REFVAL_P(op2); + } else if (!converted) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function); - if (EXPECTED(op1 != op2)) { - if (Z_TYPE_P(op1) == IS_ARRAY) { - ZVAL_LONG(result, 0); - return SUCCESS; - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - } - if (Z_TYPE_P(op2) == IS_ARRAY) { - ZVAL_LONG(result, 1L); - return SUCCESS; - } else { - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); - } + if (EXPECTED(op1 != op2)) { + if (Z_TYPE_P(op1) == IS_ARRAY) { + ZVAL_LONG(result, 0); + return SUCCESS; } else { - if (Z_TYPE_P(op1) == IS_ARRAY) { - ZVAL_LONG(result, 0); - return SUCCESS; - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - } - op2 = op1; + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + } + if (Z_TYPE_P(op2) == IS_ARRAY) { + ZVAL_LONG(result, 1L); + return SUCCESS; + } else { + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } - converted = 1; } else { - if (result != op1) { - ZVAL_UNDEF(result); + if (Z_TYPE_P(op1) == IS_ARRAY) { + ZVAL_LONG(result, 0); + return SUCCESS; + } else { + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); } - zend_throw_error(NULL, "Unsupported operand types"); - return FAILURE; + op2 = op1; + } + converted = 1; + } else { + if (result != op1) { + ZVAL_UNDEF(result); } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; + } } } } @@ -1180,68 +1185,69 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* { int converted = 0; while (1) { - switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { - case TYPE_PAIR(IS_LONG, IS_LONG): - if (Z_LVAL_P(op2) == 0) { - zend_error(E_WARNING, "Division by zero"); - ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2))); - return SUCCESS; - } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) { - /* Prevent overflow error/crash */ - ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1); - return SUCCESS; - } - if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */ - ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2)); - } else { - ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2)); - } - return SUCCESS; + zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2)); - case TYPE_PAIR(IS_DOUBLE, IS_LONG): - if (Z_LVAL_P(op2) == 0) { - zend_error(E_WARNING, "Division by zero"); - } - ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2)); + if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) { + if (Z_LVAL_P(op2) == 0) { + zend_error(E_WARNING, "Division by zero"); + ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2))); return SUCCESS; - - case TYPE_PAIR(IS_LONG, IS_DOUBLE): - if (Z_DVAL_P(op2) == 0) { - zend_error(E_WARNING, "Division by zero"); - } - ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2)); + } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) { + /* Prevent overflow error/crash */ + ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1); return SUCCESS; + } + if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */ + ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2)); + } else { + ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2)); + } + return SUCCESS; - case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - if (Z_DVAL_P(op2) == 0) { - zend_error(E_WARNING, "Division by zero"); - } - ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2)); - return SUCCESS; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) { + if (Z_DVAL_P(op2) == 0) { + zend_error(E_WARNING, "Division by zero"); + } + ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2)); + return SUCCESS; - default: - if (Z_ISREF_P(op1)) { - op1 = Z_REFVAL_P(op1); - } else if (Z_ISREF_P(op2)) { - op2 = Z_REFVAL_P(op2); - } else if (!converted) { - ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function); + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) { + if (Z_LVAL_P(op2) == 0) { + zend_error(E_WARNING, "Division by zero"); + } + ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2)); + return SUCCESS; - if (EXPECTED(op1 != op2)) { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - zendi_convert_scalar_to_number(op2, op2_copy, result, 0); - } else { - zendi_convert_scalar_to_number(op1, op1_copy, result, 0); - op2 = op1; - } - converted = 1; + } else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) { + if (Z_DVAL_P(op2) == 0) { + zend_error(E_WARNING, "Division by zero"); + } + ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2)); + return SUCCESS; + + } else { + if (Z_ISREF_P(op1)) { + op1 = Z_REFVAL_P(op1); + } else if (Z_ISREF_P(op2)) { + op2 = Z_REFVAL_P(op2); + } else if (!converted) { + ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function); + + if (EXPECTED(op1 != op2)) { + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } else { - if (result != op1) { - ZVAL_UNDEF(result); - } - zend_throw_error(NULL, "Unsupported operand types"); - return FAILURE; /* unknown datatype */ + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + op2 = op1; } + converted = 1; + } else { + if (result != op1) { + ZVAL_UNDEF(result); + } + zend_throw_error(NULL, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ + } } } }