我想了解在执行程序过程中的实际区别解码与调度解释与线程解释。解码与调度解释与线程解释
这两者的例子将真正帮助。
我了解Java字节码的工作方式以及汇编语言的工作原理。但是DDI和TI适合在哪里?
语境:Virtual machines: versatile platforms for systems and processes
我想了解在执行程序过程中的实际区别解码与调度解释与线程解释。解码与调度解释与线程解释
这两者的例子将真正帮助。
我了解Java字节码的工作方式以及汇编语言的工作原理。但是DDI和TI适合在哪里?
语境:Virtual machines: versatile platforms for systems and processes
(注:我假设,通过“解码和派发”你的意思是基于交换机的解释。)
在基于交换机和螺纹解释之间的区别运行时间基本上是执行的跳转次数。
在基于开关的解释器中,指令在某个中心位置被解码,并根据解码结果对处理解码指令的代码段执行跳转。一旦这段代码完成了对指令的解释,它就跳回到集中解码代码,然后继续执行下一条指令。这意味着每个解释指令至少执行两次跳转。下面的C代码块说明了这样的解释可能是什么样子:
typedef enum {
add, /* ... */
} instruction_t;
void interpret() {
static instruction_t program[] = { add /* ... */ };
instruction_t* pc = program;
int* sp = ...; /* stack pointer */
for (;;) {
switch (*pc++) {
case add:
sp[1] += sp[0];
sp++;
break;
/* ... other instructions */
}
}
}
在螺纹解释器,解码代码不集中,但在每一段代码,处理指令的末尾处,而重复。这意味着一旦指令被解释,而不是跳回到一些集中的解码代码,解释器解码下一条指令并立即跳转到它。在ANSI-C中有效地实现线程代码并不是真的可行,但GCC的“计算goto”扩展非常适合。这里是以前解释的线程版本:
void interpret() {
void* program[] = { &&l_add, /* ... */ };
int* sp = ...;
void** pc = program;
goto **pc; /* jump to first instruction */
l_add:
sp[1] += sp[0];
++sp;
goto **(++pc); /* jump to next instruction */
/* ... other instructions */
}
除了可节省跳跃,这种螺纹解释也更有效,因为复制的间接跳转(下一条指令),可以预见通过现代的CPU更好。 Anton Ertl在his home page上发表了一些有趣的论文,特别是一篇名为“高效翻译的结构和性能”的文章,其中对上述代码进行了修改。