Skip to content

Commit aed3de1

Browse files
committed
Split add/sub_function(s) into fast and slow parts
1 parent df6bd50 commit aed3de1

File tree

1 file changed

+132
-99
lines changed

1 file changed

+132
-99
lines changed

Zend/zend_operators.c

Lines changed: 132 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -901,132 +901,165 @@ ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(zval *op) /* {{{ */
901901
}
902902
/* }}} */
903903

904-
ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
904+
static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
905905
{
906-
zval op1_copy, op2_copy;
907-
int converted = 0;
908-
909-
while (1) {
910-
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
911-
912-
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
913-
fast_long_add_function(result, op1, op2);
914-
return SUCCESS;
906+
if ((result == op1) && (result == op2)) {
907+
/* $a += $a */
908+
return;
909+
}
910+
if (result != op1) {
911+
ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1)));
912+
} else {
913+
SEPARATE_ARRAY(result);
914+
}
915+
zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
916+
}
917+
/* }}} */
915918

916-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
917-
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
918-
return SUCCESS;
919+
static zend_always_inline int add_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
920+
{
921+
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
919922

920-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
921-
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
922-
return SUCCESS;
923+
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
924+
fast_long_add_function(result, op1, op2);
925+
return SUCCESS;
926+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
927+
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
928+
return SUCCESS;
929+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
930+
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
931+
return SUCCESS;
932+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
933+
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
934+
return SUCCESS;
935+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) {
936+
add_function_array(result, op1, op2);
937+
return SUCCESS;
938+
} else {
939+
return FAILURE;
940+
}
941+
} /* }}} */
923942

