Skip to content

Commit 56b8b16

Browse files
committed
Optimization of INC/DEC helpers
1 parent 6ab04a6 commit 56b8b16

File tree

7 files changed

+257
-247
lines changed

7 files changed

+257
-247
lines changed

Zend/zend_compile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,9 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
999999
#define ZEND_SYMBOL_FUNCTION (1<<1)
10001000
#define ZEND_SYMBOL_CONST (1<<2)
10011001

1002+
/* All increment opcodes are even (decrement are odd) */
1003+
#define ZEND_IS_INCREMENT(opcode) (((opcode) & 1) == 0)
1004+
10021005
/* Pseudo-opcodes that are used only temporarily during compilation */
10031006
#define ZEND_PARENTHESIZED_CONCAT 252 /* removed with PHP 8 */
10041007
#define ZEND_GOTO 253

Zend/zend_execute.c

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,33 +1623,48 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re
16231623
return NULL;
16241624
}
16251625

1626-
static ZEND_COLD void zend_throw_incdec_ref_error(zend_reference *ref, zend_bool inc)
1626+
static ZEND_COLD zend_long zend_throw_incdec_ref_error(zend_reference *ref OPLINE_DC)
16271627
{
16281628
zend_property_info *error_prop = zend_get_prop_not_accepting_double(ref);
16291629
/* Currently there should be no way for a typed reference to accept both int and double.
16301630
* Generalize this and the related property code once this becomes possible. */
16311631
ZEND_ASSERT(error_prop);
1632-
zend_type_error(
1633-
"Cannot %s a reference held by property %s::$%s of type %sint past its %simal value",
1634-
inc ? "increment" : "decrement",
1635-
ZSTR_VAL(error_prop->ce->name),
1636-
zend_get_unmangled_property_name(error_prop->name),
1637-
ZEND_TYPE_ALLOW_NULL(error_prop->type) ? "?" : "",
1638-
inc ? "max" : "min");
1632+
if (ZEND_IS_INCREMENT(opline->opcode)) {
1633+
zend_type_error(
1634+
"Cannot increment a reference held by property %s::$%s of type %sint past its maximal value",
1635+
ZSTR_VAL(error_prop->ce->name),
1636+
zend_get_unmangled_property_name(error_prop->name),
1637+
ZEND_TYPE_ALLOW_NULL(error_prop->type) ? "?" : "");
1638+
return ZEND_LONG_MAX;
1639+
} else {
1640+
zend_type_error(
1641+
"Cannot decrement a reference held by property %s::$%s of type %sint past its minimal value",
1642+
ZSTR_VAL(error_prop->ce->name),
1643+
zend_get_unmangled_property_name(error_prop->name),
1644+
ZEND_TYPE_ALLOW_NULL(error_prop->type) ? "?" : "");
1645+
return ZEND_LONG_MIN;
1646+
}
16391647
}
16401648

