код:
void f() {
g();
}
void g() {}
Я хочу транслировать в нативный код только функцию f(). Соответственно,
внутри у меня будет CALL g, который не имеет адреса перехода. Когда я запущу на
исполнение данный код, у меня возникнет ошибка.
Вопрос по конкретике: как в данном случае организовать возврат в интерпретатор?
Более общий вопрос: возможно ли при реализации jit'а обойтись без собственного
ассемблирования и использовать штатный as?
Есть ли какая-нибудь литература где можно почитать про подобные нюансы?
вам нужно каким-то образом передать объект вызываемого метода, через регистр или стек
Но ведь объекта нет, это байткод интерпретатора
ну есть же каая-то абстракция, описывающая f()
as это ассемблер поставляемый с операционной системой, на разных системах могут быть разные ассемблеры, либо их вообще может не быть. Лучше не полагаться на системный ассемблер и использовать библиотеки для генерации машинного кода вроде LLVM, Cranelift, libjit
сделайте метод-мост return_type run_bytecode_method(int index, context)
Да, наверное самый простой (и пока что единственный приходящий в голову) способ. А вообще, реальные jit'ы часто транслируют такие случаи? Т.е. чтобы подменять вызов на метод-мост и делать возврат в интерпретатор по середине? Выглядит как довольно накладное дело
при вызове i -> c и c->i всегда придется что-то делать, чтобы было ненакладно обычно рано или поздно джитуется и второй метод
Это понятно что в реальных проектах полагаться нельзя, но я пока для себя эксперименты делаю, и хочется часть вплоть до целевого ассемблера включительно сделать самому, а вот перевод в бинарный вид передать во вне )
Он заджитируется, это понятно. Скорее вопрос был в том как в реальных проектах дело обстоит. Т.е. интуитивно, нам было бы проще заджитировать сразу и f() и g() и вообще не париться с функциями мостами. Но возможно существуют случаи когда без них обойтись невозможно, и механизм необходимо сделать в любом случае (наверняка существуют)
в jvm работает так: есть специальный стабик, который вставляет jit и он выполняет первоначальное разрешение (resolve), а также адаптеры i2c и c2i resolve смотрит, что вызывается и вычисляет либо ep джитованного метода, либо ep адаптер с2i и потчит call site на нужный ep
as обычно превращает ассемблерный код в объектный файл с машинным кодом. Чтобы этот файл потом загрузить в уже исполняющийся рантайм языка с jit компилятором нужно будет парсить объектный файл и реаллоцировать код что сложно
Альтернативный вариант: запросить у as не объектный файл, а .dll и затем загрузить библиотеку через LoadLibrary, такой способ проще но выглядит очень непрактично, лучше сразу подключить библиотеку вроде LLVM и не мучаться с as
Обсуждают сегодня