我试图理解程序执行过程中的实际差异 解码和分派解释和线程解释.

两者的例子都会很有帮助。

我了解 Java 字节码的工作原理以及汇编语言的工作原理。但 DDI 和 TI 的作用在哪里呢?

语境: 虚拟机:适用于系统和流程的多功能平台

有帮助吗?

解决方案

(笔记:我假设“解码和分派”是指基于开关的解释器。)

基于开关的解释器和线程解释器在运行时的区别基本上在于执行的跳转次数。

在基于开关的解释器中,指令在某个中心位置被解码,并且基于解码的结果,执行跳转到处理解码指令的代码段。一旦该代码完成指令解释,它就会跳回集中解码代码,继续处理下一条指令。这意味着每个解释指令(至少)执行两次跳转。下面的 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 有一些有趣的论文 他的主页, ,尤其是那篇《高效解释器的结构与性能》,上面的代码片段就是改编自该书。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top