]> granicus.if.org Git - php/commitdiff
Fixed support for extra arguments in conjunction with variadiv argument.
authorDmitry Stogov <dmitry@zend.com>
Mon, 30 Jun 2014 10:17:17 +0000 (14:17 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 30 Jun 2014 10:17:17 +0000 (14:17 +0400)
Use compile time flags to check if we call constructor and result of ZEND_NEW is used or not.

Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index d084c564e71cd564602545d729fde13406dc1e0c..df81c5d666995de01c6ac6f72cfbc3b322d0bea6 100644 (file)
@@ -409,7 +409,7 @@ ZEND_FUNCTION(func_num_args)
    Get the $arg_num'th argument that was passed to the function */
 ZEND_FUNCTION(func_get_arg)
 {
-       int arg_count;
+       int arg_count, first_extra_arg;
        zval *arg;
        long requested_offset;
        zend_execute_data *ex;
@@ -436,8 +436,12 @@ ZEND_FUNCTION(func_get_arg)
                RETURN_FALSE;
        }
 
-       if (requested_offset >= ex->func->op_array.num_args && (ex->num_args > ex->func->op_array.num_args)) {
-               arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - ex->func->op_array.num_args);
+       first_extra_arg = ex->func->op_array.num_args;
+       if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+               first_extra_arg--;
+       }
+       if (requested_offset >= first_extra_arg && (ex->num_args > first_extra_arg)) {
+               arg = EX_VAR_NUM_2(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
        } else {
                arg = ZEND_CALL_ARG(ex, requested_offset + 1);
        }
@@ -450,7 +454,7 @@ ZEND_FUNCTION(func_get_arg)
 ZEND_FUNCTION(func_get_args)
 {
        zval *p;
-       int arg_count;
+       int arg_count, first_extra_arg;
        int i;
        zend_execute_data *ex = EG(current_execute_data);
 
@@ -465,12 +469,16 @@ ZEND_FUNCTION(func_get_args)
        if (arg_count) {
                Bucket *q;              
 
+               first_extra_arg = ex->func->op_array.num_args;
+               if (ex->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+                       first_extra_arg--;
+               }
                zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
                i = 0;
                q = Z_ARRVAL_P(return_value)->arData;
                p = ZEND_CALL_ARG(ex, 1);
-               if (ex->num_args > ex->func->op_array.num_args) {
-                       while (i < ex->func->op_array.num_args) {
+               if (ex->num_args > first_extra_arg) {
+                       while (i < first_extra_arg) {
                                q->h = i;
                                q->key = NULL;
                                if (!Z_ISREF_P(p)) {
@@ -1985,14 +1993,21 @@ static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array TS
                int i = 0;
                zval *p = ZEND_CALL_ARG(call, 1);
 
-               if (call->func->type == ZEND_USER_FUNCTION && (call->num_args > call->func->op_array.num_args)) {
-                       while (i < call->func->op_array.num_args) {
-                               if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
-                               zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
-                               p++;
-                               i++;
+               if (call->func->type == ZEND_USER_FUNCTION) {
+                       int first_extra_arg = call->func->op_array.num_args;
+                       
+                       if (call->func->op_array.fn_flags & ZEND_ACC_VARIADIC) {
+                               first_extra_arg--;
+                       }
+                       if (call->num_args > first_extra_arg) {
+                               while (i < first_extra_arg) {
+                                       if (Z_REFCOUNTED_P(p)) Z_ADDREF_P(p);
+                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(arg_array), p);
+                                       p++;
+                                       i++;
+                               }
+                               p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
                        }
-                       p = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
                }
 
                while (i < num_args) {
index 0434e7c754677fb328281bdb0bfffd524467de91..a49195d407c39cf07703e12f53331036a2c86f80 100644 (file)
@@ -1461,6 +1461,11 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
                                        && opline->result.var == op1->u.op.var) {
                                        if (opline->opcode == ZEND_NEW) {
                                                opline->result_type |= EXT_TYPE_UNUSED;
+                                               opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
+                                               while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
+                                                       opline--;
+                                               }
+                                               opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
                                        }
                                        break;
                                }
@@ -2544,13 +2549,20 @@ void zend_do_end_function_call(znode *function_name, znode *result, int is_metho
                }
                opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
        } else {
+               zend_uint call_flags = 0;
+
                opline = &CG(active_op_array)->opcodes[fcall->op_number];
                opline->extended_value = fcall->arg_num;
 
+               if (opline->opcode == ZEND_NEW) {
+                       call_flags = ZEND_CALL_CTOR;
+               }
+
                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                opline->opcode = ZEND_DO_FCALL;
                SET_UNUSED(opline->op1);
                SET_UNUSED(opline->op2);
+               opline->op1.num = call_flags;
        }
 
        opline->result.var = get_temporary_variable(CG(active_op_array));
index 5c4aae7fbbcdf33df356246602bdc2fcda8f02ee..b053ee9820b86c584b2cf190f712a0f42b240b35 100644 (file)
@@ -379,7 +379,7 @@ struct _zend_execute_data {
 };
 
 #define ZEND_CALL_CTOR               (1 << 0)
-#define ZEND_CALL_CTOR_RESULT_USED   (1 << 1)
+#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 1)
 #define ZEND_CALL_DONE               (1 << 2)
 
 #define ZEND_CALL_FRAME_SLOT \
@@ -741,7 +741,6 @@ int zend_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC);
 #define ZEND_PARSED_NEW                                        (1<<6)
 #define ZEND_PARSED_LIST_EXPR                  (1<<7)
 
-
 /* unset types */
 #define ZEND_UNSET_REG 0
 
index 7e94642aa8cdc5e1228a2a12b7546dcbc537fafc..5318bbe2d3b584eb3f0e294a5be0a8bee1a5d27e 100644 (file)
@@ -1556,18 +1556,22 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
 
        EG(opline_ptr) = &EX(opline);
        EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
-//???  EX(func) = (zend_function*)op_array;
        EX(scope) = EG(scope);
        EX(symbol_table) = EG(active_symbol_table);
 
        if (UNEXPECTED(EX(symbol_table) != NULL)) {
                zend_attach_symbol_table(execute_data);
        } else {
-
-               if (UNEXPECTED(EX(num_args) > op_array->num_args)) {
+               zend_uint first_extra_arg = op_array->num_args;
+               
+               if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_VARIADIC) != 0)) {
+                       first_extra_arg--;
+               }
+               if (UNEXPECTED(EX(num_args) > first_extra_arg)) {
                        /* move extra args into separate array after all CV and TMP vars */
                        zval *extra_args = EX_VAR_NUM(op_array->last_var + op_array->T);
-                       memmove(extra_args, EX_VAR_NUM(op_array->num_args), sizeof(zval) * (EX(num_args) - op_array->num_args));
+
+                       memmove(extra_args, EX_VAR_NUM(first_extra_arg), sizeof(zval) * (EX(num_args) - first_extra_arg));
                }
 
                do {
index 92022621893b9abf2eef0c1c3eaf42c0be41c999..40f42ae2dda5ef70f702473ec9ac69a15135aec6 100644 (file)
@@ -211,7 +211,7 @@ static zend_always_inline void zend_vm_stack_extend(int count TSRMLS_DC)
        EG(argument_stack) = p;
 }
 
-static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uint flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
+static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_function *func, zend_uint num_args, zend_uchar flags, zend_class_entry *called_scope, zend_object *object, zend_execute_data *prev TSRMLS_DC)
 {
        int used_stack = ZEND_CALL_FRAME_SLOT + num_args;
        zend_execute_data *call;
@@ -223,7 +223,7 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_
        call = (zend_execute_data*)EG(argument_stack)->top;
        EG(argument_stack)->top += used_stack;
        call->func = func;
-       call->num_args = 0; //??? num_args;
+       call->num_args = 0;
        call->flags = flags;
        call->called_scope = called_scope;
        call->object = object;
@@ -233,9 +233,11 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(zend_
 
 static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call TSRMLS_DC)
 {
-       if (UNEXPECTED(call->num_args > call->func->op_array.num_args)) {
+       zend_uint first_extra_arg = call->func->op_array.num_args - ((call->func->common.fn_flags & ZEND_ACC_VARIADIC) != 0);
+
+       if (UNEXPECTED(call->num_args > first_extra_arg)) {
                zval *end = EX_VAR_NUM_2(call, call->func->op_array.last_var + call->func->op_array.T);
-               zval *p = end + (call->num_args - call->func->op_array.num_args);
+               zval *p = end + (call->num_args - first_extra_arg);
                do {
                        p--;
                        i_zval_ptr_dtor_nogc(p ZEND_FILE_LINE_CC TSRMLS_CC);
index 2a9af52d6729d1900f09b879e122e52826d72067..54a33fe1afbc361f3cb7b6d6608124a82d752b93 100644 (file)
@@ -1773,7 +1773,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
        zend_execute_data *prev_nested_call;
-       zend_uint call_flags;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -1785,7 +1784,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
                        zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
                }
-               call_flags = EX(flags);
                prev_nested_call = EX(prev_nested_call);
                zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
                zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
@@ -1797,8 +1795,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                EG(active_symbol_table) = EX(symbol_table);
 
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
-                               if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+                               if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -2576,10 +2574,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
        USE_OPLINE
        zend_execute_data *call = EX(call);
        zend_function *fbc = call->func;
-       zend_uint call_flags = call->flags;
 
        SAVE_OPLINE();
-       call->flags |= ZEND_CALL_DONE;
+       call->flags = ZEND_CALL_DONE;
        if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
                        zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@@ -2753,8 +2750,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
 
 ZEND_VM_C_LABEL(fcall_end_change_scope):
        if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
-                       if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
+               if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
+                       if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -3343,31 +3340,23 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
        params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
 
        if (arg_num <= arg_count) {
-               zval *param, tmp;
+               zval *param;
 
-               ZVAL_COPY_VALUE(&tmp, params);
                array_init_size(params, arg_count - arg_num + 1);
                param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
                if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
-                       zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC);
-                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
-                       if (param) {
-                               while (++arg_num <= arg_count) {
-                                       zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
-                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                                       param++;
-                               }
-                       }
+                       do {                    
+                               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                               param++;
+                       } while (++arg_num <= arg_count);
                } else {
-                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
-                       if (param) {
-                               while (++arg_num <= arg_count) {
-                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                                       param++;
-                               }
-                       }
+                       do {
+                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                               param++;
+                       } while (++arg_num <= arg_count);
                }
        } else {
                array_init(params);
@@ -3495,7 +3484,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
                EX(call) = zend_vm_stack_push_call_frame(
                        constructor, opline->extended_value,
                        RETURN_VALUE_USED(opline) ?
-                               (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
+                               ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
                        Z_CE_P(EX_VAR(opline->op1.var)),
                        Z_OBJ(object_zval),
                        EX(call) TSRMLS_CC);
@@ -5177,7 +5166,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
 
                        if (call->object) {
                                if (call->flags & ZEND_CALL_CTOR) {
-                                       if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
+                                       if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {
index 80aefc1d7fd2c9529513f7016b0022a6b509341a..6f87261b5509171fc415676431b58b32f810aff7 100644 (file)
@@ -396,7 +396,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 {
        vm_frame_kind frame_kind = EX(frame_kind);
        zend_execute_data *prev_nested_call;
-       zend_uint call_flags;
 
        EG(current_execute_data) = EX(prev_execute_data);
 
@@ -408,7 +407,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
                        zval_ptr_dtor((zval*)EX(func)->op_array.prototype);
                }
-               call_flags = EX(flags);
                prev_nested_call = EX(prev_nested_call);
                zend_vm_stack_free_extra_args(execute_data TSRMLS_CC);
                zend_vm_stack_free_call_frame(execute_data TSRMLS_CC);
@@ -420,8 +418,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                EG(active_symbol_table) = EX(symbol_table);
 
                if (Z_OBJ(EG(This))) {
-                       if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
-                               if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
+                       if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
+                               if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                        Z_DELREF(EG(This));
                                }
                                if (Z_REFCOUNT(EG(This)) == 1) {
@@ -528,10 +526,9 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        USE_OPLINE
        zend_execute_data *call = EX(call);
        zend_function *fbc = call->func;
-       zend_uint call_flags = call->flags;
 
        SAVE_OPLINE();
-       call->flags |= ZEND_CALL_DONE;
+       call->flags = ZEND_CALL_DONE;
        if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
                        zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@@ -705,8 +702,8 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
 fcall_end_change_scope:
        if (Z_OBJ(EG(This))) {
-               if (UNEXPECTED(EG(exception) != NULL) && (call_flags & ZEND_CALL_CTOR)) {
-                       if (call_flags & ZEND_CALL_CTOR_RESULT_USED) {
+               if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
+                       if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                Z_DELREF(EG(This));
                        }
                        if (Z_REFCOUNT(EG(This)) == 1) {
@@ -945,31 +942,23 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
        params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
 
        if (arg_num <= arg_count) {
-               zval *param, tmp;
+               zval *param;
 
-               ZVAL_COPY_VALUE(&tmp, params);
                array_init_size(params, arg_count - arg_num + 1);
                param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
                if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
-                       zend_verify_arg_type(EX(func), arg_num, &tmp, opline->extended_value TSRMLS_CC);
-                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
-                       if (param) {
-                               while (++arg_num <= arg_count) {
-                                       zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
-                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                                       param++;
-                               }
-                       }
+                       do {
+                               zend_verify_arg_type(EX(func), arg_num, param, opline->extended_value TSRMLS_CC);
+                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                               param++;
+                       } while (++arg_num <= arg_count);
                } else {
-                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), &tmp);
-                       if (param) {
-                               while (++arg_num <= arg_count) {
-                                       zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
-                                       if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
-                                       param++;
-                               }
-                       }
+                       do {
+                               zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
+                               if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+                               param++;
+                       } while (++arg_num <= arg_count);
                }
        } else {
                array_init(params);
@@ -1010,7 +999,7 @@ static int ZEND_FASTCALL  ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                EX(call) = zend_vm_stack_push_call_frame(
                        constructor, opline->extended_value,
                        RETURN_VALUE_USED(opline) ?
-                               (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_USED) : ZEND_CALL_CTOR,
+                               ZEND_CALL_CTOR : (ZEND_CALL_CTOR | ZEND_CALL_CTOR_RESULT_UNUSED),
                        Z_CE_P(EX_VAR(opline->op1.var)),
                        Z_OBJ(object_zval),
                        EX(call) TSRMLS_CC);
@@ -1246,7 +1235,7 @@ static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
 
                        if (call->object) {
                                if (call->flags & ZEND_CALL_CTOR) {
-                                       if (call->flags & ZEND_CALL_CTOR_RESULT_USED) {
+                                       if (!(call->flags & ZEND_CALL_CTOR_RESULT_UNUSED)) {
                                                GC_REFCOUNT(call->object)--;
                                        }
                                        if (GC_REFCOUNT(call->object) == 1) {