]> gitweb.factorcode.org Git - factor.git/blob - vm/layouts.hpp
callstack>array primitive was not GC safe
[factor.git] / vm / layouts.hpp
1 namespace factor
2 {
3
4 typedef unsigned char u8;
5 typedef unsigned short u16;
6 typedef unsigned int u32;
7 typedef unsigned long long u64;
8 typedef signed char s8;
9 typedef signed short s16;
10 typedef signed int s32;
11 typedef signed long long s64;
12
13 #ifdef _WIN64
14         typedef long long fixnum;
15         typedef unsigned long long cell;
16 #else
17         typedef long fixnum;
18         typedef unsigned long cell;
19 #endif
20
21 inline static cell align(cell a, cell b)
22 {
23         return (a + (b-1)) & ~(b-1);
24 }
25
26 inline static cell align8(cell a)
27 {
28         return align(a,8);
29 }
30
31 #define WORD_SIZE (signed)(sizeof(cell)*8)
32
33 #define TAG_MASK 7
34 #define TAG_BITS 3
35 #define TAG(x) ((cell)(x) & TAG_MASK)
36 #define UNTAG(x) ((cell)(x) & ~TAG_MASK)
37 #define RETAG(x,tag) (UNTAG(x) | (tag))
38
39 /*** Tags ***/
40 #define FIXNUM_TYPE 0
41 #define BIGNUM_TYPE 1
42 #define ARRAY_TYPE 2
43 #define FLOAT_TYPE 3
44 #define QUOTATION_TYPE 4
45 #define F_TYPE 5
46 #define OBJECT_TYPE 6
47 #define TUPLE_TYPE 7
48
49 /* Canonical F object */
50 #define F F_TYPE
51
52 #define HEADER_TYPE 8 /* anything less than this is a tag */
53
54 #define GC_COLLECTED 5 /* can be anything other than FIXNUM_TYPE */
55
56 /*** Header types ***/
57 #define WRAPPER_TYPE 8
58 #define BYTE_ARRAY_TYPE 9
59 #define CALLSTACK_TYPE 10
60 #define STRING_TYPE 11
61 #define WORD_TYPE 12
62 #define DLL_TYPE 13
63 #define ALIEN_TYPE 14
64
65 #define TYPE_COUNT 15
66
67 /* Not a real type, but code_block's type field can be set to this */
68 #define PIC_TYPE 69
69
70 inline static bool immediate_p(cell obj)
71 {
72         return (obj == F || TAG(obj) == FIXNUM_TYPE);
73 }
74
75 inline static fixnum untag_fixnum(cell tagged)
76 {
77 #ifdef FACTOR_DEBUG
78         assert(TAG(tagged) == FIXNUM_TYPE);
79 #endif
80         return ((fixnum)tagged) >> TAG_BITS;
81 }
82
83 inline static cell tag_fixnum(fixnum untagged)
84 {
85         return RETAG(untagged << TAG_BITS,FIXNUM_TYPE);
86 }
87
88 inline static cell tag_for(cell type)
89 {
90         return type < HEADER_TYPE ? type : OBJECT_TYPE;
91 }
92
93 struct object;
94
95 struct header {
96         cell value;
97
98         /* Default ctor to make gcc 3.x happy */
99         header() { abort(); }
100
101         header(cell value_) : value(value_ << TAG_BITS) {}
102
103         void check_header() {
104 #ifdef FACTOR_DEBUG
105                 assert(TAG(value) == FIXNUM_TYPE && untag_fixnum(value) < TYPE_COUNT);
106 #endif
107         }
108
109         cell hi_tag() {
110                 check_header();
111                 return value >> TAG_BITS;
112         }
113
114         bool forwarding_pointer_p() {
115                 return TAG(value) == GC_COLLECTED;
116         }
117
118         object *forwarding_pointer() {
119                 return (object *)UNTAG(value);
120         }
121
122         void forward_to(object *pointer) {
123                 value = RETAG(pointer,GC_COLLECTED);
124         }
125 };
126
127 #define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
128
129 struct object {
130         NO_TYPE_CHECK;
131         header h;
132         cell *slots() { return (cell *)this; }
133 };
134
135 /* Assembly code makes assumptions about the layout of this struct */
136 struct array : public object {
137         static const cell type_number = ARRAY_TYPE;
138         static const cell element_size = sizeof(cell);
139         /* tagged */
140         cell capacity;
141
142         cell *data() { return (cell *)(this + 1); }
143 };
144
145 /* These are really just arrays, but certain elements have special
146 significance */
147 struct tuple_layout : public array {
148         NO_TYPE_CHECK;
149         /* tagged */
150         cell klass;
151         /* tagged fixnum */
152         cell size;
153         /* tagged fixnum */
154         cell echelon;
155 };
156
157 struct bignum : public object {
158         static const cell type_number = BIGNUM_TYPE;
159         static const cell element_size = sizeof(cell);
160         /* tagged */
161         cell capacity;
162
163         cell *data() { return (cell *)(this + 1); }
164 };
165
166 struct byte_array : public object {
167         static const cell type_number = BYTE_ARRAY_TYPE;
168         static const cell element_size = 1;
169         /* tagged */
170         cell capacity;
171
172         template<typename T> T *data() { return (T *)(this + 1); }
173 };
174
175 /* Assembly code makes assumptions about the layout of this struct */
176 struct string : public object {
177         static const cell type_number = STRING_TYPE;
178         /* tagged num of chars */
179         cell length;
180         /* tagged */
181         cell aux;
182         /* tagged */
183         cell hashcode;
184
185         u8 *data() { return (u8 *)(this + 1); }
186 };
187
188 /* The compiled code heap is structured into blocks. */
189 enum block_status
190 {
191         B_FREE,
192         B_ALLOCATED,
193         B_MARKED
194 };
195
196 struct heap_block
197 {
198         unsigned char status; /* free or allocated? */
199         unsigned char type; /* this is WORD_TYPE or QUOTATION_TYPE */
200         unsigned char last_scan; /* the youngest generation in which this block's literals may live */
201         unsigned char needs_fixup; /* is this a new block that needs full fixup? */
202
203         /* In bytes, includes this header */
204         cell size;
205 };
206
207 struct free_heap_block : public heap_block
208 {
209         free_heap_block *next_free;
210 };
211
212 struct code_block : public heap_block
213 {
214         cell literals; /* # bytes */
215         cell relocation; /* tagged pointer to byte-array or f */
216         
217         void *xt() { return (void *)(this + 1); }
218 };
219
220 /* Assembly code makes assumptions about the layout of this struct */
221 struct word : public object {
222         static const cell type_number = WORD_TYPE;
223         /* TAGGED hashcode */
224         cell hashcode;
225         /* TAGGED word name */
226         cell name;
227         /* TAGGED word vocabulary */
228         cell vocabulary;
229         /* TAGGED definition */
230         cell def;
231         /* TAGGED property assoc for library code */
232         cell props;
233         /* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
234         cell pic_def;
235         /* TAGGED alternative entry point for direct tail calls. Used for inline caching */
236         cell pic_tail_def;
237         /* TAGGED call count for profiling */
238         cell counter;
239         /* TAGGED machine code for sub-primitive */
240         cell subprimitive;
241         /* UNTAGGED execution token: jump here to execute word */
242         void *xt;
243         /* UNTAGGED compiled code block */
244         code_block *code;
245         /* UNTAGGED profiler stub */
246         code_block *profiling;
247 };
248
249 /* Assembly code makes assumptions about the layout of this struct */
250 struct wrapper : public object {
251         static const cell type_number = WRAPPER_TYPE;
252         cell object;
253 };
254
255 /* Assembly code makes assumptions about the layout of this struct */
256 struct boxed_float : object {
257         static const cell type_number = FLOAT_TYPE;
258
259 #ifndef FACTOR_64
260         cell padding;
261 #endif
262
263         double n;
264 };
265
266 /* Assembly code makes assumptions about the layout of this struct */
267 struct quotation : public object {
268         static const cell type_number = QUOTATION_TYPE;
269         /* tagged */
270         cell array;
271         /* tagged */
272         cell cached_effect;
273         /* tagged */
274         cell cache_counter;
275         /* UNTAGGED */
276         void *xt;
277         /* UNTAGGED compiled code block */
278         code_block *code;
279 };
280
281 /* Assembly code makes assumptions about the layout of this struct */
282 struct alien : public object {
283         static const cell type_number = ALIEN_TYPE;
284         /* tagged */
285         cell alien;
286         /* tagged */
287         cell expired;
288         /* untagged */
289         cell displacement;
290 };
291
292 struct dll : public object {
293         static const cell type_number = DLL_TYPE;
294         /* tagged byte array holding a C string */
295         cell path;
296         /* OS-specific handle */
297         void *dll;
298 };
299
300 struct stack_frame
301 {
302         void *xt;
303         /* Frame size in bytes */
304         cell size;
305 };
306
307 struct callstack : public object {
308         static const cell type_number = CALLSTACK_TYPE;
309         /* tagged */
310         cell length;
311         
312         stack_frame *frame_at(cell offset)
313         {
314                 return (stack_frame *)((char *)(this + 1) + offset);
315         }
316
317         stack_frame *top() { return (stack_frame *)(this + 1); }
318         stack_frame *bottom() { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
319 };
320
321 struct tuple : public object {
322         static const cell type_number = TUPLE_TYPE;
323         /* tagged layout */
324         cell layout;
325
326         cell *data() { return (cell *)(this + 1); }
327 };
328
329 }