xref: /PHP-7.1/Zend/zend_types.h (revision ccd4716e)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@zend.com>                                |
16    |          Zeev Suraski <zeev@zend.com>                                |
17    |          Dmitry Stogov <dmitry@zend.com>                             |
18    |          Xinchen Hui <xinchen.h@zend.com>                            |
19    +----------------------------------------------------------------------+
20 */
21 
22 /* $Id$ */
23 
24 #ifndef ZEND_TYPES_H
25 #define ZEND_TYPES_H
26 
27 #include "zend_portability.h"
28 #include "zend_long.h"
29 
30 #ifdef WORDS_BIGENDIAN
31 # define ZEND_ENDIAN_LOHI(lo, hi)          hi; lo;
32 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi)    hi; mi; lo;
33 # define ZEND_ENDIAN_LOHI_4(a, b, c, d)    d; c; b; a;
34 # define ZEND_ENDIAN_LOHI_C(lo, hi)        hi, lo
35 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi)  hi, mi, lo,
36 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d)  d, c, b, a
37 #else
38 # define ZEND_ENDIAN_LOHI(lo, hi)          lo; hi;
39 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi)    lo; mi; hi;
40 # define ZEND_ENDIAN_LOHI_4(a, b, c, d)    a; b; c; d;
41 # define ZEND_ENDIAN_LOHI_C(lo, hi)        lo, hi
42 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi)  lo, mi, hi,
43 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d)  a, b, c, d
44 #endif
45 
46 typedef unsigned char zend_bool;
47 typedef unsigned char zend_uchar;
48 
49 typedef enum {
50   SUCCESS =  0,
51   FAILURE = -1,		/* this MUST stay a negative number, or it may affect functions! */
52 } ZEND_RESULT_CODE;
53 
54 #ifdef ZEND_ENABLE_ZVAL_LONG64
55 # ifdef ZEND_WIN32
56 #  define ZEND_SIZE_MAX  _UI64_MAX
57 # else
58 #  define ZEND_SIZE_MAX  SIZE_MAX
59 # endif
60 #else
61 # if defined(ZEND_WIN32)
62 #  define ZEND_SIZE_MAX  _UI32_MAX
63 # else
64 #  define ZEND_SIZE_MAX SIZE_MAX
65 # endif
66 #endif
67 
68 typedef intptr_t zend_intptr_t;
69 typedef uintptr_t zend_uintptr_t;
70 
71 #ifdef ZTS
72 #define ZEND_TLS static TSRM_TLS
73 #define ZEND_EXT_TLS TSRM_TLS
74 #else
75 #define ZEND_TLS static
76 #define ZEND_EXT_TLS
77 #endif
78 
79 typedef struct _zend_object_handlers zend_object_handlers;
80 typedef struct _zend_class_entry     zend_class_entry;
81 typedef union  _zend_function        zend_function;
82 typedef struct _zend_execute_data    zend_execute_data;
83 
84 typedef struct _zval_struct     zval;
85 
86 typedef struct _zend_refcounted zend_refcounted;
87 typedef struct _zend_string     zend_string;
88 typedef struct _zend_array      zend_array;
89 typedef struct _zend_object     zend_object;
90 typedef struct _zend_resource   zend_resource;
91 typedef struct _zend_reference  zend_reference;
92 typedef struct _zend_ast_ref    zend_ast_ref;
93 typedef struct _zend_ast        zend_ast;
94 
95 typedef int  (*compare_func_t)(const void *, const void *);
96 typedef void (*swap_func_t)(void *, void *);
97 typedef void (*sort_func_t)(void *, size_t, size_t, compare_func_t, swap_func_t);
98 typedef void (*dtor_func_t)(zval *pDest);
99 typedef void (*copy_ctor_func_t)(zval *pElement);
100 
101 typedef union _zend_value {
102 	zend_long         lval;				/* long value */
103 	double            dval;				/* double value */
104 	zend_refcounted  *counted;
105 	zend_string      *str;
106 	zend_array       *arr;
107 	zend_object      *obj;
108 	zend_resource    *res;
109 	zend_reference   *ref;
110 	zend_ast_ref     *ast;
111 	zval             *zv;
112 	void             *ptr;
113 	zend_class_entry *ce;
114 	zend_function    *func;
115 	struct {
116 		uint32_t w1;
117 		uint32_t w2;
118 	} ww;
119 } zend_value;
120 
121 struct _zval_struct {
122 	zend_value        value;			/* value */
123 	union {
124 		struct {
125 			ZEND_ENDIAN_LOHI_4(
126 				zend_uchar    type,			/* active type */
127 				zend_uchar    type_flags,
128 				zend_uchar    const_flags,
129 				zend_uchar    reserved)	    /* call info for EX(This) */
130 		} v;
131 		uint32_t type_info;
132 	} u1;
133 	union {
134 		uint32_t     next;                 /* hash collision chain */
135 		uint32_t     cache_slot;           /* literal cache slot */
136 		uint32_t     lineno;               /* line number (for ast nodes) */
137 		uint32_t     num_args;             /* arguments number for EX(This) */
138 		uint32_t     fe_pos;               /* foreach position */
139 		uint32_t     fe_iter_idx;          /* foreach iterator index */
140 		uint32_t     access_flags;         /* class constant access flags */
141 		uint32_t     property_guard;       /* single property guard */
142 		uint32_t     extra;                /* not further specified */
143 	} u2;
144 };
145 
146 typedef struct _zend_refcounted_h {
147 	uint32_t         refcount;			/* reference counter 32-bit */
148 	union {
149 		struct {
150 			ZEND_ENDIAN_LOHI_3(
151 				zend_uchar    type,
152 				zend_uchar    flags,    /* used for strings & objects */
153 				uint16_t      gc_info)  /* keeps GC root number (or 0) and color */
154 		} v;
155 		uint32_t type_info;
156 	} u;
157 } zend_refcounted_h;
158 
159 struct _zend_refcounted {
160 	zend_refcounted_h gc;
161 };
162 
163 struct _zend_string {
164 	zend_refcounted_h gc;
165 	zend_ulong        h;                /* hash value */
166 	size_t            len;
167 	char              val[1];
168 };
169 
170 typedef struct _Bucket {
171 	zval              val;
172 	zend_ulong        h;                /* hash value (or numeric index)   */
173 	zend_string      *key;              /* string key or NULL for numerics */
174 } Bucket;
175 
176 typedef struct _zend_array HashTable;
177 
178 struct _zend_array {
179 	zend_refcounted_h gc;
180 	union {
181 		struct {
182 			ZEND_ENDIAN_LOHI_4(
183 				zend_uchar    flags,
184 				zend_uchar    nApplyCount,
185 				zend_uchar    nIteratorsCount,
186 				zend_uchar    consistency)
187 		} v;
188 		uint32_t flags;
189 	} u;
190 	uint32_t          nTableMask;
191 	Bucket           *arData;
192 	uint32_t          nNumUsed;
193 	uint32_t          nNumOfElements;
194 	uint32_t          nTableSize;
195 	uint32_t          nInternalPointer;
196 	zend_long         nNextFreeElement;
197 	dtor_func_t       pDestructor;
198 };
199 
200 /*
201  * HashTable Data Layout
202  * =====================
203  *
204  *                 +=============================+
205  *                 | HT_HASH(ht, ht->nTableMask) |
206  *                 | ...                         |
207  *                 | HT_HASH(ht, -1)             |
208  *                 +-----------------------------+
209  * ht->arData ---> | Bucket[0]                   |
210  *                 | ...                         |
211  *                 | Bucket[ht->nTableSize-1]    |
212  *                 +=============================+
213  */
214 
215 #define HT_INVALID_IDX ((uint32_t) -1)
216 
217 #define HT_MIN_MASK ((uint32_t) -2)
218 #define HT_MIN_SIZE 8
219 
220 #if SIZEOF_SIZE_T == 4
221 # define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
222 # define HT_HASH_TO_BUCKET_EX(data, idx) \
223 	((Bucket*)((char*)(data) + (idx)))
224 # define HT_IDX_TO_HASH(idx) \
225 	((idx) * sizeof(Bucket))
226 # define HT_HASH_TO_IDX(idx) \
227 	((idx) / sizeof(Bucket))
228 #elif SIZEOF_SIZE_T == 8
229 # define HT_MAX_SIZE 0x80000000
230 # define HT_HASH_TO_BUCKET_EX(data, idx) \
231 	((data) + (idx))
232 # define HT_IDX_TO_HASH(idx) \
233 	(idx)
234 # define HT_HASH_TO_IDX(idx) \
235 	(idx)
236 #else
237 # error "Unknown SIZEOF_SIZE_T"
238 #endif
239 
240 #define HT_HASH_EX(data, idx) \
241 	((uint32_t*)(data))[(int32_t)(idx)]
242 #define HT_HASH(ht, idx) \
243 	HT_HASH_EX((ht)->arData, idx)
244 
245 #define HT_HASH_SIZE(nTableMask) \
246 	(((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t))
247 #define HT_DATA_SIZE(nTableSize) \
248 	((size_t)(nTableSize) * sizeof(Bucket))
249 #define HT_SIZE_EX(nTableSize, nTableMask) \
250 	(HT_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask)))
251 #define HT_SIZE(ht) \
252 	HT_SIZE_EX((ht)->nTableSize, (ht)->nTableMask)
253 #define HT_USED_SIZE(ht) \
254 	(HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(Bucket)))
255 #define HT_HASH_RESET(ht) \
256 	memset(&HT_HASH(ht, (ht)->nTableMask), HT_INVALID_IDX, HT_HASH_SIZE((ht)->nTableMask))
257 #define HT_HASH_RESET_PACKED(ht) do { \
258 		HT_HASH(ht, -2) = HT_INVALID_IDX; \
259 		HT_HASH(ht, -1) = HT_INVALID_IDX; \
260 	} while (0)
261 #define HT_HASH_TO_BUCKET(ht, idx) \
262 	HT_HASH_TO_BUCKET_EX((ht)->arData, idx)
263 
264 #define HT_SET_DATA_ADDR(ht, ptr) do { \
265 		(ht)->arData = (Bucket*)(((char*)(ptr)) + HT_HASH_SIZE((ht)->nTableMask)); \
266 	} while (0)
267 #define HT_GET_DATA_ADDR(ht) \
268 	((char*)((ht)->arData) - HT_HASH_SIZE((ht)->nTableMask))
269 
270 typedef uint32_t HashPosition;
271 
272 typedef struct _HashTableIterator {
273 	HashTable    *ht;
274 	HashPosition  pos;
275 } HashTableIterator;
276 
277 struct _zend_object {
278 	zend_refcounted_h gc;
279 	uint32_t          handle; // TODO: may be removed ???
280 	zend_class_entry *ce;
281 	const zend_object_handlers *handlers;
282 	HashTable        *properties;
283 	zval              properties_table[1];
284 };
285 
286 struct _zend_resource {
287 	zend_refcounted_h gc;
288 	int               handle; // TODO: may be removed ???
289 	int               type;
290 	void             *ptr;
291 };
292 
293 struct _zend_reference {
294 	zend_refcounted_h gc;
295 	zval              val;
296 };
297 
298 struct _zend_ast_ref {
299 	zend_refcounted_h gc;
300 	zend_ast         *ast;
301 };
302 
303 /* regular data types */
304 #define IS_UNDEF					0
305 #define IS_NULL						1
306 #define IS_FALSE					2
307 #define IS_TRUE						3
308 #define IS_LONG						4
309 #define IS_DOUBLE					5
310 #define IS_STRING					6
311 #define IS_ARRAY					7
312 #define IS_OBJECT					8
313 #define IS_RESOURCE					9
314 #define IS_REFERENCE				10
315 
316 /* constant expressions */
317 #define IS_CONSTANT					11
318 #define IS_CONSTANT_AST				12
319 
320 /* fake types */
321 #define _IS_BOOL					13
322 #define IS_CALLABLE					14
323 #define IS_ITERABLE					19
324 #define IS_VOID						18
325 
326 /* internal types */
327 #define IS_INDIRECT             	15
328 #define IS_PTR						17
329 #define _IS_ERROR					20
330 
zval_get_type(const zval * pz)331 static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
332 	return pz->u1.v.type;
333 }
334 
335 #define ZEND_SAME_FAKE_TYPE(faketype, realtype) ( \
336 	(faketype) == (realtype) \
337 	|| ((faketype) == _IS_BOOL && ((realtype) == IS_TRUE || (realtype) == IS_FALSE)) \
338 )
339 
340 /* we should never set just Z_TYPE, we should set Z_TYPE_INFO */
341 #define Z_TYPE(zval)				zval_get_type(&(zval))
342 #define Z_TYPE_P(zval_p)			Z_TYPE(*(zval_p))
343 
344 #define Z_TYPE_FLAGS(zval)			(zval).u1.v.type_flags
345 #define Z_TYPE_FLAGS_P(zval_p)		Z_TYPE_FLAGS(*(zval_p))
346 
347 #define Z_CONST_FLAGS(zval)			(zval).u1.v.const_flags
348 #define Z_CONST_FLAGS_P(zval_p)		Z_CONST_FLAGS(*(zval_p))
349 
350 #define Z_TYPE_INFO(zval)			(zval).u1.type_info
351 #define Z_TYPE_INFO_P(zval_p)		Z_TYPE_INFO(*(zval_p))
352 
353 #define Z_NEXT(zval)				(zval).u2.next
354 #define Z_NEXT_P(zval_p)			Z_NEXT(*(zval_p))
355 
356 #define Z_CACHE_SLOT(zval)			(zval).u2.cache_slot
357 #define Z_CACHE_SLOT_P(zval_p)		Z_CACHE_SLOT(*(zval_p))
358 
359 #define Z_FE_POS(zval)				(zval).u2.fe_pos
360 #define Z_FE_POS_P(zval_p)			Z_FE_POS(*(zval_p))
361 
362 #define Z_FE_ITER(zval)				(zval).u2.fe_iter_idx
363 #define Z_FE_ITER_P(zval_p)			Z_FE_ITER(*(zval_p))
364 
365 #define Z_ACCESS_FLAGS(zval)		(zval).u2.access_flags
366 #define Z_ACCESS_FLAGS_P(zval_p)	Z_ACCESS_FLAGS(*(zval_p))
367 
368 #define Z_EXTRA(zval)				(zval).u2.extra
369 #define Z_EXTRA_P(zval_p)			Z_EXTRA(*(zval_p))
370 
371 #define Z_COUNTED(zval)				(zval).value.counted
372 #define Z_COUNTED_P(zval_p)			Z_COUNTED(*(zval_p))
373 
374 #define Z_TYPE_MASK					0xff
375 
376 #define Z_TYPE_FLAGS_SHIFT			8
377 #define Z_CONST_FLAGS_SHIFT			16
378 
379 #define GC_REFCOUNT(p)				(p)->gc.refcount
380 #define GC_TYPE(p)					(p)->gc.u.v.type
381 #define GC_FLAGS(p)					(p)->gc.u.v.flags
382 #define GC_INFO(p)					(p)->gc.u.v.gc_info
383 #define GC_TYPE_INFO(p)				(p)->gc.u.type_info
384 
385 #define Z_GC_TYPE(zval)				GC_TYPE(Z_COUNTED(zval))
386 #define Z_GC_TYPE_P(zval_p)			Z_GC_TYPE(*(zval_p))
387 
388 #define Z_GC_FLAGS(zval)			GC_FLAGS(Z_COUNTED(zval))
389 #define Z_GC_FLAGS_P(zval_p)		Z_GC_FLAGS(*(zval_p))
390 
391 #define Z_GC_INFO(zval)				GC_INFO(Z_COUNTED(zval))
392 #define Z_GC_INFO_P(zval_p)			Z_GC_INFO(*(zval_p))
393 
394 #define Z_GC_TYPE_INFO(zval)		GC_TYPE_INFO(Z_COUNTED(zval))
395 #define Z_GC_TYPE_INFO_P(zval_p)	Z_GC_TYPE_INFO(*(zval_p))
396 
397 /* zval.u1.v.type_flags */
398 #define IS_TYPE_CONSTANT			(1<<0)
399 #define IS_TYPE_IMMUTABLE			(1<<1)
400 #define IS_TYPE_REFCOUNTED			(1<<2)
401 #define IS_TYPE_COLLECTABLE			(1<<3)
402 #define IS_TYPE_COPYABLE			(1<<4)
403 
404 /* extended types */
405 #define IS_INTERNED_STRING_EX		IS_STRING
406 
407 #define IS_STRING_EX				(IS_STRING         | ((                   IS_TYPE_REFCOUNTED |                       IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
408 #define IS_ARRAY_EX					(IS_ARRAY          | ((                   IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
409 #define IS_OBJECT_EX				(IS_OBJECT         | ((                   IS_TYPE_REFCOUNTED | IS_TYPE_COLLECTABLE                   ) << Z_TYPE_FLAGS_SHIFT))
410 #define IS_RESOURCE_EX				(IS_RESOURCE       | ((                   IS_TYPE_REFCOUNTED                                         ) << Z_TYPE_FLAGS_SHIFT))
411 #define IS_REFERENCE_EX				(IS_REFERENCE      | ((                   IS_TYPE_REFCOUNTED                                         ) << Z_TYPE_FLAGS_SHIFT))
412 
413 #define IS_CONSTANT_EX				(IS_CONSTANT       | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED |                       IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
414 #define IS_CONSTANT_AST_EX			(IS_CONSTANT_AST   | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED |                       IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT))
415 
416 /* zval.u1.v.const_flags */
417 #define IS_CONSTANT_UNQUALIFIED		0x010
418 #define IS_CONSTANT_VISITED_MARK	0x020
419 #define IS_CONSTANT_CLASS           0x080  /* __CLASS__ in trait */
420 #define IS_CONSTANT_IN_NAMESPACE	0x100  /* used only in opline->extended_value */
421 
422 #define IS_CONSTANT_VISITED(p)		(Z_CONST_FLAGS_P(p) & IS_CONSTANT_VISITED_MARK)
423 #define MARK_CONSTANT_VISITED(p)	Z_CONST_FLAGS_P(p) |= IS_CONSTANT_VISITED_MARK
424 #define RESET_CONSTANT_VISITED(p)	Z_CONST_FLAGS_P(p) &= ~IS_CONSTANT_VISITED_MARK
425 
426 /* string flags (zval.value->gc.u.flags) */
427 #define IS_STR_PERSISTENT			(1<<0) /* allocated using malloc   */
428 #define IS_STR_INTERNED				(1<<1) /* interned string          */
429 #define IS_STR_PERMANENT        	(1<<2) /* relives request boundary */
430 
431 #define IS_STR_CONSTANT             (1<<3) /* constant index */
432 #define IS_STR_CONSTANT_UNQUALIFIED (1<<4) /* the same as IS_CONSTANT_UNQUALIFIED */
433 
434 /* array flags */
435 #define IS_ARRAY_IMMUTABLE			(1<<1) /* the same as IS_TYPE_IMMUTABLE */
436 
437 /* object flags (zval.value->gc.u.flags) */
438 #define IS_OBJ_APPLY_COUNT			0x07
439 #define IS_OBJ_DESTRUCTOR_CALLED	(1<<3)
440 #define IS_OBJ_FREE_CALLED			(1<<4)
441 #define IS_OBJ_USE_GUARDS           (1<<5)
442 #define IS_OBJ_HAS_GUARDS           (1<<6)
443 
444 #define Z_OBJ_APPLY_COUNT(zval) \
445 	(Z_GC_FLAGS(zval) & IS_OBJ_APPLY_COUNT)
446 
447 #define Z_OBJ_INC_APPLY_COUNT(zval) do { \
448 		Z_GC_FLAGS(zval) = \
449 			(Z_GC_FLAGS(zval) & ~IS_OBJ_APPLY_COUNT) | \
450 			((Z_GC_FLAGS(zval) & IS_OBJ_APPLY_COUNT) + 1); \
451 	} while (0)
452 
453 #define Z_OBJ_DEC_APPLY_COUNT(zval) do { \
454 		Z_GC_FLAGS(zval) = \
455 			(Z_GC_FLAGS(zval) & ~IS_OBJ_APPLY_COUNT) | \
456 			((Z_GC_FLAGS(zval) & IS_OBJ_APPLY_COUNT) - 1); \
457 	} while (0)
458 
459 #define Z_OBJ_APPLY_COUNT_P(zv)     Z_OBJ_APPLY_COUNT(*(zv))
460 #define Z_OBJ_INC_APPLY_COUNT_P(zv) Z_OBJ_INC_APPLY_COUNT(*(zv))
461 #define Z_OBJ_DEC_APPLY_COUNT_P(zv) Z_OBJ_DEC_APPLY_COUNT(*(zv))
462 
463 /* All data types < IS_STRING have their constructor/destructors skipped */
464 #define Z_CONSTANT(zval)			((Z_TYPE_FLAGS(zval) & IS_TYPE_CONSTANT) != 0)
465 #define Z_CONSTANT_P(zval_p)		Z_CONSTANT(*(zval_p))
466 
467 #define Z_REFCOUNTED(zval)			((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0)
468 #define Z_REFCOUNTED_P(zval_p)		Z_REFCOUNTED(*(zval_p))
469 
470 #define Z_COLLECTABLE(zval)			((Z_TYPE_FLAGS(zval) & IS_TYPE_COLLECTABLE) != 0)
471 #define Z_COLLECTABLE_P(zval_p)		Z_COLLECTABLE(*(zval_p))
472 
473 #define Z_COPYABLE(zval)			((Z_TYPE_FLAGS(zval) & IS_TYPE_COPYABLE) != 0)
474 #define Z_COPYABLE_P(zval_p)		Z_COPYABLE(*(zval_p))
475 
476 #define Z_IMMUTABLE(zval)			((Z_TYPE_FLAGS(zval) & IS_TYPE_IMMUTABLE) != 0)
477 #define Z_IMMUTABLE_P(zval_p)		Z_IMMUTABLE(*(zval_p))
478 
479 /* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */
480 #define Z_OPT_TYPE(zval)			(Z_TYPE_INFO(zval) & Z_TYPE_MASK)
481 #define Z_OPT_TYPE_P(zval_p)		Z_OPT_TYPE(*(zval_p))
482 
483 #define Z_OPT_CONSTANT(zval)		((Z_TYPE_INFO(zval) & (IS_TYPE_CONSTANT << Z_TYPE_FLAGS_SHIFT)) != 0)
484 #define Z_OPT_CONSTANT_P(zval_p)	Z_OPT_CONSTANT(*(zval_p))
485 
486 #define Z_OPT_REFCOUNTED(zval)		((Z_TYPE_INFO(zval) & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0)
487 #define Z_OPT_REFCOUNTED_P(zval_p)	Z_OPT_REFCOUNTED(*(zval_p))
488 
489 #define Z_OPT_COLLECTABLE(zval)		((Z_TYPE_INFO(zval) & (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT)) != 0)
490 #define Z_OPT_COLLECTABLE_P(zval_p)	Z_OPT_COLLECTABLE(*(zval_p))
491 
492 #define Z_OPT_COPYABLE(zval)		((Z_TYPE_INFO(zval) & (IS_TYPE_COPYABLE << Z_TYPE_FLAGS_SHIFT)) != 0)
493 #define Z_OPT_COPYABLE_P(zval_p)	Z_OPT_COPYABLE(*(zval_p))
494 
495 #define Z_OPT_IMMUTABLE(zval)		((Z_TYPE_INFO(zval) & (IS_TYPE_IMMUTABLE << Z_TYPE_FLAGS_SHIFT)) != 0)
496 #define Z_OPT_IMMUTABLE_P(zval_p)	Z_OPT_IMMUTABLE(*(zval_p))
497 
498 #define Z_OPT_ISREF(zval)			(Z_OPT_TYPE(zval) == IS_REFERENCE)
499 #define Z_OPT_ISREF_P(zval_p)		Z_OPT_ISREF(*(zval_p))
500 
501 #define Z_ISREF(zval)				(Z_TYPE(zval) == IS_REFERENCE)
502 #define Z_ISREF_P(zval_p)			Z_ISREF(*(zval_p))
503 
504 #define Z_ISUNDEF(zval)				(Z_TYPE(zval) == IS_UNDEF)
505 #define Z_ISUNDEF_P(zval_p)			Z_ISUNDEF(*(zval_p))
506 
507 #define Z_ISNULL(zval)				(Z_TYPE(zval) == IS_NULL)
508 #define Z_ISNULL_P(zval_p)			Z_ISNULL(*(zval_p))
509 
510 #define Z_ISERROR(zval)				(Z_TYPE(zval) == _IS_ERROR)
511 #define Z_ISERROR_P(zval_p)			Z_ISERROR(*(zval_p))
512 
513 #define Z_LVAL(zval)				(zval).value.lval
514 #define Z_LVAL_P(zval_p)			Z_LVAL(*(zval_p))
515 
516 #define Z_DVAL(zval)				(zval).value.dval
517 #define Z_DVAL_P(zval_p)			Z_DVAL(*(zval_p))
518 
519 #define Z_STR(zval)					(zval).value.str
520 #define Z_STR_P(zval_p)				Z_STR(*(zval_p))
521 
522 #define Z_STRVAL(zval)				ZSTR_VAL(Z_STR(zval))
523 #define Z_STRVAL_P(zval_p)			Z_STRVAL(*(zval_p))
524 
525 #define Z_STRLEN(zval)				ZSTR_LEN(Z_STR(zval))
526 #define Z_STRLEN_P(zval_p)			Z_STRLEN(*(zval_p))
527 
528 #define Z_STRHASH(zval)				ZSTR_HASH(Z_STR(zval))
529 #define Z_STRHASH_P(zval_p)			Z_STRHASH(*(zval_p))
530 
531 #define Z_ARR(zval)					(zval).value.arr
532 #define Z_ARR_P(zval_p)				Z_ARR(*(zval_p))
533 
534 #define Z_ARRVAL(zval)				Z_ARR(zval)
535 #define Z_ARRVAL_P(zval_p)			Z_ARRVAL(*(zval_p))
536 
537 #define Z_OBJ(zval)					(zval).value.obj
538 #define Z_OBJ_P(zval_p)				Z_OBJ(*(zval_p))
539 
540 #define Z_OBJ_HT(zval)				Z_OBJ(zval)->handlers
541 #define Z_OBJ_HT_P(zval_p)			Z_OBJ_HT(*(zval_p))
542 
543 #define Z_OBJ_HANDLER(zval, hf)		Z_OBJ_HT((zval))->hf
544 #define Z_OBJ_HANDLER_P(zv_p, hf)	Z_OBJ_HANDLER(*(zv_p), hf)
545 
546 #define Z_OBJ_HANDLE(zval)          (Z_OBJ((zval)))->handle
547 #define Z_OBJ_HANDLE_P(zval_p)      Z_OBJ_HANDLE(*(zval_p))
548 
549 #define Z_OBJCE(zval)				(Z_OBJ(zval)->ce)
550 #define Z_OBJCE_P(zval_p)			Z_OBJCE(*(zval_p))
551 
552 #define Z_OBJPROP(zval)				Z_OBJ_HT((zval))->get_properties(&(zval))
553 #define Z_OBJPROP_P(zval_p)			Z_OBJPROP(*(zval_p))
554 
555 #define Z_OBJDEBUG(zval,tmp)		(Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&tmp):(tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL))
556 #define Z_OBJDEBUG_P(zval_p,tmp)	Z_OBJDEBUG(*(zval_p), tmp)
557 
558 #define Z_RES(zval)					(zval).value.res
559 #define Z_RES_P(zval_p)				Z_RES(*zval_p)
560 
561 #define Z_RES_HANDLE(zval)			Z_RES(zval)->handle
562 #define Z_RES_HANDLE_P(zval_p)		Z_RES_HANDLE(*zval_p)
563 
564 #define Z_RES_TYPE(zval)			Z_RES(zval)->type
565 #define Z_RES_TYPE_P(zval_p)		Z_RES_TYPE(*zval_p)
566 
567 #define Z_RES_VAL(zval)				Z_RES(zval)->ptr
568 #define Z_RES_VAL_P(zval_p)			Z_RES_VAL(*zval_p)
569 
570 #define Z_REF(zval)					(zval).value.ref
571 #define Z_REF_P(zval_p)				Z_REF(*(zval_p))
572 
573 #define Z_REFVAL(zval)				&Z_REF(zval)->val
574 #define Z_REFVAL_P(zval_p)			Z_REFVAL(*(zval_p))
575 
576 #define Z_AST(zval)					(zval).value.ast
577 #define Z_AST_P(zval_p)				Z_AST(*(zval_p))
578 
579 #define Z_ASTVAL(zval)				(zval).value.ast->ast
580 #define Z_ASTVAL_P(zval_p)			Z_ASTVAL(*(zval_p))
581 
582 #define Z_INDIRECT(zval)			(zval).value.zv
583 #define Z_INDIRECT_P(zval_p)		Z_INDIRECT(*(zval_p))
584 
585 #define Z_CE(zval)					(zval).value.ce
586 #define Z_CE_P(zval_p)				Z_CE(*(zval_p))
587 
588 #define Z_FUNC(zval)				(zval).value.func
589 #define Z_FUNC_P(zval_p)			Z_FUNC(*(zval_p))
590 
591 #define Z_PTR(zval)					(zval).value.ptr
592 #define Z_PTR_P(zval_p)				Z_PTR(*(zval_p))
593 
594 #define ZVAL_UNDEF(z) do {				\
595 		Z_TYPE_INFO_P(z) = IS_UNDEF;	\
596 	} while (0)
597 
598 #define ZVAL_NULL(z) do {				\
599 		Z_TYPE_INFO_P(z) = IS_NULL;		\
600 	} while (0)
601 
602 #define ZVAL_FALSE(z) do {				\
603 		Z_TYPE_INFO_P(z) = IS_FALSE;	\
604 	} while (0)
605 
606 #define ZVAL_TRUE(z) do {				\
607 		Z_TYPE_INFO_P(z) = IS_TRUE;		\
608 	} while (0)
609 
610 #define ZVAL_BOOL(z, b) do {			\
611 		Z_TYPE_INFO_P(z) =				\
612 			(b) ? IS_TRUE : IS_FALSE;	\
613 	} while (0)
614 
615 #define ZVAL_LONG(z, l) {				\
616 		zval *__z = (z);				\
617 		Z_LVAL_P(__z) = l;				\
618 		Z_TYPE_INFO_P(__z) = IS_LONG;	\
619 	}
620 
621 #define ZVAL_DOUBLE(z, d) {				\
622 		zval *__z = (z);				\
623 		Z_DVAL_P(__z) = d;				\
624 		Z_TYPE_INFO_P(__z) = IS_DOUBLE;	\
625 	}
626 
627 #define ZVAL_STR(z, s) do {						\
628 		zval *__z = (z);						\
629 		zend_string *__s = (s);					\
630 		Z_STR_P(__z) = __s;						\
631 		/* interned strings support */			\
632 		Z_TYPE_INFO_P(__z) = ZSTR_IS_INTERNED(__s) ? \
633 			IS_INTERNED_STRING_EX : 			\
634 			IS_STRING_EX;						\
635 	} while (0)
636 
637 #define ZVAL_INTERNED_STR(z, s) do {				\
638 		zval *__z = (z);							\
639 		zend_string *__s = (s);						\
640 		Z_STR_P(__z) = __s;							\
641 		Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX;	\
642 	} while (0)
643 
644 #define ZVAL_NEW_STR(z, s) do {					\
645 		zval *__z = (z);						\
646 		zend_string *__s = (s);					\
647 		Z_STR_P(__z) = __s;						\
648 		Z_TYPE_INFO_P(__z) = IS_STRING_EX;		\
649 	} while (0)
650 
651 #define ZVAL_STR_COPY(z, s) do {						\
652 		zval *__z = (z);								\
653 		zend_string *__s = (s);							\
654 		Z_STR_P(__z) = __s;								\
655 		/* interned strings support */					\
656 		if (ZSTR_IS_INTERNED(__s)) {							\
657 			Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX;	\
658 		} else {										\
659 			GC_REFCOUNT(__s)++;							\
660 			Z_TYPE_INFO_P(__z) = IS_STRING_EX;			\
661 		}												\
662 	} while (0)
663 
664 #define ZVAL_ARR(z, a) do {						\
665 		zval *__z = (z);						\
666 		Z_ARR_P(__z) = (a);						\
667 		Z_TYPE_INFO_P(__z) = IS_ARRAY_EX;		\
668 	} while (0)
669 
670 #define ZVAL_NEW_ARR(z) do {									\
671 		zval *__z = (z);										\
672 		zend_array *_arr =										\
673 		(zend_array *) emalloc(sizeof(zend_array));				\
674 		Z_ARR_P(__z) = _arr;									\
675 		Z_TYPE_INFO_P(__z) = IS_ARRAY_EX;						\
676 	} while (0)
677 
678 #define ZVAL_NEW_PERSISTENT_ARR(z) do {							\
679 		zval *__z = (z);										\
680 		zend_array *_arr =										\
681 		(zend_array *) malloc(sizeof(zend_array));				\
682 		Z_ARR_P(__z) = _arr;									\
683 		Z_TYPE_INFO_P(__z) = IS_ARRAY_EX;						\
684 	} while (0)
685 
686 #define ZVAL_OBJ(z, o) do {						\
687 		zval *__z = (z);						\
688 		Z_OBJ_P(__z) = (o);						\
689 		Z_TYPE_INFO_P(__z) = IS_OBJECT_EX;		\
690 	} while (0)
691 
692 #define ZVAL_RES(z, r) do {						\
693 		zval *__z = (z);						\
694 		Z_RES_P(__z) = (r);						\
695 		Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX;	\
696 	} while (0)
697 
698 #define ZVAL_NEW_RES(z, h, p, t) do {							\
699 		zend_resource *_res =									\
700 		(zend_resource *) emalloc(sizeof(zend_resource));		\
701 		zval *__z;												\
702 		GC_REFCOUNT(_res) = 1;									\
703 		GC_TYPE_INFO(_res) = IS_RESOURCE;						\
704 		_res->handle = (h);										\
705 		_res->type = (t);										\
706 		_res->ptr = (p);										\
707 		__z = (z);												\
708 		Z_RES_P(__z) = _res;									\
709 		Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX;					\
710 	} while (0)
711 
712 #define ZVAL_NEW_PERSISTENT_RES(z, h, p, t) do {				\
713 		zend_resource *_res =									\
714 		(zend_resource *) malloc(sizeof(zend_resource));		\
715 		zval *__z;												\
716 		GC_REFCOUNT(_res) = 1;									\
717 		GC_TYPE_INFO(_res) = IS_RESOURCE;						\
718 		_res->handle = (h);										\
719 		_res->type = (t);										\
720 		_res->ptr = (p);										\
721 		__z = (z);												\
722 		Z_RES_P(__z) = _res;									\
723 		Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX;					\
724 	} while (0)
725 
726 #define ZVAL_REF(z, r) do {										\
727 		zval *__z = (z);										\
728 		Z_REF_P(__z) = (r);										\
729 		Z_TYPE_INFO_P(__z) = IS_REFERENCE_EX;					\
730 	} while (0)
731 
732 #define ZVAL_NEW_EMPTY_REF(z) do {								\
733 		zend_reference *_ref =									\
734 		(zend_reference *) emalloc(sizeof(zend_reference));		\
735 		GC_REFCOUNT(_ref) = 1;									\
736 		GC_TYPE_INFO(_ref) = IS_REFERENCE;						\
737 		Z_REF_P(z) = _ref;										\
738 		Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;						\
739 	} while (0)
740 
741 #define ZVAL_NEW_REF(z, r) do {									\
742 		zend_reference *_ref =									\
743 		(zend_reference *) emalloc(sizeof(zend_reference));		\
744 		GC_REFCOUNT(_ref) = 1;									\
745 		GC_TYPE_INFO(_ref) = IS_REFERENCE;						\
746 		ZVAL_COPY_VALUE(&_ref->val, r);							\
747 		Z_REF_P(z) = _ref;										\
748 		Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;						\
749 	} while (0)
750 
751 #define ZVAL_NEW_PERSISTENT_REF(z, r) do {						\
752 		zend_reference *_ref =									\
753 		(zend_reference *) malloc(sizeof(zend_reference));		\
754 		GC_REFCOUNT(_ref) = 1;									\
755 		GC_TYPE_INFO(_ref) = IS_REFERENCE;						\
756 		ZVAL_COPY_VALUE(&_ref->val, r);							\
757 		Z_REF_P(z) = _ref;										\
758 		Z_TYPE_INFO_P(z) = IS_REFERENCE_EX;						\
759 	} while (0)
760 
761 #define ZVAL_NEW_AST(z, a) do {									\
762 		zval *__z = (z);										\
763 		zend_ast_ref *_ast =									\
764 		(zend_ast_ref *) emalloc(sizeof(zend_ast_ref));			\
765 		GC_REFCOUNT(_ast) = 1;									\
766 		GC_TYPE_INFO(_ast) = IS_CONSTANT_AST;					\
767 		_ast->ast = (a);										\
768 		Z_AST_P(__z) = _ast;									\
769 		Z_TYPE_INFO_P(__z) = IS_CONSTANT_AST_EX;				\
770 	} while (0)
771 
772 #define ZVAL_INDIRECT(z, v) do {								\
773 		Z_INDIRECT_P(z) = (v);									\
774 		Z_TYPE_INFO_P(z) = IS_INDIRECT;							\
775 	} while (0)
776 
777 #define ZVAL_PTR(z, p) do {										\
778 		Z_PTR_P(z) = (p);										\
779 		Z_TYPE_INFO_P(z) = IS_PTR;								\
780 	} while (0)
781 
782 #define ZVAL_FUNC(z, f) do {									\
783 		Z_FUNC_P(z) = (f);										\
784 		Z_TYPE_INFO_P(z) = IS_PTR;								\
785 	} while (0)
786 
787 #define ZVAL_CE(z, c) do {										\
788 		Z_CE_P(z) = (c);										\
789 		Z_TYPE_INFO_P(z) = IS_PTR;								\
790 	} while (0)
791 
792 #define ZVAL_ERROR(z) do {				\
793 		Z_TYPE_INFO_P(z) = _IS_ERROR;	\
794 	} while (0)
795 
796 #define Z_REFCOUNT_P(pz)			zval_refcount_p(pz)
797 #define Z_SET_REFCOUNT_P(pz, rc)	zval_set_refcount_p(pz, rc)
798 #define Z_ADDREF_P(pz)				zval_addref_p(pz)
799 #define Z_DELREF_P(pz)				zval_delref_p(pz)
800 
801 #define Z_REFCOUNT(z)				Z_REFCOUNT_P(&(z))
802 #define Z_SET_REFCOUNT(z, rc)		Z_SET_REFCOUNT_P(&(z), rc)
803 #define Z_ADDREF(z)					Z_ADDREF_P(&(z))
804 #define Z_DELREF(z)					Z_DELREF_P(&(z))
805 
806 #define Z_TRY_ADDREF_P(pz) do {		\
807 	if (Z_REFCOUNTED_P((pz))) {		\
808 		Z_ADDREF_P((pz));			\
809 	}								\
810 } while (0)
811 
812 #define Z_TRY_DELREF_P(pz) do {		\
813 	if (Z_REFCOUNTED_P((pz))) {		\
814 		Z_DELREF_P((pz));			\
815 	}								\
816 } while (0)
817 
818 #define Z_TRY_ADDREF(z)				Z_TRY_ADDREF_P(&(z))
819 #define Z_TRY_DELREF(z)				Z_TRY_DELREF_P(&(z))
820 
zval_refcount_p(zval * pz)821 static zend_always_inline uint32_t zval_refcount_p(zval* pz) {
822 	ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz));
823 	return GC_REFCOUNT(Z_COUNTED_P(pz));
824 }
825 
zval_set_refcount_p(zval * pz,uint32_t rc)826 static zend_always_inline uint32_t zval_set_refcount_p(zval* pz, uint32_t rc) {
827 	ZEND_ASSERT(Z_REFCOUNTED_P(pz));
828 	return GC_REFCOUNT(Z_COUNTED_P(pz)) = rc;
829 }
830 
zval_addref_p(zval * pz)831 static zend_always_inline uint32_t zval_addref_p(zval* pz) {
832 	ZEND_ASSERT(Z_REFCOUNTED_P(pz));
833 	return ++GC_REFCOUNT(Z_COUNTED_P(pz));
834 }
835 
zval_delref_p(zval * pz)836 static zend_always_inline uint32_t zval_delref_p(zval* pz) {
837 	ZEND_ASSERT(Z_REFCOUNTED_P(pz));
838 	return --GC_REFCOUNT(Z_COUNTED_P(pz));
839 }
840 
841 #if SIZEOF_SIZE_T == 4
842 # define ZVAL_COPY_VALUE_EX(z, v, gc, t)				\
843 	do {												\
844 		uint32_t _w2 = v->value.ww.w2;					\
845 		Z_COUNTED_P(z) = gc;							\
846 		z->value.ww.w2 = _w2;							\
847 		Z_TYPE_INFO_P(z) = t;							\
848 	} while (0)
849 #elif SIZEOF_SIZE_T == 8
850 # define ZVAL_COPY_VALUE_EX(z, v, gc, t)				\
851 	do {												\
852 		Z_COUNTED_P(z) = gc;							\
853 		Z_TYPE_INFO_P(z) = t;							\
854 	} while (0)
855 #else
856 # error "Unknown SIZEOF_SIZE_T"
857 #endif
858 
859 #define ZVAL_COPY_VALUE(z, v)							\
860 	do {												\
861 		zval *_z1 = (z);								\
862 		const zval *_z2 = (v);							\
863 		zend_refcounted *_gc = Z_COUNTED_P(_z2);		\
864 		uint32_t _t = Z_TYPE_INFO_P(_z2);				\
865 		ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t);			\
866 	} while (0)
867 
868 #define ZVAL_COPY(z, v)									\
869 	do {												\
870 		zval *_z1 = (z);								\
871 		const zval *_z2 = (v);							\
872 		zend_refcounted *_gc = Z_COUNTED_P(_z2);		\
873 		uint32_t _t = Z_TYPE_INFO_P(_z2);				\
874 		ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t);			\
875 		if ((_t & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) { \
876 			GC_REFCOUNT(_gc)++;							\
877 		}												\
878 	} while (0)
879 
880 #define ZVAL_DUP(z, v)									\
881 	do {												\
882 		zval *_z1 = (z);								\
883 		const zval *_z2 = (v);							\
884 		zend_refcounted *_gc = Z_COUNTED_P(_z2);		\
885 		uint32_t _t = Z_TYPE_INFO_P(_z2);				\
886 		ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t);			\
887 		if ((_t & ((IS_TYPE_REFCOUNTED|IS_TYPE_IMMUTABLE) << Z_TYPE_FLAGS_SHIFT)) != 0) { \
888 			if ((_t & ((IS_TYPE_COPYABLE|IS_TYPE_IMMUTABLE) << Z_TYPE_FLAGS_SHIFT)) != 0) { \
889 				_zval_copy_ctor_func(_z1 ZEND_FILE_LINE_CC); \
890 			} else {									\
891 				GC_REFCOUNT(_gc)++;						\
892 			}											\
893 		}												\
894 	} while (0)
895 
896 #define ZVAL_DEREF(z) do {								\
897 		if (UNEXPECTED(Z_ISREF_P(z))) {					\
898 			(z) = Z_REFVAL_P(z);						\
899 		}												\
900 	} while (0)
901 
902 #define ZVAL_OPT_DEREF(z) do {							\
903 		if (UNEXPECTED(Z_OPT_ISREF_P(z))) {				\
904 			(z) = Z_REFVAL_P(z);						\
905 		}												\
906 	} while (0)
907 
908 #define ZVAL_MAKE_REF(zv) do {							\
909 		zval *__zv = (zv);								\
910 		if (!Z_ISREF_P(__zv)) {							\
911 			ZVAL_NEW_REF(__zv, __zv);					\
912 		}												\
913 	} while (0)
914 
915 #define ZVAL_UNREF(z) do {								\
916 		zval *_z = (z);									\
917 		zend_reference *ref;							\
918 		ZEND_ASSERT(Z_ISREF_P(_z));						\
919 		ref = Z_REF_P(_z);								\
920 		ZVAL_COPY_VALUE(_z, &ref->val);					\
921 		efree_size(ref, sizeof(zend_reference));		\
922 	} while (0)
923 
924 #define ZVAL_COPY_UNREF(z, v) do {						\
925 		zval *_z3 = (v);								\
926 		if (Z_REFCOUNTED_P(_z3)) {						\
927 			if (UNEXPECTED(Z_ISREF_P(_z3))				\
928 			 && UNEXPECTED(Z_REFCOUNT_P(_z3) == 1)) {	\
929 				ZVAL_UNREF(_z3);						\
930 				if (Z_REFCOUNTED_P(_z3)) {				\
931 					Z_ADDREF_P(_z3);					\
932 				}										\
933 			} else {									\
934 				Z_ADDREF_P(_z3);						\
935 			}											\
936 		}												\
937 		ZVAL_COPY_VALUE(z, _z3);						\
938 	} while (0)
939 
940 
941 #define SEPARATE_STRING(zv) do {						\
942 		zval *_zv = (zv);								\
943 		if (Z_REFCOUNT_P(_zv) > 1) {					\
944 			if (Z_REFCOUNTED_P(_zv)) {					\
945 				Z_DELREF_P(_zv);						\
946 			}											\
947 			zval_copy_ctor_func(_zv);					\
948 		}												\
949 	} while (0)
950 
951 #define SEPARATE_ARRAY(zv) do {							\
952 		zval *_zv = (zv);								\
953 		zend_array *_arr = Z_ARR_P(_zv);				\
954 		if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) {		\
955 			if (!Z_IMMUTABLE_P(_zv)) {					\
956 				GC_REFCOUNT(_arr)--;					\
957 			}											\
958 			ZVAL_ARR(_zv, zend_array_dup(_arr));		\
959 		}												\
960 	} while (0)
961 
962 #define SEPARATE_ZVAL_NOREF(zv) do {					\
963 		zval *_zv = (zv);								\
964 		ZEND_ASSERT(Z_TYPE_P(_zv) != IS_REFERENCE);		\
965 		if (Z_COPYABLE_P(_zv) ||						\
966 		    Z_IMMUTABLE_P(_zv)) {						\
967 			if (Z_REFCOUNT_P(_zv) > 1) {				\
968 				if (!Z_IMMUTABLE_P(_zv)) {				\
969 					Z_DELREF_P(_zv);					\
970 				}										\
971 				zval_copy_ctor_func(_zv);				\
972 			}											\
973 		}												\
974 	} while (0)
975 
976 #define SEPARATE_ZVAL(zv) do {							\
977 		zval *_zv = (zv);								\
978 		if (Z_REFCOUNTED_P(_zv) ||						\
979 		    Z_IMMUTABLE_P(_zv)) {						\
980 			if (Z_REFCOUNT_P(_zv) > 1) {				\
981 				if (Z_COPYABLE_P(_zv) ||				\
982 				    Z_IMMUTABLE_P(_zv)) {				\
983 					if (!Z_IMMUTABLE_P(_zv)) {			\
984 						Z_DELREF_P(_zv);				\
985 					}									\
986 					zval_copy_ctor_func(_zv);			\
987 				} else if (Z_ISREF_P(_zv)) {			\
988 					Z_DELREF_P(_zv);					\
989 					ZVAL_DUP(_zv, Z_REFVAL_P(_zv));		\
990 				}										\
991 			}											\
992 		}												\
993 	} while (0)
994 
995 #define SEPARATE_ZVAL_IF_NOT_REF(zv) do {				\
996 		zval *_zv = (zv);								\
997 		if (Z_COPYABLE_P(_zv) ||                    	\
998 		    Z_IMMUTABLE_P(_zv)) {						\
999 			if (Z_REFCOUNT_P(_zv) > 1) {				\
1000 				if (!Z_IMMUTABLE_P(_zv)) {				\
1001 					Z_DELREF_P(_zv);					\
1002 				}										\
1003 				zval_copy_ctor_func(_zv);				\
1004 			}											\
1005 		}												\
1006 	} while (0)
1007 
1008 #define SEPARATE_ARG_IF_REF(varptr) do { 				\
1009 		ZVAL_DEREF(varptr);								\
1010 		if (Z_REFCOUNTED_P(varptr)) { 					\
1011 			Z_ADDREF_P(varptr); 						\
1012 		}												\
1013 	} while (0)
1014 
1015 #endif /* ZEND_TYPES_H */
1016 
1017 /*
1018  * Local variables:
1019  * tab-width: 4
1020  * c-basic-offset: 4
1021  * indent-tabs-mode: t
1022  * End:
1023  */
1024