]> gitweb.factorcode.org Git - factor.git/blob - vm/layouts.hpp
Merge branch 'master' into new_gc
[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 static const cell data_alignment = 16;
27
28 #define WORD_SIZE (signed)(sizeof(cell)*8)
29
30 #define TAG_MASK 7
31 #define TAG_BITS 3
32 #define TAG(x) ((cell)(x) & TAG_MASK)
33 #define UNTAG(x) ((cell)(x) & ~TAG_MASK)
34 #define RETAG(x,tag) (UNTAG(x) | (tag))
35
36 /*** Tags ***/
37 #define FIXNUM_TYPE 0
38 #define BIGNUM_TYPE 1
39 #define ARRAY_TYPE 2
40 #define FLOAT_TYPE 3
41 #define QUOTATION_TYPE 4
42 #define F_TYPE 5
43 #define OBJECT_TYPE 6
44 #define TUPLE_TYPE 7
45
46 #define HEADER_TYPE 8 /* anything less than this is a tag */
47
48 #define GC_COLLECTED 5 /* can be anything other than FIXNUM_TYPE */
49
50 /*** Header types ***/
51 #define WRAPPER_TYPE 8
52 #define BYTE_ARRAY_TYPE 9
53 #define CALLSTACK_TYPE 10
54 #define STRING_TYPE 11
55 #define WORD_TYPE 12
56 #define DLL_TYPE 13
57 #define ALIEN_TYPE 14
58
59 #define TYPE_COUNT 15
60
61 enum code_block_type
62 {
63         code_block_unoptimized,
64         code_block_optimized,
65         code_block_profiling,
66         code_block_pic
67 };
68
69 /* Constants used when floating-point trap exceptions are thrown */
70 enum
71 {
72         FP_TRAP_INVALID_OPERATION = 1 << 0,
73         FP_TRAP_OVERFLOW          = 1 << 1,
74         FP_TRAP_UNDERFLOW         = 1 << 2,
75         FP_TRAP_ZERO_DIVIDE       = 1 << 3,
76         FP_TRAP_INEXACT           = 1 << 4,
77 };
78
79 /* What Factor calls 'f' */
80 static const cell false_object = F_TYPE;
81
82 inline static bool immediate_p(cell obj)
83 {
84         return (obj == false_object || TAG(obj) == FIXNUM_TYPE);
85 }
86
87 inline static fixnum untag_fixnum(cell tagged)
88 {
89 #ifdef FACTOR_DEBUG
90         assert(TAG(tagged) == FIXNUM_TYPE);
91 #endif
92         return ((fixnum)tagged) >> TAG_BITS;
93 }
94
95 inline static cell tag_fixnum(fixnum untagged)
96 {
97         return RETAG(untagged << TAG_BITS,FIXNUM_TYPE);
98 }
99
100 inline static cell tag_for(cell type)
101 {
102         return type < HEADER_TYPE ? type : OBJECT_TYPE;
103 }
104
105 struct object;
106
107 struct header {
108         cell value;
109
110         /* Default ctor to make gcc 3.x happy */
111         explicit header() { abort(); }
112
113         explicit header(cell value_) : value(value_ << TAG_BITS) {}
114
115         void check_header() const
116         {
117 #ifdef FACTOR_DEBUG
118                 assert(TAG(value) == FIXNUM_TYPE && untag_fixnum(value) < TYPE_COUNT);
119 #endif
120         }
121
122         cell hi_tag() const
123         {
124                 check_header();
125                 return value >> TAG_BITS;
126         }
127
128         bool forwarding_pointer_p() const
129         {
130                 return TAG(value) == GC_COLLECTED;
131         }
132
133         object *forwarding_pointer() const
134         {
135                 return (object *)UNTAG(value);
136         }
137
138         void forward_to(object *pointer)
139         {
140                 value = RETAG(pointer,GC_COLLECTED);
141         }
142 };
143
144 #define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
145
146 struct object {
147         NO_TYPE_CHECK;
148         header h;
149
150         cell size() const;
151
152         cell *slots()  const { return (cell *)this; }
153
154         /* Only valid for objects in tenured space; must fast to free_heap_block
155         to do anything with it if its free */
156         bool free_p() const
157         {
158                 return h.value & 1 == 1;
159         }
160 };
161
162 /* Assembly code makes assumptions about the layout of this struct */
163 struct array : public object {
164         static const cell type_number = ARRAY_TYPE;
165         static const cell element_size = sizeof(cell);
166         /* tagged */
167         cell capacity;
168
169         cell *data() const { return (cell *)(this + 1); }
170 };
171
172 /* These are really just arrays, but certain elements have special
173 significance */
174 struct tuple_layout : public array {
175         NO_TYPE_CHECK;
176         /* tagged */
177         cell klass;
178         /* tagged fixnum */
179         cell size;
180         /* tagged fixnum */
181         cell echelon;
182 };
183
184 struct bignum : public object {
185         static const cell type_number = BIGNUM_TYPE;
186         static const cell element_size = sizeof(cell);
187         /* tagged */
188         cell capacity;
189
190         cell *data() const { return (cell *)(this + 1); }
191 };
192
193 struct byte_array : public object {
194         static const cell type_number = BYTE_ARRAY_TYPE;
195         static const cell element_size = 1;
196         /* tagged */
197         cell capacity;
198
199 #ifndef FACTOR_64
200         cell padding0;
201         cell padding1;
202 #endif
203
204         template<typename Scalar> Scalar *data() const { return (Scalar *)(this + 1); }
205 };
206
207 /* Assembly code makes assumptions about the layout of this struct */
208 struct string : public object {
209         static const cell type_number = STRING_TYPE;
210         /* tagged num of chars */
211         cell length;
212         /* tagged */
213         cell aux;
214         /* tagged */
215         cell hashcode;
216
217         u8 *data() const { return (u8 *)(this + 1); }
218
219         cell nth(cell i) const;
220 };
221
222 /* The compiled code heap is structured into blocks. */
223 struct heap_block
224 {
225         cell header;
226
227         bool free_p() const
228         {
229                 return header & 1 == 1;
230         }
231
232         cell size() const
233         {
234                 cell bytes = header >> 3;
235 #ifdef FACTOR_DEBUG
236                 assert(bytes > 0);
237 #endif
238                 return bytes;
239         }
240
241         void set_size(cell size)
242         {
243                 header = ((header & 0x7) | (size << 3));
244         }
245 };
246
247 struct free_heap_block : public heap_block
248 {
249         free_heap_block *next_free;
250
251         void make_free(cell size)
252         {
253                 header = (size << 3) | 1;
254         }
255 };
256
257 struct code_block : public heap_block
258 {
259         cell owner; /* tagged pointer to word, quotation or f */
260         cell literals; /* tagged pointer to array or f */
261         cell relocation; /* tagged pointer to byte-array or f */
262
263         void *xt() const
264         {
265                 return (void *)(this + 1);
266         }
267
268         code_block_type type() const
269         {
270                 return (code_block_type)((header >> 1) & 0x3);
271         }
272
273         void set_type(code_block_type type)
274         {
275                 header = ((header & ~0x7) | (type << 1));
276         }
277
278         bool pic_p() const
279         {
280                 return type() == code_block_pic;
281         }
282
283         bool optimized_p() const
284         {
285                 return type() == code_block_optimized;
286         }
287 };
288
289 /* Assembly code makes assumptions about the layout of this struct */
290 struct word : public object {
291         static const cell type_number = WORD_TYPE;
292         /* TAGGED hashcode */
293         cell hashcode;
294         /* TAGGED word name */
295         cell name;
296         /* TAGGED word vocabulary */
297         cell vocabulary;
298         /* TAGGED definition */
299         cell def;
300         /* TAGGED property assoc for library code */
301         cell props;
302         /* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
303         cell pic_def;
304         /* TAGGED alternative entry point for direct tail calls. Used for inline caching */
305         cell pic_tail_def;
306         /* TAGGED call count for profiling */
307         cell counter;
308         /* TAGGED machine code for sub-primitive */
309         cell subprimitive;
310         /* UNTAGGED execution token: jump here to execute word */
311         void *xt;
312         /* UNTAGGED compiled code block */
313         code_block *code;
314         /* UNTAGGED profiler stub */
315         code_block *profiling;
316 };
317
318 /* Assembly code makes assumptions about the layout of this struct */
319 struct wrapper : public object {
320         static const cell type_number = WRAPPER_TYPE;
321         cell object;
322 };
323
324 /* Assembly code makes assumptions about the layout of this struct */
325 struct boxed_float : object {
326         static const cell type_number = FLOAT_TYPE;
327
328 #ifndef FACTOR_64
329         cell padding;
330 #endif
331
332         double n;
333 };
334
335 /* Assembly code makes assumptions about the layout of this struct */
336 struct quotation : public object {
337         static const cell type_number = QUOTATION_TYPE;
338         /* tagged */
339         cell array;
340         /* tagged */
341         cell cached_effect;
342         /* tagged */
343         cell cache_counter;
344         /* UNTAGGED */
345         void *xt;
346         /* UNTAGGED compiled code block */
347         code_block *code;
348 };
349
350 /* Assembly code makes assumptions about the layout of this struct */
351 struct alien : public object {
352         static const cell type_number = ALIEN_TYPE;
353         /* tagged */
354         cell base;
355         /* tagged */
356         cell expired;
357         /* untagged */
358         cell displacement;
359 };
360
361 struct dll : public object {
362         static const cell type_number = DLL_TYPE;
363         /* tagged byte array holding a C string */
364         cell path;
365         /* OS-specific handle */
366         void *dll;
367 };
368
369 struct stack_frame
370 {
371         void *xt;
372         /* Frame size in bytes */
373         cell size;
374 };
375
376 struct callstack : public object {
377         static const cell type_number = CALLSTACK_TYPE;
378         /* tagged */
379         cell length;
380         
381         stack_frame *frame_at(cell offset) const
382         {
383                 return (stack_frame *)((char *)(this + 1) + offset);
384         }
385
386         stack_frame *top() const { return (stack_frame *)(this + 1); }
387         stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
388 };
389
390 struct tuple : public object {
391         static const cell type_number = TUPLE_TYPE;
392         /* tagged layout */
393         cell layout;
394
395         cell *data() const { return (cell *)(this + 1); }
396 };
397
398 }