diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-04-04 02:52:53 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-04-04 02:52:53 +0400 |
commit | 58f0f2503c0c1e8733615a582836a96b2f04a41a (patch) | |
tree | 4371c223a1af3c12d87a1e514386bfe05e9c819d | |
parent | 58871730c84b736b750b9dca681a8246feacf443 (diff) | |
download | php-git-58f0f2503c0c1e8733615a582836a96b2f04a41a.tar.gz |
Various VM optimizations
-rw-r--r-- | Zend/zend.h | 99 | ||||
-rw-r--r-- | Zend/zend_API.c | 2 | ||||
-rw-r--r-- | Zend/zend_API.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 209 | ||||
-rw-r--r-- | Zend/zend_gc.h | 3 | ||||
-rw-r--r-- | Zend/zend_types.h | 69 | ||||
-rw-r--r-- | Zend/zend_variables.h | 14 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 63 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 571 | ||||
-rw-r--r-- | ext/standard/array.c | 20 |
10 files changed, 419 insertions, 633 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index d8c14f0a07..71b80c3e79 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -661,7 +661,7 @@ END_EXTERN_C() zval *__z1 = (z); \ zval *__z2 = (v); \ ZVAL_COPY_VALUE(__z1, __z2); \ - if (Z_REFCOUNTED_P(__z1)) { \ + if (Z_OPT_REFCOUNTED_P(__z1)) { \ Z_ADDREF_P(__z1); \ } \ } while (0) @@ -671,7 +671,7 @@ END_EXTERN_C() zval *__z1 = (z); \ zval *__z2 = (v); \ ZVAL_COPY_VALUE(__z1, __z2); \ - zval_copy_ctor(__z1); \ + zval_opt_copy_ctor(__z1); \ } while (0) #define ZVAL_DEREF(z) do { \ @@ -698,7 +698,7 @@ END_EXTERN_C() zval *__z2 = (v); \ ZVAL_DEREF(__z2); \ ZVAL_COPY_VALUE(__z1, __z2); \ - zval_copy_ctor(__z1); \ + zval_opt_copy_ctor(__z1); \ } while (0) #define ZVAL_UNREF(z) do { \ @@ -718,66 +718,69 @@ END_EXTERN_C() Z_UNSET_ISREF_P(z); \ } while (0) -#define SEPARATE_ZVAL(zv) do { \ - zval *_zv = (zv); \ - if (Z_REFCOUNTED_P(_zv)) { \ - if (Z_REFCOUNT_P(_zv) > 1) { \ - if (Z_ISREF_P(_zv)) { \ - Z_DELREF_P(_zv); \ - ZVAL_DUP(_zv, Z_REFVAL_P(_zv)); \ - } else if (Z_TYPE_FLAGS_P(_zv) & IS_TYPE_COPYABLE) { \ - Z_DELREF_P(_zv); \ - zval_copy_ctor_func(_zv); \ - } \ - } \ - } \ +#define SEPARATE_ZVAL(zv) do { \ + zval *_zv = (zv); \ + if (Z_REFCOUNTED_P(_zv)) { \ + if (Z_REFCOUNT_P(_zv) > 1) { \ + if (Z_ISREF_P(_zv)) { \ + Z_DELREF_P(_zv); \ + ZVAL_DUP(_zv, Z_REFVAL_P(_zv)); \ + } else if (Z_COPYABLE_P(_zv)) { \ + Z_DELREF_P(_zv); \ + zval_copy_ctor_func(_zv); \ + } \ + } \ + } \ } while (0) -#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \ - zval *_zv = (zv); \ - if (!Z_ISREF_P(_zv) && \ - (Z_TYPE_FLAGS_P(_zv) & IS_TYPE_COPYABLE) && \ - Z_REFCOUNT_P(_zv) > 1) { \ - Z_DELREF_P(_zv); \ - zval_copy_ctor_func(_zv); \ - } \ +#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \ + zval *_zv = (zv); \ + if (!Z_ISREF_P(_zv) && \ + Z_COPYABLE_P(_zv) && \ + Z_REFCOUNT_P(_zv) > 1) { \ + Z_DELREF_P(_zv); \ + zval_copy_ctor_func(_zv); \ + } \ } 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)); \ - } \ - } \ +#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_TYPE_FLAGS_P(__zv) & IS_TYPE_COPYABLE) || \ - Z_REFCOUNT_P(__zv) == 1) { \ - ZVAL_NEW_REF(__zv, __zv); \ - } else { \ - Z_DELREF_P(__zv); \ - ZVAL_NEW_REF(__zv, __zv); \ - zval_copy_ctor_func(Z_REFVAL_P(__zv)); \ - } \ - } \ +#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) { \ + ZVAL_NEW_REF(__zv, __zv); \ + } else { \ + Z_DELREF_P(__zv); \ + ZVAL_NEW_REF(__zv, __zv); \ + zval_copy_ctor_func(Z_REFVAL_P(__zv)); \ + } \ + } \ } while (0) + +// TODO: remove ??? #define COPY_PZVAL_TO_ZVAL(zv, pzv) \ ZVAL_COPY_VALUE(&(zv), (pzv)); \ - if (Z_REFCOUNTED_P(pzv)) { \ + if (Z_OPT_REFCOUNTED_P(pzv)) { \ if (Z_REFCOUNT_P(pzv)>1) { \ zval_copy_ctor(&(zv)); \ Z_DELREF_P((pzv)); \ } \ } \ +// TODO: remove ??? #define REPLACE_ZVAL_VALUE(ppzv_dest, pzv_src, copy) { \ int is_ref, refcount; \ \ @@ -787,7 +790,7 @@ END_EXTERN_C() zval_dtor(*ppzv_dest); \ ZVAL_COPY_VALUE(*ppzv_dest, pzv_src); \ if (copy) { \ - zval_copy_ctor(*ppzv_dest); \ + zval_opt_copy_ctor(*ppzv_dest); \ } \ Z_SET_ISREF_TO_PP(ppzv_dest, is_ref); \ Z_SET_REFCOUNT_PP(ppzv_dest, refcount); \ diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 4c100a55d4..36995787df 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3844,7 +3844,7 @@ ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *na zval_dtor(property); ZVAL_COPY_VALUE(property, value); if (Z_REFCOUNT_P(value) > 0) { - zval_copy_ctor(property); + zval_opt_copy_ctor(property); } } else { zval garbage; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index a8bb4f3ff0..01ab9892e2 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -583,7 +583,7 @@ END_EXTERN_C() Z_REFVAL_P(__zv)); \ } \ if (copy) { \ - zval_copy_ctor(__z); \ + zval_opt_copy_ctor(__z); \ } \ if (dtor) { \ if (!copy) { \ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c4d2297a08..5c32ef0705 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -64,40 +64,13 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze #define TEMP_VAR_STACK_LIMIT 2000 -static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC) +static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free) { should_free->var = NULL; - if (Z_REFCOUNTED_P(z)) { - if (!Z_DELREF_P(z)) { - Z_SET_REFCOUNT_P(z, 1); -//??? Z_UNSET_ISREF_P(z); -//??? if (Z_ISREF_P(z)) { -//??? zend_reference *ref = Z_REF_P(z); -//??? ZVAL_COPY_VALUE(z, &ref->val); -//??? efree(ref); -//??? } - should_free->var = z; -/* should_free->is_var = 1; */ -//??? } else { -//??? if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) { -//??? Z_UNSET_ISREF_P(z); -//??? if (Z_ISREF_P(z)) { -//??? zend_reference *ref = Z_REF_P(z); -//??? ZVAL_COPY_VALUE(z, &ref->val); -//??? efree(ref); -//??? } -//??? } - } - } -} - -static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) -{ - if (Z_REFCOUNTED_P(z)) { - if (!Z_DELREF_P(z)) { - ZEND_ASSERT(z != &EG(uninitialized_zval)); - zval_dtor(z); - } + if (Z_REFCOUNTED_P(z) && !Z_DELREF_P(z)) { + Z_SET_REFCOUNT_P(z, 1); + should_free->var = z; + /* should_free->is_var = 1; */ } } @@ -105,9 +78,7 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) #define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC) #define zval_ptr_dtor_nogc(zv) i_zval_ptr_dtor_nogc(zv ZEND_FILE_LINE_CC TSRMLS_CC) -#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC) -#define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC) -#define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC) +#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f) #define PZVAL_LOCK(z) if (Z_REFCOUNTED_P(z)) Z_ADDREF_P((z)) #define SELECTIVE_PZVAL_LOCK(pzv, opline) if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); } @@ -183,9 +154,6 @@ static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_exec { zval *ret = EX_VAR(var); - if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); - } should_free->var = ret; return ret; } @@ -194,9 +162,6 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen { zval *ret = EX_VAR(var); - if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); - } should_free->var = ret; ZVAL_DEREF(ret); return ret; @@ -462,22 +427,6 @@ static zend_always_inline zval *_get_zval_ptr_ptr_var(zend_uint var, const zend_ return ret; } -//??? -#if 0 -static zend_always_inline zval *_get_zval_ptr_var_fast(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) -{ - zval* ptr = EX_VAR(var); - - if (EXPECTED(Z_TYPE_P(ptr) != IS_STR_OFFSET)) { - should_free->var = ptr; - } else { - /* string offset */ - should_free->var = Z_STR_OFFSET_P(EX_VAR(var))->str; - } - return ptr; -} -#endif - static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D) { if (EXPECTED(Z_OBJ(EG(This)) != NULL)) { @@ -514,22 +463,25 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v } /* this should modify object only if it's empty */ -static inline void make_real_object(zval *object_ptr TSRMLS_DC) +static inline zval* make_real_object(zval *object_ptr TSRMLS_DC) { zval *object = object_ptr; ZVAL_DEREF(object); - if (Z_TYPE_P(object) == IS_NULL - || (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) - || (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0) - ) { - if (EXPECTED(!Z_ISREF_P(object_ptr))) { - SEPARATE_ZVAL(object); + if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + if (Z_TYPE_P(object) == IS_NULL + || (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) + || (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); + object_init(object); + zend_error(E_WARNING, "Creating default object from empty value"); } - zval_dtor(object); - object_init(object); - zend_error(E_WARNING, "Creating default object from empty value"); } + return object; } ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC) @@ -722,16 +674,22 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p FREE_OP_IF_VAR(free_value); } -static inline int zend_assign_to_string_offset(zval *str_offset, zval *value, int value_type TSRMLS_DC) +static void zend_assign_to_string_offset(zval *str_offset, zval *value, int value_type, zval *result TSRMLS_DC) { - zval *str = Z_STR_OFFSET_P(str_offset)->str; - zend_uint offset = Z_STR_OFFSET_P(str_offset)->offset; + zval *str = Z_STR_OFFSET_STR_P(str_offset); + zend_uint offset = Z_STR_OFFSET_IDX_P(str_offset); + zend_string *old_str; if ((int)offset < 0) { zend_error(E_WARNING, "Illegal string offset: %d", offset); - return 0; + STR_RELEASE(Z_STR_P(str)); + if (result) { + ZVAL_NULL(result); + } + return; } + old_str = Z_STR_P(str); if (offset >= Z_STRLEN_P(str)) { int old_len = Z_STRLEN_P(str); Z_STR_P(str) = STR_REALLOC(Z_STR_P(str), offset + 1, 0); @@ -748,7 +706,7 @@ static inline int zend_assign_to_string_offset(zval *str_offset, zval *value, in ZVAL_COPY_VALUE(&tmp, value); if (value_type != IS_TMP_VAR) { - zval_copy_ctor(&tmp); + zval_opt_copy_ctor(&tmp); } convert_to_string(&tmp); Z_STRVAL_P(str)[offset] = Z_STRVAL(tmp)[0]; @@ -766,65 +724,92 @@ static inline int zend_assign_to_string_offset(zval *str_offset, zval *value, in * the value of an assignment to a string offset is undefined T(result->u.var).var = &T->str_offset.str; */ - return 1; + + STR_RELEASE(old_str); + if (result) { + zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[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(str) + offset, 1, 0)); + } + } } static inline zval* zend_assign_tmp_to_variable(zval *variable_ptr, zval *value TSRMLS_DC) { ZVAL_DEREF(variable_ptr); - 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); - return variable_ptr; - } - if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { - ZVAL_COPY_VALUE(variable_ptr, value); - } else if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1)) { - /* we need to split */ - Z_DELREF_P(variable_ptr); - GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); - } else { - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + zend_refcounted *garbage; + + 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); + return variable_ptr; + } - ZVAL_COPY_VALUE(variable_ptr, value); - _zval_dtor_func(garbage ZEND_FILE_LINE_CC); + garbage = Z_COUNTED_P(variable_ptr); + if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) { + /* we need to split */ + GC_REFCOUNT(garbage)--; + /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ + if ((Z_COLLECTABLE_P(variable_ptr)) && + UNEXPECTED(!GC_INFO(garbage))) { + gc_possible_root(garbage TSRMLS_CC); + } + } else { + ZVAL_COPY_VALUE(variable_ptr, value); + _zval_dtor_func(garbage ZEND_FILE_LINE_CC); + return variable_ptr; + } } + + ZVAL_COPY_VALUE(variable_ptr, value); + return variable_ptr; } static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *value TSRMLS_DC) { ZVAL_DEREF(variable_ptr); - 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); - return variable_ptr; - } - if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { - ZVAL_COPY_VALUE(variable_ptr, value); - if (Z_REFCOUNTED_P(value)) { - zval_copy_ctor(variable_ptr); - } - } else if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1)) { - /* we need to split */ - Z_DELREF_P(variable_ptr); - GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); - if (Z_REFCOUNTED_P(value)) { - zval_copy_ctor(variable_ptr); + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + zend_refcounted *garbage; + + 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); + return variable_ptr; } - } else { - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); - if (Z_REFCOUNTED_P(value)) { - zval_copy_ctor(variable_ptr); + garbage = Z_COUNTED_P(variable_ptr); + if (UNEXPECTED(GC_REFCOUNT(garbage) > 1)) { + /* we need to split */ + GC_REFCOUNT(garbage)--; + /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ + if (Z_COLLECTABLE_P(variable_ptr) && + UNEXPECTED(!GC_INFO(garbage))) { + gc_possible_root(garbage TSRMLS_CC); + } + } else { + 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_dtor_func(garbage ZEND_FILE_LINE_CC); + return variable_ptr; } - _zval_dtor_func(garbage ZEND_FILE_LINE_CC); } + + 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); + } + return variable_ptr; } diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h index fcf9159b2e..d060fae9dd 100644 --- a/Zend/zend_gc.h +++ b/Zend/zend_gc.h @@ -139,8 +139,7 @@ END_EXTERN_C() static zend_always_inline void gc_check_possible_root(zval *z TSRMLS_DC) { ZVAL_DEREF(z); - if ((Z_TYPE_FLAGS_P(z) & IS_TYPE_COLLECTABLE) && - UNEXPECTED(!Z_GC_INFO_P(z))) { + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { gc_possible_root(Z_COUNTED_P(z) TSRMLS_CC); } } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index c4c7bcdca2..5a50b37156 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -80,7 +80,6 @@ typedef struct _zend_resource zend_resource; typedef struct _zend_reference zend_reference; typedef struct _zend_ast_ref zend_ast_ref; typedef struct _zend_ast zend_ast; -typedef struct _zend_str_offset zend_str_offset; typedef int (*compare_func_t)(const void *, const void * TSRMLS_DC); typedef void (*sort_func_t)(void *, size_t, size_t, compare_func_t TSRMLS_DC); @@ -101,7 +100,6 @@ typedef union _zend_value { void *ptr; zend_class_entry *ce; zend_function *func; - zend_str_offset *str_offset; } zend_value; struct _zval_struct { @@ -119,6 +117,7 @@ struct _zval_struct { union { zend_uint var_flags; zend_uint next; /* hash collision chain */ + zend_uint str_offset; /* string offset */ } u2; }; @@ -142,12 +141,6 @@ struct _zend_string { char val[1]; }; -struct _zend_str_offset { - zend_refcounted gc; - zval *str; - int offset; -}; - typedef struct _Bucket { zend_ulong h; /* hash value (or numeric index) */ zend_string *key; /* string key or NULL for numerics */ @@ -251,6 +244,9 @@ static inline zend_uchar zval_get_type(const zval* pz) { #define Z_COUNTED(zval) (zval).value.counted #define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p)) +#define Z_TYPE_FLAGS_SHIFT 8 +#define Z_CONST_FLAGS_SHIFT 8 + #define GC_REFCOUNT(p) ((zend_refcounted*)(p))->refcount #define GC_TYPE(p) ((zend_refcounted*)(p))->u.v.type #define GC_FLAGS(p) ((zend_refcounted*)(p))->u.v.flags @@ -278,15 +274,15 @@ static inline zend_uchar zval_get_type(const zval* pz) { /* extended types */ #define IS_INTERNED_STRING_EX IS_STRING -#define IS_STRING_EX (IS_STRING | (( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << 8)) -#define IS_ARRAY_EX (IS_ARRAY | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE | IS_TYPE_COPYABLE) << 8)) -#define IS_OBJECT_EX (IS_OBJECT | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE ) << 8)) -#define IS_RESOURCE_EX (IS_RESOURCE | (( IS_TYPE_REFCOUNTED ) << 8)) -#define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << 8)) +#define IS_STRING_EX (IS_STRING | (( IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_ARRAY_EX (IS_ARRAY | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_OBJECT_EX (IS_OBJECT | (( IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE ) << Z_TYPE_FLAGS_SHIFT)) +#define IS_RESOURCE_EX (IS_RESOURCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) +#define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) -#define IS_CONSTANT_EX (IS_CONSTANT | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << 8)) -#define IS_CONSTANT_ARRAY_EX (IS_CONSTANT_ARRAY | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << 8)) -#define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << 8)) +#define IS_CONSTANT_EX (IS_CONSTANT | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_CONSTANT_ARRAY_EX (IS_CONSTANT_ARRAY | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) +#define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) /* zval.u1.v.const_flags */ #define IS_CONSTANT_UNQUALIFIED 0x010 @@ -330,9 +326,28 @@ static inline zend_uchar zval_get_type(const zval* pz) { #define Z_OBJ_DEC_APPLY_COUNT_P(zv) Z_OBJ_DEC_APPLY_COUNT(*(zv)) /* All data types < IS_STRING have their constructor/destructors skipped */ -#define Z_REFCOUNTED(zval) (Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) +#define Z_REFCOUNTED(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0) #define Z_REFCOUNTED_P(zval_p) Z_REFCOUNTED(*(zval_p)) +#define Z_COLLECTABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_COLLECTABLE) != 0) +#define Z_COLLECTABLE_P(zval_p) Z_COLLECTABLE(*(zval_p)) + +#define Z_COPYABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_COPYABLE) != 0) +#define Z_COPYABLE_P(zval_p) Z_COPYABLE(*(zval_p)) + +/* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */ +#define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & 0xff) +#define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p)) + +#define Z_OPT_REFCOUNTED(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) +#define Z_OPT_REFCOUNTED_P(zval_p) Z_OPT_REFCOUNTED(*(zval_p)) + +#define Z_OPT_COLLECTABLE(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT)) != 0) +#define Z_OPT_COLLECTABLE_P(zval_p) Z_OPT_COLLECTABLE(*(zval_p)) + +#define Z_OPT_COPYABLE(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_COPYABLE << Z_TYPE_FLAGS_SHIFT)) != 0) +#define Z_OPT_COPYABLE_P(zval_p) Z_OPT_COPYABLE(*(zval_p)) + #define Z_ISREF(zval) (Z_TYPE(zval) == IS_REFERENCE) #define Z_ISREF_P(zval_p) Z_ISREF(*(zval_p)) @@ -420,9 +435,6 @@ static inline zend_uchar zval_get_type(const zval* pz) { #define Z_PTR(zval) (zval).value.ptr #define Z_PTR_P(zval_p) Z_PTR(*(zval_p)) -#define Z_STR_OFFSET(zval) (zval).value.str_offset -#define Z_STR_OFFSET_P(zval_p) Z_STR_OFFSET(*(zval_p)) - #define ZVAL_UNDEF(z) do { \ Z_TYPE_INFO_P(z) = IS_UNDEF; \ } while (0) @@ -579,13 +591,16 @@ static inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(z) = IS_PTR; \ } while (0) -#define ZVAL_STR_OFFSET(z, s, o) do { \ - zend_str_offset *x = emalloc(sizeof(zend_str_offset)); \ - GC_REFCOUNT(x) = 1; \ - GC_TYPE_INFO(x) = IS_STR_OFFSET; \ - x->str = (s); \ - x->offset = (o); \ - Z_STR_OFFSET_P(z) = x; \ + +#define Z_STR_OFFSET_STR(zval) Z_INDIRECT(zval) +#define Z_STR_OFFSET_STR_P(zval_p) Z_STR_OFFSET_STR(*(zval_p)) + +#define Z_STR_OFFSET_IDX(zval) (zval).u2.str_offset +#define Z_STR_OFFSET_IDX_P(zval_p) Z_STR_OFFSET_IDX(*(zval_p)) + +#define ZVAL_STR_OFFSET(z, s, i) do { \ + Z_STR_OFFSET_STR_P(z) = (s); \ + Z_STR_OFFSET_IDX_P(z) = (i); \ Z_TYPE_INFO_P(z) = IS_STR_OFFSET; \ } while (0) diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h index 37accac191..848efa3bf4 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -43,7 +43,18 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC); static zend_always_inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC) { if (Z_REFCOUNTED_P(zvalue)) { - if (Z_TYPE_FLAGS_P(zvalue) & IS_TYPE_COPYABLE) { + if (Z_COPYABLE_P(zvalue)) { + _zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC); + } else { + Z_ADDREF_P(zvalue); + } + } +} + +static zend_always_inline void _zval_opt_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC) +{ + if (Z_OPT_REFCOUNTED_P(zvalue)) { + if (Z_OPT_COPYABLE_P(zvalue)) { _zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC); } else { Z_ADDREF_P(zvalue); @@ -60,6 +71,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC); ZEND_API void _zval_internal_ptr_dtor(zval *zvalue ZEND_FILE_LINE_DC); ZEND_API void _zval_dtor_wrapper(zval *zvalue); #define zval_copy_ctor(zvalue) _zval_copy_ctor((zvalue) ZEND_FILE_LINE_CC) +#define zval_opt_copy_ctor(zvalue) _zval_opt_copy_ctor((zvalue) ZEND_FILE_LINE_CC) #define zval_dtor(zvalue) _zval_dtor((zvalue) ZEND_FILE_LINE_CC) #define zval_ptr_dtor(zval_ptr) _zval_ptr_dtor((zval_ptr) ZEND_FILE_LINE_CC) #define zval_internal_dtor(zvalue) _zval_internal_dtor((zvalue) ZEND_FILE_LINE_CC) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 758dcaa4bf..3ef75f1279 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -340,10 +340,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -595,7 +592,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -694,7 +691,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -1701,17 +1698,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -1754,17 +1741,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) variable_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, OP2_TYPE TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP1_VAR_PTR() - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, OP2_TYPE, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_OP2_TMP_FREE()) { zval_dtor(value); @@ -2867,7 +2844,7 @@ 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_TMP_VAR) { - zval_copy_ctor(EX(return_value)); + zval_opt_copy_ctor(EX(return_value)); } FREE_OP1_IF_VAR(); } else if (Z_ISREF_P(retval_ptr)) { @@ -2876,7 +2853,7 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (OP1_TYPE == IS_CV) { - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } } @@ -2975,7 +2952,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) /* Not sure if a complete copy is what we want here */ ZVAL_COPY_VALUE(&exception, value); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(&exception); + zval_opt_copy_ctor(&exception); } zend_throw_exception_object(&exception TSRMLS_CC); @@ -3059,7 +3036,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY) ZVAL_COPY_VALUE(&valptr, value); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(&valptr); + zval_opt_copy_ctor(&valptr); } zend_vm_stack_push(&valptr TSRMLS_CC); FREE_OP1_IF_VAR(); @@ -3141,7 +3118,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY) } ZVAL_COPY_VALUE(&val, varptr); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(&val); + zval_opt_copy_ctor(&val); } FREE_OP1_IF_VAR(); zend_vm_stack_push(&val TSRMLS_CC); @@ -3849,7 +3826,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } @@ -3880,7 +3857,7 @@ ZEND_VM_C_LABEL(cast_again): } else { ZVAL_COPY_VALUE(result, expr); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } break; @@ -4893,7 +4870,7 @@ 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_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } FREE_OP1_IF_VAR(); #if DEBUG_ZEND>=2 @@ -4922,7 +4899,7 @@ ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY) } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } FREE_OP1_IF_VAR(); @@ -4948,7 +4925,7 @@ ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY) ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } FREE_OP1_IF_VAR(); CHECK_EXCEPTION(); @@ -4969,7 +4946,7 @@ ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY) } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!IS_OP1_TMP_FREE()) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -5347,7 +5324,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) if (Z_TYPE_FLAGS_P(val) & IS_TYPE_CONSTANT) { ZVAL_COPY_VALUE(&c.value, val); if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval_copy_ctor(&c.value); + zval_opt_copy_ctor(&c.value); } zval_update_constant(&c.value, NULL TSRMLS_CC); } else { @@ -5433,7 +5410,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE value = GET_OP1_ZVAL_PTR(BP_VAR_R); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!IS_OP1_TMP_FREE()) { @@ -5470,7 +5447,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!IS_OP1_TMP_FREE()) { @@ -5501,7 +5478,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!IS_OP2_TMP_FREE()) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 48bbb2b5e6..342762b941 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2551,7 +2551,7 @@ 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_TMP_VAR) { - zval_copy_ctor(EX(return_value)); + zval_opt_copy_ctor(EX(return_value)); } } else if (Z_ISREF_P(retval_ptr)) { @@ -2560,7 +2560,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_CONST == IS_CV) { - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } } @@ -2646,7 +2646,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS /* Not sure if a complete copy is what we want here */ ZVAL_COPY_VALUE(&exception, value); if (!0) { - zval_copy_ctor(&exception); + zval_opt_copy_ctor(&exception); } zend_throw_exception_object(&exception TSRMLS_CC); @@ -2676,7 +2676,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ZVAL_COPY_VALUE(&valptr, value); if (!0) { - zval_copy_ctor(&valptr); + zval_opt_copy_ctor(&valptr); } zend_vm_stack_push(&valptr TSRMLS_CC); @@ -2770,7 +2770,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } @@ -2801,7 +2801,7 @@ cast_again: } else { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } break; @@ -3157,7 +3157,7 @@ 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_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } #if DEBUG_ZEND>=2 @@ -3185,7 +3185,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -3210,7 +3210,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -3231,7 +3231,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -4208,7 +4208,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD if (Z_TYPE_FLAGS_P(val) & IS_TYPE_CONSTANT) { ZVAL_COPY_VALUE(&c.value, val); if (Z_TYPE_P(val) == IS_CONSTANT_ARRAY) { - zval_copy_ctor(&c.value); + zval_opt_copy_ctor(&c.value); } zval_update_constant(&c.value, NULL TSRMLS_CC); } else { @@ -4257,7 +4257,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE value = opline->op1.zv; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -4293,7 +4293,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -4323,7 +4323,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -4910,7 +4910,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ value = opline->op1.zv; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -4946,7 +4946,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -4976,7 +4976,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -5889,7 +5889,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ value = opline->op1.zv; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -5925,7 +5925,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -5955,7 +5955,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -6578,7 +6578,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL value = opline->op1.zv; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -6614,7 +6614,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -6644,7 +6644,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDL ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -7284,7 +7284,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A value = opline->op1.zv; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -7320,7 +7320,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -7350,7 +7350,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -7625,7 +7625,7 @@ 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_TMP_VAR) { - zval_copy_ctor(EX(return_value)); + zval_opt_copy_ctor(EX(return_value)); } } else if (Z_ISREF_P(retval_ptr)) { @@ -7634,7 +7634,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_TMP_VAR == IS_CV) { - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } } @@ -7720,7 +7720,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) /* Not sure if a complete copy is what we want here */ ZVAL_COPY_VALUE(&exception, value); if (!1) { - zval_copy_ctor(&exception); + zval_opt_copy_ctor(&exception); } zend_throw_exception_object(&exception TSRMLS_CC); @@ -7750,7 +7750,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_COPY_VALUE(&valptr, value); if (!1) { - zval_copy_ctor(&valptr); + zval_opt_copy_ctor(&valptr); } zend_vm_stack_push(&valptr TSRMLS_CC); @@ -7845,7 +7845,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); if (!1) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } @@ -7876,7 +7876,7 @@ cast_again: } else { ZVAL_COPY_VALUE(result, expr); if (!1) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } break; @@ -8259,7 +8259,7 @@ 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_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } #if DEBUG_ZEND>=2 @@ -8288,7 +8288,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!1) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -8314,7 +8314,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!1) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -8335,7 +8335,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!1) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -9249,7 +9249,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -9285,7 +9285,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -9315,7 +9315,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -9902,7 +9902,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -9938,7 +9938,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -9968,7 +9968,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -10881,7 +10881,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -10917,7 +10917,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -10947,7 +10947,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -11438,7 +11438,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -11474,7 +11474,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -11504,7 +11504,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -12088,7 +12088,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -12124,7 +12124,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -12154,7 +12154,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -12621,7 +12621,7 @@ 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_TMP_VAR) { - zval_copy_ctor(EX(return_value)); + zval_opt_copy_ctor(EX(return_value)); } zval_ptr_dtor_nogc(free_op1.var); } else if (Z_ISREF_P(retval_ptr)) { @@ -12630,7 +12630,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_VAR == IS_CV) { - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } } @@ -12717,7 +12717,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) /* Not sure if a complete copy is what we want here */ ZVAL_COPY_VALUE(&exception, value); if (!0) { - zval_copy_ctor(&exception); + zval_opt_copy_ctor(&exception); } zend_throw_exception_object(&exception TSRMLS_CC); @@ -12799,7 +12799,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND } ZVAL_COPY_VALUE(&val, varptr); if (!0) { - zval_copy_ctor(&val); + zval_opt_copy_ctor(&val); } zval_ptr_dtor_nogc(free_op1.var); zend_vm_stack_push(&val TSRMLS_CC); @@ -12962,7 +12962,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } @@ -12993,7 +12993,7 @@ cast_again: } else { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } break; @@ -13488,7 +13488,7 @@ 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_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } zval_ptr_dtor_nogc(free_op1.var); #if DEBUG_ZEND>=2 @@ -13517,7 +13517,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } zval_ptr_dtor_nogc(free_op1.var); @@ -13543,7 +13543,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } zval_ptr_dtor_nogc(free_op1.var); CHECK_EXCEPTION(); @@ -13564,7 +13564,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -13883,10 +13883,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -14137,7 +14134,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -14236,7 +14233,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -15003,17 +15000,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -15056,17 +15043,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_CONST TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);} - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_CONST, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -15949,7 +15926,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -15986,7 +15963,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -16017,7 +15994,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -16348,10 +16325,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -16603,7 +16577,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -16702,7 +16676,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -17291,17 +17265,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -17344,17 +17308,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);} - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (1) { zval_dtor(value); @@ -17999,7 +17953,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -18036,7 +17990,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -18067,7 +18021,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -18398,10 +18352,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -18653,7 +18604,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -18752,7 +18703,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -19520,17 +19471,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -19573,17 +19514,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_VAR TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);} - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -20440,7 +20371,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -20477,7 +20408,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -20508,7 +20439,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -20564,10 +20495,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -21125,17 +21053,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -21567,7 +21485,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -21604,7 +21522,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -21635,7 +21553,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -21966,10 +21884,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -22220,7 +22135,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -22319,7 +22234,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -22907,17 +22822,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -22960,17 +22865,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_CV TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);} - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_CV, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -23676,7 +23571,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -23713,7 +23608,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -23744,7 +23639,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -23880,10 +23775,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -24133,7 +24025,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -24232,7 +24124,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -25133,7 +25025,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -25169,7 +25061,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -25199,7 +25091,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDL ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -25254,10 +25146,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -25508,7 +25397,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -25607,7 +25496,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -26422,7 +26311,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -26458,7 +26347,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -26488,7 +26377,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -26543,10 +26432,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -26797,7 +26683,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -26896,7 +26782,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -27711,7 +27597,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -27747,7 +27633,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -27777,7 +27663,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -27833,10 +27719,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -28113,7 +27996,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -28149,7 +28032,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -28179,7 +28062,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HAND ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -28234,10 +28117,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -28487,7 +28367,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -28586,7 +28466,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -29399,7 +29279,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -29435,7 +29315,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -29465,7 +29345,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -29913,7 +29793,7 @@ 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_TMP_VAR) { - zval_copy_ctor(EX(return_value)); + zval_opt_copy_ctor(EX(return_value)); } } else if (Z_ISREF_P(retval_ptr)) { @@ -29922,7 +29802,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_CV == IS_CV) { - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } } @@ -30008,7 +29888,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) /* Not sure if a complete copy is what we want here */ ZVAL_COPY_VALUE(&exception, value); if (!0) { - zval_copy_ctor(&exception); + zval_opt_copy_ctor(&exception); } zend_throw_exception_object(&exception TSRMLS_CC); @@ -30090,7 +29970,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL } ZVAL_COPY_VALUE(&val, varptr); if (!0) { - zval_copy_ctor(&val); + zval_opt_copy_ctor(&val); } zend_vm_stack_push(&val TSRMLS_CC); @@ -30241,7 +30121,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } @@ -30272,7 +30152,7 @@ cast_again: } else { ZVAL_COPY_VALUE(result, expr); if (!0) { - zval_copy_ctor(result); + zval_opt_copy_ctor(result); } } break; @@ -30628,7 +30508,7 @@ 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_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } #if DEBUG_ZEND>=2 @@ -30656,7 +30536,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -30681,7 +30561,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } CHECK_EXCEPTION(); @@ -30702,7 +30582,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER } else { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value); if (!0) { - zval_copy_ctor(EX_VAR(opline->result.var)); + zval_opt_copy_ctor(EX_VAR(opline->result.var)); } } @@ -31020,10 +30900,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -31273,7 +31150,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -31372,7 +31249,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -32133,17 +32010,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -32186,17 +32053,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_CONST TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_CONST, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -32867,7 +32724,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -32903,7 +32760,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -32933,7 +32790,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -33264,10 +33121,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -33518,7 +33372,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -33617,7 +33471,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -34200,17 +34054,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -34253,17 +34097,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (1) { zval_dtor(value); @@ -34789,7 +34623,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -34825,7 +34659,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -34855,7 +34689,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!1) { @@ -35186,10 +35020,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -35440,7 +35271,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -35539,7 +35370,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -36301,17 +36132,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -36354,17 +36175,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_VAR TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_VAR, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -37101,7 +36912,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -37137,7 +36948,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -37167,7 +36978,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -37223,10 +37034,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -37781,17 +37589,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -38091,7 +37889,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -38127,7 +37925,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -38157,7 +37955,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -38488,10 +38286,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - make_real_object(object TSRMLS_CC); - } - ZVAL_DEREF(object); + object = make_real_object(object TSRMLS_CC); value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); @@ -38741,7 +38536,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -38840,7 +38635,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); } - make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ + object = make_real_object(object TSRMLS_CC); /* this should modify object only if it's empty */ if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); @@ -39422,17 +39217,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of FREE_OP_VAR_PTR(free_op_data2); - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) { if (IS_TMP_FREE(free_op_data1)) { zval_dtor(value); @@ -39475,17 +39260,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) { - zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str); - if (zend_assign_to_string_offset(variable_ptr, value, IS_CV TSRMLS_CC)) { - if (RETURN_VALUE_USED(opline)) { - ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1); - } - } else if (RETURN_VALUE_USED(opline)) { - ZVAL_NULL(EX_VAR(opline->result.var)); - } -//??? instead of - STR_RELEASE(old_str); - efree(Z_STR_OFFSET_P(variable_ptr)); + zend_assign_to_string_offset(variable_ptr, value, IS_CV, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC); } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { if (0) { zval_dtor(value); @@ -40071,7 +39846,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -40107,7 +39882,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ) { //??? INIT_PZVAL_COPY(copy, value); ZVAL_COPY_VALUE(&generator->value, value); - if (Z_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); + if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1); /* Temporary variables don't need ctor copying */ if (!0) { @@ -40137,7 +39912,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ) { //??? INIT_PZVAL_COPY(copy, key); ZVAL_COPY_VALUE(&generator->key, key); - if (Z_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); + if (Z_OPT_REFCOUNTED(generator->key)) Z_SET_REFCOUNT(generator->key, 1); /* Temporary variables don't need ctor copying */ if (!0) { diff --git a/ext/standard/array.c b/ext/standard/array.c index e774a7371b..b38dc6dceb 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -832,6 +832,10 @@ PHP_FUNCTION(end) RETURN_FALSE; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + RETURN_ZVAL_FAST(entry); } } @@ -855,6 +859,10 @@ PHP_FUNCTION(prev) RETURN_FALSE; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + RETURN_ZVAL_FAST(entry); } } @@ -878,6 +886,10 @@ PHP_FUNCTION(next) RETURN_FALSE; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + RETURN_ZVAL_FAST(entry); } } @@ -901,6 +913,10 @@ PHP_FUNCTION(reset) RETURN_FALSE; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + RETURN_ZVAL_FAST(entry); } } @@ -921,6 +937,10 @@ PHP_FUNCTION(current) RETURN_FALSE; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + } + RETURN_ZVAL_FAST(entry); } /* }}} */ |