]> gitweb.factorcode.org Git - factor.git/blob - vm/callbacks.hpp
VM: Remove unnecessary explicit keywords
[factor.git] / vm / callbacks.hpp
1 namespace factor {
2
3 /* The callback heap is used to store the machine code that alien-callbacks
4 actually jump to when C code invokes them.
5
6 The callback heap has entries that look like code_blocks from the code heap, but
7 callback heap entries are allocated contiguously, never deallocated, and all
8 fields but the owner are set to false_object. The owner points to the callback
9 bottom word, whose entry point is the callback body itself, generated by the
10 optimizing compiler. The machine code that follows a callback stub consists of a
11 single CALLBACK_STUB machine code template, which performs a jump to a "far"
12 address (on PowerPC and x86-64, its loaded into a register first).
13
14 GC updates the CALLBACK_STUB code if the code block of the callback bottom word
15 is ever moved. The callback stub itself won't move, though, and is never
16 deallocated. This means that the callback stub itself is a stable function
17 pointer that C code can hold on to until the associated Factor VM exits.
18
19 Since callback stubs are GC roots, and are never deallocated, the associated
20 callback code in the code heap is also never deallocated.
21
22 The callback heap is not saved in the image. Running GC in a new session after
23 saving the image will deallocate any code heap entries that were only reachable
24 from the callback heap in the previous session when the image was saved. */
25
26 struct callback_heap {
27   segment* seg;
28   cell here;
29   factor_vm* parent;
30
31   callback_heap(cell size, factor_vm* parent);
32   ~callback_heap();
33
34   void* callback_entry_point(code_block* stub) {
35     word* w = (word*)UNTAG(stub->owner);
36     return w->entry_point;
37   }
38
39   bool setup_seh_p();
40   bool return_takes_param_p();
41   instruction_operand callback_operand(code_block* stub, cell index);
42   void store_callback_operand(code_block* stub, cell index);
43   void store_callback_operand(code_block* stub, cell index, cell value);
44
45   void update(code_block* stub);
46
47   code_block* add(cell owner, cell return_rewind);
48
49   void update();
50
51   code_block* next(code_block* stub) {
52     return (code_block*)((cell) stub + stub->size());
53   }
54
55   template <typename Iterator> void each_callback(Iterator& iter) {
56     code_block* scan = (code_block*)seg->start;
57     code_block* end = (code_block*)here;
58     while (scan < end) {
59       iter(scan);
60       scan = next(scan);
61     }
62   }
63 };
64
65 }