]> gitweb.factorcode.org Git - factor.git/blob - vm/vm.hpp
c89268f9b6059d83322f7ee531ecdf21a31947e1
[factor.git] / vm / vm.hpp
1 namespace factor
2 {
3
4 struct factor_vm
5 {
6         // First five fields accessed directly by assembler. See vm.factor
7
8         /* Current stacks */
9         context *stack_chain;
10         
11         /* New objects are allocated here */
12         zone nursery;
13
14         /* Add this to a shifted address to compute write barrier offsets */
15         cell cards_offset;
16         cell decks_offset;
17
18         /* TAGGED user environment data; see getenv/setenv prims */
19         cell userenv[USER_ENV];
20
21         /* Data stack and retain stack sizes */
22         cell ds_size, rs_size;
23
24         /* Pooling unused contexts to make callbacks cheaper */
25         context *unused_contexts;
26
27         /* Canonical T object. It's just a word */
28         cell T;
29
30         /* Is call counting enabled? */
31         bool profiling_p;
32
33         /* Global variables used to pass fault handler state from signal handler to
34            user-space */
35         cell signal_number;
36         cell signal_fault_addr;
37         unsigned int signal_fpu_status;
38         stack_frame *signal_callstack_top;
39
40         /* Zeroes out deallocated memory; set by the -securegc command line argument */
41         bool secure_gc;
42
43         /* A heap walk allows useful things to be done, like finding all
44            references to an object for debugging purposes. */
45         cell heap_scan_ptr;
46
47         /* GC is off during heap walking */
48         bool gc_off;
49
50         /* Data heap */
51         data_heap *data;
52
53         /* Code heap */
54         code_heap *code;
55
56         /* Only set if we're performing a GC */
57         gc_state *current_gc;
58
59         /* Statistics */
60         gc_statistics gc_stats;
61
62         /* If a runtime function needs to call another function which potentially
63            allocates memory, it must wrap any local variable references to Factor
64            objects in gc_root instances */
65         std::vector<cell> gc_locals;
66         std::vector<cell> gc_bignums;
67
68         /* Debugger */
69         bool fep_disabled;
70         bool full_output;
71
72         /* Canonical bignums */
73         cell bignum_zero;
74         cell bignum_pos_one;
75         cell bignum_neg_one;
76
77         /* Method dispatch statistics */
78         cell megamorphic_cache_hits;
79         cell megamorphic_cache_misses;
80
81         cell cold_call_to_ic_transitions;
82         cell ic_to_pic_transitions;
83         cell pic_to_mega_transitions;
84         /* Indexed by PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */
85         cell pic_counts[4];
86
87         /* Number of entries in a polymorphic inline cache */
88         cell max_pic_size;
89
90         // contexts
91         void reset_datastack();
92         void reset_retainstack();
93         void fix_stacks();
94         void save_stacks();
95         context *alloc_context();
96         void dealloc_context(context *old_context);
97         void nest_stacks();
98         void unnest_stacks();
99         void init_stacks(cell ds_size_, cell rs_size_);
100         bool stack_to_array(cell bottom, cell top);
101         cell array_to_stack(array *array, cell bottom);
102         void primitive_datastack();
103         void primitive_retainstack();
104         void primitive_set_datastack();
105         void primitive_set_retainstack();
106         void primitive_check_datastack();
107
108         // run
109         void primitive_getenv();
110         void primitive_setenv();
111         void primitive_exit();
112         void primitive_micros();
113         void primitive_sleep();
114         void primitive_set_slot();
115         void primitive_load_locals();
116         cell clone_object(cell obj_);
117         void primitive_clone();
118
119         // profiler
120         void init_profiler();
121         code_block *compile_profiling_stub(cell word_);
122         void set_profiling(bool profiling);
123         void primitive_profiling();
124
125         // errors
126         void throw_error(cell error, stack_frame *callstack_top);
127         void not_implemented_error();
128         bool in_page(cell fault, cell area, cell area_size, int offset);
129         void memory_protection_error(cell addr, stack_frame *native_stack);
130         void signal_error(int signal, stack_frame *native_stack);
131         void divide_by_zero_error();
132         void fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top);
133         void primitive_call_clear();
134         void primitive_unimplemented();
135         void memory_signal_handler_impl();
136         void misc_signal_handler_impl();
137         void fp_signal_handler_impl();
138         void type_error(cell type, cell tagged);
139         void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *native_stack);
140
141         // bignum
142         int bignum_equal_p(bignum * x, bignum * y);
143         enum bignum_comparison bignum_compare(bignum * x, bignum * y);
144         bignum *bignum_add(bignum * x, bignum * y);
145         bignum *bignum_subtract(bignum * x, bignum * y);
146         bignum *bignum_multiply(bignum * x, bignum * y);
147         void bignum_divide(bignum * numerator, bignum * denominator, bignum * * quotient, bignum * * remainder);
148         bignum *bignum_quotient(bignum * numerator, bignum * denominator);
149         bignum *bignum_remainder(bignum * numerator, bignum * denominator);
150         cell bignum_to_cell(bignum * bignum);
151         fixnum bignum_to_fixnum(bignum * bignum);
152         s64 bignum_to_long_long(bignum * bignum);
153         u64 bignum_to_ulong_long(bignum * bignum);
154         double bignum_to_double(bignum * bignum);
155         bignum *double_to_bignum(double x);
156         int bignum_equal_p_unsigned(bignum * x, bignum * y);
157         enum bignum_comparison bignum_compare_unsigned(bignum * x, bignum * y);
158         bignum *bignum_add_unsigned(bignum * x, bignum * y, int negative_p);
159         bignum *bignum_subtract_unsigned(bignum * x, bignum * y);
160         bignum *bignum_multiply_unsigned(bignum * x, bignum * y, int negative_p);
161         bignum *bignum_multiply_unsigned_small_factor(bignum * x, bignum_digit_type y,int negative_p);
162         void bignum_destructive_add(bignum * bignum, bignum_digit_type n);
163         void bignum_destructive_scale_up(bignum * bignum, bignum_digit_type factor);
164         void bignum_divide_unsigned_large_denominator(bignum * numerator, bignum * denominator,
165                                                       bignum * * quotient, bignum * * remainder, int q_negative_p, int r_negative_p);
166         void bignum_divide_unsigned_normalized(bignum * u, bignum * v, bignum * q);
167         bignum_digit_type bignum_divide_subtract(bignum_digit_type * v_start, bignum_digit_type * v_end,
168                                                  bignum_digit_type guess, bignum_digit_type * u_start);
169         void bignum_divide_unsigned_medium_denominator(bignum * numerator,bignum_digit_type denominator,
170                                                        bignum * * quotient, bignum * * remainder,int q_negative_p, int r_negative_p);
171         void bignum_destructive_normalization(bignum * source, bignum * target, int shift_left);
172         void bignum_destructive_unnormalization(bignum * bignum, int shift_right);
173         bignum_digit_type bignum_digit_divide(bignum_digit_type uh, bignum_digit_type ul,
174                                               bignum_digit_type v, bignum_digit_type * q) /* return value */;
175         bignum_digit_type bignum_digit_divide_subtract(bignum_digit_type v1, bignum_digit_type v2,
176                                                        bignum_digit_type guess, bignum_digit_type * u);
177         void bignum_divide_unsigned_small_denominator(bignum * numerator, bignum_digit_type denominator,
178                                                       bignum * * quotient, bignum * * remainder,int q_negative_p, int r_negative_p);
179         bignum_digit_type bignum_destructive_scale_down(bignum * bignum, bignum_digit_type denominator);
180         bignum * bignum_remainder_unsigned_small_denominator(bignum * n, bignum_digit_type d, int negative_p);
181         bignum *bignum_digit_to_bignum(bignum_digit_type digit, int negative_p);
182         bignum *allot_bignum(bignum_length_type length, int negative_p);
183         bignum * allot_bignum_zeroed(bignum_length_type length, int negative_p);
184         bignum *bignum_shorten_length(bignum * bignum, bignum_length_type length);
185         bignum *bignum_trim(bignum * bignum);
186         bignum *bignum_new_sign(bignum * x, int negative_p);
187         bignum *bignum_maybe_new_sign(bignum * x, int negative_p);
188         void bignum_destructive_copy(bignum * source, bignum * target);
189         bignum *bignum_bitwise_not(bignum * x);
190         bignum *bignum_arithmetic_shift(bignum * arg1, fixnum n);
191         bignum *bignum_bitwise_and(bignum * arg1, bignum * arg2);
192         bignum *bignum_bitwise_ior(bignum * arg1, bignum * arg2);
193         bignum *bignum_bitwise_xor(bignum * arg1, bignum * arg2);
194         bignum *bignum_magnitude_ash(bignum * arg1, fixnum n);
195         bignum *bignum_pospos_bitwise_op(int op, bignum * arg1, bignum * arg2);
196         bignum *bignum_posneg_bitwise_op(int op, bignum * arg1, bignum * arg2);
197         bignum *bignum_negneg_bitwise_op(int op, bignum * arg1, bignum * arg2);
198         void bignum_negate_magnitude(bignum * arg);
199         bignum *bignum_integer_length(bignum * x);
200         int bignum_logbitp(int shift, bignum * arg);
201         int bignum_unsigned_logbitp(int shift, bignum * bignum);
202         bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p);
203
204         //data heap
205         void init_card_decks();
206         data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
207         void clear_cards(old_space *gen);
208         void clear_decks(old_space *gen);
209         void reset_generation(old_space *gen);
210         void set_data_heap(data_heap *data_);
211         void init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_);
212         cell untagged_object_size(object *pointer);
213         cell unaligned_object_size(object *pointer);
214         void primitive_size();
215         cell binary_payload_start(object *pointer);
216         void primitive_data_room();
217         void begin_scan();
218         void end_scan();
219         void primitive_begin_scan();
220         cell next_object();
221         void primitive_next_object();
222         void primitive_end_scan();
223         template<typename Iterator> void each_object(Iterator &iterator);
224         cell find_all_words();
225         cell object_size(cell tagged);
226
227         //write barrier
228         inline card *addr_to_card(cell a)
229         {
230                 return (card*)(((cell)(a) >> card_bits) + cards_offset);
231         }
232
233         inline cell card_to_addr(card *c)
234         {
235                 return ((cell)c - cards_offset) << card_bits;
236         }
237
238         inline card_deck *addr_to_deck(cell a)
239         {
240                 return (card_deck *)(((cell)a >> deck_bits) + decks_offset);
241         }
242
243         inline cell deck_to_addr(card_deck *c)
244         {
245                 return ((cell)c - decks_offset) << deck_bits;
246         }
247
248         inline card *deck_to_card(card_deck *d)
249         {
250                 return (card *)((((cell)d - decks_offset) << (deck_bits - card_bits)) + cards_offset);
251         }
252
253         /* the write barrier must be called any time we are potentially storing a
254            pointer from an older generation to a younger one */
255         inline void write_barrier(object *obj)
256         {
257                 *addr_to_card((cell)obj) = card_mark_mask;
258                 *addr_to_deck((cell)obj) = card_mark_mask;
259         }
260
261         // gc
262         void free_unmarked_code_blocks();
263         void update_dirty_code_blocks(std::set<code_block *> *remembered_set);
264         void collect_nursery();
265         void collect_aging();
266         void collect_to_tenured();
267         void collect_full(cell requested_bytes, bool trace_contexts_p);
268         void record_gc_stats();
269         void garbage_collection(cell gen, bool growing_data_heap, bool trace_contexts_p, cell requested_bytes);
270         void gc();
271         void primitive_gc();
272         void primitive_gc_stats();
273         void clear_gc_stats();
274         void primitive_become();
275         void inline_gc(cell *gc_roots_base, cell gc_roots_size);
276         object *allot_object(header header, cell size);
277         void primitive_clear_gc_stats();
278
279         template<typename Type> Type *allot(cell size)
280         {
281                 return (Type *)allot_object(header(Type::type_number),size);
282         }
283
284         inline void check_data_pointer(object *pointer)
285         {
286         #ifdef FACTOR_DEBUG
287                 if(!(current_gc && current_gc->growing_data_heap))
288                 {
289                         assert((cell)pointer >= data->seg->start
290                                && (cell)pointer < data->seg->end);
291                 }
292         #endif
293         }
294
295         inline void check_tagged_pointer(cell tagged)
296         {
297         #ifdef FACTOR_DEBUG
298                 if(!immediate_p(tagged))
299                 {
300                         object *obj = untag<object>(tagged);
301                         check_data_pointer(obj);
302                         obj->h.hi_tag();
303                 }
304         #endif
305         }
306
307         // generic arrays
308         template<typename Array> Array *allot_array_internal(cell capacity);
309         template<typename Array> bool reallot_array_in_place_p(Array *array, cell capacity);
310         template<typename Array> Array *reallot_array(Array *array_, cell capacity);
311
312         //debug
313         void print_chars(string* str);
314         void print_word(word* word, cell nesting);
315         void print_factor_string(string* str);
316         void print_array(array* array, cell nesting);
317         void print_tuple(tuple *tuple, cell nesting);
318         void print_nested_obj(cell obj, fixnum nesting);
319         void print_obj(cell obj);
320         void print_objects(cell *start, cell *end);
321         void print_datastack();
322         void print_retainstack();
323         void print_callstack();
324         void dump_cell(cell x);
325         void dump_memory(cell from, cell to);
326         void dump_zone(cell gen, zone *z);
327         void dump_generations();
328         void dump_objects(cell type);
329         void find_data_references_step(cell *scan);
330         void find_data_references(cell look_for_);
331         void dump_code_heap();
332         void factorbug();
333         void primitive_die();
334
335         //arrays
336         array *allot_array(cell capacity, cell fill_);
337         void primitive_array();
338         cell allot_array_1(cell obj_);
339         cell allot_array_2(cell v1_, cell v2_);
340         cell allot_array_4(cell v1_, cell v2_, cell v3_, cell v4_);
341         void primitive_resize_array();
342         inline void set_array_nth(array *array, cell slot, cell value);
343
344         //strings
345         cell string_nth(string* str, cell index);
346         void set_string_nth_fast(string *str, cell index, cell ch);
347         void set_string_nth_slow(string *str_, cell index, cell ch);
348         void set_string_nth(string *str, cell index, cell ch);
349         string *allot_string_internal(cell capacity);
350         void fill_string(string *str_, cell start, cell capacity, cell fill);
351         string *allot_string(cell capacity, cell fill);
352         void primitive_string();
353         bool reallot_string_in_place_p(string *str, cell capacity);
354         string* reallot_string(string *str_, cell capacity);
355         void primitive_resize_string();
356         void primitive_string_nth();
357         void primitive_set_string_nth_fast();
358         void primitive_set_string_nth_slow();
359
360         //booleans
361         void box_boolean(bool value);
362         bool to_boolean(cell value);
363         inline cell tag_boolean(cell untagged);
364
365         //byte arrays
366         byte_array *allot_byte_array(cell size);
367         void primitive_byte_array();
368         void primitive_uninitialized_byte_array();
369         void primitive_resize_byte_array();
370
371         //tuples
372         tuple *allot_tuple(cell layout_);
373         void primitive_tuple();
374         void primitive_tuple_boa();
375
376         //words
377         word *allot_word(cell name_, cell vocab_, cell hashcode_);
378         void primitive_word();
379         void primitive_word_xt();
380         void update_word_xt(cell w_);
381         void primitive_optimized_p();
382         void primitive_wrapper();
383
384         //math
385         void primitive_bignum_to_fixnum();
386         void primitive_float_to_fixnum();
387         void primitive_fixnum_divint();
388         void primitive_fixnum_divmod();
389         bignum *fixnum_to_bignum(fixnum);
390         bignum *cell_to_bignum(cell);
391         bignum *long_long_to_bignum(s64 n);
392         bignum *ulong_long_to_bignum(u64 n);
393         inline fixnum sign_mask(fixnum x);
394         inline fixnum branchless_max(fixnum x, fixnum y);
395         inline fixnum branchless_abs(fixnum x);
396         void primitive_fixnum_shift();
397         void primitive_fixnum_to_bignum();
398         void primitive_float_to_bignum();
399         void primitive_bignum_eq();
400         void primitive_bignum_add();
401         void primitive_bignum_subtract();
402         void primitive_bignum_multiply();
403         void primitive_bignum_divint();
404         void primitive_bignum_divmod();
405         void primitive_bignum_mod();
406         void primitive_bignum_and();
407         void primitive_bignum_or();
408         void primitive_bignum_xor();
409         void primitive_bignum_shift();
410         void primitive_bignum_less();
411         void primitive_bignum_lesseq();
412         void primitive_bignum_greater();
413         void primitive_bignum_greatereq();
414         void primitive_bignum_not();
415         void primitive_bignum_bitp();
416         void primitive_bignum_log2();
417         unsigned int bignum_producer(unsigned int digit);
418         void primitive_byte_array_to_bignum();
419         cell unbox_array_size();
420         void primitive_fixnum_to_float();
421         void primitive_bignum_to_float();
422         void primitive_str_to_float();
423         void primitive_float_to_str();
424         void primitive_float_eq();
425         void primitive_float_add();
426         void primitive_float_subtract();
427         void primitive_float_multiply();
428         void primitive_float_divfloat();
429         void primitive_float_mod();
430         void primitive_float_less();
431         void primitive_float_lesseq();
432         void primitive_float_greater();
433         void primitive_float_greatereq();
434         void primitive_float_bits();
435         void primitive_bits_float();
436         void primitive_double_bits();
437         void primitive_bits_double();
438         fixnum to_fixnum(cell tagged);
439         cell to_cell(cell tagged);
440         void box_signed_1(s8 n);
441         void box_unsigned_1(u8 n);
442         void box_signed_2(s16 n);
443         void box_unsigned_2(u16 n);
444         void box_signed_4(s32 n);
445         void box_unsigned_4(u32 n);
446         void box_signed_cell(fixnum integer);
447         void box_unsigned_cell(cell cell);
448         void box_signed_8(s64 n);
449         s64 to_signed_8(cell obj);
450         void box_unsigned_8(u64 n);
451         u64 to_unsigned_8(cell obj);
452         void box_float(float flo);
453         float to_float(cell value);
454         void box_double(double flo);
455         double to_double(cell value);
456         inline void overflow_fixnum_add(fixnum x, fixnum y);
457         inline void overflow_fixnum_subtract(fixnum x, fixnum y);
458         inline void overflow_fixnum_multiply(fixnum x, fixnum y);
459         inline cell allot_integer(fixnum x);
460         inline cell allot_cell(cell x);
461         inline cell allot_float(double n);
462         inline bignum *float_to_bignum(cell tagged);
463         inline double bignum_to_float(cell tagged);
464         inline double untag_float(cell tagged);
465         inline double untag_float_check(cell tagged);
466         inline fixnum float_to_fixnum(cell tagged);
467         inline double fixnum_to_float(cell tagged);
468         template<typename Type> Type *untag_check(cell value);
469         template<typename Type> Type *untag(cell value);
470
471         //io
472         void init_c_io();
473         void io_error();
474         void primitive_fopen();
475         void primitive_fgetc();
476         void primitive_fread();
477         void primitive_fputc();
478         void primitive_fwrite();
479         void primitive_ftell();
480         void primitive_fseek();
481         void primitive_fflush();
482         void primitive_fclose();
483
484         //code_block
485         relocation_type relocation_type_of(relocation_entry r);
486         relocation_class relocation_class_of(relocation_entry r);
487         cell relocation_offset_of(relocation_entry r);
488         void flush_icache_for(code_block *block);
489         int number_of_parameters(relocation_type type);
490         void *object_xt(cell obj);
491         void *xt_pic(word *w, cell tagged_quot);
492         void *word_xt_pic(word *w);
493         void *word_xt_pic_tail(word *w);
494         void undefined_symbol();
495         void *get_rel_symbol(array *literals, cell index);
496         cell compute_relocation(relocation_entry rel, cell index, code_block *compiled);
497         template<typename Iterator> void iterate_relocations(code_block *compiled, Iterator &iter);
498         void store_address_2_2(cell *ptr, cell value);
499         void store_address_masked(cell *ptr, fixnum value, cell mask, fixnum shift);
500         void store_address_in_code_block(cell klass, cell offset, fixnum absolute_value);
501         void update_literal_references(code_block *compiled);
502         void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled);
503         void update_word_references(code_block *compiled);
504         void check_code_address(cell address);
505         void relocate_code_block(code_block *compiled);
506         void fixup_labels(array *labels, code_block *compiled);
507         code_block *allot_code_block(cell size, cell type);
508         code_block *add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
509
510         //code heap
511         inline void check_code_pointer(cell ptr)
512         {
513         #ifdef FACTOR_DEBUG
514                 assert(in_code_heap_p(ptr));
515         #endif
516         }
517
518         void init_code_heap(cell size);
519         bool in_code_heap_p(cell ptr);
520         void jit_compile_word(cell word_, cell def_, bool relocate);
521         void update_code_heap_words();
522         void primitive_modify_code_heap();
523         void primitive_code_room();
524         code_block *forward_xt(code_block *compiled);
525         void forward_object_xts();
526         void fixup_object_xts();
527         void compact_code_heap();
528         void primitive_strip_stack_traces();
529
530         /* Apply a function to every code block */
531         template<typename Iterator> void iterate_code_heap(Iterator &iter)
532         {
533                 heap_block *scan = code->first_block();
534
535                 while(scan)
536                 {
537                         if(scan->type() != FREE_BLOCK_TYPE)
538                                 iter((code_block *)scan);
539                         scan = code->next_block(scan);
540                 }
541         }
542
543         //image
544         void init_objects(image_header *h);
545         void load_data_heap(FILE *file, image_header *h, vm_parameters *p);
546         void load_code_heap(FILE *file, image_header *h, vm_parameters *p);
547         bool save_image(const vm_char *filename);
548         void primitive_save_image();
549         void primitive_save_image_and_exit();
550         void data_fixup(cell *handle, cell data_relocation_base);
551         template<typename Type> void code_fixup(Type **handle, cell code_relocation_base);
552         void fixup_word(word *word, cell code_relocation_base);
553         void fixup_quotation(quotation *quot, cell code_relocation_base);
554         void fixup_alien(alien *d);
555         void fixup_callstack_object(callstack *stack, cell code_relocation_base);
556         void relocate_object(object *object, cell data_relocation_base, cell code_relocation_base);
557         void relocate_data(cell data_relocation_base, cell code_relocation_base);
558         void fixup_code_block(code_block *compiled, cell data_relocation_base);
559         void relocate_code(cell data_relocation_base);
560         void load_image(vm_parameters *p);
561
562         //callstack
563         template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
564         void check_frame(stack_frame *frame);
565         callstack *allot_callstack(cell size);
566         stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom);
567         stack_frame *capture_start();
568         void primitive_callstack();
569         void primitive_set_callstack();
570         code_block *frame_code(stack_frame *frame);
571         cell frame_type(stack_frame *frame);
572         cell frame_executing(stack_frame *frame);
573         stack_frame *frame_successor(stack_frame *frame);
574         cell frame_scan(stack_frame *frame);
575         void primitive_callstack_to_array();
576         stack_frame *innermost_stack_frame(callstack *stack);
577         stack_frame *innermost_stack_frame_quot(callstack *callstack);
578         void primitive_innermost_stack_frame_executing();
579         void primitive_innermost_stack_frame_scan();
580         void primitive_set_innermost_stack_frame_quot();
581         void save_callstack_bottom(stack_frame *callstack_bottom);
582         template<typename Iterator> void iterate_callstack(cell top, cell bottom, Iterator &iterator);
583
584         /* Every object has a regular representation in the runtime, which makes GC
585         much simpler. Every slot of the object until binary_payload_start is a pointer
586         to some other object. */
587         template<typename Iterator> void do_slots(cell obj, Iterator &iter)
588         {
589                 cell scan = obj;
590                 cell payload_start = binary_payload_start((object *)obj);
591                 cell end = obj + payload_start;
592
593                 scan += sizeof(cell);
594
595                 while(scan < end)
596                 {
597                         iter((cell *)scan);
598                         scan += sizeof(cell);
599                 }
600         }
601
602         //alien
603         char *pinned_alien_offset(cell obj);
604         cell allot_alien(cell delegate_, cell displacement);
605         void primitive_displaced_alien();
606         void primitive_alien_address();
607         void *alien_pointer();
608         void primitive_dlopen();
609         void primitive_dlsym();
610         void primitive_dlclose();
611         void primitive_dll_validp();
612         void primitive_vm_ptr();
613         char *alien_offset(cell obj);
614         char *unbox_alien();
615         void box_alien(void *ptr);
616         void to_value_struct(cell src, void *dest, cell size);
617         void box_value_struct(void *src, cell size);
618         void box_small_struct(cell x, cell y, cell size);
619         void box_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size);
620
621         //quotations
622         void primitive_jit_compile();
623         void primitive_array_to_quotation();
624         void primitive_quotation_xt();
625         void set_quot_xt(quotation *quot, code_block *code);
626         void jit_compile(cell quot_, bool relocating);
627         void compile_all_words();
628         fixnum quot_code_offset_to_scan(cell quot_, cell offset);
629         cell lazy_jit_compile_impl(cell quot_, stack_frame *stack);
630         void primitive_quot_compiled_p();
631
632         //dispatch
633         cell search_lookup_alist(cell table, cell klass);
634         cell search_lookup_hash(cell table, cell klass, cell hashcode);
635         cell nth_superclass(tuple_layout *layout, fixnum echelon);
636         cell nth_hashcode(tuple_layout *layout, fixnum echelon);
637         cell lookup_tuple_method(cell obj, cell methods);
638         cell lookup_hi_tag_method(cell obj, cell methods);
639         cell lookup_hairy_method(cell obj, cell methods);
640         cell lookup_method(cell obj, cell methods);
641         void primitive_lookup_method();
642         cell object_class(cell obj);
643         cell method_cache_hashcode(cell klass, array *array);
644         void update_method_cache(cell cache, cell klass, cell method);
645         void primitive_mega_cache_miss();
646         void primitive_reset_dispatch_stats();
647         void primitive_dispatch_stats();
648
649         //inline cache
650         void init_inline_caching(int max_size);
651         void deallocate_inline_cache(cell return_address);
652         cell determine_inline_cache_type(array *cache_entries);
653         void update_pic_count(cell type);
654         code_block *compile_inline_cache(fixnum index,cell generic_word_,cell methods_,cell cache_entries_,bool tail_call_p);
655         void *megamorphic_call_stub(cell generic_word);
656         cell inline_cache_size(cell cache_entries);
657         cell add_inline_cache_entry(cell cache_entries_, cell klass_, cell method_);
658         void update_pic_transitions(cell pic_size);
659         void *inline_cache_miss(cell return_address);
660         void primitive_reset_inline_cache_stats();
661         void primitive_inline_cache_stats();
662
663         //factor
664         void default_parameters(vm_parameters *p);
665         bool factor_arg(const vm_char* str, const vm_char* arg, cell* value);
666         void init_parameters_from_args(vm_parameters *p, int argc, vm_char **argv);
667         void do_stage1_init();
668         void init_factor(vm_parameters *p);
669         void pass_args_to_factor(int argc, vm_char **argv);
670         void start_factor(vm_parameters *p);
671         void start_embedded_factor(vm_parameters *p);
672         void start_standalone_factor(int argc, vm_char **argv);
673         char *factor_eval_string(char *string);
674         void factor_eval_free(char *result);
675         void factor_yield();
676         void factor_sleep(long us);
677
678         // os-*
679         void primitive_existsp();
680         void init_ffi();
681         void ffi_dlopen(dll *dll);
682         void *ffi_dlsym(dll *dll, symbol_char *symbol);
683         void ffi_dlclose(dll *dll);
684         void c_to_factor_toplevel(cell quot);
685
686         // os-windows
687   #if defined(WINDOWS)
688         void sleep_micros(u64 usec);
689         const vm_char *vm_executable_path();
690         const vm_char *default_image_path();
691         void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length);
692         bool windows_stat(vm_char *path);
693
694    #if defined(WINNT)
695         void open_console();
696         LONG exception_handler(PEXCEPTION_POINTERS pe);
697         // next method here:
698    #endif
699   #else  // UNIX
700         void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap);
701         void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap);
702         void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap);
703         stack_frame *uap_stack_pointer(void *uap);
704
705   #endif
706
707   #ifdef __APPLE__
708         void call_fault_handler(exception_type_t exception, exception_data_type_t code, MACH_EXC_STATE_TYPE *exc_state, MACH_THREAD_STATE_TYPE *thread_state, MACH_FLOAT_STATE_TYPE *float_state);
709   #endif
710
711         factor_vm();
712
713 };
714
715 #ifndef FACTOR_REENTRANT
716         #define FACTOR_SINGLE_THREADED_TESTING
717 #endif
718
719 #ifdef FACTOR_SINGLE_THREADED_SINGLETON
720 /* calls are dispatched using the singleton vm ptr */
721         extern factor_vm *vm;
722         #define PRIMITIVE_GETVM() vm
723         #define PRIMITIVE_OVERFLOW_GETVM() vm
724         #define VM_PTR vm
725         #define ASSERTVM()
726         #define SIGNAL_VM_PTR() vm
727 #endif
728
729 #ifdef FACTOR_SINGLE_THREADED_TESTING
730 /* calls are dispatched as per multithreaded, but checked against singleton */
731         extern factor_vm *vm;
732         #define ASSERTVM() assert(vm==myvm)
733         #define PRIMITIVE_GETVM() ((factor_vm*)myvm)
734         #define PRIMITIVE_OVERFLOW_GETVM() ASSERTVM(); myvm
735         #define VM_PTR myvm
736         #define SIGNAL_VM_PTR() tls_vm()
737 #endif
738
739 #ifdef FACTOR_REENTRANT_TLS
740 /* uses thread local storage to obtain vm ptr */
741         #define PRIMITIVE_GETVM() tls_vm()
742         #define PRIMITIVE_OVERFLOW_GETVM() tls_vm()
743         #define VM_PTR tls_vm()
744         #define ASSERTVM()
745         #define SIGNAL_VM_PTR() tls_vm()
746 #endif
747
748 #ifdef FACTOR_REENTRANT
749         #define PRIMITIVE_GETVM() ((factor_vm*)myvm)
750         #define PRIMITIVE_OVERFLOW_GETVM() ((factor_vm*)myvm)
751         #define VM_PTR myvm
752         #define ASSERTVM()
753         #define SIGNAL_VM_PTR() tls_vm()
754 #endif
755
756 extern unordered_map<THREADHANDLE, factor_vm *> thread_vms;
757
758 }