将本机函数内嵌到编译的Java代码中的方法和系统的制作方法

文档序号:6554564阅读:195来源:国知局
专利名称:将本机函数内嵌到编译的Java代码中的方法和系统的制作方法
技术领域
本发明涉及改进的数据处理系统。具体地,本发明涉及数据处理系统中的Java本机函数。更具体地,本发明涉及在数据处理系统中将Java本机函数调用内嵌(inline)到编译的Java代码中。
背景技术
Java是一种面向对象的编程语言和环境,其专注于将数据定义为对象以及可应用于这些对象的方法。Java仅支持单继承,这意味着每个类在任何给定时间仅能从一个其他类继承。Java也允许创建被称为接口的完全抽象的类,这种类允许定义可与若干类共享的方法,而不管其他类如何处理这些方法。
Java提供了分发软件和扩展Web浏览器的能力的机制,因为程序员能编写小应用程序一次,而该小应用程序能在Web上的任何Java使能的机器上运行。
Java虚拟机(JVM)是一种仅存在于存储器中的虚拟计算机组件。JVM允许Java程序在不同平台上被执行,而不是仅在为其编译代码的一个平台上被执行。Java程序是为JVM编译的。以这种方式,Java能够支持用于很多类型的数据处理系统的应用,这些数据处理系统可包含多种中央处理单元和操作系统体系结构。为了使得Java应用能在不同类型的数据处理系统上执行,编译器通常生成一体系结构中性的文件格式—编译的代码可在很多处理器上执行,倘若存在Java运行时系统的话。Java编译器生成非特定于具体计算机体系结构的字节码指令。字节码是由Java编译器生成并由Java解释器解释的独立于机器的代码。Java解释器是JVM中的交替地解码和执行一个或多个字节码的模块。这些字节码指令被设计为易于在任何机器上解释,并易于被动态地(on the fly)转换为本机机器码。
可使用开发环境,例如可从Sun Microsystems公司获得的Java开发工具包(JDK),来从Java语言源代码和库构建Java字节码。可将这种Java字节码存储为Web服务器上的Java应用或小应用程序,可通过网络将该Java应用或小应用程序从该Web服务器下载到用户的机器并在本地JVM上执行。
Java运行时环境被特别设计为限制Java应用可能对它运行于其上的系统造成的损害。这对于万维网尤其重要,在万维网上当用户访问包含Java小应用程序的网页时,Java小应用程序被自动下载和执行。一般说来,人们不想执行任意的程序;它们可能包含病毒,或者它们甚至可能本身就是潜在恶意的,而不仅是无意地携带了不受欢迎的代码。除非用户特别地允许它(通过设置到JVM的用户接口中的适当标志),Java小应用程序不能向附加的存储设备(除非可能向一特定的、受限制的区域)读或写,它也不能向存储器位置(除非向一特定的、受限制的区域)读或写。
不仅Java小应用程序是为通过网络下载设计的,标准的Java库也特别地支持客户机-服务器计算。Java语言包括用于多线程和用于网络通信的规定。与其他语言(例如C)相比,编写这样的一对程序更容易得多,一个程序在用户的计算机上本地执行并处理用户交互,另一个在服务器上远程执行并可能执行更复杂和处理器密集的工作。
尽管Java语言被设计为是独立于平台的并主要在安全环境中执行,程序员可通过Java本机接口(JNI)使用C风格的调用约定来使用主机操作系统上的编译的本机二进制代码,从而扩展Java应用。以这种方式,Java应用可具有对主机操作系统的完全访问权,包括对附加的I/O设备、存储器等的读或写。由于此,Java程序可以成为特定于平台的代价完成通过JVM通常不允许的任务。然而,使用设计良好的体系结构,Java语言程序员可干净地将独立于平台的部分隔离,并向其他Java组件呈现一干净的、独立于平台的对象API,而同时完成特定于平台的任务。
当在编译的Java代码中通过JNI调用本机函数调用时,涉及到开销。例如,必须在运行时进行工作以便为进行调用准备该调用。一般而言,必须在调用本机函数时或之前加载包含该本机函数的本机库。也必须在运行时系统中解析(resolve)本机函数,并且必须更新相关的JVM数据结构以指示该本机函数的使用。
此外,JVM也必须根据底层操作系统体系结构的函数调用约定设置本机栈和/或寄存器,并对引用自变量执行空检查(null-checking)。对于某些JVM,还需要进行设置以添加用于垃圾收集的信息。在从本机代码返回时,在将来自于本机代码的返回值返回到Java运行时环境后,必须恢复所使用的栈和/或寄存器。
已做出了若干尝试来最小化调用本机函数的开销。最初的尝试是基于程序员的最优化,这种最优化将责任加于应用程序员,要其在编写使用本机函数的Java代码时实施高效的编码技术。例如,批处理本机调用,并且每函数调用向本机代码传递尽可能多的数据,从而可能减少Java程序中的边界跨越。
另一种最小化开销的尝试涉及限制在本机代码中提供的功能的类型。例如,回避构造本来会存在于调用栈上的本机调用帧(call frame)之前的特殊的包装器(wrapper)代码的机制。然而,这种机制只能用于那些被保证不会要求包括垃圾收集、异常处理、同步或安全性的栈遍历(stackwalking)支持的方法,因为所述垃圾收集等是包装器代码帮助提供的服务。
在又一种最小化开销的尝试中,执行工作以通过将字节码映射到低级的汇编语句来将非管理的存储区引入JVM。使用对非管理的存储区的高速访问,可实现共享存储段、存储器映射文件、通信和I/O缓冲器、和存储器映射硬件。然而,这种尝试不会识别和映射长而复杂的字节码序列,或将映射应用于虚拟方法调用,因为代码映射不能处理动态类加载。
尽管上述尝试最小化了本机函数调用的某些开销,每种尝试都有其自己的缺点。因此,有利的将是具有一种改进的目标为最优化本机函数调用的方法、装置、和计算机指令,以便最小化开销。

