我正在实现一个简单的 VM,目前我正在使用运行时算法来计算单个程序对象地址作为基指针的偏移量。
我今天就这个主题问了几个问题,但我似乎无处可去。
我从问题一中学到了一些东西—— 对象和结构成员访问以及地址偏移量计算——我了解到现代处理器具有虚拟寻址功能,允许计算内存偏移量而无需任何额外的算术周期。
从问题二开始 -在 C/C++ 编译期间地址偏移是否已解决?- 我了解到手动进行偏移时无法保证会发生这种情况。
现在应该很清楚,我想要实现的是利用硬件的虚拟内存寻址特性并从运行时卸载这些特性。
我正在使用 GCC,至于平台 - 我正在 Windows 中的 x86 上进行开发,但由于它是一个 VM,我希望它能够在 GCC 支持的所有平台上有效地运行。
因此,欢迎提供有关该主题的任何信息,并将不胜感激。
提前致谢!
编辑:关于我的程序代码生成的一些概述 - 在设计阶段,程序被构建为树层次结构,然后递归序列化为一个连续的内存块,以及索引对象并计算它们从程序内存块开始的偏移量.
编辑2:这是VM的一些伪代码:
switch *instruction
case 1: call_fn1(*(instruction+1)); instruction += (1+sizeof(parameter1)); break;
case 2: call_fn2(*(instruction+1), *(instruction+1+sizeof(parameter1));
instruction += (1+sizeof(parameter1)+sizeof(parameter2); break;
case 3: instruction += *(instruction+1); break;
情况 1 是一个接受一个参数的函数,该参数在指令之后立即找到,因此它作为指令的 1 个字节的偏移量传递。指令指针递增 1 + 第一个参数的大小以查找下一条指令。
情况 2 是一个接受两个参数的函数,和之前一样,第一个参数作为 1 字节偏移量传递,第二个参数作为 1 字节偏移量加上第一个参数的大小传递。指令指针然后增加指令的大小加上两个参数的大小。
情况 3 是 goto 语句,指令指针增加一个偏移量,该偏移量紧跟 goto 指令。
编辑3:据我了解,操作系统将为每个进程提供自己专用的虚拟内存寻址空间。如果是这样,这是否意味着第一个地址总是......以及零,所以从内存块的第一个字节的偏移实际上就是这个元素的地址?如果内存地址专用于每个进程,并且我知道我的程序内存块的偏移量以及每个程序对象相对于内存块第一个字节的偏移量,那么对象地址是否在编译时解析?
问题是这些偏移量在 C 代码编译期间不可用,它们在“编译”阶段和转换为字节码期间变得已知。这是否意味着没有办法为“免费”进行对象内存地址计算?
例如,在 Java 中这是如何完成的,只有虚拟机被编译为机器代码,这是否意味着对象地址的计算会因为运行时算法而降低性能?