用于调试本机代码的方法和系统与流程

文档序号:17148704发布日期:2019-03-19 23:13阅读:396来源:国知局
用于调试本机代码的方法和系统与流程

本发明涉及计算机技术,更具体地,涉及用于调试本机代码的方法和系统。



背景技术:

编译器能通过将源代码编译成可被特定处理器执行的代码来产生可执行代码。这种类型的因处理器而异的代码被称为“本机代码”,即能被特定类型的处理器执行但不能被任意类型的处理器执行的机器指令。另一类型的编译器可接收源代码并产生不是因处理器而异的中间代码或虚拟机字节代码。中间代码通常由中间语言编译器(例如,即时(JIT)编译器)接收,并就在程序执行之前被编译为本机代码。中间代码不是因平台而异的。

解释器读取源代码或中间代码并逐语句地来执行代码而无需将代码转换成本机代码。典型地,对代码进行解释慢于执行本机代码。对代码进行解释通常慢于将中间代码JIT编译为本机代码并执行本机代码。

对经解释的代码的调试器的实现通常没有对本机代码的调试器的实现那么复杂。然而,对于本机代码的调试器的响应时间通常快于对经解释的代码的调试器的响应时间。调试器通常通过以下向用户提供控制程序的执行的能力:步入或步出函数、步跃函数、暂停和恢复执行、检查变量的当前值或栈位置等。



技术实现要素:

如本文中描述的双模式调试器可调试表示程序的本机代码。响应于在被调试的程序中检测到定义的调试跳出(bailout)条件,调试器可停止调试表示程序的本机代码并且可转变为调试表示程序的对应的经解释的代码。在本机模式中,调试器可调试表示程序的本机代码。提供对程序变量的当前值和/或栈信息的检查和/或修改的调试操作可在本机模式中执行。在本机模式调试中,每当变量被保存到寄存器内(例如,当变量在程序中被定义时),该值也可被保存到函数的栈位置。被调试的函数的变量可被存储在栈中的为被调试的程序保留的特定本地化区域中。栈的该同一区域可在编译为本机代码期间被使用以供溢出(即,当存在比计算设备所具有的寄存器更多的活动变量时,变量可从寄存器“溢出”到存储器)。栈位置可被调试器使用来获得和改变变量的值。

响应于检测到跳出条件,对表示程序的本机代码的调试可停止。解释器可接收表示程序的经解释的代码,该接收到的经解释的代码对应于被调试的本机代码,并且解释器可恢复对该程序的、在经解释的模式中运行的经解释的代码的调试。例如,控制被调试的程序的执行的调试操作可在经解释的模式中运行。执行控制操作可通过异步中断、步进、中断点和/或在异常操作上的中断来实现。解释器模式调试可被用于调试最顶层的函数(其变量值位于栈的最顶层帧中的函数),同时使用本机模式来调试程序的其它部分。

调试器可在经定义的跳出点从在本机模式中调试转变为在经解释的模式中调试。与调试器相关联的跳出引擎可接收跳出记录,该跳出记录包括在调试器下执行的本机代码的当前状态。跳出引擎可实例化解释器的实例,创建解释器的该实例的解释器栈帧并可用来自跳出记录的值来填充为解释器的该实例创建的解释器栈帧。对程序的调试可在该程序的类似的对应的经解释的代码上恢复。调试跳出点是程序中的在其处本机模式调试可转变为经解释的模式调试的位置,如果某些跳出条件被满足的话。可定义针对程序的调试跳出点,诸如在函数的开始处、循环的回边(back edge)处、当函数返回时、当对助手函数或库的调用返回时或当遇到调试器语句时。当在调试会话中遇到调试跳出点时,运行时调试标志的状态以及栈帧的栈深度校验可被用于确定是否满足调试跳出条件。如果满足调试跳出条件,则与在调试器下执行的本机代码相对应的代码可被发送到解释器并且调试可在对应的经解释的代码上继续。

提供本概述以便以简化形式介绍将在以下详细描述中进一步描述的一些概念。本概述并不旨在标识所要求保护主题的关键特征或必要特征,也不旨在用于限制所要求保护主题的范围。

附图说明

在附图中:

图1a示出了包括呈现来自接收到的文档的页的浏览器应用的系统100的示例;

图1b示出根据在此所述的主题的各方面的包括可从执行经编译的代码变换到解释代码的运行时引擎的系统200的示例;

图1c示出根据在此所述的主题的各方面的包括可从执行经编译的代码变换到解释代码的运行时引擎的系统300的示例;

图1d示出根据本文中公开的主题的各方面的系统400的示例,该系统可通过从本机模式变换到经解释的模式来调试代码;

图2示出根据在此所述的主题的各方面的从调试本机代码转变到调试经解释的代码的方法250的示例;

图3是根据此处所公开主题的各方面的计算环境的示例的框图;以及

图4是根据此处所公开的主题的各方面的集成开发环境(IDE)的示例的框图。

具体实施方式

概览

可通过将程序编译为本机代码并调试该本机代码来调试该程序。在该程序中经定义的点处,调试可从本机模式转变到经解释的模式,并且调试可在经解释的代码上继续。涉及执行控制的调试操作:暂停执行、继续执行、步入、步出或步跃代码片段等,可在经解释的模式中发生。涉及对变量的检查和修改的调试操作可在本机模式中发生。双模式调试器可将本机模式调试的速度与经解释的模式调试的简单性组合在一起。

通过从在本机模式中执行转变为在解释器模式中执行来调试本机代码

图1a示出根据在此所述的主题的一些方面的web浏览环境100的示例。如在图1a中所示,环境100可以包括下述一个或多个:计算设备102、服务器104、网络106以及浏览器应用108。Web浏览环境100可以包括本领域中已知的其它组件。

