高速缓存运行时生成的代码的制作方法

xiaoxiao2020-7-22  14

专利名称:高速缓存运行时生成的代码的制作方法
高速缓存运行时生成的代码背景传统上,软件编译器产生本机代码,S卩,对代码将在其上运行的机器来说是专用的二进制代码。由传统的编译器生成的本机(非托管)代码通常包括操作系统运行代码所需要的所有事物,除此之外很少有别的。相比之下,在虚拟机环境中,源代码被编译成对任何特定的机器来说不是专用的中间字节代码表示。另外,托管代码编译器的输出通常包括比仅二进制代码多得多的信息。该附加信息描述二进制代码的特性,且有时被称为元数据用于描述其他数据的数据的通用术语,其中在此情况中,所描述的数据是二进制代码。包含中间字节代码和元数据的容器有时被称为托管汇编件。这些容器还可以被称为类文件、Java 档案或Java模块。在此所使用的术语“汇编件”或“托管汇编件”是指任何这样的字节代码和元数据的容器。在非托管环境中,在运行时,预先存在的本机指令被加载到存储器并被执行。在托管环境中,在运行时,托管汇编件可以就在执行之前被编译或被翻译成本机二进制指令。即,托管汇编件可以被加载到存储器并被即时(just-in-time,JIT)编译器或运行中 (on-the-fly)编译器编译成机器专用的和运行时专用的指令,然后执行该指令。尽管托管环境的编译/翻译阶段涉及可以影响性能的另外的处理,但另一方面,JIT/运行中编译器可以进行非托管环境所不能利用的环境专用的优化。例如,如果JIT/运行中编译器知道正在执行的代码完全可信任地运行,则它可以跳过在非托管环境中不能跳过的某些昂贵的安全检查。在托管环境中,代替就在执行托管汇编件之前编译托管汇编件,源代码或中间字节代码可以由优化编译器编译成本机二进制代码并在宿主系统上运行之前被存储(被高速缓存)。例如,诸如NGEN等的本机映像生成器可以通过在接收到执行该汇编件之前将中间字节代码转换成二进制的本机机器指令来产生用于该环境的本机二进制映像。以此方式,在运行时,以类似于传统的本机代码环境的方式,预先存在的可执行代码可以无需第二编译/翻译阶段就被加载和运行。尽管高速缓存旨在通过移除在运行时的JIT/运行中编译 /翻译过程来使得该汇编件执行得更快,但可能不改善性能,这是因为在预先高速缓存汇编件时不能进行由JIT/运行中编译器进行的环境专用的优化。如上面所说明的,大多数本机语言不跟踪关于源代码的内部结构的信息。相反,由于在托管环境中产生的中间字节代码中所包括的元数据,可以容易地在运行时生成利用当前现有的对象、创建新的对象、从现有的对象继承等等的代码。运行时生成的代码可以要求使用专用的机制以便无需从长期存储介质(例如,硬盘)加载运行时生成的代码就创建或加载动态代码。这样的机制在本文档的其余部分中被称为反射发出(Reflection Emit)。 也被称为动态地生成的代码的在运行时生成的代码通常在每一进程实例期间被编译成中间字节代码,且然后,被JIT/运行时编译器处理。这是并非微不足道的每进程成本。概述如果诸如托管汇编件或托管汇编件的部分(例如方法或函数)等的实体在运行时生成另外的代码,如果该方法或函数是纯的,则高速缓存另外的运行时生成的代码,以使得在该实体的随后的执行时可以通过从缓存查找经高速缓存的运行时生成的代码的标识符并从高速缓存检索所标识的代码来从高速缓存检索该代码,这旁路了代码生成的一个或多个阶段。此外,所高速缓存的代码可以由编译器预先编译和/或可以作为额外的数据而被添加到源汇编件的元数据。因此,运行时生成的代码可以被高速缓存并跨越程序的各实例而被重用。在运行时,检查一个或多个运行时生成的代码高速缓存,且如果所标识的实体存在于高速缓存中,则加载和使用该实体,这消除了中间字节代码生成阶段、编译/翻译阶段或中间字节代码生成阶段和编译/翻译阶段两者。提供本概述以便以简化形式介绍下面在详细描述中进一步描述的概念的选集。本概述不旨在标识所要求保护的本主题的关键特征或必要特征,也不旨在用于限制所要求保护的本主题的范围。附图简述各图中

