]> 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         cell binary_payload_start() const;
152
153         cell *slots()  const { return (cell *)this; }
154
155         /* Only valid for objects in tenured space; must fast to free_heap_block
156         to do anything with it if its free */
157         bool free_p() const
158         {
159                 return h.value & 1 == 1;
160         }
161 };
162
163 /* Assembly code makes assumptions about the layout of this struct */
164 struct array : public object {
165         static const cell type_number = ARRAY_TYPE;
166         static const cell element_size = sizeof(cell);
167         /* tagged */
168         cell capacity;
169
170         cell *data() const { return (cell *)(this + 1); }
171 };
172
173 /* These are really just arrays, but certain elements have special
174 significance */
175 struct tuple_layout : public array {
176         NO_TYPE_CHECK;
177         /* tagged */
178         cell klass;
179         /* tagged fixnum */
180         cell size;
181         /* tagged fixnum */
182         cell echelon;
183 };
184
185 struct bignum : public object {
186         static const cell type_number = BIGNUM_TYPE;
187         static const cell element_size = sizeof(cell);
188         /* tagged */
189         cell capacity;
190
191         cell *data() const { return (cell *)(this + 1); }
192 };
193
194 struct byte_array : public object {
195         static const cell type_number = BYTE_ARRAY_TYPE;
196         static const cell element_size = 1;
197         /* tagged */
198         cell capacity;
199
200 #ifndef FACTOR_64
201         cell padding0;
202         cell padding1;
203 #endif
204
205         template<typename Scalar> Scalar *data() const { return (Scalar *)(this + 1); }
206 };
207
208 /* Assembly code makes assumptions about the layout of this struct */
209 struct string : public object {
210         static const cell type_number = STRING_TYPE;
211         /* tagged num of chars */
212         cell length;
213         /* tagged */
214         cell aux;
215         /* tagged */
216         cell hashcode;
217
218         u8 *data() const { return (u8 *)(this + 1); }
219
220         cell nth(cell i) const;
221 };
222
223 /* The compiled code heap is structured into blocks. */
224 struct code_block
225 {
226         cell header;
227         cell owner; /* tagged pointer to word, quotation or f */
228         cell literals; /* tagged pointer to array or f */
229         cell relocation; /* tagged pointer to byte-array or f */
230
231         bool free_p() const
232         {
233                 return header & 1 == 1;
234         }
235
236         code_block_type type() const
237         {
238                 return (code_block_type)((header >> 1) & 0x3);
239         }
240
241         void set_type(code_block_type type)
242         {
243                 header = ((header & ~0x7) | (type << 1));
244         }
245
246         bool pic_p() const
247         {
248                 return type() == code_block_pic;
249         }
250
251         bool optimized_p() const
252         {
253                 return type() == code_block_optimized;
254         }
255
256         cell size() const
257         {
258                 return header >> 3;
259         }
260
261         void *xt() const
262         {
263                 return (void *)(this + 1);
264         }
265 };
266
267 /* Assembly code makes assumptions about the layout of this struct */
268 struct word : public object {
269         static const cell type_number = WORD_TYPE;
270         /* TAGGED hashcode */
271         cell hashcode;
272         /* TAGGED word name */
273         cell name;
274         /* TAGGED word vocabulary */
275         cell vocabulary;
276         /* TAGGED definition */
277         cell def;
278         /* TAGGED property assoc for library code */
279         cell props;
280         /* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
281         cell pic_def;
282         /* TAGGED alternative entry point for direct tail calls. Used for inline caching */
283         cell pic_tail_def;
284         /* TAGGED call count for profiling */
285         cell counter;
286         /* TAGGED machine code for sub-primitive */
287         cell subprimitive;
288         /* UNTAGGED execution token: jump here to execute word */
289         void *xt;
290         /* UNTAGGED compiled code block */
291         code_block *code;
292         /* UNTAGGED profiler stub */
293         code_block *profiling;
294 };
295
296 /* Assembly code makes assumptions about the layout of this struct */
297 struct wrapper : public object {
298         static const cell type_number = WRAPPER_TYPE;
299         cell object;
300 };
301
302 /* Assembly code makes assumptions about the layout of this struct */
303 struct boxed_float : object {
304         static const cell type_number = FLOAT_TYPE;
305
306 #ifndef FACTOR_64
307         cell padding;
308 #endif
309
310         double n;
311 };
312
313 /* Assembly code makes assumptions about the layout of this struct */
314 struct quotation : public object {
315         static const cell type_number = QUOTATION_TYPE;
316         /* tagged */
317         cell array;
318         /* tagged */
319         cell cached_effect;
320         /* tagged */
321         cell cache_counter;
322         /* UNTAGGED */
323         void *xt;
324         /* UNTAGGED compiled code block */
325         code_block *code;
326 };
327
328 /* Assembly code makes assumptions about the layout of this struct */
329 struct alien : public object {
330         static const cell type_number = ALIEN_TYPE;
331         /* tagged */
332         cell base;
333         /* tagged */
334         cell expired;
335         /* untagged */
336         cell displacement;
337 };
338
339 struct dll : public object {
340         static const cell type_number = DLL_TYPE;
341         /* tagged byte array holding a C string */
342         cell path;
343         /* OS-specific handle */
344         void *dll;
345 };
346
347 struct stack_frame
348 {
349         void *xt;
350         /* Frame size in bytes */
351         cell size;
352 };
353
354 struct callstack : public object {
355         static const cell type_number = CALLSTACK_TYPE;
356         /* tagged */
357         cell length;
358         
359         stack_frame *frame_at(cell offset) const
360         {
361                 return (stack_frame *)((char *)(this + 1) + offset);
362         }
363
364         stack_frame *top() const { return (stack_frame *)(this + 1); }
365         stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
366 };
367
368 struct tuple : public object {
369         static const cell type_number = TUPLE_TYPE;
370         /* tagged layout */
371         cell layout;
372
373         cell *data() const { return (cell *)(this + 1); }
374 };
375
376 }