1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Dmitry Stogov <dmitry@php.net> |
18 | Xinchen Hui <xinchen.h@zend.com> |
19 +----------------------------------------------------------------------+
20 */
21
22 #ifndef ZEND_TYPES_H
23 #define ZEND_TYPES_H
24
25 #include "zend_portability.h"
26 #include "zend_long.h"
27
28 #ifdef __SSE2__
29 # include <mmintrin.h>
30 # include <emmintrin.h>
31 #endif
32
33 #ifdef WORDS_BIGENDIAN
34 # define ZEND_ENDIAN_LOHI(lo, hi) hi; lo;
35 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi) hi; mi; lo;
36 # define ZEND_ENDIAN_LOHI_4(a, b, c, d) d; c; b; a;
37 # define ZEND_ENDIAN_LOHI_C(lo, hi) hi, lo
38 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi) hi, mi, lo,
39 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d) d, c, b, a
40 #else
41 # define ZEND_ENDIAN_LOHI(lo, hi) lo; hi;
42 # define ZEND_ENDIAN_LOHI_3(lo, mi, hi) lo; mi; hi;
43 # define ZEND_ENDIAN_LOHI_4(a, b, c, d) a; b; c; d;
44 # define ZEND_ENDIAN_LOHI_C(lo, hi) lo, hi
45 # define ZEND_ENDIAN_LOHI_C_3(lo, mi, hi) lo, mi, hi,
46 # define ZEND_ENDIAN_LOHI_C_4(a, b, c, d) a, b, c, d
47 #endif
48
49 typedef unsigned char zend_bool;
50 typedef unsigned char zend_uchar;
51
52 typedef enum {
53 SUCCESS = 0,
54 FAILURE = -1, /* this MUST stay a negative number, or it may affect functions! */
55 } ZEND_RESULT_CODE;
56
57 #ifdef ZEND_ENABLE_ZVAL_LONG64
58 # ifdef ZEND_WIN32
59 # define ZEND_SIZE_MAX _UI64_MAX
60 # else
61 # define ZEND_SIZE_MAX SIZE_MAX
62 # endif
63 #else
64 # if defined(ZEND_WIN32)
65 # define ZEND_SIZE_MAX _UI32_MAX
66 # else
67 # define ZEND_SIZE_MAX SIZE_MAX
68 # endif
69 #endif
70
71 typedef intptr_t zend_intptr_t;
72 typedef uintptr_t zend_uintptr_t;
73
74 #ifdef ZTS
75 #define ZEND_TLS static TSRM_TLS
76 #define ZEND_EXT_TLS TSRM_TLS
77 #else
78 #define ZEND_TLS static
79 #define ZEND_EXT_TLS
80 #endif
81
82 typedef struct _zend_object_handlers zend_object_handlers;
83 typedef struct _zend_class_entry zend_class_entry;
84 typedef union _zend_function zend_function;
85 typedef struct _zend_execute_data zend_execute_data;
86
87 typedef struct _zval_struct zval;
88
89 typedef struct _zend_refcounted zend_refcounted;
90 typedef struct _zend_string zend_string;
91 typedef struct _zend_array zend_array;
92 typedef struct _zend_object zend_object;
93 typedef struct _zend_resource zend_resource;
94 typedef struct _zend_reference zend_reference;
95 typedef struct _zend_ast_ref zend_ast_ref;
96 typedef struct _zend_ast zend_ast;
97
98 typedef int (*compare_func_t)(const void *, const void *);
99 typedef void (*swap_func_t)(void *, void *);
100 typedef void (*sort_func_t)(void *, size_t, size_t, compare_func_t, swap_func_t);
101 typedef void (*dtor_func_t)(zval *pDest);
102 typedef void (*copy_ctor_func_t)(zval *pElement);
103
104 /*
105 * zend_type - is an abstraction layer to represent information about type hint.
106 * It shouldn't be used directly. Only through ZEND_TYPE_* macros.
107 *
108 * ZEND_TYPE_IS_SET() - checks if type-hint exists
109 * ZEND_TYPE_IS_CODE() - checks if type-hint refer to standard type
110 * ZEND_TYPE_IS_CLASS() - checks if type-hint refer to some class
111 * ZEND_TYPE_IS_CE() - checks if type-hint refer to some class by zend_class_entry *
112 * ZEND_TYPE_IS_NAME() - checks if type-hint refer to some class by zend_string *
113 *
114 * ZEND_TYPE_NAME() - returns referenced class name
115 * ZEND_TYPE_CE() - returns referenced class entry
116 * ZEND_TYPE_CODE() - returns standard type code (e.g. IS_LONG, _IS_BOOL)
117 *
118 * ZEND_TYPE_ALLOW_NULL() - checks if NULL is allowed
119 *
120 * ZEND_TYPE_ENCODE() and ZEND_TYPE_ENCODE_CLASS() should be used for
121 * construction.
122 */
123
124 typedef uintptr_t zend_type;
125
126 #define ZEND_TYPE_IS_SET(t) \
127 ((t) > Z_L(0x3))
128
129 #define ZEND_TYPE_IS_CODE(t) \
130 (((t) > Z_L(0x3)) && ((t) <= Z_L(0x3ff)))
131
132 #define ZEND_TYPE_IS_CLASS(t) \
133 ((t) > Z_L(0x3ff))
134
135 #define ZEND_TYPE_IS_CE(t) \
136 (((t) & Z_L(0x2)) != 0)
137
138 #define ZEND_TYPE_IS_NAME(t) \
139 (ZEND_TYPE_IS_CLASS(t) && !ZEND_TYPE_IS_CE(t))
140
141 #define ZEND_TYPE_NAME(t) \
142 ((zend_string*)((t) & ~Z_L(0x3)))
143
144 #define ZEND_TYPE_CE(t) \
145 ((zend_class_entry*)((t) & ~Z_L(0x3)))
146
147 #define ZEND_TYPE_CODE(t) \
148 ((t) >> Z_L(2))
149
150 #define ZEND_TYPE_ALLOW_NULL(t) \
151 (((t) & Z_L(0x1)) != 0)
152
153 #define ZEND_TYPE_WITHOUT_NULL(t) \
154 ((t) & ~Z_L(0x1))
155
156 #define ZEND_TYPE_ENCODE(code, allow_null) \
157 (((code) << Z_L(2)) | ((allow_null) ? Z_L(0x1) : Z_L(0x0)))
158
159 #define ZEND_TYPE_ENCODE_CE(ce, allow_null) \
160 (((uintptr_t)(ce)) | ((allow_null) ? Z_L(0x3) : Z_L(0x2)))
161
162 #define ZEND_TYPE_ENCODE_CLASS(class_name, allow_null) \
163 (((uintptr_t)(class_name)) | ((allow_null) ? Z_L(0x1) : Z_L(0x0)))
164
165 #define ZEND_TYPE_ENCODE_CLASS_CONST_0(class_name) \
166 ((zend_type) class_name)
167 #define ZEND_TYPE_ENCODE_CLASS_CONST_1(class_name) \
168 ((zend_type) "?" class_name)
169 #define ZEND_TYPE_ENCODE_CLASS_CONST_Q2(macro, class_name) \
170 macro(class_name)
171 #define ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) \
172 ZEND_TYPE_ENCODE_CLASS_CONST_Q2(ZEND_TYPE_ENCODE_CLASS_CONST_ ##allow_null, class_name)
173 #define ZEND_TYPE_ENCODE_CLASS_CONST(class_name, allow_null) \
174 ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name)
175
176 typedef union _zend_value {
177 zend_long lval; /* long value */
178 double dval; /* double value */
179 zend_refcounted *counted;
180 zend_string *str;
181 zend_array *arr;
182 zend_object *obj;
183 zend_resource *res;
184 zend_reference *ref;
185 zend_ast_ref *ast;
186 zval *zv;
187 void *ptr;
188 zend_class_entry *ce;
189 zend_function *func;
190 struct {
191 uint32_t w1;
192 uint32_t w2;
193 } ww;
194 } zend_value;
195
196 struct _zval_struct {
197 zend_value value; /* value */
198 union {
199 struct {
200 ZEND_ENDIAN_LOHI_3(
201 zend_uchar type, /* active type */
202 zend_uchar type_flags,
203 union {
204 uint16_t extra; /* not further specified */
205 } u)
206 } v;
207 uint32_t type_info;
208 } u1;
209 union {
210 uint32_t next; /* hash collision chain */
211 uint32_t cache_slot; /* cache slot (for RECV_INIT) */
212 uint32_t opline_num; /* opline number (for FAST_CALL) */
213 uint32_t lineno; /* line number (for ast nodes) */
214 uint32_t num_args; /* arguments number for EX(This) */
215 uint32_t fe_pos; /* foreach position */
216 uint32_t fe_iter_idx; /* foreach iterator index */
217 uint32_t access_flags; /* class constant access flags */
218 uint32_t property_guard; /* single property guard */
219 uint32_t constant_flags; /* constant flags */
220 uint32_t extra; /* not further specified */
221 } u2;
222 };
223
224 typedef struct _zend_refcounted_h {
225 uint32_t refcount; /* reference counter 32-bit */
226 union {
227 uint32_t type_info;
228 } u;
229 } zend_refcounted_h;
230
231 struct _zend_refcounted {
232 zend_refcounted_h gc;
233 };
234
235 struct _zend_string {
236 zend_refcounted_h gc;
237 zend_ulong h; /* hash value */
238 size_t len;
239 char val[1];
240 };
241
242 typedef struct _Bucket {
243 zval val;
244 zend_ulong h; /* hash value (or numeric index) */
245 zend_string *key; /* string key or NULL for numerics */
246 } Bucket;
247
248 typedef struct _zend_array HashTable;
249
250 struct _zend_array {
251 zend_refcounted_h gc;
252 union {
253 struct {
254 ZEND_ENDIAN_LOHI_4(
255 zend_uchar flags,
256 zend_uchar _unused,
257 zend_uchar nIteratorsCount,
258 zend_uchar _unused2)
259 } v;
260 uint32_t flags;
261 } u;
262 uint32_t nTableMask;
263 Bucket *arData;
264 uint32_t nNumUsed;
265 uint32_t nNumOfElements;
266 uint32_t nTableSize;
267 uint32_t nInternalPointer;
268 zend_long nNextFreeElement;
269 dtor_func_t pDestructor;
270 };
271
272 /*
273 * HashTable Data Layout
274 * =====================
275 *
276 * +=============================+
277 * | HT_HASH(ht, ht->nTableMask) |
278 * | ... |
279 * | HT_HASH(ht, -1) |
280 * +-----------------------------+
281 * ht->arData ---> | Bucket[0] |
282 * | ... |
283 * | Bucket[ht->nTableSize-1] |
284 * +=============================+
285 */
286
287 #define HT_INVALID_IDX ((uint32_t) -1)
288
289 #define HT_MIN_MASK ((uint32_t) -2)
290 #define HT_MIN_SIZE 8
291
292 #if SIZEOF_SIZE_T == 4
293 # define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
294 # define HT_HASH_TO_BUCKET_EX(data, idx) \
295 ((Bucket*)((char*)(data) + (idx)))
296 # define HT_IDX_TO_HASH(idx) \
297 ((idx) * sizeof(Bucket))
298 # define HT_HASH_TO_IDX(idx) \
299 ((idx) / sizeof(Bucket))
300 #elif SIZEOF_SIZE_T == 8
301 # define HT_MAX_SIZE 0x80000000
302 # define HT_HASH_TO_BUCKET_EX(data, idx) \
303 ((data) + (idx))
304 # define HT_IDX_TO_HASH(idx) \
305 (idx)
306 # define HT_HASH_TO_IDX(idx) \
307 (idx)
308 #else
309 # error "Unknown SIZEOF_SIZE_T"
310 #endif
311
312 #define HT_HASH_EX(data, idx) \
313 ((uint32_t*)(data))[(int32_t)(idx)]
314 #define HT_HASH(ht, idx) \
315 HT_HASH_EX((ht)->arData, idx)
316
317 #define HT_SIZE_TO_MASK(nTableSize) \
318 ((uint32_t)(-((nTableSize) + (nTableSize))))
319 #define HT_HASH_SIZE(nTableMask) \
320 (((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t))
321 #define HT_DATA_SIZE(nTableSize) \
322 ((size_t)(nTableSize) * sizeof(Bucket))
323 #define HT_SIZE_EX(nTableSize, nTableMask) \
324 (HT_DATA_SIZE((nTableSize)) + HT_HASH_SIZE((nTableMask)))
325 #define HT_SIZE(ht) \
326 HT_SIZE_EX((ht)->nTableSize, (ht)->nTableMask)
327 #define HT_USED_SIZE(ht) \
328 (HT_HASH_SIZE((ht)->nTableMask) + ((size_t)(ht)->nNumUsed * sizeof(Bucket)))
329 #ifdef __SSE2__
330 # define HT_HASH_RESET(ht) do { \
331 char *p = (char*)&HT_HASH(ht, (ht)->nTableMask); \
332 size_t size = HT_HASH_SIZE((ht)->nTableMask); \
333 __m128i xmm0 = _mm_setzero_si128(); \
334 xmm0 = _mm_cmpeq_epi8(xmm0, xmm0); \
335 ZEND_ASSERT(size >= 64 && ((size & 0x3f) == 0)); \
336 do { \
337 _mm_storeu_si128((__m128i*)p, xmm0); \
338 _mm_storeu_si128((__m128i*)(p+16), xmm0); \
339 _mm_storeu_si128((__m128i*)(p+32), xmm0); \
340 _mm_storeu_si128((__m128i*)(p+48), xmm0); \
341 p += 64; \
342 size -= 64; \
343 } while (size != 0); \
344 } while (0)
345 #else
346 # define HT_HASH_RESET(ht) \
347 memset(&HT_HASH(ht, (ht)->nTableMask), HT_INVALID_IDX, HT_HASH_SIZE((ht)->nTableMask))
348 #endif
349 #define HT_HASH_RESET_PACKED(ht) do { \
350 HT_HASH(ht, -2) = HT_INVALID_IDX; \
351 HT_HASH(ht, -1) = HT_INVALID_IDX; \
352 } while (0)
353 #define HT_HASH_TO_BUCKET(ht, idx) \
354 HT_HASH_TO_BUCKET_EX((ht)->arData, idx)
355
356 #define HT_SET_DATA_ADDR(ht, ptr) do { \
357 (ht)->arData = (Bucket*)(((char*)(ptr)) + HT_HASH_SIZE((ht)->nTableMask)); \
358 } while (0)
359 #define HT_GET_DATA_ADDR(ht) \
360 ((char*)((ht)->arData) - HT_HASH_SIZE((ht)->nTableMask))
361
362 typedef uint32_t HashPosition;
363
364 typedef struct _HashTableIterator {
365 HashTable *ht;
366 HashPosition pos;
367 } HashTableIterator;
368
369 struct _zend_object {
370 zend_refcounted_h gc;
371 uint32_t handle; // TODO: may be removed ???
372 zend_class_entry *ce;
373 const zend_object_handlers *handlers;
374 HashTable *properties;
375 zval properties_table[1];
376 };
377
378 struct _zend_resource {
379 zend_refcounted_h gc;
380 int handle; // TODO: may be removed ???
381 int type;
382 void *ptr;
383 };
384
385 typedef struct {
386 size_t num;
387 size_t num_allocated;
388 struct _zend_property_info *ptr[1];
389 } zend_property_info_list;
390
391 typedef union {
392 struct _zend_property_info *ptr;
393 uintptr_t list;
394 } zend_property_info_source_list;
395
396 #define ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(list) (0x1 | (uintptr_t) (list))
397 #define ZEND_PROPERTY_INFO_SOURCE_TO_LIST(list) ((zend_property_info_list *) ((list) & ~0x1))
398 #define ZEND_PROPERTY_INFO_SOURCE_IS_LIST(list) ((list) & 0x1)
399
400 struct _zend_reference {
401 zend_refcounted_h gc;
402 zval val;
403 zend_property_info_source_list sources;
404 };
405
406 struct _zend_ast_ref {
407 zend_refcounted_h gc;
408 /*zend_ast ast; zend_ast follows the zend_ast_ref structure */
409 };
410
411 /* regular data types */
412 #define IS_UNDEF 0
413 #define IS_NULL 1
414 #define IS_FALSE 2
415 #define IS_TRUE 3
416 #define IS_LONG 4
417 #define IS_DOUBLE 5
418 #define IS_STRING 6
419 #define IS_ARRAY 7
420 #define IS_OBJECT 8
421 #define IS_RESOURCE 9
422 #define IS_REFERENCE 10
423
424 /* constant expressions */
425 #define IS_CONSTANT_AST 11
426
427 /* internal types */
428 #define IS_INDIRECT 13
429 #define IS_PTR 14
430 #define IS_ALIAS_PTR 15
431 #define _IS_ERROR 15
432
433 /* fake types used only for type hinting (Z_TYPE(zv) can not use them) */
434 #define _IS_BOOL 16
435 #define IS_CALLABLE 17
436 #define IS_ITERABLE 18
437 #define IS_VOID 19
438 #define _IS_NUMBER 20
439
zval_get_type(const zval * pz)440 static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
441 return pz->u1.v.type;
442 }
443
444 #define ZEND_SAME_FAKE_TYPE(faketype, realtype) ( \
445 (faketype) == (realtype) \
446 || ((faketype) == _IS_BOOL && ((realtype) == IS_TRUE || (realtype) == IS_FALSE)) \
447 )
448
449 /* we should never set just Z_TYPE, we should set Z_TYPE_INFO */
450 #define Z_TYPE(zval) zval_get_type(&(zval))
451 #define Z_TYPE_P(zval_p) Z_TYPE(*(zval_p))
452
453 #define Z_TYPE_FLAGS(zval) (zval).u1.v.type_flags
454 #define Z_TYPE_FLAGS_P(zval_p) Z_TYPE_FLAGS(*(zval_p))
455
456 #define Z_TYPE_INFO(zval) (zval).u1.type_info
457 #define Z_TYPE_INFO_P(zval_p) Z_TYPE_INFO(*(zval_p))
458
459 #define Z_NEXT(zval) (zval).u2.next
460 #define Z_NEXT_P(zval_p) Z_NEXT(*(zval_p))
461
462 #define Z_CACHE_SLOT(zval) (zval).u2.cache_slot
463 #define Z_CACHE_SLOT_P(zval_p) Z_CACHE_SLOT(*(zval_p))
464
465 #define Z_LINENO(zval) (zval).u2.lineno
466 #define Z_LINENO_P(zval_p) Z_LINENO(*(zval_p))
467
468 #define Z_OPLINE_NUM(zval) (zval).u2.opline_num
469 #define Z_OPLINE_NUM_P(zval_p) Z_OPLINE_NUM(*(zval_p))
470
471 #define Z_FE_POS(zval) (zval).u2.fe_pos
472 #define Z_FE_POS_P(zval_p) Z_FE_POS(*(zval_p))
473
474 #define Z_FE_ITER(zval) (zval).u2.fe_iter_idx
475 #define Z_FE_ITER_P(zval_p) Z_FE_ITER(*(zval_p))
476
477 #define Z_ACCESS_FLAGS(zval) (zval).u2.access_flags
478 #define Z_ACCESS_FLAGS_P(zval_p) Z_ACCESS_FLAGS(*(zval_p))
479
480 #define Z_PROPERTY_GUARD(zval) (zval).u2.property_guard
481 #define Z_PROPERTY_GUARD_P(zval_p) Z_PROPERTY_GUARD(*(zval_p))
482
483 #define Z_CONSTANT_FLAGS(zval) (zval).u2.constant_flags
484 #define Z_CONSTANT_FLAGS_P(zval_p) Z_CONSTANT_FLAGS(*(zval_p))
485
486 #define Z_EXTRA(zval) (zval).u2.extra
487 #define Z_EXTRA_P(zval_p) Z_EXTRA(*(zval_p))
488
489 #define Z_COUNTED(zval) (zval).value.counted
490 #define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p))
491
492 #define Z_TYPE_MASK 0xff
493 #define Z_TYPE_FLAGS_MASK 0xff00
494
495 #define Z_TYPE_FLAGS_SHIFT 8
496
497 #define GC_REFCOUNT(p) zend_gc_refcount(&(p)->gc)
498 #define GC_SET_REFCOUNT(p, rc) zend_gc_set_refcount(&(p)->gc, rc)
499 #define GC_ADDREF(p) zend_gc_addref(&(p)->gc)
500 #define GC_DELREF(p) zend_gc_delref(&(p)->gc)
501 #define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc)
502 #define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc)
503
504 #define GC_TYPE_MASK 0x0000000f
505 #define GC_FLAGS_MASK 0x000003f0
506 #define GC_INFO_MASK 0xfffffc00
507 #define GC_FLAGS_SHIFT 0
508 #define GC_INFO_SHIFT 10
509
zval_gc_type(uint32_t gc_type_info)510 static zend_always_inline zend_uchar zval_gc_type(uint32_t gc_type_info) {
511 return (gc_type_info & GC_TYPE_MASK);
512 }
513
zval_gc_flags(uint32_t gc_type_info)514 static zend_always_inline uint32_t zval_gc_flags(uint32_t gc_type_info) {
515 return (gc_type_info >> GC_FLAGS_SHIFT) & (GC_FLAGS_MASK >> GC_FLAGS_SHIFT);
516 }
517
zval_gc_info(uint32_t gc_type_info)518 static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
519 return (gc_type_info >> GC_INFO_SHIFT);
520 }
521
522 #define GC_TYPE_INFO(p) (p)->gc.u.type_info
523 #define GC_TYPE(p) zval_gc_type(GC_TYPE_INFO(p))
524 #define GC_FLAGS(p) zval_gc_flags(GC_TYPE_INFO(p))
525 #define GC_INFO(p) zval_gc_info(GC_TYPE_INFO(p))
526
527 #define GC_ADD_FLAGS(p, flags) do { \
528 GC_TYPE_INFO(p) |= (flags) << GC_FLAGS_SHIFT; \
529 } while (0)
530 #define GC_DEL_FLAGS(p, flags) do { \
531 GC_TYPE_INFO(p) &= ~((flags) << GC_FLAGS_SHIFT); \
532 } while (0)
533
534 #define Z_GC_TYPE(zval) GC_TYPE(Z_COUNTED(zval))
535 #define Z_GC_TYPE_P(zval_p) Z_GC_TYPE(*(zval_p))
536
537 #define Z_GC_FLAGS(zval) GC_FLAGS(Z_COUNTED(zval))
538 #define Z_GC_FLAGS_P(zval_p) Z_GC_FLAGS(*(zval_p))
539
540 #define Z_GC_INFO(zval) GC_INFO(Z_COUNTED(zval))
541 #define Z_GC_INFO_P(zval_p) Z_GC_INFO(*(zval_p))
542 #define Z_GC_TYPE_INFO(zval) GC_TYPE_INFO(Z_COUNTED(zval))
543 #define Z_GC_TYPE_INFO_P(zval_p) Z_GC_TYPE_INFO(*(zval_p))
544
545 /* zval_gc_flags(zval.value->gc.u.type_info) (common flags) */
546 #define GC_COLLECTABLE (1<<4)
547 #define GC_PROTECTED (1<<5) /* used for recursion detection */
548 #define GC_IMMUTABLE (1<<6) /* can't be canged in place */
549 #define GC_PERSISTENT (1<<7) /* allocated using malloc */
550 #define GC_PERSISTENT_LOCAL (1<<8) /* persistent, but thread-local */
551
552 #define GC_ARRAY (IS_ARRAY | (GC_COLLECTABLE << GC_FLAGS_SHIFT))
553 #define GC_OBJECT (IS_OBJECT | (GC_COLLECTABLE << GC_FLAGS_SHIFT))
554
555 /* zval.u1.v.type_flags */
556 #define IS_TYPE_REFCOUNTED (1<<0)
557 #define IS_TYPE_COLLECTABLE (1<<1)
558
559 #if 1
560 /* This optimized version assumes that we have a single "type_flag" */
561 /* IS_TYPE_COLLECTABLE may be used only with IS_TYPE_REFCOUNTED */
562 # define Z_TYPE_INFO_REFCOUNTED(t) (((t) & Z_TYPE_FLAGS_MASK) != 0)
563 #else
564 # define Z_TYPE_INFO_REFCOUNTED(t) (((t) & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0)
565 #endif
566
567 /* extended types */
568 #define IS_INTERNED_STRING_EX IS_STRING
569
570 #define IS_STRING_EX (IS_STRING | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
571 #define IS_ARRAY_EX (IS_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT) | (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT))
572 #define IS_OBJECT_EX (IS_OBJECT | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT) | (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT))
573 #define IS_RESOURCE_EX (IS_RESOURCE | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
574 #define IS_REFERENCE_EX (IS_REFERENCE | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
575
576 #define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
577
578 /* string flags (zval.value->gc.u.flags) */
579 #define IS_STR_INTERNED GC_IMMUTABLE /* interned string */
580 #define IS_STR_PERSISTENT GC_PERSISTENT /* allocated using malloc */
581 #define IS_STR_PERMANENT (1<<8) /* relives request boundary */
582 #define IS_STR_VALID_UTF8 (1<<9) /* valid UTF-8 according to PCRE */
583
584 /* array flags */
585 #define IS_ARRAY_IMMUTABLE GC_IMMUTABLE
586 #define IS_ARRAY_PERSISTENT GC_PERSISTENT
587
588 /* object flags (zval.value->gc.u.flags) */
589 #define IS_OBJ_WEAKLY_REFERENCED GC_PERSISTENT
590 #define IS_OBJ_DESTRUCTOR_CALLED (1<<8)
591 #define IS_OBJ_FREE_CALLED (1<<9)
592
593 #define OBJ_FLAGS(obj) GC_FLAGS(obj)
594
595 /* Recursion protection macros must be used only for arrays and objects */
596 #define GC_IS_RECURSIVE(p) \
597 (GC_FLAGS(p) & GC_PROTECTED)
598
599 #define GC_PROTECT_RECURSION(p) do { \
600 GC_ADD_FLAGS(p, GC_PROTECTED); \
601 } while (0)
602
603 #define GC_UNPROTECT_RECURSION(p) do { \
604 GC_DEL_FLAGS(p, GC_PROTECTED); \
605 } while (0)
606
607 #define GC_TRY_PROTECT_RECURSION(p) do { \
608 if (!(GC_FLAGS(p) & GC_IMMUTABLE)) GC_PROTECT_RECURSION(p); \
609 } while (0)
610
611 #define GC_TRY_UNPROTECT_RECURSION(p) do { \
612 if (!(GC_FLAGS(p) & GC_IMMUTABLE)) GC_UNPROTECT_RECURSION(p); \
613 } while (0)
614
615 #define Z_IS_RECURSIVE(zval) GC_IS_RECURSIVE(Z_COUNTED(zval))
616 #define Z_PROTECT_RECURSION(zval) GC_PROTECT_RECURSION(Z_COUNTED(zval))
617 #define Z_UNPROTECT_RECURSION(zval) GC_UNPROTECT_RECURSION(Z_COUNTED(zval))
618 #define Z_IS_RECURSIVE_P(zv) Z_IS_RECURSIVE(*(zv))
619 #define Z_PROTECT_RECURSION_P(zv) Z_PROTECT_RECURSION(*(zv))
620 #define Z_UNPROTECT_RECURSION_P(zv) Z_UNPROTECT_RECURSION(*(zv))
621
622 /* All data types < IS_STRING have their constructor/destructors skipped */
623 #define Z_CONSTANT(zval) (Z_TYPE(zval) == IS_CONSTANT_AST)
624 #define Z_CONSTANT_P(zval_p) Z_CONSTANT(*(zval_p))
625
626 #if 1
627 /* This optimized version assumes that we have a single "type_flag" */
628 /* IS_TYPE_COLLECTABLE may be used only with IS_TYPE_REFCOUNTED */
629 #define Z_REFCOUNTED(zval) (Z_TYPE_FLAGS(zval) != 0)
630 #else
631 #define Z_REFCOUNTED(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_REFCOUNTED) != 0)
632 #endif
633 #define Z_REFCOUNTED_P(zval_p) Z_REFCOUNTED(*(zval_p))
634
635 #define Z_COLLECTABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_COLLECTABLE) != 0)
636 #define Z_COLLECTABLE_P(zval_p) Z_COLLECTABLE(*(zval_p))
637
638 /* deprecated: (COPYABLE is the same as IS_ARRAY) */
639 #define Z_COPYABLE(zval) (Z_TYPE(zval) == IS_ARRAY)
640 #define Z_COPYABLE_P(zval_p) Z_COPYABLE(*(zval_p))
641
642 /* deprecated: (IMMUTABLE is the same as IS_ARRAY && !REFCOUNTED) */
643 #define Z_IMMUTABLE(zval) (Z_TYPE_INFO(zval) == IS_ARRAY)
644 #define Z_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p))
645 #define Z_OPT_IMMUTABLE(zval) Z_IMMUTABLE(zval_p)
646 #define Z_OPT_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p))
647
648 /* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */
649 #define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & Z_TYPE_MASK)
650 #define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p))
651
652 #define Z_OPT_CONSTANT(zval) (Z_OPT_TYPE(zval) == IS_CONSTANT_AST)
653 #define Z_OPT_CONSTANT_P(zval_p) Z_OPT_CONSTANT(*(zval_p))
654
655 #define Z_OPT_REFCOUNTED(zval) Z_TYPE_INFO_REFCOUNTED(Z_TYPE_INFO(zval))
656 #define Z_OPT_REFCOUNTED_P(zval_p) Z_OPT_REFCOUNTED(*(zval_p))
657
658 /* deprecated: (COPYABLE is the same as IS_ARRAY) */
659 #define Z_OPT_COPYABLE(zval) (Z_OPT_TYPE(zval) == IS_ARRAY)
660 #define Z_OPT_COPYABLE_P(zval_p) Z_OPT_COPYABLE(*(zval_p))
661
662 #define Z_OPT_ISREF(zval) (Z_OPT_TYPE(zval) == IS_REFERENCE)
663 #define Z_OPT_ISREF_P(zval_p) Z_OPT_ISREF(*(zval_p))
664
665 #define Z_ISREF(zval) (Z_TYPE(zval) == IS_REFERENCE)
666 #define Z_ISREF_P(zval_p) Z_ISREF(*(zval_p))
667
668 #define Z_ISUNDEF(zval) (Z_TYPE(zval) == IS_UNDEF)
669 #define Z_ISUNDEF_P(zval_p) Z_ISUNDEF(*(zval_p))
670
671 #define Z_ISNULL(zval) (Z_TYPE(zval) == IS_NULL)
672 #define Z_ISNULL_P(zval_p) Z_ISNULL(*(zval_p))
673
674 #define Z_ISERROR(zval) (Z_TYPE(zval) == _IS_ERROR)
675 #define Z_ISERROR_P(zval_p) Z_ISERROR(*(zval_p))
676
677 #define Z_LVAL(zval) (zval).value.lval
678 #define Z_LVAL_P(zval_p) Z_LVAL(*(zval_p))
679
680 #define Z_DVAL(zval) (zval).value.dval
681 #define Z_DVAL_P(zval_p) Z_DVAL(*(zval_p))
682
683 #define Z_STR(zval) (zval).value.str
684 #define Z_STR_P(zval_p) Z_STR(*(zval_p))
685
686 #define Z_STRVAL(zval) ZSTR_VAL(Z_STR(zval))
687 #define Z_STRVAL_P(zval_p) Z_STRVAL(*(zval_p))
688
689 #define Z_STRLEN(zval) ZSTR_LEN(Z_STR(zval))
690 #define Z_STRLEN_P(zval_p) Z_STRLEN(*(zval_p))
691
692 #define Z_STRHASH(zval) ZSTR_HASH(Z_STR(zval))
693 #define Z_STRHASH_P(zval_p) Z_STRHASH(*(zval_p))
694
695 #define Z_ARR(zval) (zval).value.arr
696 #define Z_ARR_P(zval_p) Z_ARR(*(zval_p))
697
698 #define Z_ARRVAL(zval) Z_ARR(zval)
699 #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*(zval_p))
700
701 #define Z_OBJ(zval) (zval).value.obj
702 #define Z_OBJ_P(zval_p) Z_OBJ(*(zval_p))
703
704 #define Z_OBJ_HT(zval) Z_OBJ(zval)->handlers
705 #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*(zval_p))
706
707 #define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
708 #define Z_OBJ_HANDLER_P(zv_p, hf) Z_OBJ_HANDLER(*(zv_p), hf)
709
710 #define Z_OBJ_HANDLE(zval) (Z_OBJ((zval)))->handle
711 #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*(zval_p))
712
713 #define Z_OBJCE(zval) (Z_OBJ(zval)->ce)
714 #define Z_OBJCE_P(zval_p) Z_OBJCE(*(zval_p))
715
716 #define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval))
717 #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*(zval_p))
718
719 #define Z_RES(zval) (zval).value.res
720 #define Z_RES_P(zval_p) Z_RES(*zval_p)
721
722 #define Z_RES_HANDLE(zval) Z_RES(zval)->handle
723 #define Z_RES_HANDLE_P(zval_p) Z_RES_HANDLE(*zval_p)
724
725 #define Z_RES_TYPE(zval) Z_RES(zval)->type
726 #define Z_RES_TYPE_P(zval_p) Z_RES_TYPE(*zval_p)
727
728 #define Z_RES_VAL(zval) Z_RES(zval)->ptr
729 #define Z_RES_VAL_P(zval_p) Z_RES_VAL(*zval_p)
730
731 #define Z_REF(zval) (zval).value.ref
732 #define Z_REF_P(zval_p) Z_REF(*(zval_p))
733
734 #define Z_REFVAL(zval) &Z_REF(zval)->val
735 #define Z_REFVAL_P(zval_p) Z_REFVAL(*(zval_p))
736
737 #define Z_AST(zval) (zval).value.ast
738 #define Z_AST_P(zval_p) Z_AST(*(zval_p))
739
740 #define GC_AST(p) ((zend_ast*)(((char*)p) + sizeof(zend_ast_ref)))
741
742 #define Z_ASTVAL(zval) GC_AST(Z_AST(zval))
743 #define Z_ASTVAL_P(zval_p) Z_ASTVAL(*(zval_p))
744
745 #define Z_INDIRECT(zval) (zval).value.zv
746 #define Z_INDIRECT_P(zval_p) Z_INDIRECT(*(zval_p))
747
748 #define Z_CE(zval) (zval).value.ce
749 #define Z_CE_P(zval_p) Z_CE(*(zval_p))
750
751 #define Z_FUNC(zval) (zval).value.func
752 #define Z_FUNC_P(zval_p) Z_FUNC(*(zval_p))
753
754 #define Z_PTR(zval) (zval).value.ptr
755 #define Z_PTR_P(zval_p) Z_PTR(*(zval_p))
756
757 #define ZVAL_UNDEF(z) do { \
758 Z_TYPE_INFO_P(z) = IS_UNDEF; \
759 } while (0)
760
761 #define ZVAL_NULL(z) do { \
762 Z_TYPE_INFO_P(z) = IS_NULL; \
763 } while (0)
764
765 #define ZVAL_FALSE(z) do { \
766 Z_TYPE_INFO_P(z) = IS_FALSE; \
767 } while (0)
768
769 #define ZVAL_TRUE(z) do { \
770 Z_TYPE_INFO_P(z) = IS_TRUE; \
771 } while (0)
772
773 #define ZVAL_BOOL(z, b) do { \
774 Z_TYPE_INFO_P(z) = \
775 (b) ? IS_TRUE : IS_FALSE; \
776 } while (0)
777
778 #define ZVAL_LONG(z, l) { \
779 zval *__z = (z); \
780 Z_LVAL_P(__z) = l; \
781 Z_TYPE_INFO_P(__z) = IS_LONG; \
782 }
783
784 #define ZVAL_DOUBLE(z, d) { \
785 zval *__z = (z); \
786 Z_DVAL_P(__z) = d; \
787 Z_TYPE_INFO_P(__z) = IS_DOUBLE; \
788 }
789
790 #define ZVAL_STR(z, s) do { \
791 zval *__z = (z); \
792 zend_string *__s = (s); \
793 Z_STR_P(__z) = __s; \
794 /* interned strings support */ \
795 Z_TYPE_INFO_P(__z) = ZSTR_IS_INTERNED(__s) ? \
796 IS_INTERNED_STRING_EX : \
797 IS_STRING_EX; \
798 } while (0)
799
800 #define ZVAL_INTERNED_STR(z, s) do { \
801 zval *__z = (z); \
802 zend_string *__s = (s); \
803 Z_STR_P(__z) = __s; \
804 Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX; \
805 } while (0)
806
807 #define ZVAL_NEW_STR(z, s) do { \
808 zval *__z = (z); \
809 zend_string *__s = (s); \
810 Z_STR_P(__z) = __s; \
811 Z_TYPE_INFO_P(__z) = IS_STRING_EX; \
812 } while (0)
813
814 #define ZVAL_STR_COPY(z, s) do { \
815 zval *__z = (z); \
816 zend_string *__s = (s); \
817 Z_STR_P(__z) = __s; \
818 /* interned strings support */ \
819 if (ZSTR_IS_INTERNED(__s)) { \
820 Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX; \
821 } else { \
822 GC_ADDREF(__s); \
823 Z_TYPE_INFO_P(__z) = IS_STRING_EX; \
824 } \
825 } while (0)
826
827 #define ZVAL_ARR(z, a) do { \
828 zend_array *__arr = (a); \
829 zval *__z = (z); \
830 Z_ARR_P(__z) = __arr; \
831 Z_TYPE_INFO_P(__z) = IS_ARRAY_EX; \
832 } while (0)
833
834 #define ZVAL_NEW_ARR(z) do { \
835 zval *__z = (z); \
836 zend_array *_arr = \
837 (zend_array *) emalloc(sizeof(zend_array)); \
838 Z_ARR_P(__z) = _arr; \
839 Z_TYPE_INFO_P(__z) = IS_ARRAY_EX; \
840 } while (0)
841
842 #define ZVAL_NEW_PERSISTENT_ARR(z) do { \
843 zval *__z = (z); \
844 zend_array *_arr = \
845 (zend_array *) malloc(sizeof(zend_array)); \
846 Z_ARR_P(__z) = _arr; \
847 Z_TYPE_INFO_P(__z) = IS_ARRAY_EX; \
848 } while (0)
849
850 #define ZVAL_OBJ(z, o) do { \
851 zval *__z = (z); \
852 Z_OBJ_P(__z) = (o); \
853 Z_TYPE_INFO_P(__z) = IS_OBJECT_EX; \
854 } while (0)
855
856 #define ZVAL_RES(z, r) do { \
857 zval *__z = (z); \
858 Z_RES_P(__z) = (r); \
859 Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX; \
860 } while (0)
861
862 #define ZVAL_NEW_RES(z, h, p, t) do { \
863 zend_resource *_res = \
864 (zend_resource *) emalloc(sizeof(zend_resource)); \
865 zval *__z; \
866 GC_SET_REFCOUNT(_res, 1); \
867 GC_TYPE_INFO(_res) = IS_RESOURCE; \
868 _res->handle = (h); \
869 _res->type = (t); \
870 _res->ptr = (p); \
871 __z = (z); \
872 Z_RES_P(__z) = _res; \
873 Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX; \
874 } while (0)
875
876 #define ZVAL_NEW_PERSISTENT_RES(z, h, p, t) do { \
877 zend_resource *_res = \
878 (zend_resource *) malloc(sizeof(zend_resource)); \
879 zval *__z; \
880 GC_SET_REFCOUNT(_res, 1); \
881 GC_TYPE_INFO(_res) = IS_RESOURCE | \
882 (GC_PERSISTENT << GC_FLAGS_SHIFT); \
883 _res->handle = (h); \
884 _res->type = (t); \
885 _res->ptr = (p); \
886 __z = (z); \
887 Z_RES_P(__z) = _res; \
888 Z_TYPE_INFO_P(__z) = IS_RESOURCE_EX; \
889 } while (0)
890
891 #define ZVAL_REF(z, r) do { \
892 zval *__z = (z); \
893 Z_REF_P(__z) = (r); \
894 Z_TYPE_INFO_P(__z) = IS_REFERENCE_EX; \
895 } while (0)
896
897 #define ZVAL_NEW_EMPTY_REF(z) do { \
898 zend_reference *_ref = \
899 (zend_reference *) emalloc(sizeof(zend_reference)); \
900 GC_SET_REFCOUNT(_ref, 1); \
901 GC_TYPE_INFO(_ref) = IS_REFERENCE; \
902 _ref->sources.ptr = NULL; \
903 Z_REF_P(z) = _ref; \
904 Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
905 } while (0)
906
907 #define ZVAL_NEW_REF(z, r) do { \
908 zend_reference *_ref = \
909 (zend_reference *) emalloc(sizeof(zend_reference)); \
910 GC_SET_REFCOUNT(_ref, 1); \
911 GC_TYPE_INFO(_ref) = IS_REFERENCE; \
912 ZVAL_COPY_VALUE(&_ref->val, r); \
913 _ref->sources.ptr = NULL; \
914 Z_REF_P(z) = _ref; \
915 Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
916 } while (0)
917
918 #define ZVAL_MAKE_REF_EX(z, refcount) do { \
919 zval *_z = (z); \
920 zend_reference *_ref = \
921 (zend_reference *) emalloc(sizeof(zend_reference)); \
922 GC_SET_REFCOUNT(_ref, (refcount)); \
923 GC_TYPE_INFO(_ref) = IS_REFERENCE; \
924 ZVAL_COPY_VALUE(&_ref->val, _z); \
925 _ref->sources.ptr = NULL; \
926 Z_REF_P(_z) = _ref; \
927 Z_TYPE_INFO_P(_z) = IS_REFERENCE_EX; \
928 } while (0)
929
930 #define ZVAL_NEW_PERSISTENT_REF(z, r) do { \
931 zend_reference *_ref = \
932 (zend_reference *) malloc(sizeof(zend_reference)); \
933 GC_SET_REFCOUNT(_ref, 1); \
934 GC_TYPE_INFO(_ref) = IS_REFERENCE | \
935 (GC_PERSISTENT << GC_FLAGS_SHIFT); \
936 ZVAL_COPY_VALUE(&_ref->val, r); \
937 _ref->sources.ptr = NULL; \
938 Z_REF_P(z) = _ref; \
939 Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
940 } while (0)
941
942 #define ZVAL_AST(z, ast) do { \
943 zval *__z = (z); \
944 Z_AST_P(__z) = ast; \
945 Z_TYPE_INFO_P(__z) = IS_CONSTANT_AST_EX; \
946 } while (0)
947
948 #define ZVAL_INDIRECT(z, v) do { \
949 Z_INDIRECT_P(z) = (v); \
950 Z_TYPE_INFO_P(z) = IS_INDIRECT; \
951 } while (0)
952
953 #define ZVAL_PTR(z, p) do { \
954 Z_PTR_P(z) = (p); \
955 Z_TYPE_INFO_P(z) = IS_PTR; \
956 } while (0)
957
958 #define ZVAL_FUNC(z, f) do { \
959 Z_FUNC_P(z) = (f); \
960 Z_TYPE_INFO_P(z) = IS_PTR; \
961 } while (0)
962
963 #define ZVAL_CE(z, c) do { \
964 Z_CE_P(z) = (c); \
965 Z_TYPE_INFO_P(z) = IS_PTR; \
966 } while (0)
967
968 #define ZVAL_ALIAS_PTR(z, p) do { \
969 Z_PTR_P(z) = (p); \
970 Z_TYPE_INFO_P(z) = IS_ALIAS_PTR; \
971 } while (0)
972
973 #define ZVAL_ERROR(z) do { \
974 Z_TYPE_INFO_P(z) = _IS_ERROR; \
975 } while (0)
976
977 #define Z_REFCOUNT_P(pz) zval_refcount_p(pz)
978 #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc)
979 #define Z_ADDREF_P(pz) zval_addref_p(pz)
980 #define Z_DELREF_P(pz) zval_delref_p(pz)
981
982 #define Z_REFCOUNT(z) Z_REFCOUNT_P(&(z))
983 #define Z_SET_REFCOUNT(z, rc) Z_SET_REFCOUNT_P(&(z), rc)
984 #define Z_ADDREF(z) Z_ADDREF_P(&(z))
985 #define Z_DELREF(z) Z_DELREF_P(&(z))
986
987 #define Z_TRY_ADDREF_P(pz) do { \
988 if (Z_REFCOUNTED_P((pz))) { \
989 Z_ADDREF_P((pz)); \
990 } \
991 } while (0)
992
993 #define Z_TRY_DELREF_P(pz) do { \
994 if (Z_REFCOUNTED_P((pz))) { \
995 Z_DELREF_P((pz)); \
996 } \
997 } while (0)
998
999 #define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z))
1000 #define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
1001
1002 #ifndef ZEND_RC_DEBUG
1003 # define ZEND_RC_DEBUG 0
1004 #endif
1005
1006 #if ZEND_RC_DEBUG
1007 extern ZEND_API zend_bool zend_rc_debug;
1008 # define ZEND_RC_MOD_CHECK(p) do { \
1009 if (zend_rc_debug && zval_gc_type((p)->u.type_info) != IS_OBJECT) { \
1010 ZEND_ASSERT(!(zval_gc_flags((p)->u.type_info) & GC_IMMUTABLE)); \
1011 ZEND_ASSERT((zval_gc_flags((p)->u.type_info) & (GC_PERSISTENT|GC_PERSISTENT_LOCAL)) != GC_PERSISTENT); \
1012 } \
1013 } while (0)
1014 # define GC_MAKE_PERSISTENT_LOCAL(p) do { \
1015 GC_ADD_FLAGS(p, GC_PERSISTENT_LOCAL); \
1016 } while (0)
1017 #else
1018 # define ZEND_RC_MOD_CHECK(p) \
1019 do { } while (0)
1020 # define GC_MAKE_PERSISTENT_LOCAL(p) \
1021 do { } while (0)
1022 #endif
1023
zend_gc_refcount(const zend_refcounted_h * p)1024 static zend_always_inline uint32_t zend_gc_refcount(const zend_refcounted_h *p) {
1025 return p->refcount;
1026 }
1027
zend_gc_set_refcount(zend_refcounted_h * p,uint32_t rc)1028 static zend_always_inline uint32_t zend_gc_set_refcount(zend_refcounted_h *p, uint32_t rc) {
1029 p->refcount = rc;
1030 return p->refcount;
1031 }
1032
zend_gc_addref(zend_refcounted_h * p)1033 static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
1034 ZEND_RC_MOD_CHECK(p);
1035 return ++(p->refcount);
1036 }
1037
zend_gc_delref(zend_refcounted_h * p)1038 static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
1039 ZEND_ASSERT(p->refcount > 0);
1040 ZEND_RC_MOD_CHECK(p);
1041 return --(p->refcount);
1042 }
1043
zend_gc_addref_ex(zend_refcounted_h * p,uint32_t rc)1044 static zend_always_inline uint32_t zend_gc_addref_ex(zend_refcounted_h *p, uint32_t rc) {
1045 ZEND_RC_MOD_CHECK(p);
1046 p->refcount += rc;
1047 return p->refcount;
1048 }
1049
zend_gc_delref_ex(zend_refcounted_h * p,uint32_t rc)1050 static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint32_t rc) {
1051 ZEND_RC_MOD_CHECK(p);
1052 p->refcount -= rc;
1053 return p->refcount;
1054 }
1055
zval_refcount_p(const zval * pz)1056 static zend_always_inline uint32_t zval_refcount_p(const zval* pz) {
1057 #if ZEND_DEBUG
1058 ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_TYPE_P(pz) == IS_ARRAY);
1059 #endif
1060 return GC_REFCOUNT(Z_COUNTED_P(pz));
1061 }
1062
zval_set_refcount_p(zval * pz,uint32_t rc)1063 static zend_always_inline uint32_t zval_set_refcount_p(zval* pz, uint32_t rc) {
1064 ZEND_ASSERT(Z_REFCOUNTED_P(pz));
1065 return GC_SET_REFCOUNT(Z_COUNTED_P(pz), rc);
1066 }
1067
zval_addref_p(zval * pz)1068 static zend_always_inline uint32_t zval_addref_p(zval* pz) {
1069 ZEND_ASSERT(Z_REFCOUNTED_P(pz));
1070 return GC_ADDREF(Z_COUNTED_P(pz));
1071 }
1072
zval_delref_p(zval * pz)1073 static zend_always_inline uint32_t zval_delref_p(zval* pz) {
1074 ZEND_ASSERT(Z_REFCOUNTED_P(pz));
1075 return GC_DELREF(Z_COUNTED_P(pz));
1076 }
1077
1078 #if SIZEOF_SIZE_T == 4
1079 # define ZVAL_COPY_VALUE_EX(z, v, gc, t) \
1080 do { \
1081 uint32_t _w2 = v->value.ww.w2; \
1082 Z_COUNTED_P(z) = gc; \
1083 z->value.ww.w2 = _w2; \
1084 Z_TYPE_INFO_P(z) = t; \
1085 } while (0)
1086 #elif SIZEOF_SIZE_T == 8
1087 # define ZVAL_COPY_VALUE_EX(z, v, gc, t) \
1088 do { \
1089 Z_COUNTED_P(z) = gc; \
1090 Z_TYPE_INFO_P(z) = t; \
1091 } while (0)
1092 #else
1093 # error "Unknown SIZEOF_SIZE_T"
1094 #endif
1095
1096 #define ZVAL_COPY_VALUE(z, v) \
1097 do { \
1098 zval *_z1 = (z); \
1099 const zval *_z2 = (v); \
1100 zend_refcounted *_gc = Z_COUNTED_P(_z2); \
1101 uint32_t _t = Z_TYPE_INFO_P(_z2); \
1102 ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \
1103 } while (0)
1104
1105 #define ZVAL_COPY(z, v) \
1106 do { \
1107 zval *_z1 = (z); \
1108 const zval *_z2 = (v); \
1109 zend_refcounted *_gc = Z_COUNTED_P(_z2); \
1110 uint32_t _t = Z_TYPE_INFO_P(_z2); \
1111 ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \
1112 if (Z_TYPE_INFO_REFCOUNTED(_t)) { \
1113 GC_ADDREF(_gc); \
1114 } \
1115 } while (0)
1116
1117 #define ZVAL_DUP(z, v) \
1118 do { \
1119 zval *_z1 = (z); \
1120 const zval *_z2 = (v); \
1121 zend_refcounted *_gc = Z_COUNTED_P(_z2); \
1122 uint32_t _t = Z_TYPE_INFO_P(_z2); \
1123 if ((_t & Z_TYPE_MASK) == IS_ARRAY) { \
1124 ZVAL_ARR(_z1, zend_array_dup((zend_array*)_gc));\
1125 } else { \
1126 if (Z_TYPE_INFO_REFCOUNTED(_t)) { \
1127 GC_ADDREF(_gc); \
1128 } \
1129 ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \
1130 } \
1131 } while (0)
1132
1133
1134 /* ZVAL_COPY_OR_DUP() should be used instead of ZVAL_COPY() and ZVAL_DUP()
1135 * in all places where the source may be a persistent zval.
1136 */
1137 #define ZVAL_COPY_OR_DUP(z, v) \
1138 do { \
1139 zval *_z1 = (z); \
1140 const zval *_z2 = (v); \
1141 zend_refcounted *_gc = Z_COUNTED_P(_z2); \
1142 uint32_t _t = Z_TYPE_INFO_P(_z2); \
1143 ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \
1144 if (Z_TYPE_INFO_REFCOUNTED(_t)) { \
1145 if (EXPECTED(!(GC_FLAGS(_gc) & GC_PERSISTENT))) { \
1146 GC_ADDREF(_gc); \
1147 } else { \
1148 zval_copy_ctor_func(_z1); \
1149 } \
1150 } \
1151 } while (0)
1152
1153 #define ZVAL_DEREF(z) do { \
1154 if (UNEXPECTED(Z_ISREF_P(z))) { \
1155 (z) = Z_REFVAL_P(z); \
1156 } \
1157 } while (0)
1158
1159 #define ZVAL_DEINDIRECT(z) do { \
1160 if (Z_TYPE_P(z) == IS_INDIRECT) { \
1161 (z) = Z_INDIRECT_P(z); \
1162 } \
1163 } while (0)
1164
1165 #define ZVAL_OPT_DEREF(z) do { \
1166 if (UNEXPECTED(Z_OPT_ISREF_P(z))) { \
1167 (z) = Z_REFVAL_P(z); \
1168 } \
1169 } while (0)
1170
1171 #define ZVAL_MAKE_REF(zv) do { \
1172 zval *__zv = (zv); \
1173 if (!Z_ISREF_P(__zv)) { \
1174 ZVAL_NEW_REF(__zv, __zv); \
1175 } \
1176 } while (0)
1177
1178 #define ZVAL_UNREF(z) do { \
1179 zval *_z = (z); \
1180 zend_reference *ref; \
1181 ZEND_ASSERT(Z_ISREF_P(_z)); \
1182 ref = Z_REF_P(_z); \
1183 ZVAL_COPY_VALUE(_z, &ref->val); \
1184 efree_size(ref, sizeof(zend_reference)); \
1185 } while (0)
1186
1187 #define ZVAL_COPY_DEREF(z, v) do { \
1188 zval *_z3 = (v); \
1189 if (Z_OPT_REFCOUNTED_P(_z3)) { \
1190 if (UNEXPECTED(Z_OPT_ISREF_P(_z3))) { \
1191 _z3 = Z_REFVAL_P(_z3); \
1192 if (Z_OPT_REFCOUNTED_P(_z3)) { \
1193 Z_ADDREF_P(_z3); \
1194 } \
1195 } else { \
1196 Z_ADDREF_P(_z3); \
1197 } \
1198 } \
1199 ZVAL_COPY_VALUE(z, _z3); \
1200 } while (0)
1201
1202
1203 #define SEPARATE_STRING(zv) do { \
1204 zval *_zv = (zv); \
1205 if (Z_REFCOUNT_P(_zv) > 1) { \
1206 zend_string *_str = Z_STR_P(_zv); \
1207 ZEND_ASSERT(Z_REFCOUNTED_P(_zv)); \
1208 ZEND_ASSERT(!ZSTR_IS_INTERNED(_str)); \
1209 Z_DELREF_P(_zv); \
1210 ZVAL_NEW_STR(_zv, zend_string_init( \
1211 ZSTR_VAL(_str), ZSTR_LEN(_str), 0)); \
1212 } \
1213 } while (0)
1214
1215 #define SEPARATE_ARRAY(zv) do { \
1216 zval *_zv = (zv); \
1217 zend_array *_arr = Z_ARR_P(_zv); \
1218 if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) { \
1219 if (Z_REFCOUNTED_P(_zv)) { \
1220 GC_DELREF(_arr); \
1221 } \
1222 ZVAL_ARR(_zv, zend_array_dup(_arr)); \
1223 } \
1224 } while (0)
1225
1226 #define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \
1227 zval *__zv = (zv); \
1228 if (Z_TYPE_P(__zv) == IS_ARRAY) { \
1229 if (Z_REFCOUNT_P(__zv) > 1) { \
1230 if (Z_REFCOUNTED_P(__zv)) { \
1231 Z_DELREF_P(__zv); \
1232 } \
1233 ZVAL_ARR(__zv, zend_array_dup(Z_ARR_P(__zv)));\
1234 } \
1235 } \
1236 } while (0)
1237
1238 #define SEPARATE_ZVAL_NOREF(zv) do { \
1239 zval *_zv = (zv); \
1240 ZEND_ASSERT(Z_TYPE_P(_zv) != IS_REFERENCE); \
1241 SEPARATE_ZVAL_IF_NOT_REF(_zv); \
1242 } while (0)
1243
1244 #define SEPARATE_ZVAL(zv) do { \
1245 zval *_zv = (zv); \
1246 if (Z_ISREF_P(_zv)) { \
1247 zend_reference *_r = Z_REF_P(_zv); \
1248 ZVAL_COPY_VALUE(_zv, &_r->val); \
1249 if (GC_DELREF(_r) == 0) { \
1250 efree_size(_r, sizeof(zend_reference)); \
1251 } else if (Z_OPT_TYPE_P(_zv) == IS_ARRAY) { \
1252 ZVAL_ARR(_zv, zend_array_dup(Z_ARR_P(_zv)));\
1253 break; \
1254 } else if (Z_OPT_REFCOUNTED_P(_zv)) { \
1255 Z_ADDREF_P(_zv); \
1256 break; \
1257 } \
1258 } \
1259 SEPARATE_ZVAL_IF_NOT_REF(_zv); \
1260 } while (0)
1261
1262 #define SEPARATE_ARG_IF_REF(varptr) do { \
1263 ZVAL_DEREF(varptr); \
1264 if (Z_REFCOUNTED_P(varptr)) { \
1265 Z_ADDREF_P(varptr); \
1266 } \
1267 } while (0)
1268
1269 /* Properties store a flag distinguishing unset and unintialized properties
1270 * (both use IS_UNDEF type) in the Z_EXTRA space. As such we also need to copy
1271 * the Z_EXTRA space when copying property default values etc. We define separate
1272 * macros for this purpose, so this workaround is easier to remove in the future. */
1273 #define IS_PROP_UNINIT 1
1274 #define Z_PROP_FLAG_P(z) Z_EXTRA_P(z)
1275 #define ZVAL_COPY_VALUE_PROP(z, v) \
1276 do { *(z) = *(v); } while (0)
1277 #define ZVAL_COPY_PROP(z, v) \
1278 do { ZVAL_COPY(z, v); Z_PROP_FLAG_P(z) = Z_PROP_FLAG_P(v); } while (0)
1279 #define ZVAL_COPY_OR_DUP_PROP(z, v) \
1280 do { ZVAL_COPY_OR_DUP(z, v); Z_PROP_FLAG_P(z) = Z_PROP_FLAG_P(v); } while (0)
1281
1282
1283 #endif /* ZEND_TYPES_H */
1284