我编写了一个 Brainfuck 实现(C++),其工作原理如下:

  1. 读取输入 Brainfuck 文件
  2. 进行琐碎的优化
  3. 将 Brainfuck 转换为 VM 的机器代码
  4. 在VM中执行此机器代码

这相当快,但瓶颈现在出现在虚拟机上。它是用 C++ 编写的,读取令牌、执行操作(如果您了解 Brainfuck,那么这些操作并不多)等等。

我想要做的是剥离虚拟机并动态生成本机机器代码(基本上是一个 JIT 编译器)。这很容易实现 20 倍的加速。

这意味着步骤 3 被 JIT 编译器取代,步骤 4 被执行生成的机器代码取代。

我真的不知道从哪里开始,所以我有几个问题:

  1. 这是如何工作的,生成的机器代码如何执行?
  2. 是否有用于生成本机机器代码的 C++ 库?
有帮助吗?

解决方案

  1. 生成的机器代码只是 jmp-ed 至 或 call-ed 像平常一样的功能。有时,它还需要禁用内存上包含生成代码的不执行标志(NX 位)。在 Linux 中,这是通过以下命令完成的 mprotect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC.) 在 Windows 中,NX 称为 DEP。

  2. 有一些...例如。 http://www.gnu.org/software/lightning/ - GNU Lightning(通用)和 https://developer.mozilla.org/En/Nanojit - Nanojit,用于 Firefox JavaScript JIT 引擎。更强大和现代的JIT是LLVM,你只需要将BF代码翻译成LLVM IR,然后LLVM就可以为许多平台进行优化和代码生成,或者在具有JIT功能的解释器(虚拟机)上运行LLVM IR。有一篇关于 BF 和 LLVM 的文章,其中包含 BF 的完整 LLVM JIT 编译器 http://www.remcobloemen.nl/2010/02/brainfuck-using-llvm/

另一个BF +LLVM编译器在这里,在LLVM的svn中: https://llvm.org/svn/llvm-project/llvm/trunk/examples/BrainF/BrainF.cpp

其他提示

llvm 是一个完整的c ++库(或图书馆集),用于生成来自中间形式的本机代码,完成文档和示例,并用于生产抖动。

(它还具有使用该框架的C / C ++编译器 - 但框架本身可用于其他语言)。

gnu lightning 是一组宏,它可以为几个不同的架构生成本机代码。您需要一个稳定的对汇编代码的理解,因为您的步骤3将涉及使用闪电宏将机器代码直接发出到缓冲区中,以后将稍后执行。

This might be late but for the sake of help to any other i am posting this answer.

JIT compiler has all the steps that AOT compiler has. The main difference is that AOT compiler outputs the machine dependent code to an executable file like exe etc while the JIT compiler loads the machine dependent code into the memory at run time (hence the performance overhead because every time it needs to recompile and load).

How a JIT compiler loads the machine code into the memory at runtime ?

i will not teach you about the machine code because i assume you already know about it,

for eg. assembly code

mov    rax,0x1

is translated to

48 c7 c0 01 00 00 00

you dynamically generate translated code and save it into a vector like this (this is a C vector)

vector machineCode{
   0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 
}

then you copy this vector into the memory, for this you need to know the memory size required by this code, which u can get by machinecode.size() and keep in mind the page size.

to copy this vector into the memory u need to call mmap function in C. set the pointer to the beginning of your code and call it. u are good to go.

Sorry if anything is not clear, u can always check out this post for the simplicity https://solarianprogrammer.com/2018/01/10/writing-minimal-x86-64-jit-compiler-cpp/ https://github.com/spencertipping/jit-tutorial

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top