开发者社区> 余二五> 正文

JavaScript编译器如何工作

简介:
+关注继续查看

当我们谈论JavaScript引擎的时候,通常是指它的编译器,一个把人类可读的源代码(本文中指JavaScript代码)翻译成机器可读的指令的程序。如果你还没考虑过你的代码在运行时会发生什么,那么这听起来可能相当神奇,但编译本质上只是一个翻译练习,让代码运行的快才是神奇的。

wKiom1L23onCtPe_AAGSKtLI_M0464.jpg


简单编译器是怎么工作的

JavaScript被认为是高级语言,这意味着它是人类可读的并且具有高度的灵活性。编译器的工作是把高级语言转换成计算机本地指令。

wKioL1L23mSDpXOLAAC4swj3Xt0630.jpg

一个简单的编译程序有四个处理过程:词法分析器、解析器、翻译器、解释器。

  • 1. 词法分析器(或者说是扫描器,分词器),扫描源码并把它转换为原子单位,称为记号。最常见的实现是使用正则表达式进行模式匹配。

  • 2.  被标记化之后的代码被传入解析器,解析器对代码结构和作用范围进行识别和编码,生成语法树。

  • 3. 这种类似图的结构之后被传入翻译器翻译成字节码。其中最简单的实现是把一个庞大的switch语句标记映射成等价的字节码。

  • 4. 然后字节码被传入字节码解释器,被转换为本机代码。

这是经典的编译器设计,已经存在了很多年。但是桌面程序和浏览器的要求有很大不同。这种经典的结构在多个方面都有缺陷。解决这些问题的创新方式,是浏览器的速度竞赛故事。


快速、轻量、正确

JavaScript语言是非常灵活和具有兼容性的程序结构。那么你怎么写这种后期绑定、弱类型、动态语言的编译器呢?在你使它变快之前,必须先使它变精确,或者像Brendan Eich说的,

“快速、轻量、正确。任意选择两个,只要(结果)是正确的”

一种创新的测试编译器正确性的方式是“模糊测试”。Mozilla的Jesse Ruderman创建的jsfunfuzz正是这个目的。Brendan称它为“JavaScript 嘲弄产生器”,因为它的目的是创造怪异但是语法有效的结构,然后看编译器能否处理。这种工具在验证编译错误和边界问题上非常有帮助。

JIT 编译器

经典结构的原则性问题是运行时的字节码翻译非常慢。在编译过程中,将字节码翻译成机器代码时增加一个步骤可以带来性能提升。不幸的是停留几分钟在网页上等待它完全编译是不会让你的浏览器流行的。

解决方案是由JIT提出的“懒编译”,或者叫实时编译。顾名思义,它只将你用到的这部分代码实时编译成机器代码。JIT编译器有多种多样,各自有各自的优化策略。比如正则表达式编译器致力于优化单个任务,而其它的编译器可能优化像循环或函数这些常见操作。现代化的JavaScript引擎会用到多种编译器,分工合作,从而你代码的性能得到提升。

JavaScript JIT 编译器

第一个JavaScript JIT编译器是Mozilla的TraceMonkey。这是一个“跟踪JIT”,因为它的跟踪路径是从你的代码中寻找常见的可执行代码段。然后这些“常见代码段”被编译成机器代码。和以前的引擎相比,Mozilla的这种优化可以带来20%-40%的性能提升。

在TraceMonkey推出后不久,谷歌就发布了拥有全新V8引擎的Chrome浏览器。V8引擎是为速度而生。一个关键的设计是它完全跳过了字节码生成,取而代之的是由翻译器产生本地机器代码。V8团队在一年之内已经实现了寄存器分配、改善高速缓存、重写正则引擎,使其比原来快了10倍。他们 JavaScript整体执行速度被提高了150%。速度竞赛才刚刚开始。

最近浏览器厂商都纷纷推出了含有一个附加步骤的优化编译器。在定向流图(DFG)或语法树生成之后,编译器可以使用这方面知识,在机器代码产生之前进一步优化性能。Mozilla的IonMonkey和Google的Crankshaft就是DFG编译器的例子。

所有这些别具匠心的设计,其宏伟的目标就是使Javascript代码运行的和本地C代码一样快。这个目标在几年前听起来好像是在搞笑,现在已经越来越近。在第三部分,我们将看到编译器的设计者使用多种策略,开发速度更快的Javascript编译器。











本文转自 hgditren 51CTO博客,原文链接:http://blog.51cto.com/phpme/1357436,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
成为一个编译器之「使用 JavaScript 来制作编译器」
本文讲的是成为一个编译器之「使用 JavaScript 来制作编译器」,布希维克,布鲁克林,一个很棒的周日。我在书店里发现了一本书 John Maeda 写的 “Design by Numbers” 。
1158 0
《JavaScript精粹(修订版)》——1.8 让不同的脚本在同一页面中协同工作
正如您所看到的,标准的创建方法是,直接使用事件的名字(没有on前缀),事件发生时需要调用的函数以及一个用于控制事件传递的参数放在事件名字的后面(第13章会有更详细的讨论)。IE的方法则使用事件处理者的名字(前面带有一个on前缀),需要调用的函数的名字放在其后。
1256 0
LLVM编译器前端 Clang 简介
昨天晚上安装rails的开发环境,被ruby的编译搞的有点崩溃。下载的ruby的源码不能用系统自带的gcc -4.21编译,也不能用系统自带的clang进行编译,必须下载并使用gcc -4.2进行编译才能通过。今天稍微看看编译器的一些背景。
73 0
+关注
20381
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载