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