1641-
static ZEND_COLD void zend_throw_incdec_prop_error(zend_property_info *prop, zend_bool inc) {
1649+
static ZEND_COLD zend_long zend_throw_incdec_prop_error(zend_property_info *prop OPLINE_DC) {
16421650
const char *prop_type1, *prop_type2;
16431651
zend_format_type(prop->type, &prop_type1, &prop_type2);
1644-
zend_type_error("Cannot %s property %s::$%s of type %s%s past its %simal value",
1645-
inc ? "increment" : "decrement",
1646-
ZSTR_VAL(prop->ce->name),
1647-
zend_get_unmangled_property_name(prop->name),
1648-
prop_type1, prop_type2,
1649-
inc ? "max" : "min");
1652+
if (ZEND_IS_INCREMENT(opline->opcode)) {
1653+
zend_type_error("Cannot increment property %s::$%s of type %s%s past its maximal value",
1654+
ZSTR_VAL(prop->ce->name),
1655+
zend_get_unmangled_property_name(prop->name),
1656+
prop_type1, prop_type2);
1657+
return ZEND_LONG_MAX;
1658+
} else {
1659+
zend_type_error("Cannot decrement property %s::$%s of type %s%s past its minimal value",
1660+
ZSTR_VAL(prop->ce->name),
1661+
zend_get_unmangled_property_name(prop->name),
1662+
prop_type1, prop_type2);
1663+
return ZEND_LONG_MIN;
1664+
}
16501665
}
16511666

1652-
static void zend_incdec_typed_ref(zend_reference *ref, zval *copy, int inc EXECUTE_DATA_DC)
1667+
static void zend_incdec_typed_ref(zend_reference *ref, zval *copy OPLINE_DC EXECUTE_DATA_DC)
16531668
{
16541669
zval tmp;
16551670
zval *var_ptr = &ref->val;
@@ -1660,15 +1675,15 @@ static void zend_incdec_typed_ref(zend_reference *ref, zval *copy, int inc EXECU
16601675

16611676
ZVAL_COPY(copy, var_ptr);
16621677

1663-
if (inc) {
1678+
if (ZEND_IS_INCREMENT(opline->opcode)) {
16641679
increment_function(var_ptr);
16651680
} else {
16661681
decrement_function(var_ptr);
16671682
}
16681683

16691684
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) {
1670-
zend_throw_incdec_ref_error(ref, inc);
1671-
ZVAL_COPY_VALUE(var_ptr, copy);
1685+
zend_long val = zend_throw_incdec_ref_error(ref OPLINE_CC);
1686+
ZVAL_LONG(var_ptr, val);
16721687
} else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
16731688
zval_ptr_dtor(var_ptr);
16741689
ZVAL_COPY_VALUE(var_ptr, copy);
@@ -1678,7 +1693,7 @@ static void zend_incdec_typed_ref(zend_reference *ref, zval *copy, int inc EXECU
16781693
}
16791694
}
16801695

1681-
static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr, zval *copy, int inc EXECUTE_DATA_DC)
1696+
static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr, zval *copy OPLINE_DC EXECUTE_DATA_DC)
16821697
{
16831698
zval tmp;
16841699

@@ -1688,15 +1703,15 @@ static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr,
16881703

16891704
ZVAL_COPY(copy, var_ptr);
16901705

1691-
if (inc) {
1706+
if (ZEND_IS_INCREMENT(opline->opcode)) {
16921707
increment_function(var_ptr);
16931708
} else {
16941709
decrement_function(var_ptr);
16951710
}
16961711

16971712
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) {
1698-
zend_throw_incdec_prop_error(prop_info, inc);
1699-
ZVAL_COPY_VALUE(var_ptr, copy);
1713+
zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
1714+
ZVAL_LONG(var_ptr, val);
17001715
} else if (UNEXPECTED(!zend_verify_property_type(prop_info, var_ptr, EX_USES_STRICT_TYPES()))) {
17011716
zval_ptr_dtor(var_ptr);
17021717
ZVAL_COPY_VALUE(var_ptr, copy);
@@ -1706,36 +1721,32 @@ static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr,
17061721
}
17071722
}
17081723

1709-
static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_info, int inc OPLINE_DC EXECUTE_DATA_DC)
1724+
static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
17101725
{
17111726
if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
1712-
if (inc) {
1727+
if (ZEND_IS_INCREMENT(opline->opcode)) {
17131728
fast_long_increment_function(prop);
17141729
} else {
17151730
fast_long_decrement_function(prop);
17161731
}
17171732
if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info)) {
1718-
zend_throw_incdec_prop_error(prop_info, inc);
1719-
if (inc) {
1720-
ZVAL_LONG(prop, ZEND_LONG_MAX);
1721-
} else {
1722-
ZVAL_LONG(prop, ZEND_LONG_MIN);
1723-
}
1733+
zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
1734+
ZVAL_LONG(prop, val);
17241735
}
17251736
} else {
17261737
do {
17271738
if (Z_ISREF_P(prop)) {
17281739
zend_reference *ref = Z_REF_P(prop);
17291740
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1730-
zend_incdec_typed_ref(ref, NULL, inc EXECUTE_DATA_CC);
1741+
zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC);
17311742
break;
17321743
}
17331744
prop = Z_REFVAL_P(prop);
17341745
}
17351746