计算设备102可以是任何类型的固定或移动计算设备,包括桌面计算机(例如,个人计算机等)、移动计算机或计算设备(例如,设备、RIM设备、个人数字助理(PDA)、膝上型计算机、笔记本计算机、平板计算机(例如,Apple(苹果)iPadTM)、上网本等等)、移动电话(例如,蜂窝电话、智能电话,诸如Apple iPhone、Google(谷歌)Android(安卓)TM手机、Microsoft(微软)手机等)或其它类型的移动设备。服务器104可在包括一个或多个服务器的一个或多个计算机系统中实现,其可以是在此描述的任何类型的计算设备或能够实现在此描述的相应功能的以其它方式知晓的计算设备。

计算设备102和服务器104可通过网络106来通信地耦合。网络106可包括一个或多个通信链路和/或通信网络,诸如PAN(个域网)、LAN(局域网)、WAN(广域网)、或网络的组合,诸如因特网。可使用各种链路来将计算设备102和服务器104通信地耦合到网络106,该各种链路包括有线和/或无线链路,如IEEE 802.11无线局域网(WLAN)无线链路、全球微波互联接入(Wi-MAX)链路、蜂窝网络链路、无线个人区域网络(PAN)链路(例如,BluetoothTM链路)、以太网链路、USB链路等等。

浏览器应用108可以是可在计算设备102上执行的程序。浏览器应用108可使得网络信息资源能被检索、呈现和遍历。可使用网络地址(诸如统一资源标识符(URI))来通过浏览器应用108检索信息资源或对象。信息资源的示例包括网页、图像、视频,以及其它形式的内容。出现在信息资源中的超链接使得用户能够容易地将他们的浏览器导航到相关的资源。浏览器应用108的示例包括但不限于由华盛顿州雷蒙德市的微软公司开发的Internet由加利福尼亚州芒廷维市的Mozilla公司开发的Mozilla由加利福尼亚州库珀蒂诺市的Apple公司开发的以及由加利福尼亚州芒廷维市的Chrome。

浏览器应用108可以通过网络106从服务器104检索文档112。文档112可以是包括标记语言的代码的web文档,标记语言诸如超文本标记语言(HTML)、动态HTML(DHTML)、可扩展HTML(XHTML)、可扩展标记语言(XML)等。文档112可以包括DOM(文档对象模型)对象114和一个或多个脚本116。DOM对象114可以包括根据DOM规范在文档112中所表示的一个或多个对象,该DOM规范是用于表示对象并与对象进行交互的跨平台且独立于语言的规范。DOM对象114可包括被直接包括在文档112中的对象、和/或由文档112引用的并分开地从服务器104或其它服务器检索的对象。脚本116包括根据动态语言(例如,JavaScript、VBScript、AJAX、Python、Perl等)来格式化的代码,该格式化的代码使得能够对DOM对象114做出改变,包括基于诸如用户输入、环境情况(例如,一天中的时间或其它变量)等因素的改变。脚本116的代码可在进行中访问和修改DOM对象114的对象,而无需返回到服务器104。

浏览器应用108可以接收(例如加载)文档112。浏览器应用108可包括浏览器引擎(例如,布局引擎或呈现引擎),该浏览器引擎格式化文档112的信息并显示经格式化的信息。例如,如图1a显示的,浏览器应用108可基于由计算设备102的显示器110显示的文档112来生成页面118。浏览器应用108可被配置成执行一个或多个脚本116,该一个或多个脚本116被嵌入在文档112中或与文档112分开但与文档112相关联。

图1b示出根据在此所述的主题的一些方面的系统200的框图。系统200可包括一个或多个计算机或计算设备,例如包括诸如处理器143等之类的一个或多个处理器、存储器145、执行控制器309、解释器311、诸如JIT(即时)编译器313之类的编译器、存储315、机器代码执行器317和跳出引擎337的计算设备102。执行控制器309、解释器311、诸如JIT编译器313的编译器、存储315、机器代码执行器317和跳出引擎337可被实现为一个或多个程序模块,当所述程序模块被加载到存储器145中时使得所述一个或多个处理器143等分别执行归因于执行控制器309、解释器311、诸如JIT编译器313的编译器、机器代码执行器317和跳出引擎337的动作。系统200可包括本领域已知的、未被显示的其它组件。

执行控制器309、解释器311和/或JIT编译器313可以接收从源代码生成的字节代码。源代码可以是以编程语言编写的任意源代码,例如但不局限于动态脚本语言(诸如但不限于JavaScript、VBScript、Python等等)。可以解析源代码并从经解析的源代码中生成字节代码。基于字节码325和简档、试探法或其它信息,执行控制器309可启用解释器311和JIT编译器313之一来对字节代码325进行操作。解释器311可被配置成当由从执行控制器309接收到的解释器控制信号启用时解释字节代码325。JIT编译器313可被配置成当由从执行控制器309接收到的编译器控制信号启用时编译字节代码325。

当解释器311由解释器控制信号启用时,解释器311可以解释并执行字节代码325。解释器311可以被实现为JavaScript解释器、VBScript解释器、Python解释器或用于在本文其它地方提到的或以其它方式所知的另一动态语言或动态脚本语言的解释器。通过该方式,源代码可至少部分地由解释器311的操作来执行。类似地,响应于接收到启用编译器控制信号,JIT编译器313可以编译字节代码325。JIT编译器313可被实现为JavaScript编译器、VBScript编译器、Python编译器或用于在本文其它地方提到的或以其它方式所知的另一动态语言或动态脚本语言的编译器。JIT编译器313被称为“即时”编译器,这是因为由于需要经编译的字节代码(即,要被立即执行的),特定的字节代码部分可由JIT编译器313编译,而非在执行之前预先编译完整的字节代码325。JIT编译器313可以生成具有机器可执行代码或指令形式的经编译的字节代码333。

