如何获取一个林彪坠机地点坐标的坐标

提供各种最新浏览器官方链接下载!
浏览器内核及JS引擎各有什么功能浏览器内核及javascrip引擎有哪些
&&& 我在一文中讲到过,组成可分两部分:Shell+内核。又可以分成两部分:(layout engineer或者Rendering Engine)和。
渲染引擎功能作用
&&&&&& 渲染引擎,负责对网页语法的解释(如HTML、)并渲染网页。 所以,通常所谓的浏览器内核也就是浏览器所采用的渲染引擎,渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法 的解释也有不同,因此同一网页在不同的内核的浏览器里的渲染(显示)效果也可能不同,这也是网页编写者需要在不同内核的浏览器中测试网页显示效果的原因。
当前主流四大引擎内核:
JS引擎功能作用
&&&&& 最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。JavaScript最初由网景公司的Brendan Eich设计,是一种动态、弱类型、基于原型的语言,内置支持类。以它为基础,制定了ECMAScript标 准。JavaScript在浏览器的实现中还必须含有DOM和BOM。Web浏览器一般使用公共 API来创建主机对象来负责将DOM对象反射进JavaScript。JS引擎负责对JavaScript进行解释、编译和执行,以使网页达到一些动态的效果。
主要的网页浏览器JavaScript引擎:
Rhino,由Mozilla基金会管理, 开放源代码,完全以Java编写。
SpiderMonkey,第一款JavaScript引擎,由Brendan Eich在Netscape Communications时编写,用于 1.0~3.0版本。
TraceMonkey,基于实时编译的引擎,其中部份代码取自Tamarin引擎,用于 Mozilla Firefox 3.5~3.6版本。
J&gerMonkey,(J&gerMonkey,也有人拼写成)德文J&ger原意为猎人,结合追踪 和组合码技术大幅提高效能,部分技术借凿了、JavaScriptCore、,用于以上版本。
,开放源代码,由Google丹麦开发,是的一部分。
,中文译名为查克拉,用于。
&是由微软公司开发的活动脚本语言,是微软对ECMAScript规范的实现. 3.0-使用的JS引擎
KJS,KDE的 ECMAScript/JavaScript引擎,最初由Harri Porten开发,用于KDE项目的 Konqueror网页浏览器中。
Narcissus,开放源代码, 由Brendan Eich编写(他也参与编写了第一个SpiderMonkey)。
Tamarin,由Adobe Labs编写,Flash Player 9所使用的引擎。
Nitro(原名SquirrelFish),为 4编 写。
Carakan,由编写,自10.50版 本开始使用。JavaScript引擎是一种为解释和执行JavaScript代码而专门设计的流程虚拟机。将通过布局网页使浏览器运行的布局引擎和解释,执行代码的较低水平的JavaScript引擎作对比是相当重要的。以下是一些比较到位的阐述。JavaScript引擎到底是做什么的呢?当一切就绪,JavaScript的基本工作就是将开发者写的JavaScript代码转换成能被浏览器理解甚至能在应用程序上运用的最优化的快捷代码。事实上,JavaScriptCore称自己是优化的虚拟机。更确切地说,每一个 JavaScript 引擎都实现了ECMAScript的一种版本,而JavaScript 是它的一种方言叫法。JavaScript引擎会随着ECMAScript的发展而进步,因为如此多不同的引擎都要与不同的浏览器一起运作,如headless browser, 或者像Node.js这样的执行环境。你可能对网页浏览器很熟悉,但什么是headless browser呢?这是一种没有形象的用户交界面的网页浏览器。它们擅长对你的网页产品进行机械化的测试。PhantomJS.就是很好的例子。那Node.js又是什么呢?Node.js是一种允许你在服务器端运用JavaScript的异步事件驱动的框架。既然它们是由JavaScript驱动的工具,它们也就应当受JavaScript引擎的驱动。通过以上对虚拟机的定义,将JavaScript引擎称为流程虚拟机也就是理所当然的了。因为它唯一的目的就是要读取和编译JavaScript代码。然而这并不意味着它只是一种简单的引擎。举个例子,JavaScriptCore有6个分区来分析、翻译、优化以及垃圾收集JavaScript代码。这是如何运作的?当然,这取决于引擎。WebKit的JavaScriptCore以及谷歌的V8引擎之所以能引起我们的兴趣是因为NativeScript对它们起了杠杠作用。这两种引擎不同程度地掌握着过程码。JavaScriptCore是通过一系列的步骤去编译和优化脚本。它会对词汇进行分析,将其分解成一系列的记号,或附上某些既定的意义。这些记号之后会被分析程序理出句法,并嵌入句法树文章出自,转载请保留此链接!。之后4个JIT(及时)程序开始运行、分析和执行那些分析程序产生的字节码。嗯?简单讲,JavaScript引擎将你的源代码分解成串(又叫做分词),再将那些串转换成为编译器能够理解的字节码,然后将其执行。用C++编写的谷歌的V8引擎也能编译和解释JavaScript源代码,掌握内存记忆配置且可垃圾回收残留物。它由2个能够将源代码直接转换成计算机代码的编译器组成。Full-codegen:输出非优化代码的快速编译器。Crankshaft:输出快速,优化代码的慢速编译器。如果Crankshaft认为由Full-codegen产生的不够优化的代码需要优化,它将会取而代之,这就是“crankshafting”流程。有趣的事实:机轴是运用在自动化产业中内部氧化引擎里的一个完整的部分。这种众所周知的引擎在更高级的载体也就是V8中有所运用。若计算机代码是由编译过程产生的,那么这个引擎就会在浏览器中显示出所有的ECMA标准规定的数据类型、操作员、客体和功能,或者任何需要用到它们的运行环境,如NativeScript.JavaScript引擎有哪些呢?市场上有许多令人晕眩的JavaScript引擎要去分析、理解和执行客户端的代码。随着每一种浏览器新版本的出现,JavaScript引擎有时会做出一些改变或优化来和JavaScript代码编译中的技术水平相契合。为了避免被那些引擎的各种名字搞晕,请记住,有许多市场营销计划会研究到它们强调的引擎和浏览器。在这份实用的JavaScript编辑器的分析报告中,作者讽刺到:万一你不理解,你要明白在编译器中,差不多有37%是由市场因素组成的,品牌重塑是你在编辑器上可以做的不多的事情之一,因此引擎被赋予了迎合市场的名字:SquirrelFish, Nitro, SFX&在市场因素对为引擎进行命名以及重命名有着重要影响的情况下,对JavaScript引擎发展史上的重大事件做记录是很有必要的。为此,我编辑了一份便捷的表格供大家使用:Browser, Headless Browser, or RuntimeJavaScript EngineMozillaSpidermonkeyChromeV8Safari**JavaScriptCore*IE and EdgeChakraPhantomJSJavaScriptCoreHTMLUnitRhinoTrifleJSV8Node.js***V8Io.js***V8JavaScriptCore被重写为SquirrelFish,也被重塑成SquirrelFishExtreme品牌,又叫做Nitro。然而,在WebKit安装启用下的JavaScript的确也被称为JavaScript引擎(如Safari)**iOS开发者应该认识到Mobile Safari包含Nitro,但UIWebView并不包括JIT编译器,所以这个过程会比较慢。然而,有了iOS8系统,开发者可以运用包含Nitro的WKWebView来大幅度加速这个运行速度。Hybrid App的开发者应该会觉得比较轻松。之所以有做出将io.js从Node.js中分离出来的一个因素是和可以支持这个项目的V8版本有关。这将会是一个挑战,就像这边所列出来的一样。最近更新:免责声明:本文仅代表作者个人观点,与本网无关。看完本文,记得打分哦:很好下载Doc格式文档马上分享给朋友:?知道苹果代表什么吗实用文章,深受网友追捧比较有用,值得网友借鉴没有价值,写作仍需努力相关网页程序设计:
48小时热门Marvell在开源KinomaJS应用框架中全面采用JavaScript第六版,使JavaScript能够用在迄
Marvell在开源KinomaJS应用框架中全面采用JavaScript第六版,使JavaScript能够用在迄
发布: | 作者: | 来源:
| 查看:73次 | 用户关注:
& & & &日,北京讯&-&以“Smart&Life&and&Smart&Lifestyle(美满互联、品‘智’生活)为愿景,为移动通信、存储、物联网(IoT)、云基础设施、数字娱乐、家用内容交付提供完整芯片解决方案和Kinoma?软件的全球领导厂商美满电子科技(Marvell,
& & & &日,北京讯&-&以“Smart&Life&and&Smart&Lifestyle(美满互联、品‘智’生活)为愿景,为移动通信、存储、物联网(IoT)、云基础设施、数字娱乐、家用内容交付提供完整芯片解决方案和Kinoma?软件的全球领导厂商美满电子科技(Marvell,Nasdaq:MRVL)今日宣布,进一步丰富嵌入式和物联网(IoT)原型产品解决方案。Kinoma采用JavaScript第六版以及推出两款最新硬件原型产品,将推动下一波互联原型产品的产生及生产热潮。& & & &Marvell公司总裁、联合创始人Weili&Dai表示:“新技术支持的智能生活方式必须具备简便、无缝互连、反应极其敏捷等特点。这种生活方式还需要开源模式,以使简洁的高性能产品具备开源带来的互操作性、灵活性和稳定性。开源KinomaJS应用框架以Marvell芯片为基础,是我们最先进的软件技术,&面向客户、合作伙伴和开发商。”采用JavaScript第六版& & & &在专业编程语言中,JavaScript是势头最强劲的,因为JavaScript易于上手、速度快且容错。面向Web的JavaScript开发人员群体不断壮大,同时JavaScript在服务器端日益普及,在IoT领域有巨大潜力,因此在现今的编程人员中,JavaScript成为占主导地位的语言。& & & &JavaScript第六版是JavaScript发明以来最重要的一次升级。这一版的正式名称为ECMAScript第六版或ES6,包括超过400处修改,以使这一编程语言更加简练、性能得到提高并集成对各种模块的支持。要设计可靠、长运行时间的设备,必须给该语言增加模块,这也使JavaScript第六版成为互连IoT产品的基础。Kinoma的XS6&JavaScript引擎是JavaScript第六版的一种独立实现形式:?&最全面地采用了JavaScript第六版(即ES6)。最广泛使用的一致性测试套件测试了KinomaJS采用JavaScript第六版的完整性和兼容性,得出了96%的测试结果,这远远超过其他JavaScript引擎。?&该引擎占用的内存容量最小。在RAM小至512KB的设备上运行良好,JavaScript的强大威力和便利性现在能够充分体现在面向大众市场的消费类硬件产品上了。?&快速。与Kinoma采用的JavaScript第五版相比,Kinoma采用的JavaScript第六版使应用启动性能提高了4倍,并通过与原生C代码的高效捆绑连接OS和硬件功能。& & & &Marvell公司Kinoma副总裁Peter&Hoddie表示:“用来开发嵌入式硬件产品的软件工具一般滞后于领先开发软件很多年。IoT开发商希望从语言的最新改进中受益,但是内存和CPU性能要求又使最新语言改进无法用于面向大众市场的硬件产品上。凭借KinomaJS中的XS6引擎,我们能够在JavaScript的最新改进出现在Web上之前,就将其提供给嵌入式设备开发商。”最新硬件原型产品Marvell今天推出了两款最新互联硬件原型产品:& & & &1.Kinoma&Element是JavaScript支持的、最小型嵌入式产品原型平台。该平台以Marvell&MW302无线微控制器单芯片系统为中心而开发,该单芯片系统整合了200MHz&CPU、512KB&RAM和Wi-Fi。Kinoma&Element用来将产品连接到云、移动设备以及其他IoT设备。& & & &凭借一对8引脚扩展端口,Kinoma&Element可以不断地根据原型创建人员的想法和计划进行配置。Kinoma&Element可使用现成有售的传感器、灯、电动机和起动器,这些产品均可用与Kinoma&Create所用相同的JavaScript硬件引脚模块设定。& & & &Execute&in&Place(XIP)技术是在仅有512KB&RAM的设备上运行JavaScript应用的关键。Kinoma&Element中的Cortex&M4通过XIP直接用闪存运行原生ARM代码,因此减少了需占用的RAM空间。XS6&JavaScript引擎针对JavaScript字节代码采用XIP,因此可直接用闪存运行脚本。这种XIP与原生及字节代码的独特整合使Kinoma&Element中的大部分RAM能够空出来用于处理应用数据。 & & & & &Kinoma&Element用来使制图板上的各种想法在原型机中实现,并利用Marvell微控制器产品线实现批量生产。包括August、Blossom、iHome、Rheem和小米在内的众多公司已经为其IoT产品采用了同一产品线中的其他微控制器。& & & &2.&Kinoma&HD是一款可写棒,面向希望在最大型显示器上显示丰富视觉效果的开发人员。Kinoma&HD的HDMI输出接入高清显示器,同时Kinoma&HD以无线方式连接IoT设备、iOS和安卓手持式设备、云服务以及来自Web应用的内容。该可写棒插入显示器的全尺寸HDMI端口、连接USB电源以及连接Wi-Fi网络时,是即插即用的。& & & &Kinoma&HD尽管只有拇指大小,却足够强大,可处理IoT生态系统的多样媒体内容。例如,凭借Kinoma&HD,开发人员可以为IoT产品性能及传感器数据提供富有吸引力的视觉体验。 & & & & & &Marvell公司总裁、联合创始人Weili&Dai表示:“未来,‘智能家具’将把家中和工作场所的桌面和墙壁变成交互式显示器和实时内容指挥中心。我们认为,我们正在快速接近这一愿景。对于将这一愿景变为现实的开发人员来说,Kinoma&HD是理想解决方案。”& & & &Kinoma&HD有256MB&RAM,连接Wi-Fi/g/n/ac,提供p&HDMI输出。Kinoma&HD以Marvell的88DEGHz双核单芯片系统为基础而开发,该单芯片系统属于Marvell&ARMADA&1500视频处理器系列,谷歌、LGE、瑞士电信等提供的主流消费类电子产品都采用了这款单芯片系统。& & & &可定制原型产品系列Kinoma&Element和Kinoma&HD以及最畅销的Kinoma&Create都集成了专业级硬件和JavaScript第六版,采用开源KinomaJS应用框架进行应用开发,并使用相同的开发人员工具,从而可跨产品团队实现高效率原型开发。价格与上市时间& & & &采用JavaScript第六版的升级将于今年第三季度首次在Kinoma&Create上免费提供,同时在Kinoma&Studio&IDE以及KinomaJS开源库中提供。& & & &Kinoma&Element和Kinoma&HD现在可分别以19.95美元及24.95美元的预订价在/buy/上预订。这两款硬件原型产品的定价将有助于它们易于成为实验及大量部署的选择。Kinoma&Element和Kinoma&HD预计于2015年第四季度上市零售。关注Kinoma在O’Reilly&Solid&2015上的动态& & & &Kinoma&Element和Kinoma&HD将在O’Reilly&Solid&2015大会的217号展台展示,展台位于美国旧金山Fort&Mason中心的节日馆(Festival&Pavilion)。此外,Marvell公司Kinoma副总裁Peter&Hoddie将在小组会上发言,演讲题目为“Indiegogo:最新硬件产品的反馈渠道”,时间为6月25日(周四)下午1:15至1:55,地点为Cowell&Theater。如需了解更多信息,请访问:/internet-of-things-2015/public/schedule/speaker/193660。媒体资源& & & &屏幕截图、图标以及其他相关媒体资料可在/media上下载。关于Kinoma& & & &Kinoma业务部的硬件和软件原型解决方案帮助开发人员、编程人员和设计师快速开发互联产品。这个严密整合的工程设计团队属于全球半导体领导者Marvell。Marvell&2010年收购了Kinoma,以获得Kinoma成熟的软件资产。Kinoma软件为使从手机、平板电脑到物联网设备的所有产品实现高性能而设计。如需更多信息,请访问。关于美满电子科技(Marvell)& & & &Marvell(纳斯达克代码:MRVL)是全球领先的完整芯片解决方案及Kinoma软件提供商,旨在实现&“Smart&Life&and&Smart&Lifestyle”。Marvell公司拥有从移动通信、存储、物联网&(IoT)、云基础设施、数字娱乐到家庭内容交付的多元化产品组合,将完整的平台设计与业界领先的性能、安全性、可靠性和效率相结合。作为消费电子、网络和企业系统的强大核心,Marvell公司令合作伙伴及其客户始终站在创新、性能和大众诉求的最前沿。Marvell公司致力于提高大众的生活体验,通过为世界各地的用户提供移动性和易于访问的服务,为社交网络、生活和工作增添价值。如需了解更多信息,请访问:.cn。&
本页面信息由华强电子网用户提供,如果涉嫌侵权,请与我们客服联系,我们核实后将及时处理。
&&& 目前,处理器性能的主要衡量指标是时钟频率。绝大多数的集成电路 (IC) 设计都基于同提示:用户名只能修改一次,请慎重选择名字,大讲堂建议用户使用真实姓名作为用户名。
浅析JavaScript引擎的技术变迁
  上世纪九十年代的第一次浏览器大战,微软凭借其雄厚的资金和超过90%的桌面操作系统覆盖率,毫无悬念地挤掉了网景,让IE成为当时市场上的主导浏览器,巅峰时一度达到了96%的市场份额。此后数年,IE一枝独秀,没有了竞争对手的同时也放缓(可以说是停滞)了浏览器技术革新的脚步。
JavaScript引擎
irefox&3.5
TraceMonkey
1 JavaScript
  直到2004年11月的firefox1.0发布开始,浏览器市场才又开始活跃起来,年,Chrome,Safari,Opera群雄发力,这个阶段这也被业界称作是第二次浏览器大战。从下面这个表中,可以看到各家浏览器厂商在这一阶段都引入了全新的JavaScript引擎。可以说这次浏览器大战的核心就是JavaScript引擎的较量。
  此时一向不太努力的IE浏览器,也肯定不会无动于衷,于是我们在第二年的春天(2010年3月)迎来了IE9,而微软的应对策略即是最新引入的JavaScript引擎Chakra。
  JavaScript引擎的性能对整个浏览器的影响可以说是至关重要,就在过去的几年里,各个浏览器的JavaScript引擎性能都有质的飞跃。引用Dave Mandelin在“”一文中一张图:
2 JavaScript
  在过去5~6年,JavaScript引擎的性能普遍提高了十倍甚至几十倍以上, 运行时性能已经非常接近C/C++了。在享受了性能提升所带来的超炫体验之后,我们也来探探性能提升背后的技术变迁。
  本文通过分析开源的浏览器项目中的JavaScript引擎,历数JavaScript引擎的几种实现方式:从原始的遍历语法树,到字节码方式(bytecode interpreter),直到引入了方式。每一种新方式的出现都是JavaScript引擎性能的一次飞跃。
遍历语法树(Syntax Tree Walker)&
  和很多脚本语言的解释器一样,JavaScript引擎最先也是采用遍历语法树(syntax tree walker)的方式。执行一条语句的过程就是遍历一次相对应的语法树的过程。举个例子:
一条赋值语句:
i = a + b *
  经过词法分析后,就生成了一堆单词流:
"i", "=", "a", "+", "b", "*", "c";
  再经过语法分析后,就生成了如下的语法树:
  执行这条语句,就是遍历这颗语法树的过程。遍历语法树的过程在程序设计上一般采用访问者模式(vistor pattern)来实现。要遍历这颗语法树,只要将根节点传给visit函数, 然后这个函数递归调用相应子节点的visit函数,如此反复直到叶子节点。例如,在这个例子中根节点是个赋值语句,他知道应该计算出右边表达式的值,然后赋给左边的地址;而在计算右边表达式的时候,发现是一个加法表达式,于是接着递归计算加法表达式的值,如此递归进行直到这颗树的叶子节点,然后一步步回溯,将值传到到根节点,就完成了一次遍历,也即完成了一次执行。
  这样的方式虽然原始,但是实现起来简单,对于性能要求不高,只是完成小任务的一些脚本语言,也是可以接受的。WebKit的JavaScript引擎在2008年6月(SquirrelFish的推出)之前就是用这种方式。
  每次执行这条语句,都要进行一次遍历树的过程,这种方式存在着很大的性能缺陷:
  1. 语法树只是描述语法结构,并不是执行这条语句要进行的操作。例如对于语句:{x = 1; y =},根节点是个复合语句“{...}”,他的子节点是两个赋值语句,解释器首先访问这个复合语句节点,但实际上没有做任何事情,然后访问第一个赋值语句,接着访问第二个赋值语句。在一个复杂的程序中,这种不是执行单元,但却是语法树不可或缺的节点很多。因此就会导致做很多无用功。
  2. 访问每个节点的代价太大。遍历语法树一般采用访问者模式,访问每个节点至少需要一次虚函数调用和返回,也即有两个间接跳转,而对于现代CPU而言,这种间接跳转意味着大大增加了分支预测失败的可能行(后文还有关于分支预测的讨论)。
  因此采用遍历语法树方式的JavaScript引擎是很低效的,而且有很大的提升空间。所以即使WebKit团队对这种syntax tree walker已经优化到了极致,但是由于这个方式中存在着上述提到的固有缺陷,之后他们也跟其它的JavaScript引擎一样引入了字节码(bytecode)。
字节码(bytecode)
  从上面介绍的遍历语法树方式中可以发现,要执行一棵语法树,实际上是一个后序遍历树的过程。以上面这个例子,要计算赋值语句,先计算加法表达式,那就必须先计算乘法表达式,也就是说只有子结点计算好了之后,父节点才能计算,典型的后序遍历。
  如果在后序遍历这棵树后,生成对应的后缀记法(逆波兰式)的操作序列,然后在执行时,直接解释执行这个后缀记法的操作序列。那么这时候就把这种树状结构,变换成了一种线性结构。这种操作序列就是字节码(bytecode),这种执行方式就是字节码解释方式(bytecode interpreter)。沿用上面那个遍历语法树的例子,转成相应的字节码,如下图所示:
  在JavaScript引擎中直接执行字节码,肯定比每次都遍历一遍语法树高效。
  字节码,是一种与平台无关的,需要在对应的虚拟机中执行的中间表示。如Java编译器把Java源代码编译成Java字节码,然后在对应平台的Java虚拟机中执行; ActiveScript语言,也是通过转换成字节码,然后在对应的FLASH虚拟机中执行的。Java和ActionScript语言都有标准的字节码格式,但是JavaScript的字节码没有标准的格式,每个JavaScript引擎厂商都有自己的标准。&
  虽然标准不一,但是JavaScript字节码在设计上大体上都可归类为以下两类:基于栈(stack-based)和基于寄存器(register-based)。
  传统的字节码设计大多是基于栈的,这种方式将所有的操作数和中间表示都保存在一个数据栈中。如语句:c = a + b,转换后的字节码如下:
LOAD a &# 将a推入栈顶
LOAD b &# 将b推入栈顶
ADD & & # 从栈顶弹出两个操作数,相加后,将结果推入栈顶
STORE c &#将栈顶数据保存到C中
  基于寄存器的字节码通过一些槽(slot)或称为寄存器(register)的方式保存操作数。这里的寄存器与汇编代码中的寄存器是两个概念。存在寄存器(或槽)中可以想象成就是存入一个固定数组中了。上面例子要是转换成基于寄存器的代码如下:
ADD c, a, b & # 两个操作数分别存在a和b中,将结果放在c中。
  这两种字节码设计各有优劣,如栈式字节码每条的指令更短(因为操作树是隐式得存在栈中),但是总的指令条数更多;栈式虚拟机实现起来比寄存器式来得简单。目前这两种方式都有各自的实现:如Flash Player的ActionScript虚拟机Tamarin,Firefox的JagerMonkey,采用的是栈式字节码设计;而webkit,carakan采用基于寄存器方式。
  采用哪种设计取决于设计者关注的侧重点不同。想详细了解这两种设计的优劣,可参考一些论文(&和)。
  字节码是需要在虚拟机中执行的,而虚拟机的执行过程与CPU过程类似,也是取指,解码,执行的过程。通常情况下,每个操作码对应一段处理函数,然后通过一个无限循环加一个switch的方式进行分派。如:
5 JavaScriptSwitch Loop
  这里的vpc是一个指向字节码数组的指针,在虚拟机中作用与PC寄存器在实际机器中的作用类似,所以称作虚拟PC(virtual program counter)。
  与遍历语法树方式相比,字节码方式就消除了遍历语法树所引起的大部分性能负担。首先字节码序列直接描述了需要执行的动作,去除了多余的语法信息;其次,执行一条字节码语句,只是一次的内存访问(取指令)再加上一次间接跳转(分派到对应的处理函数),这也比访问语法树中一个节点开销来的要小。
  因此,字节码方式与遍历语法树相比在性能上有很大的提升。虽然从语法树生成字节码也是需要时间的,但是这一小段时间可以从直接执行字节码所获得的性能提升上得到补偿。毕竟在实际的代码中,不会所有的代码都只被执行一次。而且生成了字节码之后,就可以对于这种中间代码进行各种优化,比如常量传播,常量折叠,公共子表达式删除等等。当然这些优化都是有针对性和选择性的,毕竟优化的过程也是需要消耗时间的。而这些优化要想直接在语法树上进行几乎是不可能的。
  虽然字节码方式相对于遍历语法树已经前进了一大步,但是在分派方式上还可以再改进。在图5中,Switch Loop分派方式每次处理完一条指令后,都要回到循环的开始,处理下一条,并且每次switch操作,可能都是一次线性搜索(现代编译器一般都能对switch语句进行优化, 以消除这种线性搜索开销,但这种优化也是只限于特定条件,如case的数量和值的跨度范围等),这对于一般的函数,只有有限的几个switch case,尚可接受,但是对于虚拟机来说,有上百个switch case并且是频繁地执行,执行一条指令就需要一次线性搜索,那还是太慢了。如果能用查表的方式直接跳转,就可以省去线性搜索的过程了。于是在字节码的分派方式上,有的新的改进,称作Direct Threading。
Direct Threading
  Direct Threading,这里的threading与我们通常理解的线程没有任何关系,可以理解成是针线中的那个“线”。以这种方式执行时,每执行完一条指令后不是回到循环的开始,而是直接跳到下一条要执行的指令地址。这种方式就比原来的Switch Loop方式有效许多。但是要想有效的实现Direct Threading,需要用到一个gcc的扩展“”,普通的goto语句的标号是在编译时指定的,但是利用“Labels As Values”扩展,goto语句的标号是就可以在运行时计算(这种goto语句也叫),利用这个特性就可以很容易地实现Direct Threading。(想在windows平台用这个特性,也有几个GCC的windows移植版本,如MinGW, Cygwin等)
  上面的Switch Loop如果用Direct Threading方式,就如下图右边所示:
6 Direct Threading
  右图中的Direct Threading方式已经没有了循环和switch分支,所有的字节码分派就是通过“goto *vpc++”进行的。
  vpc在这里是指向字节码数组的指针,字节码数组里的元素就是各个标号的地址。例如,如果有个指令序列是:
mov, add, ret
  那么对应的字节码数组就是:
[&&mov, &&add, &&ret]
  一开始,vpc指向数组的第一条指令,即vpc = &&mov, 那么goto *vpc,就会跳到标号为“mov”的地方开始执行(普通的goto语句无法完成,这是利用gcc的“labels as values”特性);在执行“mov”处理函数末尾的“goto *vpc++”之后,就直接跳转到标号“add”的地方开始执行;直到最后。&
  Direct Threading的执行过程如下图所示:
7 Direct Threading
  最左边是生成的字节码序列,中间就是字节码序列对应的数组,右边是对应的虚拟机实现代码。开始执行时,vpc指向字节码数组的开始,即“enter”指令,虚拟机开始执行“enter”指令对应的操作,在“enter”对应的操作的末尾有个“goto *vpc++”,这时的vpc就指向字节码数组的下一条字节码,在图7中即为mov指令,然后进入mov指令对应的操作。如此反复直到执行完这个字节码数组中的指令。每执行完一条指令,就直接跳转到下一条指令的地址处,这就跟一根“线”穿过一条弯曲的隧道,虽然道路是弯曲的,但每次都是前进的,而不是想Switch Loop那样,每次执行完一条字节码后,又回到起点。
  在引入即时编译(JIT)之前,Direct Threading方式基本上就是采用字节码方式的解释器的最有效和最块的分派方式了。对于一般的JavaScript运算,这种方式也足够用了。但是毕竟解释执行方式肯定比不上直接执行二进制代码。于是接下来即时编译(JIT)技术被引入了JavaScript引擎。
即时编译(Just-In-Time)
  其实JIT这种技术本身很古老,可以追溯到上世纪60年代的LISP语言;并且现代的大部分运行时环境(runtime environment),如微软的.NET框架和大多数的Java实现都是依赖JIT技术来提高运行性能。在JavaScript引擎中引入JIT技术则是在2008年才开始。
  JIT编译技术是一种提高程序运行性能的方法。通常一个程序有两种方式执行:静态编译和解释执行。静态编译就是在运行前先将源代码(如c,c++)针对特定平台(如x86,arm,mips)编译成机器代码,在运行时就可以直接在相应的平台上执行;而解释执行则是每次运行的时候,将每条源代码(如python, javascript)翻译成相应的机器码并立刻执行,并不保存翻译后的机器码,周而复始。可以看到解释执行的运行效率很低,因为每次执行都需要逐句地翻译成机器码然后执行;而静态编译在运行前就编译成相应平台的代码。但是静态编译使得平台移植性很差,也无法实施运行时优化,而且对于动态语言(弱类型语言),变量的类型在运行前未知,很难做到静态编译。JIT编译则是这两种方式的混合,在运行时将源代码翻译成机器码(这一点与解释执行类似),但是会保存已翻译的机器代码,下次执行同一代码段时无需再翻译(这又与静态编译类似)。
  虽然对于一般的运算,Direct Threading方式已经很好了,但是对性能的追求永无之境,没有最好,只有更好。Direct Threading方式曾经是解释器(不仅仅JavaScript引擎)非常有效的分派方式。但是有研究和数据显示在现代体系结构下,这种方式也有很大的局限性()。
  现在的微处理器大量应用流水线构架来达到提高性能的目的。要让流水线总是保持满负荷运转,微处理器有一个专门的硬件设备“分支预测器”来预判分支的目标地址。这样在执行一条指令时,能提前将接下来可能执行的其他指令放入流水线中,上一条指令执行一结束,接下来的指令都已经完成取值和解码阶段,就可以直接执行。所以如果分支预测正确,将会大大提高处理器的性能。但是如果分支预测失败,那么就需要清空整个流水线,重新加载新的指令,而这会导致很严重的性能损耗。
  是通过利用PC寄存器和分支目标的相关性来进行预测。而从图7的Direct Threading执行过程,可以看到分支跳转的目标(如goto *vpc++),是与vPC相关,而不是与实际的硬件PC寄存器相关。所以分支预测器没有足够的信息来进行有效的预测,这就导致的大量的分支预测失败。举个例子,图7中,当运行到add处理函数的尾部,在运行"goto *vpc++"之前,“分支预测器”是无法判断实际的跳转目标是在哪里,而只有等到执行完这句的时候才能准确知道要跳转到哪,而这样就会导致分支预测的时候不能把正确的后续指令推入流水线。数据表明30%~40%的执行时间会消耗在这种由于分支预测失败引起的额外处理上。所以要有效地降低分支预测的失败概率,就要给“分支预测器”提供足够的上下文信息。Context threading技术就是以此得名。
8 Context Threading
  可以看到最左边的图还是原来那个字节码数组,Context Threading是在这个表的基础上又增加了一个表Context Threading Table(从这个表中可以看到已经开始有即时编译了)。将字节码数组中的每条指令编译成一条条的本地调用(call指令)。上图与图7相比,除了多一个Context Threading Table外,在每个处理函数的结尾(右图红色标示)是一个与call 指令对应的ret指令。现代CPU对本地调用的返回地址提供一个非常有效的预测机制,从而就能避免大量的分支预测失败。如上图CPU在执行到“call add”时,在进入add的处理函数之前,会将返回地址(在这里就是下一条指令“call sub”指令的地址)保存在栈中,然后进入add的处理函数,当执行到add处理函数末尾ret时,“分支预测器”这时当然可以预测到要跳到哪了,就是刚才进入add处理函数之前保存的返回地址。所以在实际执行ret之前就可以准确的判断到将要执行的指令。而之前的Direct Threading方式无法做到这一点。
  是否有必要将字节码数组中的每条指令都编译成一条条的本地调用呢?是的,没有必要。在实际的JavaScript引擎实现中,对于简单的指令,如mov,就直接即时编译,inline到机器码中;而对于复杂的指令,如add指令(因为JavaScript是动态语言,是无类型的,所以在运行add指令时需要做一系列的类型判断,如操作数都是数值类型,那么就进行数值加运算;如果操作数都是字符串类型,就进行字符串加运算,还有其他各种类型,所以add指令也算是一个比较复杂的指令),也会对它的常用方式(如操作数都是数值,或都是字符串)直接生成对应的机器码,对于add的其他不常用情况(如一个操作数是数值,另一个是字符串,或者发生溢出了等等情况)则是生成一条call本地调用。
  在上文中提到从语法树生成字节码会消耗执行时间,而将字节码编译成本地机器码(JIT的过程)也需要消耗执行时间。在生成机器码过程中,实施越多的优化,生成的机器码质量越高,同时延迟时间也越长,所以需要权衡延迟的时间与生成的代码质量。
  所以一般情况下,JavaScript引擎并不是对所有代码都会生成机器码,而是只对热点(hot spot)片段进行即时编译,同时在运行中会随时跟踪热点的状态,如果热点的程度越高(被执行得越频繁),实施的优化也越激进。
  以FireFox3.5 JavaScript引擎为例(FireFox的JavaScript引擎叫SpiderMonkey, 在FireFox3.5中,他的JIT编译器叫TraceMonkey),在开始执行时,将源代码生成字节码,然后解释执行字节码,在执行过程中,如果发现一条路径多次执行(比如一个循环体),那么就标记为“HOT”,同时将这条路径上的代码即时编译成机器码,当下次再运行到这条路径时,就直接运行机器码。
  在FireFox4.0中,引入了新的JIT编译器JaegerMonkey替换原来的TraceMonkey,JaegerMonke实际上是TraceMonkey的加强版,它除了跟踪热点路径外,同时又加入的热点函数的跟踪。
  如下图:
9 FireFox4.0JavaScript
  在上图判断热点的虚框中,如果一个路径被执行了超过16次(比如“循环”迭代了超过16次),或一个函数被调用超过16次,那么就进行即时编译;否则解释执行。以这种方式,在JavaScript代码运算强度越大时JavaScript引擎性能提高得越明显,因为对于越频繁执行的代码,不仅是已经被编译成机器码了,同时执行的编译时优化和运行时优化也越充分。目前JIT编译已经是主流浏览器中JavaScript引擎的标配了。
  随着JavaScript引擎性能显著提升,现在网站开发人员就可以在服务器端或者客户端上,充分利用JavaScript语言来完成一些繁重的运算任务。如果说AJAX让JavaScript焕发了第二春,那么HTML5的普及,则是进一步巩固了JavaScript在Web前端技术中的地位。所以JavaScript引擎的性能,一直会是各个浏览器厂商之间相互较量的重要利器。
  这篇文章虽然只是关于JavaScript引擎发展的其中一条线索,但是只要抓住一条绳子,应该就能顺势摘到其它想要的桃子。
请选择禁言时间:
Copyright (C) 1998 - 2013 Tencent. All Rights Reserved.&&腾讯公司 版权所有

我要回帖

更多关于 林彪坠机地点坐标 的文章

 

随机推荐