![](/img/trans.png)
[英]How to get class files or Dalvik byte code of standard java libraries that are used by Dalvik VM?
[英]How does mterp (Dalvik VM) organize its byte-code interprete loop?
我正在研究Android Dalvik VM,当我在文件vm / mterp / out / InterpC-portable.cpp中读取mterp代码时会遇到一个问题。 实际上它是dalvik vm的主要解释器循环来解释dex文件中的字节代码。 如果我写了这个文件,我会选择一个switch-case结构来做这样的事情:
while (hasMoreIns()) {
int ins = getNextIns();
switch(ins) {
case MOV:
//interprete this instruction
...
break;
case ADD:
...
break;
...
default: break;
}
}
然而,mterp使用的与我的想法非常不同,它使用了一些神奇的代码(对我而言),如下所示:
FINISH(0);
HANDLE_OPCODE(OP_NOP)
FINISH(1);
OP_END
HANDLE_OPCODE(OP_MOVE)
...
OP_END
...
我谷歌它发现它似乎是一个修改过的“线程”式执行,它与switch-case风格不同,并且具有更好的性能,因为它删除了while循环中的分支操作。 但我仍然无法理解这段代码以及为什么它在性能上更好。 它是如何找到解释器的下一个代码的?
作为一个简短的指导, out
目录中填充了预处理文件,如果你想弄清楚代码的话,那就不是我想要读的好东西了。 与InterpC-portable.cpp
对应的源(本身)是portable
和c
目录的内容。
就代码如何进行操作码调度而言,您需要在portable/stubdefs.cpp
FINISH
宏的定义:
# define FINISH(_offset) { \
ADJUST_PC(_offset); \
inst = FETCH(0); \
if (self->interpBreak.ctl.subMode) { \
dvmCheckBefore(pc, fp, self); \
} \
goto *handlerTable[INST_INST(inst)]; \
}
此宏在每个操作码定义的末尾使用,并用作switch (opcode)
语句的等效项。 简而言之,它读取PC指向的指令代码单元 - inst = FETCH(0)
- 从其中获取操作码 - INST_INST(inst)
- 并使用该操作码作为所有操作码的地址表的索引。 地址直接用goto
语句分支。
goto
是一个“计算goto”,它是一个非标准的GCC扩展。 您可以在GCC手册中阅读相关内容,您也可以在2008年我在Google IO上的Dalvik内部演示文稿中找到有关该主题的内容。(在https://sites.google.com/site上查找) / io / dalvik-vm-internals 。)
我的演讲还谈到了这项技术的性能特征。 简而言之,它节省了一些分支并且在分支预测方面起到了相对较好的作用。 但是,有更好的方法来编写解释器(正如我在演讲中所介绍的那样,以及特定于CPU的Dalvik解释器实际上工作)。
而对于更大的上下文,将字节码编译为本机CPU指令通常会导致执行速度比最精心调整的解释器更快,假设您有足够的RAM来保存编译结果。 在Froyo中引入的基于跟踪的Dalvik JIT旨在进行权衡,其中使用适量的额外RAM来实现合理有效的性能提升。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.