summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_compile.h5
-rw-r--r--Zend/zend_execute.c16
-rw-r--r--Zend/zend_execute.h8
-rw-r--r--Zend/zend_types.h10
4 files changed, 27 insertions, 12 deletions
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index f56005450c..7909e9800a 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -412,8 +412,9 @@ struct _zend_execute_data {
#define ZEND_CALL_CODE (1 << 0)
#define ZEND_CALL_NESTED (0 << 1)
#define ZEND_CALL_TOP (1 << 1)
-#define ZEND_CALL_CTOR (1 << 2)
-#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 3)
+#define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) /* equal to IS_TYPE_REFCOUNTED */
+#define ZEND_CALL_CTOR (1 << 3)
+#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4)
#define ZEND_CALL_INFO(call) \
(Z_TYPE_INFO((call)->This) >> 24)
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 35dd10feb2..3c01b28c48 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1617,6 +1617,7 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
num_args = EX_NUM_ARGS();
if (UNEXPECTED(num_args > first_extra_arg)) {
zval *end, *src, *dst;
+ uint32_t type_flags = 0;
if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
@@ -1629,12 +1630,19 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
dst = src + (op_array->last_var + op_array->T - first_extra_arg);
if (EXPECTED(src != dst)) {
do {
+ type_flags |= Z_TYPE_INFO_P(src);
ZVAL_COPY_VALUE(dst, src);
ZVAL_UNDEF(src);
src--;
dst--;
} while (src != end);
+ } else {
+ do {
+ type_flags |= Z_TYPE_INFO_P(src);
+ src--;
+ } while (src != end);
}
+ ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
} else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
EX(opline) += num_args;
@@ -1709,6 +1717,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
num_args = EX_NUM_ARGS();
if (UNEXPECTED(num_args > first_extra_arg)) {
zval *end, *src, *dst;
+ uint32_t type_flags = 0;
if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
@@ -1721,12 +1730,19 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
dst = src + (op_array->last_var + op_array->T - first_extra_arg);
if (EXPECTED(src != dst)) {
do {
+ type_flags |= Z_TYPE_INFO_P(src);
ZVAL_COPY_VALUE(dst, src);
ZVAL_UNDEF(src);
src--;
dst--;
} while (src != end);
+ } else {
+ do {
+ type_flags |= Z_TYPE_INFO_P(src);
+ src--;
+ } while (src != end);
}
+ ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
} else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
EX(opline) += num_args;
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 9197e4c9e5..a94299fd06 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -176,11 +176,9 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3
static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call)
{
- uint32_t first_extra_arg = call->func->op_array.num_args;
-
- if (UNEXPECTED(ZEND_CALL_NUM_ARGS(call) > first_extra_arg)) {
- zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
- zval *p = end + (ZEND_CALL_NUM_ARGS(call) - first_extra_arg);
+ if (ZEND_CALL_INFO(call) & ZEND_CALL_FREE_EXTRA_ARGS) {
+ zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
+ zval *p = end + (ZEND_CALL_NUM_ARGS(call) - call->func->op_array.num_args);
do {
p--;
zval_ptr_dtor_nogc(p);
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 1f7978b688..28885db75a 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -264,7 +264,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p))
#define Z_TYPE_FLAGS_SHIFT 8
-#define Z_CONST_FLAGS_SHIFT 8
+#define Z_CONST_FLAGS_SHIFT 16
#define GC_REFCOUNT(p) ((zend_refcounted*)(p))->refcount
#define GC_TYPE(p) ((zend_refcounted*)(p))->u.v.type
@@ -286,10 +286,10 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
/* zval.u1.v.type_flags */
#define IS_TYPE_CONSTANT (1<<0)
-#define IS_TYPE_REFCOUNTED (1<<1)
-#define IS_TYPE_COLLECTABLE (1<<2)
-#define IS_TYPE_COPYABLE (1<<3)
-#define IS_TYPE_IMMUTABLE (1<<4)
+#define IS_TYPE_IMMUTABLE (1<<1)
+#define IS_TYPE_REFCOUNTED (1<<2)
+#define IS_TYPE_COLLECTABLE (1<<3)
+#define IS_TYPE_COPYABLE (1<<4)
/* extended types */
#define IS_INTERNED_STRING_EX IS_STRING