动态编程语言的基于跟踪器的运行时优化的制作方法

文档序号:6532910阅读:144来源:国知局
动态编程语言的基于跟踪器的运行时优化的制作方法
【专利摘要】本发明描述了一种方法和装置,所述方法和装置随机地且不频繁地针对在源代码的编译代码的运行时期间创建的值的起源和目标生成跟踪器数据。可更新跟踪器图以记录在所述运行时期间所述值的起源和目标。可优化所述编译代码以根据所述跟踪器图减少所述值的起源和目标之间的处理资源。可针对所述源代码的至少一部分来执行所述优化编译代码。
【专利说明】动态编程语言的基于跟踪器的运行时优化
[0001]相关专利申请的交叉引用
[0002]本申请与由Filip Pizlo等人于2012年2月3日提交的名称为“RUNHMECOMPILATION FOR DYNAMIC PROGRAMMING LANGUAGES”的美国临时专利申请号 61/594,983、由Filip Pizlo等人于2012年2月 15 日提交的名称为“RUNTIME COMPILATION FOR DYNAMICPROGRAMMING LANGUAGES”的美国临时专利申请号61/599,309相关并要求其权益,这两个专利据此全文以引用方式并入本文。

【技术领域】
[0003]本发明整体涉及运行时编译。更具体地,本发明涉及基于动态语言的源代码的运行时编译。

【背景技术】
[0004]不含任何种类的类型注释的动态语言越来越普遍。例如,JavaScript已经成为万维网的通用语言,而Ruby、Python、Perl和PHP已经成为服务器端基础架构的标准语言。然而,当可能未提供优化编译策略以编译代码时,基于动态语言的代码的运行时可能需要显著开销。
[0005]例如,JavaScript不允许程序指定变量的类型。因此,在运行时期间,变量可被动态转换为不同执行路径中的独立类型。此类转换可能在计算上开销大,使整体性能受到重大影响。另外,动态创建的数据类型可能需要索引数据结构例如字典间大量的查找或搜索操作,以将类型分配到数据或访问特定类型数据的属性。
[0006]此外,需要现代JavaScript引擎来非常快速地执行非可信代码,并且由于这个原因,通过诸如即时(JIT)编译的机制使用运行时代码生成,攻击者可利用这一点绕过操作系统/硬件保护。现有保护技术,例如常量盲化,可用于阻止此类攻击。然而,这些技术可在存储器使用和处理器执行时间两方面引发目标代码的性能成本,无论所执行的目标代码是否具有风险。
[0007]因此,传统的动态运行时编译方法往往是昂贵、低效和未优化的。


【发明内容】

[0008]可随机地且不频繁地分配跟踪器数据(例如,堆分配单元或跟踪弹(tracerbullet))以分析从起源代码位置和目标代码位置流出的值以便优化编译代码。跟踪器数据可包括或装箱某个值以及该值在源代码或程序中的相应起源(或来源)。值的起源可指示值在源代码中的生成位置。在一个实施例中,可在运行时期间将值存储在存储器中时创建跟踪器数据。来源可以是标识用于存储该值的代码位置(例如行号)的指针宽度字。可将特定的类型或标签与跟踪器数据相关联以迫使使用(或访问、引用)跟踪器数据的代码执行或操作采用慢速路径,因为可能无法在源代码中对跟踪器数据进行现有类型检查。所述慢速路径可记录跟踪器数据中的值的起源(或源)代码位置和正在使用跟踪器数据的接收(或目标)代码位置之间的链接。该链接可分配有权重以指示值传递(或跟踪)通过链接的次数。
[0009]在一个实施例中,可基于运行时期间在值的起源代码位置和目标代码位置之间记录的链接来生成概率数据流程图。可对图形的每个边加权以对应于占用边的值流的相对概率。值如何流过程序以及使用那些值的不同操作执行频率有多高可从概率数据流程图识另IJ。因此,概率数据流程图可提供执行程序的运行时概率视图以揭示运行时编译的优化机
A
O
[0010]在一个实施例中,可根据概率数据流程图来执行运行时编译器上的优化操作。例如,如果流过整数路径的值更可能用于浮点运算,则整数路径可被转化为浮点路径。同样,如果以浮点格式存储的整数极有可能(例如基于概率数据流程图)在以后用于整数运算,则可将其转换为整数格式。作为另外一种选择,如果整数堆存储(例如,整数格式的值)具有流入浮点加载中的高概率,则可优化编译器而替代地以浮点数据的形式堆存储,但要进行另外的类型检查操作以确保可靠性。
[0011]在一个实施例中,可使用相对于数据结构集合描述了键的属性的元数据,对使用键索引数据结构(例如字典、哈希表、关联数组等)集合中的键的操作进行优化。元数据可对应于动态更新的高速缓存以指示不变量,该不变量对于处于数据结构集合的当前状态的键而言为真。可避免用于在键的数据结构集合上进行搜索的昂贵计算。例如,如果已知键始终(或从不)引用某些特定的值,或者由于这些值具有在处于当前状态的系统的全局范围内的任何数据结构集合中的某些元属性,则可能根本无需在数据结构(或字典)集合上进行昂贵的查找操作。
[0012]在另一个实施例中,运行时编译器可以发射实现快速路径(例如,无负载和分支结构)的编译代码,以基于对与通过源代码识别的键相关联的元数据的假设来执行源代码的指令。编译代码可包括保护符,例如条件检查代码,以基于与键相关联的元数据进入慢速路径并防止进入快速路径。在运行时执行编译代码期间,可保持包括对象的运行时状态,所述对象具有通过键而散列的属性。可动态更新键的元数据以反映运行时状态的变化(例如,在对象中)。可执行保护符以执行廉价的检查操作(例如,引用键的元数据而不在运行时状态下的对象上执行昂贵的查找),从而更新已发射编译代码以在运行时期间需要时包括慢速路径。
[0013]在另一个实施例中,可使用类型信息(或其他属性信息)修改(或破坏)存储器中类型化数据的指针值,以在通过修改的指针值对类型化数据执行存储器访问操作时,利用基于硬件的安全检查机制针对类型化数据自动检查类型信息。从而,当执行使用已修改指针的软件代码(其经受安全检查但不执行例如软件代码中的比较和分支指令)时,硬件内置逻辑可用于广义类的编程语言安全检查。
[0014]在一个实施例中,动态编程语言中类型的对象的指针的一部分(例如,64位系统中的高16位)可配置(或设置)有用于对类型进行标识的类型标识符。当通过被怀疑为该类型但并非已知为该类型的指针对所述对象执行访问时,可使用类型标识符(例如,通过XOR算术运算)来更新指针以执行访问。如果对象确实是由类型标识符所标识的类型,则访问可能成功,否则将导致硬件陷阱自动激活陷阱处理程序。
[0015]在另一个实施例中,运行时编译(例如JIT编译)可基于启发式规则生成非确定性和不可预测的代码以防止非可信代码攻击,例如JIT SPRAY攻击,而不需要所有已生成代码的确定性行为减少操作。启发式规则可包括对例如所引发代码保护的成本(例如,运行时开销)、所需代码保护的量和/或其他适用因素及其关系的估算。
[0016]在一个实施例中,当执行源代码的运行时编译时,动态收集或累计数字(或测量值)以估算源代码状态的可信度。所述数字可基于对来自源代码的已发射代码的量(例如,已生成的字节数)以及对已发射代码的不可信控制量的跟踪。例如,所述数字可确定(不可预测地)是否盲化(或重整、随机化)编译代码的源代码的常量,以抵御嵌入常量中的潜在非可信可执行代码。
[0017]通过附图以及通过以下具体描述,本发明的其他特征将显而易见。

【专利附图】

【附图说明】
[0018]本发明以举例的方式进行说明,而不仅限于各个附图的图形,在附图中类似的附图标号表示类似的元件,并且其中:
[0019]图1为网络图,其示出了从网络化设备检索的源代码的示例性运行时编译;
[0020]图2为框图,其示出了动态编程语言运行时编译的系统的一个实施例;
[0021]图3为流程图,其示出了采用跟踪器数据(或跟踪弹)的优化运行时编译过程的一个实施例;
[0022]图4为流程图,其示出了在运行时期间随机跟踪跟踪器图中的值以优化编译的过程的一个实施例;
[0023]图5为图形示意图,其示出了在运行时期间跟踪值的示例性跟踪器图;
[0024]图6为流程图,其示出了使用散列键的元数据访问散列值的过程的一个实施例;
[0025]图7为流程图,其示出了使用散列键的元数据动态更新推测生成的编译代码而无需查询散列键的散列数据的过程的一个实施例;
[0026]图8示出了根据本文所述一个实施例的运行时的示例性键元数据;
[0027]图9为流程图,其示出了访问特定类型数据而无需比较和分支操作的过程的一个实施例;
[0028]图10为流程图,其示出了用于根据已缓存类型访问对象的数据元而无需执行比较和分支操作的过程的一个实施例;
[0029]图11示出了根据本文所述实施例表示对象的类型嵌入指针的一个例子;
[0030]图12为框图,其示出了用于访问特定类型数据而无需比较和分支操作的系统的一个实施例;
[0031]图13为流程图,其示出了以非确定性方式选择性地随机化来自源代码的编译代码的过程的一个实施例;
[0032]图14为流程图,其示出了从源代码的编译代码流发射非确定性随机化的可执行代码的过程的一个实施例;
[0033]图15A-15B示出了根据本文所述某些实施例的采用分散随机化操作的即时编译的例子;
[0034]图16示出了诸如计算机系统的数据处理系统的一个例子,该数据处理系统可与本文所述的实施例一起使用。

