]> granicus.if.org Git - php/commitdiff
Avoid copying of immutable arrays
authorDmitry Stogov <dmitry@zend.com>
Mon, 2 Jun 2014 22:43:53 +0000 (02:43 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 2 Jun 2014 22:43:53 +0000 (02:43 +0400)
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 7a2b6da99e00e0e049e6e8a055ee8c237a1c4d99..0e30ca304edc558de69878722a83f6d931e160d3 100644 (file)
@@ -150,7 +150,12 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
 
        zend_call_method_with_0_params(object, ce, &ce->__debugInfo, ZEND_DEBUGINFO_FUNC_NAME, &retval);
        if (Z_TYPE(retval) == IS_ARRAY) {
-               if (Z_REFCOUNT(retval) <= 1) {
+               if (Z_IMMUTABLE(retval)) {
+                       *is_temp = 1;
+                       ALLOC_HASHTABLE(ht);
+                       zend_array_dup(ht, Z_ARRVAL(retval));
+                       return ht;
+               } else if (Z_REFCOUNT(retval) <= 1) {
                        *is_temp = 1;
                        ALLOC_HASHTABLE(ht);
                        *ht = *Z_ARRVAL(retval);
@@ -159,6 +164,7 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC
                } else {
                        *is_temp = 0;
                        zval_ptr_dtor(&retval);
+                       return Z_ARRVAL(retval);
                }
        } else if (Z_TYPE(retval) == IS_NULL) {
                *is_temp = 1;
index 862a0a10ba60402a2af33c6871c78f58f00e519a..367ac86940d8f492d87f40f286a765762e24608d 100644 (file)
@@ -2823,7 +2823,7 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
        } else {
                if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {               
                        ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
-                       if (OP1_TYPE != IS_TMP_VAR) {
+                       if (OP1_TYPE == IS_CONST && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
                                zval_opt_copy_ctor(EX(return_value));
                        }
                } else if (Z_ISREF_P(retval_ptr)) {
@@ -2858,10 +2858,11 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
                                if (OP1_TYPE == IS_TMP_VAR) {
                                        FREE_OP1();
                                }
-                       } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
-                               ZVAL_DUP(EX(return_value), retval_ptr);
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               if (OP1_TYPE != IS_TMP_VAR && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
+                                       zval_opt_copy_ctor(EX(return_value));
+                               }
                        }
                        break;
                }
@@ -3737,8 +3738,10 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (OP1_TYPE == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -4932,7 +4935,9 @@ ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
 
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
        if (!IS_OP1_TMP_FREE()) {
-               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               }
        }
        FREE_OP1_IF_VAR();
        CHECK_EXCEPTION();
@@ -4953,7 +4958,9 @@ ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
        } else {
                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
                if (!IS_OP1_TMP_FREE()) {
-                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       }
                }
        }
 
index 8385c6b6708b217c941a8537366300c904ca623f..cfb733e455c64a9b0cebbef8723b019149699649 100644 (file)
@@ -2605,7 +2605,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
        } else {
                if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
                        ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
-                       if (IS_CONST != IS_TMP_VAR) {
+                       if (IS_CONST == IS_CONST && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
                                zval_opt_copy_ctor(EX(return_value));
                        }
                } else if (Z_ISREF_P(retval_ptr)) {
@@ -2640,10 +2640,11 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
                                if (IS_CONST == IS_TMP_VAR) {
 
                                }
-                       } else if (!0) { /* Not a temp var */
-                               ZVAL_DUP(EX(return_value), retval_ptr);
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               if (IS_CONST != IS_TMP_VAR && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
+                                       zval_opt_copy_ctor(EX(return_value));
+                               }
                        }
                        break;
                }
@@ -3262,7 +3263,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
 
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
        if (!0) {
-               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               }
        }
 
        CHECK_EXCEPTION();
@@ -3283,7 +3286,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
        } else {
                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
                if (!0) {
-                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       }
                }
        }
 
@@ -3996,8 +4001,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CONST == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -4862,8 +4869,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CONST == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -5692,8 +5701,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CONST == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -6365,8 +6376,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CONST == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -7253,8 +7266,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CONST == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -7731,7 +7746,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
                        ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
