diff options
Diffstat (limited to 'Zend/zend.h')
-rw-r--r-- | Zend/zend.h | 460 |
1 files changed, 219 insertions, 241 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index a226e11c60..c071acd87d 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -52,20 +52,20 @@ # define ZEND_PATHS_SEPARATOR ':' #endif -#ifdef ZEND_WIN32 /* Only use this macro if you know for sure that all of the switches values are covered by its case statements */ -#define EMPTY_SWITCH_DEFAULT_CASE() \ - default: \ - __assume(0); \ - break; +#if ZEND_DEBUG +# define EMPTY_SWITCH_DEFAULT_CASE() default: ZEND_ASSERT(0); break; +#elif defined(ZEND_WIN32) +# define EMPTY_SWITCH_DEFAULT_CASE() default: __assume(0); break; #else -#define EMPTY_SWITCH_DEFAULT_CASE() +# define EMPTY_SWITCH_DEFAULT_CASE() #endif /* all HAVE_XXX test have to be after the include of zend_config above */ #include <stdio.h> +#include <assert.h> #ifdef HAVE_UNIX_H # include <unix.h> @@ -179,6 +179,14 @@ char *alloca (); # define ZEND_ATTRIBUTE_DEPRECATED #endif +#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4003 +# define ZEND_ATTRIBUTE_UNUSED __attribute__((unused)) +# define ZEND_ATTRIBUTE_UNUSED_LABEL __attribute__((cold, unused)); +#else +# define ZEND_ATTRIBUTE_UNUSED +# define ZEND_ATTRIBUTE_UNUSED_LABEL +#endif + #if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__) # define ZEND_FASTCALL __attribute__((fastcall)) #elif defined(_MSC_VER) && defined(_M_IX86) @@ -252,7 +260,6 @@ char *alloca (); #include "zend_alloc.h" #include "zend_types.h" -#include "zend_string.h" #ifdef HAVE_LIMITS_H # include <limits.h> @@ -284,11 +291,16 @@ typedef enum { } ZEND_RESULT_CODE; #include "zend_hash.h" -#include "zend_ts_hash.h" #include "zend_llist.h" -#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC -#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC +#define INTERNAL_FUNCTION_PARAMETERS zend_uint param_count, zval *return_value TSRMLS_DC +#define INTERNAL_FUNCTION_PARAM_PASSTHRU param_count, return_value TSRMLS_CC + +#define USED_RET() \ + (!EG(current_execute_data) || \ + !EG(current_execute_data)->prev_execute_data || \ + !ZEND_USER_CODE(EG(current_execute_data)->prev_execute_data->func->common.type) || \ + !(EG(current_execute_data)->prev_execute_data->opline->result_type & EXT_TYPE_UNUSED)) #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__) void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn)); @@ -296,75 +308,38 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore # define zend_error_noreturn zend_error #endif -/* - * zval - */ -typedef struct _zend_class_entry zend_class_entry; - -typedef struct _zend_guard { - zend_bool in_get; - zend_bool in_set; - zend_bool in_unset; - zend_bool in_isset; - zend_bool dummy; /* sizeof(zend_guard) must not be equal to sizeof(void*) */ -} zend_guard; - -typedef struct _zend_object { - zend_class_entry *ce; - HashTable *properties; - zval **properties_table; - HashTable *guards; /* protects from __get/__set ... recursion */ -} zend_object; - #include "zend_object_handlers.h" #include "zend_ast.h" -typedef union _zvalue_value { - long lval; /* long value */ - double dval; /* double value */ - struct { - char *val; - int len; - } str; - HashTable *ht; /* hash table value */ - zend_object_value obj; - zend_ast *ast; -} zvalue_value; - -struct _zval_struct { - /* Variable information */ - zvalue_value value; /* value */ - zend_uint refcount__gc; - zend_uchar type; /* active type */ - zend_uchar is_ref__gc; -}; - -#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) -#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) -#define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) -#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) -#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) -#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) -#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) -#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) +/* overloaded elements data types */ +#define OE_IS_ARRAY (1<<0) +#define OE_IS_OBJECT (1<<1) +#define OE_IS_METHOD (1<<2) -#define Z_REFCOUNT_P(pz) zval_refcount_p(pz) +#define Z_REFCOUNT_P(pz) zval_refcount_p(pz) #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) -#define Z_ADDREF_P(pz) zval_addref_p(pz) -#define Z_DELREF_P(pz) zval_delref_p(pz) -#define Z_ISREF_P(pz) zval_isref_p(pz) -#define Z_SET_ISREF_P(pz) zval_set_isref_p(pz) -#define Z_UNSET_ISREF_P(pz) zval_unset_isref_p(pz) -#define Z_SET_ISREF_TO_P(pz, isref) zval_set_isref_to_p(pz, isref) - -#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) +#define Z_ADDREF_P(pz) zval_addref_p(pz) +#define Z_DELREF_P(pz) zval_delref_p(pz) + +#define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z)) #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc) -#define Z_ADDREF(z) Z_ADDREF_P(&(z)) -#define Z_DELREF(z) Z_DELREF_P(&(z)) -#define Z_ISREF(z) Z_ISREF_P(&(z)) -#define Z_SET_ISREF(z) Z_SET_ISREF_P(&(z)) -#define Z_UNSET_ISREF(z) Z_UNSET_ISREF_P(&(z)) -#define Z_SET_ISREF_TO(z, isref) Z_SET_ISREF_TO_P(&(z), isref) +#define Z_ADDREF(z) Z_ADDREF_P(&(z)) +#define Z_DELREF(z) Z_DELREF_P(&(z)) + +#define Z_TRY_ADDREF_P(pz) do { \ + if (Z_REFCOUNTED_P((pz))) { \ + Z_ADDREF_P((pz)); \ + } \ +} while (0) + +#define Z_TRY_DELREF_P(pz) do { \ + if (Z_REFCOUNTED_P((pz))) { \ + Z_DELREF_P((pz)); \ + } \ +} while (0) + +#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z)) +#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z)) #if ZEND_DEBUG #define zend_always_inline inline @@ -388,43 +363,63 @@ struct _zval_struct { #endif /* ZEND_DEBUG */ #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) -# define EXPECTED(condition) __builtin_expect(condition, 1) -# define UNEXPECTED(condition) __builtin_expect(condition, 0) +# define EXPECTED(condition) __builtin_expect(!(!(condition)), 1) +# define UNEXPECTED(condition) __builtin_expect(!(!(condition)), 0) #else # define EXPECTED(condition) (condition) # define UNEXPECTED(condition) (condition) #endif -static zend_always_inline zend_uint zval_refcount_p(zval* pz) { - return pz->refcount__gc; -} +#ifndef XtOffsetOf +# if defined(CRAY) || (defined(__ARMCC_VERSION) && !defined(LINUX)) +# ifdef __STDC__ +# define XtOffset(p_type, field) _Offsetof(p_type, field) +# else +# ifdef CRAY2 +# define XtOffset(p_type, field) \ + (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) -static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) { - return pz->refcount__gc = rc; -} +# else /* !CRAY2 */ -static zend_always_inline zend_uint zval_addref_p(zval* pz) { - return ++pz->refcount__gc; -} +# define XtOffset(p_type, field) ((unsigned int)&(((p_type)NULL)->field)) -static zend_always_inline zend_uint zval_delref_p(zval* pz) { - return --pz->refcount__gc; -} +# endif /* !CRAY2 */ +# endif /* __STDC__ */ +# else /* ! (CRAY || __arm) */ + +# define XtOffset(p_type, field) \ + ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) + +# endif /* !CRAY */ -static zend_always_inline zend_bool zval_isref_p(zval* pz) { - return pz->is_ref__gc; +# ifdef offsetof +# define XtOffsetOf(s_type, field) offsetof(s_type, field) +# else +# define XtOffsetOf(s_type, field) XtOffset(s_type*, field) +# endif + +#endif + +#include "zend_string.h" + +static zend_always_inline zend_uint zval_refcount_p(zval* pz) { + ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz)); + return GC_REFCOUNT(Z_COUNTED_P(pz)); } -static zend_always_inline zend_bool zval_set_isref_p(zval* pz) { - return pz->is_ref__gc = 1; +static zend_always_inline zend_uint zval_set_refcount_p(zval* pz, zend_uint rc) { + ZEND_ASSERT(Z_REFCOUNTED_P(pz)); + return GC_REFCOUNT(Z_COUNTED_P(pz)) = rc; } -static zend_always_inline zend_bool zval_unset_isref_p(zval* pz) { - return pz->is_ref__gc = 0; +static zend_always_inline zend_uint zval_addref_p(zval* pz) { + ZEND_ASSERT(Z_REFCOUNTED_P(pz)); + return ++GC_REFCOUNT(Z_COUNTED_P(pz)); } -static zend_always_inline zend_bool zval_set_isref_to_p(zval* pz, zend_bool isref) { - return pz->is_ref__gc = isref; +static zend_always_inline zend_uint zval_delref_p(zval* pz) { + ZEND_ASSERT(Z_REFCOUNTED_P(pz)); + return --GC_REFCOUNT(Z_COUNTED_P(pz)); } /* excpt.h on Digital Unix 4.0 defines function_table */ @@ -442,20 +437,18 @@ typedef struct _zend_serialize_data zend_serialize_data; typedef struct _zend_unserialize_data zend_unserialize_data; struct _zend_trait_method_reference { - const char* method_name; - unsigned int mname_len; - + zend_string *method_name; zend_class_entry *ce; - - const char* class_name; - unsigned int cname_len; + zend_string *class_name; }; typedef struct _zend_trait_method_reference zend_trait_method_reference; struct _zend_trait_precedence { - zend_trait_method_reference *trait_method; - - zend_class_entry** exclude_from_classes; + zend_trait_method_reference *trait_method; + union { + zend_class_entry *ce; + zend_string *class_name; + } *exclude_from_classes; }; typedef struct _zend_trait_precedence zend_trait_precedence; @@ -465,8 +458,7 @@ struct _zend_trait_alias { /** * name for method to be added */ - const char* alias; - unsigned int alias_len; + zend_string *alias; /** * modifiers to be set on trait method @@ -477,17 +469,16 @@ typedef struct _zend_trait_alias zend_trait_alias; struct _zend_class_entry { char type; - const char *name; - zend_uint name_length; + zend_string *name; struct _zend_class_entry *parent; int refcount; zend_uint ce_flags; HashTable function_table; HashTable properties_info; - zval **default_properties_table; - zval **default_static_members_table; - zval **static_members_table; + zval *default_properties_table; + zval *default_static_members_table; + zval *static_members_table; HashTable constants_table; int default_properties_count; int default_static_members_count; @@ -509,14 +500,14 @@ struct _zend_class_entry { zend_class_iterator_funcs iterator_funcs; /* handlers */ - zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC); + zend_object* (*create_object)(zend_class_entry *class_type TSRMLS_DC); zend_object_iterator *(*get_iterator)(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC); int (*interface_gets_implemented)(zend_class_entry *iface, zend_class_entry *class_type TSRMLS_DC); /* a class implements this interface */ - union _zend_function *(*get_static_method)(zend_class_entry *ce, char* method, int method_len TSRMLS_DC); + union _zend_function *(*get_static_method)(zend_class_entry *ce, zend_string* method TSRMLS_DC); /* serializer callbacks */ int (*serialize)(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC); - int (*unserialize)(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC); + int (*unserialize)(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC); zend_class_entry **interfaces; zend_uint num_interfaces; @@ -528,11 +519,10 @@ struct _zend_class_entry { union { struct { - const char *filename; + zend_string *filename; zend_uint line_start; zend_uint line_end; - const char *doc_comment; - zend_uint doc_comment_len; + zend_string *doc_comment; } user; struct { const struct _zend_function_entry *builtin_functions; @@ -555,6 +545,7 @@ typedef struct _zend_utility_functions { void (*on_timeout)(int seconds TSRMLS_DC); int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC); int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap); + zend_string *(*vstrpprintf_function)(size_t max_len, const char *format, va_list ap); char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC); char *(*resolve_path_function)(const char *filename, int filename_len TSRMLS_DC); } zend_utility_functions; @@ -578,33 +569,6 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length); #define ZEND_TRUTH(x) ((x) ? 1 : 0) #define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b)) -/* data types */ -/* All data types <= IS_BOOL have their constructor/destructors skipped */ -#define IS_NULL 0 -#define IS_LONG 1 -#define IS_DOUBLE 2 -#define IS_BOOL 3 -#define IS_ARRAY 4 -#define IS_OBJECT 5 -#define IS_STRING 6 -#define IS_RESOURCE 7 -#define IS_CONSTANT 8 -#define IS_CONSTANT_AST 9 -#define IS_CALLABLE 10 - -#define IS_CONSTANT_TYPE_MASK 0x00f -#define IS_CONSTANT_UNQUALIFIED 0x010 -#define IS_LEXICAL_VAR 0x020 -#define IS_LEXICAL_REF 0x040 -#define IS_CONSTANT_IN_NAMESPACE 0x100 - -#define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST) - -/* overloaded elements data types */ -#define OE_IS_ARRAY (1<<0) -#define OE_IS_OBJECT (1<<1) -#define OE_IS_METHOD (1<<2) - int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC); void zend_shutdown(TSRMLS_D); void zend_register_standard_ini_entries(TSRMLS_D); @@ -645,9 +609,9 @@ END_EXTERN_C() BEGIN_EXTERN_C() ZEND_API char *get_zend_version(void); -ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy); -ZEND_API int zend_print_zval(zval *expr, int indent); -ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent); +ZEND_API int zend_make_printable_zval(zval *expr, zval *expr_copy TSRMLS_DC); +ZEND_API int zend_print_zval(zval *expr, int indent TSRMLS_DC); +ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC); ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC); ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); @@ -671,22 +635,9 @@ END_EXTERN_C() BEGIN_EXTERN_C() ZEND_API void free_estring(char **str_p); +ZEND_API void free_string_zval(zval *zv); END_EXTERN_C() -/* FIXME: Check if we can save if (ptr) too */ - -#define STR_FREE(ptr) if (ptr) { str_efree(ptr); } -#define STR_FREE_REL(ptr) if (ptr) { str_efree_rel(ptr); } - -#ifndef ZTS -#define STR_EMPTY_ALLOC() CG(interned_empty_string)? CG(interned_empty_string) : estrndup("", sizeof("")-1) -#else -#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1) -#endif - -#define STR_REALLOC(ptr, size) \ - ptr = (char *) erealloc(ptr, size); - /* output support */ #define ZEND_WRITE(str, str_len) zend_write((str), (str_len)) #define ZEND_WRITE_EX(str, str_len) write_func((str), (str_len)) @@ -705,6 +656,7 @@ extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, cons extern ZEND_API void (*zend_on_timeout)(int seconds TSRMLS_DC); extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC); extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap); +extern zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap); extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC); extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC); @@ -747,101 +699,127 @@ END_EXTERN_C() #define ZMSG_LOG_SCRIPT_NAME 6L #define ZMSG_MEMORY_LEAKS_GRAND_TOTAL 7L -#define INIT_PZVAL(z) \ - (z)->refcount__gc = 1; \ - (z)->is_ref__gc = 0; +#define ZVAL_COPY_VALUE(z, v) \ + do { \ + zval *_z1 = (z); \ + zval *_z2 = (v); \ + (_z1)->value = (_z2)->value; \ + Z_TYPE_INFO_P(_z1) = Z_TYPE_INFO_P(_z2); \ + } while (0) -#define INIT_ZVAL(z) z = zval_used_for_init; +#define ZVAL_COPY(z, v) \ + do { \ + zval *__z1 = (z); \ + zval *__z2 = (v); \ + ZVAL_COPY_VALUE(__z1, __z2); \ + if (Z_OPT_REFCOUNTED_P(__z1)) { \ + Z_ADDREF_P(__z1); \ + } \ + } while (0) -#define ALLOC_INIT_ZVAL(zp) \ - ALLOC_ZVAL(zp); \ - INIT_ZVAL(*zp); +#define ZVAL_DUP(z, v) \ + do { \ + zval *__z1 = (z); \ + zval *__z2 = (v); \ + ZVAL_COPY_VALUE(__z1, __z2); \ + zval_opt_copy_ctor(__z1); \ + } while (0) -#define MAKE_STD_ZVAL(zv) \ - ALLOC_ZVAL(zv); \ - INIT_PZVAL(zv); +#define ZVAL_DEREF(z) do { \ + if (UNEXPECTED(Z_ISREF_P(z))) { \ + (z) = Z_REFVAL_P(z); \ + } \ + } while (0) -#define PZVAL_IS_REF(z) Z_ISREF_P(z) +#define ZVAL_MAKE_REF(zv) do { \ + zval *__zv = (zv); \ + if (!Z_ISREF_P(__zv)) { \ + ZVAL_NEW_REF(__zv, __zv); \ + } \ + } while (0) -#define ZVAL_COPY_VALUE(z, v) \ - do { \ - (z)->value = (v)->value; \ - Z_TYPE_P(z) = Z_TYPE_P(v); \ +#define ZVAL_UNREF(z) do { \ + zval *_z = (z); \ + zend_reference *ref; \ + ZEND_ASSERT(Z_ISREF_P(_z)); \ + ref = Z_REF_P(_z); \ + ZVAL_COPY_VALUE(_z, &ref->val); \ + efree(ref); \ } while (0) -#define INIT_PZVAL_COPY(z, v) \ - do { \ - ZVAL_COPY_VALUE(z, v); \ - Z_SET_REFCOUNT_P(z, 1); \ - Z_UNSET_ISREF_P(z); \ +#define SEPARATE_STRING(zv) do { \ + zval *_zv = (zv); \ + if (Z_REFCOUNTED_P(_zv) && \ + Z_REFCOUNT_P(_zv) > 1) { \ + Z_DELREF_P(_zv); \ + zval_copy_ctor_func(_zv); \ + } \ } while (0) -#define SEPARATE_ZVAL(ppzv) \ - do { \ - if (Z_REFCOUNT_PP((ppzv)) > 1) { \ - zval *new_zv; \ - Z_DELREF_PP(ppzv); \ - ALLOC_ZVAL(new_zv); \ - INIT_PZVAL_COPY(new_zv, *(ppzv)); \ - *(ppzv) = new_zv; \ - zval_copy_ctor(new_zv); \ - } \ +#define SEPARATE_ARRAY(zv) do { \ + zval *_zv = (zv); \ + if (Z_REFCOUNT_P(_zv) > 1) { \ + if (!Z_IMMUTABLE_P(_zv)) { \ + Z_DELREF_P(_zv); \ + } \ + zval_copy_ctor_func(_zv); \ + } \ } while (0) -#define SEPARATE_ZVAL_IF_NOT_REF(ppzv) \ - if (!PZVAL_IS_REF(*ppzv)) { \ - SEPARATE_ZVAL(ppzv); \ - } +#define SEPARATE_ZVAL_NOREF(zv) do { \ + zval *_zv = (zv); \ + if (Z_COPYABLE_P(_zv) || \ + Z_IMMUTABLE_P(_zv)) { \ + if (Z_REFCOUNT_P(_zv) > 1) { \ + if (!Z_IMMUTABLE_P(_zv)) { \ + Z_DELREF_P(_zv); \ + } \ + zval_copy_ctor_func(_zv); \ + } \ + } \ + } while (0) -#define SEPARATE_ZVAL_TO_MAKE_IS_REF(ppzv) \ - if (!PZVAL_IS_REF(*ppzv)) { \ - SEPARATE_ZVAL(ppzv); \ - Z_SET_ISREF_PP((ppzv)); \ - } +#define SEPARATE_ZVAL(zv) do { \ + zval *_zv = (zv); \ + if (Z_REFCOUNTED_P(_zv) || \ + Z_IMMUTABLE_P(_zv)) { \ + if (Z_REFCOUNT_P(_zv) > 1) { \ + if (Z_COPYABLE_P(_zv) || \ + Z_IMMUTABLE_P(_zv)) { \ + if (!Z_IMMUTABLE_P(_zv)) { \ + Z_DELREF_P(_zv); \ + } \ + zval_copy_ctor_func(_zv); \ + } else if (Z_ISREF_P(_zv)) { \ + Z_DELREF_P(_zv); \ + ZVAL_DUP(_zv, Z_REFVAL_P(_zv)); \ + } \ + } \ + } \ + } while (0) -#define COPY_PZVAL_TO_ZVAL(zv, pzv) \ - (zv) = *(pzv); \ - if (Z_REFCOUNT_P(pzv)>1) { \ - zval_copy_ctor(&(zv)); \ - Z_DELREF_P((pzv)); \ - } else { \ - FREE_ZVAL(pzv); \ - } \ - INIT_PZVAL(&(zv)); - -#define MAKE_COPY_ZVAL(ppzv, pzv) \ - INIT_PZVAL_COPY(pzv, *(ppzv)); \ - zval_copy_ctor((pzv)); - -#define REPLACE_ZVAL_VALUE(ppzv_dest, pzv_src, copy) { \ - int is_ref, refcount; \ - \ - SEPARATE_ZVAL_IF_NOT_REF(ppzv_dest); \ - is_ref = Z_ISREF_PP(ppzv_dest); \ - refcount = Z_REFCOUNT_PP(ppzv_dest); \ - zval_dtor(*ppzv_dest); \ - ZVAL_COPY_VALUE(*ppzv_dest, pzv_src); \ - if (copy) { \ - zval_copy_ctor(*ppzv_dest); \ - } \ - Z_SET_ISREF_TO_PP(ppzv_dest, is_ref); \ - Z_SET_REFCOUNT_PP(ppzv_dest, refcount); \ -} +#define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \ + zval *_zv = (zv); \ + if (Z_COPYABLE_P(_zv) || \ + Z_IMMUTABLE_P(_zv)) { \ + if (Z_REFCOUNT_P(_zv) > 1) { \ + if (!Z_IMMUTABLE_P(_zv)) { \ + Z_DELREF_P(_zv); \ + } \ + zval_copy_ctor_func(_zv); \ + } \ + } \ + } while (0) -#define SEPARATE_ARG_IF_REF(varptr) \ - if (PZVAL_IS_REF(varptr)) { \ - zval *original_var = varptr; \ - ALLOC_ZVAL(varptr); \ - INIT_PZVAL_COPY(varptr, original_var); \ - zval_copy_ctor(varptr); \ - } else { \ - Z_ADDREF_P(varptr); \ - } +#define SEPARATE_ARG_IF_REF(varptr) do { \ + ZVAL_DEREF(varptr); \ + if (Z_REFCOUNTED_P(varptr)) { \ + Z_ADDREF_P(varptr); \ + } \ + } while (0) #define READY_TO_DESTROY(zv) \ - (Z_REFCOUNT_P(zv) == 1 && \ - (Z_TYPE_P(zv) != IS_OBJECT || \ - zend_objects_store_get_refcount(zv TSRMLS_CC) == 1)) + (Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1) #define ZEND_MAX_RESERVED_RESOURCES 4 @@ -858,7 +836,7 @@ typedef enum { typedef struct { zend_error_handling_t handling; zend_class_entry *exception; - zval *user_handler; + zval user_handler; } zend_error_handling; ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC); |