【具体实施方式】
[0035]本文描述了用于运行时编译器的方法和装置。以下说明中示出了许多具体细节,以提供对本发明实施例的全面解释。然而,对于本领域的技术人员显而易见的是,本发明的实施例可在不具有这些具体细节的情况下实施。在其他情况下,未详细示出已熟知的组件、结构和技术,以免影响对此说明的理解。
[0036]本说明书中提到的“一个实施例”或“实施例”是指,结合实施例所描述的特定特征、结构或特性可包括在本发明的至少一个实施例中。在本说明书中的不同位置出现短语“在一个实施例中”不一定都是指同一个实施例。
[0037]下图中示出的过程通过处理逻辑执行,所述处理逻辑包括硬件(例如,电路、专用逻辑等)、软件(例如在通用计算机系统或专用机上运行的软件),或它们两者的组合。虽然下文按照某些顺序操作来描述过程,但应当理解,所描述的某些操作可以不同的顺序来执行。此外,某些操作也可以并行地执行而并非按顺序执行。
[0038]图1为网络图,其示出了从网络化设备检索的源代码的示例性运行时编译。在一个实施例中,网络系统100可包括一个或多个服务器应用101,例如在一个或多个服务器设备中托管的web服务器,以提供可用于客户端应用105的内容,例如在客户端设备中运行的web浏览器。服务器101和客户端105可基于例如诸如HTTP (超文本传输协议)之类的互联网络协议或其他适用的协议通过网络103彼此通信。
[0039]在一个实施例中,从服务器101检索的内容可包括基于超文本语言(例如HTML (超文本标记语言)或其他标记语言)的web页面,该超文本语言嵌入在动态编程语言(例如JavaScript)中或与动态编程语言的源链接(例如超链接)。客户端105可以动态地下载或获取用于执行的链接源。在一个实施例中,客户端105可以在运行时期间动态地编译所下载的源以提高执行性能。
[0040]图2为框图,其示出了动态编程语言运行时编译的系统的一个实施例。在一个实施例中,系统200可包括操作环境201,例如图1的操作系统托管客户端应用101。操作环境201可包括动态地将源代码203编译成可执行代码213的运行时编译器221。源代码203可包括动态编程语言例如JavaScript中的程序。在一个实施例中,可通过在操作环境201中运行的浏览器应用程序从远程设备(例如,图1的服务器101)检索源代码203。运行时编译器221和执行运行时215均可由浏览器应用程序控制以执行浏览操作。
[0041]在一个实施例中,运行时编译器221可包括未优化代码生成器模块207以编译源代码203。模块207可包括源概要分析模块209以从源代码203生成概要分析信息(例如,代码位置标识符、令牌密钥、或其他静态分析代码数据等)。根据一些实施例,模块207可提供可执行代码213的初始版本,可通过优化编译模块211而在运行时期间动态地更新和优化该初始版本。
[0042]例如,执行运行时215可以执行可执行代码213以收集跟踪器图219,该跟踪器图提供优化编译模块211的运行时统计值以在可执行代码213上执行优化操作(例如,数据类型转换、代码替换等)。执行运行时215可以动态地保持运行时状态217,包括例如创建的用于执行源代码203的数据实例(例如,对象或其他数据结构)。运行时编译器221可包括非确定性代码随机化模块205,以在源代码203和可执行代码213之间引入不可预测性,从而防止执行嵌入在源代码203内的潜在隐藏的可执行代码。
[0043]基于动态跟踪器的运行时优化
[0044]在一个实施例中,在编译源代码时,可在例如概要分析阶段期间将跟踪代码引入(或注入、植入)源代码的编译代码中。跟踪代码在执行编译代码(例如,未优化代码)的运行时期间被执行时,可以随机地和偶发地生成跟踪器数据,以提供信息暴露机会从而优化编译代码。
[0045]应当理解,基于跟踪器的运行时优化也将是实用的和有用的,即使优化代码有时生成跟踪器也是如此。该技术可适用于未优化代码和/或以前优化的代码它们两者。例如,可执行基于跟踪器的运行时优化以通过到生成跟踪器的子例程的跳转随机地覆写优化代码;该子例程随后将在执行后“撤销”代码更改,使得后续的执行不会付出创建跟踪器的代价。
[0046]可在运行时期间,通过利用从执行跟踪代码获得的信息,而将优化操作(例如类型转换或其他适用的编译操作)动态地应用于优化编译代码的多个部分。可动态地执行优化编译代码(而不是未优化编译代码)以便在由跟踪代码引发的有限的处理或资源成本的情况下,加快例如源代码的某些选择部分,例如重复函数调用或循环。
[0047]例如,可执行跟踪代码以创建跟踪器数据,从而表示在编译代码的运行时期间使用的值。可使值的跟踪器数据结构化以包括(或装箱)该值及该值的附加代码信息,例如该值的起源或来源(例如,源文件名、行号、或指示该值在编译代码或源代码中的创建位置或来源位置的其他信息,例如针对该值生成的机器代码的位置)。在一个实施例中,可使用特定类型来标记或标识跟踪器数据,以与在源代码的编程语言(例如,JavaScript)中采用的现有数据类型(例如,字符串、整数等)、对象或其他动态类型区分开。因此,在运行时期间,可识别(例如直接地从用特定类型标记的指针识别)对跟踪器数据的访问以执行操作,从而访问其相应的值。
[0048]在一个实施例中,可将跟踪器代码插入到编译代码中的触发点(例如,用于访问或存储存储器中的值的指令)。跟踪器代码可包括随机求值器以在被执行时确定是否生成跟踪器数据(例如,跟踪弹),以装箱(或承载、封装)具有值的附加代码信息(例如可得自相应源代码的概要分析阶段)的值。可在值被存储于存储器中、放入栈中或传递至函数调用等时创建跟踪器数据。在一个实施例中,随机求值器可被配置为以低概率(例如小于1%)在编译代码中偶发地生成跟踪器数据。因此,可以减小在运行时期间遇到时从跟踪器数据提取(或拆箱)相应值的开销。在某些实施例中,随机求值器可基于全局计数器,该全局计数器在计数数量超过配置数量(例如,100)时返回真,否则返回假,以引导跟踪器数据以被评估为真的低概率生成。
[0049]在某些实施例中,可生成跟踪器数据以允许实时收集运行时数据流信息,而不用对源代码(或整个程序)进行昂贵的分析。概率数据流程图可被动态地构造为表示运行时数据流信息。可将代码信息(例如值的起源)记录在跟踪器数据中,从而易于在运行时期间访问跟踪器数据时获得,而无需重复地扫描(或读取)源代码以搜索用于收集运行时数据的代码信息。
[0050]在一个实施例中,当在编译代码中创建值的跟踪器数据时,可用对跟踪器数据的引用(或指针)来更新编译代码中值的现有链接(例如,用于访问值)。对跟踪器数据的引用可包括特殊标签以允许调用特定处理程序,从而基于通过在执行编译代码时遇到的更新链接所识别的特殊标签,使值与跟踪器数据解包。此外或任选地,垃圾收集器例程可以识别分配在存储器中的跟踪器数据(例如,基于特殊标签),以在每个存储器清理会话处移除跟踪器数据,从而确保来自跟踪器数据的最小存储器使用影响。
[0051]在用跟踪器代码插桩或注入的未优化编译代码的运行时期间,可保持数据流程图以通过动态创建的跟踪器数据以出现的相对频率收集有关如何创建、消耗或使用值等的信息。例如,图中的第一节点可与被创建为整数常量的值相关联。第一节点可与按照程序中的指示创建(或存储)值的代码位置相关。可在运行时期间将跟踪器数据存储在存储器中以连同指示值起源的代码位置的信息一起来表示值。
[0052]当值在程序的目标位置被引用用于消耗时(例如,其传递到被用作算术运算或其他适用操作中的操作数的函数时),可从存储器访问跟踪器数据以解除对内嵌值的引用。值的第二节点可在图中更新以表示使用值的目标位置。该图可以包括从第一节点到第二节点的值的有向边。
[0053]在一个实施例中,数据流程图的每个节点可与和值相关的信息相关联,例如创建值时的数据类型、使用值时的数据类型(或在使用时转化的数据类型)、对应于节点的代码位置、指令在该代码位置中被执行的次数(例如,基于计数器记录)、或其他适用的信息。数据流程图中的每个边可包括值的源节点和目标节点。所述边可包括运行时期间动态更新的数(例如,基于计数器)以指示频率、权重或遇到(或跟踪)的从与源节点相关联的代码位置传递到与目标节点相关联的另一个代码位置的值的累计次数。从而,数据流程图可承载运行时执行轨迹以允许在不停止程序的情况下推断程序的值如何在运行时期间使用。
[0054]可基于在数据流程图中收集的运行时数据来优化编译代码。例如,源代码可以指定在对应于数据流程图中节点的代码位置(或代码块)处分配值的类型(例如,整数值)。优化编译器可例如基于起源于图中节点的边(例如,出边)分析数据流程图以识别该值在运行时期间的使用方式。每个边都可从作为源节点的节点被引导向目标节点。另外,所述边可以根据目标节点指示值用作特定类型(例如,字符串、双精度、整数,或其他适用的类型)的次数。
[0055]在一个实施例中,可基于数据流程图来计算被用作数据的特定类型的值的概率。来自对应于用于创建值的代码位置的源节点的有向边可提供运行时执行记录,所述记录在早期运行时作为启发法收集以估计值将如何使用。与有向边相关联的目标节点可指示值已经使用的类型。在预测要在运行时期间执行的潜在类型转换中,可对代码位置处的值的编译代码进行优化以将值预先转换为数据的推断类型,以减少类型转换操作或其他运行时资源使用。该推断类型可为被观察为最常见的,或在目标节点中具有使用该值的最高概率的特定类型。
[0056]在一个实施例中,可以动态地监测未优化编译代码的执行以确定何时在编译代码的哪些部分上执行编译器优化。例如,如果函数调用次数或循环代码执行次数已超过阈值次数(例如,66次函数调用,1000次循环或其他静态或动态配置次数),则可在运行时期间调用编译器优化以优化相应的代码。作为另外一种选择,如果运行时监测指示代码的一部分具有低使用(或执行)率,则可能不会在编译代码的该部分上执行编译器优化。低使用率可基于预定的使用阈值(例如,观察到函数仅被调用了一次)或在监测时间期间与编译代码的其他部分的相对资源使用比较。
[0057]图3为流程图,其示出了采用跟踪器数据的优化运行时编译过程的一个实施例。示例性过程300可通过处理逻辑来执行,所述处理逻辑可包括硬件(电路、专用逻辑等)、软件(例如在专用机上运行的软件)、或它们两者的组合。例如,过程300可通过图2的系统200的一些组件来执行。在框301处,根据一个实施例,在源代码的运行时编译期间,过程300的处理逻辑可将跟踪器代码插入到源代码。例如,过程300的处理逻辑可从远程设备(或本地存储器)检索源代码以动态地执行从源代码编译的可执行代码。作为另外一种选择,可通过解译器机构来执行源代码而无需编译但带来一定的性能开销。
[0058]在一个实施例中,源代码可基于动态编程语言,例如JavaScript,而无需在源代码中创建的值的数据类型的明确规范。过程300的处理逻辑可将跟踪器代码添加到引用源代码中的值的代码块,以允许选择性地跟踪源代码执行期间的值流。
[0059]在框303处,在源代码的编译代码(例如,未优化)的运行时期间,过程300的处理逻辑可根据在源代码中插入的跟踪器代码随机地且不频繁地(例如,小于1%)生成遇到的(例如,当值存储在存储器中时)值的跟踪器数据。所述值和所述值的起源(例如初始代码位置)可被封装在跟踪器数据内。
[0060]在框305处,当在源代码的运行时期间(例如,基于未优化编译代码)在目标代码位置处使用(或遇到)值时,过程300的处理逻辑可加载跟踪器数据(例如,从存储器)以从跟踪器数据访问值。所加载的跟踪器数据可指示相应值的起源。在一个实施例中,过程300的处理逻辑可根据加载的跟踪器数据更新跟踪器图以记录运行时信息。该运行时信息可包括在执行期间跟踪器数据内指示的值的起源和所使用值的目标。
[0061]在框309处,过程300的处理逻辑可优化编译代码,以减少跟踪器图中跟踪的值的起源和目标之间的处理资源。例如,过程300的处理逻辑可使用跟踪器图中跟踪的目标(或接收)代码位置中主要使用的数据类型在其初始代码位置处转换值。在一些实施例中,过程300的处理逻辑可监测未优化编译代码的运行时状态以选择性地优化代码的多个部分。例如,对应于不频繁执行函数的代码块可能不需要优化。在框311处,处理逻辑可执行优化编译代码,并且任选地执行未优化编译代码的多个部分。
[0062]图4为流程图,其示出了在运行时期间随机跟踪跟踪器图中的值以优化编译的过程的一个实施例。可通过处理逻辑执行示例性过程400,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程400可通过图2的系统200的一些组件来执行。在框401处,过程400的处理逻辑可随机地且不频繁地确定是否跟踪在源代码中指定的(例如,将基于存储或分配操作存储在存储器中的)值V。值V可与起源0(例如,行号)相关联,该起源O指示值V在源代码中的创建位置。在一个实施例中,是否跟踪值V可基于对全局计数器进行计数,以及所计数的全局计数器是否溢出一定的配置数(例如,100)来决定。如果发生了溢出并且全局计数器重置回其初始值(例如,O),则可对值V进行跟踪。
[0063]在框403处,如果确定要跟踪值V,过程400的处理逻辑可根据跟踪器数据类型(或弹跟踪器类型)分配存储器中的跟踪器数据以存储值V和起源O。例如,跟踪器类型可指定具有两个64位字的数据结构。可通过具有指示跟踪器数据(例如,可跟踪弹类型)的标签的指针来指向跟踪器数据。过程400的处理逻辑可以识别直接来自指针自身的跟踪器数据的指针。
[0064]在框405处,过程400的处理逻辑可通过目标D的指针来访问值V,该目标D位于使用(或消耗)值V的代码中。例如,目标D可指示用值V传递的函数内的代码位置。在框407处,过程400的处理逻辑可例如根据指示可跟踪弹类型的标签来确定指针是否指向跟踪器数据。
[0065]在框407处,如果指针指向跟踪器数据,则过程400的处理逻辑可以访问来自跟踪器数据的值V和起源O (例如,从存储值V的位置偏移8个字节)。在一个实施例中,通过跟踪器数据访问(或检索)值V可基于跟随代码慢速路径的代码执行。作为另外一种选择,不使用跟踪器数据(例如,通过指向存储器中的值V的指针)访问值V可基于跟随代码快速路径的代码执行;与慢速路径相比,快速路径可能需要更少的操作。
[0066]在一个实施例中,在框411处,如果跟踪器图G(例如,表不基于有向图的关系的数据结构)包括从起源O导向目标D的边E (例如,图G的独立节点),则过程400的处理逻辑可更新边E的权重(例如,加I)。图G中边的权重可表示运行时期间从起源O到目标D的值流的出现次数(或其他收集的统计值)。反之,如果图G中当前不存在边E,则过程400的处理逻辑可使用具有初始权重(例如,I)的边E来更新图G。随后在框415处,过程400的处理逻辑可从要用于位于目标D中的代码的跟踪器数据中加载值V。
[0067]图5为图形示意图,其示出了在运行时期间跟踪值的示例性跟踪器图。例如,节点511可指示已监测执行的运行时期间值0.X = a+b生成的12个观察结果(或已跟踪12个记录)。边509可包括数100,该数表示在节点511处创建的值在对应于节点505的代码位置处已使用的次数(如,基于循环代码执行)。在一个实施例中,节点505可指示代码0.x*2.1已使用在节点511和节点501处创建的值执行了 102次。边503可指示节点505消耗了在节点501处创建的2个值。节点501可指示已跟踪通过0.X = c*d创建的3个值。
[0068]在一个实施例中,节点505、节点507和节点517可包括代码信息,该代码信息分别指示用于值0.X的不同类型,例如双精度类型、整数类型和字符串类型。边509、513和515可提供收集数(或统计值),其指示在节点511处创建的值0.X已使用(例如,被跟踪时)的次数,例如双精度类型时的100次,双精度整数类型时的2次以及时间字符串类型时的一次。因此,优化编译器可更新对应于节点511的代码位置(或块)处的编译代码,以将值0.X预转换为双精度类型,使得可以避免为节点505定位的代码的双精度的潜在转换操作。_9] 使用元数据的运行时优化
[0070]在一个实施例中,可通过维护键的元数据来避免用于搜索与键相关联的对象属性的昂贵查找操作。每个键都可被表示为字符串、字符序列或数据的其他适用单元。在基于动态编程语言(例如,JavaScript)执行代码的运行时期间,可采用一类字典来存储已分配数据(例如对象)的属性。对象的属性存储器中的示例性条目可包括元属性,例如,“为只读”、“为访问器”或其他适用的属性,以及相关联的属性值,例如指示相应的属性为真还是不为真。
[0071]可执行给定字典/键对的示例性运行时计算或操作以确定字典是否包含由键引用的只读值。用表示键的键对象直接记录某些重要不变量时可不需要此类计算或搜索操作。例如,可创建与键相关的数据或对象以包含数据片,例如“只读”键元数据,从而跟踪任何现有的字典是否包含只读属性或与当前运行时状态下的键相关联(或被其索引)的值。每当在运行时期间执行此类计算时,可检查键的这些不变量。
[0072]在一些实施例中,可提供某种机制以确定依靠与键(或键特定不变量)相关联的不变量或元数据的优化代码块是否仍然有效。每当这些不变量更改时,相应的优化代码块可失效。例如,运行时编译代码(例如,通过JIT编译器)可基于不变量的有效性,其中给定键将从不引用具有“为访问器”元属性的属性。如果在运行时期间该不变量的状态改变(即,具有“为访问器”元属性的属性被添加到由给定键引用的字典),则依靠该不变量的运行时编译代码一定会失效、被删除或更换,使得其不再被使用。
[0073]用于执行基于动态语言的代码的运行时状态(例如,在某个时间点处)可包括具有键索引(或相关联)属性的对象域,例如字典、哈希表或其他适用的关联数据结构。另外,运行时状态可包括键和键特定元数据(或不变量)的集合。可例如在运行时编译的配置文件阶段期间从代码(例如,源代码)中识别键。作为另外一种选择,可在运行时期间动态地创建键(例如,通过执行key = inputO)。创建或维护键元数据以明确描述在全局范围内与当前运行时状态(例如,所有现有的对象或数据实例)相关的键的某些方面的“事实”或断言。
[0074]在一个实施例中,键元数据可指示全局断言,该全局断言可通过对相对于与元数据相关联的键的现有对象的搜索操作而被验证为真。例如,运行时状态可包括在任何当前现有对象中未使用(或包括)的特定键。键特定元数据可包括用于特定键的条目,指示该特定键当前未在任何对象中使用。对被特定键索引的属性的运行时状态(或域)的所有当前现有对象的搜索操作结果可与键特定元数据一致。可通过键特定元数据的可用性来避免此类搜索操作。
[0075]执行基于动态编程语言的代码的运行时状态的键特定元数据可指示键是否在运行时状态下被使用(被任何现有对象),在运行时状态下被键索引的属性是否具有“只读”属性,函数调用是否与键(例如静态地)相关联,和/或与键相关的其他适用的全局信息。在一个实施例中,键特定元数据可包括需要低存储器资源开销的多位数据。每个位可具有二进制值,该二进制值指示与位(与相应的键相关联)相关联的语句或断言是否相对于当前运行时状态在全局范围内为真。
[0076]基于动态语言(例如JavaScript)的程序的运行时编译代码可包括代码块以访问键特定元数据(或不变量数据),以及防止其在例如访问动态分配的属性(例如,V = ο.m)时进行潜在冗长和昂贵的查找操作。可在代码块中调用键元数据访问函数以确定对应于属性(例如,m)的键是否被使用。如果属性未被使用,则用于搜索运行时的所有现有对象(或字典)的慢速路径代码可被跳过。
[0077]可动态更新运行时状态的键元数据以与运行时的变化同步。例如,一旦(或同时)与特定键相关联的对象属性被创建(或被添加到字典),则可修改(例如,翻转位值)特定键的键元数据以反映该特定键在运行时状态下在至少一个对象中被使用。
[0078]在一个实施例中,运行时编译器可基于初始建立的键不变量(或键特定元数据)来生成源代码的优化编译代码,该初始建立的键不变量(或键特定元数据)具有与用于执行源代码的初始运行时状态一致的初始值。例如,运行时编译器可为源代码中属性“m”(例如,0.m = x)的每个访问生成优化代码,以分配属性“m” (或更新对象的动态类型)而不执行安全防护操作,以在执行时在运行时状态下搜索现有对象中的属性“m” (或相应的键)。
[0079]在运行时期间,当键不变量由于可在运行时状态期间发生的变化而被修改时,运行时编译器可动态更新优化编译代码。因此,基于键不变量的某些假设(例如,初始值)的优化编译代码的多个部分可失效,前提是此类假设不再为真。例如,如果属性“m”在运行时期间被分配到现有对象,则可以更新编译代码中属性“m”的访问的优化代码的每个块,例如,以执行独立代码路径从而用附加操作(例如,搜索或查找操作)来保证可靠性。在某些实施例中,优化编译代码可包括指示代码块被优化的指示器(例如,基于表数据结构中的标记)。
[0080]图6为流程图,其示出了使用散列键的元数据访问散列值的过程的一个实施例。可通过处理逻辑执行示例性过程600,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程600可通过图2的系统200的一些组件来执行。在框601处,过程600的处理逻辑可以检查键的键元数据,以确定是否响应于在执行代码的运行时期间访问由目标数据对象的键索引的属性而执行查找操作。
[0081]在一个实施例中,运行时状态可包括当前(例如,在运行时期间的时间点处)分配的数据对象,例如,包括目标数据对象。访问由目标数据对象的键所索引的属性可导致对由该键所索引的新属性的分配。可能需要查找(或搜索)操作以确定与目标数据对象相关的当前分配的数据对象的任何现有属性是否由键所索引。键的键元数据可包括不变量的描述,其对于在当前分配的数据对象中的键在全局范围内为真。例如,键的不变量中的一者可指示是否使用键来索引当前分配的数据中的现有属性。
[0082]在框603处,如果键的不变量或元数据满足某些条件,则过程600的处理逻辑可针对由直接位于目标数据对象上的键所索引的属性来执行访问操作,而不在当前处于运行时状态的分配的数据对象上执行查找操作。例如,条件可为这样的要求:键当前未在运行时状态下的现有数据对象的任何一者中被使用或引用。例如,如果键满足该条件,则不需要在多个数据对象中执行潜在的昂贵查找操作来定位由键所索引的属性。
[0083]在一个实施例中,属性访问操作可导致运行时状态的变化。例如,属性访问操作可导致对象使用新添加或分配的由键所索引的属性进行更新,所述属性先前未在任何现有对象中使用。在框605处,过程600的处理逻辑可更新键的键元数据,以保持键的不变量和由访问操作更新(或更改)的运行时状态之间的一致性。
[0084]图7为流程图,其示出了使用散列键的元数据动态地更新推测生成的编译代码而无需查询散列键的散列数据的过程的一个实施例。可通过处理逻辑来执行示例性过程700,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程700可通过图2的系统200的一些组件来执行。在框701处,过程700的处理逻辑可针对与从源代码概要分析的键相关联的源代码的多个部分推测生成编译代码(例如,无需执行查找操作的快速路径)。所述键可以索引存储在散列数据中的值,例如在源代码的运行时状态下表示对象或其他键相关联数据结构的字典。可使用运行时状态下的所有现有散列数据中的键的一个或多个全局属性来维护与键相关联的元数据。
[0085]在框703处,过程700的处理逻辑可响应于用键更新运行时状态的散列数据而更新键的元数据,以确保在键的元数据中描述的全局属性与包括已更新散列数据的变化的当前运行时状态一致。例如,已更新散列数据可包括由对象数据中的键索引的新属性,而键的已更新元数据可指示描述键未在任何现有对象数据中使用的全局属性不再有效。
[0086]在框705处,过程700的处理逻辑可确定推测生成的与键相关联的编译代码是否因键的已更新元数据而失效,以保证推测生成的编译代码具有可靠性,而不会在运行时状态的散列数据上引发查询操作。可基于以下假设来发射推测生成的编译代码:键元数据的某些条件为真或得到满足。如果这些条件如同在键的已更新元数据中那样不再有效,则推测生成的编译代码可能需要失效。
[0087]如果推测生成的编译代码失效,则在框707处,过程700的处理逻辑可以更新与键相关联的源代码的多个部分以重新导向来自推测生成的编译代码的执行路径。例如,与根据推测生成的编译代码来执行快速路径相反,过程700的处理逻辑可以继续执行代码的慢速路径,该代码的慢速路径包括在值的现有散列数据或由键索引的属性中的诸如查找、搜索或查询操作的操作。
[0088]图8示出了根据本文所述一个实施例的运行时的示例性键元数据。实例800可基于图2的系统200的一些组件。在一个实施例中,运行时状态217可表示执行从源代码801编译的代码的运行时。对象805、807可能已在源代码801的执行期间的某个时间点处于运行时状态217下分配,例如,当执行源代码801的代码块V = 0.W以访问指向对象805的O803的属性W时。
[0089]键元数据811可在运行时状态217下保持,描述了当前存在于运行时状态217中的所有对象中的键X、W的全局不变量或元数据。例如,键的元数据可被表示为多位(例如
2位)值,指示键是否在任何现有对象中使用以及键是否与“只读”属性相关联。位813可指示键W未在运行时状态217的任何当前现有对象中使用。位815可指示键W与“只读”属性不相关联。如果执行V = 0.W并在对象805中分配了属性W,则位813可被更新为I。
[0090]借助已破坏指针的自动类型检杳
[0091]在一个实施例中,可根据来自存储器的单次加载来优化诸如JavaScript的动态语言中的属性访问(例如“0.X”,其中O是指对象,而X是指对象的属性X)。某些操作,例如比较操作、分支操作和一个存储器加载操作,可能不需要属性访问来提高诸如内联高速缓存的运行时优化技术的性能。任选地,利用特殊处理器架构(例如流水线处理器或多处理器)执行代码的优化机会可增加(例如,通过代码路径的预测执行),同时在代码中存在较少比较操作和分支操作。
[0092]在某些实施例中,属性访问可被指定(或断言)为仅在特定(或期望)类型的对象上执行。可使用不同的期望类型来指定不同的属性访问。用于对存储器中的属性进行寻址的指针可被限制为最大允许地址数(例如,248),该最大允许地址数小于可由指针表示的可能地址数(例如,基于64位值的处理系统中的264)。可使用通过指针寻址的数据的期望类型(例如,在最高至216可能类型数之内)来指定指针中的额外空间(例如,高16位)。可将指针加载到硬件寄存器以针对由指针寻址的数据单元(例如,64位大小)自动地访问存储器。
[0093]可在访问存储器中的已寻址数据(例如,加载到硬件寄存器)之前处理断言类型的指针以确保自动类型检查。处理系统可以自动检查由指针指向的存储器地址是否满足某些条件(例如,高16位必须为零),而无需执行另外的机器指令(例如,用于比较操作、分支操作等)。如果条件未得到满足,则处理系统可以自动调用(例如,未经可执行代码指示)陷阱处理程序,该陷阱处理程序可使用预期的指令进行预注册。在一个实施例中,可使用期望的数据类型来处理断言类型的指针以获取期望类型的数据或执行陷阱处理程序;如果数据不是期望的类型,该陷阱处理程序会执行必要的补偿动作。
[0094]在一个实施例中,对象(例如,结构化数据)的属性存储器的指针可包括(或嵌入)该对象的类型标识符(例如,在高16位中)和属性存储器的存储器地址。指针可为嵌入的类型以通过嵌入类型标识符来断言已寻址数据的类型。在一个实施例中,可针对对象可具有属性的给定组合和排序动态地指派或分配类型。因此,例如,具有属性lx,y,z}(例如,通过x、y和z标识的有序属性)的每个对象可具有相同的类型,但该类型将不同于具有属性lx,y}或甚至lz,y,x}的对象的类型。类型(例如lx,y})可指定所述类型的属性存储器内的属性数据(例如y)的偏移(例如8)。
[0095]在一些实施例中,优化的内联高速缓存机制可包括通过类型嵌入指针的自动类型检查。例如,已知的类型可指定该已知类型的属性存储器内的属性数据的偏移O。要访问预期为已知类型的对象的属性数据,可仅通过两个加载操作和一个算术运算,使用对象的属性存储器的类型嵌入指针P来执行优化的内联高速缓存机制。在一个实施例中,硬件已在堆访问期间测试了指针的一部分(例如,高16位)的事实可在优化的内联高速缓存机制中加以利用。
[0096]例如,用于访问来自对象的属性存储器的属性数据的优化操作可按以下步骤执行:1)从对象加载属性存储器指针P ;2)从P中减去E*248,其中E为标识所述期望类型的标识符;以及3)从P+0加载。如果E匹配对象的类型,则将会成功访问P+0,因为从P减去E*248将导致P的高位为零。但是,如果E不匹配对象的类型,则P - E*248将得到大于248的某个值,并且访问P+0将导致硬件陷阱。可注册陷阱处理程序以将执行转移到用于属性访问的慢速路径代码,这可以修复内联高速缓存的数据或执行完整的查找。因此,可通过优化操作来优化内联高速缓存机制以访问属性数据,而不执行代码以执行昂贵的比较和分支操作(例如,以确定对象是否为匹配已知类型的类型)。
[0097]在一个实施例中,类型嵌入指针可允许对大量的动态创建数据类型(例如,最多至216种类型)同时进行检查。另外,可通过简单的算术运算(例如,通过清除高16位或减去相应的类型标识符)随时恢复类型嵌入指针的初始值(例如,存储器地址)。如果类型标识符不匹配指针中嵌入的类型,则通过地址的存储器访问可能不会成功,所述地址通过与类型标识符的减法运算从类型嵌入指针恢复。
[0098]图9为流程图,其示出了访问特定类型数据而无需比较和分支操作的过程的一个实施例。可通过处理逻辑执行示例性过程900,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程900可通过图2的系统200的一些组件来执行。在框901处,过程900的处理逻辑可为根据类型结构化的数据加载(例如,自动而不中断地)指针。例如,可以动态地创建/分配类型,指定如何为该类型的数据分配或结构化数据元。借助于地址,结构化数据在存储器中可为可寻址的。指针可包括结构化数据的地址和类型它们两者。
[0099]在框903处,过程900的处理逻辑可通过对指针的值执行的算术运算和标识已知类型的标识符来更新指针。可以更新指针以便确定通过指针(例如,通过在指针中指定的存储器地址)指向(或寻址)的数据是否为已知类型,而无需执行比较和分支操作。
[0100]在框905处,过程900的处理逻辑可以加载(例如自动地)通过已更新指针指向的数据,例如,通过保持更新指针以对数据进行寻址的硬件地址寄存器。如果用一种类型结构化的数据匹配已知类型,则数据可以成功加载(或检索)。反之,在一个实施例中,硬件陷阱处理程序可被激活。例如,如果通过指针的存储器地址指向的数据不是已知类型,则已更新的指针可能会变为无效的(或指向非法存储器地址)。在一个实施例中,当被指示加载数据(通过硬件地址寄存器)时,硬件内置逻辑可以自动检测非法存储器地址。当检测到非法存储器地址时,硬件陷阱可被发布为直接执行陷阱处理程序。
[0101]图10为流程图,其示出了用于根据已缓存类型访问对象的数据元而无需执行比较和分支操作的过程的一个实施例。可通过处理逻辑执行示例性过程1000,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程1000可通过图2的系统200的一些组件来执行。在框1001处,例如,过程1000的处理逻辑可以存储第一类型标识符和存储器地址以表示通过第一类型标识符标识的第一类型的对象数据。对象数据可在存储器中的存储器地址处进行分配。
[0102]在框1003处,过程1000的处理逻辑可将偏移和第二类型标识符进行缓存,该第二类型标识符标识用数据元进行结构化的对象数据的第二类型,该数据元以所述偏移位于数据的第二类型内。数据元可对应于为数据的第二类型动态分配的属性。在一个实施例中,过程1000的处理逻辑可能已在先前通过第二类型的数据中的偏移执行了对数据元的访问操作。
[0103]在框1005处,过程1000的处理逻辑可配置指针以基于已缓存的偏移来访问第一类型的对象数据的特定数据元,而无需执行比较和分支操作。已配置的指针可将地址值作为对象数据、已缓存的偏移、标识第一类型的第一类型标识符和标识数据的第二类型的已缓存的类型标识符的存储器地址的算术组合。
[0104]在框1007处,在一个实施例中,过程1000的处理逻辑可执行加载操作以访问来自已配置指针的对象数据的特定数据元。如果标识数据对象的第一类型的第一类型标识符匹配已缓存的第二类型标识符,则可成功加载特定数据元。作为另外一种选择,如果第一类型标识符和第二类型标识符不匹配,则加载操作可激活硬件陷阱处理程序。
[0105]图11示出了根据本文所述实施例表示对象的类型嵌入指针的一个例子。实例1100可包括指向对象单元1103以表示对象的对象指针O 1101。对象单元1103可包括配置(例如,通过低48位)有对象属性存储1107的地址的类型嵌入指针1105,该对象属性存储被分配用于存储对象O的属性。另外,可使用标识类型数据1109的标识符来标记(例如,通过高16位)类型嵌入指针1105。在一些实施例中,可动态地创建类型数据1109以指定通过类型标识符标识的数据结构。
[0106]在一个实施例中,已知类型1111可为标识数据的已缓存类型或现有类型的类型标识符(例如,在运行时期间)。可通过例如能够表示数据的216个不同类型的64位字的低16位(例如,在基于64位的机器中)来表示类型标识符。已配置指针1113可用于访问对象O的属性存储器1107以及验证嵌入在对象O的类型嵌入指针中的类型标识符是否匹配已知类型1111。例如,可通过类型嵌入指针1101和已知类型1113上的算术运算而得到已配置指针1113。基于硬件的机制可基于例如高16位是否为值O、NULL或其他预定的值等来自动检查已配置指针1113的有效性。如果已知类型1111不匹配类型数据1109的标识符,则可能在已配置指针1113中配置了无效地址。
[0107]图12为框图,其示出了用于访问特定类型数据而无需比较和分支操作的系统的一个实施例。例如,系统1200可包括图2的系统200的一些组件。在一个实施例中,系统1200可包括类型化数据处理程序模块1201,其用于访问通过操作环境201托管的运行时215中的类型化数据。在检查已知类型的类型化数据是否利用了基于硬件的机制时,类型嵌入指针处理程序模块1205可以配置指针以访问类型化数据,而无需执行另外的代码(例如,比较和分支代码)。
[0108]在一个实施例中,属性访问高速缓存1207可以提供访问对象的已缓存的(或期望的)类型标识符和/或已缓存的(或期望的)地址偏移。可使用属性访问高速缓存1207基于类型嵌入指针处理程序模块1205来执行数据访问(或检索)操作,而无需额外的加载和/或比较操作成本,从而确定类型和/或存储器地址偏移以访问目标对象属性。在一个实施例中,可注册硬件陷阱处理程序模块1203以在下列情况下激活或执行:在例如使用指针(其使用属性访问高速缓存1207中的期望类型进行配置)访问的目标数据不同于期望类型时出现硬件陷阱。
[0109]非确定性编译代码的选择性随机化
[0110]运行时编译器(例如JIT编译器)可以选择性地和随机地引入非确定性元素,以生成源代码(例如,远程获取的JavaScript代码)的不可预测的编译代码,从而防止嵌入在源代码内的非可信代码的潜在执行。由运行时编译器在通用源代码上的单独编译可导致不同的不可预测的编译代码,而不具有彼此之间的可预测性。可配置运行时编译器以改变所需的保护度(或随机性)和不可预测的编译代码中所引发的开销的量。例如,可基于非确定性决策随机地在编译代码的不同部分处选择性地应用非确定性元素。从而,可以减少运行时编译器中代码生成器的可能确定性行为。
[0111]在一个实施例中,运行时编译器可以启发式地以随机方式(例如,随机散发方式)改变常规编译代码的机器指令以生成不可预测的编译代码。可以动态地应用启发式评估,以非确定性地决定是否在源代码的常规编译代码的不同部分处引入不可预测性。在一个实施例中,在编译源代码时,启发式评估可基于源代码的静态或动态测量或分析而将可信度的量分配到代码块。
[0112]例如,从源代码编译的每个代码单元(例如,值、常量等)可被指定为可信或非可信。可动态地维护可信代码的总大小(例如,字节数)和非可信代码的总大小,以提供在编译期间某个时间点处遇到的可信代码和非可信代码之间的比率的启发式测度。任选地或另夕卜,启发式测度可包括已被发射(例如,被生成为不可预测的编译代码的一部分)的函数块代码(或函数)的数量、函数块代码的大小,或其他适用的测度。通常,函数块代码的大小越大,函数块代码可被信任的可能性就越低。相似地,源代码包括的函数越多,可认为其可信度越低。
[0113]在一个实施例中,可以结合代码(例如,编译代码的块)可信度的启发式测度,来确定是否对作为不可预测的编译代码的一部分的代码执行随机化操作。所述确定可基于随机函数的结果。随机函数的行为可导致不太可能以与基于启发式测度估算的信任度的量成比例地执行随机化操作。随机函数可在不可预测的编译代码中提供非确定性属性或不可预测性。例如,根据随机函数,要随机化的常规编译代码的多个部分可为不可预测的。
[0114]在一些实施例中,可在JIT编译期间对已按给定指令流发射的一定比例的非可信字节进行跟踪。所述比例可用作加权因子以决定是否应用随机化操作以保护所生成的代码。该决定可基于一组可根据环境易受到这些攻击的程度而随环境变化的启发法和随机过程的输出作出。任何选择在代码的哪些部分应用随机化操作(或硬化点)的确定性因素可能会被阻止。
[0115]示例性随机化操作可包括NOP(空操作)填充操作、随机指令选择,常量盲化操作、或其他适用的代码随机化操作。可执行(例如,通过运行时编译器的代码生成器)Ν0Ρ填充操作以随机地生成除更改指令之间的间隔外对执行无影响的指令。随机指令选择操作可利用以下事实:多个指令可以不同的方式进行编码,或被具有相同结果(例如,减去正常量相对于加上负常量)的其他指令取代。可执行常量盲化操作以用通过可逆操作生成的另一个常量来替换某个常量(例如,被攻击者使用),然后执行代码以进行逆向转换。
[0116]运行时编译器中的选择性随机化可有效地阻止攻击者尝试执行嵌入在源代码中的非可信代码(例如,JIT Spray攻击),同时限制引发的资源开销(例如,在所需的代码大小、总运行时和/或存储器空间中引发的资源开销)。虽然选择性随机化可对代码的某些子集(例如,代码的某些常量而不是所有常量)应用随机化操作(例如,常量盲化操作),但在已发射编译代码中引入的随机性和不可预测性可以防止实际的攻击,例如JIT Spray攻击或其他攻击。例如,不能迫使代码生成器生成按照攻击者期望那样被处理器解译的指令。
[0117]图13为流程图,其示出了以非确定性方式选择性地随机化来自源代码的编译代码的过程的一个实施例。可通过处理逻辑执行示例性过程1300,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程1300可通过图2的系统200的一些组件来执行。在框1301处,过程1300的处理逻辑可动态地确定启发式指示器,该启发式指示器指示用于生成源代码的编译代码的源代码可信度的可能性。启发式指示器可指示代码的一部分(例如,在代码中创建的值)是否可信、可信代码的量、非可信代码的量、可信代码与非可信代码之间的相对大小、代码函数块的总大小、启发式环境设置、或其他适用的启发式估算。
[0118]在框1303处,过程1300的处理逻辑可根据启发式指示器非确定性地选择编译代码的多个部分。过程1300的处理逻辑可使编译代码的所选择部分随机化,以将不可预测性引入到随机化编译代码,而不会在未随机化的编译代码的未选择部分中引发执行成本。源代码的随机化编译代码可能无法通过源代码的独立编译代码预测。在框1305处,过程1300的处理逻辑可以执行从源代码编译的随机化编译代码,而不会执行嵌入在源代码内的潜在非可信代码。
[0119]图14为流程图,其示出了用于从源代码的编译代码流以非确定性随机方式发射可执行代码的过程的一个实施例。可通过处理逻辑执行示例性过程1400,该处理逻辑可包括硬件、软件或它们两者的组合。例如,过程1400可通过图2的系统200的一些组件来执行。在框1401处,在一个实施例中,过程1400的处理逻辑可以动态地跟踪已发射代码流中的非可信代码与可信代码的比例(例如,以将下一代码发射到代码流),以便生成可执行代码。过程1400的处理逻辑可在运行时期间将源代码(例如,JavaScript代码)编译成可执行代码。
[0120]在框1403处,过程1400的处理逻辑可以确定准备用于发射的下一代码是否可信。例如,下一代码可为紧接编译代码中已发射代码流的代码块(例如,指令)。下一代码可能不可信,例如,具有从不可信源代码(接收或检索自未验证的源)创建或指定的值或常量。作为另外一种选择,由编译器创建或控制的值(例如编程语言的内置常量)可以被信任。
[0121]如果在框1405处下一代码不可信,则过程1400的处理逻辑可以随机地确定是否例如基于被动态跟踪的非可信代码与可信代码的比例来更改下一代码。过程1400的处理逻辑可以选择性地执行随机化操作以随机化或更改下一代码,从而允许对已发射代码流中的随机化量进行非确定性调整,以便提高随机化编译代码的执行性能。例如,非可信代码的比例越高,可随机化下一代码的可能性就越大。
[0122]在框1407处,如果选择下一代码进行随机化,则过程1400的处理逻辑可对下一代码执行一个或多个随机化操作以隐藏嵌入在下一代码中的潜在非可信可执行指令。随机化操作可为常量盲化操作、NOP填充操作、指令随机化操作,或用于下一代码的其他合适操作。在框1409处,过程1400的处理逻辑可以将随机化代码发射到用于执行的代码流。
[0123]图15A-15B示出了根据本文所述某些实施例的采用分散随机化操作的即时编译的例子。现在转到图15A,代码块(或指令)1501可包括非可信恒定值I。可选择性地应用随机化操作(例如常量盲化操作)以使用任意数57382将代码块1501随机化或更改为代码块1503,从而执行与块1501相同的函数。通过代码块1501中的非可信值I嵌入的潜在隐藏可执行指令可被防止在代码块1503中执行。
[0124]实例1500B描述了用于选择性地随机化编译代码以按成本有效方式引入可预测性的示例性操作。在1505处,基于当前在编译代码流中遇到的非可信值的总数(或字节数)以及可信值的总数,针对非可信内容与可信内容的比例来计算启发式测度。在1507处,执行随机选择以确定是否应用随机操作来随机化要发射的代码(或硬化某个值)。在一个实施例中,由于非可信内容的比例变高,因此随机化代码的可能性可增大。通过在1507处包含随机数,选择操作、进而已发射的编译代码可变得不确定或不可预测。
[0125]在一些实施例中,可以估算非可信代码的比例以指示非可信代码大小与当前遇到的代码(可信代码和非可信代码两者)的总大小的比率。1507处的函数randomNumber可返回介于O和I之间的随机值。在一个实施例中,如果所指示的比率大于所返回的随机值,则当前非可信代码可被硬化(或随机化)。因此,非可信代码的比例越高,可硬化当前非可信代码以用于发射的可能性就越大。
[0126]在一个实施例中,函数发射(例如,在1509处)可将字节一直传输到指令流而无需修改。1511处的函数emitHardenedValue可以执行一个或多个随机化操作以硬化正被发射的值。所应用的随机化操作可以不被攻击者所预测。1513处的函数decayUntrustedByteCount可以应用衰减因子来调节(例如,动态地减少)所遇到的非可信值的总数(例如,untrustedBytes)。
[0127]实例1500B可包括可配置的参数或函数,所述可配置的参数或函数基于启发式地确定的环境设置(例如,基于源代码的接收位置、主机操作系统的版本、用户输入或其他适用的设置),以调节例如攻击者防护效果与代码执行效率。例如,可应用1513处的衰减因子以防止惩罚所有大的代码段,因为由攻击者植入的潜在隐藏非可信代码可能已在发射硬化值之前被破坏。在不应用衰减因子(例如,decayUntrustedByteCount)的情况下,实例1500B中的操作可能最终进入编译代码的几乎所有值均被硬化的状态。相似地,非可信值的总数的快速衰减可能会导致对于要发起成功攻击的攻击者而言足够大的非硬化值流。从而,行1513处的decayUntrustedByteCount可应用已被确定适用于目标环境的衰减因子,例如通过 1507 处环境设置的 EnviornmentSafetyHeuristic。
[0128]图16示出了诸如计算机系统的数据处理系统的一个例子,该数据处理系统可与本发明的一个实施例一起使用。例如,图2的系统2可被实现为图16所示系统的一部分。需注意,虽然图16示出了计算机系统的各种组件,它并不旨在表示使这些组件互连的任何特定构造或方式,因此这些细节与本发明并无密切关系。还应理解,具有较少组件或可能较多组件的网络计算机以及其他数据处理系统也可用于本发明。
[0129]如图16所示,数据处理系统形式的计算机系统1600包括耦接到一个或多个微处理器1605、R0M(只读存储器)1607、易失性RAM 1609和非易失性存储器1611的总线1603。微处理器1605可从存储器1607、1609、1611检索指令并执行所述指令以执行上述操作。总线1603与这些各种组件互连在一起,并且将这些组件1605、1607、1609和1611互连至显示控制器和显示设备1613,以及互连至诸如输入/输出(I/O)设备的外围设备,该输入/输出(I/O)设备可以是鼠标、键盘、调制解调器、网络接口、打印机和本领域熟知的其他设备。通常,输入/输出设备1615通过输入/输出控制器1617耦接到系统。易失性RAM(随机存取存储器)1609通常被实现为动态RAM(DRAM),其需要连续供电以刷新或维持存储器中的数据。
[0130]大容量存储器1611通常为磁性硬盘驱动器或磁性光驱或光驱或DVDRAM或闪存存储器或者即使在系统断电后也保持数据(例如,大量数据)的其他类型的存储器系统。通常,大容量存储器1611也可以是随机存取存储器,虽然这并非必需。虽然图16显示,大容量存储器1611是直接耦接到数据处理系统中的其余组件的本地设备,但应当理解,本发明可利用远离系统的非易失性存储器,例如网络存储设备,其通过例如调制解调器或以太网接口或无线网络接口等网络接口耦接到数据处理系统。总线1603可包括一条或多条总线,其通过本领域熟知的各种桥接器、控制器和/或适配器相互连接。
[0131]上述内容的多个部分可使用诸如专用逻辑电路的逻辑电路实现,或使用微控制器或执行程序代码指令的处理核心的其他形式实现。从而,可使用诸如机器可执行指令的程序代码来执行上述讨论所教导的过程,所述机器可执行指令使机器执行这些指令以执行某些函数。在该上下文中,“机器”可为将中间形式(或“抽象”)指令转换为处理器专用指令(例如,诸如“虚拟机”(例如,Java虚拟机)、解译器、公共语言运行时、高级语言虚拟机等的抽象执行环境)的机器,和/或设置在半导体芯片(例如,使用晶体管实现的“逻辑电路”)上的电子电路,其设计用于执行诸如通用处理器和/或专用处理器的指令。上述讨论所教导的过程也可以通过(作为机器的替代或与机器结合)电子电路执行,该电子电路设计用于执行过程(或其一部分)而不执行程序代码。
[0132]制造的制品可用于存储程序代码。存储程序代码的制造的制品可体现为但不限于一个或多个存储器(例如,一个或多个闪存存储器、随机存取存储器(静态、动态或其他))、光盘、CD-ROM、DVD ROM、EPROM、EEPR0M、磁卡或光卡,或适用于存储电子指令的其他类型的机器可读介质。也可借助于包含在传播介质(例如,通过通信链路(例如网络连接))中的数据信号,将程序代码从远程计算机(例如,服务器)下载到请求计算机(例如,客户端)。
[0133]已按照对计算机存储器中的数据位进行操作的算法和符号表示来呈现前面的详细描述。这些算法描述和表示是数据处理领域技术人员所用的工具,而这些工具也能最有效地将其工作实质传达给该领域其他技术人员。算法在本文中并且通常被认为是引导至所需结果的自相一致的操作序列。操作是需要实际操控物理量的那些操作。通常,尽管不是必须的,这些量采用能够被存储、传输、组合、比较、和换句话讲操纵的电信号或磁信号的形式。已被证明的是,其在主要出于通用原因而将这些信号指代为位、值、元素、符号、字符、项、数字等时是方便的。
[0134]然而,应当牢记的是,所有这些以及类似的术语都与适当的物理量相关联,并且只是应用于这些量的方便标签。除非另外特别说明,否则从上述讨论中显而易见的是,可以理解,在整个说明书中,使用例如诸如“处理”或“运算”或“计算”或“确定”或“显示”等术语的讨论是指计算机系统或类似的电子计算设备的操作和流程,其可对计算机系统寄存器和存储器中表示为物理(电子)量的数据进行操作并将其转换成在计算机系统存储器或寄存器或其他此类信息存储、传输或显示设备中相似地显示为物理量的其他数据。
[0135]本发明还涉及一种用于执行本文所述操作的装置。该装置可专门构造用于所需的目的,或者可以包括由存储在计算机中的计算机程序选择性地激活或重新配置的通用计算机。此类计算机程序可存储在计算机可读存储介质中,例如但不限于任何类型的盘,包括软盘、光盘、CD-ROM和磁光盘,只读存储器(ROM)、RAM、EPROM、EEPR0M、磁卡或光卡、或适用于存储电子指令的任何类型的介质,并且每个均耦接到计算机系统总线。
[0136]本文中所呈现的过程和显示并不固有地与任何特定计算机或其他装置相关。根据本文的教导内容,各种通用系统可以与程序一起使用,或者可以证明其便于构造用于执行所述操作的更专用的装置。根据下文的描述,用于各种这些系统的所需结构将是显而易见的。此外,本发明未参照任何特定的编程语言进行描述。应当理解,多种编程语言可用于实现如本文所述的本发明的教导内容。
[0137]前面的讨论仅描述了本发明的一些示例性实施例。本领域的技术人员将易于从这些讨论、附图和权利要求书中认识到,可在不脱离本发明的实质和范围的情况下进行各种修改。
【权利要求】
1.一种其内具有指令的机器可读非暂态存储介质,所述指令在被机器执行时使得所述机器执行一种方法,所述方法包括: 在编译代码的运行时期间在遇到值时,根据跟踪器代码随机地且不频繁地生成跟踪器数据,所述编译代码编译自插入有所述跟踪器代码的源代码,所述跟踪器数据指示所述源代码中的所述值的起源; 在所述运行时期间在所述源代码中的所述值的目标处加载所述值的所述跟踪器数据;以及 优化所述编译代码以根据运行时信息减少所述值的所述起源和所述目标之间的处理资源,所述运行时信息包括所述值的所述起源和所述目标。
2.根据权利要求1所述的介质,其中所述跟踪器代码在所述源代码的运行时编译期间插入所述源代码中。
3.根据权利要求1所述的介质,其中所述跟踪器代码包括求值器,并且其中所述生成包括: 根据所述求值器确定是否在遇到所述值时生成所述跟踪器数据,其中所述求值器配置有用于以随机且不频繁方式生成所述跟踪器数据的所述确定的概率。
4.根据权利要求3所述的介质,其中所述求值器对全局计数器进行计数,其中所述求值器返回真以基于所 述全局计数器和根据所述求值器的所述配置的值的比较来生成所述跟踪器数据。
5.根据权利要求1所述的介质,其中针对所述值中的一个生成所述跟踪器数据中的一个,并且其中所述一个跟踪器数据包括所述一个值和所述一个值的代码信息,所述代码信息从所述源代码的配置文件记录。
6.根据权利要求5所述的介质,其中所述源的所述配置文件指定所述源代码中的所述值的起源。
7.根据权利要求5所述的介质,其中所述编译代码包括到所述一个值的链接,并且其中所述跟踪数据的生成包括: 利用对所述跟踪器数据的引用来更新所述链接,所述一个值能够通过所述引用从所述跟踪器数据访问。
8.根据权利要求7所述的介质,其中所述编译代码包括所述跟踪器数据的处理程序,并且其中所述引用允许调用所述处理程序以使所述一个值从所述一个跟踪器数据解包。
9.根据权利要求1所述的介质,其中所述运行时信息包括数据流记录,还包括: 保持所述数据流记录,所述数据流记录指示所述运行时期间的所述值的轨迹,所述轨迹包括所述值的所述起源和所述目标,其中所述数据流记录包括所述轨迹的出现统计值。
10.根据权利要求9所述的介质,其中所述轨迹的出现统计值包括所述起源已被执行的次数。
11.根据权利要求9所述的介质,其中所述数据流记录包括流程图,其中所述流程图的每个节点与所述源代码的代码位置相关联,其中所述流程图的每个边从所述流程图的源节点被导向到所述流程图的目标节点,所述源节点与所述源代码的所述起源中的一个相关联,所述目标节点与所述源代码的所述目标中的一个相关联,其中所述边指示在所述运行时期间在所述一个起源处创建和在所述一个目标处引用的所述值中的至少一个。
12.根据权利要求11所述的介质,其中所述边与所述统计值中的一个相关联,所述统计值指示所述至少一个值的出现次数,所述至少一个值与所述一个源位置和所述一个目标位置相关联。
13.根据权利要求9所述的介质,其中所述加载包括: 用所述轨迹更新所述数据流记录,其中基于所述跟踪器数据来更新所述轨迹的所述值的起源。
14.根据权利要求13所述的介质,其中所述跟踪器数据中的一个包括所述值中的一个,所述一个值在所述目标的一个中引用,所述一个跟踪器数据包括所述一个值的所述起源中的一个,所述更新包括: 确定对应于所述一个起源和所述一个目标的所述轨迹中的一个是否存在于所述数据流记录中;以及 如果所述一个轨迹尚未存在于所述数据流记录中,则用所述一个轨迹更新所述数据流记录。
15.根据权利要求14所述的介质,还包括: 如果所述一个轨迹已存在于所述数据流记录中,则更新所述一个轨迹的出现统计值。
16.根据权利要求15所述的介质,其中所述一个轨迹的出现统计值包括指示在所述一个起源处累计执行次数的所述一个起源的统计值。
17.根据权利要求9所述的介质,其中所述目标是所述值的相关联目标类型,并且其中所述编译代码的所述优化包括: 基于所述出现统计值,分析所述运行时记录以获得将在所述起源中的一个处创建的值作为所述目标类型中的一个进行引用的可能性。
18.根据权利要求17所述的介质,其中所述分析启发式地指示所述目标类型中的特定一个,所述目标类型中的特定一个在所述目标类型中具有最大一种可能性。
19.根据权利要求18所述的介质,其中所述值与所述一个起源处的源类型相关联,还包括: 根据所述优化编译代码中的所述启发法,将所述值的所述源类型预转换为所述值的所述特定目标类型,其中所述处理资源包括在所述优化编译代码的未来运行时期间从所述源类型到所述特定目标类型的类型转换。
20.根据权利要求1所述的介质,还包括: 监测在所述运行时期间所述编译代码的执行;以及 确定何时为所述源代码的一部分执行所述编译代码的所述优化。
21.根据权利要求20所述的介质,其中所述监测包括: 对所述源代码的所述部分已被执行的次数进行计数,并且其中如果所述次数超过阈值,则执行所述编译代码的所述优化。
22.—种其内具有指令的机器可读非暂态存储介质,所述指令在被机器执行时使得所述机器执行一种方法,所述方法包括: 执行从源代码编译的编译代码; 随机地且不频繁地分配存储器内的跟踪器数据以存储在所述源代码的起源中指定的所述值,所述跟踪器数据包括所述值和指示所述值的所述源代码中的起源的代码信息;通过用于访问所述源代码的目标处的所述值的指针,从所述跟踪器数据加载所述代码信息; 使用从所述源代码的所述起源到所述目标跟踪所述值的出现率来更新数据流记录;以及 在所述执行的运行时期间基于所述数据流记录动态地优化所述编译代码。
23.根据权利要求23所述的介质,还包括: 随机地确定是否在所述运行时期间跟踪所述值,其中如果确定要跟踪所述值,则分配所述跟踪器数据,并且其中所述跟踪器数据为跟踪器类型;以及 确定用于访问所述源代码的目标处的所述值的指针是否指向所述跟踪器类型的数据,其中如果确定所述指针指向所述跟踪器类型的数据,则从所述跟踪器数据加载所述代码信息。
24.根据权利要求24所述的介质,其中所述指针包括标识标签,并且其中所述标识标签指示所述指针是否指向所述跟踪器类型的数据。
25.—种计算机实现的方法,包括: 在编译代码的运行时期间在遇到值时,根据跟踪器代码随机地且不频繁地生成跟踪器数据,所述编译代码编译自插入有所述跟踪器代码的源代码,所述跟踪器数据指示所述源代码中的所述值的起源; 在所述运行时期间在所述源代码的所述值的目标处加载所述值的所述跟踪器数据;以及 优化所述编译代码以根据运行时信息减少所述值的所述起源和所述目标之间的处理资源,所述运行时信息包括所述值的所述起源和所述目标。
26.一种计算机系统,包括: 存储可执行指令的存储器,所述可执行指令包括编译自源代码的编译代码; 动态地获取所述源代码的接口 ;以及 耦接到所述存储器和所述接口以执行来自所述存储器的所述指令的处理器,所述处理器被配置为: 在所述编译代码的运行时期间在遇到值时,根据跟踪器代码随机地且不频繁地生成跟踪器数据,所述源代码插入有所述跟踪器代码,所述跟踪器数据指示所述源代码中的所述值的起源, 在所述运行时期间在所述源代码中的所述值的目标处加载所述值的所述跟踪器数据,以及 优化所述编译代码以根据运行时信息减少所述值的所述起源和所述目标之间的处理资源,所述运行时信息包括所述值的所述起源和所述目标。
【文档编号】G06F9/45GK104081361SQ201380007188
【公开日】2014年10月1日 申请日期:2013年1月31日 优先权日:2012年2月3日
【发明者】F·J·皮茨罗, G·巴瑞克罗 申请人:苹果公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1