Skip to content

Commit 98fa0e2

Browse files
committed
ZPP: Return double directly from zend_parse_arg_double_weak()
This idea is based on @ndossche previous PR to reduce codebloat: #18436 We can use NAN as a sentinel value as neither int nor string value can actually hold a NAN value.
1 parent 1bab072 commit 98fa0e2

File tree

3 files changed

+29
-24
lines changed

3 files changed

+29
-24
lines changed

Zend/zend_API.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -624,44 +624,46 @@ ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_l
624624
return zend_parse_arg_long_weak(arg, dest, arg_num);
625625
}
626626

627-
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */
627+
ZEND_API double ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, uint32_t arg_num) /* {{{ */
628628
{
629629
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
630-
*dest = (double)Z_LVAL_P(arg);
630+
return Z_LVAL_P(arg);
631631
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
632632
zend_long l;
633+
double dval;
633634
uint8_t type;
634635

635-
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
636+
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, &dval)) != IS_DOUBLE)) {
636637
if (EXPECTED(type != 0)) {
637-
*dest = (double)(l);
638+
return (double)(l);
638639
} else {
639-
return 0;
640+
return NAN;
640641
}
642+
} else {
643+
return dval;
641644
}
642645
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
643646
if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) {
644-
return 0;
647+
return NAN;
645648
}
646-
*dest = 0.0;
649+
return 0.0;
647650
} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
648-
*dest = 1.0;
651+
return 1.0;
649652
} else {
650-
return 0;
653+
return NAN;
651654
}
652-
return 1;
653655
}
654656
/* }}} */
655657

656-
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */
658+
ZEND_API double ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, uint32_t arg_num) /* {{{ */
657659
{
658660
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
659661
/* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
660-
*dest = (double)Z_LVAL_P(arg);
662+
return (double)Z_LVAL_P(arg);
661663
} else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
662-
return 0;
664+
return NAN;
663665
}
664-
return zend_parse_arg_double_weak(arg, dest, arg_num);
666+
return zend_parse_arg_double_weak(arg, arg_num);
665667
}
666668
/* }}} */
667669

Zend/zend_API.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,8 +2178,8 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, bool *dest
21782178
ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest, uint32_t arg_num);
21792179
ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num);
21802180
ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num);
2181-
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, double *dest, uint32_t arg_num);
2182-
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num);
2181+
ZEND_API double ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, uint32_t arg_num);
2182+
ZEND_API double ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, uint32_t arg_num);
21832183
ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, uint32_t arg_num);
21842184
ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, uint32_t arg_num);
21852185
ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num);
@@ -2253,7 +2253,8 @@ static zend_always_inline bool zend_parse_arg_double(const zval *arg, double *de
22532253
*is_null = 1;
22542254
*dest = 0.0;
22552255
} else {
2256-
return zend_parse_arg_double_slow(arg, dest, arg_num);
2256+
*dest = zend_parse_arg_double_slow(arg, arg_num);
2257+
return !zend_isnan(*dest);
22572258
}
22582259
return 1;
22592260
}

Zend/zend_execute.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -759,10 +759,13 @@ static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg)
759759
return false;
760760
}
761761
}
762-
if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, 0)) {
763-
zval_ptr_dtor(arg);
764-
ZVAL_DOUBLE(arg, dval);
765-
return true;
762+
if (type_mask & MAY_BE_DOUBLE) {
763+
dval = zend_parse_arg_double_weak(arg, 0);
764+
if (EXPECTED(!zend_isnan(dval))) {
765+
zval_ptr_dtor(arg);
766+
ZVAL_DOUBLE(arg, dval);
767+
return true;
768+
}
766769
}
767770
if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, 0)) {
768771
/* on success "arg" is converted to IS_STRING */
@@ -792,16 +795,15 @@ static bool can_convert_to_string(const zval *zv) {
792795
static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, const zval *arg)
793796
{
794797
zend_long lval;
795-
double dval;
796798
bool bval;
797799

798800
/* Pass (uint32_t)-1 as arg_num to indicate to ZPP not to emit any deprecation notice,
799801
* this is needed because the version with side effects also uses 0 (e.g. for typed properties) */
800802
if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval, (uint32_t)-1)) {
801803
return true;
802804
}
803-
if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, (uint32_t)-1)) {
804-
return true;
805+
if (type_mask & MAY_BE_DOUBLE) {
806+
return !zend_isnan(zend_parse_arg_double_weak(arg, (uint32_t)-1));
805807
}
806808
if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) {
807809
return true;

0 commit comments

Comments
 (0)