* src/packdump.c:
[parrot.git] / include / parrot / pobj.h
blobcc297eb214c30d6854aec8a1d2da070c453d48ee
1 /* pobj.h
2 * Copyright (C) 2001-2005, The Perl Foundation.
3 * SVN Info
4 * $Id$
5 * Overview:
6 * Parrot Object data members and flags enum
7 * Data Structure and Algorithms:
8 * History:
9 * Notes:
10 * References: memory_internals.pod
13 #ifndef PARROT_POBJ_H_GUARD
14 #define PARROT_POBJ_H_GUARD
16 #include "parrot/config.h"
18 typedef union UnionVal {
19 struct _b { /* One Buffer structure */
20 void * _bufstart;
21 size_t _buflen;
22 } _b;
23 struct _ptrs { /* or two pointers, both are defines */
24 DPOINTER * _struct_val;
25 PMC * _pmc_val;
26 } _ptrs;
27 struct _i {
28 INTVAL _int_val; /* or 2 intvals */
29 INTVAL _int_val2;
30 } _i;
31 FLOATVAL _num_val; /* or one float */
32 struct parrot_string_t * _string_val; /* or a pointer to a string */
33 } UnionVal;
35 #define UVal_ptr(u) (u)._ptrs._struct_val
36 #define UVal_pmc(u) (u)._ptrs._pmc_val
37 #define UVal_int(u) (u)._i._int_val
38 #define UVal_int2(u) (u)._i._int_val2
39 #define UVal_num(u) (u)._num_val
40 #define UVal_str(u) (u)._string_val
42 /* Parrot Object - base class for all others */
43 typedef struct pobj_t {
44 UnionVal u;
45 Parrot_UInt flags;
46 } pobj_t;
48 /* plain Buffer is the smallest Parrot Obj */
49 typedef struct Buffer {
50 UnionVal cache;
51 Parrot_UInt flags;
52 } Buffer;
54 typedef Buffer PObj;
56 #define PObj_bufstart(pmc) (pmc)->cache._b._bufstart
57 #define PObj_buflen(pmc) (pmc)->cache._b._buflen
58 #define PMC_struct_val(pmc) (pmc)->cache._ptrs._struct_val
59 #define PMC_pmc_val(pmc) (pmc)->cache._ptrs._pmc_val
60 #define PMC_int_val(pmc) (pmc)->cache._i._int_val
61 #define PMC_int_val2(pmc) (pmc)->cache._i._int_val2
62 #define PMC_num_val(pmc) (pmc)->cache._num_val
63 #define PMC_str_val(pmc) (pmc)->cache._string_val
65 /* See src/gc/resources.c. the basic idea is that buffer memory is
66 set up as follows:
67 +-----------------+
68 | ref_count |f | # GC header
69 obj->bufstart -> +-----------------+
70 | data |
71 v v
73 The actual set-up is more involved because of padding. obj->bufstart must
74 be suitably aligned for any UnionVal. (Perhaps it should be a Buffer
75 there instead.) The start of the memory region (as returned by malloc()
76 is also suitably aligned for any use. If, for example, malloc() returns
77 objects aligned on 8-byte boundaries, and obj->bufstart is also aligned
78 on 8-byte boundaries, then there should be 4 bytes of padding. It is
79 handled differently in the two files resources.c and res_lea.c.
80 In resources.c, the buffer is carved out of a larger memory pool. In
81 res_lea.c, each buffer is individually allocated.
83 src/gc/resources.c: src/gc/res_lea.c:
85 ptr from malloc -> +------------------+ +------------------+
86 [other blocks?] | INTVAL ref_count |
87 | INTVAL ref_count | | possible padding |
88 obj->bufstart -> +------------------+ +------------------+
89 | data | | data |
90 v v v v
93 typedef struct Buffer_alloc_unit {
94 INTVAL ref_count;
95 UnionVal buffer[1]; /* Guarantee it's suitably aligned */
96 } Buffer_alloc_unit;
98 /* Given a pointer to the buffer, find the ref_count and the actual start of
99 the allocated space. Setting ref_count is clunky because we avoid lvalue
100 casts. */
101 #ifdef GC_IS_MALLOC /* see src/gc/res_lea.c */
102 # define Buffer_alloc_offset (offsetof(Buffer_alloc_unit, buffer))
103 # define PObj_bufallocstart(b) ((char *)PObj_bufstart(b) - Buffer_alloc_offset)
104 # define PObj_bufrefcount(b) (((Buffer_alloc_unit *)PObj_bufallocstart(b))->ref_count)
105 # define PObj_bufrefcountptr(b) (&PObj_bufrefcount(b))
106 #else /* see src/gc/resources.c */
107 # define Buffer_alloc_offset sizeof (INTVAL)
108 # define PObj_bufallocstart(b) ((char *)PObj_bufstart(b) - Buffer_alloc_offset)
109 # define PObj_bufrefcount(b) (*(INTVAL *)PObj_bufallocstart(b))
110 # define PObj_bufrefcountptr(b) ((INTVAL *)PObj_bufallocstart(b))
111 #endif
113 typedef enum {
114 enum_stringrep_unknown = 0,
115 enum_stringrep_one = 1,
116 enum_stringrep_two = 2,
117 enum_stringrep_four = 4
118 } parrot_string_representation_t;
120 struct parrot_string_t {
121 UnionVal cache;
122 Parrot_UInt flags;
123 char *strstart;
124 UINTVAL bufused;
125 UINTVAL strlen;
126 /* parrot_string_representation_t representation;*/
127 const struct _encoding *encoding;
128 const struct _charset *charset;
129 UINTVAL hashval; /* cached hash value computation; not yet used */
133 /* put data into the PMC_EXT structure */
134 #define PMC_DATA_IN_EXT 0
136 /* note that cache and flags are isomorphic with Buffer and PObj */
137 struct PMC {
138 UnionVal cache;
139 Parrot_UInt flags;
140 VTABLE *vtable;
141 DPOINTER *data;
142 struct PMC_EXT *pmc_ext;
143 PMC *real_self;
146 struct _Sync; /* forward decl */
148 typedef struct PMC_EXT {
149 #if PMC_DATA_IN_EXT
150 DPOINTER *data;
151 #endif /* PMC_DATA_IN_EXT */
152 PMC *_metadata; /* properties */
154 * PMC access synchronization for shared PMCs
155 * s. parrot/thread.h
157 struct _Sync *_synchronize;
159 /* This flag determines the next PMC in the 'used' list during
160 dead object detection in the GC. It is a linked list, which is
161 only valid in trace_active_PMCs. Also, the linked list is
162 guaranteed to have the tail element's _next_for_GC point to itself,
163 which makes much of the logic and checks simpler. We then have to
164 check for PMC->_next_for_GC == PMC to find the end of list. */
165 PMC *_next_for_GC;
167 /* Yeah, the GC data should be out of
168 band, but that makes things really slow when actually marking
169 things for the GC runs. Unfortunately putting this here makes
170 marking things clear for the GC pre-run slow as well, as we need
171 to touch all the PMC structs. (Though we will for flag setting
172 anyway) We can potentially make this a pointer to the real GC
173 stuff, which'd merit an extra dereference when setting, but let
174 us memset the actual GC data in a big block
176 } PMC_EXT;
178 #ifdef NDEBUG
179 # define PMC_ext_checked(pmc) (pmc)->pmc_ext
180 #else
181 # define PMC_ext_checked(pmc) (PARROT_ASSERT((pmc)->pmc_ext), (pmc)->pmc_ext)
182 #endif /* NDEBUG */
183 #if PMC_DATA_IN_EXT
184 # define PMC_data(pmc) PMC_ext_checked(pmc)->data
185 # define PMC_data_typed(pmc, type) (type)PMC_ext_checked(pmc)->data
186 # define PMC_data0(pmc) ((pmc)->pmc_ext ? pmc->pmc_ext->data : 0)
187 # define PMC_data0_typed(pmc, type) (type)((pmc)->pmc_ext ? pmc->pmc_ext->data : 0)
188 #else
189 # define PMC_data(pmc) (pmc)->data
190 # define PMC_data_typed(pmc, type) (type)(pmc)->data
191 /* do not allow PMC_data2 as lvalue */
192 # define PMC_data0(pmc) (1 ? (pmc)->data : 0)
193 # define PMC_data0_typed(pmc) (type)(1 ? (pmc)->data : 0)
194 #endif /* PMC_DATA_IN_EXT */
195 #define PMC_metadata(pmc) PMC_ext_checked(pmc)->_metadata
196 #define PMC_next_for_GC(pmc) PMC_ext_checked(pmc)->_next_for_GC
197 #define PMC_sync(pmc) PMC_ext_checked(pmc)->_synchronize
198 #define PMC_union(pmc) (pmc)->cache
200 #define POBJ_FLAG(n) ((UINTVAL)1 << (n))
201 /* PObj flags */
202 typedef enum PObj_enum {
203 /* This first 8 flags may be used privately by a Parrot Object.
204 * You should alias these within an individual class's header file.
206 * Note: If the meanings of these flags are changed, then the symbolic
207 * names kept in flag_bit_names (see src/packdump.c) must also be updated.
209 PObj_private0_FLAG = POBJ_FLAG(0),
210 PObj_private1_FLAG = POBJ_FLAG(1),
211 PObj_private2_FLAG = POBJ_FLAG(2),
212 PObj_private3_FLAG = POBJ_FLAG(3),
213 PObj_private4_FLAG = POBJ_FLAG(4),
214 PObj_private5_FLAG = POBJ_FLAG(5),
215 PObj_private6_FLAG = POBJ_FLAG(6),
216 PObj_private7_FLAG = POBJ_FLAG(7),
218 /* Object specification FLAGs */
219 /* PObj is a string */
220 PObj_is_string_FLAG = POBJ_FLAG(8),
221 /* PObj is a PMC */
222 PObj_is_PMC_FLAG = POBJ_FLAG(9),
223 /* the PMC has a PMC_EXT structure appended */
224 PObj_is_PMC_EXT_FLAG = POBJ_FLAG(10),
225 /* the PMC is a shared PMC */
226 PObj_is_PMC_shared_FLAG = POBJ_FLAG(11), /* Same as PObj_is_shared_FLAG */
227 /* PObj is otherwise shared */
228 PObj_is_shared_FLAG = POBJ_FLAG(11), /* Same as PObj_is_PMC_shared_FLAG */
230 /* Memory management FLAGs */
231 /* This is a constant--don't kill it! */
232 PObj_constant_FLAG = POBJ_FLAG(12),
233 /* Marks the contents as coming from a non-Parrot source */
234 PObj_external_FLAG = POBJ_FLAG(13),
235 /* the Buffer is aligned to BUFFER_ALIGNMENT boundaries */
236 PObj_aligned_FLAG = POBJ_FLAG(14),
237 /* Mark the buffer as pointing to system memory */
238 PObj_sysmem_FLAG = POBJ_FLAG(15),
240 /* PObj usage FLAGs, COW & GC */
241 /* Mark the contents as Copy on write */
242 PObj_COW_FLAG = POBJ_FLAG(16),
243 /* the Buffer may have COW copies */
244 PObj_is_COWable_FLAG = POBJ_FLAG(17),
245 /* Private flag for the GC system. Set if the PObj's in use as
246 * far as the GC's concerned */
247 b_PObj_live_FLAG = POBJ_FLAG(18),
248 /* Mark the object as on the free list */
249 b_PObj_on_free_list_FLAG = POBJ_FLAG(19),
251 /* DOD/GC FLAGS */
252 /* Set to true if the PObj has a custom mark routine */
253 PObj_custom_mark_FLAG = POBJ_FLAG(20),
254 /* Mark the buffer as needing GC */
255 PObj_custom_GC_FLAG = POBJ_FLAG(21),
256 /* Set if the PObj has a destroy method that must be called */
257 PObj_active_destroy_FLAG = POBJ_FLAG(22),
258 /* For debugging, report when this buffer gets moved around */
259 PObj_report_FLAG = POBJ_FLAG(23),
261 /* PMC specific FLAGs */
262 /* Set to true if the PMC data pointer points to a malloced
263 * array of PObjs
265 PObj_data_is_PMC_array_FLAG = POBJ_FLAG(24),
266 /* call object finalizer */
267 PObj_need_finalize_FLAG = POBJ_FLAG(25),
268 /* a PMC that needs special handling in DOD, i.e one that has either:
269 * - metadata
270 * - data_is_PMC_array_FLAG
271 * - custom_mark_FLAG
273 b_PObj_is_special_PMC_FLAG = POBJ_FLAG(26),
275 /* true if this is connected by some route to a needs_early_DOD object */
276 PObj_high_priority_DOD_FLAG = POBJ_FLAG(27),
277 PObj_needs_early_DOD_FLAG = (POBJ_FLAG(27) | POBJ_FLAG(28)),
279 /* True if the PMC is a class */
280 PObj_is_class_FLAG = POBJ_FLAG(29),
281 /* True if the PMC is a parrot object */
282 PObj_is_object_FLAG = POBJ_FLAG(30)
284 } PObj_flags;
285 #undef POBJ_FLAG
288 * flag access macros:
289 * directly using any flags is STRONGLY discouraged, please use
290 * these macros
293 # define PObj_live_FLAG b_PObj_live_FLAG
294 # define PObj_on_free_list_FLAG b_PObj_on_free_list_FLAG
295 # define PObj_is_special_PMC_FLAG b_PObj_is_special_PMC_FLAG
297 # define DOD_flag_TEST(flag, o) PObj_flag_TEST(flag, o)
298 # define DOD_flag_SET(flag, o) PObj_flag_SET(flag, o)
299 # define DOD_flag_CLEAR(flag, o) PObj_flag_CLEAR(flag, o)
301 #define PObj_get_FLAGS(o) ((o)->flags)
303 #define PObj_flag_TEST(flag, o) (PObj_get_FLAGS(o) & PObj_ ## flag ## _FLAG)
304 #define PObj_flag_SET(flag, o) (PObj_get_FLAGS(o) |= PObj_ ## flag ## _FLAG)
305 #define PObj_flag_CLEAR(flag, o) \
306 (PObj_get_FLAGS(o) &= ~(UINTVAL)(PObj_ ## flag ## _FLAG))
308 #define PObj_flags_SETTO(o, f) PObj_get_FLAGS(o) = (f)
309 #define PObj_flags_CLEARALL(o) PObj_flags_SETTO(o, 0)
311 #define PObj_COW_TEST(o) PObj_flag_TEST(COW, o)
312 #define PObj_COW_SET(o) PObj_flag_SET(COW, o)
313 #define PObj_COW_CLEAR(o) PObj_flag_CLEAR(COW, o)
315 #define PObj_is_COWable_TEST(o) PObj_flag_TEST(is_COWable, o)
316 #define PObj_is_COWable_SET(o) PObj_flag_SET(is_COWable, o)
318 #define PObj_aligned_TEST(o) PObj_flag_TEST(aligned, o)
319 #define PObj_aligned_SET(o) PObj_flag_SET(aligned, o)
321 #define PObj_constant_TEST(o) PObj_flag_TEST(constant, o)
322 #define PObj_constant_SET(o) PObj_flag_SET(constant, o)
323 #define PObj_constant_CLEAR(o) PObj_flag_CLEAR(constant, o)
325 #define PObj_external_TEST(o) PObj_flag_TEST(external, o)
326 #define PObj_external_SET(o) PObj_flag_SET(external, o)
327 #define PObj_external_CLEAR(o) PObj_flag_CLEAR(external, o)
329 #define PObj_report_TEST(o) PObj_flag_TEST(report, o)
330 #define PObj_report_SET(o) PObj_flag_SET(report, o)
331 #define PObj_report_CLEAR(o) PObj_flag_CLEAR(report, o)
334 #define PObj_on_free_list_TEST(o) DOD_flag_TEST(on_free_list, o)
335 #define PObj_on_free_list_SET(o) DOD_flag_SET(on_free_list, o)
336 #define PObj_on_free_list_CLEAR(o) DOD_flag_CLEAR(on_free_list, o)
338 #define PObj_live_TEST(o) DOD_flag_TEST(live, o)
339 #define PObj_live_SET(o) DOD_flag_SET(live, o)
340 #define PObj_live_CLEAR(o) DOD_flag_CLEAR(live, o)
342 #define PObj_is_string_TEST(o) PObj_flag_TEST(is_string, o)
343 #define PObj_is_string_SET(o) PObj_flag_SET(is_string, o)
344 #define PObj_is_string_CLEAR(o) PObj_flag_CLEAR(is_string, o)
346 #define PObj_sysmem_TEST(o) PObj_flag_TEST(sysmem, o)
347 #define PObj_sysmem_SET(o) PObj_flag_SET(sysmem, o)
348 #define PObj_sysmem_CLEAR(o) PObj_flag_CLEAR(sysmem, o)
351 #define PObj_special_SET(flag, o) do { \
352 PObj_flag_SET(flag, o); \
353 DOD_flag_SET(is_special_PMC, o); \
354 } while (0)
356 #define PObj_special_CLEAR(flag, o) do { \
357 PObj_flag_CLEAR(flag, o); \
358 if ((PObj_get_FLAGS(o) & \
359 (PObj_active_destroy_FLAG | \
360 PObj_custom_mark_FLAG | \
361 PObj_data_is_PMC_array_FLAG | \
362 PObj_is_PMC_EXT_FLAG | \
363 PObj_needs_early_DOD_FLAG))) \
364 DOD_flag_SET(is_special_PMC, o); \
365 else \
366 DOD_flag_CLEAR(is_special_PMC, o); \
367 } while (0)
369 #define PObj_is_special_PMC_TEST(o) DOD_flag_TEST(is_special_PMC, o)
370 #define PObj_is_special_PMC_SET(o) DOD_flag_SET(is_special_PMC, o)
372 #define PObj_data_is_PMC_array_SET(o) do { \
373 PObj_special_SET(data_is_PMC_array, o); \
374 PObj_flag_SET(active_destroy, o); \
375 } while (0)
377 #define PObj_data_is_PMC_array_CLEAR(o) do {\
378 PObj_special_CLEAR(data_is_PMC_array, o); \
379 PObj_flag_CLEAR(active_destroy, o); \
380 } while (0)
382 #define PObj_data_is_PMC_array_TEST(o) \
383 PObj_flag_TEST(data_is_PMC_array, o)
385 #define PObj_needs_early_DOD_TEST(o) PObj_flag_TEST(needs_early_DOD, o)
386 #define PObj_needs_early_DOD_SET(o) PObj_special_SET(needs_early_DOD, o)
387 #define PObj_needs_early_DOD_CLEAR(o) PObj_special_CLEAR(needs_early_DOD, o)
389 #define PObj_high_priority_DOD_TEST(o) PObj_flag_TEST(high_priority_DOD, o)
390 #define PObj_high_priority_DOD_SET(o) PObj_special_SET(high_priority_DOD, o)
391 #define PObj_high_priority_DOD_CLEAR(o) PObj_special_CLEAR(high_priority_DOD, o)
393 #define PObj_custom_mark_SET(o) PObj_special_SET(custom_mark, o)
394 #define PObj_custom_mark_CLEAR(o) PObj_special_CLEAR(custom_mark, o)
395 #define PObj_custom_mark_TEST(o) PObj_flag_TEST(custom_mark, o)
397 #define PObj_active_destroy_SET(o) PObj_flag_SET(active_destroy, o)
398 #define PObj_active_destroy_TEST(o) PObj_flag_TEST(active_destroy, o)
399 #define PObj_active_destroy_CLEAR(o) PObj_flag_CLEAR(active_destroy, o)
401 #define PObj_is_class_SET(o) PObj_flag_SET(is_class, o)
402 #define PObj_is_class_TEST(o) PObj_flag_TEST(is_class, o)
403 #define PObj_is_class_CLEAR(o) PObj_flag_CLEAR(is_class, o)
405 #define PObj_is_object_SET(o) PObj_flag_SET(is_object, o)
406 #define PObj_is_object_TEST(o) PObj_flag_TEST(is_object, o)
407 #define PObj_is_object_CLEAR(o) PObj_flag_CLEAR(is_object, o)
409 #define PObj_is_PMC_TEST(o) PObj_flag_TEST(is_PMC, o)
411 #define PObj_is_PMC_EXT_TEST(o) PObj_flag_TEST(is_PMC_EXT, o)
412 #define PObj_is_PMC_EXT_SET(o) PObj_special_SET(is_PMC_EXT, o)
414 #define PObj_is_PMC_shared_TEST(o) PObj_flag_TEST(is_PMC_shared, o)
415 #define PObj_is_PMC_shared_SET(o) PObj_flag_SET(is_PMC_shared, o)
416 #define PObj_is_PMC_shared_CLEAR(o) PObj_flag_CLEAR(is_PMC_shared, o)
418 #define PObj_is_shared_TEST(o) PObj_flag_TEST(is_shared, o)
419 #define PObj_is_shared_SET(o) PObj_flag_SET(is_shared, o)
420 #define PObj_is_shared_CLEAR(o) PObj_flag_CLEAR(is_shared, o)
422 /* some combinations */
423 #define PObj_is_cowed_TESTALL(o) (PObj_get_FLAGS(o) & \
424 (PObj_COW_FLAG|PObj_constant_FLAG|PObj_external_FLAG))
425 #define PObj_is_cowed_SETALL(o) (PObj_get_FLAGS(o) |= \
426 (PObj_COW_FLAG|PObj_constant_FLAG|PObj_external_FLAG))
428 #define PObj_is_external_or_free_TESTALL(o) (PObj_get_FLAGS(o) & \
429 (UINTVAL)(PObj_external_FLAG|PObj_on_free_list_FLAG))
431 #define PObj_is_external_CLEARALL(o) (PObj_get_FLAGS(o) &= \
432 ~(UINTVAL)(PObj_COW_FLAG| \
433 PObj_external_FLAG|PObj_sysmem_FLAG))
435 #define PObj_is_live_or_free_TESTALL(o) (PObj_get_FLAGS(o) & \
436 (PObj_live_FLAG | PObj_on_free_list_FLAG))
438 #define PObj_is_movable_TESTALL(o) (!(PObj_get_FLAGS(o) & \
439 (PObj_sysmem_FLAG | PObj_on_free_list_FLAG | \
440 PObj_constant_FLAG | PObj_external_FLAG)))
442 #define PObj_custom_mark_destroy_SETALL(o) do { \
443 PObj_custom_mark_SET(o); \
444 PObj_active_destroy_SET(o); \
445 } while (0)
447 #endif /* PARROT_POBJ_H_GUARD */
450 * Local variables:
451 * c-file-style: "parrot"
452 * End:
453 * vim: expandtab shiftwidth=4: