在C ++中是否有任何可移植的方式跳转到计算的偏移量?

时间:2010-11-11 09:54:58

标签: c++

我正在寻找一种可移植的方式来跳转到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?

5 个答案:

答案 0 :(得分:2)

  1. switch允许跳转到预定义的偏移量
  2. 函数指针/函数对象的数组
  3. 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使其可移植。这不应该太难,而且是最快的解决方案。