]> granicus.if.org Git - php/commitdiff
Separated zend_binary_assign_op_typed_ref() and zend_binary_assign_op_typed_prop...
authorDmitry Stogov <dmitry@zend.com>
Tue, 15 Jan 2019 15:49:05 +0000 (18:49 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 15 Jan 2019 15:49:05 +0000 (18:49 +0300)
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 3dbcff34b6ad0066f8d95ff58b1910c5f2926168..c86f7df169dea5dc9f714eeb5b7fede900eb494b 100644 (file)
@@ -1331,6 +1331,32 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *
        }
 }
 
+static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *ref, zval *value, binary_op_type binary_op EXECUTE_DATA_DC)
+{
+       zval z_copy;
+
+       binary_op(&z_copy, &ref->val, value);
+       if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()))) {
+               zval_ptr_dtor(&ref->val);
+               ZVAL_COPY_VALUE(&ref->val, &z_copy);
+       } else {
+               zval_ptr_dtor(&z_copy);
+       }
+}
+
+static zend_never_inline void zend_binary_assign_op_typed_prop(zend_property_info *prop_info, zval *zptr, zval *value, binary_op_type binary_op EXECUTE_DATA_DC)
+{
+       zval z_copy;
+
+       binary_op(&z_copy, zptr, value);
+       if (EXPECTED(zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
+               zval_ptr_dtor(zptr);
+               ZVAL_COPY_VALUE(zptr, &z_copy);
+       } else {
+               zval_ptr_dtor(&z_copy);
+       }
+}
+
 static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type EXECUTE_DATA_DC)
 {
        zend_long offset;
index 884a8552e4ec61c086d04d0e8f44401755d15739..bfbd371b38ead89d2782486a236d943b30e62043 100644 (file)
@@ -836,33 +836,29 @@ ZEND_VM_C_LABEL(assign_op_object):
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
 
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                               if (OP2_TYPE == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
-
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (OP2_TYPE == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -889,7 +885,6 @@ ZEND_VM_HELPER(zend_binary_assign_op_static_prop_helper, CONST|TMP|VAR|CV, UNUSE
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -902,26 +897,23 @@ ZEND_VM_HELPER(zend_binary_assign_op_static_prop_helper, CONST|TMP|VAR|CV, UNUSE
 
        value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -966,28 +958,17 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-                                       FREE_OP2();
-                                       FREE_OP(free_op_data1);
-                                       FREE_OP1_VAR_PTR();
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -1059,25 +1040,17 @@ ZEND_VM_HELPER(zend_binary_assign_op_simple_helper, VAR|CV, CONST|TMPVAR|CV, bin
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
index 22b96eb82288a7b4863134ae83fef44043940f8f..7ff5be8c29eb90137f667d8afd5e9c7f0b90c18b 100644 (file)
@@ -4441,7 +4441,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -4454,26 +4453,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -7118,7 +7114,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -7131,26 +7126,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -9018,7 +9010,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -9031,26 +9022,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -20345,7 +20333,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -20358,26 +20345,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -20904,7 +20888,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -20917,26 +20900,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -21596,7 +21576,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -21609,26 +21588,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -24258,33 +24234,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if (IS_CONST == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CONST == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -24311,7 +24283,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -24324,26 +24295,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -24388,28 +24356,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-                                       if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -24480,25 +24437,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -27193,33 +27142,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -27246,7 +27191,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -27259,26 +27203,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -27323,28 +27264,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-                                       zval_ptr_dtor_nogc(free_op2);
-                                       FREE_OP(free_op_data1);
-                                       if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                                       HANDLE_EXCEPTION();
+               do {
+                       if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -27416,25 +27346,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -30303,7 +30225,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -30316,26 +30237,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -30380,28 +30298,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-                                       if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -31874,33 +31781,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
 
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
-
-                               if (IS_CV == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CV == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -31952,28 +31855,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-                                       if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -32044,25 +31936,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -34882,33 +34766,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if (IS_CONST == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CONST == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -36929,33 +36809,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -39627,33 +39503,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if (IS_CV == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CV == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -43968,33 +43840,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
 
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
-
-                               if (IS_CONST == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CONST == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -44021,7 +43889,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -44034,26 +43901,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -44098,28 +43962,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -44190,25 +44043,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -48658,33 +48503,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
 
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
-
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -48711,7 +48552,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -48724,26 +48564,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -48788,28 +48625,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-                                       zval_ptr_dtor_nogc(free_op2);
-                                       FREE_OP(free_op_data1);
-
-                                       HANDLE_EXCEPTION();
+               do {
+                       if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -48881,25 +48707,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -52761,7 +52579,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
        zval *prop, *value;
        zend_property_info *prop_info;
        zend_reference *ref;
-       zend_bool is_typed_ref = 0;
 
        SAVE_OPLINE();
 
@@ -52774,26 +52591,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_static_prop_h
 
        value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data);
 
-       if (UNEXPECTED(Z_ISREF_P(prop))) {
-               ref = Z_REF_P(prop);
-               is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-               prop = Z_REFVAL_P(prop);
-       }
-
-       if (UNEXPECTED(prop_info->type || is_typed_ref)) {
-               /* special case for typed properties */
-               zval z_copy;
+       do {
+               if (UNEXPECTED(Z_ISREF_P(prop))) {
+                       ref = Z_REF_P(prop);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                               break;
+                       }
+                       prop = Z_REFVAL_P(prop);
+               }
 
-               binary_op(&z_copy, prop, value);
-               if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                       zval_ptr_dtor(prop);
-                       ZVAL_COPY_VALUE(prop, &z_copy);
+               if (UNEXPECTED(prop_info->type)) {
+                       /* special case for typed properties */
+                       zend_binary_assign_op_typed_prop(prop_info, prop, value, binary_op);
                } else {
-                       zval_ptr_dtor(&z_copy);
+                       binary_op(prop, prop, value);
                }
-       } else {
-               binary_op(prop, prop, value);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), prop);
@@ -52838,28 +52652,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -55635,33 +55438,29 @@ assign_op_object:
                        } else {
                                zval *orig_zptr = zptr;
                                zend_reference *ref;
-                               zend_bool is_typed_ref = 0;
-
-                               if (UNEXPECTED(Z_ISREF_P(zptr))) {
-                                       ref = Z_REF_P(zptr);
-                                       is_typed_ref = ZEND_REF_HAS_TYPE_SOURCES(ref);
-                                       zptr = Z_REFVAL_P(zptr);
-                               }
 
-                               if (IS_CV == IS_CONST) {
-                                       prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
-                               } else {
-                                       prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
-                               }
-                               if (UNEXPECTED(prop_info || is_typed_ref)) {
-                                       /* special case for typed properties */
-                                       zval z_copy;
+                               do {
+                                       if (UNEXPECTED(Z_ISREF_P(zptr))) {
+                                               ref = Z_REF_P(zptr);
+                                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                                       break;
+                                               }
+                                               zptr = Z_REFVAL_P(zptr);
+                                       }
 
-                                       binary_op(&z_copy, zptr, value);
-                                       if (EXPECTED(is_typed_ref ? zend_verify_ref_assignable_zval(ref, &z_copy, EX_USES_STRICT_TYPES()) : zend_verify_property_type(prop_info, &z_copy, EX_USES_STRICT_TYPES()))) {
-                                               zval_ptr_dtor(zptr);
-                                               ZVAL_COPY_VALUE(zptr, &z_copy);
+                                       if (IS_CV == IS_CONST) {
+                                               prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
                                        } else {
-                                               zval_ptr_dtor(&z_copy);
+                                               prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr);
                                        }
-                               } else {
-                                       binary_op(zptr, zptr, value);
-                               }
+                                       if (UNEXPECTED(prop_info)) {
+                                               /* special case for typed properties */
+                                               zend_binary_assign_op_typed_prop(prop_info, zptr, value, binary_op);
+                                       } else {
+                                               binary_op(zptr, zptr, value);
+                                       }
+                               } while (0);
 
                                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), zptr);
@@ -55713,28 +55512,17 @@ assign_dim_op_new_array:
 
                value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
 
-               if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
-                       zend_reference *ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                               zval tmp;
-                               binary_op(&tmp, var_ptr, value);
-                               if (EXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                                       zval_ptr_dtor(var_ptr);
-                                       ZVAL_COPY_VALUE(var_ptr, &tmp);
-                               } else {
-                                       zval_ptr_dtor(&tmp);
-
-                                       FREE_OP(free_op_data1);
-
-                                       HANDLE_EXCEPTION();
+               do {
+                       if (IS_CV != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               var_ptr = Z_REFVAL_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
                                }
-                       } else {
-                               binary_op(var_ptr, var_ptr, value);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -55805,25 +55593,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_simple_helper
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
        } else {
-               zend_reference *ref = NULL;
-               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-                       ref = Z_REF_P(var_ptr);
-                       var_ptr = Z_REFVAL_P(var_ptr);
-               }
-
-               if (UNEXPECTED(ref && ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval tmp;
-                       binary_op(&tmp, var_ptr, value);
-
-                       if (UNEXPECTED(zend_verify_ref_assignable_zval(ref, &tmp, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &tmp);
-                       } else {
-                               zval_ptr_dtor(&tmp);
+               do {
+                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                               zend_reference *ref = Z_REF_P(var_ptr);
+                               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                                       zend_binary_assign_op_typed_ref(ref, value, binary_op);
+                                       break;
+                               }
+                               var_ptr = Z_REFVAL_P(var_ptr);
                        }
-               } else {
                        binary_op(var_ptr, var_ptr, value);
-               }
+               } while (0);
 
                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);