JIT编译器313可以基于如上所述的假设执行代码优化。JIT编译器313可以在它生成的经编译的字节代码中插入一个或多个预先确定的跳出点。对于每个跳出点,诸如跳出表格303等之类的跳出表格可以被创建,在其中,可以记录变量的位置、在字节代码325中或在源代码中与跳出点位置相对应的位置以及其它信息。跳出表格303等可以描述在栈上或寄存器中哪里可以找到变量。JIT编译器313可以生成一个或多个跳出表格并可以将它们与经优化的经编译的字节代码(例如作为机器代码)一起保存。可以通过编码跳出表格中的信息来避免对变量的生存期的非必要的延长来优化跳出表格。例如,如果已知变量x的值在跳出时间是常量10,则x=10可以被编码在跳出表格中,这样,值10就不需要在存储器或寄存器中被复活。类似地,当超过一个变量在跳出点处具有相同的值(例如x=y)时,如果该信息被编码在跳出表格中(例如跳出表格中的相同位置可以被用于x和y),则对于具有相同值的所有变量来说,该相同的位置可被用在跳出表格中。这些技术可以使得寄存器分配更加有效。经优化的经编译的字节代码可以作为用于在由系统200进行的后续执行程序期间访问的经编译的字节代码333来存储在存储315中。

当执行经优化的经编译的字节代码时,可由机器代码执行器317(它可以是诸如处理器143等的一个或多个处理器)接收经优化的经编译的字节代码333。执行经编译的字节代码可以与栈335上的编译器帧341相关联。在每个跳出点处可以确定所述优化所基于的底层的一种或多种假设是有效还是无效的。响应于确定所述假设是有效的,经优化的经编译的代码可以继续执行。响应于确定所述假设是无效的,经优化的经编译的代码的执行可以被停止。可以将该跳出点的跳出表格传递给跳出引擎337。跳出引擎337可以还原解释器所需的变量的状态(例如值)。跳出引擎可以为栈335创建新的帧(例如解释器帧339)。如果解释器所需的变量已变成非活动的,则跳出引擎337可以通过将变量的状态从非活动改变到活动来复活该变量。跳出引擎337可以实例化解释器311的一个实例,向解释器传递在字节代码中与在经优化的经编译的代码中的跳出点相对应的位置以及包括所有被还原的活动变量的值的新创建的解释器帧。因此这样,从其生成字节代码325的源代码可以由JIT编译器313和机器代码执行器317的操作来部分执行并由解释器311来部分执行。

图1c示出根据在此所述的主题的各方面的系统300的另一示例。系统300可以包括诸如计算设备102的计算设备,该计算设备包括诸如处理器142等的一个或多个处理器、存储器144以及包括下述一个或多个项的运行时引擎:引擎接口302、解析器304、字节代码生成器306、执行控制器308、解释器310、诸如但不限于JIT(即时)编译器312之类的编译器、存储314、机器代码执行器316、跳出引擎336以及脚本库318。系统300可包括本领域已知的、未被显示的其它组件。

如在图1c中所示的,引擎接口302可接收脚本源代码208。引擎接口302可以是在场的或不在场的。解析器304可以被配置作为到运行时引擎的接口,而不是使得引擎接口302在场。当在场时,引擎接口302可以是提供用于将主机与图1c的运行时引擎对接的一个或多个方法的通信接口。根据在此所述的主题的一些方面,可以根据由华盛顿州雷蒙德市的微软公司所开发的IActiveScript来实现引擎接口302。引擎接口302可以为解析器304提供源代码208。

解析器304可以接收并解析源代码208。解析器304可对源代码208执行令牌生成或词法分析,使得源代码208被格式化成符号或令牌。解析器304可对令牌执行差错校验以确定是否形成可允许的表达式、句法差错不存在等。解析器304可以将经解析的源代码作为经解析的源代码(未示出)输出。经解析的源代码可具有任何合适的形式,包括由解析器304生成为AST(抽象句法树)代码,如本领域的技术人员知晓的,该AST代码包括源代码208的抽象句法结构的树表示。

字节代码生成器306可以接收经解析的源代码。字节代码生成器306可被配置成将经解析的源代码转换成字节代码,其包括被配置成用于解释器的高效执行以及用于进一步编译成机器代码的指令集。所生成的字节代码可以将经解析的源代码表示为数字代码和相应的可选参数。字节代码生成器306可以输出经生成的字节代码(未示出)。字节代码可具有任何合适的形式,包括由字节代码生成器306生成的如本领域的技术人员知晓的p-代码(便携式代码)形式。

执行控制器308、解释器310和JIT编译器312每个都可以接收所生成的字节代码。解释器310或机器代码执行器316可包括简档生成器204。简档生成器204可被配置成分析所生成的字节代码来收集有关源代码208的统计数据以及进一步的信息。简档生成器204可生成简档信息320,其可包括所收集的信息并可被存储在存储314中。

执行控制器308可以访问简档信息320,并且可以被通信地耦合到解释器310和JIT编译器312。基于所生成的字节代码和简档信息320,执行控制器308可启用解释器310和JIT编译器312之一来对所生成的字节代码进行操作。解释器310可被配置成当由从执行控制器308接收到的解释器控制信号启用时解释所生成的字节代码。JIT编译器312可被配置成,当由从执行控制器308接收到的编译器控制信号启用时编译所生成的字节代码。例如,在源代码208的第一次执行期间,简档信息320可能还不存在。在这种情况下,执行控制器308可启用解释器310来解释所生成的字节代码并生成简档信息320。在源代码208后续的执行期间(例如,在源代码208的相同的第一次执行期间的稍后,和/或在源代码208的后续的执行期间),根据简档信息320,执行控制器308可启用解释器310来解释源代码208的各部分,并可启用JIT编译器312来编译源代码208的其它各部分。

当由解释器控制信号启用解释器310时,解释器310可以解释并执行所生成的字节代码。解释器310可被实现为JavaScript解释器、VBScript解释器、Python解释器或用于在此其它地方提到的或以其它方式所知的另一动态语言的解释器。通过该方式,源代码208可至少部分地由解释器310的操作来执行。

当JIT编译器312由编译器控制信号启用时,JIT编译器312可编译所生成的字节代码。JIT编译器312可被实现为JavaScript编译器、VBScript编译器、Python编译器或用于在此其它地方提到的或以其它方式所知的另一动态语言的编译器。JIT编译器312被称为“即时”编译器,这是因为由于需要经编译的字节代码(即,要被立即执行的),特定的字节代码部分可由JIT编译器312编译,而非在执行之前预先编译完整的字节代码。JIT编译器312可以生成具有机器可执行代码或指令形式的经编译的字节代码332。