图1是根据在此公开的本主题的各方面的用于高速缓存运行时生成的代码的系统的示例的框图;图加是本领域中已知的用于执行动态程序的方法;图2b是根据在此公开的本主题的各方面的用于高速缓存运行时生成的代码的方法的示例;图2c是根据在此公开的本主题的各方面的用于高速缓存运行时生成的代码的方法的另一示例;图3是阐释在此公开的本主题的各方面可以在其中实现的计算环境的示例的框图;和图4是根据在此公开的本主题的各方面的集成开发环境的示例的框图。详细描述概览反射发出是允许在运行时动态地创建另外的程序指令并调用这些程序指令的机制。即,可以在运行时基于在运行时适用的数据、服务和具体的操作来决定该程序体系结构本身。例如,假定特定的程序执行数学运算且用户想要基于具体大小的矩阵来执行计算。一种方法是写出能够对任何大小的矩阵执行计算的类属函数。这样的函数是静态的,这是因为它采用的算法直接地求解所期望的问题。这样的程序可能由于它要求对任何大小的矩阵起作用而具有低效率。替代地,该问题的动态解决方案可以涉及生成自定义算法以便解决该问题。这样的解决方案将涉及静态函数A,给予静态函数A各种输入自变量,静态函数A 将使用那些自变量中的一些来生成新的动态函数B,且然后将其他各种输入自变量传递给该动态函数。此自定义动态函数将可能仅对特定的输入起作用,但是可以以允许对于给定的受限的输入集的最佳性能的方式来写出它。例如,静态函数A可以接收到将大小为16x16 的两个矩阵相乘的请求。静态函数A可以生成仅能够将16x16矩阵相乘的新的动态函数B。 然后,静态函数A可以将把矩阵相乘的实际任务委托给动态函数B。通过使用诸如反射发出等的机制,可以在运行时编程地(动态地)对程序指令进行添加。即是说,继续上面的示例,通过使用诸如反射发出等的机制,可以在运行时编程地 (动态地)对类属程序指令进行优化,以便优化程序对16x16矩阵的这一特定执行。由诸如
5反射发出等的机制做出的动态修改可以改善性能、增加兼容性或提供其他有用的优点。在面向对象的环境的上下文内,反射发出允许创建新类型和关于各类型的新方法,且可以指定新方法实现的算法。在托管代码环境内,可以通过反射发出生成中间字节代码。在已知的现有系统中,运行时生成的中间字节代码必须在每次程序运行时被编译/被转换成本机机器指令。根据在此公开的本主题的各方面,动态程序第一次运行时,中间字节代码被创建、 被给予执行上下文专用的标识符并被高速缓存。在程序下次运行时,可以无需重新创建中间代码。例如,假定动态函数(即,在运行时生成中间字节代码的函数)存在。进一步假定函数接受在该函数的各次执行之间可以改变或可以不改变的两个自变量。取决于所接收的自变量的值,将创建不同的中间字节代码。根据在此公开的本主题的各方面,可以创建基于自变量值和动态代码生成函数名称的标识符,并将其与由该函数的这一执行产生的中间字节代码相关联。所标识的字节代码可以被高速缓存在中间字节代码高速缓存或该汇编件的元数据部分的任一个中,使得下次以自变量的相同的值执行该函数,可以从高速缓存检索所高速缓存的字节代码并将其直接加载到存储器中,这消除了对重新生成中间字节代码的需要。类似地,动态函数的标识符可以基于被给予生成动态函数的函数的自变量值。所高速缓存的动态函数的标识符可以基于生成函数用来生成动态函数的算法。动态函数的标识符可以标识动态代码生成的函数的特定版本。此外,如果中间字节代码被转换成本机代码,则该本机代码可以被高速缓存在本机代码高速缓存或源汇编件的元数据部分的任一个中。程序下次执行时,既不需要执行中间字节代码的生成,也不需要执行字节代码到本机二进制代码的转换。可以直接地从本机代码缓存加载并执行本机二进制代码。所高速缓存的本机二进制代码可以按先前段落所描述的来标识。高速缓存运行时生成的代码图1阐释根据在此公开的本主题的各方面的高速缓存运行时生成的代码的系统 100的示例。系统100可以包括下列中的一个或多个一个或多个组件120、编译器105、JIT 或运行中编译器110和一个或多个高速缓存(例如中间字节代码高速缓存109和/或可重用的可执行(机器代码)高速缓存118和/或源汇编件高速缓存12 ,其中组件120高速缓存运行时生成的代码和/或执行对运行时生成的代码高速缓存(例如中间字节代码高速缓存109和/或可重用的可执行(机器代码)高速缓存118和/或源汇编件高速缓存122) 的查找操作并将所标识的代码返回给请求者。JIT或运行中编译器可以在存储器中生成可执行的但不可重用的本机代码。可以在要运行程序时提供诸如输入自变量113等的输入自变量。系统100可以还包括诸如NGEN 112等的本机映像生成器。本机映像生成器可以生成和存储以本机二进制(机器语言)的可重用的可执行机器代码116。可重用的可执行机器代码116可以被存储在可重用的可执行(机器代码)高速缓存118。中间字节代码可以被存储在中间字节代码高速缓存109中。本机二进制代码或中间字节代码可以被存储在源汇编件高速缓存122中。中间字节代码高速缓存109、可重用的可执行(机器代码)高速缓存118和/或源汇编件高速缓存122可以是机器范围的或系统范围的高速缓存。系统 100的全部或部分可以驻留在诸如下面相对于图3所描述的计算机等的一个或多个计算机上。系统100或其部分可以包括诸如下面相对于图4所描述和阐释的IDE等的集成设计环境600 (IDE)的部分,驻留也在下面相对于图3所描述的计算机等的一个或多个计算机上。 替代地,可以作为单机系统或作为插件来提供系统100或其部分。编译器105可以包括将以.NET语言写成的源代码编译成中间字节代码(例如,普通中间语言或CIL)的.NET编译器。.NET语言包括但不限于Visual Basic、Visual J#、 C++、C#、J#、Java Script、APL、COBOL>Pascal、Eiffel、Haskell、ML、Oberon、Perl、Python、 Scheme, Smalltalk或任何其他.NET语言。编译器102可以包括将以JAVA写成的源代码编译成JAVA字节代码的JAVA编译器。编译器105可以将源代码104编译成一个或多个托管汇编件108等等。源代码 104可以包括动态程序代码,即,在被执行时在运行时生成另外的代码的代码,例如,运行时生成的中间字节代码111。托管汇编件可以包括中间字节代码106和元数据107。元数据 107可以包括和标识实体(例如汇编件或汇编件的部分(例如该汇编件的函数或方法))是否在运行时生成代码以及该实体是否适用于高速缓存的自定义属性有关的信息。一般地, 适用于高速缓存的程序实体不扰乱全局状态。这样的实体被称为“纯的”或“纯功能的”。例如,纯函数不扰乱全局状态。元数据可以被嵌入在生成函数、被传送给动态的代码的生成器的自变量数据或其他地方中。源汇编件可以被维持在诸如源汇编件高速缓存122等的源汇编件高速缓存(库)中。如本领域中已知的,当执行任一汇编件时,该汇编件被加载到存储器中。如果可获得预先编译的可执行代码(例如,由诸如NGEN 112等的本机映像生成器创建的),可以加载和执行本机二进制代码。如果不可获得预先编译的可执行代码,则JIT或运行中编译器110 可以将托管汇编件108转换成存储器中的不可重用的本机二进制代码114。在已知的系统中,即使程序本身已经以本机二进制格式预先编译,也必须在每次运行程序时重新编译由该程序在运行时生成的代码。调用生成另外的程序代码的诸如反射发出等的机制(例如, 使用被存储在汇编件的元数据中的附加信息,反射发出生成诸如运行时生成的中间字节代码111等的中间字节代码)。生成运行时生成的中间字节代码111,且JIT或运行中编译器将运行时生成的中间字节代码转换成不可重用的可执行本机二进制代码114(机器代码)。相比之下,根据在此公开的本主题的各方面,运行时生成的代码可以在某些情况下被高速缓存(例如,在中间字节代码高速缓存109和/或可重用的可执行(机器代码) 高速缓存118和/或源汇编件高速缓存122中)。例如,假定程序包括在运行时生成另外的代码的纯函数。在此所使用的纯函数是指不扰乱全局状态的函数。假定函数A采用两个自变量,即自变量a和自变量b。在用自变量a =值1和自变量b =值2调用函数A时,所生成的中间代码是相同的。因此,通过为到运行时代码生成方法的一个或多个自变量的特定值(执行专用的特性)创建用于该运行时代码生成方法的特定身份,并且高速缓存所生成的中间代码,可以消除用于该函数的随后调用的中间语言的生成。因此,第一次执行函数时,可以生成、标识和高速缓存中间语言。将值1用于自变量a且值2用于自变量b,第二次执行函数时,不需要生成中间代码,这是因为它已经被高速缓存了。可以改为从由标识符鉴别的高速缓存检索由函数名称和自变量值标识的中间代码。此外,如果已经从中间代码生成了本机代码(例如,由诸如NGEN等的本机二进制代码映像生成器),则可以从机器代码高速缓存检索机器代码,这消除了对生成中间字节代码的需要和对从中间字节代码生成本机机器代码的需要。可以测试公共场景,且可以产生公共地生成的中间字节代码,和/或可以产生和预先高速缓存本机二进制代码。根据一些在此公开的本主题的各方面,中间字节代码和/ 或本机二进制代码映像可以作为另外的元数据被包括在汇编件内,以使得即使汇编件第一次在用户的机器上运行且机器范围的中间字节代码高速缓存和/或本机二进制机器代码高速缓存是空的,也可以在汇编件本身中找到中间字节代码或本机二进制代码。根据一些在此公开的本主题的各方面,已经用动态代码生成函数更新的汇编件可以接收用于汇编件的新的版本号和/或用于可能被废弃的或未被使用的汇编件的先前的(例如,未经更新的或原始的)高速缓存信息。图加阐释用于本领域中已知的运行时生成的代码的方法。在202,包括动态程序 (产生运行时生成的代码的程序)的源代码可以由诸如以上相对于图1所描述的编译器等的编译器进行编译。编译器的输出可以是包括中间字节代码和与所产生的中间字节代码关联的元数据的汇编件。在204,可以接收执行汇编件的请求。在206,可以将汇编件加载到存储器。在208,基于标识符键的查找可以判断是否可获得预先编译的本机二进制可执行代码。在210,该查找过程可以判断可获得本机二进制可执行代码,且可以加载和执行该本机二进制可执行代码。在208,该查找可以判断不可获得预先编译的本机二进制可执行代码。响应于此判断,在212,JIT或运行中编译器可以将中间字节代码编译或翻译成本机二进制代码、加载和执行该二进制代码。在214,无论是预先编译还是JIT编译,动态程序都可以执行。在216,动态程序可以在它执行时通过调用诸如反射发出等的机制来生成另外的程序代码。可以由反射发出将此运行时生成的代码作为中间字节代码而发出。在可以执行运行时生成的代码之前,它必须被JIT或运行中编译器编译成本机二进制代码。不存在预先编译运行时生成的代码的能力,也不存在为运行时生成的代码创建本机二进制可执行代码的方法。图2b阐释根据在此公开的本主题的各方面的用于高速缓存运行时生成的代码的方法的示例。在302,可以接收到对生成程序实体(例如动态程序或程序的部分(例如动态的方法或函数))的请求。可以通过与生成程序实体的方法相关联的元数据中的特定指示符的存在来判断适用于高速缓存的程序实体。适用于高速缓存其结果的方法或函数是不扰乱全局状态的方法或函数。不会出乎意料地改变全局状态的方法或函数被称为“纯”方法(或“纯”函数)。根据在此公开的本主题的各方面,这样的方法或函数的指示符可以是自定义属性。在304,可以根据指定的算法或方案来计算或生成标识符。例如,假定函数A采用两个自变量,自变量a和自变量b。在用自变量a =值1和自变量b =值2调用函数A时生成的中间代码不同于在用自变量a兴值a和/或自变量 b兴值2调用函数A时所生成的中间代码。下次用自变量a =值1和自变量b =值2调用函数A所生成的中间代码与第一次用自变量a=值1和自变量b=值2调用函数A时相同, 除非函数A在两次调用之间发生改变。为确保过期的缓存不被使用并被自动地冲洗,可以使用运行时代码生成函数A的名称(例如,“ [Namespace:: JObjectName: :A”)来生成用于该函数的特定身份,且除了各自变量的特定值(值1和值幻之外,该特定身份还包括包含函数A的汇编件的强名称。即,使用标识符中的各自变量的特定值防止了错误的中间代码的使用,且包含函数A的汇编件的的强名称的使用被用于确保汇编件的错误版本的中间代码不被使用(例如,汇编件1意味着调用旧的函数A且汇编件2意味着调用经更新的函数 A)。在306,可以针对所标识的程序实体检查诸如中间字节代码高速缓存等的第一高速缓存。在308,如果所计算的标识符存在于第一高速缓存(例如,中间字节代码高速缓存) 中,则在330,可以检查第二高速缓存。次级高速缓存可以是本机二进制代码高速缓存。在 332,如果所标识的程序实体存在于次级高速缓存中,则可以针对中间字节代码高速缓存查找的结果来验证本机代码,以判断它是否是与中间代码高速缓存的版本相同的版本,且在 346,如果本机代码是最新的(例如,在344,与用于所标识的程序实体的中间字节代码的版本相同的版本),则可以加载和执行本机代码二进制。如果,在332所标识的程序实体不存在于次级(本机代码)高速缓存中,则在334,可以生成本机代码(由JIT或运行中编译器或由NGEN生成,以供稍后高速缓存),在336,加载和执行本机代码,且如果由NGEN生成,则在338高速缓存本机代码。如果在308,用于程序实体的中间代码不存在于主高速缓存中,在340,可以在340 生成中间代码(例如,通过调用反射发出)且在342将其高速缓存。在340生成中间代码之后,在330,可以针对程序实体检查次级高速缓存。次级高速缓存可以是本机二进制代码高速缓存。在332,如果所标识的程序实体存在于次级高速缓存中,则针对中间字节代码高速缓存查找的结果来验证本机代码,以便在344判断其是否是与中间代码缓存的版本相同的版本,且在346,如果本机代码是最新的(例如,与用于所标识的程序实体的中间字节代码的版本相同的版本),则可以加载和执行本机代码二进制。如果,在332,所标识的程序实体不存在于次级(本机代码)高速缓存中,则在334,可以生成本机代码(由JIT或运行中编译器或由NGEN生成,以供稍后高速缓存),在336,加载和执行本机代码,且如果由NGEN 生成,则在338高速缓存本机代码。应明白,本机二进制代码高速缓存可以是在汇编件本身内或可以是机器范围的高速缓存。类似地,应明白,第一高速缓存可以是中间字节代码高速缓存或源汇编件高速缓存。根据在此参照图2c公开的本主题的其他方面,在306,可以针对所标识的程序实体检查诸如本机二进制代码高速缓存等的第一高速缓存。如果,在308,所计算的标识符存在于该第一高速缓存(例如,本机二进制代码高速缓存)中,则在324,可以从本机二进制代码高速缓存检索本机二进制代码,并加载和执行本机二进制代码。如果所计算的标识符不存在于第一高速缓存(例如,本机二进制代码高速缓存)中,则在310,可以在第二高速缓存 (例如,中间字节代码高速缓存)执行查找以得到所标识的实体。在312,如果用于所标识的实体的中间代码存在于中间字节代码高速缓存中,则在314,可以检索中间字节代码并将其翻译/编译成本机代码。可选地可以高速缓存本机代码。在316,可以加载和执行本机代码。如果用于所标识的实体的中间字节代码不存在于中间字节代码高速缓存中,则可以生成中间字节代码(例如,通过调用反射发出),在318,生成中间字节代码,在320,可以高速缓存中间字节代码,且在322可以加载和执行中间字节代码。应明白,本机二进制代码高速缓存可以是在汇编件本身内或可以是机器范围的高速缓存。类似地,应明白,第一高速缓存可以是中间字节代码高速缓存或源汇编件高速缓存,且反之亦然。合适的计算环境的示例为了提供在此公开的本主题的各种方面的上下文,图3和下列的讨论旨在提供其中可以实现各种实施方式的合适的计算环境510的简要的一般的描述。尽管在此公开的本主题由一个或多个计算机或其他计算设备执行的诸如程序模块等的计算机可执行指令的一般的上下文来描述,但是本领域技术人员应认识到,还可以组合其他程序模块和/或硬件和软件的组合来实现在此公开的本主题的各部分。一般地,程序模块包括执行特定任务或实现特定数据类型的例程、程序、对象、物理人工制品、数据结构等等。通常,在各种实施方式中可以根据需要组合或分布程序模块的功能。计算环境510仅是合适的操作环境的一个示例且不旨在限制在此公开的本主题的使用范围或功能。参考图3,描述了以计算机512的形式的通用计算设备。计算机512可以包括处理单元514、系统存储器516和系统总线518。处理单元514可以是各种可获得的处理器中的任一种。双微处理器和其他多处理器体系结构也可以用作处理单元514。系统存储器516 可以包括易失性存储器520和非易失性存储器522。非易失性存储器522可以包括只读存储器(ROM)、可编程ROM(PROM)、电可编程ROM(EPROM)或闪速存储器。易失性存储器520可以包括可以充当外部高速缓存存储器的随机存取存储器(RAM)。系统总线518将包括系统存储器516的系统物理人工制品耦合到处理单元514。系统总线518可以是包括存储器总线、存储器控制器、外围总线、外部总线或局部总线的若干类型中的任一种,且可以使用任何种类的可获得的总线体系结构。计算机512通常包括诸如易失性介质和非易失性介质、可移动介质和不可移动介质等的各种计算机可读介质。计算机存储介质可以以用于存储诸如计算机可读指令、数据结构、程序模块或其他数据等的信息的任何方法或技术来实现。计算机存储介质包括但不限于RAM、ROM、EEPROM、闪速存储器或其他存储器技术、CDROM、数字多用盘(DVD)或其他光盘存储、磁带盒、磁带、磁盘存储或其他磁存储设备、或可以用于存储所期望的信息且可由计算机512访问的任何其他介质。应明白,图3描述了可以充当在用户和计算机资源之间的中介的软件。此软件可以包括可以被存储在盘存储5M上且可以控制和分配计算机系统512的资源的操作系统 528。盘存储5 可以是通过诸如接口 5 等的不可移动存储器接口连接到系统总线518 的硬盘驱动器。系统应用程序530通过被存储在系统存储器516中或盘存储5M上的程序模块532和程序数据534来利用操作系统5 对资源的管理。应明白,可以用各种操作系统或操作系统的组合来实现计算机。用户可以通过输入设备536将命令或信息输入到计算机512。输入设备536包括但不限于指点设备,例如鼠标、跟踪球、触笔、触摸垫、键盘、话筒等等。这些和其他输入设备通过系统总线518经由接口端口 538连接到处理单元514。接口端口 538可以代表串行端口、并行端口、通用串行总线(USB)等等。输出设备540可以使用与输入设备所使用的端口具有相同类型的端口。提供输出适配器542以便阐释存在要求特定的适配器的一些输出设备M0,如监视器、扬声器和打印机。输出适配器542包括但不限于提供在输出设备540和系统总线518之间的连接的视频卡和声卡。诸如远程计算机544等的其他设备和/或系统或设备可以提供输入能力和输出能力两者。计算机512可以使用到诸如远程计算机544等的一个或多个远程计算机的逻辑连接来在联网环境内操作。远程计算机544可以是个人计算机、服务器、路由器、网络PC、对等设备或其他普通网络节点,且通常包括上文相对于计算机512所描述的元件中的许多或全部,尽管在图3中仅已阐释存储器存储设备M6。远程计算机544可以经由通信连接550 而被逻辑连接。网络接口 548包括诸如局域网(LAN)和广域网(WAN)等的通信网络,但还可以包括其他网络。通信连接550是指被用来将网络接口 548连接到总线518的硬件/软件。连接550可以是内置或外置于计算机512,且包括内置技术和外置技术,例如调制调解器(电话、线缆、DSL和无线)和ISDN适配器、以太网卡等等。应明白,所示出的网络连接仅仅是示例,且可以使用在计算机之间建立通信链路的其他手段。本领域普通技术人员应明白,计算机512或其他客户机设备可以被部署为计算机网络的部分。在这一点上,在此公开的本主题可以属于具有任何数量的存储器或存储单元的任何计算机系统以及跨越任何数量的存储器或存储单元而发生的任何数量的应用程序和进程。在此公开的本主题的各方面可以应用到具有被部署在网络环境中的服务器计算机和客户机计算机、具有远程或本地存储的环境。在此公开的本主题的各方面还可以应用到具有编程语言功能性、解释和执行能力的单机计算设备。图4阐释集成开发环境(IDE) 600和公共语言运行时环境602。IDE 600可以允许用户(例如,开发者、程序员、设计人员、编码员等等)在计算机系统中设计、编码、编译、测试、运行、编辑、调试或构建程序、程序集、web站点、web应用程序和web服务。软件程序可以包括以一种或多种源代码语言(例如,Visual Basic,Visual J#、C++、C#、J#、Java Script、 APL> COBOL、Pascal、Eiffel、Haskell、ML、Oberon、Perl、Python、Scheme、Smalltalk 等等) 创建的源代码(组件610)。IDE 600可以提供本机代码开发环境或可以提供在虚拟机上运行的托管代码开发环境或可以提供其组合。IDE 600可以提供使用.NET架构的托管代码开发环境。在应用程序被执行时,中间语言组件650可以由源代码组件610和本机代码组件 611使用语言专用的源编译器620来创建,且本机代码组件611 (例如,机器可执行指令)由中间语言组件650使用中间语言编译器660(例如,准实时(JIT)编译器)来创建。S卩,在 IL应用程序被执行时,它在被执行的同时被编译成它正在其上被执行的平台的适当的机器语言,由此使得可跨越若干平台移植的代码。替代地,在其他实施方式中,程序可以被编译为适合于其预期平台的本机代码机器语言(未示出)。用户可以经由IDE 600中的用户界面640和源代码编辑器651,根据已知的软件编程技术和与特定的源语言相关联的具体逻辑和语法规则来创建和/或编辑源代码组件。此后,源代码组件610可以经由源编译器620来编译,由此可以创建程序的诸如汇编件630等的中间语言表示。汇编件630可以包括中间语言组件650和元数据642。可以在部署之前验证应用程序设计。在此描述的各种技术可以结合硬件或软件或在适当时结合两者的组合来实现。因而,在此描述的方法和装置或其某些方面或部分,可以采取在诸如软盘、⑶-ROM、硬盘驱动器或任何其他机器可读的存储介质等的有形介质中具体化的程序代码(即,指令)的形式, 其中,在程序代码被加载到诸如计算机等的机器中并被诸如计算机等的机器执行时,该机器变成用于实践在此公开的本主题的各方面的装置。在可编程的计算机上执行程序代码的情况下,计算设备将一般地包括处理器、处理器可读存储介质(包括易失性和非易失性存储器和/或存储元件)、至少一个输入设备和至少一个输出设备。可以例如通过使用数据处理API等等来利用领域专用的编程模型方面的创建和/或实现的一个或多个程序,可以以高级面向过程的编程语言或面向对象的编程语言来实现,以便与计算机系统通信。然而,如
11果期望的话,(诸)程序可以以汇编件或机器语言来实现。在任何情况下,语言可以是编译语言或解释语言,并与硬件实现组合。 尽管已经结合附图描述了在此公开的本主题,但应理解,可以进行修改以便以不同的方式执行相同的功能。
权利要求
1.一种缓存运行时生成的代码的系统(100),包括在计算机上的托管代码环境中执行的组件(120),所述组件将实体(116,111)高速缓存在第一高速缓存(109,118)或第二高速缓存(109,118)中,所缓存的实体(116,111)包括运行时生成的代码,所述运行时生成的代码由动态代码生成实体在运行时生成,其中所述动态代码生成实体不扰乱全局状态,其中在所高速缓存的实体(116,111)的随后的执行中从所述第一高速缓存(109,118)或所述第二高速缓存(109,118)检索所高速缓存的实体 (116,111),这旁路了代码生成的至少一个阶段,所旁路的代码生成的至少一个阶段包括中间字节代码的生成或本机二进制代码的生成。
2.如权利要求1所述的系统,其特征在于,所述第一高速缓存包括存储表示所述运行时生成的代码的中间字节代码的高速缓存,且其中所旁路的代码生成的至少一个阶段包括用于所述运行时生成的代码的中间字节代码的生成。
3.如权利要求1所述的系统,其特征在于,所述第二高速缓存包括存储本机二进制代码的高速缓存,且其中所旁路的代码生成的至少一个阶段包括用于所述运行时生成的代码的本机二进制代码的生成。
4.如权利要求1所述的系统,其特征在于,所述第一高速缓存是源汇编件高速缓存且其中所旁路的代码生成的至少一个阶段包括用于所述运行时生成的代码的中间字节代码的生成或用于所述运行时生成的代码的本机二进制代码的生成。
5.如权利要求1所述的系统,其特征在于,通过标识符来检索用于所述运行时生成的代码的所述中间字节代码,所述标识符由与所述动态代码生成实体关联的名称、被传送给所述动态代码生成实体的至少一个自变量和用于所述动态代码生成实体的版本指示符组成。
6.一种高速缓存运行时生成的代码的方法,包括计算用于包括由纯功能的运行时代码生成实体生成的运行时生成的代码的实体的标识符(304),所述运行时生成的代码实体包括由反射发出机制创建的中间字节代码,所计算的标识符包括所述运行时生成的代码的执行上下文专用的特性,在所述实体的第一次执行时将所述实体存储在所计算的标识符所鉴别的第一高速缓存上(320);响应于所存储的实体的第二次执行,返回(322)所述所存储的实体,其中为所述所存储的实体的所述第二次执行旁路用于所述所存储的实体的所述中间字节代码的生成。
7.如权利要求6所述的方法,进一步包括从用于所述所存储的实体的所述中间字节代码生成用于所述运行时生成的代码的本机二进制代码。
8.如权利要求7所述的方法,进一步包括将所生成的本机二进制代码高速缓存在包括第二高速缓存的本机二进制代码高速缓存中。
9.如权利要求6所述的方法,其特征在于,所述第一高速缓存或所述第二高速缓存是包括所存储的实体的源汇编件。
10.如权利要求6所述的方法,其特征在于,所计算的标识符包括由与所述纯功能的运行时代码生成实体关联的名称、被传送给所述纯功能的运行时代码生成实体的至少一个自变量和用于所述纯功能的运行时代码生成实体的版本指示符组成的标识符。
11.一种包括计算机可执行指令的计算机可读存储介质,所述计算机可执行指令在被执行时引起托管计算环境将实体高速缓存在第一高速缓存或第二高速缓存中,所述实体包括由不扰乱全局状态的运行时代码生成实体生成的运行时生成的代码,其中在所述实体的随后的执行中检索所高速缓存的实体,这在所述随后的执行中旁路了代码生成的至少一个阶段。
12.如权利要11所述的计算机可读存储介质,包括进一步的计算机可执行指令,所述计算机可执行指令在被执行时引起所述计算环境为所高速缓存的实体的所述随后的执行旁路用于所述运行时生成的代码的中间字节代码的生成。
13.如权利要11所述的计算机可读存储介质,包括进一步的计算机可执行指令,所述计算机可执行指令在被执行时引起所述计算环境为所高速缓存的实体的所述随后的执行从用于所述运行时生成的代码的中间字节代码旁路本机二进制代码的生成。
14.如权利要13所述的计算机可读存储介质,包括进一步的计算机可执行指令,所述计算机可执行指令在被执行时引起所述计算环境将所述本机二进制代码或中间字节代码高速缓存在所高速缓存的实体的源汇编件中。
15.如权利要13所述的计算机可读存储介质,包括进一步的计算机可执行指令,所述计算机可执行指令在被执行时引起所述计算环境使用所高速缓存的实体的执行专用的特性来向所述实体提供特定身份;以及从所述特定身份所鉴别的所述第一高速缓存或所述第二高速缓存检索所高速缓存的实体。
全文摘要
标识生成代码但不扰乱全局状态的程序实体。可以在第一次执行由所标识的程序实体产生的代码时给它指派标识符并将其高速缓存。程序实体的随后的执行可以消除代码的生成和/或所生成的代码到本机二进制代码的翻译。运行时生成的代码和本机二进制代码可以被高速缓存在机器范围的高速缓存中,或者可以被添加到从程序实体的源代码生成的汇编件的元数据。
文档编号G06F9/06GK102187313SQ200980141635
公开日2011年9月14日 申请日期2009年9月30日 优先权日2008年10月15日
发明者N·赫林, D·C·赖顿 申请人:微软公司

最新回复(0)