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