Compiler construction 解码和分派解释与线程解释
我试图理解在执行解码和分派解释以及线程解释中的程序时的实际差异 这两个例子都很有帮助 我了解Java字节码的工作原理和汇编语言的工作原理。但是DDI和TI在哪里合适呢 上下文:(注意:我假设“解码和分派”是指基于开关的解释器。) 基于开关的解释器和线程解释器在运行时的区别基本上是执行的跳转次数 在基于开关的解释器中,指令在某个中心位置解码,并根据解码结果跳转到处理解码指令的代码段。一旦这段代码解释完指令,它就会跳回集中解码代码,然后继续执行下一条指令。这意味着(至少)每个解释指令执行两次跳转。下面的一段C代码说明了此类解释器的外观:Compiler construction 解码和分派解释与线程解释,compiler-construction,operating-system,interpretation,Compiler Construction,Operating System,Interpretation,我试图理解在执行解码和分派解释以及线程解释中的程序时的实际差异 这两个例子都很有帮助 我了解Java字节码的工作原理和汇编语言的工作原理。但是DDI和TI在哪里合适呢 上下文:(注意:我假设“解码和分派”是指基于开关的解释器。) 基于开关的解释器和线程解释器在运行时的区别基本上是执行的跳转次数 在基于开关的解释器中,指令在某个中心位置解码,并根据解码结果跳转到处理解码指令的代码段。一旦这段代码解释完指令,它就会跳回集中解码代码,然后继续执行下一条指令。这意味着(至少)每个解释指令执行两次跳转。下
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的“computed 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有一些有趣的论文,特别是一篇名为“高效口译员的结构和性能”的论文,上面的代码片段就是从中改编而来的