Я написал интерпретатор байт-кода для простой виртуальной машины на основе стека в (GNU) C. Все инструкции VM реализованы в виде кода между метками. Большинство инструкций не используют встроенные аргументы, поскольку они просто выталкивают их из стека виртуальных машин (например, add
извлекает два числа a
, b
из стека и возвращает a+b
обратно).
IЯ думал, что JIT будет так же просто, как идентифицировать основные блоки в байт-коде и генерировать «динамические суперинструкции», просто соединяя реализации инструкций, memcpy
вставляя между метками в буфер, помеченный как исполняемый, используя mmap
/ mprotect
. Это работает для всех инструкций, кроме инструкции push b
, которая помещает следующий байт потока байт-кода в стек VM (например, push 17
).
Существует ли какой-либо, по крайней мере, несколько переносимый способ, которым я могу реализоватьинструкции, которые используют аргументы аналогичным образом, либо «вставляя» аргументы в каждый экземпляр инструкции push
, которая получает memcpy
(таким образом, имитируя замыкания во время выполнения (?)), либо, по крайней мере, каким-то образом доступ к ПК (хотя любое упоминание о ПК, вероятно, изначально непереносимо) работающего экземпляра с использованием некоторого варианта setjmp / longjmp, который позволяет мне прочитать значение ПК?
РЕДАКТИРОВАТЬ: ПК потенциально может быть полезен при выполнениичто-то вроде следующего в псевдо-C (???)
char arg;
char args[] = {1, 2, 3};
push:
uintptr_t pc = get_pc();
arg = args[some_clever_hash(pc)];
stack.push(arg);
Может быть, что-то вроде этого будет более реалистичным?:
char arg;
char args[] = {1, 2, 3};
push:
setarg();
stack.push(arg);
void setarg(void)
{
uintptr_t pc = get_pc_of_caller();
arg = args[some_clever_hash(pc)];
}