Hello,
I am using gnu lightning to make a compiler for register machines (each register is a 64bit word, say). I would like to have many of these register machines working simultaneously, and throughout time I am interested in adding new register machines to memory (perhaps many thousands of them), destroying & deallocating old register machines (again, by the thousands).
First thing I noticed was that lightning allocates a full page (4k of memory, or whatever) whenever it wants to emit a function, and that it had no way to erase a given piece of code from memory. This wouldn't do, so I decided to try and do the following:
Use lightning to generate the code;
find the code length by surrounding the code by start = jit_node, and end = jit_note, and then do:
length = jit_address(start) - jit_address(end);
Allocate as large block of memory as I need, with read, write and exec permissions;
then copy the code by memcpy(_my_memory_block_code_start, jit_address(start), length);
then I cast _my_memory_block_code_start as a function, and call it.
void (*entryPoint)(void *code_address, void *registers_address); entryPoint = _my_memory_block_code_start;
entryPoint(_my_memory_block_code_start, _my_memory_block_registers_start);
I call it with a pointer somewhere else in the same block I allocated earlier, and the machine will use that same block to store the registers;
Now the advantage of this is when I want to delete some register machine, I can simply erase it and reuse the space.
Of course, the compiled code needs to have to access to the registers of the machine, and it needs to be able to jump around.
I could have solved the register access by allocating the register space before jit_emit'ing the code, but how was I going to do the jumping around?
I was hoping that the following would work:
whenever the register machine wanted to jump to some jit label, call it LABEL; what I would do is to store in one of the registers the value: jit_address(LABEL) - jit_address(start),
i.e., I store somewhere the difference between where the code starts and where the label is.
Then, instead of having an instruction
jmpi <address of LABEL>,
I would have
R1 = code_address + <value of register holding jit_address(LABEL) - jit_address(start)>
jmpr R1
I wasn't sure this was going to work, but my first few tests seemed to do OK. And then I came up with a thoroughly weird bug.