-                       if (IS_TMP_VAR != IS_TMP_VAR) {
+                       if (IS_TMP_VAR == IS_CONST && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
                                zval_opt_copy_ctor(EX(return_value));
                        }
                } else if (Z_ISREF_P(retval_ptr)) {
@@ -7766,10 +7781,11 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
                                if (IS_TMP_VAR == IS_TMP_VAR) {
                                        zval_dtor(free_op1.var);
                                }
-                       } else if (!1) { /* Not a temp var */
-                               ZVAL_DUP(EX(return_value), retval_ptr);
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               if (IS_TMP_VAR != IS_TMP_VAR && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
+                                       zval_opt_copy_ctor(EX(return_value));
+                               }
                        }
                        break;
                }
@@ -8418,7 +8434,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
 
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
        if (!1) {
-               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               }
        }
 
        CHECK_EXCEPTION();
@@ -8439,7 +8457,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
        } else {
                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
                if (!1) {
-                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       }
                }
        }
 
@@ -9074,8 +9094,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_TMP_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -9907,8 +9929,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_TMP_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -10737,8 +10761,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_TMP_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -11296,8 +11322,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_TMP_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -12111,8 +12139,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_TMP_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -12813,7 +12843,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
                        ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
-                       if (IS_VAR != IS_TMP_VAR) {
+                       if (IS_VAR == IS_CONST && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
                                zval_opt_copy_ctor(EX(return_value));
                        }
                } else if (Z_ISREF_P(retval_ptr)) {
@@ -12848,10 +12878,11 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
                                if (IS_VAR == IS_TMP_VAR) {
                                        zval_ptr_dtor_nogc(free_op1.var);
                                }
-                       } else if (!0) { /* Not a temp var */
-                               ZVAL_DUP(EX(return_value), retval_ptr);
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               if (IS_VAR != IS_TMP_VAR && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
+                                       zval_opt_copy_ctor(EX(return_value));
+                               }
                        }
                        break;
                }
@@ -13749,7 +13780,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
 
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
        if (!0) {
-               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               }
        }
        zval_ptr_dtor_nogc(free_op1.var);
        CHECK_EXCEPTION();
@@ -13770,7 +13803,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
        } else {
                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
                if (!0) {
-                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       }
                }
        }
 
@@ -15495,8 +15530,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -17623,8 +17660,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -19814,8 +19853,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -21259,8 +21300,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -23174,8 +23217,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_VAR == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -29910,7 +29955,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        } else {
                if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
                        ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
-                       if (IS_CV != IS_TMP_VAR) {
+                       if (IS_CV == IS_CONST && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
                                zval_opt_copy_ctor(EX(return_value));
                        }
                } else if (Z_ISREF_P(retval_ptr)) {
@@ -29945,10 +29990,11 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
                                if (IS_CV == IS_TMP_VAR) {
 
                                }
-                       } else if (!0) { /* Not a temp var */
-                               ZVAL_DUP(EX(return_value), retval_ptr);
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               if (IS_CV != IS_TMP_VAR && !Z_OPT_IMMUTABLE_P(EX(return_value))) {
+                                       zval_opt_copy_ctor(EX(return_value));
+                               }
                        }
                        break;
                }
@@ -30691,7 +30737,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
 
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
        if (!0) {
-               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+               }
        }
 
        CHECK_EXCEPTION();
@@ -30712,7 +30760,9 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
        } else {
                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
                if (!0) {
-                       zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       if (!Z_OPT_IMMUTABLE_P(EX_VAR(opline->result.var))) {
+                               zval_opt_copy_ctor(EX_VAR(opline->result.var));
+                       }
                }
        }
 
@@ -32228,8 +32278,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CV == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -34239,8 +34291,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CV == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -36312,8 +36366,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CV == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -37641,8 +37697,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CV == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;
@@ -39420,8 +39478,10 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
                        ZVAL_COPY_VALUE(&new_expr, expr_ptr);
                        expr_ptr = &new_expr;
                } else if (IS_CV == IS_CONST) {
-                       ZVAL_DUP(&new_expr, expr_ptr);
-                       expr_ptr = &new_expr;
+                       if (!Z_IMMUTABLE_P(expr_ptr)) {
+                               ZVAL_DUP(&new_expr, expr_ptr);
+                               expr_ptr = &new_expr;
+                       }
                } else if (Z_ISREF_P(expr_ptr)) {
                        ZVAL_DUP(&new_expr, Z_REFVAL_P(expr_ptr));
                        expr_ptr = &new_expr;