17361747
if (UNEXPECTED(prop_info)) {
1737-
zend_incdec_typed_prop(prop_info, prop, NULL, inc EXECUTE_DATA_CC);
1738-
} else if (inc) {
1748+
zend_incdec_typed_prop(prop_info, prop, NULL OPLINE_CC EXECUTE_DATA_CC);
1749+
} else if (ZEND_IS_INCREMENT(opline->opcode)) {
17391750
increment_function(prop);
17401751
} else {
17411752
decrement_function(prop);
@@ -1747,38 +1758,34 @@ static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_i
17471758
}
17481759
}
17491760

1750-
static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_info, int inc OPLINE_DC EXECUTE_DATA_DC)
1761+
static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
17511762
{
17521763
if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
17531764
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(prop));
1754-
if (inc) {
1765+
if (ZEND_IS_INCREMENT(opline->opcode)) {
17551766
fast_long_increment_function(prop);
17561767
} else {
17571768
fast_long_decrement_function(prop);
17581769
}
17591770
if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && UNEXPECTED(prop_info)) {
1760-
zend_throw_incdec_prop_error(prop_info, inc);
1761-
if (inc) {
1762-
ZVAL_LONG(prop, ZEND_LONG_MAX);
1763-
} else {
1764-
ZVAL_LONG(prop, ZEND_LONG_MIN);
1765-
}
1771+
zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
1772+
ZVAL_LONG(prop, val);
17661773
}
17671774
} else {
17681775
if (Z_ISREF_P(prop)) {
17691776
zend_reference *ref = Z_REF_P(prop);
17701777
if (ZEND_REF_HAS_TYPE_SOURCES(ref)) {
1771-
zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), inc EXECUTE_DATA_CC);
1778+
zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
17721779
return;
17731780
}
17741781
prop = Z_REFVAL_P(prop);
17751782
}
17761783

17771784
if (UNEXPECTED(prop_info)) {
1778-
zend_incdec_typed_prop(prop_info, prop, EX_VAR(opline->result.var), inc EXECUTE_DATA_CC);
1785+
zend_incdec_typed_prop(prop_info, prop, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
17791786
} else {
17801787
ZVAL_COPY(EX_VAR(opline->result.var), prop);
1781-
if (inc) {
1788+
if (ZEND_IS_INCREMENT(opline->opcode)) {
17821789
increment_function(prop);
17831790
} else {
17841791
decrement_function(prop);
@@ -1787,7 +1794,7 @@ static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_
17871794
}
17881795
}
17891796

1790-
static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
1797+
static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
17911798
{
17921799
zval rv, obj;
17931800
zval *z;
@@ -1813,7 +1820,7 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zval *object,
18131820

18141821
ZVAL_COPY_DEREF(&z_copy, z);
18151822
ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
1816-
if (inc) {
1823+
if (ZEND_IS_INCREMENT(opline->opcode)) {
18171824
increment_function(&z_copy);
18181825
} else {
18191826
decrement_function(&z_copy);
@@ -1824,7 +1831,7 @@ static zend_never_inline void zend_post_incdec_overloaded_property(zval *object,
18241831
zval_ptr_dtor(z);
18251832
}
18261833

1827-
static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
1834+
static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
18281835
{
18291836
zval rv;
18301837
zval *z, obj;
@@ -1851,7 +1858,7 @@ static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object,
18511858
ZVAL_COPY_VALUE(z, value);
18521859
}
18531860
ZVAL_COPY_DEREF(&z_copy, z);
1854-
if (inc) {
1861+
if (ZEND_IS_INCREMENT(opline->opcode)) {
18551862
increment_function(&z_copy);
18561863
} else {
18571864
decrement_function(&z_copy);

0 commit comments

Comments
 (0)