JIT编译器312可以基于如上所述的假设执行代码优化。JIT编译器312可以在它生成的经编译的字节代码中插入一个或多个预先确定的跳出点。对于每个跳出点,诸如跳出表格303等之类的跳出表格可以被创建,在其中,可以记录变量的状态、在所生成的字节代码中与跳出点的位置相对应的位置。跳出表格可以描述在栈上或机器代码的寄存器中哪里可以找到变量。JIT编译器312可以生成表格并将它们与经优化的经编译的字节代码332(例如机器代码)一起保存。经优化的经编译的字节代码332可以作为用于在由系统300进行后续执行程序期间访问的经编译的字节代码332来存储在存储314中。

当执行经优化的经编译的字节代码时,可由机器代码执行器316(它可以是诸如处理器142等的一个或多个处理器)接收经优化的经经编译的字节代码332。在每个跳出点处可以检查所述优化所基于的底层的一种或多种假设是有效还是无效的。响应于确定所述假设是有效的,经优化的经编译的字节代码332可以继续执行。响应于确定所述假设是无效的,经优化的经编译的代码的执行可以被停止。可以将该跳出点的跳出表格传递给跳出引擎336。跳出引擎336可以还原解释器所需的变量的状态(例如值)。如果解释器所需的变量已变成非活动的,则跳出引擎336可以通过将变量的状态从非活动改变到活动来复活该变量。跳出引擎336可以实例化解释器310的实例,向解释器传递在字节代码中与在经优化的经编译的代码中的跳出点相对应的位置、变量和它们的位置。因此这样,从其生成字节代码的源代码可以由JIT编译器312和机器代码执行器316的操作来部分执行并由解释器310来部分执行。

跳出的使用可以允许多次优化。在许多动态编程语言中的变量可以是日期、字符串、数组、整数等等。在一些动态语言中,为变量创建对象,并且存储在寄存器中并随后存储在表格中的位置包括指向该对象的指针。对象自身可以存储对象的描述和对象的数据。这样,如果变量a是字符串,可以为该字符串创建对象,指向该对象的指针可以被存储,且对象自身可以标识变量a为字符串并可以指定该字符串自身(例如“你好世界”(“Hello World”))。一种用于在当基于简档数据假设变量为整数的情况下的方案的优化是将整数自身存储在变量中以取代指向为该整数创建的对象的指针或表示并描述该整数对象的经编码的值。一种直接对整数对象进行编码的方案是使用单词的位之一来存储标记该值为整数指示符。这样,在32位处理器的情况下,32位的一个位可以指示其它31位的内容表示整数值或可指示其它31位的内容不表示整数值。

图1d示出根据本文中公开的主题的各方面的系统400的示例,该系统可通过从在本机模式中执行变换到在经解释的模式中执行来调试本机代码。系统400的全部或部分可以驻留在诸如下面参考图3所描述的计算机之类的一个或多个计算机或计算设备上。系统400可包括如图1b和/或图1c中示出的本文中描述的调试器等被添加到其的系统。系统400或其部分可作为独立系统或作为插件或附件提供。系统400可全部或部分在软件开发计算机(诸如参考图4描述的软件开发计算机)上执行。系统400的全部或部分可由程序开发工具来操作。例如,系统400的全部或部分可在诸如关于图4被更完整地描述的IDE等集成开发环境(IDE)内执行或可以是另一IDE。系统400可整体上或部分地在IDE之外执行。系统400可在浏览器内执行或与浏览器相关联,浏览器诸如举例来说,Microsoft InternetMozilla’s Firefox或任何现在已知或将来开发的浏览器。可以理解,系统400不被限制为在浏览器内操作或与浏览器相关联。

系统400或其部分可包括从某一服务(如云中)获得的信息或可在云计算环境中操作。云计算环境可以是其中计算服务不被拥有但被按需提供的环境。例如,信息可驻留在联网云中的多个设备上,和/或数据可被存储在云内的多个设备上。

系统400可以包括诸如处理器142等的一个或多个处理器、存储器144以及包括下述一个或多个项:语言编译器404、JIT编译器408、跳出引擎414、调试器416、解释器418和/或可显示调试信息的调试器显示420。语言编译器404、JIT编译器408、跳出引擎414、调试器416和解释器418可被实现为一个或多个程序模块,当该一个或多个程序模块被加载到存储器144内时致使一个或多个处理器142等分别执行归因于语言编译器404、JIT编译器408、跳出引擎414、调试器416和/或解释器418的动作。系统400可包括本领域已知的、未被显示的其它组件。

如图1d中显示的,系统400可包括诸如语言编译器404之类的语言编译器。语言编译器404可以是接收用特定编程语言编写的源代码并从其生成中间语言(诸如中间语言(IL)406)的编译器。源代码的各部分或全部可被语言编译器404处理来创建中间语言代码,诸如IL 406。语言编译器404可接收源代码(诸如源代码402)或其部分。源代码402可用任意编程语言来编写。源代码402或其各部分可通过将源代码402发送到解释器418来解释。由此,源代码402的各部分可被编译。源代码402的各部分可被解释。程序部分是被编译还是被解释可基于性能试探法:如果特定程序部分在本机模式中运行地更快,则其可被编译为本机模式,如果特定程序部分在经解释的模式中运行地更快,则它可被解释。

如图1d中显示的,系统400可包括诸如JIT编译器408之类的JIT编译器。JIT编译器408可接收中间语言(诸如IL 406)并可从其生成本机代码(诸如本机代码410)。本机代码410可被加载到进程(诸如进程412)中以供执行。JIT编译器408可被实现为JavaScript编译器、VBScript编译器、Python编译器或用于在此其它地方提到的或以其它方式所知的另一动态语言或动态脚本语言的编译器。JIT编译器408被称为“即时”编译器,这是因为特定的程序部分可在需要(即,要被立即执行的)经编译的本机代码时由JIT编译器408编译,而非在执行之前预先编译完整的本机代码。JIT编译器408可以生成具有机器可执行代码或指令形式的经编译的本机代码。