924-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
925-
ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
926-
return SUCCESS;
943+
static zend_never_inline int ZEND_FASTCALL add_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
944+
{
945+
zval op1_copy, op2_copy;
946+
int converted = 0;
927947

928-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_ARRAY, IS_ARRAY))) {
929-
if ((result == op1) && (result == op2)) {
930-
/* $a += $a */
931-
return SUCCESS;
932-
}
933-
if (result != op1) {
934-
ZVAL_ARR(result, zend_array_dup(Z_ARR_P(op1)));
948+
while (1) {
949+
if (Z_ISREF_P(op1)) {
950+
op1 = Z_REFVAL_P(op1);
951+
} else if (Z_ISREF_P(op2)) {
952+
op2 = Z_REFVAL_P(op2);
953+
} else if (!converted) {
954+
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
955+
956+
if (EXPECTED(op1 != op2)) {
957+
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
958+
op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
935959
} else {
936-
SEPARATE_ARRAY(result);
960+
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
961+
op2 = op1;
937962
}
938-
zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
939-
return SUCCESS;
940-
941-
} else {
942-
if (Z_ISREF_P(op1)) {
943-
op1 = Z_REFVAL_P(op1);
944-
} else if (Z_ISREF_P(op2)) {
945-
op2 = Z_REFVAL_P(op2);
946-
} else if (!converted) {
947-
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
948-
949-
if (EXPECTED(op1 != op2)) {
950-
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
951-
op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
952-
} else {
953-
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
954-
op2 = op1;
955-
}
956-
if (EG(exception)) {
957-
if (result != op1) {
958-
ZVAL_UNDEF(result);
959-
}
960-
return FAILURE;
961-
}
962-
converted = 1;
963-
} else {
963+
if (EG(exception)) {
964964
if (result != op1) {
965965
ZVAL_UNDEF(result);
966966
}
967-
zend_throw_error(NULL, "Unsupported operand types");
968-
return FAILURE; /* unknown datatype */
967+
return FAILURE;
969968
}
969+
converted = 1;
970+
} else {
971+
if (result != op1) {
972+
ZVAL_UNDEF(result);
973+
}
974+
zend_throw_error(NULL, "Unsupported operand types");
975+
return FAILURE; /* unknown datatype */
970976
}
977+
if (add_function_fast(result, op1, op2) == SUCCESS) {
978+
return SUCCESS;
979+
}
980+
}
981+
} /* }}} */
982+
983+
ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
984+
{
985+
if (add_function_fast(result, op1, op2) == SUCCESS) {
986+
return SUCCESS;
987+
} else {
988+
return add_function_slow(result, op1, op2);
971989
}
972990
}
973991
/* }}} */
974992

975-
ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
993+
static zend_always_inline int sub_function_fast(zval *result, zval *op1, zval *op2) /* {{{ */
994+
{
995+
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
996+
997+
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
998+
fast_long_sub_function(result, op1, op2);
999+
return SUCCESS;
1000+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
1001+
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
1002+
return SUCCESS;
1003+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
1004+
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
1005+
return SUCCESS;
1006+
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
1007+
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
1008+
return SUCCESS;
1009+
} else {
1010+
return FAILURE;
1011+
}
1012+
}
1013+
/* }}} */
1014+
1015+
static zend_never_inline int ZEND_FASTCALL sub_function_slow(zval *result, zval *op1, zval *op2) /* {{{ */
9761016
{
9771017
zval op1_copy, op2_copy;
9781018
int converted = 0;
979-
9801019
while (1) {
981-
zend_uchar type_pair = TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2));
982-
983-
if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_LONG))) {
984-
fast_long_sub_function(result, op1, op2);
985-
return SUCCESS;
986-
987-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_DOUBLE))) {
988-
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
989-
return SUCCESS;
990-
991-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_LONG, IS_DOUBLE))) {
992-
ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
993-
return SUCCESS;
994-
995-
} else if (EXPECTED(type_pair == TYPE_PAIR(IS_DOUBLE, IS_LONG))) {
996-
ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
997-
return SUCCESS;
998-
999-
} else {
1000-
if (Z_ISREF_P(op1)) {
1001-
op1 = Z_REFVAL_P(op1);
1002-
} else if (Z_ISREF_P(op2)) {
1003-
op2 = Z_REFVAL_P(op2);
1004-
} else if (!converted) {
1005-
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
1006-
1007-
if (EXPECTED(op1 != op2)) {
1008-
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
1009-
op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
1010-
} else {
1011-
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
1012-
op2 = op1;
1013-
}
1014-
if (EG(exception)) {
1015-
if (result != op1) {
1016-
ZVAL_UNDEF(result);
1017-
}
1018-
return FAILURE;
1019-
}
1020-
converted = 1;
1020+
if (Z_ISREF_P(op1)) {
1021+
op1 = Z_REFVAL_P(op1);
1022+
} else if (Z_ISREF_P(op2)) {
1023+
op2 = Z_REFVAL_P(op2);
1024+
} else if (!converted) {
1025+
ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
1026+
1027+
if (EXPECTED(op1 != op2)) {
1028+
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
1029+
op2 = zendi_convert_scalar_to_number(op2, &op2_copy, result, 0);
10211030
} else {
1031+
op1 = zendi_convert_scalar_to_number(op1, &op1_copy, result, 0);
1032+
op2 = op1;
1033+
}
1034+
if (EG(exception)) {
10221035
if (result != op1) {
10231036
ZVAL_UNDEF(result);
10241037
}
1025-
zend_throw_error(NULL, "Unsupported operand types");
1026-
return FAILURE; /* unknown datatype */
1038+
return FAILURE;
10271039
}
1040+
converted = 1;
1041+
} else {
1042+
if (result != op1) {
1043+
ZVAL_UNDEF(result);
1044+
}
1045+
zend_throw_error(NULL, "Unsupported operand types");
1046+
return FAILURE; /* unknown datatype */
1047+
}
1048+
if (sub_function_fast(result, op1, op2) == SUCCESS) {
1049+
return SUCCESS;
10281050
}
10291051
}
1052+
1053+
}
1054+
/* }}} */
1055+
1056+
ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
1057+
{
1058+
if (sub_function_fast(result, op1, op2) == SUCCESS) {
1059+
return SUCCESS;
1060+
} else {
1061+
return sub_function_slow(result, op1, op2);
1062+
}
10301063
}
10311064
/* }}} */
10321065

0 commit comments

Comments
 (0)