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