From: Dmitry Stogov Date: Mon, 2 Jun 2014 22:43:53 +0000 (+0400) Subject: Avoid copying of immutable arrays X-Git-Tag: POST_PHPNG_MERGE~230 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=af78ea1d9781edd0e733be63d0b2033a8c445da7;p=php Avoid copying of immutable arrays --- diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 7a2b6da99e..0e30ca304e 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 862a0a10ba..367ac86940 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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)); + } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8385c6b670..cfb733e455 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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;