首页 / 动态二进制优化

动态二进制优化失效专利 发明

技术领域

[0001] 本发明一般涉及数字数据处理,尤其涉及计算机编程代码的动态优化。

相关背景技术

[0002] 二十世纪后半叶,开始发生被称为信息革命的事件。虽然信息革命在影响范围上是比任何某个事件或机器都要广泛的具有历史意义的发展,但是没有哪个单个设备比数字电子计算机更能代表信息革命。计算机系统的发展当然已经是一场革命。每一年,计算机系统都变得更快,存储更多的数据,并为用户提供更多的应用。
[0003] 计算机系统的核心部分是一个或多个中央处理单元(CPU),也被称为处理器,它们执行存储在计算机存储器中的指令。从计算机硬件的角度来看,大多数的系统都以基本相同的方式运行。处理器能够执行所定义的一组非常简单的操作,如算术、逻辑比较以及将数据从一个位置移动到另一个位置。然而,每个操作执行得非常快。多层次的计算机程序代码引导计算机执行大量的这些简单操作,使得计算机能够执行复杂的任务。尽管所定义的一组简单操作是有限的,但是能够在程序代码中规定的这些操作的可能序列和组合实际上是无穷的。
[0004] 在数字计算机非常早期的历史中,指示计算机执行某一任务的计算机程序是以可由计算机处理器直接执行的形式写成的。即使在执行相对简单的任务时,这些程序对人来说也很难编写、理解和维护。随着这种程序的数量和复杂度的增加,这种方法变得明显不再可行。为了使得计算机程序更容易开发,开发了大量的并且多样化的高级语言以支持创建计算机程序代码。
[0005] 虽然高级语言的特征各有不同,但是所有这些语言都用来使得人能够更容易地编写执行某一任务的程序。通常地,高级语言以人类程序员容易理解而不是计算机容易理解的方式来表示操作、固定值、变量和其他结构。这些程序并不能直接由计算机处理器执行。为了在计算机上运行,这些程序必须首先从人类可读的形式(源代码)转换成可由计算机处理器执行的某种东西,即,可被处理器直接读取并执行的指令序列。
[0006] 可被处理器直接读取并执行的指令(处理器可执行指令)是预定义格式的二进制比特序列,每一比特的位置特定于读取它并对其译码的处理器中的逻辑。比特值的组合规定将要执行的一个操作或若干操作、数据源或数据目的地、分支条件或分支目的地等等。比特序列的格式编排和比特组合的含义定义了处理器的“指令集”。虽然任何处理器执行的一组有限的简单操作与另一个处理器执行的一组有限的简单操作相似,但是每个处理器的指令集(即,预定义格式和处理器可执行指令二进制比特序列的含义)并不相似。
[0007] 大体上说,源代码是通用的,并且可被任何受过使用可应用语言训练的人理解,虽然可执行代码对具体的计算机系统环境来说是特定的,并且只能在该计算机系统或类似配置的计算机系统上执行。具体地说,可执行代码对处理器指令集来说是特定的,尽管它可能对计算机系统的其他参数也是特定的。
[0008] 目前存在将高级语言的源代码转换成处理器指令集中的处理器可执行指令的各种技术。可以对源代码进行“解释”,意思是某一特殊程序(“解释器”)获取序列中的每一条源代码语句,并执行与每一条源代码指令对应的小例程(即,处理器可执行指令集中的一系列指令)。解释对于达到某些目的是有用的,但是它通常是非常低效的。
[0009] 传统上,为了更高的执行效率,对源代码的若干单独部分(模块)进行编译以形成处理器可执行指令的若干模块,它们可以被链接在一起形成更大的程序(尽管某些程序只包含单个编译模块)。这些程序以可执行形式被保存在数字介质存储装置中,并可以以该形式分发给其他计算机系统,或继续留在它们最先被编译的系统上。随后它们通常以此形式被执行许多次。编译自身是一项由特殊的计算机程序(编译器)执行的任务,会耗费大量时间。通常,编译涉及对可执行代码的一些优化,它要求对程序内的各个指令序列进行分析。与解释的代码不同,编译的模块中的得到的处理器可执行指令不一定与特定的源指令对应,不一定遵循同一序列,尽管它们必定产生相同的逻辑输出。由于期望这些程序被执行许多次,因此编译的负担扩展到许多执行中。传统形式的编译有时被称作“静态编译”。
[0010] 近年来,“及时”动态编译或优化已经越来越令人感兴趣。与静态编译类似,“及时”或动态编译/优化涉及生成优化的处理器可执行指令。但与静态编译不同,程序的处理器可执行指令在处理器可执行指令作为其一部分的程序执行期间或者执行的一部分而生成(目标程序)。这实际上意味着及时或动态编译/优化旨在被执行多次,例如每次执行程序时或针对执行程序的每个用户进程。
[0011] 明显地,与传统的静态编译比较,动态编译/优化有下述缺点:每次执行程序时或针对每个新的用户进程,它都会再次执行。然而,及时或动态编译/优化也有各种优点,使得它在许多情况下具有吸引力。例如,动态编译的代码在将要执行它的系统上生成,并且可以从通用的中间级代码形式(处于高级源语言和处理器可执行形式之间)生成,这有利于程序的可移植性。这种方法在大家熟知的JAVA(TM)虚拟机环境中经常使用。此外,系统在执行时可用的附加知识(如,精确的系统配置、使用的代码模块和代码执行的实际模式)使得可能生成较之通常使用静态编译器能够生成的编译代码更有效率的编译代码。这些附加知识在实际代码使用模式的情形中尤其有效,这允许动态编译/优化关注于优化代码的特定部分。
[0012] 动态编译的一种形式是在执行时从之前编译的可执行代码生成处理器可执行指令,通常不使用原始源代码。这被称作动态二进制优化。动态二进制优化通常用来模拟(emulate)具有不同的、通常是更老的指令集架构的计算机系统。即,可以将之前被编译成包含更老的指令集架构的处理器可执行指令的可执行计算机程序从之前编译的可执行代码重新编译生成当前处理器的指令集的处理器可执行指令。
[0013] 尽管动态二进制优化通常用来支持模拟,但是它具有改善执行效率的潜力,即使是在原始编译的可执行代码被编译成与当前处理器的指令集架构相同的指令集架构的情形中。换言之,即使之前的程序编译版本完全能够在当前处理器上执行,而不需要进一步的编译、优化或翻译,但可能经过动态二进制优化的执行效率在某些情况下可能表明对已经编译的代码进行动态重新编译的额外开销是合理的。在一些情形中,如果指令集架构已经被增强为具有未被原始静态编译代码(可能相当老)利用的新功能,那么这些执行效率可以得到提升。通常地,只有之前编译的代码的可选择部分才将被动态重新编译,这是因为动态编译的一个优点是,它能够识别“热点”(经常执行的代码部分),并将优化活动集中于这些热点。
[0014] 对使用相同指令集架构的程序进行动态二进制优化存在一个难点,因为编译器通常自由地使用可应用指令集架构中的所有可用的寄存器进行程序优化。因此,当目标程序以其原始编译形式执行时,通常使用所有可用的寄存器。动态二进制优化由在同一计算机上执行的另一个程序(称作“虚拟机”)执行。虚拟机必须使用这些相同的寄存器,因此这些寄存器的内容被保存到存储装置,并在虚拟机和目标程序之间切换执行上下文时从存储装置中恢复。为了保存大多数计算机架构中的寄存器,至少一个寄存器必须可用于存放关于保存寄存器的存储器的区域(“上下文保存区域”)的地址信息。如果目标程序被编译成使用所有可用的寄存器,那么无法保证用于存放上下文保存区域的地址信息的寄存器将是可用的。
[0015] 尽管已经有人提出通过动态定位未使用的寄存器来解决此问题,但是却未能找到一个解决方案将一个或多个有效使用的寄存器的内容临时存储(“溢出”)到存储器,此解决方案导致出现严格的寄存器状态兼容性和数据完整性/安全性的各种问题。因此,虽然不一定认识到,但存在一种支持动态二进制优化的更好的机制的需要,具体是使用与目标程序相同的指令集架构来支持动态二进制优化。

