快速的基于补丁的方法调用技术

技术编号:2838862 阅读:174 留言:0更新日期:2012-04-11 18:40
公开了一种用于从编译的调用方法中提供对目标方法的快速调用的基于补丁的机制。调用方法的代码存储在存储器中。调用方法的代码包括用于调用目标方法的指令,其中,指令包括参数。响应于目标方法所经历的从当前状态到新状态的状态变化,将参数从第一值修改成第二值,其中,第二值指示正确地址以有助于目标方法在其新状态中的执行。因此,在用于调用目标方法的指令中的参数总是反映目标方法的正确状态,这为在执行指令时对目标方法的快速调用作好了准备。

【技术实现步骤摘要】

技术介绍
本节中描述的方法可以被推行,但不一定是先前已经构思或推行的方法。因此,除非本文另外指出,否则本节中描述的方法相对于本申请的权利要求来说就不是现有技术,而且也不应该由于包含在本节中就被认为是现有技术。典型的Java虚拟机(JVM)包括用于执行Java应用程序或其他基于Java的代码的解释器。当作为Java类的实例(instance)中的字节码而被执行的Java方法被调用时,解释器就访问该方法并解释地执行字节码。一些JVM可进一步提供动态自适应编译器来加速Java方法的执行。当这样的JVM检测到特定方法被频繁执行时,JVM就使用动态自适应编译器来将该方法编译成本机代码(nativecode)。JVM将本机代码存储到内存(如,代码高速缓存)的区域中,而在下一次调用该方法时,JVM就执行在内存中找到的本机代码而不是使用解释器来解释地执行该方法的字节码。为了有效利用其所分配的内存,这种JVM通常从内存中去除不再频繁使用的编译方法的本机代码。从内存中去除编译方法的可执行代码的过程在本文被称为反编译(decompilation)。典型方法可包括对多个其他方法的调用(invocation或call)甚或其自身的调用(如,循环调用)。调用另一方法的方法在本文中称为调用方法。正被另一方法调用的方法在本文中称为目标方法。在典型的JVM中,来自于被编译的方法的方法调用要慢于所需要的,这是因为在编译时调用方法不知道目标方法的正确运行时间地址。例如,假设JVM决定编译包括对目标方法的调用的调用方法。在编译时,该JVM并不肯定地知道该目标方法的运行时间地址,这是因为(1)在对调用方法进行了编译之后目标方法的编译状态(如,编译的或未编译的)会改变,或者(2)目标方法可以是在调用方法被编译之后,可以由另一方法覆盖的虚拟方法。由于这一不确定性,JVM仅在目标方法被调用时的运行时间可以确定目标方法的正确地址;因此,在编译调用方法并将其可执行代码存储在内存中之后,必须在调用方法每次实际调用目标方法时、通过在存储在内存中的目标方法的方法块中执行查找来确定目标方法的地址。(被加载的方法的方法块通常指明方法的类型并存储关于该方法的其他运行时间信息)。这种调用目标方法的方法可导致具有流水线结构的计算机处理器速度明显降低。在这种处理器中,流水线用于在处理器对来自于前一指令的结果进行解码、执行或写入时,预见并预先取得后续指令。这样,流水线处理器可并行处理和执行多个指令(例如,在将第一指令的结果写入内存或寄存器时,该处理器执行第二指令、对第三指令解码以及获取第四指令。在调用目标方法的上述方法中,在调用方法被编译时该目标方法的地址不确定性可造成处理器在执行调用方法的过程中会预先取得错误指令,这又会使得该处理器刷新其流水线。然而,刷新处理器流水线浪费了处理器周期并造成执行速度降低。例如,当对调用目标方法的调用方法的代码进行编译时,有必要使用间接引用,因为并不知道,在调用所述目标方法的时刻,是否将会编译该目标方法。在一些处理器结构中,以下指令组可用于调用方法的编译代码之中,以通过间接引用来对目标方法进行调用#目标方法的方法块地址被预先存储在“a0”中 movlr,pcldrpc,. 上述指令中的第一条(“mov lr,pc”)将程序计数器“pc”的值存为在目标方法已经完成执行之后将在此继续执行的返回地址。例如,在ARM处理器结构上,程序计数器“pc”将会包含当前指令地址加8。第二条指令(“ldr pc,”)将目标方法的当前地址从内存中的目标方法的方法块的第一个字开始加载到程序计数器中。如果在执行时编译目标方法,则目标方法的当前地址(其存储在目标方法的方法块的第一个字中)是代码高速缓存中的目标方法地址;如果目标方法未被编译,则目标方法的当前地址就是使得将执行改向到解释器的一些协助器胶水代码(helper glue code)的地址。上述调用目标方法的指令组在具有流水线的处理器上执行不佳,这是因为该处理器由于间接引用而不能预见以及确定目标方法的当前地址。这可能会导致每次调用目标方法时都完全刷新一次处理器流水线,并且浪费掉的处理器周期数量可能等于流水线的深度。为了减少处理器流水线刷新的可能,用于目标方法调用的过去的方法依赖于对已经被编译的目标方法进行直接方法调用。然而,当编译目标方法从被编译状态改变到未被编译的状态时会出现问题,这是因为,在目标方法被反编译以后,调用该目标方法的调用方法中的直接调用就不再指向正确的地址。为了解决这一问题,过去的方法通常依赖于对被编译的调用方法进行强制性的反编译。强制性的反编译规定无论何时目标方法的状态发生变化(例如,无论何时目标方法被覆盖或者被反编译),都对包括用于直接调用该目标方法的指令的所有编译方法进行反编译。然而,强制性的反编译有某些显著的缺陷。一种缺陷在于强制性的反编译难于执行,特别是对于当前正在执行的方法。强制性的反编译的另一缺陷在于在所使用的内存和处理器周期方面成本很高。当反编译方法时,必须反编译有必要调用该方法的所有其他编译方法。因此,单个目标方法的状态变化可能引起相当数量的编译方法的一连串的反编译。此外,被频繁调用的反编译方法最终将不得不被重新编译,这就造成了诸如内存和处理器周期的资源的额外的使用。基于前述,明确需要一种不引起处理器流水线刷新以及避免上述强制性的反编译的缺陷的技术。
技术实现思路
为了能够实现更快速的方法调用,本专利技术的一个实施例提供了一种技术,该技术用于修改在调用目标方法的编译的调用方法的可执行代码中的指令参数。维护调用目标方法的指令参数以在任何给定时间都反映目标方法的当前状态。参数可以是与指令相关的任何数据,例如,诸如与指令相关的操作码、与指令相关的操作数、以及操作码和一个或多个操作数的组合。响应于目标方法的状态变化,编译的调用方法中的指令参数被修改以反映目标方法的当前状态。因此,本文所述的技术要快于现有方法,这是因为调用方法不需要被反编译并且不执行目标方法的方法块中的额外的内存查找。根据本文所述的技术,编译的调用方法包括用于调用目标方法的指令。基于目标方法是虚拟方法还是非虚拟的或静态方法,目标方法存在六种可能状态(1)非虚拟/静态被编译(2)非虚拟/静态未被编译 (3)虚拟被覆盖且被编译(4)虚拟被覆盖且未被编译(5)虚拟未被覆盖且被编译(6)虚拟未被覆盖且未被编译与指令相关联的参数总是反映正确地址,以有助于在其当前状态的目标方法的执行。如果目标方法处于状态(1)或(5),那么参数就指明目标方法开始执行的代码高速缓存中的地址。如果目标方法处于状态(2),那么参数就引用一组代码,这些代码使得解释器执行目标方法的未编译版本。如果目标方法处于状态(3)、(4)或(6),那么参数就引用用于调用虚拟方法的一组代码。在一个实施例中,用于本文中所述的快速的基于补丁的方法调用的技术为从调用方法的可执行代码对非虚拟的和静态的这两种目标方法所进行的补丁调用作好了准备。在该实施例中,在调用方法的可执行代码中编译包括参数的直接转移-链接(brand-and-link)指令以调用目标方法。如果目标方法当前被编译并存于代码高速缓存中,则转移-链接指令参数就指示目标方法开始执行的代码高速缓存中的地址。响应本文档来自技高网
...

【技术保护点】
一种机器执行的方法,包括:    将调用方法的代码存储到存储器中,其中,所述调用方法的代码包括调用目标方法的指令,所述指令包括参数;以及    响应于所述目标方法经历的从当前状态到新状态的状态变化,将所述参数从第一值修改成第二值。

【技术特征摘要】
...

【专利技术属性】
技术研发人员:克里斯多弗J普卢默
申请(专利权)人:太阳微系统有限公司
类型:发明
国别省市:US[美国]

网友询问留言 已有0条评论
  • 还没有人留言评论。发表了对其他浏览者有用的留言会获得科技券。

1