summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-06-05 16:04:11 +0400
committerDmitry Stogov <dmitry@zend.com>2014-06-05 16:04:11 +0400
commitc1965f58d4dd3970912dcd6a63ccd5860bae1a97 (patch)
tree15b4a94e8e8405f791438c468ad4eb03f60c4079 /Zend
parent3d87391cc06fe87344536e88ac74ded22b0195cf (diff)
downloadphp-git-c1965f58d4dd3970912dcd6a63ccd5860bae1a97.tar.gz
Use reference counting instead of zval duplication
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend.h73
-rw-r--r--Zend/zend_API.c26
-rw-r--r--Zend/zend_builtin_functions.c3
-rw-r--r--Zend/zend_compile.c11
-rw-r--r--Zend/zend_execute.c149
-rw-r--r--Zend/zend_generators.c2
-rw-r--r--Zend/zend_hash.c9
-rw-r--r--Zend/zend_object_handlers.c8
-rw-r--r--Zend/zend_variables.c4
-rw-r--r--Zend/zend_vm_def.h213
-rw-r--r--Zend/zend_vm_execute.h801
11 files changed, 715 insertions, 584 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index d9c8db19b6..c346c023c1 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -707,6 +707,13 @@ END_EXTERN_C()
} \
} while (0)
+#define ZVAL_MAKE_REF(zv) do { \
+ zval *__zv = (zv); \
+ if (!Z_ISREF_P(__zv)) { \
+ ZVAL_NEW_REF(__zv, __zv); \
+ } \
+ } while (0)
+
#define ZVAL_UNREF(z) do { \
zval *_z = (z); \
zend_reference *ref; \
@@ -716,6 +723,38 @@ END_EXTERN_C()
efree(ref); \
} while (0)
+#define SEPARATE_STRING(zv) do { \
+ zval *_zv = (zv); \
+ if (Z_REFCOUNTED_P(_zv) && \
+ Z_REFCOUNT_P(_zv) > 1) { \
+ Z_DELREF_P(_zv); \
+ zval_copy_ctor_func(_zv); \
+ } \
+ } while (0)
+
+#define SEPARATE_ARRAY(zv) do { \
+ zval *_zv = (zv); \
+ if (Z_IMMUTABLE_P(_zv)) { \
+ zval_copy_ctor_func(_zv); \
+ } else if (Z_REFCOUNT_P(_zv) > 1) { \
+ Z_DELREF_P(_zv); \
+ zval_copy_ctor_func(_zv); \
+ } \
+ } while (0)
+
+#define SEPARATE_ZVAL_NOREF(zv) do { \
+ zval *_zv = (zv); \
+ if (Z_COPYABLE_P(_zv) || \
+ Z_IMMUTABLE_P(_zv)) { \
+ if (Z_IMMUTABLE_P(_zv)) { \
+ zval_copy_ctor_func(_zv); \
+ } else if (Z_REFCOUNT_P(_zv) > 1) { \
+ Z_DELREF_P(_zv); \
+ zval_copy_ctor_func(_zv); \
+ } \
+ } \
+ } while (0)
+
#define SEPARATE_ZVAL(zv) do { \
zval *_zv = (zv); \
if (Z_REFCOUNTED_P(_zv) || \
@@ -749,38 +788,10 @@ END_EXTERN_C()
} \
} while (0)
-#define SEPARATE_ZVAL_IF_REF(zv) do { \
- zval *__zv = (zv); \
- if (Z_ISREF_P(__zv)) { \
- if (Z_REFCOUNT_P(__zv) == 1) { \
- ZVAL_UNREF(__zv); \
- } else { \
- Z_DELREF_P(__zv); \
- ZVAL_DUP(__zv, Z_REFVAL_P(__zv)); \
- } \
- } \
- } while (0)
-
-#define SEPARATE_ZVAL_TO_MAKE_IS_REF(zv) do { \
- zval *__zv = (zv); \
- if (!Z_ISREF_P(__zv)) { \
- if (Z_COPYABLE_P(__zv) && \
- Z_REFCOUNT_P(__zv) > 1) { \
- Z_DELREF_P(__zv); \
- zval_copy_ctor_func(__zv); \
- } \
- ZVAL_NEW_REF(__zv, __zv); \
- } \
- } while (0)
-
#define SEPARATE_ARG_IF_REF(varptr) do { \
- zval *_varptr = (varptr); \
- if (Z_ISREF_P(_varptr)) { \
- zval tmp; \
- ZVAL_DUP(&tmp, Z_REFVAL_P(_varptr)); \
- varptr = &tmp; \
- } else if (Z_REFCOUNTED_P(_varptr)) { \
- Z_ADDREF_P(_varptr); \
+ ZVAL_DEREF(varptr); \
+ if (Z_REFCOUNTED_P(varptr)) { \
+ Z_ADDREF_P(varptr); \
} \
} while (0)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 45e2331518..33f1fc67cc 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -273,7 +273,7 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
}
/* Standard PHP objects */
if (Z_OBJ_HT_P(arg) == &std_object_handlers || !Z_OBJ_HANDLER_P(arg, cast_object)) {
- SEPARATE_ZVAL_IF_NOT_REF(arg);
+ SEPARATE_ZVAL_NOREF(arg);
if (zend_std_cast_object_tostring(arg, arg, type TSRMLS_CC) == SUCCESS) {
*pl = Z_STRLEN_P(arg);
*p = Z_STRVAL_P(arg);
@@ -315,7 +315,7 @@ static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS
}
/* Standard PHP objects */
if (Z_OBJ_HT_P(arg) == &std_object_handlers || !Z_OBJ_HANDLER_P(arg, cast_object)) {
- SEPARATE_ZVAL_IF_NOT_REF(arg);
+ SEPARATE_ZVAL_NOREF(arg);
if (zend_std_cast_object_tostring(arg, arg, type TSRMLS_CC) == SUCCESS) {
*str = Z_STR_P(arg);
return SUCCESS;
@@ -350,9 +350,11 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
zval *real_arg = arg;
/* scan through modifiers */
+ ZVAL_DEREF(arg);
while (1) {
if (*spec_walk == '/') {
- SEPARATE_ZVAL_IF_NOT_REF(arg);
+ SEPARATE_ZVAL(arg);
+ real_arg = arg;
} else if (*spec_walk == '!') {
check_null = 1;
} else {
@@ -361,8 +363,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
spec_walk++;
}
- ZVAL_DEREF(arg);
-
switch (c) {
case 'l':
case 'L':
@@ -486,12 +486,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_TRUE:
convert_to_string_ex(arg);
case IS_STRING:
- if (UNEXPECTED(Z_ISREF_P(arg))) {
- /* it's dangerous to return pointers to string
- buffer of referenced variable, because it can
- be clobbered throug magic callbacks */
- SEPARATE_ZVAL(arg);
- }
*p = Z_STRVAL_P(arg);
*pl = Z_STRLEN_P(arg);
if (c == 'p' && CHECK_ZVAL_NULL_PATH(arg)) {
@@ -533,12 +527,6 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
case IS_TRUE:
convert_to_string_ex(arg);
case IS_STRING:
- if (UNEXPECTED(Z_ISREF_P(arg))) {
- /* it's dangerous to return pointers to string
- buffer of referenced variable, because it can
- be clobbered throug magic callbacks */
- SEPARATE_ZVAL(arg);
- }
*str = Z_STR_P(arg);
if (c == 'P' && CHECK_ZVAL_NULL_PATH(arg)) {
return "a valid path";
@@ -2714,8 +2702,8 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_lengt
if (num_symbol_tables <= 0) return FAILURE;
- if (is_ref && !Z_ISREF_P(symbol)) {
- ZVAL_NEW_REF(symbol, symbol);
+ if (is_ref) {
+ ZVAL_MAKE_REF(symbol);
}
va_start(symbol_table_list, num_symbol_tables);
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index d58099418f..f8f6a435f5 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -585,11 +585,10 @@ ZEND_FUNCTION(each)
HashTable *target_hash;
zend_string *key;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &array) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &array) == FAILURE) {
return;
}
- ZVAL_DEREF(array);
target_hash = HASH_OF(array);
if (!target_hash) {
zend_error(E_WARNING,"Variable passed to each() is not an array or object");
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index fda1c7606e..c84937b645 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3793,7 +3793,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
}
for (i = 0; i < parent_ce->default_static_members_count; i++) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
+ ZVAL_MAKE_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
Z_ADDREF(ce->default_static_members_table[i]);
}
@@ -3811,7 +3811,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
}
}
for (i = 0; i < parent_ce->default_static_members_count; i++) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
+ ZVAL_MAKE_REF(&parent_ce->default_static_members_table[i]);
ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
Z_ADDREF(ce->default_static_members_table[i]);
}
@@ -3896,9 +3896,7 @@ static int do_inherit_iface_constant(zval *zv TSRMLS_DC, int num_args, va_list a
zend_class_entry *iface = va_arg(args, zend_class_entry *);
if (hash_key->key && do_inherit_constant_check(&ce->constants_table, zv, hash_key, iface)) {
- if (!Z_ISREF_P(zv)) {
- ZVAL_NEW_REF(zv, zv);
- }
+ ZVAL_MAKE_REF(zv);
Z_ADDREF_P(zv);
zend_hash_update(&ce->constants_table, hash_key->key, zv);
}
@@ -7524,6 +7522,9 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{
if (ast->kind == ZEND_CONST) {
ZVAL_COPY_VALUE(&result->u.constant, &ast->u.val);
efree(ast);
+ if (Z_TYPE(result->u.constant) == IS_ARRAY) {
+ zend_make_immutable_array_r(&result->u.constant TSRMLS_CC);
+ }
} else if (zend_ast_is_ct_constant(ast)) {
zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC);
zend_ast_destroy(ast);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 80d4fbb5db..471a02976a 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -114,13 +114,6 @@ static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *sho
#define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
-#define MAKE_REAL_ZVAL_PTR(val) \
- do { \
- zval _tmp; \
- ZVAL_COPY_VALUE(&_tmp, (val)); \
- (val) = &_tmp; \
- } while (0)
-
/* End of zend_execute_locks.h */
#define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
@@ -488,12 +481,12 @@ static inline zval *_get_obj_zval_ptr_ptr(int op_type, const znode_op *node, con
static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr TSRMLS_DC)
{
if (EXPECTED(variable_ptr != value_ptr)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
Z_ADDREF_P(value_ptr);
zval_ptr_dtor(variable_ptr);
- ZVAL_COPY_VALUE(variable_ptr, value_ptr);
- } else if (!Z_ISREF_P(variable_ptr)) {
- ZVAL_NEW_REF(variable_ptr, variable_ptr);
+ ZVAL_REF(variable_ptr, Z_REF_P(value_ptr));
+ } else {
+ ZVAL_MAKE_REF(variable_ptr);
}
}
@@ -507,11 +500,7 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
if (Z_TYPE_P(object) == IS_NULL
|| Z_TYPE_P(object) == IS_FALSE
|| (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
- if (EXPECTED(object == object_ptr)) {
- /* object_ptr is not a reference */
- SEPARATE_ZVAL(object);
- }
- zval_dtor(object);
+ zval_ptr_dtor_nogc(object);
object_init(object);
zend_error(E_WARNING, "Creating default object from empty value");
}
@@ -730,7 +719,8 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
value = &tmp;
} else if (value_type == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
- ZVAL_DUP(&tmp, value);
+ ZVAL_COPY_VALUE(&tmp, value);
+ zval_copy_ctor_func(&tmp);
value = &tmp;
}
} else if (Z_REFCOUNTED_P(value)) {
@@ -793,15 +783,10 @@ static void zend_assign_to_string_offset(zval *str_offset, zval *value, int valu
}
if (Z_TYPE_P(value) != IS_STRING) {
- zval tmp;
+ zend_string *tmp = zval_get_string(value);
- ZVAL_COPY_VALUE(&tmp, value);
- if (value_type != IS_TMP_VAR) {
- zval_opt_copy_ctor(&tmp);
- }
- convert_to_string(&tmp);
- Z_STRVAL_P(str)[offset] = Z_STRVAL(tmp)[0];
- zval_dtor(&tmp);
+ Z_STRVAL_P(str)[offset] = tmp->val[0];
+ STR_RELEASE(tmp);
} else {
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
if (value_type == IS_TMP_VAR) {
@@ -888,7 +873,7 @@ static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *valu
ZVAL_COPY_VALUE(variable_ptr, value);
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- _zval_copy_ctor_func(variable_ptr ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(variable_ptr);
}
_zval_dtor_func(garbage ZEND_FILE_LINE_CC);
return variable_ptr;
@@ -898,7 +883,7 @@ static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *valu
ZVAL_COPY_VALUE(variable_ptr, value);
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(variable_ptr))) {
- _zval_copy_ctor_func(variable_ptr ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(variable_ptr);
}
return variable_ptr;
@@ -907,42 +892,33 @@ static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *valu
static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
{
zend_refcounted *garbage;
- zval *is_ref = NULL;
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- if (EXPECTED(!Z_ISREF_P(value))) {
- ZVAL_COPY(variable_ptr, value);
- } else {
- goto assign_ref;
- }
+ goto assign_simple;
+ } else if (UNEXPECTED(variable_ptr == value)) {
return variable_ptr;
- } else if (Z_ISREF_P(variable_ptr)) {
- is_ref = variable_ptr;
+ }
+ if (Z_ISREF_P(variable_ptr)) {
variable_ptr = Z_REFVAL_P(variable_ptr);
+ if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
+ goto assign_simple;
+ }
}
- if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
- goto assign_simple;
- } else if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
+ if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
} else if (EXPECTED(variable_ptr != value)) {
if (Z_REFCOUNT_P(variable_ptr)==1) {
garbage = Z_COUNTED_P(variable_ptr);
if (EXPECTED(!Z_ISREF_P(value))) {
- if (!is_ref) {
- ZVAL_COPY(variable_ptr, value);
- } else {
- ZVAL_DUP(variable_ptr, value);
- }
- } else if (is_ref == value) {
- return variable_ptr;
+ ZVAL_COPY(variable_ptr, value);
} else {
if (Z_REFCOUNT_P(value) == 1) {
ZVAL_UNREF(value);
ZVAL_COPY(variable_ptr, value);
} else {
- ZVAL_DUP(variable_ptr, Z_REFVAL_P(value));
+ ZVAL_COPY(variable_ptr, Z_REFVAL_P(value));
}
}
_zval_dtor_func(garbage ZEND_FILE_LINE_CC);
@@ -951,18 +927,13 @@ static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRM
GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
assign_simple:
if (EXPECTED(!Z_ISREF_P(value))) {
- if (!is_ref) {
- ZVAL_COPY(variable_ptr, value);
- } else {
- ZVAL_DUP(variable_ptr, value);
- }
- } else if (is_ref != value) {
-assign_ref:
+ ZVAL_COPY(variable_ptr, value);
+ } else {
if (Z_REFCOUNT_P(value) == 1) {
ZVAL_UNREF(value);
ZVAL_COPY(variable_ptr, value);
} else {
- ZVAL_DUP(variable_ptr, Z_REFVAL_P(value));
+ ZVAL_COPY(variable_ptr, Z_REFVAL_P(value));
}
}
}
@@ -1124,12 +1095,7 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
ZVAL_DEREF(container);
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- if (Z_IMMUTABLE_P(container)) {
- zval_copy_ctor_func(container);
- } else if (Z_REFCOUNT_P(container) > 1) {
- Z_DELREF_P(container);
- zval_copy_ctor_func(container);
- }
+ SEPARATE_ARRAY(container);
fetch_from_array:
if (dim == NULL) {
retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
@@ -1141,12 +1107,15 @@ fetch_from_array:
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
}
if (is_ref) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- ZVAL_COPY(result, retval);
+ ZVAL_MAKE_REF(retval);
+ Z_ADDREF_P(retval);
+ ZVAL_REF(result, Z_REF_P(retval));
} else {
ZVAL_INDIRECT(result, retval);
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ long offset;
+
if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
convert_to_array:
zval_dtor(container);
@@ -1158,14 +1127,10 @@ convert_to_array:
}
if (type != BP_VAR_UNSET) {
- if (container == container_ptr) {
- SEPARATE_ZVAL(container);
- }
+ SEPARATE_STRING(container);
}
if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
- zval tmp;
-
switch(Z_TYPE_P(dim)) {
case IS_STRING:
if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
@@ -1186,13 +1151,13 @@ convert_to_array:
break;
}
- ZVAL_DUP(&tmp, dim);
- convert_to_long(&tmp);
- dim = &tmp;
+ offset = zval_get_long(dim);
+ } else {
+ offset = Z_LVAL_P(dim);
}
if (!IS_INTERNED(Z_STR_P(container))) STR_ADDREF(Z_STR_P(container));
- ZVAL_STR_OFFSET(result, container, Z_LVAL_P(dim));
+ ZVAL_STR_OFFSET(result, container, offset);
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
if (!Z_OBJ_HT_P(container)->read_dimension) {
zend_error_noreturn(E_ERROR, "Cannot use object as array");
@@ -1221,8 +1186,9 @@ convert_to_array:
}
if (result != retval) {
if (is_ref) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
- ZVAL_COPY(result, retval);
+ ZVAL_MAKE_REF(retval);
+ Z_ADDREF_P(retval);
+ ZVAL_REF(result, Z_REF_P(retval));
} else {
ZVAL_INDIRECT(result, retval);
}
@@ -1284,9 +1250,9 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
ZVAL_COPY(result, retval);
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
- zval tmp;
+ long offset;
+ if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
switch(Z_TYPE_P(dim)) {
/* case IS_LONG: */
case IS_STRING:
@@ -1310,23 +1276,23 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
break;
}
- ZVAL_DUP(&tmp, dim);
- convert_to_long(&tmp);
- dim = &tmp;
+ offset = zval_get_long(dim);
+ } else {
+ offset = Z_LVAL_P(dim);
}
- if (UNEXPECTED(Z_LVAL_P(dim) < 0) || UNEXPECTED(Z_STRLEN_P(container) <= Z_LVAL_P(dim))) {
+ if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= offset)) {
if (type != BP_VAR_IS) {
- zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
+ zend_error(E_NOTICE, "Uninitialized string offset: %ld", offset);
}
ZVAL_EMPTY_STRING(result);
} else {
- zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[Z_LVAL_P(dim)];
+ zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
if (CG(one_char_string)[c]) {
ZVAL_INT_STR(result, CG(one_char_string)[c]);
} else {
- ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(container) + Z_LVAL_P(dim), 1, 0));
+ ZVAL_NEW_STR(result, STR_INIT(Z_STRVAL_P(container) + offset, 1, 0));
}
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
@@ -1376,9 +1342,7 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
((Z_TYPE_P(container) == IS_NULL ||
Z_TYPE_P(container) == IS_FALSE ||
(Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
- if (container == container_ptr) {
- SEPARATE_ZVAL(container);
- }
+ zval_ptr_dtor_nogc(container);
object_init(container);
} else {
zend_error(E_WARNING, "Attempt to modify property of non-object");
@@ -1394,8 +1358,9 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
(ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC)) != NULL) {
if (ptr != result) {
if (is_ref && ptr != &EG(uninitialized_zval)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(ptr);
- ZVAL_COPY(result, ptr);
+ ZVAL_MAKE_REF(ptr);
+ Z_ADDREF_P(ptr);
+ ZVAL_REF(result, Z_REF_P(ptr));
} else {
ZVAL_INDIRECT(result, ptr);
}
@@ -1405,8 +1370,9 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
}
} else {
if (is_ref) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(ptr);
- ZVAL_COPY(result, ptr);
+ ZVAL_MAKE_REF(ptr);
+ Z_ADDREF_P(ptr);
+ ZVAL_REF(result, Z_REF_P(ptr));
} else {
ZVAL_INDIRECT(result, ptr);
}
@@ -1415,8 +1381,9 @@ static void zend_fetch_property_address(zval *result, zval *container_ptr, zval
zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result TSRMLS_CC);
if (ptr != result) {
if (is_ref && ptr != &EG(uninitialized_zval)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(ptr);
- ZVAL_COPY(result, ptr);
+ ZVAL_MAKE_REF(ptr);
+ Z_ADDREF_P(ptr);
+ ZVAL_REF(result, Z_REF_P(ptr));
} else {
ZVAL_INDIRECT(result, ptr);
}
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index e275d92c91..c80e909565 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -239,7 +239,7 @@ static int copy_closure_static_var(zval *var TSRMLS_DC, int num_args, va_list ar
{
HashTable *target = va_arg(args, HashTable *);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(var);
+ ZVAL_MAKE_REF(var);
Z_ADDREF_P(var);
zend_hash_update(target, key->key, var);
return 0;
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 08b4cb5e4e..e7aa255d78 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -1207,7 +1207,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
q->key = NULL;
if (Z_OPT_REFCOUNTED_P(data)) {
if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
- ZVAL_DUP(&q->val, Z_REFVAL_P(data));
+ ZVAL_COPY(&q->val, Z_REFVAL_P(data));
} else {
ZVAL_COPY(&q->val, data);
}
@@ -1256,7 +1256,7 @@ ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
target->arHash[nIndex] = target_idx;
if (Z_OPT_REFCOUNTED_P(data)) {
if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
- ZVAL_DUP(&q->val, Z_REFVAL_P(data));
+ ZVAL_COPY(&q->val, Z_REFVAL_P(data));
} else {
ZVAL_COPY(&q->val, data);
}
@@ -1495,14 +1495,15 @@ ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
} else if (ht->nInternalPointer != ptr->pos) {
IS_CONSISTENT(ht);
if (ht->u.flags & HASH_FLAG_PACKED) {
- if (Z_TYPE(ht->arData[ptr->h].val) != IS_UNDEF) {
+ if (ptr->h < ht->nNumUsed &&
+ Z_TYPE(ht->arData[ptr->h].val) != IS_UNDEF) {
ht->nInternalPointer = ptr->h;
return 1;
}
} else {
idx = ht->arHash[ptr->h & ht->nTableMask];
while (idx != INVALID_IDX) {
- if (idx == ptr->pos) {
+ if (ht->arData[idx].h == ptr->h && idx == ptr->pos) {
ht->nInternalPointer = idx;
return 1;
}
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 0e30ca304e..4d2d799441 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -188,7 +188,7 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval TSRMLS
it should return whether the call was successfull or not
*/
- SEPARATE_ARG_IF_REF(member);
+ if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
@@ -202,7 +202,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
int result;
zend_class_entry *ce = Z_OBJCE_P(object);
- SEPARATE_ARG_IF_REF(member);
+ if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
/* __set handler is called with two arguments:
@@ -234,7 +234,7 @@ static void zend_std_call_unsetter(zval *object, zval *member TSRMLS_DC) /* {{{
property name
*/
- SEPARATE_ARG_IF_REF(member);
+ if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
@@ -252,7 +252,7 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval TSRM
it should return whether the property is set or not
*/
- SEPARATE_ARG_IF_REF(member);
+ if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member);
zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 79bd00db13..2031b017eb 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -210,7 +210,7 @@ ZEND_API void zval_add_ref(zval *p)
{
if (Z_REFCOUNTED_P(p)) {
if (Z_ISREF_P(p) && Z_REFCOUNT_P(p) == 1) {
- ZVAL_DUP(p, Z_REFVAL_P(p));
+ ZVAL_COPY(p, Z_REFVAL_P(p));
} else {
Z_ADDREF_P(p);
}
@@ -340,7 +340,7 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args,
}
}
if (is_ref) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
+ ZVAL_MAKE_REF(p);
Z_ADDREF_P(p);
} else if (Z_ISREF_P(p)) {
ZVAL_DUP(&tmp, Z_REFVAL_P(p));
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 4f87f5b375..554ac2ca80 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -457,7 +457,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -512,7 +512,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -896,7 +896,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -954,7 +954,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -1012,7 +1012,7 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -1066,7 +1066,7 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -1216,7 +1216,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -2830,10 +2830,12 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
if (OP1_TYPE == IS_CONST) {
- zval_opt_copy_ctor_no_imm(EX(return_value));
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
+ zval_copy_ctor_func(EX(return_value));
+ }
}
} else if (Z_ISREF_P(retval_ptr)) {
- ZVAL_DUP(EX(return_value), Z_REFVAL_P(retval_ptr));
+ ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
FREE_OP1_IF_VAR();
} else {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
@@ -2894,8 +2896,9 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
}
if (EX(return_value)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
- ZVAL_COPY(EX(return_value), retval_ptr);
+ ZVAL_MAKE_REF(retval_ptr);
+ Z_ADDREF_P(retval_ptr);
+ ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
}
} while (0);
@@ -3012,9 +3015,9 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
top = zend_vm_stack_top_inc(TSRMLS_C);
ZVAL_COPY_VALUE(top, value);
if (OP1_TYPE == IS_CONST) {
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
+ zval_copy_ctor_func(top);
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -3028,10 +3031,7 @@ ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
FREE_OP1();
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -3067,13 +3067,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
Z_TYPE_P(varptr) == IS_OBJECT ||
(Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
- if (!Z_ISREF_P(varptr)) {
- ZVAL_NEW_REF(varptr, varptr);
- }
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
+ ZVAL_MAKE_REF(varptr);
if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(varptr);
}
@@ -3085,8 +3079,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
zend_error(E_STRICT, "Only variables should be passed by reference");
}
top = zend_vm_stack_top_inc(TSRMLS_C);
- // TODO: Try to avoid copying of immutable arrays ???
- ZVAL_DUP(top, varptr);
+ ZVAL_COPY(top, varptr);
FREE_OP1_IF_VAR();
}
CHECK_EXCEPTION();
@@ -3113,24 +3106,16 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
}
if (Z_ISREF_P(varptr)) {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
Z_ADDREF_P(varptr);
ZVAL_COPY_VALUE(top, varptr);
} else if (OP1_TYPE == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
ZVAL_COPY_VALUE(top, varptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(top);
+ ZVAL_MAKE_REF(top);
} else {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(varptr)) {
- zval_opt_copy_ctor(varptr);
- }
- SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr);
+ ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_REF(top, Z_REF_P(varptr));
}
FREE_OP1_VAR_PTR();
@@ -3152,10 +3137,7 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY)
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
FREE_OP1();
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -3214,9 +3196,9 @@ ZEND_VM_C_LABEL(send_again):
top = zend_vm_stack_top_inc(TSRMLS_C);
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
if (!Z_IMMUTABLE_P(args)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(arg);
+ ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
- ZVAL_COPY_VALUE(top, arg);
+ ZVAL_REF(top, Z_REF_P(arg));
} else {
ZVAL_DUP(top, arg);
}
@@ -3375,7 +3357,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
- _zval_copy_ctor_func(var_ptr ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(var_ptr);
}
}
} else {
@@ -3655,7 +3637,14 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c);
}
retval = EX_VAR(opline->result.var);
- ZVAL_DUP(retval, &c->value);
+ ZVAL_COPY_VALUE(retval, &c->value);
+ if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
+ if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ zval_copy_ctor_func(retval);
+ } else {
+ Z_ADDREF_P(retval);
+ }
+ }
} else {
/* class constant */
zend_class_entry *ce;
@@ -3729,7 +3718,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
FREE_OP1_VAR_PTR();
} else {
@@ -3839,11 +3828,11 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
- zval *expr;
+ zval *expr, tmp;
zval *result = EX_VAR(opline->result.var);
SAVE_OPLINE();
- expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ expr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
switch (opline->extended_value) {
case IS_NULL:
@@ -3880,27 +3869,59 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
if (Z_TYPE_P(expr) == opline->extended_value) {
ZVAL_COPY_VALUE(result, expr);
if (OP1_TYPE == IS_CONST) {
- zval_opt_copy_ctor(result);
- } else if (OP1_TYPE == IS_CV) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
+ zval_copy_ctor_func(result);
+ }
+ } else if (OP1_TYPE != IS_TMP_VAR) {
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
}
+ FREE_OP1();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- ZVAL_DEREF(expr);
- }
- ZVAL_COPY_VALUE(result, expr);
- if (!IS_OP1_TMP_FREE()) {
- zval_opt_copy_ctor(result);
- }
-
if (opline->extended_value == IS_ARRAY) {
- convert_to_array(result);
+ if (Z_TYPE_P(expr) != IS_OBJECT) {
+ ZVAL_NEW_ARR(result);
+ zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (OP1_TYPE != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!IS_OP1_TMP_FREE()) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_array(result);
+ }
} else {
- convert_to_object(result);
+ if (Z_TYPE_P(expr) != IS_ARRAY) {
+ object_init(result);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (OP1_TYPE != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!IS_OP1_TMP_FREE()) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_object(result);
+ }
}
FREE_OP1_IF_VAR();
@@ -4258,7 +4279,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
@@ -4278,7 +4299,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
Z_ADDREF_P(array_ptr);
}
@@ -4430,7 +4451,13 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
zval *key = NULL;
array = array_ref = EX_VAR(opline->op1.var);
- ZVAL_DEREF(array);
+ if (Z_ISREF_P(array)) {
+ array = Z_REFVAL_P(array);
+ // TODO: referenced value might be changed to different array ???
+ if (Z_IMMUTABLE_P(array)) {
+ zval_copy_ctor(array);
+ }
+ }
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
key = EX_VAR((opline+1)->result.var);
}
@@ -4549,9 +4576,12 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
}
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value);
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- ZVAL_COPY(EX_VAR(opline->result.var), value);
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
@@ -4891,10 +4921,13 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!IS_OP1_TMP_FREE()) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (OP1_TYPE == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- FREE_OP1_IF_VAR();
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -4913,15 +4946,14 @@ ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (i_zend_is_true(value TSRMLS_CC)) {
- if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!IS_OP1_TMP_FREE()) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (OP1_TYPE == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- FREE_OP1_IF_VAR();
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -4940,11 +4972,13 @@ ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!IS_OP1_TMP_FREE()) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (OP1_TYPE == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- FREE_OP1_IF_VAR();
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -4957,17 +4991,14 @@ ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
SAVE_OPLINE();
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!IS_OP1_TMP_FREE()) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (OP1_TYPE == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (OP1_TYPE == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- FREE_OP1_IF_VAR();
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5343,7 +5374,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) {
- _zval_copy_ctor_func(&c.value ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(&c.value);
}
}
c.flags = CONST_CS; /* non persistent, case sensetive */
@@ -5446,7 +5477,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 4a66c7390d..c391cffdb9 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -782,9 +782,9 @@ send_again:
top = zend_vm_stack_top_inc(TSRMLS_C);
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, arg_num)) {
if (!Z_IMMUTABLE_P(args)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(arg);
+ ZVAL_MAKE_REF(arg);
Z_ADDREF_P(arg);
- ZVAL_COPY_VALUE(top, arg);
+ ZVAL_REF(top, Z_REF_P(arg));
} else {
ZVAL_DUP(top, arg);
}
@@ -1657,7 +1657,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(var_ptr))) {
- _zval_copy_ctor_func(var_ptr ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(var_ptr);
}
}
} else {
@@ -2606,10 +2606,12 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
if (IS_CONST == IS_CONST) {
- zval_opt_copy_ctor_no_imm(EX(return_value));
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
+ zval_copy_ctor_func(EX(return_value));
+ }
}
} else if (Z_ISREF_P(retval_ptr)) {
- ZVAL_DUP(EX(return_value), Z_REFVAL_P(retval_ptr));
+ ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
} else {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
@@ -2670,8 +2672,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
}
if (EX(return_value)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
- ZVAL_COPY(EX(return_value), retval_ptr);
+ ZVAL_MAKE_REF(retval_ptr);
+ Z_ADDREF_P(retval_ptr);
+ ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
}
} while (0);
@@ -2722,9 +2725,9 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
top = zend_vm_stack_top_inc(TSRMLS_C);
ZVAL_COPY_VALUE(top, value);
if (IS_CONST == IS_CONST) {
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
+ zval_copy_ctor_func(top);
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -2805,7 +2808,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *expr;
+ zval *expr, tmp;
zval *result = EX_VAR(opline->result.var);
SAVE_OPLINE();
@@ -2846,8 +2849,10 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(expr) == opline->extended_value) {
ZVAL_COPY_VALUE(result, expr);
if (IS_CONST == IS_CONST) {
- zval_opt_copy_ctor(result);
- } else if (IS_CONST == IS_CV) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
+ zval_copy_ctor_func(result);
+ }
+ } else if (IS_CONST != IS_TMP_VAR) {
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
}
@@ -2855,18 +2860,47 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- ZVAL_DEREF(expr);
- }
- ZVAL_COPY_VALUE(result, expr);
- if (!0) {
- zval_opt_copy_ctor(result);
- }
-
if (opline->extended_value == IS_ARRAY) {
- convert_to_array(result);
+ if (Z_TYPE_P(expr) != IS_OBJECT) {
+ ZVAL_NEW_ARR(result);
+ zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_CONST != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_array(result);
+ }
} else {
- convert_to_object(result);
+ if (Z_TYPE_P(expr) != IS_ARRAY) {
+ object_init(result);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_CONST != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_object(result);
+ }
}
CHECK_EXCEPTION();
@@ -3019,7 +3053,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
@@ -3039,7 +3073,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
Z_ADDREF_P(array_ptr);
}
@@ -3213,10 +3247,13 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_CONST == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -3234,15 +3271,14 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
value = opline->op1.zv;
if (i_zend_is_true(value TSRMLS_CC)) {
- if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_CONST == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -3260,11 +3296,13 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
value = opline->op1.zv;
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_CONST == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -3277,16 +3315,14 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
SAVE_OPLINE();
value = opline->op1.zv;
- if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_CONST == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_CONST == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -3669,7 +3705,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -3912,7 +3948,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c);
}
retval = EX_VAR(opline->result.var);
- ZVAL_DUP(retval, &c->value);
+ ZVAL_COPY_VALUE(retval, &c->value);
+ if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
+ if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ zval_copy_ctor_func(retval);
+ } else {
+ Z_ADDREF_P(retval);
+ }
+ }
} else {
/* class constant */
zend_class_entry *ce;
@@ -3986,7 +4029,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -4261,7 +4304,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD
} else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) {
- _zval_copy_ctor_func(&c.value ZEND_FILE_LINE_CC);
+ zval_copy_ctor_func(&c.value);
}
}
c.flags = CONST_CS; /* non persistent, case sensetive */
@@ -4327,7 +4370,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -4856,7 +4899,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -5013,7 +5056,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -5486,7 +5529,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -5690,7 +5733,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -5998,7 +6041,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -6196,7 +6239,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -6367,7 +6410,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -6693,7 +6736,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -7259,7 +7302,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
if (IS_CONST == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -7416,7 +7459,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -7751,10 +7794,12 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
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_CONST) {
- zval_opt_copy_ctor_no_imm(EX(return_value));
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
+ zval_copy_ctor_func(EX(return_value));
+ }
}
} else if (Z_ISREF_P(retval_ptr)) {
- ZVAL_DUP(EX(return_value), Z_REFVAL_P(retval_ptr));
+ ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
} else {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
@@ -7815,8 +7860,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
if (EX(return_value)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
- ZVAL_COPY(EX(return_value), retval_ptr);
+ ZVAL_MAKE_REF(retval_ptr);
+ Z_ADDREF_P(retval_ptr);
+ ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
}
} while (0);
@@ -7867,9 +7913,9 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
top = zend_vm_stack_top_inc(TSRMLS_C);
ZVAL_COPY_VALUE(top, value);
if (IS_TMP_VAR == IS_CONST) {
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(top))) {
+ zval_copy_ctor_func(top);
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -7951,7 +7997,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_free_op free_op1;
- zval *expr;
+ zval *expr, tmp;
zval *result = EX_VAR(opline->result.var);
SAVE_OPLINE();
@@ -7992,27 +8038,59 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(expr) == opline->extended_value) {
ZVAL_COPY_VALUE(result, expr);
if (IS_TMP_VAR == IS_CONST) {
- zval_opt_copy_ctor(result);
- } else if (IS_TMP_VAR == IS_CV) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
+ zval_copy_ctor_func(result);
+ }
+ } else if (IS_TMP_VAR != IS_TMP_VAR) {
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
}
+ zval_dtor(free_op1.var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- ZVAL_DEREF(expr);
- }
- ZVAL_COPY_VALUE(result, expr);
- if (!1) {
- zval_opt_copy_ctor(result);
- }
-
if (opline->extended_value == IS_ARRAY) {
- convert_to_array(result);
+ if (Z_TYPE_P(expr) != IS_OBJECT) {
+ ZVAL_NEW_ARR(result);
+ zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_TMP_VAR != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!1) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_array(result);
+ }
} else {
- convert_to_object(result);
+ if (Z_TYPE_P(expr) != IS_ARRAY) {
+ object_init(result);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_TMP_VAR != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!1) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_object(result);
+ }
}
CHECK_EXCEPTION();
@@ -8165,7 +8243,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
@@ -8185,7 +8263,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
Z_ADDREF_P(array_ptr);
}
@@ -8386,10 +8464,13 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!1) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_TMP_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -8408,15 +8489,14 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (i_zend_is_true(value TSRMLS_CC)) {
- if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!1) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_TMP_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -8435,11 +8515,13 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!1) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_TMP_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -8452,16 +8534,14 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!1) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_TMP_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_TMP_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -8865,7 +8945,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -9083,7 +9163,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -9391,7 +9471,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -9920,7 +10000,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -10077,7 +10157,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -10550,7 +10630,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -10754,7 +10834,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -11062,7 +11142,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -11260,7 +11340,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -11317,7 +11397,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -11625,7 +11705,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -12136,7 +12216,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -12293,7 +12373,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -12445,7 +12525,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -12503,7 +12583,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -12561,7 +12641,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -12615,7 +12695,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -12852,10 +12932,12 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
if (IS_VAR == IS_CONST) {
- zval_opt_copy_ctor_no_imm(EX(return_value));
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
+ zval_copy_ctor_func(EX(return_value));
+ }
}
} else if (Z_ISREF_P(retval_ptr)) {
- ZVAL_DUP(EX(return_value), Z_REFVAL_P(retval_ptr));
+ ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
zval_ptr_dtor_nogc(free_op1.var);
} else {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
@@ -12916,8 +12998,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
}
if (EX(return_value)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
- ZVAL_COPY(EX(return_value), retval_ptr);
+ ZVAL_MAKE_REF(retval_ptr);
+ Z_ADDREF_P(retval_ptr);
+ ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
}
} while (0);
@@ -12961,10 +13044,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_AR
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
zval_ptr_dtor_nogc(free_op1.var);
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -13000,13 +13080,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
Z_TYPE_P(varptr) == IS_OBJECT ||
(Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
- if (!Z_ISREF_P(varptr)) {
- ZVAL_NEW_REF(varptr, varptr);
- }
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
+ ZVAL_MAKE_REF(varptr);
if (IS_VAR == IS_CV) {
Z_ADDREF_P(varptr);
}
@@ -13018,8 +13092,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
zend_error(E_STRICT, "Only variables should be passed by reference");
}
top = zend_vm_stack_top_inc(TSRMLS_C);
- // TODO: Try to avoid copying of immutable arrays ???
- ZVAL_DUP(top, varptr);
+ ZVAL_COPY(top, varptr);
zval_ptr_dtor_nogc(free_op1.var);
}
CHECK_EXCEPTION();
@@ -13046,24 +13119,16 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
if (Z_ISREF_P(varptr)) {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
Z_ADDREF_P(varptr);
ZVAL_COPY_VALUE(top, varptr);
} else if (IS_VAR == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
ZVAL_COPY_VALUE(top, varptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(top);
+ ZVAL_MAKE_REF(top);
} else {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(varptr)) {
- zval_opt_copy_ctor(varptr);
- }
- SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr);
+ ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_REF(top, Z_REF_P(varptr));
}
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
@@ -13085,10 +13150,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
zval_ptr_dtor_nogc(free_op1.var);
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -13186,11 +13248,11 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_free_op free_op1;
- zval *expr;
+ zval *expr, tmp;
zval *result = EX_VAR(opline->result.var);
SAVE_OPLINE();
- expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+ expr = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
switch (opline->extended_value) {
case IS_NULL:
@@ -13227,27 +13289,59 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(expr) == opline->extended_value) {
ZVAL_COPY_VALUE(result, expr);
if (IS_VAR == IS_CONST) {
- zval_opt_copy_ctor(result);
- } else if (IS_VAR == IS_CV) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
+ zval_copy_ctor_func(result);
+ }
+ } else if (IS_VAR != IS_TMP_VAR) {
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
}
+ zval_ptr_dtor_nogc(free_op1.var);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
- if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- ZVAL_DEREF(expr);
- }
- ZVAL_COPY_VALUE(result, expr);
- if (!0) {
- zval_opt_copy_ctor(result);
- }
-
if (opline->extended_value == IS_ARRAY) {
- convert_to_array(result);
+ if (Z_TYPE_P(expr) != IS_OBJECT) {
+ ZVAL_NEW_ARR(result);
+ zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_VAR != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_array(result);
+ }
} else {
- convert_to_object(result);
+ if (Z_TYPE_P(expr) != IS_ARRAY) {
+ object_init(result);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_VAR != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_object(result);
+ }
}
zval_ptr_dtor_nogc(free_op1.var);
@@ -13401,7 +13495,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
@@ -13421,7 +13515,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
Z_ADDREF_P(array_ptr);
}
@@ -13573,7 +13667,13 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zval *key = NULL;
array = array_ref = EX_VAR(opline->op1.var);
- ZVAL_DEREF(array);
+ if (Z_ISREF_P(array)) {
+ array = Z_REFVAL_P(array);
+ // TODO: referenced value might be changed to different array ???
+ if (Z_IMMUTABLE_P(array)) {
+ zval_copy_ctor(array);
+ }
+ }
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
key = EX_VAR((opline+1)->result.var);
}
@@ -13692,9 +13792,12 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value);
+ ZVAL_MAKE_REF(value);
+ Z_ADDREF_P(value);
+ ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
+ } else {
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- ZVAL_COPY(EX_VAR(opline->result.var), value);
CHECK_EXCEPTION();
ZEND_VM_INC_OPCODE();
@@ -13734,10 +13837,13 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- zval_ptr_dtor_nogc(free_op1.var);
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -13756,15 +13862,14 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
if (i_zend_is_true(value TSRMLS_CC)) {
- if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- zval_ptr_dtor_nogc(free_op1.var);
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -13783,11 +13888,13 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
- zval_ptr_dtor_nogc(free_op1.var);
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -13800,17 +13907,14 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
SAVE_OPLINE();
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
- if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_VAR == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_VAR == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- zval_ptr_dtor_nogc(free_op1.var);
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -14240,7 +14344,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -14295,7 +14399,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -14749,7 +14853,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -15453,7 +15557,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c);
}
retval = EX_VAR(opline->result.var);
- ZVAL_DUP(retval, &c->value);
+ ZVAL_COPY_VALUE(retval, &c->value);
+ if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
+ if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ zval_copy_ctor_func(retval);
+ } else {
+ Z_ADDREF_P(retval);
+ }
+ }
} else {
/* class constant */
zend_class_entry *ce;
@@ -15527,7 +15638,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
} else {
@@ -16109,7 +16220,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -16615,7 +16726,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -16670,7 +16781,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -17669,7 +17780,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
} else {
@@ -18102,7 +18213,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -18608,7 +18719,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -18663,7 +18774,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -19119,7 +19230,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -19874,7 +19985,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
} else {
@@ -20458,7 +20569,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -20688,7 +20799,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -20743,7 +20854,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -21019,7 +21130,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -21333,7 +21444,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
} else {
@@ -21659,7 +21770,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -22149,7 +22260,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -22204,7 +22315,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -23258,7 +23369,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
} else {
@@ -23689,7 +23800,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -23998,7 +24109,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -24053,7 +24164,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -24734,7 +24845,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
CACHE_PTR(Z_CACHE_SLOT_P(opline->op2.zv), c);
}
retval = EX_VAR(opline->result.var);
- ZVAL_DUP(retval, &c->value);
+ ZVAL_COPY_VALUE(retval, &c->value);
+ if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
+ if (Z_OPT_COPYABLE_P(retval) && (c->flags & CONST_PERSISTENT)) {
+ zval_copy_ctor_func(retval);
+ } else {
+ Z_ADDREF_P(retval);
+ }
+ }
} else {
/* class constant */
zend_class_entry *ce;
@@ -25151,7 +25269,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -25365,7 +25483,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -25420,7 +25538,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -26439,7 +26557,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -26653,7 +26771,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -26708,7 +26826,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -27727,7 +27845,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -27940,7 +28058,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -27995,7 +28113,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -28249,7 +28367,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -28462,7 +28580,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -28517,7 +28635,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -29528,7 +29646,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -29670,7 +29788,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -29727,7 +29845,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
var_ptr = Z_REFVAL_P(var_ptr);
} else {
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -29784,7 +29902,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -29837,7 +29955,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZVAL_DUP(retval, var_ptr);
} else {
ZVAL_DUP(retval, var_ptr);
- SEPARATE_ZVAL(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
}
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_OBJECT)
@@ -30058,10 +30176,12 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
if (IS_CV == IS_CONST) {
- zval_opt_copy_ctor_no_imm(EX(return_value));
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
+ zval_copy_ctor_func(EX(return_value));
+ }
}
} else if (Z_ISREF_P(retval_ptr)) {
- ZVAL_DUP(EX(return_value), Z_REFVAL_P(retval_ptr));
+ ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
} else {
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
@@ -30122,8 +30242,9 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
}
if (EX(return_value)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr);
- ZVAL_COPY(EX(return_value), retval_ptr);
+ ZVAL_MAKE_REF(retval_ptr);
+ Z_ADDREF_P(retval_ptr);
+ ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
}
} while (0);
@@ -30166,10 +30287,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARG
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -30205,13 +30323,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
Z_TYPE_P(varptr) == IS_OBJECT ||
(Z_REFCOUNTED_P(varptr) && Z_REFCOUNT_P(varptr) == 1))) {
- if (!Z_ISREF_P(varptr)) {
- ZVAL_NEW_REF(varptr, varptr);
- }
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
+ ZVAL_MAKE_REF(varptr);
if (IS_CV == IS_CV) {
Z_ADDREF_P(varptr);
}
@@ -30223,8 +30335,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
zend_error(E_STRICT, "Only variables should be passed by reference");
}
top = zend_vm_stack_top_inc(TSRMLS_C);
- // TODO: Try to avoid copying of immutable arrays ???
- ZVAL_DUP(top, varptr);
+ ZVAL_COPY(top, varptr);
}
CHECK_EXCEPTION();
@@ -30251,24 +30362,16 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
if (Z_ISREF_P(varptr)) {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(Z_REFVAL_P(varptr))) {
- zval_opt_copy_ctor(Z_REFVAL_P(varptr));
- }
Z_ADDREF_P(varptr);
ZVAL_COPY_VALUE(top, varptr);
} else if (IS_CV == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
ZVAL_COPY_VALUE(top, varptr);
- SEPARATE_ZVAL_TO_MAKE_IS_REF(top);
+ ZVAL_MAKE_REF(top);
} else {
- // TODO: Try to avoid copying of immutable arrays ???
- if (Z_OPT_IMMUTABLE_P(varptr)) {
- zval_opt_copy_ctor(varptr);
- }
- SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr);
+ ZVAL_MAKE_REF(varptr);
Z_ADDREF_P(varptr);
- ZVAL_COPY_VALUE(top, varptr);
+ ZVAL_REF(top, Z_REF_P(varptr));
}
ZEND_VM_NEXT_OPCODE();
@@ -30289,10 +30392,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
top = zend_vm_stack_top_inc(TSRMLS_C);
if (Z_ISREF_P(varptr)) {
- ZVAL_COPY_VALUE(top, Z_REFVAL_P(varptr));
- /* Immutable arrays may be passed without copying ??? */
- /* some internal functions may try to modify them !!! */
- zval_opt_copy_ctor_no_imm(top);
+ ZVAL_COPY(top, Z_REFVAL_P(varptr));
} else {
ZVAL_COPY_VALUE(top, varptr);
@@ -30379,11 +30479,11 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
- zval *expr;
+ zval *expr, tmp;
zval *result = EX_VAR(opline->result.var);
SAVE_OPLINE();
- expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
+ expr = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
switch (opline->extended_value) {
case IS_NULL:
@@ -30420,8 +30520,10 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(expr) == opline->extended_value) {
ZVAL_COPY_VALUE(result, expr);
if (IS_CV == IS_CONST) {
- zval_opt_copy_ctor(result);
- } else if (IS_CV == IS_CV) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
+ zval_copy_ctor_func(result);
+ }
+ } else if (IS_CV != IS_TMP_VAR) {
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
}
@@ -30429,18 +30531,47 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
- if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- ZVAL_DEREF(expr);
- }
- ZVAL_COPY_VALUE(result, expr);
- if (!0) {
- zval_opt_copy_ctor(result);
- }
-
if (opline->extended_value == IS_ARRAY) {
- convert_to_array(result);
+ if (Z_TYPE_P(expr) != IS_OBJECT) {
+ ZVAL_NEW_ARR(result);
+ zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_CV != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_array(result);
+ }
} else {
- convert_to_object(result);
+ if (Z_TYPE_P(expr) != IS_ARRAY) {
+ object_init(result);
+ if (Z_TYPE_P(expr) != IS_NULL) {
+ expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
+ zval_copy_ctor_func(expr);
+ }
+ } else if (IS_CV != IS_TMP_VAR) {
+ if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
+ }
+ }
+ } else {
+ ZVAL_COPY_VALUE(result, expr);
+ if (!0) {
+ zval_opt_copy_ctor(result);
+ }
+ convert_to_object(result);
+ }
}
CHECK_EXCEPTION();
@@ -30593,7 +30724,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ZVAL_DEREF(array_ptr);
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
array_ref = array_ptr;
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
ZVAL_NEW_REF(array_ptr, array_ptr);
@@ -30613,7 +30744,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = Z_OBJCE_P(array_ptr);
if (!ce || ce->get_iterator == NULL) {
if (!Z_ISREF_P(array_ref)) {
- SEPARATE_ZVAL(array_ptr);
+ SEPARATE_ZVAL_NOREF(array_ptr);
}
Z_ADDREF_P(array_ptr);
}
@@ -30787,10 +30918,13 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (i_zend_is_true(value TSRMLS_CC)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_CV == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -30808,15 +30942,14 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
if (i_zend_is_true(value TSRMLS_CC)) {
- if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_CV == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
ZEND_VM_JMP(opline->op2.jmp_addr);
}
@@ -30834,11 +30967,13 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
+ }
+ } else if (IS_CV == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -30851,16 +30986,14 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
SAVE_OPLINE();
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC);
- if (IS_CV == IS_VAR || IS_CV == IS_CV) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
- } else {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
- if (!0) {
- zval_opt_copy_ctor_no_imm(EX_VAR(opline->result.var));
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
+ if (IS_CV == IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
+ zval_copy_ctor_func(EX_VAR(opline->result.var));
}
+ } else if (IS_CV == IS_CV) {
+ if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
}
-
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -31289,7 +31422,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -31344,7 +31477,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -31798,7 +31931,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -32369,7 +32502,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -32951,7 +33084,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -33455,7 +33588,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -33510,7 +33643,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -34394,7 +34527,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -34827,7 +34960,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -35331,7 +35464,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -35386,7 +35519,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -35842,7 +35975,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -36481,7 +36614,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -37065,7 +37198,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -37293,7 +37426,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -37348,7 +37481,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -37624,7 +37757,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
ZVAL_COPY(EX_VAR(opline->result.var), retval);
} else {
if (/*type == BP_VAR_W &&*/ (opline->extended_value & ZEND_FETCH_MAKE_REF)) {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(retval);
+ ZVAL_MAKE_REF(retval);
}
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
}
@@ -37824,7 +37957,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -38132,7 +38265,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);
@@ -38620,7 +38753,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -38675,7 +38808,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op
}
if (EXPECTED(!Z_ISREF_P(var_ptr))) {
- SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
+ SEPARATE_ZVAL_NOREF(var_ptr);
} else {
ZVAL_DEREF(var_ptr);
}
@@ -39613,7 +39746,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(expr_ptr) == IS_STR_OFFSET)) {
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
}
- SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr);
+ ZVAL_MAKE_REF(expr_ptr);
Z_ADDREF_P(expr_ptr);
} else {
@@ -40044,7 +40177,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
&& (Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) {
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
} else {
- SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr);
+ ZVAL_MAKE_REF(value_ptr);
}
ZVAL_COPY(&generator->value, value_ptr);