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,如需转载请自行联系原作者
目录
相关文章
|
8月前
|
自然语言处理 JavaScript 前端开发
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(修订版)(一)
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(修订版)
64 0
|
8月前
|
自然语言处理 前端开发 JavaScript
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(四)结语
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(四)结语
58 0
|
8月前
|
自然语言处理 JavaScript 前端开发
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(三)模拟执行
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(三)模拟执行
61 0
|
8月前
|
自然语言处理 JavaScript 前端开发
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(修订版)(二)
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(修订版)(二)
61 0
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(修订版)(二)
|
8月前
|
自然语言处理 JavaScript 前端开发
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(二)语法分析
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(二)语法分析
59 0
|
8月前
|
自然语言处理 JavaScript 前端开发
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(一)词法分析
编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器(一)词法分析
64 0
|
Web App开发 自然语言处理 JavaScript
浏览器原理 13 # 编译器和解释器:V8是如何执行一段JavaScript代码的?
浏览器原理 13 # 编译器和解释器:V8是如何执行一段JavaScript代码的?
139 0
浏览器原理 13 # 编译器和解释器:V8是如何执行一段JavaScript代码的?
|
编解码 JavaScript 前端开发
javaScript编译器,Babel详解!
ES6的某些高级语法在浏览器环境甚至是Node.js环境中无法执行。 Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行执行。 这意味着,你可以现在就用 ES6 编写程序,而不用担心现有环境是否支持。
|
JSON JavaScript 安全
分分钟学会 JS AST,打造自己的编译器
抽象语法树是js代码另一种结构映射,可以将js拆解成AST,也可以把AST转成源代码。这中间的过程就是我们的用武之地。 利用 抽象语法树(AST) 可以对你的源代码进行修改、优化,甚至可以打造自己的编译工具。其实有点类似babel的功能。咱们就一起学习下怎么玩转 ast。
579 0
分分钟学会 JS AST,打造自己的编译器
|
存储 Web App开发 缓存
【译】JavaScript工作原理:V8编译器的优化
【译】JavaScript工作原理:V8编译器的优化
280 0
【译】JavaScript工作原理:V8编译器的优化