]> granicus.if.org Git - php/commitdiff
Improved return by reference handling
authorDmitry Stogov <dmitry@zend.com>
Tue, 7 Oct 2014 18:38:37 +0000 (22:38 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 7 Oct 2014 18:38:37 +0000 (22:38 +0400)
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index fd4311c0bdb04b64ab1250bbc8627b4dc611afc8..91036489becb59ff167204d83fbb3add7e788649 100644 (file)
@@ -2698,17 +2698,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                        ZEND_VM_C_GOTO(fcall_end);
                }
        } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
-               zval *return_value = NULL;
-
                EG(scope) = fbc->common.scope;
-               call->symbol_table = NULL;
-               if (RETURN_VALUE_USED(opline)) {
-                       return_value = EX_VAR(opline->result.var);
-
-                       ZVAL_NULL(return_value);
-                       Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
-               }
-
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                        if (RETURN_VALUE_USED(opline)) {
                                zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC);
@@ -2718,6 +2708,16 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
        
                        zend_vm_stack_free_call_frame(call TSRMLS_CC);
                } else {
+                       zval *return_value = NULL;
+
+                       call->symbol_table = NULL;
+                       if (RETURN_VALUE_USED(opline)) {
+                               return_value = EX_VAR(opline->result.var);
+
+                               ZVAL_NULL(return_value);
+                               Z_VAR_FLAGS_P(return_value) = 0;
+                       }
+
                        call->prev_execute_data = execute_data;
                        i_init_func_execute_data(call, &fbc->op_array, return_value TSRMLS_CC);
 
@@ -2842,6 +2842,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
                                }
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                if (OP1_TYPE != IS_TMP_VAR) {
                                        zval_opt_copy_ctor_no_imm(EX(return_value));
                                }
@@ -2862,6 +2863,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
                                zend_error(E_NOTICE, "Only variable references should be returned by reference");
                                if (EX(return_value)) {
                                        ZVAL_NEW_REF(EX(return_value), retval_ptr);
+                                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                        if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
                                }
                                break;
@@ -2872,6 +2874,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
                        ZVAL_MAKE_REF(retval_ptr);
                        Z_ADDREF_P(retval_ptr);
                        ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
+                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                }
        } while (0);
 
index 4937bceda22f68f7e45600ec1dd4e66a3a5e01f0..fba611a1e2f78069ae07f079ab4a5f4b79a111fb 100644 (file)
@@ -580,17 +580,7 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        goto fcall_end;
                }
        } else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
-               zval *return_value = NULL;
-
                EG(scope) = fbc->common.scope;
-               call->symbol_table = NULL;
-               if (RETURN_VALUE_USED(opline)) {
-                       return_value = EX_VAR(opline->result.var);
-
-                       ZVAL_NULL(return_value);
-                       Z_VAR_FLAGS_P(return_value) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
-               }
-
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
                        if (RETURN_VALUE_USED(opline)) {
                                zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var) TSRMLS_CC);
@@ -600,6 +590,16 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
                        zend_vm_stack_free_call_frame(call TSRMLS_CC);
                } else {
+                       zval *return_value = NULL;
+
+                       call->symbol_table = NULL;
+                       if (RETURN_VALUE_USED(opline)) {
+                               return_value = EX_VAR(opline->result.var);
+
+                               ZVAL_NULL(return_value);
+                               Z_VAR_FLAGS_P(return_value) = 0;
+                       }
+
                        call->prev_execute_data = execute_data;
                        i_init_func_execute_data(call, &fbc->op_array, return_value TSRMLS_CC);
 
@@ -2648,6 +2648,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
                                }
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                if (IS_CONST != IS_TMP_VAR) {
                                        zval_opt_copy_ctor_no_imm(EX(return_value));
                                }
@@ -2668,6 +2669,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
                                zend_error(E_NOTICE, "Only variable references should be returned by reference");
                                if (EX(return_value)) {
                                        ZVAL_NEW_REF(EX(return_value), retval_ptr);
+                                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                        if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
                                }
                                break;
@@ -2678,6 +2680,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
                        ZVAL_MAKE_REF(retval_ptr);
                        Z_ADDREF_P(retval_ptr);
                        ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
+                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                }
        } while (0);
 
@@ -9474,6 +9477,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
                                }
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                if (IS_TMP_VAR != IS_TMP_VAR) {
                                        zval_opt_copy_ctor_no_imm(EX(return_value));
                                }
@@ -9494,6 +9498,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
                                zend_error(E_NOTICE, "Only variable references should be returned by reference");
                                if (EX(return_value)) {
                                        ZVAL_NEW_REF(EX(return_value), retval_ptr);
+                                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                        if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
                                }
                                break;
@@ -9504,6 +9509,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
                        ZVAL_MAKE_REF(retval_ptr);
                        Z_ADDREF_P(retval_ptr);
                        ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
+                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                }
        } while (0);
 
@@ -16036,6 +16042,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
                                }
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                if (IS_VAR != IS_TMP_VAR) {
                                        zval_opt_copy_ctor_no_imm(EX(return_value));
                                }
@@ -16056,6 +16063,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
                                zend_error(E_NOTICE, "Only variable references should be returned by reference");
                                if (EX(return_value)) {
                                        ZVAL_NEW_REF(EX(return_value), retval_ptr);
+                                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                        if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
                                }
                                break;
@@ -16066,6 +16074,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
                        ZVAL_MAKE_REF(retval_ptr);
                        Z_ADDREF_P(retval_ptr);
                        ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
+                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                }
        } while (0);
 
@@ -33680,6 +33689,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
                                }
                        } else {
                                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
+                               Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                if (IS_CV != IS_TMP_VAR) {
                                        zval_opt_copy_ctor_no_imm(EX(return_value));
                                }
@@ -33700,6 +33710,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
                                zend_error(E_NOTICE, "Only variable references should be returned by reference");
                                if (EX(return_value)) {
                                        ZVAL_NEW_REF(EX(return_value), retval_ptr);
+                                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                                        if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
                                }
                                break;
@@ -33710,6 +33721,7 @@ static int ZEND_FASTCALL  ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
                        ZVAL_MAKE_REF(retval_ptr);
                        Z_ADDREF_P(retval_ptr);
                        ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
+                       Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
                }
        } while (0);