JIT编译器408可以基于如上所述的假设执行代码优化。JIT编译器408可以在它生成的经编译的代码中插入一个或多个定义的调试跳出点。调试跳出点是程序中的在其处本机模式调试可转变为经解释的模式调试的位置,如果某些调试跳出条件被满足的话。可定义针对程序的调试跳出点,诸如在函数的开始处、循环的回边(back edge)处、当函数返回时、当对助手函数或库的调用返回时或当遇到调试器语句时。当调试跳出发生时,本机代码的执行可停止。在本机模式中执行的程序的当前状态可被捕捉在调试跳出记录中,该调试跳出记录可记录当前执行点、源代码402中对应于调试跳出点位置的位置、变量值以及变量值位于寄存器中的何处和/或变量值位于栈中的何处。针对该调试跳出点的调试跳出记录可被传递到跳出引擎。

如图1d中显示的,系统400可包括诸如跳出引擎414之类的跳出引擎。跳出引擎412可接收一个或多个调试跳出记录。跳出引擎414可以还原解释器所需的变量的状态(例如值)。跳出引擎414可创建栈的新帧。如果解释器所需的变量已变成非活动的,则跳出引擎414可以通过将非活动变量的状态从非活动改变到活动来复活该变量。跳出引擎414可以实例化解释器418的一个实例,向解释器传递在源代码中与本机代码中的调试跳出点相对应的位置以及包括所有被还原的活动变量的值的新创建的解释器帧。如果调试跳出位置位于代码片段(诸如函数)内,则在其处调试在经解释的模式中恢复的点可以在该代码片段的开始处(例如,调式可在函数的开始处而非在在其处遇到调试跳出点的点处恢复)。

当调试跳出被触发时,对本机代码的调试可停止。本机代码的执行可停止。状态可被捕捉在调试跳出记录中,该调试跳出记录记录当前执行点、变量值以及变量值位于何处。变量值可被存储在CPU寄存器中或可被存储在本机栈上。可以将针对该跳出点的调试跳出记录传递给跳出引擎414。跳出引擎414可以在为解释器创建的栈上还原解释器所需的变量的状态(例如值)。跳出引擎414可创建针对该栈的新的解释器帧。如果解释器所需的变量已变成非活动的,则跳出引擎414可以通过将变量的状态从非活动改变到活动来复活该变量。跳出引擎414可以实例化解释器418的一个实例,向解释器传递在源代码中与本机代码中的调试跳出点相对应的位置以及包括所有被还原的活动变量的值的新创建的解释器帧。

如图1d中显示的,诸如调试器416之类的调试器可接收本机代码以供调试。如本文中描述的调试器可在本机模式中运行,意味着调试器可对本机代码执行调试操作。根据本文中描述的主题的一些方面的调试器可提供程序变量的当前值和栈信息以供显示在调试器显示上。包括对变量的检查、表达式求值以及对值的修改在内的调试操作可使用调用栈中的本机帧。每当变量被保存到寄存器内(例如,当变量在程序中被定义时),值也可被保存到函数的栈位置。为了保持对特定局部变量的值的位置的跟踪,根据本文中描述的主题的各方面,每次局部变量被定义时(即,值被赋予局部变量),它可被写入到栈位置。用于某一函数的局部变量的栈位置可被分组在一起,使得存在其中某一函数的局部变量可被找到的一个栈区域。由此,特定函数的任一局部变量的当前值总是在对应的栈位置中,即使本机代码正在使用用于该变量的寄存器。栈的该同一区域可被用于溢出(即,当存在比计算设备所具有的寄存器更多的活动变量时,变量可从寄存器“溢出”到存储器)。栈位置可被调试器使用来获得和改变变量的值。为了支持对调试器中的各值的修改,指示符可被定位在毗邻栈中局部变量被存储在其中的区域。指示符可以是在被设置时指示被调试的函数中的局部变量被用户改变的标志。被调试的函数可以是最顶层栈帧上的函数或者是在之下栈帧中的函数。例如,假设遇到中断点。用户可改变属于与不是当前栈帧的栈帧相关联的函数的局部变量的值,同时在本机模式中执行该函数。指示函数中的局部变量已经被改变的标志将被设置在与其局部变量被用户改变的函数相关联的栈帧中。

函数元数据包括关于多少局部变量被用在函数中的信息。根据本文中描述的主题的一些方面,为了获得局部变量的值,调试器可通过读取驻留在离栈中的开始位置达等于局部变量的标识符的偏移处的栈位置中的值来确定局部变量的值。为了改变局部变量的值,调试器可将新值写入对应的栈位置中并可设置经改变的局部变量标志(位于紧邻局部变量可被存储在其中的区域的栈上)来指示函数中的局部变量已经被改变。

当执行返回到在本机模式中运行的函数时,跳出引擎可校验经改变的局部变量标志。在局部变量值针对对应于执行所返回的函数的栈帧被改变的情况下,标志将被设置,并且到经解释的模式的跳出将被触发。在跳出期间,局部变量的值可从栈位置中(而非从寄存器中)还原,并且在经解释的模式中运行的调试器将接收经修改的局部变量被改变到其的值。

调试器可在程序中调用了调试跳出点的经定义的点处从在本机模式中执行转变到在经解释的模式中执行。调试跳出点包括但不限于以下:在函数的开始处、在循环的回边(back edge)处(例如,在计数器被递增并且计数器已经被检查出超出范围之后)、当从对函数的调用返回时、当从对库的调用返回时、当从对助手函数的调用返回时、当遇到调试器语言语句时等等。本文中描述的调试器可在经解释的模式中运行。在经解释的模式中,调试器可调试经解释的代码。例如,控制被调试的程序的执行的调试操作可在经解释的模式中运行。执行控制操作可通过异步中断、步进、中断点和/或在异常操作上的中断来实现。