发明内容
本发明提供了用于将本机函数内嵌到编译的Java代码的方法、装置、和计算机指令。当检测到Java程序中的本机函数调用时,使用由本发明提供的转换引擎来将该本机函数的中间表示转换为即时(JIT)编译器中间表示。接着,由一JIT编译器内嵌器将该即时编译器中间表示内嵌到Java本机调用点(callsite),并且包含在该内嵌的代码中的任何本机调用也被递归地内嵌。
如果在内嵌时内嵌器确定达到了即时编译器增长极限,进行对一不透明函数的本机调用,或者在本机函数实现中不存在另外的本机函数调用,则递归内嵌过程终止。不透明函数是即时编译器不能为其生成中间表示的函数。
所述转换引擎通过在本机函数的中间表示(其由高级语言编译器产生)进行迭代并为该中间表示中的每个指令生成一即时编译器中间表示来转换该中间表示。所述本机函数的中间表示是从包含该本机函数的本机二进制代码和中间表示两者的本机库中检索的。
响应于确定该本机函数调用不是针对不透明函数的,内嵌器使用所述中间的即时编译器中间表示将该本机函数调用替换为该本机函数的实际实现,并具体化(materialize)一JNI环境指针并将该指针传递给该本机函数调用的实际实现。
响应于确定该本机函数调用是针对不透明函数的并且该本机函数调用不代表从Java到一本机函数的调用,则内嵌器合成到一Java可调用函数的新的调用,该Java可调用函数的用途是调用该本机函数,并将该原始的本机函数调用替换为对该合成的本机函数的调用,其中该合成的本机函数提供了对包含该不透明函数目标的实现的本机库的访问。


