我想为我编写的玩具语言处理器编写一个非常小的概念验证JIT编译器(纯粹是学术性的),但我在设计的中间高度上遇到了一些麻烦.从概念上讲,我熟悉JIT的工作原理 - 您将字节码编译成(机器或汇编?)代码来运行.然而,在螺栓和螺栓水平上,我并不是在想你实际上是怎么做的.
我的(非常"新手")下意识的反应,因为我没有第一个线索从哪里开始,将尝试类似以下内容:
这甚至接近正确的算法吗?我已经尝试过阅读我知道有JIT编译器学习的不同项目(比如V8),但是由于它们的大小,这些代码库很难被消费,而我几乎不知道从哪里开始寻找.
鉴于函数原型及其在内存中的地址的知识,是否可以从另一个进程或一些只知道原型和内存地址的代码调用此函数?如果可能,如何在代码中处理返回的类型?
通过 gcc 文档,我偶然发现了内置函数__builtin___clear_cache。
— 内置函数:void __builtin___clear_cache (char *begin, char *end) 该函数用于为begin inclusive 和end exclusive 之间的内存区域刷新处理器的指令缓存。某些目标要求在修改包含代码的内存后刷新指令缓存,以获得确定性行为。
如果目标不需要指令缓存刷新,则 __builtin___clear_cache 无效。否则,要么内联发出指令以清除指令缓存,要么调用 libgcc 中的 __clear_cache 函数。
我觉得这很有趣,但令人惊讶。在很多情况下,当前堆栈的大量指令存储在 L1 缓存(指令缓存)中。因此,乍一看,这个内置函数可能会显着破坏我们程序的流程,因为它会清除堆栈中的下一条指令。
此指令是否还会重新填充 L1 缓存中的堆栈部分?
这似乎不太可能。如果没有,那么我想用户有责任使用权利begin和end参数,以免破坏我们的过程。在实践中,如何找到正确begin和end使用的东西?
我理解JIT编译的工作原理(在阅读了这个SO问题之后的资源).但是,我仍然想知道它是如何在运行时实际执行机器代码的?
我没有深入的操作系统或编译器优化背景,也没有直接使用机器代码做任何事情,但我开始探索它.我已经开始在汇编中玩,看看像NASM这样的东西可以把你的汇编代码编译成机器代码(可执行文件),然后你可以从命令行"调用"它./my-executable.
但是JIT编译器在运行时实际上是如何做到的呢?是将流机器代码转换为stdin还是其他东西,或者它是如何工作的?如果你可以提供一个例子或一些伪代码来说明某些程序集(或那些沿着这些行的东西,而不是像C那样高的程度)可能看起来可以展示基本流程,那也是惊人的.
I'm developing an online judge system for programming contests like LeetCode, Codeforces, etc. As for most programming contests, inline assembler is not allowed in C/C++, so I would like to add the same restriction to my system.
I would like to let GCC and G++ produce an error when compiling a C/C++ program containing inline assembler, so that any code containing inline assembler will result in compilation error.
Is there a way to achieve that? Should I pass some command …
在c中是否有办法将字符串转换为命令?例如:
void x(string n){
//do something
}
void y(int n){
//do something
}
void z(int n){
//do something
}
stringForConvert="z(10);y(2);x(\"Its cool\");";
mysteryCommand(stringForConvert);
Run Code Online (Sandbox Code Playgroud)
请注意,我没有奢侈的写入另一个文件并进行编译.