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