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