This source file includes following definitions.
- gc_check_possible_root
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #ifndef ZEND_GC_H
23 #define ZEND_GC_H
24
25 #ifndef GC_BENCH
26 # define GC_BENCH 0
27 #endif
28
29 #if GC_BENCH
30 # define GC_BENCH_INC(counter) GC_G(counter)++
31 # define GC_BENCH_DEC(counter) GC_G(counter)--
32 # define GC_BENCH_PEAK(peak, counter) do { \
33 if (GC_G(counter) > GC_G(peak)) { \
34 GC_G(peak) = GC_G(counter); \
35 } \
36 } while (0)
37 #else
38 # define GC_BENCH_INC(counter)
39 # define GC_BENCH_DEC(counter)
40 # define GC_BENCH_PEAK(peak, counter)
41 #endif
42
43 #define GC_COLOR 0xc000
44
45 #define GC_BLACK 0x0000
46 #define GC_WHITE 0x8000
47 #define GC_GREY 0x4000
48 #define GC_PURPLE 0xc000
49
50 #define GC_ADDRESS(v) \
51 ((v) & ~GC_COLOR)
52 #define GC_INFO_GET_COLOR(v) \
53 (((zend_uintptr_t)(v)) & GC_COLOR)
54 #define GC_INFO_SET_ADDRESS(v, a) \
55 do {(v) = ((v) & GC_COLOR) | (a);} while (0)
56 #define GC_INFO_SET_COLOR(v, c) \
57 do {(v) = ((v) & ~GC_COLOR) | (c);} while (0)
58 #define GC_INFO_SET_BLACK(v) \
59 do {(v) = (v) & ~GC_COLOR;} while (0)
60 #define GC_INFO_SET_PURPLE(v) \
61 do {(v) = (v) | GC_COLOR;} while (0)
62
63 typedef struct _gc_root_buffer {
64 zend_refcounted *ref;
65 struct _gc_root_buffer *next;
66 struct _gc_root_buffer *prev;
67 uint32_t refcount;
68 } gc_root_buffer;
69
70 typedef struct _zend_gc_globals {
71 zend_bool gc_enabled;
72 zend_bool gc_active;
73 zend_bool gc_full;
74
75 gc_root_buffer *buf;
76 gc_root_buffer roots;
77 gc_root_buffer *unused;
78 gc_root_buffer *first_unused;
79 gc_root_buffer *last_unused;
80
81 gc_root_buffer to_free;
82 gc_root_buffer *next_to_free;
83
84 uint32_t gc_runs;
85 uint32_t collected;
86
87 #if GC_BENCH
88 uint32_t root_buf_length;
89 uint32_t root_buf_peak;
90 uint32_t zval_possible_root;
91 uint32_t zval_buffered;
92 uint32_t zval_remove_from_buffer;
93 uint32_t zval_marked_grey;
94 #endif
95
96 } zend_gc_globals;
97
98 #ifdef ZTS
99 BEGIN_EXTERN_C()
100 ZEND_API extern int gc_globals_id;
101 END_EXTERN_C()
102 #define GC_G(v) ZEND_TSRMG(gc_globals_id, zend_gc_globals *, v)
103 #else
104 #define GC_G(v) (gc_globals.v)
105 extern ZEND_API zend_gc_globals gc_globals;
106 #endif
107
108 BEGIN_EXTERN_C()
109 ZEND_API extern int (*gc_collect_cycles)(void);
110
111 ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref);
112 ZEND_API void ZEND_FASTCALL gc_remove_from_buffer(zend_refcounted *ref);
113 ZEND_API void gc_globals_ctor(void);
114 ZEND_API void gc_globals_dtor(void);
115 ZEND_API void gc_init(void);
116 ZEND_API void gc_reset(void);
117
118
119 ZEND_API int zend_gc_collect_cycles(void);
120 END_EXTERN_C()
121
122 #define GC_ZVAL_CHECK_POSSIBLE_ROOT(z) \
123 gc_check_possible_root((z))
124
125 #define GC_REMOVE_FROM_BUFFER(p) do { \
126 zend_refcounted *_p = (zend_refcounted*)(p); \
127 if (GC_ADDRESS(GC_INFO(_p))) { \
128 gc_remove_from_buffer(_p); \
129 } \
130 } while (0)
131
132 static zend_always_inline void gc_check_possible_root(zval *z)
133 {
134 ZVAL_DEREF(z);
135 if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
136 gc_possible_root(Z_COUNTED_P(z));
137 }
138 }
139
140 #endif
141
142
143
144
145
146
147
148