法律状态公告日
法律状态信息
法律状态
2018-12-14
未缴年费专利权终止 IPC(主分类):G06F9/45 授权公告日:20120425 终止日期:20171225 申请日:20081225
专利权的终止
2012-04-25
授权
授权
2009-08-05
实质审查的生效
实质审查的生效
2009-06-10
公开
公开
技术领域
本发明涉及一种结合静态优化的动态二进制翻译方法,用于提高源机器平台的程序在翻译器上的执行性能。本发明属于二进制翻译技术领域。
背景技术
动态二进制翻译用于将对应源机器平台的二进制代码动态翻译为可在目标机器平台上运行的二进制代码,从而对软件移植和改善系统性能提供了途径。动态二进制翻译器运行时仅对执行到的代码片段进行翻译,对用户完全透明。利用程序运行时的剖分信息可以对翻译好的代码做有针对性的优化,而这些动态执行的信息在静态是无法被收集到的。
Profiling(剖分)是指通过对运行中的程序进行监测,对体现程序执行行为、特征的数据信息进行收集的过程。这些剖分信息可以用作对翻译好的目标代码进行优化的依据。常用的profiling方法有以下两种:
1、采用instrumentation(插装)的方式,这种方法通过在代码中插入探针指令或直接利用支持profiling技术的硬件来采集与程序执行行为、特性有关的数据信息。
2、采用sampling(采样)的方式,这种方法以一定的时间间隔对程序运行的相关数据进行数据收集,而不需要对程序进行修改。
现在动态二进制翻译器的优化一般都是利用收集到的剖分信息在程序动态执行的过程中做优化,这样在动态可以做一些静态翻译器无法完成的优化工作,比如指令分支跳转预测,超级块的生成,以及针对超级块的优化。这些优化通常会带来明显的性能提升。
但是受制于以下几个方面,动态期间进行的这些优化带来的性能提升很难再有大的突破:
1、收集剖分信息的过程是动态进行的,不管是采用instrumentation技术还是sampling技术,收集过程本身都会有一定的性能开销。如果想做一些更深入的优化,必然需要关于程序运行的更详细的剖分信息,比如要想生成高质量的超级块,需要对程序的执行路径做profiling,这样会带来很大的性能开销。也就是说收集剖分信息和利用剖分信息做优化是矛盾的两个过程,动态做优化要想取得理想的效果就要在两者之间寻找一个平衡点。
2、优化程序本身会消耗性能,而且如要获得更好的优化结果,优化算法一般也会更复杂,这就会使性能开销增加。
3、在动态时无法取得对程序整个运行期间的行为信息,动态优化利用的剖分信息一般只是程序运行到某一阶段的行为信息,不能反映程序运行行为的全貌,这会导致一些动态优化(比如指令分支跳转预测等)的优化效果打折扣。
4、假如同一个程序要在动态二进制翻译器上运行多次,将对应源机器平台的二进制代码翻译成目标机器平台的二进制代码的过程在程序每次运行时都会存在,这部分翻译时间也会带来开销。
针对上述缺点,一般的解决方案是简化profiling的实现,抛弃复杂的优化算法,从而降低性能的开销。显而易见,这种妥协性质的方案无法获得较优的优化效果。
除此之外,另一种解决方案是分阶段翻译,其主要的步骤是:首先,模拟执行源程序获取剖分信息;然后,根据获得的信息,优化翻译过程,产生较优的目标代码,同时将目标代码保存;最后,在之后的执行中,利用现有的目标代码提高性能。这一方案虽能提高执行性能,但其优势仅在于利用剖分信息产生较优的目标代码,而不是对目标代码或执行流本身的优化,无法大幅度提高实际执行性能。
发明内容
本发明的目的在于针对现有技术的不足,提供一种结合静态优化的动态二进制翻译方法,把一些动态期间执行的优化操作放在静态执行,降低程序运行时翻译和优化的开销,使程序执行性能有较大的提升。
为实现上述目的,本发明在源程序第一遍执行时在翻译后的代码中插入探测指令,收集丰富的剖分信息,并在程序运行结束时将剖分信息和翻译后的目标代码持久化,利用保存的剖分信息对翻译后的目标代码在静态期间做各种优化,在此程序以后的运行中直接加载这些经过优化的目标代码。
本发明的结合静态优化的动态二进制翻译方法的具体步骤如下:
1、以基本块为单位划分程序,跳转指令的下一条指令到下一个跳转指令为一个基本块。
2、收集翻译后代码的重定位信息。二进制翻译器以基本块为单位,将源机器代码翻译成目标代码,收集翻译后的目标代码的重定位信息,生成一个重定位信息表,重定位信息表中记录下每条需要重定位指令在内存中的偏移、重定位类型、回填地址时要使用的详细信息。
保存到文件中的二进制代码会涉及对内存地址的访存等操作,在动态二进制翻译器翻译后的代码中,某些这类针对内存地址操作的指令在程序每次运行时是变化的,所以动态二进制翻译器翻译源机器指令时会生成一个重定位信息表,将这些变化的信息记录下来。
3、在每个目标代码基本块的尾部插入探测指令,用以在程序运行时收集剖分信息。
4、程序执行结束时将剖分信息、翻译后的目标代码和重定位信息表保存到文件中。
文件格式的设计,需要适合快速遍历信息的要求,以期提高后续分析优化阶段的效率和效果。
5、静态利用保存在文件中的剖分信息对翻译后的目标代码进行分析、优化(比如生成超级块,分支跳转指令预测,对一些跳转指令的合并,静态做链接等),并将优化后的代码保存在文件当中。
文件格式需重新设计,以适应后续加载执行过程。这些优化在动态也可以做,但如果将这些优化放到静态来做程序执行性能会有更大的提高。
6、相同的程序在第二次及以后运行时,以基本块为单位直接加载静态分析优化过的代码文件,每加载完一个基本块,根据重定位信息表对此基本块中的指令进行重定位。
因为加载进来的是翻译后的目标代码,所以不需要将源机器代码翻译成目标代码的过程。另外由于目标代码已经在静态进行过优化,Profiling和动态优化的开销也被消除。
本发明所涉及的方法在源程序需要多次运行的情况下具有显著的优点。首先翻译源平台指令到目标平台指令的时间可以省掉。其次在程序第二次及以后的运行中不需要收集剖分信息,而且也不需要动态运行复杂的优化算法。最重要的是在程序第一遍运行中可以收集到更加丰富的剖分信息,并且静态不用顾忌优化的开销,利用这些保存的剖分信息可以对翻译好的目标代码进行详细、全面的分析,利用复杂的优化算法对其做优化,而这些优化算法有些在动态无法完成,有些虽然可以在动态完成但会带来很大的性能开销。只要保证程序第一遍运行时收集的剖分信息足够丰富,在动态做的优化都可以使用本发明的方法实现。由于在程序第二遍及以后运行时直接加载保存的翻译后目标代码,这些代码已经经过优化,这样使得优化效果从程序运行初始阶段就得以体现。而在传统的动态优化中,优化后的代码需要经过一定的时间才能被利用。采用本发明的方法会明显提高动态二进制翻译器的性能。
具体实施方式
为了更好的理解本发明的技术方案,以下通过具体的实施例作进一步描述。以下实施例不构成对本发明的限定。
实施例采用了一个多源多目标的动态二进制翻译系统Crossbit,它能翻译多种体系结构的指令集,并在动态做优化。Crossbit从架构上分为前端、中端、后端三大部分。前端负责将源机器平台指令翻译成Crossbit的中间指令,中端对中间指令进行进一步转换,后端将中间指令转换为可运行的目标平台机器代码。Crossbit是一个的动态二进制翻译器,本实施例采用的方法可将Crossbit改造成结合静态优化的动态二进制翻译器,具体步骤如下:
1.以基本块为单位划分程序,跳转指令的下一条指令开始到下一个跳转指令为一个基本块。
这部分工作在Crossbit前端将源机器平台的代码翻译为中间指令时会完成,程序被包装成一个个基本块,每个基本块都以跳转、系统调用等指令结尾。经过划分基本块后的程序能够更方便地进行翻译和优化。
2.收集翻译后目标代码的重定位信息
二进制翻译器以基本块为单位,将源机器代码翻译成目标代码,收集翻译后的目标代码的重定位信息,生成一个重定位信息表。
在Crossbit中有5种类型的数据在下次运行时需要重定位,分别是:
1)REG_ADDR:记录Crossbit前端机器平台相应整型寄存器的重定位信息。Crossbit模拟了源机器平台的cpu,Crossbit中都有相应的变量来维护源机器平台的所有寄存器的状态信息,这些虚拟的寄存器是在内存中的,源机器指令中对寄存器的操作被翻译成了对内存地址的访存操作,而Crossbit中模拟源机器寄存器的变量在每次运行时在内存中的地址是变化的,所以涉及对这类内存操作的指令需要被重定位。
2)FREG_ADDR:记录对应Crossbit前端机器平台的浮点型寄存器的重定位信息。原因同上。
3)GLOBAL_VAR:在经过Crossbit翻译后的对应目标机器平台的代码中,会有一些对全局变量进行操作的指令,这些全局变量是在Crossbit中定义的,每次运行时它们的地址也是不确定的。所以对这类变量操作的指令需要重定位。
4)EXITS_NEXT:在Crossbit中,每个基本块执行到最后会将跳转出口记录到一个Exit结构体中,而这个Exit是属于TBlock的局部变量,程序每次运行中Exit地址会发生变化。
5)REG_SPILL:对于动态二进制翻译系统来说,寄存器分配要解决的问题是如何是源机器寄存器高效的映射到目标机器的寄存器。在目标机器的寄存器资源大于源机器的情况下,只需要将源机器寄存器直接一一对应到目标机器的寄存器即可。但在另一种情况下,源机器具有更多的寄存器资源,例如前端mips后端x86,源机器mips拥有32个通用寄存器,目标机器x86只有8个通用寄存器。如果目标机器的寄存器全被使用,只能替换掉其中的一个以满足当前的分配需求。这种情况下寄存器分配算法会在翻译好的代码中插入指令来将替换出的寄存器的值spillout(脱出)到内存中,保存这些spillout寄存器的变量的地址在Crossbit每次运行时也是会改变的,所以要对这些spillout指令进行重定位。
在Crossbit后端翻译时会将所有需要重定位的指令信息收集到重定位信息表中,记录下每条需要重定位指令在内存中的偏移、重定位类型、回填地址时要使用的详细信息。
3.在每个目标代码基本块的尾部插入探测指令,利用探测指令收集程序运行时剖分信息。
Crossbit的后端将中间指令翻译成目标机器平台的代码,在这个过程中往翻译好的代码中插入探测指令。插入的探测指令尽可能地精简,因为这些指令会频繁被执行。
所有的TBlock都有数据结构专门用来保存剖分信息,每当一个基本块被执行,探测指令也同时被执行,将存储程序执行行为的变量(包括当前基本块执行次数,跳到当前基本块的这条边的执行次数)执行加1操作。
4.程序执行结束时将内存中的剖分信息、翻译后的目标代码、重定位信息等以一定的格式保存到文件中。
在本实施例中,将剖分信息和翻译过的代码分别保存到两个文件中,一个文件保存剖分信息、目标代码基本块的信息和重定位信息,另一个文件保存翻译过的代码。下面介绍前者的文件结构,文件头保存关于文件的汇总信息,包括TBlock的数量,Exit的数量,重定位信息表的项数等。然后将TBlock对象信息、Exit对象信息、重定位信息分类保存和边的关系信息分类保存,这种保存方式有很好的结构性,适合于对文件中的各类数据项查找、修改。后者的文件结构很简单,只是将翻译好的目标代码以二进制形式保存到文件中。
5.静态利用保存在文件中的剖分信息对翻译后的目标代码进行分析、优化(比如生成超级块,分支跳转指令预测,对一些跳转指令的合并,静态做链接等),并将优化后的代码保存在文件当中。这里的文件结构采用了能提高运行时加载速度的设计,将各种数据项以TBlock为索引保存,在加载时可以顺序读取,不用频繁移动文件指针,从而提高加载文件的速度。
本实施例中,在静态实现了超级块生成算法,分支跳转指令预测,以及对一些跳转指令的合并等优化。另外将基本块之间的链接尽可能地在静态做好。这样动态可以省掉动态做链接的开销。这些优化在一般的动态二进制翻译器中是在动态完成的,在本发明中,我们将这些优化放到静态,利用丰富的剖分信息以及使用更复杂的优化算法大大提高了优化后目标代码的质量。
6.相同的程序在第二次及以后运行时可以直接加载优化后的代码运行。
程序第二次运行开始时需要加载源程序文件,同时以基本块为单位直接加载静态分析优化过的代码文件,并初始化SPC和TBlock的映射表,将加载进来的经过静态优化的代码信息填到这个映射表中。每加载完一个基本块,接着根据重定位信息表对此基本块中的指令进行重定位,将程序每次期间会改变的内存地址信息进行回填。
由于程序在静态期间已经做好了链接,如果当前执行块的下一块已经被翻译过,程序会继续执行下去而不跳回Crossbit主程序。如果程序运行期间当前块没有做链接,会跳回到Crossbit,到SPC与TBlock映射表中查找,看对应某SPC的基本块是否已经被翻译过,如果没有,动态二进制翻译器会翻译这个基本块,并将此基本块的SPC与TBlock的关系更新到映射表中。
机译: 动态二进制翻译器以最小的优化约束来支持精确异常的设备和方法
机译: 动态二进制翻译器以最小的优化约束来支持精确异常的设备和方法
机译: 使用简档信息优化经历动态二进制翻译的程序的方法和装置