具体实施方式

[0029] 参照附图,其中相同的数字表示相同的部件,图1是根据本发明的优选实施例的在计算机程序代码的动态二进制优化中使用的计算机系统100的主要硬件组件的高级表示。计算机系统100包括至少一个执行预定义指令集的指令并处理来自主存储器102的数据的通用可编程处理器(CPU)101。主存储器102优选地是使用各种存储器技术中任一种的随机存取存储器,其中数据从存储装置加载或以其他方式供CPU101处理。
[0030] 一个或多个通信总线105提供在CPU101、主存储器102和各种I/O接口单元111-114(也可被称为I/O处理器(IOP)或I/O适配器(IOA))之间传输数据的数据通信路径。I/O接口单元支持与各种存储装置和I/O设备的通信。例如,终端接口单元111支持一个或多个用户终端121-124的附接。存储装置接口单元112支持一个或多个直接存取存储设备(DASD)125-127(它们是典型的旋转磁盘驱动存储设备,尽管替代性地它们可以是其他设备,包括被配置为从外观上看起来是主机的单个大容量存储设备的盘驱动器阵列)的附接。I/O设备接口单元113支持附接任何各种其它类型的I/O设备,例如打印机128和传真机129,应该理解的是,可以使用其他或更多类型的I/O设备。网络接口114支持连接到一个或多个外部网络130(示出了其中一个),以与一个或多个其他的数字设备通信。网络130可以是本领域中已知的任何各种局域或广域网络。例如,网络130可以是以太网局域网,或者可以是因特网。
[0031] 但应当理解的是,图1的目的是以高级图示出计算机系统100的代表性的主要组件,各个组件可以具有比表示在图1中更高的复杂度,不同于或者除了那些图1所示出的那些,还可能存在其他的组件,这些组件的数量、类型和配置可能会发生变化,大型计算机系统通常具有比表示在图1中更多的组件。本说明书公开了若干具有这种附加复杂度或附加变化的特定示例,应该理解的是,这些仅用作示例,而不一定是只有这些变化。
[0032] 虽然为了说明的目的在图1中只示出单个CPU101,但是计算机系统100可以包含多个CPU,这在本领域中是已知的。虽然主存储器102在图1中被示为单个整体实体,但是存储器102可能实际上是分布式和/或分级的,这在本领域中是已知的。例如,存储器可能存在于多级缓存之中,这些缓存可以进一步按功能划分,使得一个缓存存放指令,而另一个存放由一个或多个处理器使用的非指令数据。存储器还可以进一步是分布式的,与不同的CPU或多组CPU相关联,这在任何各种所谓的非统一存储器存取(NUMA)的计算机架构中是已知的。虽然通信总线105在图1中被示为单个实体,但是实际上各种系统组件之间的通信通常是通过总线、接口等复杂的层级完成的,其中较高速度的路径用于CPU101和存储器102之间的通信,较低速度的路径用于与I/O接口单元111-114的通信。总线105可以布置成任何各种形式,如分级的点至点链接、星状或网状配置、多条分级总线、并行和冗余路径等等。例如,如在NUMA架构中已知的,通信路径可以被布置为以节点为基础。总线可以使用例如工业标准PCI总线或任何其他合适的总线技术。虽然多个I/O接口单元被示为从各种通信路径到达各种I/O设备的分离的总线105,但是可替代性地,也可以将部分或全部的I/O设备直接连接到一个或多个系统总线。
[0033] 如图1所示的计算机系统100具有多个附接终端121-124,例如,可能是典型的多用户“大型计算机(mainframe)”的计算机系统。通常情况下,在此情形中,附接设备的实际数量大于图1中所示的数量,尽管本发明不局限于任何特定大小的系统。访问计算机系统100的用户工作站或终端可能被用来向执行应用的用户提供用户界面,这些应用访问数据库(类似于调用服务器通过网络访问数据库的客户端应用程序),但直接在计算机系统100上执行,而不需要通过网络进行通信。系统100替代性地可以是单用户系统,通常只包含单个用户显示器和键盘输入。此外,虽然本发明此处出于说明目的被描述为在单个计算机系统中体现,但是本发明可以替代性地通过使用彼此通信的计算机系统的分布式网络来实现,其中此处描述的不同的功能或步骤在不同的计算机系统上执行。具体地,目标程序的静态代码编译可以在第一计算机系统上执行,而同一目标程序的执行和执行过程中的动态二进制优化可以在第二计算机系统上进行。
[0034] 虽然已经描述了各种系统组件并以高级图示出,但是应该理解的是,典型的计算机系统包含许多不是理解本发明所必需的其他未示出的组件。在一个优选实施例中,计算TM机系统100是多用户计算机系统,如基于IBM i/Series 架构的计算机系统,应该理解的是,本发明可以在其他计算机系统上实现。
[0035] 图2是根据一个优选实施例的包括某些相关联的缓存结构的中央处理单元(CPU)101(有时也称为处理器或处理器核)的主要组件的高级图,比图1所示更详细地示出了CPU101。如前所述,系统100可以包含多个CPU,尽管图2中只示出单一的一个。CPU101包括指令单元部分201、专用寄存器部分205和执行单元部分211。图2中还示出1级指令缓存(L1I-Cache)221、1级数据缓存(L1D-Cache)222、2级缓存(L2Cache)223、地址转换单元
224和存储器接口225。在一般情况下,指令单元201从L1I-Cache221获取指令,译码CPU预定义指令集的指令以确定要执行的操作,并解析分支条件以控制程序流程。执行单元211对寄存器中的数据进行算术和逻辑运算,并从L1D-Cache222加载或存储数据。专用寄存器
205包含用于控制CPU的指令流和适当操作且未被包含在指令单元201或执行单元211中的各种状态数据。L2Cache223是2级缓存,通常大于L1I-Cache221或L1D-Cache222,它提供数据给L1I-Cache221和L1D-Cache222。L2缓存223从更低级别的缓存(未示出)或通过存储器接口225从主存储器中获取数据。
[0036] 任何一级缓存在逻辑上都是主存储器的扩展。在一个示例性实施例中,L1和L2缓存221-223与CPU被物理封装在一起,例如,被实现在与CPU相同的集成电路芯片上。出于此原因,这些缓存有时被视为是CPU的一部分。在本实施例中,每个CPU都有它自己各自的L1和L2缓存,这些缓存不与其他CPU共享,尽管替代性地可以共享一些或所有缓存。图2表示的目的是代表性的,而并非将本发明限制为任何特定的物理或逻辑缓存实施方式。应该认识到,可以根据不同的布置来设计处理器和缓存,一个或多个处理器芯片可以包括比图2所示更多的缓存或更少的缓存,或根本没有缓存。
[0037] 指令单元201包括分支单元202、指令译码/调度单元203以及指令寄存器和缓冲器204。来自L1I-cache221的指令在执行前被加载到缓冲器204。根据CPU的设计,可能存在多个缓冲器(例如,用于不同线程的缓冲器,或者在一个线程内,一个缓冲器用于连续一系列指令,其他缓冲器用于转移到位置(branch-to location)),其中每一个可以包含多个指令。译码/调度单元203在当前机器周期中从一个或多个缓冲器204中选择一个或多个将被调度以供执行的指令,并根据处理器预定义指令集的语义来译码(多个)指令以确定将要执行的(多个)操作或分支条件。分支单元202通过评估分支条件控制程序流程,并从L1I-cache221重新填充缓冲器204。
[0038] 执行单元211包括用于存储数据的一组通用寄存器212和用于响应于指令单元201译码的指令对通用(GP)寄存器212中的数据进行算术和逻辑运算的标量算术逻辑单元(ALU)213。执行单元211可以进一步包括任何各种专用计算子单元。例如,图2中示出了浮点运算子单元214,它优选地是用于使用较大操作数(如双精度64比特操作数)执行浮点运算的专用浮点硬件流水线。可以可选地包括其他专用单元(未示出),诸如用于并行地对多个操作数执行常见运算的矢量运算子单元。浮点子单元214(可选地,其他专用单元)中每一个都包括它自己各自的寄存器组215。通用寄存器212和浮点寄存器215一般可供在处理器101上执行的已编译程序使用。具体地,对在处理器101上执行的程序进行编译的编译器可以使用任一或所有这些寄存器来存放任意程序状态数据,如编译器确定将产生最有效率的程序执行。除了图2中所示的组件,执行单元211还可以包括附加的逻辑电路、计数器、控制硬件等等,并可以包括某些单元的多个副本(如,多个ALU213)。应该理解的是,图
2中所示的执行单元211的目的是代表性的,执行单元可以有附加的子单元和组件(包括附加的流水线和寄存器),或者可以有比图2所示的所有组件更少的组件。
[0039] 专用寄存器205包含除了指令(被包含在指令寄存器204中)以及指令对其进行操作的通用数据(包含在寄存器212、215中)之外的某些状态数据。例如,专用寄存器205可以包括机器状态寄存器206,它可能包含除其他之外的指示当前正在执行的一个线程或多个线程(如果CPU支持多个并行线程执行)的特权级别的数据;中断矢量207;错误指示;以及其他专用寄存器。具体地,专用寄存器205包括一个或多个上下文切换寄存器208,它们被保留供特殊的具有特权的进程(如,操作系统内核)使用,用于存放在切换执行上下文中使用的某些状态信息。即,当执行的进程线程由于任何各种原因被挂起并将在稍后恢复时,线程的状态,具体地,在另一个线程的可执行指令和状态数据被加载并在处理器上开始执行之前,寄存器的状态被保存在存储器102的上下文保存区域中。操作系统使用上下文切换寄存器208存放上下文切换所需要的数据,具体是识别上下文保存区域在存储器中的位置的地址数据。
[0040] L1I-Cache221和L1D-Cache222是提供数据给指令单元和执行单元的单独的指令缓存和数据缓存,尽管替代性地它们也可以是单个组合的缓存。L2-Cache223是包含指令和非指令数据的无区别(non-discriminate)缓存。通常情况下,数据由指令或执行单元取自L1缓存或存储在L1缓存,如果L1缓存中的数据不可用,那么从L2缓存223加载数据到L1缓存,其继而通过存储器接口225从较低级别的缓存或主存储器获取数据。根据处理器的设计,可以绕开某一级缓存并且从更低级别的缓存或存储器加载数据。
[0041] 地址转换单元224将处理器生成的有效地址(在某些架构中,被称为“虚拟地址”或其他名称)转换成存储器中对应的真实地址。如本领域中已知的,在一方面的有效地址和另一方面的真实地址之间存在根本差异。有效地址与物理存储位置不具有固定的对应关系;这种对应关系会随着从存储装置加载新页面到主存储器、随着进程变化等等而变化。真实地址与固定的物理存储位置对应,尽管它不一定直接转换到此位置。处理器在有效地址空间中生成与每个相应的执行进程对应的有效地址(它可被称为“虚拟”或某些其他的术语)。在某些计算机架构中,有多个级别的有效或虚拟地址,可能需要进一步的转换。在某些架构中,处理器生成的有效地址可能只是指令自身包含的地址。然而,在大多数现代系统中,有效地址空间相对于指令大小是如此之大以至于指令不包含完整的地址。因此,地址被包含在指令引用的寄存器中,或者被获取为多个值的总和,这样的偏移值被包含在指令中,一个或更多值中的每一个被包含在相应的寄存器中。地址转换单元224将有效地址进一步转换成“真实地址”,与数据所在的实际存储位置对应。应该理解的是,各种计算机架构采用不同的寻址结构,本发明不限于任何特定形式的寻址。
[0042] L1I-Cache221和L1D-Cache222优选地使用有效地址寻址,因此访问1级缓存不需要地址转换。然而,L2缓存223及其以下所有的存储器都使用真实地址寻址。因此,如果必须访问较低级别的缓存或主存储器,那么处理器生成的有效地址被首先转换成真实地址。应该理解的是,L1缓存替代性地可以使用真实地址寻址,或者任何更低级别的缓存替代性地可以使用有效地址寻址。
[0043] 地址转换单元224被表示为单个逻辑实体,但通常包括多个表和逻辑电路,它们可以分布在各种芯片位置。例如,地址转换机制可以包括转换旁路缓冲器、有效-真实地址转换表、段表和附加结构。此外,分立的结构(separate structure)可用于转换指令和非指令数据。
[0044] CPU101可以是在同一机器周期内支持多个线程并行执行并同时调度来自不同线程的指令的多线程处理器,或者它可以是单线程处理器。当支持多线程时,通常存在单独的一组多数寄存器用于每个线程,即,存在单独的一组通用寄存器212和浮点寄存器215用于每个线程。此外,可以复制某些其他状态或专用寄存器来支持多个活动线程。执行单元流水线硬件、指令单元和缓存通常由所有线程共享。
[0045] 虽然已经描述并以高级图示出了各种CPU组件,但应该理解的是,优选实施例中的CPU包含许多对理解本发明来说不是必需的未被示出的其他组件。例如,在一个典型设计中,需要各种附加的专用寄存器。此外,应该理解的是,图2所示的CPU仅仅是CPU架构的一个示例,CPU101内的组件的数量、类型和布置可以存在许多变化,除了那些已经示出的还可以存在未示出的组件,并非示出的所有组件都存在于CPU设计中。例如,缓冲器和缓存的数量和配置可以变化;执行单元流水线的数量和功能可以变化;寄存器可以被配置为不同的阵列和组;专用浮点硬件可以存在或不存在;等等。此外,CPU101可以使用简单或复杂的指令集。
[0046] 图3是存储器102中系统100的主要软件组件的概念图。操作系统内核301是可执行代码和提供各种低级软件功能(如,本领域所熟知的设备接口、存储页面管理、多任务管理和调度等等)的状态数据。动态二进制优化器302有时也被称作虚拟机,是用于支持执行并对编译的可执行目标程序进行动态优化的可执行程序,如在本说明书中详细说明的。静态编译器303是将高级语言中的源代码模块(或者,替代性地,中间的、之前分析的符号形式的代码模块)编译成处理器可执行指令的目标代码模块的可执行计算机程序。构建程序(build utility)304通过并入或链接(也称作绑定)多个之前编译的目标代码模块和程序来构建应用程序的可执行计算机程序。
[0047] 图3还示出了多个源代码模块311A-C(在此总称为特征311)、多个中间代码模块312A-C(在此总称为特征312)和多个目标代码模块313A-C(在此总称为特征313)。源代码模块311是使用源编辑器(未示出)或通用编辑器(未示出)创建的高级语言代码模块。这些模块可以在其他计算机系统上创建。中间代码模块是中间符号语言代码模块,中间符号语言既不是用于人类表示的高级语言,也不是可直接执行的代码。中间代码表示的示例是斯坦福的p-代码、IBM(TM)的w-代码、IBM(TM)的New Machine Interface(NMI)代码和JAVA(TM)字节代码。中间代码通过专用分析器或“前端编译器”(未示出)从源代码产生,或替代性地作为静态编译器303编译的副产品。目标代码模块313是包含可直接在处理器101上执行的并且由静态编译器303产生的处理器可执行指令的模块。每个目标代码模块要么直接从对应的源模块311产生,要么通过将源模块预编译成中间代码模块312并且然后将中间代码模块编译成对应的目标代码模块而产生。
[0048] 用户应用程序314、315是构建程序304从多个目标代码模块313构建的可执行程序。构建程序在构建应用程序时可能进一步并入来自各种程序库(未示出)的已编译例程。
[0049] 如在本技术领域中众所周知的,OS内核301支持多个进程的并行执行。对于每个并行执行的进程,保持各自的进程状态数据区域321-323,每个进程状态数据区域都包含执行进程特定的状态数据。图3描述了三个进程状态数据区域321-323,应该理解的是,这个数字可以有所不同,通常要大得多。每个进程状态数据可以包括例如进程栈、进程堆和/或其他数据结构。
[0050] 具体地说,通过动态二进制优化器302的实例(instance)执行目标用户应用程序的进程被表示为进程状态数据区域323。除了可能存在于任何进程状态数据区域中的任何各种数据结构,进程状态数据区域323还包括目标程序上下文保存区域324、目标程序优化代码缓存325和目标程序数据区域326。目标程序上下文保存区域324用来在目标程序被优化器中断以便优化器能够执行各种优化功能时暂时存储处理器状态。目标程序优化代码缓存325存储优化器在动态优化过程中修改的目标程序代码;该优化代码不一定被保存,由于使用动态二进制优化器执行目标程序,因此原始目标程序可执行代码保持不变。目标程序数据区域326存放目标程序在执行过程中所引用的数据。
[0051] 图3中的各种软件实体都被表示为单独的实体,或被包含于其他实体内。然而,应该理解的是,此种表示仅用于示例目的,特定的模块或数据实体可以是单独的实体,或者是公用模块或模块包的一部分。此外,虽然在图3的概念表示图中示出了一定数量和类型的软件实体,但是,应该理解的是,这些实体的实际数量可以变化,具体地,在复杂的计算机系统环境中,这些实体的数量和复杂度通常要大得多,也可能存在其他实体(未示出)。此外,虽然在图3中为了表示的完整性将软件组件301-304、311-315和321-326描述为位于单个计算机系统100上,但是并非所有的程序、功能和数据都一定存在于单个计算机系统或在单个计算机系统上执行。特别是,静态编译器303和/或构建程序304可以位于与动态二进制优化器302所在系统不同的系统上,源代码311、中间代码312或目标代码模块313中的任一个可以与或可以不与动态二进制优化器位于相同的系统。事实上,虽然为了完整性在图中3示出了源模块,但是在许多情况下,源模块可能不再存在,或者如果它们存在,可能不可用或在某个未知位置。
[0052] 虽然图3中的软件组件被概念性地示为驻留在存储器102中,但是应该理解的是,通常情况下,计算机系统的存储器太小以至于不能同时存放所有的程序和数据,信息通常存储在包括一个或多个大容量存储设备(如,旋转磁盘驱动器)的数据存储设备125-127中,操作系统根据需要将信息分页存储进存储器。此外,应该理解的是,图3的概念性表示并非暗示任何特定的存储器组织模型,系统100可能采用单一地址空间虚拟存储器,或者可能采用重叠的多个虚拟地址空间。
[0053] 图4是示出根据一个优选实施例的使用动态二进制优化器创建可执行目标程序并执行目标程序的一般过程的高级流程图。参看图4,程序可以直接从源代码编译(如,从块401开始的流程所示),或者可以从一些中间形式的代码编译(如,从块402开始的流程所示)。如块401所示的源代码可以由程序员以各种常规方式(如,使用源编辑器)生成。根据一个优选实施例,源代码不要求使用特殊语句或结构,一般任何常规的高级语言源代码都可以被动态优化,尽管并非所有的代码都会以相同的效率优化。中间形式的代码可以由用于此目的专用中间代码生成器生成,或者可以是之前编译的副产品。例如,在IBM i平台的情形中,编译器自动生成被称为“NMI代码”的中间表示,并将其连同处理器可执行指令一起包括在编译后的目标程序中。通常情况下,在老的程序的情形中,原始源代码可能不再可用。然而,如果原始源在某个平台上编译或使用生成中间表示(如,“NMI代码”)的编译器,那么该程序可以从中间表示重新编译,尽管原始源不可用。源或中间代码表示可能在块403-405中所述的编译和执行之前已经生成了许多年,并且可能在使用不同的处理器和/或操作系统架构的不同的系统上生成。
[0054] 无论是使用源代码还是中间表示,编译器都对一个或多个程序模块进行编译,以产生处理器可执行指令模块(也被称为目标代码模块),其中一个或多个寄存器被保留供动态二进制优化器使用。编译过程表示为图4的高级流程图中的块403,并在图5中更详细地示出。
[0055] 图5是示出根据一个优选实施例的使用动态二进制优化器静态编译供执行的目标程序的一个或多个模块的过程的高级流程图。
[0056] 参看图5,调用并初始化静态编译器303(501块)。在调用编译器时,指定待编译的源代码文件311或中间代码文件312。
[0057] 在各种其他的参数中,静态编译器隐性或显性地确定可供目标程序使用的通用寄存器212的数量,用NGP表示(块502)。此数量可以在编译器中硬编码,但更可能作为编译器的输入参数接收。例如,编译器可能会通过操作系统调用来确定编译器正在其上运行的计算机系统的(多个)处理器中的处理器的类型和通用寄存器的数量,并使用此数量作为默认设置。此默认设置可能会被显性的编译器指示覆盖(override),以编译代码供在具有不同处理器类型的不同机器中使用。
[0058] 编译器进一步确定它是否应该保留任何通用寄存器以供动态二进制优化器在寻址上下文保存区域时使用(503块)。优选地,响应于编译器指示进行一个或多个寄存器的保留。编译器指示可以是源代码文件311或中间代码文件312中的语句,但在一个优选的实施例中,它是在调用编译器时由用户指定的可选编译器参数。优选地,避免需要将这样的指示嵌入源或中间代码文件,因为这些文件可能是非常老的,如果编辑工具或前端编译器/分析器不再可用,那么将语句插入其中可能是很困难的。替代性地,为动态二进制优化器保留一个或多个寄存器可以是默认选项,该选项被自动选择,除非用户指示编译器不保留寄存器。替代性地,编译器可能会被编写为总是保留至少一个寄存器,尽管这被视为是不希望看到的情形,因为可能存在想要使用所有寄存器的情况。
[0059] 如果编译器确定应该保留寄存器(块503的“Y”分支),那么可用的通用寄存器的数量NGP减去将被保留的寄存器数量NR(块504)。在一个优选实施例中,NR是一,尽管替代性地可以使用或者用户可以指定更大的数字。由于每个保留的寄存器必定会减少可用于编译器分配变量的寄存器数量,因此往往会增加交换寄存器内和外部的值的需要,从而降低执行性能,因此不希望保留超过必要的任何更多的寄存器。单个寄存器通常足以指定上下文保存区域地址,因此NR优选地是一。依赖于架构,可能希望为相关上下文保存操作保留一个或多个更多附加的寄存器。如果编译器在块503确定不应该保留通用寄存器,那么绕开块504,并且NGP的值保持不变。
[0060] 编译器可选地分析源文件311以生成中间符号代码表示和源中使用的变量映射、程序名称等等(块505)。这个过程有时被称为“前端编译”。一般来说,这只有当直接从源代码编译时才有必要。如果编译器从中间代码版本编译,那么中间代码通常会包含必要的信息。
[0061] 编译器构建控制流图(块506)。如在编译器技术领域中已知的,控制流图是正在编译的代码模块中的控制流的表示,其包含多个节点和连接这些节点的有向弧(directed arc),其中每个节点代表仅仅具有执行的单一直接(straight)路径的代码指令序列,每条弧代表从一个节点到另一个可能的路径(如,分支)。
[0062] 使用控制流图,编译器选择向可用寄存器分配程序变量(块507),可用于此目的的通用寄存器的数量是NGP。可以采用任何各种寄存器分配技术(在编译器技术领域中现在已有的或以后开发的),只要可用通用寄存器的数量被限制为NGP。依赖于程序需要和使用的分配技术,编译器可以(尽管不一定)分配所有可用通用寄存器供一个或多个程序变量使用,但在任何情况下,如果在块503-504保留一个或多个通用寄存器,那么这些保留的寄存器将不会被分配。
[0063] 编译器使用之前做出的寄存器分配执行任何支持的代码优化,并生成优化的编译代码(块508)。执行的优化将取决于编译器,可以包括例如除去不必要的代码语句、重新排序操作、合并别名(alias)等等,如在本技术领域中已知的。编译器执行任何特定的优化或编译器作为优化编译器,这不是必须的。尽管图5示出优化(块508)在寄存器分配之后(块507)之后进行,但是寄存器分配可以在优化之前或之后,或在某些优化之前其他优化之后进行;通常至少一些优化在寄存器分配之前进行。
[0064] 通常为待编译的每个代码模块单独调用编译器。不同的代码模块可以在大约相同的时间编译,或者可以在不同的时间编译,并且可以在不同的机器上或不同于它们将在其上执行的机器的单个机器上编译。
[0065] 再参看图4,编译之后,使用构建程序304从一个或多个编译的目标代码模块构建程序(块404)。构建是将多个编译的目标代码模块链接成单个可执行程序的过程。得到的可执行程序可以例如是单个文件,其包含头文件和来自一个或多个编译的目标代码模块的嵌入代码并可能包含对外部目标代码模块的引用。依赖于程序架构和/或大小,构建可能是不必要的,并且编译独自产生可执行形式的程序是可能的。
[0066] 可执行程序通常是一个文件(或多个文件)。作为程序文件,它可以无限期地(indefinitely)存储在系统上和/或加载到另一个计算机系统上。在某些架构中,通常在执行之前立即进行构建。
[0067] 然后,使用动态二进制优化器执行程序。程序执行在高级形式上被表示为图4的块405,并在图6中更详细地示出。
[0068] 图6是示出根据一个优选实施例的使用动态二进制优化器302执行目标程序的过程的高级流程图。参看图6,调用动态二进制优化器执行目标程序并在可应用的进程数据区域中分配状态数据结构(块601)。动态二进制优化器本身是可执行程序。当被执行时,它模拟执行其他可执行程序(在此情形中目标程序)的虚拟机,因此目标程序是程序中的程序。像任何可执行程序一样,代表用户进程调用动态二进制优化器,该用户进程具有进程数据区域。用于执行动态二进制优化器的进程的进程数据区域在图2中被示为特征323。在动态二进制优化器保持的状态数据中,有目标程序优化代码325、目标程序数据326和目标程序上下文保存区域324。
[0069] 动态二进制优化器302将陷阱(trap)插入编译的各种目标程序模块(块602)。每个陷阱都使得目标程序代码序列的执行暂停,并将控制返回动态二进制优化器。陷阱可能只不过是转移到优化器自身的预定代码序列的单条处理器可执行指令。在跟踪目标程序执行流程并确定是否优化选择代码部分的方便位置插入陷阱。例如,可以在每次调用例程或从例程返回时插入陷阱。
[0070] 在初始化并插入任何必要的陷阱之后,动态二进制优化器跳转到编译的目标程序中的入口点(块603),使得目标程序的处理器可执行指令的段直接在处理器101上执行(块604)。虽然使用了词语“段”,但是执行的指令在可寻址存储器中不一定是连续的,也不一定是任何预定大小的段。它只是具有一个或多个出口点以及在每个出口点处插入的对应的陷阱的一部分程序。在该段的执行过程中,段的处理器可执行指令可以引用目标程序数据区域326中的数据,以与像是被直接执行时相同的方式加载和存储来自此存储器区域中的数据,而无需动态二进制优化器的任何干预。程序段继续执行,直到遇到陷阱(块605)。
[0071] 优选地,陷阱导致跳转到动态二进制优化器自身内的预定代码段。陷入陷阱(trapping)之后的首要事情是保存处理器的状态(块606)。为达到此目的,保留的通用寄存器(GP寄存器R)被用来寻址目标程序上下文保存区域324。例如,跳转到陷阱位置时遇到的第一条指令可能是将GP寄存器0的内容存储到GP寄存器R指定的有效存储地址;第二条指令可能是将GP寄存器1的内容存储到由GP寄存器R中的值与规定的偏移量之和指定的有效存储地址,等等。由于各种通用寄存器的内容已经被存储,因此这些寄存器变得可供动态二进制优化器用于保存其他状态数据,这可能需要多于单个的寄存器。因此,如上所述,仅需单个保留的寄存器用于保存处理器状态。
[0072] 一旦已经保存目标程序的处理器状态,动态二进制优化器就可以执行任何想要的优化功能。优化器确定目标程序的执行是否已经完成(块607)。如果不是(从块607的分支“N”),那么优化器更新用于进行优化的任何执行数据(块608)。例如,优化器通常会跟踪选择性的代码段的执行频率,如果该段被频繁执行,那么重新优化并重新编译代码。优化器也可以选择重新编译被认为特别缺乏效率的代码。因此,优化器使用此执行数据来确定代码段(如,例程)是否应该被重新优化(块609)。如果决定重新优化代码段,那么重新优化并重新编译对应的代码段(块610),并存储到目标程序优化代码区域325。通常情况下,要被重新优化的段是接着以其它方式执行的段。
[0073] 在一个优选的实施例中,在动态二进制优化器可以进行的优化中,存在利用别名信息的优化,具体是涉及对某些操作的执行的重新排序的优化,其别名信息指示的这些操作的执行可以被安全地重新排序。出于此目的,别名信息优选地在编译时被嵌入目标代码模块313。此项技术在与本申请同日提交的题为《Using Aliasing Information for Dynamic Binary Optimization》的共同受让的美国专利申请序列号第13/016038号(受让人案卷号第ROC920100267US1号)中有更加详细的描述,此申请通过引用在此被并入。然而,在一个替代性实施例中,这样的别名信息不存在和/或不用于优化。
[0074] 当优化器已经完成更新其数据并执行完任何想要的优化时,它从目标程序上下文保存区域重新加载处理器状态,并将GP寄存器R的值重置为上下文保存区域的开始地址(块611)。然后跳转到目标程序执行被挂起的代码位置(块612),并执行下一个目标程序段(块604)。
[0075] 当目标程序已经完成执行时(即,它遇到程序退出点处的陷阱),取道从块607起始的“Y”分支。然后,优化器进行任何所需的数据结构的最后清理,输出数据等,并结束执行(块613)。
[0076] 如上所述,在开始执行时,在块602插入多个陷阱。然而,优化器可以替代性地在每个目标程序段的每个出口点处,在该段刚好要被执行之前插入一个或多个陷阱(如果以前未插入),从而避免在永远不会执行的程序段中插入陷阱的需要。此外,虽然插入陷阱在此作为示例性实施例公开,但还存在动态二进制优化器可以通过其获得对处理器的控制的替代性技术。例如,一些系统使用周期性中断对程序计数器采样并决定何时优化代码段。替代性地,可以有硬件辅助来帮助收集分支踪迹并调用优化器。
[0077] 通常情况下,动态二进制优化器不会生成任何持久的、存在时间超过导致其生成的用户进程的优化代码。依赖于动态二进制优化器的实施,单个用户进程可以多次执行程序,并重新使用在前一次执行过程中生成的优化代码。然而,一旦用户进程结束,优化不会被保存。这是动态二进制优化的特征。如果随后在不同的用户进程中使用动态二进制优化器再次执行之前编译的程序,那么优化器通常会重新开始该程序,如块403的静态编译和块404的构建,而没有从在之前的用户进程中进行的任何之前的优化中获益。
[0078] 虽然流程图中示出并在相应的文字中描述了特定的操作顺序,但是应该理解的是,某些操作可以以不同的顺序执行,某些操作不需要执行,而可以代之执行其他操作,这与本发明一致。
[0079] 一般情况下,被执行以实现本发明的示例实施例的例程,无论是实施为操作系统的一部分,还是实施为特定的应用程序、程序、对象、模块或指令序列,包括特殊设备(如,服务处理器)中的模块,在本说明书中都被称为“程序”或“控制程序”。程序通常包括当被与本发明一致的计算机系统中的设备或系统中的一个或多个处理器读取和执行时,使得这些设备或系统执行用于执行体现本发明各个方面的步骤或生成体现本发明各个方面的元素所必需的步骤的指令。此外,虽然本发明已经并将在下文中在完全起到计算机系统的功能的情景中描述,但是本发明的各种实施例也能够作为在非临时性计算机可读介质上体现的程序产品分发,本发明均等地适用于任何分发形式。非临时性计算机可读介质的示例包括但不限于易失性和非易失性存储设备、软盘、硬盘驱动器、CD-ROM、DVD和磁带,应该理解的是,这些示例不是穷举性的。非临时性计算机可读介质的示例在图1中被图示为系统存储器102和数据存储设备125-127。
[0080] 除非与本发明不一致或在本说明书中另有限定,否则用于执行本发明的操作的计算机程序代码可以用一种或多种编程语言的任何组合编写,包括面向对象的编程语言(如,Java、Smalltalk、C++等)和传统的过程编程语言(如,“C”编程语言或类似编程语言)。程序代码可以作为独立的软件包全部在用户计算机上执行、部分在用户计算机上执行、部分在用户计算机部分在远程计算机上执行,或全部在远程计算机或服务器上执行。在后一种情景中,远程计算机可以通过任何类型的网络(包括局域网(LAN)或广域网(WAN))连接到用户计算机,或连接到外部的计算机(例如,使用互联网服务提供商通过互联网)。
[0081] 在本文,参照根据本发明的实施例的流程图示例和/或方法、装置(系统)和计算机程序产品的框图对本发明进行了说明。应该理解的是,流程图示例和/或框图的每一个块以及流程图示例和/或框图中的块的组合都可以通过计算机程序指令实现。这些计算机程序指令可以被提供给通用计算机、专用计算机或其他可编程数据处理设备的处理器以产生机器(machine),使得通过计算机或其他可编程数据处理装置的处理器执行的这些指令创建用于实现流程图和/或框图的一个块或几个块中规定的功能/行为的部件。
[0082] 这些计算机程序指令也可以被存储在非临时性的计算机可读介质中,可以引导计算机或其他可编程数据处理设备以特定的方式运行,使得存储在非临时性计算机可读介质中的指令产生包括实现流程图和/或框图的一个块或多个块中规定的功能/行为的指令部件的制成品。
[0083] 计算机程序指令还可以被加载到计算机或其他可编程数据处理装置上以促使在计算机或其他可编程设备上执行一系列的操作步骤,从而产生计算机执行的过程,使得在计算机或其他可编程设备上执行的指令提供用于实现流程图和/或框图的一个块或多个块中规定的功能/行为的多个过程。
[0084] 附图中流程图和框图示出了根据本发明的各种实施方式的系统、方法和计算机程序产品的可能的实现的架构、功能和操作。在此方面,流程图或框图中的每个块可以代表模块、段或部分代码,它包括一个或多个用于执行(多个)特定的逻辑功能的可执行指令。还应该指出的是,在一些替代性实现中,块中提到的功能可以以不同于附图中提到的顺序发生。例如,以连续方式示出的两个块实际上可以基本同时执行,或者有时候块可以以相反的顺序执行,这取决于所涉及的功能。还应该注意的是,框图和/或流程图示例的每个块以及框图和/或流程图示例中多个块的组合可以通过执行规定的功能或行为的专用的基于硬件的系统或专用的硬件和计算机指令的组合实现。
[0085] 虽然已经公开了本发明的特定实施例以及某些替代性实施例,但是本领域的技术人员应该认识到,在所附权利要求的范围内可以进行形式和细节的其他变化。

当前第1页 第1页 第2页 第3页