在所附权利要求中提出了相信为本发明的特点的新颖特征。然而,通过结合附图参照以下对示例性实施例的详细说明可最好地理解本发明本身以及其优选使用方式、其他目标和优点,在这些附图中图1是根据本发明的一优选实施例可在其中实现本发明的数据处理系统的图示;图2是可在其中实现本发明的数据处理系统的框图;图3是示出了可在其中实现本发明的数据处理系统的框图;图4是根据本发明的一优选实施例的JVM的框图;图5示出了根据本发明的一优选实施例用于将本机函数的中间表示转换为JIT编译器的中间表示的转换过程;图6示出了在根据本发明的一优选实施例的递归本机内嵌过程中的一个步骤;图7示出了根据本发明的一优选实施例的合成的本机函数;图8示出了根据本发明的一优选实施例内嵌的和合成的本机函数之间的连接;图9是根据本发明的一优选实施例用于将本机函数内嵌到编译的Java代码中的示例性过程的流程图;图10A示出了根据本发明的一优选实施例的示例性本机函数调用;图10B示出了根据本发明的一优选实施例的在非Java语言中实现的示例性本机函数调用;图10C示出了根据本发明的一优选实施例用于DummyCall类中的主方法的没有内嵌的带注释的基于树的中间表示;图10D示出了根据本发明的一优选实施例用于DummyCall类中的主方法的具有内嵌的带注释的基于树的中间表示;以及图10E示出了根据本发明的一优选实施例用于DummyCall类中的主方法的具有内嵌的优化的基于树的中间表示。
具体实施例方式
现参照附图并具体参照图1,其示出了根据本发明的一优选实施例可在其中实现本发明的数据处理系统的图示。示出了一计算机100,其包括系统单元102、视频显示终端104、键盘106、可包括软盘驱动器和其他类型的永久的和可拆装的存储介质的存储设备108、和鼠标110。个人计算机100中还可包括其他输入设备,例如游戏杆、触控板、触屏、跟踪球、麦克风等。可使用任何合适的计算机,例如位于纽约Armonk的国际商业机器公司的产品IBM eServer计算机或IntelliStation计算机,来实现计算机100。虽然所示的图示示出了一计算机,本发明的其他实施例可在其他类型的数据处理系统例如网络计算机中实现。计算机100还优选地包括图形用户界面(GUI),该图形用户界面可通过存在于在计算机100中运行的计算机可读介质中的系统软件来实现。
现参照图2,其示出了可在其中实现本发明的数据处理系统的框图。数据处理系统200是一计算机例如图1中的计算机100的示例,实现本发明的过程的代码或指令可位于该计算机中。数据处理系统200使用外围部件互连(PCI)局部总线体系结构。尽管所示的示例使用PCI总线,也可使用诸如加速图形端口(AGP)和工业标准结构(ISA)的其他总线体系结构。处理器202和主存储器204通过PCI桥208连接到PCI局部总线206。PCI桥208也可包括集成的存储控制器和用于处理器202的高速缓冲存储器。可通过直接部件互连或通过附加连接器进行附加的到PCI局部总线的连接。在所示的示例中,局域网(LAN)适配器210、小型计算机系统接口(SCSI)主机总线适配器212、和扩展总线接口214通过直接部件互连连接到PCI局部总线206。相反地,音频适配器216、图形适配器218、和音频/视频适配器219通过插入到扩展槽中的附加板连接到PCI局部总线206。扩展总线接口214提供了用于键盘和鼠标适配器220、调制解调器222、和附加存储器224的连接。SCSI主机总线适配器212提供了用于硬盘驱动器226、磁带驱动器228、和CD-ROM驱动器230的连接。典型的PCI局部总线实现将支持三个或四个PCI扩展槽或附加连接器。
操作系统运行在处理器202上并用于对图2中的数据处理系统200中的各部件进行协调和提供控制。操作系统可以是商业上可获得的操作系统例如可从Microsoft公司获得的Windows XP。面向对象的编程系统例如Java可与操作系统一起运行,并提供从在数据处理系统200上运行的Java程序或应用到操作系统的调用。“Java”是Sun Microsystems公司的商标。用于操作系统、面向对象的编程系统、和应用或程序的指令位于存储设备例如硬盘驱动器226上,并可被加载到主存储器204中以便由处理器202执行。
本领域的普通技术人员将理解图2中的硬件可根据实现而变化。作为对图2中所示的硬件的附加或替代,可使用其他内部硬件或外围设备例如快闪只读存储器(ROM)、等效的非易失性存储器、或光盘驱动器等。此外,可将本发明的过程应用于多处理器数据处理系统。
例如,数据处理系统200如果可选地被配置为网络计算机,则可不包括SCSI主机总线适配器212、硬盘驱动器226、磁带驱动器228、和CD-ROM 230。在这种情况下,将被适当地称为客户端计算机的该计算机包括某种类型的网络通信接口,例如LAN适配器210、调制解调器222等。作为另一个示例,数据处理系统200可以是独立的系统,其被配置为不依赖于某种类型的网络通信接口而可引导,不管数据处理系统200是否包括某种类型的网络通信接口。作为进一步的示例,数据处理系统200可以是个人数据助理(PDA),其被配置为具有ROM和/或快闪ROM,以为存储操作系统文件和/或用户生成的数据提供非易失性存储器。
图2中所示的示例和以上描述的示例并非意在暗示结构上的限制。例如,数据处理系统200除了采取PDA的形式也可以是笔记本计算机或手持式计算机。数据处理系统200也可以是信息站(kiosk)或网络电器(webappliance)。
本发明的过程是由处理器202使用计算机实现的指令执行的,这些指令可被加载到存储器例如主存储器204、存储器224、或一个或多个外围设备226-230中。
现参照图3,该框图示出了在可实现本发明的计算机系统内运行的各软件组件的关系。基于Java的系统300包含特定于平台的操作系统302,该操作系统为在特定硬件平台上执行的软件提供了硬件和系统支持。JVM304是一个可与操作系统一起执行的软件应用。JVM 304提供了Java运行时环境,该环境具有执行Java应用或小应用程序306的能力,所述Java应用或小应用程序是以Java编程语言编写的程序、小服务程序、或软件组件。JVM 304在其中运行的计算机系统可以类似于以上描述的数据处理系统200或计算机100。然而,JVM 304可在具有嵌入的picoJava内核的所谓的Java芯片、硅上Java(java-on-silicon)、或Java处理器上的专用的硬件中实现。
在Java运行时环境的中心的是JVM,该JVM支持Java的环境的所有方面,包括其体系结构、安全特征、跨网络的移动性、和平台独立性。
JVM是一虚拟计算机,即被抽象地规定的计算机。该规范定义了每个JVM必须实现的某些特征,并具有可取决于JVM被设计为在其上执行的平台的一定范围的设计选择。例如,所有JVM必须执行Java字节码,并可使用一系列技术来执行由字节码代表的指令。JVM可完全在软件中实现或在某种程度上在硬件中实现。这种灵活性允许为大型计算机和PDA设计不同的JVM。
JVM是实际执行Java程序的虚拟计算机组件的名称。Java程序不是直接由中央处理器运行的,而是由JVM运行的,JVM本身是运行在处理器上的一个软件。JVM允许Java程序在不同的平台上执行,而不是仅在为其编译代码的一个平台上执行。Java程序是为JVM编译的。以这种方式,Java能够支持用于很多类型的数据处理系统的应用,这些数据处理系统可包含各种中央处理单元和操作系统体系结构。为了使Java应用能在不同类型的数据处理系统上执行,编译器典型地生成体系结构中性的文件格式—编译的代码可在很多处理器上执行,只要存在Java运行时系统即可。Java编译器生成非特定于具体计算机体系结构的字节码指令。字节码是由Java编译器生成并由Java解释器执行的独立于机器的代码。Java解释器是交替地解码和解释一个或多个字节码的、JVM的部分。这些字节码指令被设计为易于在任何计算机上执行并易于被动态地(on the fly)转换为本机机器码。字节码可由即时(JIT)编译器转换为本机代码。
JVM加载类文件并执行其中的字节码。类文件是由JVM中的类加载器加载的。类加载器从应用加载类文件并从应用所需要Java应用编程接口(API)加载类文件。执行字节码的执行引擎可随不同的平台和实现而不同。
一种类型的基于软件的执行引擎是JIT编译器。使用这种类型的执行,在成功地满足用于JIT编译一方法的某种类型的标准后,将一方法的字节码编译为本机机器码。然后用于该方法的本机机器码被缓存,并在下次调用该方法时被重用。执行引擎也可在硬件中实现并嵌入芯片中,从而字节码被本机地执行。JVM通常解释字节码,但JVM也可使用其他技术,例如即时编译,来执行字节码。
当在特定于平台的操作系统上的软件中实现的JVM上执行应用时,Java应用可通过调用本机方法来与主机操作系统交互。Java方法是在Java语言中编写的,被编译为字节码,并被存储在类文件中。本机方法是在某种其他语言中编写的,并被编译为特定处理器的本机机器码。本机方法被存储在动态链接库中,动态链接库的精确形式是特定于平台的。
现参照图4,其示出了根据本发明的一优选实施例的JVM的框图。JVM 404包括类加载器子系统402,该子系统是一用于在给定了类型的完全限定名的情况下加载类型例如类和接口的机制。JVM 404还包含运行时数据区404、执行引擎406、本机方法接口408、和存储管理410。执行引擎406是一用于解释或执行包含在由类加载器子系统402加载的类的方法中的指令的机制。执行引擎406可以是例如Java解释器412或即时编译器414。本机方法接口408允许访问底层操作系统中的资源。本机方法接口408可以是例如Java本机接口(JNI)。
运行时数据区404包含本机方法栈416、Java栈418、PC寄存器420、方法区422、和堆424。这些不同的数据区代表JVM 404执行程序所需要的存储区的结构。
Java栈418用于存储Java方法调用的状态。当发起新的线程时,JVM为该线程创建一新的Java栈。JVM只直接在Java栈上执行两种操作它推入和弹出帧。一线程的Java栈存储用于该线程的Java方法调用的状态。Java方法调用的状态包括其局部变量、调用它所用的参数、其返回值(如果有的话)、和中间计算。Java栈由栈帧组成。一栈帧包含单个Java方法调用的状态。当一线程调用一方法时,JVM将一新的栈帧推入该线程的Java栈。当该方法完成时,JVM将用于该方法的帧弹出并丢弃它。JVM没有任何用于保存中间值的寄存器;任何需要或产生中间值的Java指令使用该栈来保存中间值。以这种方式,为多种平台体系结构良好地定义了Java指令集。
程序计数器(PC)寄存器420用于指示下一个要执行的指令。
本机方法栈416存储本机方法的调用的状态。本机方法调用的状态是以依赖于实现的方式存储在本机方法栈、寄存器、或其他依赖于实现的存储区中的。在某些JVM实现中,本机方法栈416和Java栈418是结合在一起的。
方法区422包含类数据,而堆424包含所有实例化的对象。在这些示例中,常数池位于方法区422中。JVM规范严格地定义了数据类型和操作。大多数JVM选择具有一个方法区和一个堆,每一个都由运行在该JVM例如JVM 404中的所有线程共享。当JVM 404加载类文件时,它根据包含在该类文件中的二进制数据分析关于类型的信息。JVM 404将这种类型信息放入方法区。每次创建一类实例或数组,就从堆424中分配用于该新对象的存储空间。JVM 404包括一在用于堆424的存储区中分配存储空间的指令,但不包括用于在该存储区中释放该空间的指令。所示的示例中的存储管理410管理分配给堆424的存储区中的存储空间。存储管理410可包括一垃圾收集器,该垃圾收集器自动回收由不再被引用的对象所使用的存储空间。此外,垃圾收集器也可以移动对象以减少堆的碎片化。
本发明提供了用于在编译的Java代码中递归地内嵌本机函数的方法、装置、和计算机指令。本发明通过在JIT编译期间将本机函数的调用的中间表示替换为相应的方法体的中间表示而避免了Java程序进行本机函数调用。中间表示是由JIT编译器生成的源代码的中间表示,并包括当该源代码被编译以生成二进制机器码时用于执行优化的程序构造(construct)。
在一优选实施例中,本发明使得任何试图内嵌Java可调用本机调用点的编译器能够消耗本机函数的中间表示并将其转换为它自己的中间表示以执行优化。本机调用点是任何程序中的调用本机函数的Java语句。使用本发明,JIT编译器内嵌器通过将本机函数的中间表示转换为JIT编译器的中间表示来内嵌本机函数,从而将本机方法当作在概念上如同Java函数体,尽管维持本机方法的原始原语言的语义,并递归地内嵌该内嵌的本机代码可能包含的任何本机调用(尤其是非Java可调用的那些)。
本发明包括一转换引擎,该转换引擎利用所生成的本机函数中间表示将包含本机函数的中间表示以及编译的代码的二进制表示的本机库嵌入JIT编译器环境。换言之,转换引擎将存储在本机库中的本机函数的中间表示导入JIT编译器。对于遇到的每个指令,该引擎生成新的JIT编译器中间表示语句。该JIT编译器随后将该中间表示当作如同它是从Java字节码中得出的,而同时保持遵守该本机方法的原始源语言的语义。
此外,本发明包括一内嵌器,该内嵌器将所转换的JIT编译器中间表示内嵌到本机调用点中,以消除调用本机函数的需要。该内嵌过程是递归的,它包括检查本机调用点并确定本机函数调用是否可被替换为该函数的实际实现。该函数的实际实现是JIT中间表示格式的该函数的体。
如果本机函数调用可被替换为JIT中间表示格式的该函数的实际实现,则内嵌过程继续执行内嵌工作,例如将参数映射为自变量,合并本机编译器和JIT编译器中间表示,控制流图,和具体化指向一JNIEnv结构的指针,以便内嵌的语句可使用它来调用Java本机接口以执行正常的系统活动。
然而,如果本机函数调用不能被替换为JIT中间表示中的该函数的实际实现,则本发明采取两条路径中的一个(i)如果该调用点是在处理字节码时被创建的(即调用点代表从Java到本机方法的调用),则不对调用点执行进一步的处理,或者(ii)如果该调用点是在本机上下文中发生的(即,在内嵌的非Java可调用本机代码中),则该本机函数调用被替换为对一提供对本机库的访问的合成的本机函数的调用。如果本机函数调用调用了JIT编译器不能对其呈现中间表示的过程,例如当没有该本机函数的中间表示与该库的二进制代码一起存储时,则该本机函数调用是不可内嵌的。这种不可内嵌的函数被称为不透明函数。本机函数库包括原始本机函数调用的实现。以这种方式,对不透明方法的调用可被替换为对本机库中的函数实现的直接调用。
为了同步在内嵌的本机函数和其他函数例如合成的本机函数之间共享的数据,本发明提供了到共享的存储区的适当连接,从而内嵌的本机函数和非内嵌的本机函数能够读和写相同的数据段。
此外,本发明插入代码以提供内嵌的本机函数和JVM组件之间的交互。例如,在执行内嵌之后插入与垃圾收集组件执行握手的指令。
现转到图5,该图示出了根据本发明的优选实施例用于将本机函数的中间表示转换为JIT编译器中间表示的转换过程。如图5所示,本机前端500提供了本机代码504的本机中间表示502。本机前端500的一个例子可以是C/C++编译器。
本发明的转换引擎506在由本机前端500生成的本机中间表示502上进行迭代,并为每个遇到的用于本机代码的指令生成新的JIT编译器中间表示508。这样,转换引擎506不是使用Java字节码作为输入,而是使用本机中间表示502作为输入。一旦处理了本机中间表示502,JIT编译器随后把所生成的JIT编译器中间表示508当作如同它是从Java字节码中得出的。转换引擎506还提供了适合于已被内嵌的语言的连接,例如由该函数调用的自变量。
现在转到图6,该图示出了根据本发明的一优选实施例的递归本机内嵌过程中的一个步骤。如图6所示,JIT编译器内嵌器600分析调用点602以确定它是否是本机函数调用。如果602是本机函数调用,则JIT编译器内嵌器600使用转换引擎604将该本机函数的本机中间表示606转换为JIT编译器中间表示608。
使用JIT编译器中间表示608,JIT编译器内嵌器600通过将调用点610的函数调用替换为该函数的实际实现来将该本机函数调用内嵌到编译的Java代码中,该函数的实际实现是JIT编译器中间表示608格式中的该函数的体。此外,JIT编译器内嵌器600执行内嵌工作,例如将参数映射为自变量,合并本机编译器和JIT编译器中间表示,控制流图,和具体化指向JNIEnv结构的指针,从而内嵌的语句可调用Java本机接口(JNI)。应注意,可将C或C++编译器中间表示608与程序库一起存储。
在内嵌过程期间,JIT编译器内嵌器600可能检测到不能通过JIT编译器处理的其余部分的本机中间表示606,因为所述本机中间表示可能调用JIT编译器不能为其呈现中间表示的过程。例如,如果用于该本机函数的本机二进制代码不存在或该本机函数通过函数指针来调用。
现在转向图7,该图示出了根据本发明的一优选实施例的合成的Java可调用本机函数。如图7所示,在中间表示不能通过JIT编译器处理的情况下,JIT编译器内嵌器将对不可内嵌的或不透明的本机函数的调用替换为对合成的Java可调用本机函数的调用,所述合成的Java可调用本机函数提供了对包含原始不可内嵌调用的实现的本机库的访问。
在该示例性实施例中,Java运行时700包括一个内嵌的本机函数702。在该内嵌的本机函数702内,存在对不透明本机函数a、b、和c的调用。因为函数a、b、和c是不可内嵌的,JIT编译器内嵌器例如图6中的JIT编译器内嵌器600将本机函数调用a、b、和c替换为合成的本机函数调用a 703、b 705、和c 707。合成的本机函数a 703和b 705提供了对包含用于函数a和b的实现的本机库704的访问,而合成的本机函数c 707提供了对包含用于函数c的实现的本机库706的访问。
为了确保更新Java运行时以指示合成的本机函数的存在,JIT编译器内嵌器还生成合成的辅助数据709。对于不透明函数是公知的库函数的情况,可实现对该函数的调用而无需经历该整个中间本机方法。
在一Java函数内,可存在内嵌的和非内嵌的本机函数调用,例如合成的本机函数、相同库中的另一函数、或在不同库中定义的函数。本发明保护在内嵌的和非内嵌的本机函数之间共享的数据,例如由该程序访问的全局变量,这是通过提供到共享数据的正确连接、并确保内嵌的和非内嵌的本机函数调用都能够读和写存储该共享数据的共享存储区的相同部分而实现的。共享数据可以是任何外部的或静态的数据,以及可由内嵌的本机函数调用传递给合成的函数调用的变量的地址。
现在转向图8,该图示出了根据本发明的优选实施例内嵌的和合成的本机函数之间的连接。如图8所示,Java函数800包括内嵌的本机函数802。内嵌的本机函数802包括静态变量x的声明和对同一变量x的写。用于静态变量x的存储空间804存储在库存储空间806中。
此外,内嵌的本机函数802包括对不透明本机函数的调用808。如上所述,JIT编译器内嵌器将该本机调用808替换为合成的本机函数调用810,从而提供了对库存储空间806中包含读和写x的实现的本机库812的访问。
本发明提供了从内嵌的本机函数802和实际的本机函数(其将由合成的函数810调用)812两者到用于静态变量x的存储空间804的连接。以这种方式,内嵌的本机函数802能够读和写812中的非内嵌的本机函数所读和写的存储器的相同部分,其中812是通过810到达的。
因为内嵌的本机函数是在Java运行时环境中执行的,必须使程序代码适应为与适当的JVM要求交互。具体地,在内嵌之后和JIT编译器处理的其余部分之前,本发明插入执行与诸如垃圾收集的组件的握手的指令。
在该优选实施例中,本发明递归地将本机函数内嵌到本机调用点,直到遇到对不透明函数的调用,或直到达到中间表示增长极限。中间表示增长极限指示可内嵌多少本机函数。因为内嵌增加了程序数据的大小,可使用增长极限例如以限制对指令高速缓存的负面的副作用。检查所得到的JIT编译器中间表示,并且JIT编译器继续正常进行。
现在转向图9,其示出了根据本发明的一优选实施例的用于将本机函数内嵌到编译的Java代码的示例性过程的流程图。如图9所示,当Java运行时环境运行JIT编译器到其标准内嵌阶段时(步骤909),该过程开始。
在该阶段中,遇到一本机函数调用(步骤902)。因为该本机函数的中间表示与其二进制表示一起存储在本机库中,所以使用由本机编译器生成的中间表示。然而,也可使用其他方案,例如分析本机函数的二进制代码。关键是将该本机函数映射到JIT编译器的中间表示。当遇到本机函数调用时,本发明的转换引擎确定该本机函数调用是否是不透明的(步骤904)。如果该本机函数调用是针对不透明函数的,则该过程继续进行到步骤906。
在步骤906,JIT编译器内嵌器确定该调用点是否是在处理Java字节码时创建的(即该调用点代表从Java到一本机函数的调用)。如果该调用点是在处理Java字节码时创建的,则它进行到步骤924以检查该调用点是否是启动该整个内嵌过程的原始调用点。如果它是,则JIT编译器进行到步骤922,避免内嵌该调用点。返回到步骤924,如果该调用点不是原始调用点,则它进行到步骤908,在此它开始中间转换过程。
返回到步骤906,如果该调用点不代表从Java到本机函数的调用,这意味着对不透明函数的调用发生在内嵌的本机代码内,则编译器过程进行到步骤918。在步骤918,JIT编译器内嵌器合成一Java可调用本机函数,该函数的用途是调用原始的实际函数,然后将该本机函数调用替换为对该合成的本机函数的调用(步骤920),并继续进行到步骤914。
返回到步骤904,如果该本机函数调用不是针对不透明函数的,则内嵌器将本机中间表示转换为JIT编译器中间表示(步骤908),并确保在JIT编译器的中间表示中对符号或存储的引用正确地对应于由原始代码引用的符号或存储。它还将该本机函数调用替换为该函数的实际实现(步骤910),然后具体化JNIEnv指针,并将其传递给内嵌的代码(步骤912)。该过程然后继续进行到步骤914。
在步骤914,内嵌器确定是否已达到JIT编译器增长极限。如果已达到JIT编译器增长极限,则该过程继续进行到步骤922。如果尚未达到JIT编译器增长极限,则编译器内嵌器确定在所转换的中间表示中是否还存在另外的函数调用(步骤916)。
如果在所转换的中间表示中存在另外的函数调用,则该过程返回到步骤902来检索下一步所转换的中间表示。否则,该过程继续进行到步骤922。在步骤922,恢复JIT编译器处理。这样,该过程随后终止。
现在转向图10A,该图示出了根据本发明的一优选实施例的示例性本机函数调用。在该说明性示例中,DummyCall类1000包括本机函数Dummy()1002和main()方法1004。
在main()方法1004中,整数x1006被赋值为dummy()方法1008与dummy()方法1010相加的结果。
现转向图10B,该图示出了根据本发明的一优选实施例在非Java语言中实现的一示例性本机函数。在该说明性示例中,来自图10A的dummy()方法1002是使用非Java语言例如C实现的。
结果,图10B中示出了dummy()方法1020。dummy()方法1020返回‘100’的值。
现转向图10C,该图示出了根据本发明的一优选实施例的用于DummyCall类中的主方法的、没有内嵌的、带注释的、基于树的中间表示。如图10C所示,主方法1030是由编译器生成的没有内嵌的用于图10A中的主方法1004的中间表示。
在该中间表示中,主方法1030首先求和来自对本机函数dummy 1032和dummy 1034的两个连续函数调用的返回值。然后主方法1030将结果存储在临时变量x中。使用主方法1030,由于在本文前面提到的原因,当调用本机函数时,在运行时引起开销。
现转向图10D,该图示出了根据本发明的一优选实施例的用于dummyCall类中的主方法的、具有内嵌的、带注释的、基于树的中间表示。如图10D所示,主方法1040是由JIT编译器生成的,该编译器在编译时内嵌本机函数。
因此,不是在运行时调用主机函数dummy 1032或1034,而是主方法1040包括dummy方法1032和1034的实际实现。这种技术之所以可能,是因为JIT编译器中间表示在编译时是已知的,并且可执行优化以将本来为不透明调用点的东西扩展为该函数的实际实现。
在该示例中,消除了对本机函数dummy 1032和1034的本机函数调用,并将其替换为常数值100。
现转向图10E,该图示出了根据本发明的一优选实施例的用于dummyCall类中的主方法的、具有内嵌的、优化的、基于树的中间表示。如图10E中所示,如果编译器进一步优化图10E中的所生成的表示,则编译器可将所述相加替换为如图10E中所示的200的值。
通过在JIT编译时内嵌本机函数调用,消除了本机函数的调用和相关的开销。此外,调用点可经受进一步的优化,这种优化将其缩减为一常数值。
总之,本发明通过将本机函数调用的中间表示替换为JIT编译器的本机函数中间表示,使能了本机函数内嵌。本发明重构(refactor)所产生的中间表示,并确定哪个区域包括将被向回转变为调用Java可调用本机函数的不透明函数。此外,本发明适当地合成本机函数,并创建用于访问在内嵌的本机函数和非内嵌的本机函数之间共享的数据的连接。另外,本发明插入代码以便满足JVM要求,例如垃圾收集。以这种方式,尽可能地避免了本机函数调用,并因此最小化了本机函数调用的开销。
重要的是注意到,尽管已在全功能的数据处理系统的情境中描述了本发明,本领域的普通技术人员将认识到本发明的过程也能够以指令的计算机可读介质的形式和多种形式被分发,并且不管实际用于执行这种分发的信号承载介质的特定类型是什么,本发明都同等适用。计算机可读介质的例子包括可记录类型的介质,例如软盘、硬盘驱动器、RAM、CD-ROM、DVD-ROM,以及传输类型的介质,例如使用诸如射频和光波传输等传输形式的数字和模拟通信链路、有线或无线的通信链路。该计算机可读介质可采取编码格式的形式,这种编码格式被解码以实际用于特定的数据处理系统。
本发明的描述是为了说明和描述的目的给出的,而非旨在是穷尽性的或限于本发明的所公开的形式。对本领域的普通技术人员来说很多修改和变形都将是显然的。例如,尽管所示的实施例是针对处理Java中的字节码,本发明的过程也可应用于处理这样的指令的其他编程语言和环境,所述指令不是特定于这些指令在其上执行的计算机。在这种情况下,该计算机上的虚拟机可解释这些指令或将这些指令发送给编译器以生成适于由该虚拟机位于其上的计算机执行的代码。
所选择和描述的实施例是为了最好地解释本发明的原理和实际应用,并使本领域的其他普通技术人员能理解本发明的带有适合于所考虑的特定应用的各种修改的各实施例。
权利要求
1.一种在数据处理系统中用于将本机函数内嵌到编译的Java代码的方法,该方法包括检测到在Java调用点处的本机函数调用;将本机函数的中间表示转换为即时编译器中间表示;以及将该即时编译器中间表示内嵌到该Java调用点中。
2.根据权利要求1的方法,其中所述内嵌步骤被递归地执行,直到发生以下情况之一确定达到了即时编译器增长极限,其中该即时编译器增长极限指示可内嵌多少本机函数以便限制对指令高速缓存的负面副作用;确定所述本机函数调用是针对不透明函数的;以及确定在本机函数实现中不存在另外的本机函数调用。
3.根据权利要求1的方法,其中所述本机函数调用是使用Java本机接口被调用的,并被递归地内嵌,从而内嵌的本机函数包含的任何本机调用也可随后被内嵌。
4.根据权利要求1的方法,其中所述转换步骤包括在所述本机函数的中间表示中进行迭代;以及为该本机函数的中间表示中的每个指令生成即时编译器中间表示,其中该本机函数的中间表示是从包含该本机函数的本机二进制代码和中间表示的本机库中检索的。
5.根据权利要求1的方法,其中所述内嵌步骤包括确定所述本机函数调用是否是针对不透明函数的,其中对该不透明函数的调用调用即时编译器不能为其呈现中间表示的过程;如果该本机函数调用不是针对不透明函数的,则使用所述即时编译器中间表示将该本机函数调用替换为该本机函数调用的实际实现;以及具体化本机接口环境指针,并使该指针对该本机函数调用的实际实现可用。
6.根据权利要求5的方法,还包括如果所述本机函数调用是针对不透明函数的,则确定该本机函数调用是否代表从Java到本机函数的调用;如果该本机函数调用不代表从Java到本机函数的调用,则合成Java可调用本机函数,并将该本机函数调用替换为对该合成的本机函数的调用,其中该合成的本机函数提供了对包含该不透明函数的实现的本机库的访问;以及如果该本机函数调用代表从Java到本机函数的调用,则确定该本机函数调用是否是启动整个内嵌过程的原始函数调用。
7.根据权利要求6的方法,还包括如果所述本机函数调用是启动所述整个内嵌过程的原始函数调用,则恢复即时编译器处理;以及如果该本机函数调用不是启动该整个内嵌过程的原始函数调用,则将该本机函数调用的中间表示转换为即时编译器中间表示。
8.根据权利要求1的方法,其中所述即时编译器中间表示在所述转换步骤后被即时编译器随后当作Java字节码。
9.根据权利要求5的方法,其中所述内嵌步骤还包括将参数映射为自变量;以及合并本机编译器和JIT编译器中间表示和控制流图。
10.根据权利要求6的方法,还包括将代码插入所述编译的Java代码以提供到用于由内嵌的本机函数、合成的本机函数和本机库中的其他函数共享的数据的共享存储区的连接。
11.根据权利要求6的方法,还包括将代码插入所述编译的Java代码中以提供所述本机函数调用的实际实现和虚拟机组件之间的交互。
12.一种用于将本机函数内嵌到编译的Java代码中的数据处理系统,该数据处理系统包括转换引擎,用于响应于检测到在Java调用点处的本机函数调用,将本机函数的中间表示转换为即时编译器中间表示;以及即时编译器内嵌器,用于将该即时编译器中间表示内嵌到该Java调用点中。
13.根据权利要求12的数据处理系统,其中所述即时编译器内嵌器递归地执行内嵌,直到达到了即时编译器增长极限,其中该即时编译器增长极限指示可内嵌多少本机函数以便限制对指令高速缓存的负面副作用;直到确定所述本机函数调用是针对不透明函数的;以及直到确定在本机函数实现中不存在另外的本机函数调用。
14.根据权利要求12的数据处理系统,其中所述本机函数调用是使用本机接口被调用的,并被递归地内嵌,从而内嵌的本机函数包含的任何本机调用也可随后被内嵌。
15.根据权利要求12的数据处理系统,其中所述转换引擎在所述本机函数的中间表示中进行迭代;以及为该本机函数的中间表示中的每个指令生成即时编译器中间表示,其中该本机函数的中间表示是从包含该本机函数的本机二进制代码和中间表示的本机库中检索的。
16.根据权利要求12的数据处理系统,其中所述即时编译器内嵌器还确定所述本机函数调用是否是针对不透明函数的,其中对该不透明函数的调用调用即时编译器不能为其呈现中间表示的过程;如果该本机函数调用不是针对不透明函数的,则使用所述中间的即时编译器中间表示将该本机函数调用替换为该本机函数调用的实际实现;以及具体化本机接口环境指针,并将该指针传递给该本机函数调用的实际实现。
17.根据权利要求16的数据处理系统,其中如果该本机函数调用是针对不透明函数的话,所述即时编译器内嵌器还确定该本机函数调用是否代表从Java到本机函数的调用;如果该本机函数调用不代表从Java到本机函数的调用,则合成Java可调用本机函数;以及将该本机函数调用替换为对该合成的本机函数的调用,其中该合成的本机函数提供了对包含该不透明函数的实现的本机库的访问。
18.一种在计算机可读存储介质中的用于将本机函数内嵌到编译的Java代码中的计算机程序产品,该计算机程序产品包括用于执行前述方法权利要求的任何方法的指令。
全文摘要
提供了用于将本机函数内嵌到编译的Java代码的方法、装置、和计算机指令。本发明提供了用于将本机函数的中间表示转换为即时(JIT)编译器的中间表示的转换引擎。使用所转换的中间表示,内嵌器将所转换的JIT编译器的中间表示递归地内嵌到本机调用点,以消除调用该本机函数以及由该函数进行的随后的本机调用的需要。该内嵌过程继续进行,直到遇到对不透明函数的调用,或直到达到了JIT编译器中间表示增长极限。内嵌器也将对大多数不可内嵌的或透明的本机函数的调用替换为对合成的本机函数的调用,所述合成的本机函数提供了对包含原始不可内嵌调用的实现的本机库的访问。
文档编号G06F9/45GK1821964SQ200610007688
公开日2006年8月23日 申请日期2006年2月17日 优先权日2005年2月18日
发明者A·H·基尔斯特拉, L·S·斯特帕尼安, K·A·斯图德雷 申请人:国际商业机器公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1