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