PageRenderTime 20ms CodeModel.GetById 9ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/callbacks.hpp

http://github.com/abeaumont/factor
C++ Header | 70 lines | 37 code | 11 blank | 22 comment | 0 complexity | 5414bf2ea352d7a3acfcc084b9d53f2b MD5 | raw file
 1namespace factor
 2{
 3
 4/* The callback heap is used to store the machine code that alien-callbacks
 5actually jump to when C code invokes them.
 6
 7The callback heap has entries that look like code_blocks from the code heap, but
 8callback heap entries are allocated contiguously, never deallocated, and all
 9fields but the owner are set to false_object. The owner points to the callback
10bottom word, whose entry point is the callback body itself, generated by the
11optimizing compiler. The machine code that follows a callback stub consists of a
12single CALLBACK_STUB machine code template, which performs a jump to a "far"
13address (on PowerPC and x86-64, its loaded into a register first).
14
15GC updates the CALLBACK_STUB code if the code block of the callback bottom word
16is ever moved. The callback stub itself won't move, though, and is never
17deallocated. This means that the callback stub itself is a stable function
18pointer that C code can hold on to until the associated Factor VM exits.
19
20Since callback stubs are GC roots, and are never deallocated, the associated
21callback code in the code heap is also never deallocated.
22
23The callback heap is not saved in the image. Running GC in a new session after
24saving the image will deallocate any code heap entries that were only reachable
25from the callback heap in the previous session when the image was saved. */
26
27struct 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}