异步中断可例如当用户在调试会话中暂停执行(例如,通过激活在调试器用户界面中的暂停选项)时发生。暂停可在任意时间发生。调试器预期在用户动作之后的合理时间内来中断程序的执行。可通过在代码中的各位置处插入检查来提供对用户动作的及时响应,各位置包括但不限于:在函数的开始处、在循环中等。作为响应,调试器可设置转变标志,该转变标志被设置时,迫使从本机模式调试转变到经解释的模式调试。对于进程中的每个线程可提供一个转变标志。当执行本机代码进入函数或去往循环的开始时,转变标志可被检查。如果转变标志被设置,则调试跳出可被触发并且执行可从本机模式调试转变到经解释的模式调试。类似于该函数的源代码可被检索并被发送到解释器。调试器可检测异步中断并可清除转变标志。异步中断可通过中断(停止)执行并在调试器显示上显示当前程序状态来完成。

步进操作可以是用户引导的动作,其步入函数、步出函数或步跃函数或指令。在每个步进调试操作的开始处,调试器可设置步进类型标志和步进帧基础标志。步进帧基础标志可被设置为当前函数栈帧基础。步进帧标志可被用于检查栈深度以检测递归。根据本文中公开的主题的一些方面,当执行离开在帧的顶部的与步进操作在栈上开始时相同的函数时,到解释器模式的转移没有完成。例如,考虑当前位置在函数A处并且用户旨在步出将返回到函数B(函数A的调用者)。如果函数A调用另一函数(其可以是函数A或函数B),则在当步进开始时函数A的原始栈帧依然在栈上时,当控制返回到函数A或函数B或另一函数时,调试跳出不被触发。

对于步出操作,调试器可将步进类型标志设置为步出。程序执行可恢复。当执行从当前函数返回到在本机模式中执行的另一函数内时,跳出引擎可确定步进类型标志和步进帧标志是否被设置。如果是,则当前栈帧基础可与存储在步进帧标志中的值进行比较。如果当前栈帧基础大于存储在步进帧标志中的值,假设栈朝更少的地址生长,则栈深度被减少。响应于栈深度的减少,到解释器模式的跳出可被触发。调试器可转变为调试经解释的代码。执行可停止并且当前程序状态可被显示在调试器显示上。

当本机代码进入在本机模式中执行的另一函数时或如果作出对函数的最后语句的导致从该函数返回的步进操作,则对这些标志的跳出检查发生,并且到解释器模式调试的跳出被触发。调试器在经解释的模式中操作并可在调试器显示上显示当前程序状态。

对于步跃调试操作,用于步跃的函数不被迫使在解释器模式中运行并通常在本机模式中运行。跳出可仅在步进操作在当前函数的最后语句上并导致从该函数返回时被触发。响应于栈深度的减少,到解释器模式调试的跳出被触发。调试器可在调试器显示上显示当前程序状态。

当用户在函数中设置中断点时,调试器可通过递增跟踪函数中的中断点的数量的计数器来更新函数元数据。当函数被执行时(函数开始执行或函数调用另一函数并且被调用的函数返回到作出调用的函数),检查触发调试跳出的条件。如果针对当前函数的中断点计数大于0,则调试跳出可被触发并且调试器可转变到在经解释的模式中执行。调试器可在中断点在其处被设置的语句处停止并且可在调试器显示上显示当前执行点。

如果遇到在异常之后的异常/继续上的中断点,则在调试器下运行的程序可将异常事件传递到调试器并可从导致了异常的语句之后的下一语句继续执行或可将执行设置为在特定语句处恢复并从该语句继续。为了通知调试器,本机代码可使用“抛出助手”函数,使得所有抛出通过其来路由。调试器可在抛出了异常的语句处停止并可在调试器显示上显示变量的值。

为了继续到下一语句,(在在异常被抛出时程序在本机模式中运行的情况下),编译器可标识程序中异常可发生的所有地方。当作出对助手函数的调用时或当作出对库函数的调用时,异常可通过显式的抛出语句来抛出。例如,从某一对象中删除属性的JavaScript删除语句可在该对象为空或未被定义的情况下抛出异常。由于为空或未被定义的对象不具有任何属性,异常被抛出。在此,“助手”指在语言中(例如,在JavaScript引擎中)实现的(通常在本机代码中)并被用于执行某个操作或语言构造诸如以从某一对象中删除属性的函数。“库函数”指实现库例程的函数。例如,JavaScript具有多个库对象,诸如“string(串)”。“string”对象具有多个操作,例如包括string.concat。string.concat不是纯粹的语言例程。在一些语言中,在库函数和助手函数之间进行区分可能不是合理的,但是在一些语言(诸如但不限于JavaScript)中,它们在以下方面不同:库调用在技术上与脚本(即,用户)函数调用相同并由此可被截取。例如,用户可将脚本函数分派到string.concat。下一次string.concat被调用时,引擎将调用被重新分派的用户函数而非原始的string.concat函数。助手函数不能被截取并通常在本机/经编译的代码中被直接调用。

为了在异常在本机代码中发生之后继续,每个助手调用和每个库调用可被包装在try-catch(尝试-捕获)语句块中。在尝试-捕获块的“尝试(try)”部分中,助手函数可被调用。由原始助手函数返回的值可被保存到局部变量中。在尝试-捕捉块的“捕捉(catch)”部分中,如果“在异常后继续”选项在经解释的模式调试器中被启用,则异常并继续标志可被设置。在尝试-捕捉块的“捕捉”部分之后,原始助手的值可被返回。可在从对助手函数调用的每个调用的每个返回之后或在从对库的调用的每个返回之后,插入对在异常后继续的调试跳出检查。调试跳出检查可检查异常并继续标志并可在该标志被设置的情况下触发到解释器模式的调试跳出。调试器可转变到解释器模式,使得执行控制能够在调试器内继续。例如,如果对“在异常上中断”的用户响应是步跃指令,则调试器将步进到下一语句。如果对“异常上中断”的用户响应是继续,则调试器将在经解释的模式中继续对函数的剩余部分的执行。

调试器可在调试器显示设备(诸如调试器显示420)上显示调试信息。调试器可在调试器显示上显示来自调用栈、局部变量值等的信息。

图2示出根据在此所述的主题的各方面的可从本机模式调试转变到经解释的模式调试的方法250。图2中所述的方法可由诸如但不限于参考图1d中所述的一个系统的系统来实践。尽管方法250描述了顺序执行的一系列操作,但要理解,方法250不受该顺序的次序的限制。例如,一些操作可以与所描述的不同的次序发生。另外,一个操作可以与另一操作并发发生。在一些实例中,不是所有的所描述操作都被执行。

