解码和分派解释vs线程解释 [英] Decode and dispatch interpretation vs Threaded interpretation

查看:320
本文介绍了解码和分派解释vs线程解释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解在解码和分派解释和线程解释中执行程序期间的实际差异。

I am trying to understand the practical difference during the execution of a program in Decode and dispatch interpretation and Threaded interpretation.

两者都会真的帮助。

我理解Java字节码如何工作以及汇编语言如何工作。但是DDI和TI在哪里?

I understand how Java bytecode works and how an assembly language works. But where does DDI and TI fit in?

上下文:虚拟机:系统和进程的通用平台

推荐答案

(注意:我假设decode and dispatch是指基于开关的解释器。)

(Note: I'll assume that by "decode and dispatch" you mean a switch-based interpreter.)

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

The difference between a switch-based and a threaded interpreter at run time is, basically, the number of jumps that are performed.

基于解释器的指令在某个中心位置被解码,并且基于解码的结果,对处理解码的指令的代码片段执行跳转。一旦该条代码已经完成解释指令,它跳回到集中解码代码,其继续下一条指令。这意味着每个解释指令执行(至少)两次跳转。下面的C代码说明了这样的解释器可能是什么样子:

In a switch-based interpreter, instructions are decoded at some central location, and based on the result of the decoding, a jump is performed to the piece of code that handles the decoded instruction. Once that piece of code has finished interpreting the instruction, it jumps back to the centralized decoding code, which proceeds with the next instruction. This means that (at least) two jumps are performed per interpreted instruction. The following piece of C code illustrates what such an interpreter might look like:

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扩展非常有用。这里是以前的解释器的线程版本:

In a threaded interpreter, the decoding code is not centralized, but rather duplicated at the end of each piece of code that handles an instruction. This means that once an instruction has been interpreted, instead of jumping back to some centralized decoding code, the interpreter decodes the next instruction and immediately jumps to it. Implementing threaded code efficiently in ANSI-C is not really possible, but GCC's "computed goto" extension works very well for that. Here is a threaded version of the previous interpreter:

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在他的首页上有一些有趣的文章,特别是名为结构和性能of Efficient Interpreters,从中修改了上述代码段。

Apart from saving a jump, such threaded interpreters are also more efficient because the replicated indirect jump (to the next instruction) can be predicted better by modern CPUs. Anton Ertl has some interesting papers on his home page, especially the one called "The Structure and Performance of Efficient Interpreters", from which the above pieces of code were adapted.

这篇关于解码和分派解释vs线程解释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