用XIR改善编译运行分离英语毕业论文翻译及原文.doc
《用XIR改善编译运行分离英语毕业论文翻译及原文.doc》由会员分享,可在线阅读,更多相关《用XIR改善编译运行分离英语毕业论文翻译及原文.doc(38页珍藏版)》请在三一办公上搜索。
1、本科生毕业设计英文翻译及原文Improving Compiler-Runtime Separation with XIR用XIR改善编译-运行分离Ben L. Titzer加拿大景山区公园路圆形剧场1600号谷歌94043 (650) 919-4897ben.titzerThomas Wrthinger奥地利林兹约翰内斯开普勒大学694040+43 732-2468-7137wuerthingerssw.jku.atDoug Simon加拿大门洛公园16环路太阳为系统公司实验室94025 (650) 568-4871doug.simonMarcelo Cintra加拿大尔湾市448B ICS楼
2、加州大学欧文分校安全&软件实验室92717 (949) 824-9104mcintrauci.edu摘要现阶段对虚拟机的研究迫切需要一个灵活的软件架构,来使新的设计和技术实现得到快速评估。编译器和运行系统之间的接口不仅是影响两个组件灵活性的主要因素,而且对于快速实现新优化和新特性也是至关重要的。虽然虚拟机对其内的很多组件已实现了模块化,但是在编译和运行组件如对象模型和内存管理系统之间仍存在明显的依赖性。本文通过用XIR语言精心设计一个严格的编译-运行接口来解决这个难题。编译后台是通过使用硬链接逻辑来减少机器对象操作,而XIR语言使运行系统实现了此逻辑,同时简化了后台,也使后台和运行系统彻底分离
3、。在本文中,我们将介绍编译-运行接口的设计和实现,同时也将介绍C1X动态编译器的XIR语言,其中C1X动态编译器是从HotSpotTM客户端编译器移植而来的。我们的实验结果显示,使用XIR语言虽然在编译运行时仍生成一些无关紧要的代码,对编译时间产生轻微的影响,但是它明显降低了后台的复杂性和编译-运行接口的复杂性。分类和主题描述D.3.4 编程语言:处理器代码生成;编译器;优化;运行环境。概括术语设计,实验,语言,性能关键字编译器,JIT,Java,虚拟机,降级,软件架构,对象模型,虚拟机接口,中间表示,寄存器分配,运行系统1. 简介管理虚拟机的运行软件的数量和重要性都在持续上升。新语言特性和对
4、运行软件更高性能的需求仍旧推动着虚拟机的研究和开发。快速探索新的设计方法和实现技术必须要有一个灵活的软件架构,而影响虚拟机灵活性的主要因素之一就是编译器和运行系统之间的接口,其中相关的运行系统包括垃圾回收、对象模型和同步机制等。而要在不牺牲高性能的前提下实现编译和运行的彻底分离仍然是让人头疼的难题。即使今天,对于工业强度虚拟机,当其运行系统有显著的更改时其编译器也必须做出相应的更改。编译和执行的相关性来自于以下几种软件模块。i) 平台配置。虚拟机必须给编译器配置相关的目标体系结构信息,如指令集、字长、相对字长(当使用压缩文件时它可能与字长不同)、缓存队列、堆栈队列、支持ISA扩展、可分配寄存器
5、、调用规则等。ii) 执行时访问的数据结构。编译器需要访问一些运行系统的内部数据结构,其中包括一些具有代表性的方法及它们的代码、类和常量池等。编译器也可能查询执行时解析状态的类型、字段和引用字节码的方法。iii) 优化选择和调整。执行时运行系统可能想要对每一个方法或编译标准有选择地启用不同的优化或者改变优化。尤其是运行系统希望通过动态解析信息来改变代码嵌入的方式14 1519。iv) 理论相关性。虚拟机可能乐观地假设一个非final类是叶子类来实现实体化和代码嵌入,这需要找到返回运行系统的相关性,以方便之后编译代码的优化1819。v) 安装已编译的代码。编译器生成机器码和元数据,如参考图和优化
6、信息,运行系统在执行时必须将机器码和元数据加载到它的代码区和内部数据结构中。vi) 对象模型的实现。对象操作的降级对运行系统存在很大的依赖性,同时它也包含了一大部分编译器后台逻辑。如字段访问、虚拟调用、同步操作或对诸如指针算法和内存访问之类的机器操作的内存分配等这些都是对象操作的降级。虽然许多虚拟机已经有足够的接口来实现平台配置,访问执行时的数据结构和理论相关性的定位,但是我们相信它们都没有充分实现每一个软件模块。尤其是虚拟机依赖的对象模型实现是最难实现的软件模块。本文实现了这些软件模块(除 iii)优化控制)。我们双向的编译-执行接口使编译器和运行时的数据结构抽象化,同时XIR语言允许运行系
7、统为对象操作的降级提供相应的逻辑。这样就产生了下面的设计(表示数据流的边上标注了其依赖的相关软件模块):在本文中我们将介绍C1X动态优化编译器和相应的虚拟机运行系统的分离技术。我们将重点介绍编译-执行接口。该接口使各个组件和它们的内部实现细节分离,允许编译器在编译时查询运行的数据结构,同时生成编译代码的独立于运行系统的中间表示。本文的主要贡献是一种特定领域的语言XIR语言的设计和实现,该语言允许运行系统指定对象操作实现,并且使编译器和对象模型、垃圾回收等细节彻底分离。本文的内容组织如下:第2部分介绍C1X编译器的设计概要和讨论XIR的贡献的背景。C1X编译器是从java的HotSpot客户端编
8、译器移植而来的,并且类似于HotSpot客户端编译。第3部分介绍怎样通过接口使编译和执行分离,该接口怎样表示运行时的数据结构和编译时的数据结构。第4部分介绍XIR语言和它如何使编译器与虚拟机实施细则更深层的分离。第5部分讨论结果并给出指标,包括软件复杂性、编译时间和在一套标准的基准测试程序数值上的运行性能。第6部分讨论相关产品。第7部分给出结论,并致谢。2. 编译器的设计该部分描述了C1X编译器的起源和设计,为下文对编译-执行接口的讨论和对XIR的介绍做了伏笔。2.1 C1X成因Java虚拟机想要获得工业强度的性能就必须有一个良好的动态优化编译器,使运行时间与代码质量相对平衡。当Maxine虚
9、拟机有一个新的动态优化编译器时,我们开始研究HotSpot虚拟机的编译器。HotSpot虚拟机实际包括两个编译器,客户端18和服务器端19,也分别被称为C1和C2。两者都是用C+实现的,将字节码转换成优化的机器码供解释器解析。C1编译速度快并且占用内存小,是典型的客户端默认设置编译器。而C2优化彻底并且能达到最大峰值性能,是服务器端默认设置编译器。C1设计简单,因此被移植作为Maxine虚拟机的编译器,C1忽略诸如代码移动之类的复杂优化而专于“双赢”优化进而获得高优化速度,C1执行代码嵌入、局部优化、部分全局优化,同时C1中理论的叶子类和叶子方法假定支持逆优化,并且C1中有一个良好的快速线性扫
10、描寄存器分配器。我们从OpenJDK7中提取C1的58000行C+代码,用java重写这些代码来设计C1X编译器。图1.示例代码和其产生的HIR图。实线代表控制流的边缘而虚线代表数据流的边缘。菱形代表方法的输入参数。2.2前端C1X将java字节码解析成它主要的HIR图,其中包括控制流图和值依赖图。参见图一实例和参考文献18有更多详细介绍。与值依赖图或节点表示图不同,C1X的HIR图用基本块来表示控制流,每个基本块包含一个HIR指令集的有序列表。每个HIR指令直接引用产生输入值的指令。Phi节点与基本块的起点相连。基本块连接节点,并在必要时合并数据流。SSA性质的这种表示方式是在解析字节码时以
11、CFG反序处理基本块并循环使用phi守恒估计而精心设计的。值依赖图的特性允许C1X在解析时执行大量的优化,其中包括强度降低、常量传递,常量合并、本地值编号、加载取消、无用代码删除。代码嵌入将在以下情况下发生,解析字节码时,作为参数传递给内联方法的值向前传递时。当字节码被解析成HIR图时允许内联方法使用那些优化。基于类层次分析法10的猜测性优化允许那些调用点被反虚拟化和内联化,因为反优化对已编译代码无效。随后编译通道将删除不必要的Phi,合并块,删除空格,用条件语句代替控制流,执行全局的值编号并删除无用代码。C1x和C1在优化实现上存在轻微的差别,更详细的说明,请参见文献18。2.3后端优化后,
12、C1X将高级中间表示HIR转变成低级的IR(LIR),之后执行寄存器分配和代码生成。LIR包括一个有序的基本块队列,每一个都带有有序的LIR指令队列。LIR类似于一个乘法表示,其中每一条指令有一个操作码、一个输出操作数和多个输入操作数。指令的操作数可以是物理寄存器中的操作数、虚拟寄存器中的操作数或常量。LIR指令是典型的机器级操作,如指针的加载和存储、运算和移动,但一些复杂的操作可能会生成多个机器指令并可能使用内部临时变量。与乘法不同的是,每一个LIR指令可能有无数的输入参数、无数的临时变量但只有一个输出参数。LIR不是SSA形式,它要求通过插入移动指令来移除phi节点。低级中间表示LIR与机
13、器无关,并且HIR中的大多数对象操作能被转换成与机器无关但依赖于运行的装载、存储、比较和分支。然而,一些有结构约束的操作要以依赖于机器的方式被降级(如X86中的移位和除法运算),并且那些操作可能需要物理寄存器预分配。这个转换逻辑自动声称只能生成HotSpot代码,所以采用C1手写方式实现。这个转换逻辑的实现被分成两部分:独立于机器的部分和依赖于机器的部分。我们在创建C1X和修改它来生成Maxine虚拟机代码时移植该逻辑。这种硬链接转换过程描述了本文发表的主题:降级阶段是任何编译器的经典部分,也是执行依赖和机器依赖汇聚处。虽然C1X脱离了运行时的数据结构,该数据结构在编译时需要查找(在上文提到)
14、,但是它必须为每个对象操作生成代码,而这些对象操作在执行时需要使用元数据。修改运行系统的实现,如改变调用接口,需要修改编译器的后台。在移植C1时,由于对象操作的业务不同,我们被迫对C1X降级阶段做了大量的改变。虽然java的基本操作和控制流可以独立地编译成对象模型,但我们发现那些对象操作彼此都不同(有一些例外,如读实例字段)。此外,在处理特殊情况时,如访问未定义字段或方法和慢路径操作如监听器,大量的复杂性由此而生。Maxine虚拟机和HotSpot虚拟机中的对象操作几乎完全不相同,这导致我们的第一种解决方法仅能实现慢路径操作,该解决方法是取消调用运行系统14的操作。最终Maxine后端的一系列
15、变化导致需要一个更优的解决方案:XIR,我们在第4部分讨论。3. 编译运行接口 编译器和运行系统之间的复杂相互性导致编译需要一个双向接口,这样一方为另一方提供一个接口。我们的设计使两个接口组件明确分离,编译时需要运行系统提供运行对象,运行时需要编译器提供编译对象。我们也使用了一个命名规则,即前缀Ci代表编译器提供的一个接口对象和前缀Ri代表运行系统提供的一个接口对象。首先,运行系统负责创建和配置编译器,包括选择目标体系结构和配置特定的运行设置如分配寄存器和堆栈框架整合。为了实现这一功能,编译器提供了一些具体的Ci类,这些类在执行时创建,并传给编译器完成其内部配置。我们考虑过一个更复杂的配置接口
16、,它可以避免暴露具体的Ci类,但最后我们发现这种复杂性是不合理的。其次,当运行系统请求编译操作时,它必须提供编译方法的一种中间表示,以及编译器将用的相关的数据结构。为实现这一功能,运行时必须提供RiType接口、RiField接口、RiMethod接口和RiConstantPool接口的实现,每个接口支持编译器在编译时使用的查找操作。java接口为运行系统提供了最大的灵活性;它可以通过接口实现来展示它已定义的数据结构也可以用适配器来隐藏已定义的数据结构。第三,在编译时编译器可能向运行系统的请求其他的信息,如特定的调用准则或内联决议。为了达到这个目的,运行系统必须提供一个RiRuntime接口来
17、回应编译器的请求。最后,也是最重要的,编译器将产生附加元数据的编译代码。为了这个目的,它提供了一个具体的数据结构CiTargetMethod,这样运行系统在安装和运行时只需对该数据结构回收再处理生成其内部数据结构。因为在所有情况下,编译器实现细节对用户都是透明的,并且也没必要控制那些类的生成,所以与大多数其他的Ci类类似,我们用编译器接口来提供具体的类。已选的运行接口类:l RiConstantPool:一个与字节码有关的常量池,编译器用它来查找并解析字段、类型和方法。l RiExceptionHandler:一个异常处理入口,包括字节码覆盖范围、处理索引、捕获异常的类型。l RiField:
18、:解析或未解析的字节码相关字段,包括名称、类型和封闭类。已解析的字段也允许查找属性标志如final、private、volatile等。l RiMethod:解析或未解析相关字节码的方法,包括名称、标签和封闭类。已解析的方法可能涉及方法选择或具体方法的实现,同时也允许查询属性标志如final, private, static, synchronized等。l RiRuntime:是提供给编译器各种运行服务的接口。这些服务包括Java类对象转为RiType类对象,查询系统的RiType类,调用特定方法的条件,允许嵌入的方法的协议,各种类型的查找。l RiSignature: 一个方法的标签,包括
19、参数类型和返回类型。l RiType:字节码中或其他运行接口对象中解析或未解析的java类类型、接口类型、数组类型。已解析的类型可能涉及任意的有效的java类型、响应查找的属性标志,超类型,类型是数组还是接口等。已解析的实例化类型还可以查到实现RiMethod选择器的方法。l RiXirGenerator:生成XIR的运行类。在对象操作降为机器操作时编译器调用该类。(第4部分)已选的编译器接口类:l CiArchitecture:一个表示含指令集的机器架构的对象。在创建和配置编译器时运行系统选定该对象。l CiBailout:已终止编译的异常,在输入字节码越界时或出现未预料的内部编译错误时将调
20、用该类。l CiCodePos:一个代码设置和内联调用链。该链由编译器创建,用于编译代码中的元数据。 l CiCompiler:一个能从RiMethod 实例生成CiTargetMethod 实例的对象。由运行编译方法创建、配置和使用。l CiConstant:原语表示或对象常量表示。运行阶段和编译阶段都会创建该类,用来表示或替换程序中的常量值。l CiDebugInfo:用于堆栈跟踪和优化的调试信息。它由编译器生成,包含一部分编译结果。 l CiKind:一种枚举类型,包括java基本类型、对象类型、关键字类型。涉及java虚拟机级类型时编译阶段和运行阶段都会用到该类型。 l CiLocat
21、ion:有关物理寄存器或堆栈存储单元的结构体。由编译器和运行系统创建,用来描述参数和临时变量在一个方法中的位置。 l CiRegister:物理寄存器。当涉及特定的机器寄存器时,由编译器创建,供编译器和运行系统使用。 l CiResult:编译结果,该结果中包含帮助信息和带有统计信息的目标程序。它由编译器创建并作为编译器的编译结果。l CiStatistics:编译阶段的常规统计信息,包括已编译的字节码,行数等。由编译器创建并作为编译结果的一部分。 l CiTarget:设置集。如设置引用的大小、设置缓存方式、设置可分配寄存器等。由虚拟机创建,用于配置编译器。l CiTargetMethod:
22、一个已编译的方法,包括机器码和元数据,如重定向,修改信息和调试信息。由编译器创建,作为编译结果的一部分。 l CiXirAssembler:一个面向汇编的接口,由编译器传给运行系统用来建XIR 代码。在第4节中有更详细解释。总而言之,Ri接口类由大约1300行java源代码和文档组成。而Ci类由大约2300行代码组成。在Maxine虚拟机中必要的Ri接口实现总共包括大约3500行java源代码,其中包括 RiType, RiField,RiConstantPool 和RiMethod的实现,这些接口类包装了运行系统中现有的数据结构,因此在使用时不修改这些接口来匹配Ri接口。4. XIR虽然编译
23、-运行接口的数据结构使各个组件和各自的实现细节分离,但不管怎样编译器必须生成有效机器码来实现与运行系统设计相一致的对象操作。正如第2部分所述,从对象操作到机器操作的降级对运行系统有较高依赖性。从HotSpot中移植C1X的经验使我们想出一个这样的设计,将所有降级逻辑存在运行系统中,编译器不用考虑与性系统中对象操作的实现。C1X提供给运行系统一个接口,生成XIR代码,这样的设计旨在将少对象操作。其中XIR是一种特定领域的小语言。XIR与RISC指令集的汇编语言相似。然而与RISC指令集不同的是,XIR既没有二进制格式也没有文本格式,因此将它看作是中间表示最恰当。它是一种低层次的、三地址的中间表示
24、,它拥有无数的虚拟寄存器和一套独立于机器的机器指令,如32位和64位的整数运算、指针装载和存储、条件分支但XIR语言中没有跳转计数。XIR也支持定义快捷方式和定义具体路径(参考图2),这种支持功能对字节码的实现很有用。当出错时需要进行安全检查,因此XIR中要有处理故障的代码。在方法结束生成慢路径时,编译器总会生成相应的快捷方式,这样可以充分利用指令缓存机制。此外,运行系统可以定义一个存根:可以从XIR特定的指令中调用的一块全局XIR。存根对复杂的共享逻辑有用,这种逻辑太大而不适于内联。XIR有两个调用指令变种:CALL_STUB,调用先前定义的存根,和CALL_RUNTIME,调用运行系统中任
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 用XIR改善编译运行分离 英语毕业论文翻译及原文 XIR 改善 编译 运行 分离 英语 毕业论文 翻译 原文
链接地址:https://www.31ppt.com/p-3988523.html