用于在程序代码转换中划分代码的方法和装置的制作方法

文档序号:6491674阅读:207来源:国知局
专利名称:用于在程序代码转换中划分代码的方法和装置的制作方法
技术领域
本发明一般涉及计算机和计算软件领域,并且尤其涉及例如在代码翻译器、仿真器和加速器中使用的程序代码转换方法和设备。
背景技术
在嵌入式和非嵌入式CPU中,人们发现,如果软件的主体所存在的主指令集架构(ISA)能够透明地访问相关软件,则可以“提升”其性能,或其可以被“翻译”成许多具有更好成本/性能优势的高性能处理器(capable processor)。人们也发现,主CPU架构在时间上与它们的ISA相关,并且不能改进性能或市场范围。这种结构可以受益于“合成CPU”共架构(co-architecture)。
程序代码转换方法和设备促进这种加速、翻译和共架构能力,并且例如在标题为“Program Code Conversion”的WO 00/22521中被记载。
在将为主题架构设计的源程序转换成可以通过目标架构执行的目标程序的程序代码转换期间,对于自修改代码出现了问题。“自修改代码”指的是有意修改其自己的主题代码(subject code)的源程序。程序修改其自己的代码的原因有多种,其中在表1中列出了自修改代码的一些例子。

表格1自修改代码的例子自修改代码对动态翻译器所出现的其中一个主要问题就是,被修改的主题代码可能与已经被翻译的目标代码对应。当出现主题代码的这种修改时,必须将该被修改的主题代码的所有翻译识别为失效并将其丢弃。于是,翻译器必须能够识别对应于正被修改的特定主题代码地址的所有目标代码序列(即翻译)。在动态翻译器中,寻找并删除对应于给定主题地址的目标代码是有难度的,并且有时候甚至是不可能的。在某些情况下,在翻译期间应用优化,其产生的翻译可以不再精确地与该翻译所表示的主题地址的范围相关。在这些情况下,如果源程序在某个主题地址处修改其自己的代码,则翻译器就无法识别哪个已翻译的目标代码为无效。

发明内容
根据本发明,提供一种如所附权利要求书中所述的设备和方法。根据从属权利要求以及下面的说明,可以明显看到本发明的优选特征。
下面是可以根据本发明的各种实施例实现的各个方面和优点的概述。其作为一种介绍提供,以帮助本领域的熟练技术人员更加迅速地理解后面详细的设计讨论,并且其没有也不意图以任何方式对所附的权利要求书的范围进行限制。
特别地,发明人已经开发了用于加速程序代码转换的许多优化技术,其特别是在与实时翻译器结合使用,该实时翻译器将源程序代码的连续基本块翻译成目标代码,其中在产生用于下一基本块的目标代码之前执行对应于第一基本块的目标代码。
在优选的处理中,翻译器采用分区技术,将主题代码空间划分成区域,此后称之为分区,其中每一分区包含主题代码和相应目标代码的不同的一组基本块。分区将主题代码的翻译器表示以及主题代码翻译划分成主题存储器(subject memory)的非交迭区域。通过这种方式,当源程序中的自修改代码修改主题代码时,只需要丢弃实际受到该自修改代码影响的那些分区,并且可以保留未受影响的分区中的所有翻译。该分区技术的优点在于,其限制了响应于自修改代码操作而必须被重新翻译的目标代码的数量。在另一种处理中,分区技术允许也包括自修改代码的多线程源程序以线程安全(thread-safe)的方式执行代码修改。


