/vm/callbacks.hpp
http://github.com/abeaumont/factor · C++ Header · 70 lines · 37 code · 11 blank · 22 comment · 1 complexity · 5414bf2ea352d7a3acfcc084b9d53f2b MD5 · raw file
- namespace factor
- {
- /* The callback heap is used to store the machine code that alien-callbacks
- actually jump to when C code invokes them.
- The callback heap has entries that look like code_blocks from the code heap, but
- callback heap entries are allocated contiguously, never deallocated, and all
- fields but the owner are set to false_object. The owner points to the callback
- bottom word, whose entry point is the callback body itself, generated by the
- optimizing compiler. The machine code that follows a callback stub consists of a
- single CALLBACK_STUB machine code template, which performs a jump to a "far"
- address (on PowerPC and x86-64, its loaded into a register first).
- GC updates the CALLBACK_STUB code if the code block of the callback bottom word
- is ever moved. The callback stub itself won't move, though, and is never
- deallocated. This means that the callback stub itself is a stable function
- pointer that C code can hold on to until the associated Factor VM exits.
- Since callback stubs are GC roots, and are never deallocated, the associated
- callback code in the code heap is also never deallocated.
- The callback heap is not saved in the image. Running GC in a new session after
- saving the image will deallocate any code heap entries that were only reachable
- from the callback heap in the previous session when the image was saved. */
- struct callback_heap {
- segment *seg;
- cell here;
- factor_vm *parent;
- explicit callback_heap(cell size, factor_vm *parent);
- ~callback_heap();
- void *callback_entry_point(code_block *stub)
- {
- word *w = (word *)UNTAG(stub->owner);
- return w->entry_point;
- }
- bool setup_seh_p();
- bool return_takes_param_p();
- instruction_operand callback_operand(code_block *stub, cell index);
- void store_callback_operand(code_block *stub, cell index);
- void store_callback_operand(code_block *stub, cell index, cell value);
- void update(code_block *stub);
- code_block *add(cell owner, cell return_rewind);
- void update();
- code_block *next(code_block *stub)
- {
- return (code_block *)((cell)stub + stub->size());
- }
- template<typename Iterator> void each_callback(Iterator &iter)
- {
- code_block *scan = (code_block *)seg->start;
- code_block *end = (code_block *)here;
- while(scan < end)
- {
- iter(scan);
- scan = next(scan);
- }
- }
- };
- }