1 /* pobj.h
2  *  Copyright (C) 2001-2015, Parrot Foundation.
3  *  Overview:
4  *     Parrot Object data members and flags enum
5  *  Data Structure and Algorithms:
6  *  History:
7  *  Notes:
8  *  References: memory_internals.pod (out of date as of 8/2010).
9  */
10 
11 #ifndef PARROT_POBJ_H_GUARD
12 #define PARROT_POBJ_H_GUARD
13 
14 #include "parrot/config.h"
15 
16 /* This is the base Parrot object structure. Every object begins with
17    this slot, then has additional slots as required. */
18 
19 typedef struct pobj_t {
20     Parrot_UInt flags;                  /* Lots of flags (see below). */
21 } PObj;
22 
23 /* This is a buffer header object, "inheriting" from PObj. */
24 
25 typedef struct buffer_t {
26     Parrot_UInt flags;
27     void *     _bufstart;               /* Pointer to start of buffer data
28                                            (not buffer prolog). */
29     size_t     _buflen;                 /* Length of buffer data. */
30 } Parrot_Buffer;
31 
32 typedef enum Forward_flag {
33     Buffer_moved_FLAG   = 1 << 0,
34     Buffer_shared_FLAG  = 1 << 1
35 } Forward_flags;
36 
37 /* Use these macros to access the two buffer header slots. */
38 
39 #define Buffer_bufstart(buffer)    (buffer)->_bufstart
40 #define Buffer_buflen(buffer)      (buffer)->_buflen
41 
42 /* A buffer header object points to a buffer in a Memory_Block.
43    The buffer includes a prolog, but _bufstart points to the data
44    portion. Here is how it works:
45 
46     Buffer header                         buffer
47    +-------------------+                 +------------------------+
48    |       flags       |                 |  (possible padding)    | }
49    +-------------------+                 +---------------------+--+  > prolog
50    |      _bufstart    | ------+         |    *Memory_Block    |fl| }
51    +-------------------+       |         +---------------------+--+
52    |      _buflen      |       +-------> |    data portion        |
53    +-------------------+                 |                        |
54                                          ~                        ~
55                                          |                        |
56                                          +------------------------+
57 
58    The buffer prolog consists of possible padding and a pointer to the
59    Memory_Block containing the buffer. There are two flags in the low-order
60    bits of the pointer (see string.h). Padding is only required if the
61    alignment of the data portion is higher than that of a pointer.
62    This was not the case as of 8/2010.
63 */
64 
65 /* These macros let us address the prolog of a buffer. */
66 
67 #define Buffer_prolog_offset (sizeof (void*))
68 #define Buffer_bufprolog(b) ((char *)Buffer_bufstart(b) - Buffer_prolog_offset)
69 
70 /* This macro gives us the address of the buffer prolog treated as
71    a pointer to the flags. */
72 
73 #define Buffer_bufflagsptr(b) ((INTVAL *)Buffer_bufprolog(b))
74 
75 /* These macros give us the Memory_Block pointer and pointer-pointer,
76    eliminating the flags. */
77 
78 #define Buffer_pool(b) ((Memory_Block *)( *(INTVAL*)(Buffer_bufprolog(b)) & ~3 ))
79 #define Buffer_poolptr(b) ((Memory_Block **)Buffer_bufprolog(b))
80 
81 
82 /* Here is the Parrot string header object, "inheriting" from Buffer. */
83 
84 struct parrot_string_t {
85     Parrot_UInt flags;
86     void *     _bufstart;
87     size_t     _buflen;
88     char       *strstart;               /* Pointer to start of string
89                                            (not necessarily at _bufstart). */
90     UINTVAL     bufused;                /* Length of string in bytes. */
91     UINTVAL     strlen;                 /* Length of string in characters. */
92     UINTVAL     hashval;                /* Cached hash value. */
93 
94     /*    parrot_string_representation_t representation;*/
95     const struct _str_vtable *encoding; /* Pointer to string vtable. */
96 };
97 
98 /* Here is the Parrot PMC object, "inheriting" from PObj. */
99 
100 struct PMC {
101     Parrot_UInt    flags;
102     VTABLE         *vtable;             /* Pointer to vtable. */
103     DPOINTER       *data;               /* Pointer to attribute structure. */
104     PMC            *_metadata;          /* Pointer to metadata PMC. */
105 #ifdef THREAD_DEBUG
106     Parrot_Interp  orig_interp;
107 #endif
108 };
109 
110 /* Use these macros to access the data and metadata. */
111 
112 #define PMC_data(pmc)                   (pmc)->data
113 #define PMC_data_typed(pmc, type) (type)(pmc)->data
114 #define PMC_metadata(pmc)         ((pmc)->_metadata)
115 
116 #define POBJ_FLAG(n) ((UINTVAL)1 << (n))
117 /* PObj flags */
118 typedef enum PObj_enum {
119     /* This first 8 flags may be used privately by a Parrot Object.
120      * You should alias these within an individual class's header file.
121      *
122      * Note:  If the meanings of these flags are changed, then the symbolic
123      * names kept in flag_bit_names (see src/packdump.c) must also be updated.
124      */
125     PObj_private0_FLAG          = POBJ_FLAG(0),
126     PObj_private1_FLAG          = POBJ_FLAG(1),
127     PObj_private2_FLAG          = POBJ_FLAG(2),
128     PObj_private3_FLAG          = POBJ_FLAG(3),
129     PObj_private4_FLAG          = POBJ_FLAG(4),
130     PObj_private5_FLAG          = POBJ_FLAG(5),
131     PObj_private6_FLAG          = POBJ_FLAG(6),
132     PObj_private7_FLAG          = POBJ_FLAG(7),
133 
134 /* Object specification FLAGs */
135     /* PObj is a string */
136     PObj_is_string_FLAG         = POBJ_FLAG(8),  /* 0x100 */
137     /* PObj is a PMC */
138     PObj_is_PMC_FLAG            = POBJ_FLAG(9),  /* 0x200 */
139     /* PObj is a copy of a string that doesn't own the string buffer */
140     PObj_is_string_copy_FLAG    = POBJ_FLAG(10), /* 0x400 */
141     /* the PMC is a shared PMC */
142     PObj_is_PMC_shared_FLAG     = POBJ_FLAG(11), /* 0x800 Same as PObj_is_shared_FLAG */
143     /* PObj is otherwise shared */
144     PObj_is_shared_FLAG         = POBJ_FLAG(11), /* Same as PObj_is_PMC_shared_FLAG */
145 
146 /* Memory management FLAGs */
147     /* This is a constant--don't kill it! */
148     PObj_constant_FLAG          = POBJ_FLAG(12), /* 0x1000 */
149     /* Marks the contents as coming from a non-Parrot source */
150     PObj_external_FLAG          = POBJ_FLAG(13), /* 0x2000 */
151     /* Mark the buffer as pointing to system memory */
152     PObj_sysmem_FLAG            = POBJ_FLAG(14), /* 0x4000 */
153 
154 /* PObj usage FLAGs, COW & GC */
155     /* The Buffer allows COW copies, and may have some. */
156     PObj_is_COWable_FLAG        = POBJ_FLAG(15), /* 0x8000 */
157     /* Private flag for the GC system. Set if the PObj's in use as
158      * far as the GC's concerned */
159     b_PObj_live_FLAG            = POBJ_FLAG(16), /* 0x10000 */
160     /* Mark the object as on the free list */
161     b_PObj_on_free_list_FLAG    = POBJ_FLAG(17), /* 0x20000 */
162 
163 /* GC FLAGS */
164     /* Set to true if the PObj has a custom mark routine */
165     PObj_custom_mark_FLAG       = POBJ_FLAG(18), /* 0x40000 */
166     /* Set if the PObj has a destroy method that must be called */
167     PObj_custom_destroy_FLAG    = POBJ_FLAG(19), /* 0x80000 */
168     /* For debugging, report when this buffer gets moved around */
169     PObj_report_FLAG            = POBJ_FLAG(20), /* 0x100000 */
170 
171     /* used by Proxy PMC to identify PMCs created on the current interp */
172     PObj_is_new_FLAG            = POBJ_FLAG(21), /* 0x200000 */
173 
174     /* Flags used by generation GC to determine generation object belong */
175     PObj_GC_generation_0_FLAG   = POBJ_FLAG(22), /* 0x400000 */
176     PObj_GC_generation_1_FLAG   = POBJ_FLAG(23), /* 0x800000 */
177     PObj_GC_generation_2_FLAG   = POBJ_FLAG(24), /* 0x1000000 */
178 
179     /* Object was marked dirty by write barrier */
180     PObj_GC_on_dirty_list_FLAG  = POBJ_FLAG(25), /* 0x2000000 */
181 
182     /* Object requires write barrier */
183     PObj_GC_need_write_barrier_FLAG = POBJ_FLAG(26), /* 0x4000000 */
184 
185     /* Object on C stack will require implicit put to dirty list in GMS */
186     PObj_GC_soil_root_FLAG      = POBJ_FLAG(27), /* 0x8000000 */
187 
188     /* For simplify some cleanup/setup */
189     PObj_GC_all_generation_FLAGS = PObj_GC_generation_0_FLAG
190                                  | PObj_GC_generation_1_FLAG
191                                  | PObj_GC_generation_2_FLAG,
192 
193     PObj_GC_all_FLAGS            = PObj_GC_all_generation_FLAGS
194                                  | PObj_GC_on_dirty_list_FLAG
195                                  | PObj_GC_need_write_barrier_FLAG,
196 
197 /* PMC specific FLAGs */
198     /* true if this is connected by some route to a needs_early_gc object */
199     PObj_needs_early_gc_FLAG    = POBJ_FLAG(28), /* 0x10000000 */
200 
201     /* True if the PMC is a class */
202     PObj_is_class_FLAG          = POBJ_FLAG(29), /* 0x20000000 */
203     /* True if the PMC is a parrot object */
204     PObj_is_object_FLAG         = POBJ_FLAG(30)  /* 0x40000000 */
205 
206 } PObj_flags;
207 #undef POBJ_FLAG
208 
209 /*
210  * flag access macros:
211  * directly using any flags is STRONGLY discouraged, please use
212  * these macros
213  */
214 
215 #  define PObj_live_FLAG              b_PObj_live_FLAG
216 #  define PObj_on_free_list_FLAG      b_PObj_on_free_list_FLAG
217 
218 #  define gc_flag_TEST(flag, o)      PObj_flag_TEST(flag, o)
219 #  define gc_flag_SET(flag, o)       PObj_flag_SET(flag, o)
220 #  define gc_flag_CLEAR(flag, o)     PObj_flag_CLEAR(flag, o)
221 
222 #define PObj_get_FLAGS(o) ((o)->flags)
223 
224 #define PObj_flag_TEST(flag, o) (PObj_get_FLAGS(o) & PObj_ ## flag ## _FLAG)
225 #define PObj_flag_SET(flag, o) (PObj_get_FLAGS(o) |= PObj_ ## flag ## _FLAG)
226 #define PObj_flag_CLEAR(flag, o) \
227         (PObj_get_FLAGS(o) &= ~(UINTVAL)(PObj_ ## flag ## _FLAG))
228 
229 #define PObj_flags_SETTO(o, f) PObj_get_FLAGS(o) = (f)
230 #define PObj_flags_CLEARALL(o) PObj_flags_SETTO((o), 0)
231 
232 #define PObj_is_COWable_TEST(o) PObj_flag_TEST(is_COWable, o)
233 #define PObj_is_COWable_SET(o) PObj_flag_SET(is_COWable, o)
234 
235 #define PObj_constant_TEST(o) PObj_flag_TEST(constant, o)
236 #define PObj_constant_SET(o) PObj_flag_SET(constant, o)
237 #define PObj_constant_CLEAR(o) PObj_flag_CLEAR(constant, o)
238 
239 #define PObj_external_TEST(o) PObj_flag_TEST(external, o)
240 #define PObj_external_SET(o) PObj_flag_SET(external, o)
241 #define PObj_external_CLEAR(o) PObj_flag_CLEAR(external, o)
242 
243 #define PObj_report_TEST(o) PObj_flag_TEST(report, o)
244 #define PObj_report_SET(o) PObj_flag_SET(report, o)
245 #define PObj_report_CLEAR(o) PObj_flag_CLEAR(report, o)
246 
247 #define PObj_on_free_list_TEST(o) gc_flag_TEST(on_free_list, o)
248 #define PObj_on_free_list_SET(o) gc_flag_SET(on_free_list, o)
249 #define PObj_on_free_list_CLEAR(o) gc_flag_CLEAR(on_free_list, o)
250 
251 #define PObj_live_TEST(o) gc_flag_TEST(live, o)
252 #define PObj_live_SET(o) gc_flag_SET(live, o)
253 #define PObj_live_CLEAR(o) gc_flag_CLEAR(live, o)
254 
255 #define PObj_is_string_TEST(o) PObj_flag_TEST(is_string, o)
256 #define PObj_is_string_SET(o) PObj_flag_SET(is_string, o)
257 #define PObj_is_string_CLEAR(o) PObj_flag_CLEAR(is_string, o)
258 
259 #define PObj_is_string_copy_TEST(o) PObj_flag_TEST(is_string_copy, o)
260 #define PObj_is_string_copy_SET(o) PObj_flag_SET(is_string_copy, o)
261 #define PObj_is_string_copy_CLEAR(o) PObj_flag_CLEAR(is_string_copy, o)
262 
263 #define PObj_sysmem_TEST(o) PObj_flag_TEST(sysmem, o)
264 #define PObj_sysmem_SET(o) PObj_flag_SET(sysmem, o)
265 #define PObj_sysmem_CLEAR(o) PObj_flag_CLEAR(sysmem, o)
266 
267 
268 #define PObj_needs_early_gc_TEST(o) PObj_flag_TEST(needs_early_gc, o)
269 #define PObj_needs_early_gc_SET(o) PObj_flag_SET(needs_early_gc, o)
270 #define PObj_needs_early_gc_CLEAR(o) PObj_flag_CLEAR(needs_early_gc, o)
271 
272 #define PObj_high_priority_gc_TEST(o)   PObj_flag_TEST(high_priority_gc, o)
273 #define PObj_high_priority_gc_SET(o)     PObj_flag_SET(high_priority_gc, o)
274 #define PObj_high_priority_gc_CLEAR(o) PObj_flag_CLEAR(high_priority_gc, o)
275 
276 #define PObj_custom_mark_SET(o)   PObj_flag_SET(custom_mark, o)
277 #define PObj_custom_mark_CLEAR(o)   PObj_flag_CLEAR(custom_mark, o)
278 #define PObj_custom_mark_TEST(o)   PObj_flag_TEST(custom_mark, o)
279 
280 #define PObj_custom_destroy_SET(o)   PObj_flag_SET(custom_destroy,   o)
281 #define PObj_custom_destroy_TEST(o)  PObj_flag_TEST(custom_destroy,  o)
282 #define PObj_custom_destroy_CLEAR(o) PObj_flag_CLEAR(custom_destroy, o)
283 
284 #define PObj_is_class_SET(o) PObj_flag_SET(is_class, o)
285 #define PObj_is_class_TEST(o) PObj_flag_TEST(is_class, o)
286 #define PObj_is_class_CLEAR(o) PObj_flag_CLEAR(is_class, o)
287 
288 #define PObj_is_object_SET(o) PObj_flag_SET(is_object, o)
289 #define PObj_is_object_TEST(o) PObj_flag_TEST(is_object, o)
290 #define PObj_is_object_CLEAR(o) PObj_flag_CLEAR(is_object, o)
291 
292 #define PObj_is_PMC_TEST(o) PObj_flag_TEST(is_PMC, o)
293 
294 #define PObj_is_PMC_shared_TEST(o) PObj_flag_TEST(is_PMC_shared, o)
295 #define PObj_is_PMC_shared_SET(o)  PObj_flag_SET(is_PMC_shared, o)
296 #define PObj_is_PMC_shared_CLEAR(o) PObj_flag_CLEAR(is_PMC_shared, o)
297 
298 #define PObj_is_shared_TEST(o) PObj_flag_TEST(is_shared, o)
299 #define PObj_is_shared_SET(o)  PObj_flag_SET(is_shared, o)
300 #define PObj_is_shared_CLEAR(o) PObj_flag_CLEAR(is_shared, o)
301 
302 #define PObj_is_new_TEST(o) PObj_flag_TEST(is_new, o)
303 #define PObj_is_new_SET(o)  PObj_flag_SET(is_new, o)
304 #define PObj_is_new_CLEAR(o) PObj_flag_CLEAR(is_new, o)
305 
306 #define PObj_GC_on_dirty_list_TEST(o)  PObj_flag_TEST(GC_on_dirty_list, o)
307 #define PObj_GC_on_dirty_list_SET(o)   PObj_flag_SET(GC_on_dirty_list, o)
308 #define PObj_GC_on_dirty_list_CLEAR(o) PObj_flag_CLEAR(GC_on_dirty_list, o)
309 
310 #define PObj_GC_need_write_barrier_TEST(o)  PObj_flag_TEST(GC_need_write_barrier, o)
311 #define PObj_GC_need_write_barrier_SET(o)   PObj_flag_SET(GC_need_write_barrier, o)
312 #define PObj_GC_need_write_barrier_CLEAR(o) PObj_flag_CLEAR(GC_need_write_barrier, o)
313 
314 #define PObj_GC_soil_root_TEST(o)  PObj_flag_TEST(GC_soil_root, o)
315 #define PObj_GC_soil_root_SET(o)   PObj_flag_SET(GC_soil_root, o)
316 #define PObj_GC_soil_root_CLEAR(o) PObj_flag_CLEAR(GC_soil_root, o)
317 
318 
319 /* some combinations */
320 #define PObj_is_external_or_free_TESTALL(o) (PObj_get_FLAGS(o) & \
321             (UINTVAL)(PObj_external_FLAG|PObj_on_free_list_FLAG))
322 
323 #define PObj_is_external_CLEARALL(o) (PObj_get_FLAGS(o) &= \
324             ~(UINTVAL)(PObj_external_FLAG|PObj_sysmem_FLAG))
325 
326 #define PObj_is_live_or_free_TESTALL(o) (PObj_get_FLAGS(o) & \
327         (PObj_live_FLAG | PObj_on_free_list_FLAG))
328 
329 #define PObj_is_movable_TESTALL(o) (!(PObj_get_FLAGS(o) & \
330         (PObj_sysmem_FLAG | PObj_on_free_list_FLAG | \
331          PObj_constant_FLAG | PObj_external_FLAG)))
332 
333 #define PObj_is_growable_TESTALL(o) (!(PObj_get_FLAGS(o) & \
334         (PObj_sysmem_FLAG | PObj_is_string_copy_FLAG | \
335          PObj_constant_FLAG | PObj_external_FLAG)))
336 
337 #define PObj_custom_mark_destroy_SETALL(o) \
338     (PObj_get_FLAGS(o) |= PObj_custom_mark_FLAG | PObj_custom_destroy_FLAG)
339 
340 #define PObj_gc_CLEAR(o) (PObj_get_FLAGS(o) \
341     &= ~PObj_custom_destroy_FLAG \
342      & ~PObj_custom_mark_FLAG \
343      & ~PObj_live_FLAG)
344 
345 /* Thread debugging aid for catching PMCs ending up on the wrong interp */
346 
347 #ifdef THREAD_DEBUG
348 #  define PARROT_ASSERT_INTERP(pmc, interp) \
349     PARROT_ASSERT((pmc) == NULL || PMC_IS_NULL(pmc) || \
350             PObj_is_shared_TEST(pmc) || (pmc)->orig_interp == (interp))
351 #else
352 #  define PARROT_ASSERT_INTERP(pmc, interp)
353 #endif
354 
355 #endif /* PARROT_POBJ_H_GUARD */
356 
357 /*
358  * Local variables:
359  *   c-file-style: "parrot"
360  * End:
361  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
362  */
363