附图包括在说明书中,并且构成说明书的一部分,其描述了当前优选实施例,其中图1是其中应用本发明实施例的设备的方框图;图2的示意图描述了根据本发明的示范实施例的基本块数据结构和缓存;图3的流程图描述了在翻译期间所采用的分区技术;图4的流程图描述了分区修改;图5A和5B的范例示意图描述了在分区技术中创建和修改分区;
图6的流程图描述了可缩减的分区优化技术;图7A和7B的范例示意图描述了使用可缩减的分区优化技术创建和修改分区;图8A-8E的范例示意图描述了使用可缩减的分区优化技术创建和修改具有活动和非活动SIG范围的分区;和图9A和9B的范例示意图描述了通过本发明的翻译器在分区之间的控制流。
具体实施例方式
图1中示出了用于实施下面所讨论的各种新特征的示范性设备。图1描述了包括目标寄存器15的目标处理器13以及存储多个软件成分19、20、21的存储器18,其中这种存储器18还提供用于基本块缓存23、全局寄存器存储27以及要翻译的主题代码17的工作存储。软件成分包括操作系统20、翻译器代码19以及翻译后的代码21。翻译器代码19例如可以用作仿真器,用于将一个ISA的主题代码翻译成另一个ISA的翻译后的代码,或者用作加速器,用于将主题代码翻译成相同ISA的翻译后的代码。
翻译器19、即实施翻译器的源代码的编译后的版本,以及翻译后的代码21、即通过翻译器19所产生的主题代码17的翻译,结合操作系统20-诸如运行于目标处理器13上的UNIX,典型地是微处理器或其它适当的计算机-一起运行。要理解的是,在图1中所述的结构仅仅只是示范性的,并且,例如根据本发明的软件、方法和处理可以通过驻留于操作系统中或在其下面的代码实施。主题代码、翻译器代码、操作系统以及存储器存储机制可以是本领域的熟练技术人员所熟知的任何各种广泛类型。
在根据图1的设备中,优选地,在翻译后的代码21正在运行的同时,在运行时间中,动态执行程序代码转换。翻译器19与翻译后的代码21一致地运行。翻译处理的执行路径是控制循环,包括下列步骤执行翻译器代码19,其将一块主题代码17翻译成翻译后的代码21,然后执行该块翻译后的代码21;每一块翻译后的代码21的末端包含将控制返回到翻译器代码19的指令。换言之,翻译并然后执行主题代码的步骤是交织的,从而一次只翻译源程序17的部分,并且在翻译后面的基本块之前执行第一基本块的翻译后的代码21。翻译器19的翻译基本单元是基本块,这意味着,翻译器19是一次一个基本块地翻译主题代码17。基本块正式的定义是具有刚好一个进入点和刚好一个退出点的代码部分,其将块代码限制到单个控制路径。因此,基本块是控制流的基本单元。
在产生翻译后的代码21的处理中,由翻译器19根据主题代码17的指令顺序产生中间表示(“IR”)树。IR树是所计算的表达式和源程序所执行的操作的抽象表示。随后,根据IR树产生翻译后的代码21。例如,在标题为“Block Translation Optimizations for Program CodeConversion”,并且申请日为2003年5月16日的共同未决美国专利申请No.10/439,966中描述了用于产生这种IR树的方法和设备,其全部内容在此引作参考。
在产生IR树之后,根据IR树产生相应的目标代码21。根据类IR产生目标代码21的过程是本领域所熟知的。在翻译后的块的末端插入目标代码21,以将抽象寄存器存储到全局寄存器存储27中。在目标代码21产生之后,然后其被执行。
翻译器19首先根据第一基本块的主题指令17产生翻译后的块21,然后执行用于第一基本块的翻译后的代码。在第一基本块的末端,翻译后的代码21将控制返回给翻译器19,翻译器19然后翻译第二基本块。然后执行用于第二基本块的翻译后的代码21。在执行第二基本块的末端,翻译后的代码将控制返回给翻译器19,翻译器19然后翻译下一基本块,等等。
于是,在翻译器19下运行的源程序具有以交织方式执行的两种不同类型的代码翻译器代码19和翻译后的代码21。翻译器代码19由编译器在运行时间之前根据翻译器19的高级源代码实施而产生。翻译后的代码21由翻译器代码19在整个运行时间中根据正被翻译的程序的主题代码17而产生。
同样地,在翻译器19与翻译后的代码21成分之间划分主题处理器状态的表示。翻译器19将主题存储器状态存储在各种显式编程语言装置,诸如变量和/或对象,中;用来编译翻译器的编译器确定如何在目标代码中实施状态和操作。翻译后的代码21通过比较,将主题处理器状态隐式地存储在目标寄存器和存储器位置中,其通过翻译后的代码21的目标指令直接操作。
例如,全局寄存器存储27的低级表示只是所分配的存储器的区域。通过在已定义的存储器区域与多个目标寄存器之间保存和恢复(restore),这是翻译后的代码21如何看到抽象寄存器并与之交互。然而,在翻译器19的源代码中,全局寄存器存储27是数据阵列,或者是可以在更高级被存取和操作的对象。至于翻译后的代码21,就没有高级表示。
在某些情况下,主题处理器状态在翻译器19中是静态的或者可以静态地确定,其直接被编码成翻译后的代码21,而不是被动态地计算。例如,翻译器19可以产生根据最后标志影响(flag-affecting)指令的指令类型而指定的翻译后的代码21,这就意味着,如果最后标志影响指令的指令类型改变,则翻译器为相同的基本块产生不同的目标代码。
翻译器19包含对应于每一基本块翻译的数据结构,其特别是用于促进翻译优化,诸如扩展的基本块、等同块(isoblock)、组块、以及缓存的翻译状态优化,如美国专利申请No.10/439,966中所述,并且其全部内容在此引作参考。图2描述了这种基本块数据结构30,其包括主题地址31、目标代码指针33(即翻译后的代码的目标地址)、翻译提示34、进入和退出条件35、概述度量(profiling metric)37、对前任和后继基本块的数据结构的参考38、39以及入口寄存器映射40。图2还描述了基本块缓存23,其是基本块数据结构的集合,例如通过主题地址标引的30、41、42、43、44…。在一个实施例中,对应于特定翻译后的基本块的数据结构可以被存储在C++对象中。在翻译基本块时,翻译器19创建新的基本块对象。
基本块的主题地址31是该基本块在源程序17的存储器空间中的起始地址,即如果源程序17运行于主题架构上,基本块所处于的存储器位置。其也称作为主题起始地址。虽然每一基本块对应于一个主题地址范围(每一主题指令一个),但是主题起始地址是基本块中第一指令的主题地址。
基本块的目标地址33是目标程序中翻译后的代码21的存储器位置(起始地址)。目标地址33也称作为目标代码指针,或者目标起始地址。为了执行翻译后的块,翻译器19将目标地址当作被间接访问(dereference)以调用(将控制传输给)翻译后的代码的功能指针。
基本块数据结构30、41、42、43、……被存储在基本块缓存23中,其是通过主题地址组织的基本块对象的存储库。当基本块的翻译后的代码21结束执行时,其将控制返回给翻译器19,并且也将基本块的目的(后继)主题地址31的值返回给翻译器。为了确定后继基本块是否已经被翻译,翻译器19将目的主题地址31与基本块缓存23中的基本块(即已经被翻译的那些)的主题地址31进行比较。翻译并然后执行还没有被翻译的基本块。简单地执行已经被翻译(并且具有相容进入条件,如下所述)的基本块。随着时间的推移,所遇到的许多基本块将已经被翻译,这就使得递增的翻译成本降低。于是,翻译器19随着时间推移变得更快,因为需要翻译的块越来越少。
分区在一个优选实施例中,翻译器19采用技术选择主题指令集,此后称之为主题指令组(SIG),以便每一SIG与不同集合的翻译器数据结构(例如基本块)和翻译后的目标代码21相关联。此后将SIG与它的相关翻译器数据结构和目标代码21的组合称作为分区。单个SIG包括一个或多个主题地址范围中的主题指令。来自单个主题地址或多个主题地址范围的指令可以包括在几个不同SIG中。翻译后的块可以只包括来自一个SIG的翻译。
翻译器19所利用的分区技术将控制流的翻译器19的表示划分成可能一起被修改的多组主题指令(SIG)。在某些情况下,这些分区对应于组成源程序的不同库和对象文件,从而将作为库创建并替换的分区映射到主题存储器,并在后面丢弃。当对修改其自己的主题代码17-此后称之为“自修改”-的源程序进行翻译时,分区技术对于翻译器19可以特别有用。通过将主题代码17以及其相应的翻译后的目标代码21划分成分区,当受影响的一个或多个分区的相关主题代码被修改而不影响在其SIG没有受到影响的其它分区中建立的有用信息(例如翻译)的时候,可以丢弃这些受影响的一个或多个分区。如果不使用这种分区,则响应于每次代码修改,需要丢弃所有现有翻译,即使是那些没有受到代码修改影响的翻译。
在一个优选实施例中,翻译器19保持隔离的数据结构,从而通过SIG将翻译数据结构组织成分区。这种隔离使得能够一次丢弃和释放包含在单个分区中的许多块翻译(以及关联的数据结构),而不是遍历翻译后的代码的下层表示,以查找受到影响的翻译并且将它们每次删除一个。例如,在一个实施例中,翻译器19为每一分区保持单独的基本块缓存23。
在一个优选实施例中,翻译器19定义SIG,使得单个SIG中的主题地址形成单个连续范围的地址。
在另一优选实施例中,翻译器19定义SIG,使得单个SIG中的主题地址包括(1)可能一起被修改的单个范围的连续地址;和(2)不太可能被修改的附加范围的地址。这样就使得单个块的翻译包括来自范围(1)和范围(2)的指令,并从而形成更优化的翻译。
在图3中描述了由翻译器19在修改分区中所实施的步骤。当主题代码17修改其它主题代码时,通过翻译器19在步骤100中检测“修改事件”。定义修改事件,以对应于特定主题地址范围(覆写、删除或者其他被修改所影响的主题代码的范围)。翻译器19必须首先检测主题代码在何时以及何地被自修改(即,哪一主题代码执行修改,以及哪一主题代码被修改)。修改事件是使主题代码17被修改的任何事件。自修改代码不包括其中主题代码17修改主题数据的情况。主题代码17的自修改可以有多种形式,包括但并不限于(i)将文件映射到存储器中(例如mmap()系统调用);(ii)从存储器中移除文件(例如munmap()系统调用);和(iii)使存储器区域可执行(例如使用mprotect()系统调用改变其权限)。
在使用熟知的系统调用-诸如mmap()、munmap()或mprotect()-进行主题代码17修改的情况下,翻译器19可以检测在主题代码17中对该系统调用的所有调用,以检测修改事件。翻译器19也可以通过其它机制来检测主题代码17修改。例如,许多主题处理器要求,在执行已经被修改的代码之前,源程序必须首先刷新处理器的指令缓存(I-缓存)。特别地,PowerPC架构具有用于该目的的特定指令,“ICBI”(指令缓存块无效Instruction Cache Block Invalidate),而其它架构可以使用用于相同目的的特定系统调用。在具有这种缓存刷新要求的架构上,翻译器19可以通过检测特定指令(或特定系统调用)的实例来检测修改事件。
在另一优选实施例中,翻译器19使用目标操作系统20的特征来监测对对应于主题代码的目标存储器区域进行的所有写操作,以在步骤100中检测修改事件。在某些系统上,系统调用mprotect()允许翻译器19将存储器的特定区域设置为“只读”。其它系统可以利用等同于mprotect()系统调用的功能的功能,以将存储器的特定区域定义为只读。任何对只读区域的写入尝试都触发被翻译器19检测的信号。信号通知翻译器19出现了主题代码17修改,并且翻译器19使用信号内容来确定哪些主题地址正被覆写。在检测修改事件和识别修改的范围(即受到影响的主题地址)之后,翻译器19然后允许进行正常的写入。
在另一优选实施例中,对于主题代码17中每一翻译后的存储器写操作,翻译器19产生特定目标代码序列,其检查写地址是否对应于主题代码17,而不是对应于主题数据,以在步骤100中检测修改事件。
在本发明各种实施例的每一个中,在已经检测到修改事件之后,修改导致在步骤102中创建新分区,其SIG包括被修改的范围中的主题指令。另外,然后在步骤104中修改现存的分区,以考虑(accountfor)新创建的分区。在修改现存的分区中,翻译器19实施图4中所述的步骤。当由于检测到的修改事件,翻译器19创建新分区时,其首先在步骤110中确定新创建分区的SIG是否与任何现存分区中的SIG相交。当发现与现存分区的SIG没有交迭时,在步骤116中保持现存的分区完整。如果任何现存分区所具有的SIG包括与被修改的范围相交(交迭)的主题地址,则所有这些相交分区在步骤112中被破坏,并且在步骤114中被重新创建,除非是在下述应用附加信息优化的某些情况下。对于被破坏的每一相交分区,在步骤114中为原始SIG中剩余的一个或多个范围的主题地址创建新的剩余分区,使得新的剩余分区包含相交分区的原始SIG减去相交的被修改范围。当分区被破坏时,与该分区相关联的所有现有目标代码21翻译都被丢弃。每一新创建的分区最初是完全空的翻译后的目标代码21,这意味着,必须从暂存区(scratch)翻译随后所遇到的来自该分区的SIG的任何主题代码17。
图5A和5B描述了从一组现存的分区创建新分区的范例以及与这些分区的其中一些交迭的修改事件。为了提供简单的说明性范例,在图5A和5B描述的SIG中,用于每一SIG的主题指令集形成单个连续范围,但是该技术的本质并不是要每一SIG包含单个连续范围。在进行修改之前,四个分区A、B、C和D的SIG存在于主题地址空间中,如图5A中所示。该范例中的主题代码17然后修改从存储器中的点50延伸至点52的主题编码地址的范围。修改范围54与分区A和C的SIG相交,并完全将分区B的SIG包围。图5B描述了响应于修改事件而对现存分区所进行的改变。为整个被修改范围104创建分区M。分区A和C被破坏,并且为没有与修改范围104相交的A和C的剩余部分分别创建分区A′和C′。分区B被破坏,并且其SIG完全被新分区M包含。分区D的范围没有与修改范围54交迭,其保持不受影响。
在翻译器19的另一优选实施例中,通过分区技术使用惰性分区分配优化技术,以提高翻译器19的性能。为了节省存储器,在创建分区时并不分配一个分区的完全数据结构。相反,初始创建保留分区的SIG的非活动分区,但是翻译器19初始并不分配任何下层翻译数据结构和存储器。通过这种方式,初始的非活动分区基本上是只保留特定SIG的空框架分区。被翻译器19识别为正被修改事件修改的主题存储器空间的区域可以在某些情况下实际上从不被翻译成目标代码21。这可能是因为主题存储器区域对应于数据,或者是因为主题存储器区域对应于从不被执行的代码。初始创建非活动的或框架分区避免了浪费的存储器资源的开销。
当分区的SIG中的任何主题代码17实际被翻译时,非活动分区变成活的或活动的分区,并且初始化分区数据结构。相应地,对应于源程序的数据段(例如,作为数据被mmap()的文件,以及源程序从不作为代码执行的文件)的修改事件使得新的非活动分区被创建,但是并不分配任何下层翻译数据结构和存储器区域。只有当在分区的主题地址范围内出现翻译时才实现分区的完全数据结构。因为非活动分区并不包含主题代码的翻译,所以可以创建、删除或实现它们,而不需要存储器和与活动分区相关联的性能开销。
在某些情况下,翻译器19可以为新分区分配大存储器区域,以存储目标代码21翻译。目标代码21优选地被分配为连续的,以避免不必要的分段。翻译器19更可能能够使目标代码21连续,如果其使用大存储器区域。错误检测到的分区(即不对应于可执行主题代码的主题存储器范围中的修改事件)有时候可能消耗宝贵的存储器资源,而没有任何目的。通过只是在分区内的主题代码17实际被翻译(和执行)的时候才分配翻译数据结构和存储器,惰性分区分配使得翻译器19能够避免由于与分区相关联的修改事件检测机制所产生的错误肯定的消极影响。
在另一优选实施例中,翻译器19具有解释器功能,以解释主题代码17,而不是翻译其。这就使得翻译器19能够延迟主题代码17的翻译,从而避免分配与该主题代码17相关联的分区。在申请日为2003年9月4日、标题为“Method and Apparatus for PerformingInterpreter Optimizations during Program Code Conversion”的共同未决英国专利申请No.03 20716.4中描述了便于这种解释器功能的翻译方法和设备,其全部内容在此引作参考。
在另一优选实施例中,翻译器19对分区处理应用可缩减的分区优化技术,以提高翻译器19的性能,其中将分区的SIG缩减-而不是响应于修改事件删除该分区-到包括分区中实际使用的地址集的更小SIG。缩减的更小SIG并不包括修改事件所定义的范围。初始地,响应于检测到修改事件,创建新分区,其中SIG包括具有其值由修改范围定义的起始地址和结束地址的范围。然而,在操作中,被翻译的主题地址的实际范围可以比所定义的分区范围窄。包括一个分区内所有实际已经被翻译或者被标记用于将来翻译的主题地址的SIG被称作为“活动SIG”或分区的已使用SIG。分区中还没有被翻译的主题地址的剩余SIG被称作为“非活动SIG”。为了优化翻译器19的性能,通过至少删除对应于非活动SIG与修改范围之间的交迭的非活动范围地址部分,可以将分区的SIG的范围从其初始所定义的地址集缩减到包括活动SIG中其活动范围的地址的更小集。
虽然可以通过任何多种方式实施可缩减分区的概念,但是在一个优选实施例中,翻译器19在每一分区的SIG中保持活动范围或翻译后的范围的地址。当创建分区的时候,其活动SIG初始是空的。在翻译期间,当每一主题指令被翻译的时候,将其主题地址(“翻译后的地址”)与当前分区的活动SIG进行比较。如果翻译后的地址在当前活动SIG之外,则扩展活动SIG,以包括翻译后的地址。这样,活动SIG将随着主题代码翻译的进行而增加。
在执行可缩减分区优化技术中,翻译器19实施在图6中所描述的步骤。当翻译器19在步骤200中检测到修改事件时,在步骤202中创建新分区,其中SIG包括修改范围。翻译器19然后在步骤204中确定修改范围是否与现存分区的初始所定义的SIG交迭。当发现没有交迭时,在步骤206中使已经定义的现存分区保持完整。如果存在交迭,则翻译器19然后在步骤208中确定修改范围实际上是否与分区的活动SIG交迭。如果修改范围并不与活动SIG交迭,那么翻译器19可以在步骤210中简单地改变分区的初始所定义的SIG的大小,而不删除分区中的翻译数据结构。原因是,虽然初始所定义的分区SIG表示分区的可能范围,如创建分区的前一修改事件所定义的那样,但是活动SIG表示实际的翻译后的主题地址集。不与活动SIG交迭的修改因此并不使分区内的任何翻译无效,因为翻译器19知道翻译后的主题地址与被修改的主题地址不同,并因此不会受其影响。通过改变分区的SIG的大小,以至少包括活动范围,存储在分区中的翻译可以被保持在该分区中,并且不需要被删除。另一方面,如果修改范围与分区的活动SIG交迭,那么翻译器19在步骤212中必须删除整个分区,如上所述。
现在参照图7A和7B,其说明了可缩减分区优化技术。在图7A和7B中所述的分区基本上与图5A和5B中所示的相同,除了分区A和C分别包括活动范围的主题地址56和58之外。在修改之前,存在四个分区A、B、C和D,如图10A中所示。主题代码然后修改从存储器中的点50延伸至点52的主题代码地址范围。修改范围54与分区A的初始所定义的分区范围相交,但是修改范围不与分区A的活动范围56相交。图7B描述了响应于修改事件而对现存分区所进行的改变。在为修改范围54创建分区M之后,可以缩减分区A的范围,而不影响分区A中的翻译。相反,在该范例中可以看到,修改范围54与分区C的活动范围58相交。于是,不能简单地缩减分区C的范围,必须破坏分区C,因此为分区C的不与修改范围54相交的其余部分创建新的分区C′。破坏分区B,并且其范围完全被新分区M包含。分区D保持不受影响。
现在参照图8A-8E,所述为可缩减的分区优化技术,其中存在SIG 300,其包含多个活动和非活动范围。图8A描述了初始所定义的SIG 300,如其在主题地址空间302中所显示的。SIG 300包括两个范围的主题代码地址304和306。如图8B中所示,每一主题代码地址范围304、306分别包括活动范围的主题代码地址308、310。SIG 300中的其余主题地址是位于非活动范围312、314和316中的非活动主题代码地址。一旦出现修改事件,主题代码于是修改主题代码地址的范围,以创建新的SIG 318,如图4C中所述。新创建的SIG 318的范围与SIG 300的初始所定义的主题代码地址范围304相交,其中SIG 318的范围不与其活动范围308相交,而只与其非活动范围314相交。在确定SIG 318的范围界限之后,可以如图4D中所示缩减主题地址范围314,而不影响SIG 300的活动范围308中的翻译。通过删除与SIG318相交的范围320中的主题地址来缩减非活动范围314,以产生缩减的非活动范围314′。图4E描述了响应于修改事件,对SIG 300的初始所定义的主题地址范围304、306所进行的修改。如图所示,如上所述地将初始所定义的主题地址范围304缩减到包括活动范围308和非活动范围312、314′的主题地址范围304′。主题地址范围306保持不受创建新SIG 318的影响。
翻译器19可以在解码的时候检测大多数修改事件,但是可能不知道要修改的实际主题地址,直至执行翻译后的代码21。于是,当翻译器19在解码期间检测到主题代码17修改或对于已经出现修改的指示时,翻译器19结束当前块的翻译,并且紧接着当前块之后插入通知,以将修改事件通知给翻译器。
在翻译器19的一个实施例中,借助于特定块,在该翻译器19中实施分区技术。特定块是那些虽然它们可以对应于特定主题地址但是并不表示主题代码的翻译的块。相比之下,翻译块表示以特定起始主题地址开始的特定主题代码序列的翻译。相反,特定块包含翻译器19的特定操作,其在实际执行这些块之前,在翻译期间被插入到目标代码流中。实际上,特定块是执行轻量翻译器操作的特定翻译结构,其可以被设置在目标代码控制流中的特定点,而不需要高代价地将内容从目标代码切换出来回到翻译器循环。
特定块包含伪目标代码,而不是普通的目标代码。普通的目标代码表示某主题代码序列的翻译。伪目标代码由人工(即未翻译的)目标代码序列组成,其被直接写入目标代码中或以高级编程语言(例如C++)编写并且被编译以具有与翻译器19所产生的目标代码相同的调用约定。特定块的例子包括在此讨论的通知块和边界防护块。
在一个优选实施例中,翻译器19在紧接着包含自修改主题代码的块之后的点上将被称为“通知块”的特定块插入到翻译后的程序的控制流中。通知块是“特定的”翻译结构,因为不同于翻译块,其并不表示任何特定主题代码的翻译,而是表示修改事件。实际执行修改的主题代码17被翻译作为当前块的部分。通知块作为当前块的后继被插入。于是,紧接着在翻译后的当前块中执行修改之后,随后的通知块通知翻译器19执行适当的操作,以响应于该修改(即分区调节)。在成为通知块的后继的新块中翻译修改事件之后的主题代码17。
当在运行时在目标代码21中到达通知块时,将被修改的代码的主题地址范围通知给翻译器19。翻译器19使用该信息以创建新的分区,其也可以改变或者破坏现存的分区,如上所述。
包含自修改主题代码的块(通知块的前任)在紧接着识别修改事件之后结束,因为修改可以使得当前分区无效。被修改的主题代码可以是下一主题指令,其可要求翻译器翻译并执行该指令的新修改的版本,而不是执行旧版本的现存翻译。例如,在PowerPC架构上,在缓存刷新指令之后,块必须结束。于是,当检测到修改事件时,结束翻译的当前块,并且插入通知块作为后续。
通知块也将当前主题地址的拷贝和兼容性列表从其前任块传送到其后继块。在出现通知之后,在下一主题指令,在后继块中重新开始翻译。如果由于操作而破坏了当前分区,则通知块也进行安全过渡到替换它的新分区中,使用所拷贝的主题地址和兼容性列表来在新分区中初始化后继块。这避免了在新分区的过渡期间引用可能已经被删除的数据的问题。
翻译块必须在分区边界结束,使得分区的创建可能具有对否则可以在代码的大部分上执行的优化的负面影响。由于所形成的分区,否则将一起被翻译的代码部分作为单独的块被翻译,于是就缩减了优化的范围并增加了返回到翻译器循环的次数。例如,通过分区边界限制优化,诸如在共同未决并转让给与本发明相同的受让人的美国专利申请No.10/439966中所描述的扩展块和组块优化,其在此引作参考。因此,对于已知不修改其自己的主题代码17的源程序,可以应用于当前分区技术以提高翻译器19性能的一种优化就是,将所有主题存储器聚合到单个分区中,使得所有主题代码17被包含在一个分区中。
可以通过多种方式实施主题存储器聚合。在一种方式中,将已知在普通操作中不被修改的一组库聚合到单个分区中。将源程序所需要的、不是该不变集合一部分的其余库如普通的那样放入单独的分区中。这样就使得可以更有效地对不变分区中的翻译进行翻译,同时保持响应其余的、可能变化的库的主题代码修改和其它主题代码的能力。
在主题存储器聚合的另一种方式中,将包括一组已知在普通操作中不被修改的主题代码的主题地址的区域(1)加入到分开地包含可能变化的其它区域(2)的所有分区的SIG中,这样就使得可以更理想地产生从分区的可能变化区域传送到不变区域的控制流的翻译,同时保持响应分区的可变化区域的主题代码修改的能力。如果出现包括分区整个区域(2)的主题代码修改,分区将整体被删除,以节省存储器。
分区的范围必须适当地定义,因为分区范围影响翻译器19的性能。如果分区太小,控制流必须不断地通过边界防护(如下所述)。如果分区太大,微小的代码修改将不必使得更大部分的翻译后的代码变为无效。当选择分区大小时,应该考虑这种折衷的适当平衡,因为其关系到翻译器19的性能。如果确定正被产生的特定分区对性能具有负面影响,则可以对分区应用优化。默认地,通过修改事件检测机制来确定分区大小。例如,如果翻译器19检测到运行期程序库的mmap(),那么创建包括整个库的新分区。
可以应用于分区以提高翻译器19性能的一种优化技术就是分区聚合。例如,PowerPC ICBI缓存刷新指令使得可执行存储器的一个页面无效。然而,如果一次修改主题代码17的多个页面,则源程序可以包含几个连续的ICBI指令,其使得存储器的邻接多页无效。在上述分区机制的情况下,这样将产生多个邻接的页面宽度分区。这样,分区机制的一种优化就是检测接续缓存刷新指令,并且将已修改的范围接合成为一个“聚合”分区的SIG。
在实施分区聚合优化的一个实施例中,当创建新分区时,翻译器19检查是否存在这样的现有分区(即不是作为创建新分区的副产品而创建的其余分区),其SIG在主题代码中与新分区的SIG相邻并在其前面。如果有,可以将前一现存分区的SIG的范围扩展到包括新分区的SIG的范围,有效地将两个分区聚合起来。在实现聚合之后,新分区并不需要具有单独的表示。
边界防护在一个优选实施例中,翻译器19插入用于在两个分区之间穿行的控制流的附加间接级。翻译器19使用特定的占位符,此处称之为边界防护,用于接触分区边界的块,从而前任块可以检查先前翻译后的后继块是否还存在。使用这种方式,当前任块的后继被删除时,可以有效地通知它们。翻译器19在源程序的控制流跨过分区边界的每个点,或者称之为边界交叉点,插入一对边界防护结构。该对边界防护包括退出边界防护和进入边界防护。退出边界防护是在前任块之后、并且在与该前任块相同的分区中加入的特定块。进入边界防护是将相应的退出边界防护块与后继块连接起来的数据结构。对于同一分区中的翻译后的块,控制流直接从前任块传送到后继块。对于不同分区(即边界交叉点)中的块,控制流从前任块传送到退出边界防护,然后利用进入边界防护来定位后继块,退出边界防护将控制传送到后继块。
进入边界防护用作翻译器19的占位符,其中进入边界防护存储对它们的退出边界防护副本的参考。每一退出边界防护的数据结构也包含对其进入边界防护副本的参考。退出边界防护的执行就验证还存在前面例示的后继块。边界防护块通过提供分区交叉点的显式表示而用于簿记功能。当翻译器19删除特定分区时,其遍历该分区内的每个进入边界防护,以查找对应的退出防护。由于分区被删除,每一个这种退出边界防护的副本参考被设置为空。在某些实施例中,翻译器19存储所有用于给定分区的进入边界防护,从而当分区被删除时,可以有效地对它们进行遍历。例如,在一个实施例中,翻译器19保持用于每一分区的进入边界防护列表,其中只要创建或删除进入边界防护,就对这种列表进行更新。
相应地,当执行退出边界防护时,其通过简单地检查其自己的副本参考来验证其后继还存在。如果定义了参考,那么有效的翻译后的后继存在,并且控制通过各进入边界防护传送到后继块,(并从而传送到后继分区)。如果未定义参考,那么退出边界防护不知道有效的翻译后的后继块,即以前存在后继块并且其已经被删除了,或者该退出边界防护还从来没有被执行并因此后继还从来没有被确定。如果未定义副本参考,则通过检查各自分区的基本块缓存或者通过翻译后继块而得到新的进入边界防护和后继块。从退出边界防护的角度看,被翻译并然后被删除的后继块与从来没有被翻译的后继块没有不同。
通过边界防护对所得到的分区边界交叉点的显式表示使得分区删除的处理更加有效。为了删除分区,翻译器19必须识别并取消所有对已删除块(即被删除分区内先前翻译的块)的参考。没有某薄记机制,诸如边界防护,翻译器19需要遍历大量翻译后的块,以识别被删除分区中哪些块具有后继,以便删除对这些被丢弃后继的参考。除了让删除分区的处理变得更加有效,边界防护块促进了线程安全的边界交叉点,如下参照多线程程序所讨论的那样。
为了在存在边界防护的情况下删除分区,翻译器19(i)置空(void)指向所要删除分区的所有退出防护的副本链接;和(ii)向所要删除分区的所有后继分区通知可以丢弃它们的相应进入防护;和(iii)删除所有翻译结构和属于被删除分区的目标代码21。在第一步骤(i)中,翻译器19对分区中的所有进入边界防护进行遍历,并将它们的外部退出边界防护副本复位,有效地向所有前任分区通知被删除的分区被置空。在分区删除的第二步骤(ii)中,遍历分区中的所有退出边界防护,以向后继分区通知可以丢弃它们的相应进入防护。在一个实施例中,通过遍历被删除分区的每一退出边界防护,执行第二步骤。在另一实施例中,通过包含相应退出防护的前任分区来标引分区中的所有进入防护。在这种情况下,被删除分区只需要通知每一后继分区一次,并且每一后继分区然后可以识别所要删除的相应进入点。
分区中的多线程程序当使用分区时,多线程源程序对翻译器19提供了困难,也就是必须以线程安全的方式执行分区删除。具体地,当给定分区正被删除期间,必须防止线程进入该分区。这样保证了控制总是进入有效翻译,并且从不进入被删除的或无效的块。在已经删除或重新创建分区之后,然后可以允许线程进入(重新空的)分区。
在一个优选实施例中,翻译器19使用单个全局互斥(“全局分区锁定”)来将特定的分区操作串行化,包括(i)控制流在分区(即边界交叉点)之间跳转;以及(ii)删除分区,并且在可以应用的地方重新创建分区。于是,退出边界防护必须在控制传送到其相应进入边界防护之前获得全局分区锁定。相似地,通知块必须在破坏分区之前获得全局分区锁定。对于需要删除以及随后重新创建一个或多个分区的修改事件,在全局分区锁定的保护下,自动地执行所有这种删除和重新创建,也就是顺序地执行所有这些操作而不需要释放锁定。翻译器19维持用于每一线程的分区标识符,其当控制在分区之间传送时被改变。在保持全局分区锁定期间,由边界防护对进行这种改变。
在另一优选实施例中,翻译器19使用单个全局互斥(“全局分区锁定”)来将特定分区操作串行化,包括(i)创建进入边界防护;和(ii)删除分区,并且在可以应用的地方重新创建分区。于是,退出边界防护必须在其可以得到新的进入边界防护和后继块、或者重新创建先前所删除的进入边界防护和后继块之前获得全局分区锁定。在分区删除的情况下,通知块在删除之前获得全局分区锁定,并且然后删除机制首先执行遍历其进入边界防护集合的操作,以从相应退出块中删除副本参考。这就要求,在存在执行其它线程的情况下,可以安全地解除单个副本参考的链接。一旦所有进入边界防护都已经应用了该操作,则在这样修改的任何退出边界防护可以获得被删除分区所拥有的SIG中的新后继之前,必须完成其余的删除操作,并释放全局互斥。
现在参照图9A和9B,其中描述了翻译后的程序的控制流跨过分区边界,分别具有和不具有穿越分区边界。图9A所示为当不应用分区时或者当控制流还留在单个分区中时,翻译器19中的特定源程序的控制流。控制从主题块A 401传送到主题块B 403,然后传送到主题块C 405,然后传送到主题块D 407。对于程序主题代码,块B 403是块A 401的后继,块C 405是块B 403的后继,并且块D 407是块C 405的后继。
在图9A的主题块B与主题块C之间存在或创建分区边界409的情况下,当穿过分区边界409时,控制必须流经边界防护对,如图9B中所示。块A 401和B 403都在分区415中,而块C 405和块D 407都在分区417中。在翻译后的源程序中,控制直接从块A 401传送到块B 403中,因为块A 401和B 403在同一分区415中。然而,从块B 403至块C 405的控制传送跨过分区边界。于是,控制从块B 403传送到退出边界防护块411。如上所述,退出边界防护411检查其相应进入边界防护413还没有被删除。在多线程程序(下述)中,退出边界防护也获得全局分区锁定,从而可以以线程安全的方式跨过分区边界。控制然后从退出防护边界411传送到其相应的进入边界防护213。执行现在进入到了分区417中。在多线程程序(下述)中,进入边界防护改变当前线程的分区标识符,以反映线程目前在分区417中,并然后释放全局分区锁定。一旦在分区417中,控制从进入边界防护413传送到块C 405,并然后直接从块C 405传送到块D 407。
存储器管理存储器管理是动态二进制翻译器19的各个实施例中所要重点考虑的。为了翻译用于在一种体系结构上执行的程序以允许在另一种体系结构上执行而对存储器的需求较高。当引入优化-诸如等同块(isoblock)、扩展块和组块,如共同未决美国专利申请No.10/439966中所述-时,存储器需求更高,因为每一个这些优化都产生一个主题代码17的序列可以由多个翻译表示的可能性。修改事件要求删除分区,并因此要求删除其中的所有翻译数据(即块结构和目标代码)。
在一个优选实施例中,翻译器19提供其自己的对主题代码分区进行镜像的存储器管理子系统。分区用于通过所有翻译器数据结构所对应的主题代码17区域对所有翻译器数据结构进行分组。有可能一起被无效的部分主题代码17形成分区所有相关翻译器数据结构因此存在于相同的定义完好的目标存储器区域中。如果分区被无效,则可以整体释放与该分区相关联的所有翻译数据(翻译器结构和目标代码),不必单独地释放每个结构。
在该具体实施例中,翻译器19通过存储器源对象执行所有存储器分配。每一分区有一个相应的存储器源。存储器源通过常规方式-诸如mmap()系统调用-从操作系统获得存储器,但是它们不是整体进行的。其它翻译器代码(包括伪目标代码)按照需要获得存储器(即更少量地),但是从每个分区存储器源,而不是直接从操作系统获得。这样通过减少下层与存储器相关的系统调用的数量和频率而提高了翻译器19的性能。存储器源也提供用于一次刷新存储器源的全部内容的功能。存储器源可以通过实际释放下层存储器或通过简单地丢弃其已经从该存储器进行的所有“分配”(即将记录(slate)清除,同时保留下层存储器)来实施刷新。
存储器19的存储器子系统也简化删除分区的处理。为了删除分区,翻译器19必须(i)置空所有前任分区的退出防护的副本链接;(ii)通知所有后继分区可以丢弃它们的相应进入防护;以及(iii)删除所有翻译结构和属于分区的目标代码。如果没有存储器管理子系统,第三步骤(iii)要求翻译器遍历每一分区的翻译结构和目标代码集合,以分别释放每一结构。如果使用存储器子系统,可以通过简单地刷新存储器源,一次释放所有分区结构。
尽管已经示出并描述了少数几个优选实施例,但是本领域的熟练技术人员可以理解的是,不脱离如在所附权利要求书中所定义的本发明的范围,可以进行各种改变和修改。
需要注意与本申请同时申请的或者之前申请的、以及与本说明书都已经公开给公众的所有文件和文档,并且所有这些文件和文档的内容都在此引作参考。
在本说明书(包括任何所附的权利要求书、摘要和附图)中所公开的所有特征,和/或这样公开的任何方法或处理的所有步骤可以任意组合,除了至少这些特征和/或步骤中的某些相互冲突的组合之外。
在本说明书(包括任何所附的权利要求书、摘要和附图)中所公开的每一特征都可以通过用于相同、等同或相似目的的替换特征代替,除非明确说明之外。于是,除非明确说明之外,所公开的每一特征只是一般类的等同或相似特征的一个例子。
本发明并不限于前述实施例的细节。本发明扩展到本说明书(包括任何所附的权利要求书、摘要和附图)中所公开特征的任何一种新的、或任何新的组合,或者扩展到所公开的任何方法或处理的步骤的任何一种新的、或任何新的组合。
权利要求
1.一种在将主题代码(17)翻译成翻译后的目标代码(21)期间对主题代码(17)进行分组以考虑自修改主题代码(17)的方法,包括在将主题代码(17)翻译成翻译后的代码期间,以及也在随后执行翻译后的代码期间,识别所述主题代码(17)中的自修改代码事件;和当识别自修改代码事件时,将包含所述主题代码(17)的存储器区域划分成主题地址的至少一个主题指令组,其中每一主题指令组包括所述存储器中受到各自的自修改代码事件影响的一个或多个范围的主题代码地址。
2.根据权利要求1的方法,其中每一主题指令组还与对应于包含在该主题指令组中的主题代码(17)的翻译后的目标代码(21)相关联。
3.根据任一前述权利要求的方法,其中每一所述主题指令组表示不与由其它主题指令组所描述的存储器区域交迭的存储器区域。
4.根据任一前述权利要求的方法,其中每一所述主题指令组表示可以与包含在其它主题指令组中的存储器区域交迭的存储器区域。
5.根据任一前述权利要求的方法,其中自修改代码事件修改各自范围的主题代码地址,所述方法还包括修改存在于所述存储器中的、包含受到所述自修改代码事件影响的主题代码地址的主题指令组。
6.根据权利要求5的方法,其中所述主题指令组修改步骤包括创建新主题指令组,以包括包含对应于所述自修改代码事件的被修改主题代码(17)的主题代码地址;和对于主题代码地址范围与新创建的主题指令组的主题代码地址交迭的现存主题指令组,修改所述现存的主题指令组,以从与新创建的主题指令组的主题代码地址交迭的所述现存主题指令组中删除所述主题代码地址,使得所述主题指令组不再交迭。
7.根据权利要求6的方法,其中每一主题指令组还与对应于包含在该主题指令组中的主题代码(17)的翻译后的目标代码(21)关联,所述方法进一步包括删除与响应于所述自修改代码事件而已经被修改的主题指令组相关联的翻译后的目标代码(21);和翻译用于包含在所述被修改的主题指令组中的主题代码(17)的新目标代码(21)。
8.根据权利要求6或7的方法,进一步包括当翻译后的目标代码(21)的包含在主题指令组中的相应主题代码(17)被翻译时,将所述翻译后的目标代码(21)与该主题指令组关联。
9.根据权利要求8的方法,其中每一主题指令组包括已经被翻译的主题代码地址的特定范围,使得所述特定范围的已经被翻译的主题代码地址包括所述主题指令组内的活动子组,所述方法进一步包括确定所述新创建的主题指令组的主题代码地址是否与任何现存主题指令组的所述活动子组中的任何主题代码地址交迭;和对于具有与所述新创建的主题指令组的主题代码地址交迭的活动子组的现存主题指令组删除与响应于所述自修改代码事件而已经被修改的主题指令组相关联的翻译后的目标代码(21);和翻译用于包含在所述被修改的主题指令组中的主题代码(17)的新目标代码(21)。
10.根据权利要求9的方法,其中每一主题指令组包括一个或多个范围的还未被翻译的主题代码地址,其被称为主题指令组内的非活动子组,所述方法进一步包括对于具有不与所述新创建的组的主题代码地址交迭的活动子组、但是具有与所述新创建的主题指令组的主题代码地址交迭的非活动子组的现存主题指令组修改所述现存主题指令组,以从与新创建的主题指令组的主题代码地址交迭的所述现存主题指令组中的所述非活动子组中删除所述主题代码地址,使得所述主题指令组不再交迭;和使与所述现存组中的活动子组相关联的翻译后的目标代码(21)保持不变。
11.根据任一前述权利要求的方法,进一步包括识别存储器中彼此相邻的、具有允许将它们组合的特征的主题指令组;和将所述相邻主题指令组聚合成单个组合的主题指令组。
12.根据任一前述权利要求的方法,其中在解码所述主题代码(17)期间识别所述自修改代码事件,所述方法进一步包括将特定翻译结构插入到翻译后的目标代码(21)的控制流中,作为被识别的自修改代码事件的表示。
13.根据权利要求12的方法,响应于在执行所述翻译后的目标代码(21)期间遇到所述特定翻译结构,所述方法进一步包括识别受到自修改代码事件影响的主题代码地址的范围,并利用所识别的主题代码地址的范围在存储器中创建主题指令组。
14.根据任一前述权利要求的方法,进一步包括识别当前主题指令组中表示实际或可能将控制传输到当前主题指令组之外主题地址的控制流指令。
15.根据权利要求14的方法,其中在解码所述主题代码(17)期间识别所述控制流指令,所述方法进一步包括将特定退出翻译结构插入到翻译后的目标代码(21)的控制流中,作为所识别的控制流事件的表示。
16.根据权利要求15的方法,其中利用一对特定翻译结构表示从一个主题指令组中主题代码(17)传送到不同的第二主题指令组中主题代码(17)的控制流,其中所述特定翻译结构对包括所述退出结构以及进入结构,使得每一退出结构包含对与接下来所要执行的后继主题指令组相关联的副本进入结构的特定参考。
17.根据权利要求16的方法,当在执行与当前主题指令组相关联的目标代码(21)期间遇到退出结构时,所述方法进一步包括验证在将控制从当前分区传送到后继组之前,在后继主题指令组中存在副本进入结构。
18.根据权利要求17的方法,当在执行与当前主题指令组相关联的目标代码(21)期间遇到退出结构时,其中所述退出结构不与后继主题指令组中所存在的副本进入结构相关联,创建这种进入结构,并且将其与包含所要执行的后继主题地址的适当后继主题指令组关联,并且修改所述退出结构,以特定地参照所述新创建的进入结构。
19.根据权利要求16、17或18的方法,其中存在包含所有分区的退出结构和进入结构的一组边界防护,所述方法进一步包括只要响应于自修改代码事件而删除主题指令组,就修改所述一组退出结构和进入结构。
20.根据任一前述权利要求的方法,其中当主题代码(17)定义多线程程序时,所述方法进一步包括当主题指令组正被另一线程修改时,防止其它线程进入主题指令组。
21.根据任一前述权利要求的方法,其中每一主题指令组进一步与对应于包含在该主题指令组中的主题地址的翻译后的目标代码(21)相关联,其中每一分区包括表示在主题指令组之间传送的控制流的一组进入结构和退出结构,使得每一退出结构包含对接下来所要执行的后继主题指令组中的副本进入结构的特定参考,所述方法进一步包括提供具有对主题指令组进行镜像的区域的存储器管理子系统,其中所述存储器管理子系统存储目标代码(21)、和与其相应目标代码(21)一起与主题指令组相关联的进入结构和退出结构;和只要该特定主题指令组被修改,就删除所述存储器管理子系统的对应于特定主题指令组的整个区域。
22.一种计算机可读存储介质,在其上面存在计算机可读代码形式的翻译器软件,其可以通过计算机执行,用于执行任一前述权利要求的方法。
23.目标处理器;和用于执行权利要求1至21中任一项的方法的翻译器代码的组合。
全文摘要
翻译器所采用的一种分区技术,将主题代码(17)空间划分成区域,此后称之为分区,其中每一分区包含主题代码(17)和相应目标代码(21)的不同一组基本块。分区技术将主题代码(17)的翻译器表示以及主题代码翻译划分成主题存储器的非交迭区域。通过这种方式,当源程序修改主题代码(17)时,只需要丢弃实际受到自修改代码影响的那些分区,并且可以保留未受影响的分区中的所有翻译。该分区技术的优点在于,其限制了响应于自修改代码操作而必须重新翻译的目标代码(21)的数量。在另一处理中,分区技术允许也包括自修改代码的多线程源程序以线程安全的方式执行代码修改。
文档编号G06F9/445GK1836210SQ200480023277
公开日2006年9月20日 申请日期2004年7月13日 优先权日2003年7月15日
发明者艾利克斯·布朗, 保罗·托马斯·诺尔斯, 杰兰特·诺斯 申请人:可递有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1