在操作中,诸如图1d中描述的系统的系统可如下操作。在操作251,可针对某一程序定义调试跳出点。调试跳出点是该程序中的在其中从本机模式调试到经解释的模式调试的转变可发生的点。调试跳出点包括但不限于以下:在函数的开始处、在循环的回边(back edge)处(例如,在计数器被递增并且计数器已经被检查出超出范围之后)、当从对函数的调用返回时、当从对库的调用返回时、当从对助手函数的调用返回时、当遇到调试器语言语句时,等等。当该程序被编译时,可在调试跳出点处插入调试处理。

在操作252,调试会话可被发起。当调试会话被发起时,可丢弃先前为调试器所附加到的在进程中运行的程序所生成的任意本机代码。在操作254,可从调试器所附加到的程序中生成调试模式本机代码。调试模式本机代码可包括与从调试本机代码到调试经解释的代码的转变相关联的处理。调试模式本机代码可被加载到进程中。当函数在调试模式中被编译为本机代码时,在该函数中的每个跳出点处,一个或多个跳出条件检查可被插入到本机代码中。跳出条件检查可在生成该程序的内部本机表示的编译阶段期间被插入。跳出条件检查可随着跳出记录的数据被捕捉而被插入到代码中。跳出条件检查可涉及检查被调试器控制的各个标志或指示符的状态(设置或未设置)或值。

调试跳出指示符或标志可包括但不限于:在被设置时指示调试器从本机模式转变到经解释的模式的指示符、在被设置时指示函数具有在其中的中断点的指示符、指定用于检测递归的栈地址的指示符、指示要被执行的一种类型的步进操作的指示符、在被设置时指示调试器正在执行的步进操作的类型(步入、步出、步跃)的指示符、在栈上的在被设置时指示字段在当前栈帧中被改变的指示符以及在被设置时被用于注入显式无条件跳出的指示符。

在操作256,可在调试模式中执行本机代码。当执行到达调试跳出点时,可检查各跳出条件。针对某一种类型的调试跳出场景检查的跳出条件可不同于针对其它类型的跳出检查的跳出条件。例如,假设用户在函数的开始处或在循环的回边处(在针对该循环的计数器被递增并且计数器被检查出在范围内时)暂停在调试器下运行的程序的执行。调试器可设置标志,该标志在被插入在函数的开始处或在循环的回边处的本机代码检查来查看迫使本机代码跳出到解释器模式的标志是否被设置时迫使本机代码跳出到解释器模式。转而假设用户选择调试器UI中的步入到某一函数中的选项。调试器可设置指示什么类型的步进操作被请求的步进标志。响应于确定步进标志的值被设置为“步入”,由本机代码执行的检查可跳出。假设用户动作将中断点放置在函数中的某个地方。调试器可递增跟踪函数中的中断点的数量的标志。如果当前函数中的中断点计数大于0,则跳出被触发,并且执行进入到经解释的模式中。

当执行到达具有中断点的帧时,在本机代码中程序的执行停止,跳出引擎接收调试跳出记录,函数被发送到解释器并且从函数的开始继续对经解释的函数的调试。在操作260,响应于确定至少一个跳出条件在操作258已经被满足,本机模式中的调试可停止并且调试可转变到经解释的模式。从调试本机代码到调试对应的经解释的代码的转变可由用户发起的动作来触发或可在遇到显式无条件跳出时被触发。

在操作262,可从跳出记录中还原解释器变量。如果任一跳出条件被满足,则变量的执行状态(位置)和值、临时变量的位置和值以及栈值的快照可被作出并被持久保存在调试跳出记录中。调试跳出记录可被发送到跳出引擎。跳出引擎可实例化解释器的实例并可设置针对解释器的解释器栈帧。在操作264,调试可在经解释的模式中恢复。在操作266,如果在操作258没有检测到跳出条件,则在本机模式中的调试可继续。

合适的计算环境的示例

为了提供有关本文所公开主题的各方面的上下文,图3以及以下讨论旨在提供其中可以实现本文所公开主题的各实施例的合适计算环境510的简要概括描述。尽管本文所公开的主题是在诸如程序模块等由一个或多个计算机或其他计算设备执行的计算机可执行指令的通用上下文中描述的,但本领域技术人员将认识到,本文所公开的主题的各部分还能够结合其他程序模块和/或硬件和软件的组合来实现。通常,程序模块包括执行特定任务或实现特定数据类型的例程、程序、对象、物理人为产物、数据结构等。通常,程序模块的功能可在各个实施例中按需进行组合或分布。计算环境510只是合适的操作环境的一个示例,并且不旨在对此处所公开的主题的使用范围或功能提出任何限制。

参考图3,描述了计算机512形式的计算设备。计算机512可包括至少一个处理单元514、系统存储器516和系统总线518。至少一个处理单元514可执行被存储在诸如但不限于系统存储器516之类的存储器中的指令。处理单元514可以是各种可用处理器中的任何一种。例如,处理单元514可以是图形处理单元(GPU)。这些指令可以是用于实现被描述为由上述一个或多个组件或模块所执行的功能的指令或用于实现上述方法中的一个或多个的指令。也可以使用双微处理器及其他多处理器体系结构作为处理单元514。计算机512可被用于支持在显示屏上呈现图形的系统中。在另一示例中,计算设备的至少一部分可以用在包括图形处理单元的系统中。系统存储器516可包括易失性存储器520和非易失性存储器522。非易失性存储器522可以包括只读存储器(ROM)、可编程ROM(PROM)、电可编程ROM(EPROM)或者闪存。易失性存储器520可包括可充当外高速缓冲存储器的随机存取存储器(RAM)。系统总线518将包括系统存储器516的系统物理人为产物耦合到处理单元514。系统总线518可以是几种类型的总线结构中的任何一种,包括存储器总线、存储控制器、外围总线、外总线或局部总线,并且可以使用各种可用总线体系结构中的任一种。计算机512可包括处理单元514可通过系统总线518访问的数据存储。数据存储可包括用于图形呈现的可执行指令、3D模型、素材、材质等。

