我正在寻找一种可移植的方式来跳转到C ++中的计算偏移量。
我知道GCC有一个使用goto执行此操作的机制,如下所述:
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/ec7e52b5-0978-4123-9d29-9dc7d807c6b4
可悲的是,我不认为其他编译器会实现这一点。
通常我没有理由在C ++中使用goto,但我发现它可能对优化解释语言很有用(如果你对此感兴趣,可以搜索'thread interpreter')。
我知道我可以使用内联汇编语言来实现它,但问题是我必须为解释器运行的每个平台实现它。
所以有人知道是否有可行的方法吗?
解决方案可能涉及goto,但我对你能想到的任何其他类型的hackery持开放态度。)
更新:目前解释器使用switch语句。我正在寻找能够改进这一点并使解释器运行得更快的技术。具体来说,我试图找出一种可移植的方式来说'goto< next-byte-code-instruction>'其中< next-byte-code-instruction>是一个计算的偏移量,可以存储在字节码本身中。
更新:我在这里找到了一个相关的问题。 What opcode dispatch strategies are used in efficient interpreters?
答案 0 :(得分:2)
switch
允许跳转到预定义的偏移量setjmp
/ longjmp
答案 1 :(得分:1)
我认为setjmp / longjmp尽可能接近。除此之外,该规范在指令流“实现细节”中调用偏移等内容,并且您会遇到特定于平台的内容,如内在函数和内联asm。
你可以尝试的另一个(非常丑陋)的事情是使用switch语句,它通常被实现为偏移的跳转表。即,
int ip = 0;
top:
switch( ip )
{
case 0:
ip += do_whatever(); // returns an offset
goto top;
case 1:
ip += some_other_function();
goto top;
case 2:
ip += etc();
goto top;
// ad infinitum...
}
这是贝尔原创文章的精神,其主旨是每个案例的主体都是流中的单个虚拟机“操作码”。但这似乎真的很蠢。
答案 2 :(得分:0)
除了goto和longjumping以及其他非便携式技巧之外,您是否可以考虑虚函数或至少考虑函数?您可以拥有几个从单个基类派生的单例对象。指针数组包含所有这些对象。虚函数返回下一个解释器状态的索引。 Base对象保存任何派生对象所需的所有数据。
编辑:指向功能的指针甚至可以更快一点,但也有点麻烦。有一个Guru of the Week article可以解释它。
答案 3 :(得分:0)
看起来无法以便携方式实现这一点。
(虽然我仍然欢迎其他答案!)
我发现这篇博文来自已经尝试过我想做的事情的人。他使用GCC方法并且速度提高了33%(统计数据在帖子的末尾)。
在Win32下有条件地编译解决方案以使用内联汇编来计算标签的地址。但他报告说,以这种方式使用内联汇编比正常慢3倍!哎哟
http://abepralle.wordpress.com/2009/01/25/how-not-to-make-a-virtual-machine-label-based-threading/
哦,我还是不想使用内联汇编。
答案 4 :(得分:-1)
我真的不会使用任何形式的goto。它很久以前就死了。但是,如果你必须为此编写一个宏,并使用一堆ifdef使其可移植。这不应该太难,而且是最快的解决方案。