计算机512通常包括各种计算机可读介质,诸如易失性和非易失性介质、可移动和不可移动介质。计算机可读介质可以通过用于存储诸如计算机可读指令、数据结构、程序模块或其它数据等信息的任何方法或技术来实现。计算机可读介质包括计算机可读存储介质(也称为计算机存储介质)以及通信介质。计算机存储介质包括物理(有形)介质,诸如但不限于可存储所希望的数据以及可由计算机512访问的RAM、ROM、EEPROM、闪存或其他存储器技术、CDROM、数字多功能盘(DVD)或其他光盘存储、磁盒、磁带、磁盘存储或其他磁存储设备。通信介质包括诸如但不限于通信信号、调制载波或可被用于传递所希望的信息以及可由计算机512访问的任何其他无形介质之类的介质。

将理解,图3描述了可充当用户与计算机资源之间的媒介的软件。该软件可以包括可存储在盘存储524上的操作系统528,该操作系统可分配计算机512的资源。盘存储524可以是通过诸如接口526等不可移动存储器接口连接到系统总线518的硬盘驱动器。系统应用530利用由操作系统528通过存储在系统存储器516或者存储在磁盘存储524上的程序模块532和程序数据534对资源的管理。可以理解,计算机可用各种操作系统或操作系统的组合来实现。

用户可通过输入设备536向计算机512输入命令或信息。输入设备536包括但不限于定点设备,诸如鼠标、跟踪球、指示笔、触摸垫、键盘、话筒、语音识别和姿势识别系统等。这些及其他输入设备通过系统总线518经由接口端口538连接到处理单元514。接口端口538可表示串行端口、并行端口、通用串行总线(USB)等。输出设备540可与输入设备使用相同类型的端口。提供输出适配器542以举例说明存在像监视器、扬声器、以及打印机的需要特定适配器的一些输出设备540。输出适配器542包括但不限于在输出设备540和系统总线518之间提供连接的视频和音频卡。其他设备和/或系统和/或设备,诸如远程计算机544,可提供输入和输出两种能力。

计算机512可以使用到诸如远程计算机544之类的一个或多个远程计算机的逻辑连接来在联网环境中操作。远程计算机544可以是个人计算机、服务器、路由器、网络PC、对等设备或其他常见的网络节点,并且通常包括许多或所有以上相对于计算机512所描述的元件,但在图3中仅示出了存储器存储设备546。远程计算机544可经由通信连接550逻辑地连接。网络接口548涵盖诸如局域网(LAN)和广域网(WAN)这样的通信网络,但也可包括其他网络。通信连接550是指用来将网络接口548连接到总线518的硬件/软件。通信连接550可以在计算机512内或外并且包括诸如调制解调器(电话、电缆、DSL和无线)和ISDN适配器、以太网卡等内和外技术。

可以理解,所示网络连接仅是示例,并且可以使用在计算机之间建立通信链路的其他手段。本领域的普通技术人员可以理解,计算机512或其他客户机设备可作为计算机网络的一部分来部署。在这一点上,本文所公开的主题涉及具有任意数量的存储器或存储单元以及在任意数量的存储单元或卷上发生的任意数量的应用和进程的任何计算机系统。本文所公开的主题的各方面可应用于具有部署在网络环境中的具有远程或本地存储的服务器计算机和客户计算机的环境。本文所公开的主题的各方面也可应用于具有编程语言功能、解释和执行能力的独立计算设备。

图4示出集成开发环境(IDE)600和通用语言运行时环境602。IDE 600可允许用户(例如,开发者、程序员、设计者、编码者等)在计算机系统中设计、编码、编译、测试、运行、编辑、调试或构建程序、程序集、网站、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可提供使用微软.NETTM框架的托管代码开发环境。可使用语言专用源编译器620使用建模工具652和模型存储653从源代码组件610和本机代码组件611创建中间语言组件650,并且使用中间语言编译器660(例如,即时(JIT)编译器)从中间语言组件650创建本机代码组件611(例如,机器可执行指令)。即,当中间语言(IL)应用被执行时,其在被执行的同时被编译成适合正在其上执行它的平台的合适机器语言,藉此使代码能跨若干平台移植。替代地,在其他实施例中,程序可被编译成适合其目标平台的本机代码机器语言(未示出)。

用户可根据已知软件编程技术以及与特定源语言相关联的特定逻辑和句法规则经由IDE 600中的用户接口640和源代码编辑器651来创建和/或编辑源代码组件。此后,源代码组件610可经由源编译器620被编译,借此程序的中间语言表示可被创建,诸如程序集630。程序集630可包括中间语言组件650和元数据642。

应用设计可以能够在部署前被确认。

本文所述的各种技术可结合硬件或软件,或在适当时以其组合来实现。由此,本文所公开的方法和装置或其特定方面或部分可采取包含在诸如软盘、CD-ROM、硬盘驱动器或任何其他机器可读存储介质等有形介质中的程序代码(即,指令)的形式,其中当程序代码被加载到诸如计算机等机器内并由其执行时,该机器成为用于实现本文所公开的主题的各方面的装置。如此出所用的,术语“机器可读存储介质”应被用来排除提供(即存储和/或传输)任何形式的传播信号的任何机制。在程序代码在可编程计算机上执行的情况下,计算设备通常将包括处理器、该处理器可读的存储介质(包括易失性和非易失性的存储器和/或存储元件)、至少一个输入设备、以及至少一个输出设备。可例如通过使用数据处理API等来利用域专用编程模型各方面的创建和/或实现的一个或多个程序可用高级过程语言或面向对象的编程语言来实现以与计算机系统通信。然而,如果需要,该程序可以用汇编语言或机器语言来实现。在任何情形中,语言可以是编译语言或解释语言,且与硬件实现相结合。

尽管用结构特征和/或方法动作专用的语言描述了本主题,但可以理解,所附权利要求书中定义的主题不必限于上述具体特征或动作。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1