偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

瀏覽器的引擎編譯、執(zhí)行原理知多少?

系統(tǒng) 瀏覽器
本文將分析瀏覽器引起對(duì)JS代碼的編譯情況,并結(jié)合實(shí)際開發(fā)經(jīng)驗(yàn),重新理解底層的編譯解析機(jī)制,將有助于理解前端開發(fā)在跨端中的應(yīng)用以及一套代碼生成多端的底層邏輯。

[[439465]]

本文轉(zhuǎn)載自微信公眾號(hào)「前端萬有引力」,作者一川 。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端萬有引力公眾號(hào)。

1寫在前面

瀏覽器引擎是如何編譯、執(zhí)行JS代碼的呢?

本文將分析瀏覽器引起對(duì)JS代碼的編譯情況,并結(jié)合實(shí)際開發(fā)經(jīng)驗(yàn),重新理解底層的編譯解析機(jī)制,將有助于理解前端開發(fā)在跨端中的應(yīng)用以及一套代碼生成多端的底層邏輯。那么:

  • Javascript代碼被執(zhí)行分為幾個(gè)階段呢?
  • AST到底是做什么用的?

2V8引擎

我們知道程序語言分為編譯型語言和解釋型語言,他們各自的特點(diǎn)是:

  • 編譯型語言:在代碼執(zhí)行前編譯器直接將對(duì)應(yīng)的代碼轉(zhuǎn)換為機(jī)器碼。如C++
  • 解釋型語言:先將代碼轉(zhuǎn)換為編譯型代碼,再轉(zhuǎn)為機(jī)器碼,其是在運(yùn)行時(shí)轉(zhuǎn)換的。如:Python、Javascript

為了提高運(yùn)行效率,很多瀏覽器廠商在不斷努力,在現(xiàn)代瀏覽器中Chrome的v8引擎是最出類拔萃的,引入了Java虛擬機(jī)和C++編譯器的眾多技術(shù)。也正因此,Node.js也是基于V8引擎開發(fā)的。

那么v8引擎執(zhí)行JS代碼需要經(jīng)歷哪些階段,如下:

  • Parse階段:v8引擎負(fù)責(zé)將JS代碼轉(zhuǎn)換為AST(抽象語法樹)
  • Ignition階段:解釋器將AST轉(zhuǎn)換為字節(jié)碼,解析執(zhí)行字節(jié)碼,同時(shí)為下階段優(yōu)化編譯提供需要的信息
  • TurboFan階段:編譯器利用上個(gè)階段收集的信息,將字節(jié)碼優(yōu)化為可以執(zhí)行的機(jī)器碼
  • Orinoco階段:垃圾回收階段,將程序中不再使用的內(nèi)存空間進(jìn)行回收

編譯、執(zhí)行流程圖

AST

在計(jì)算機(jī)科學(xué)中,抽象語法樹(abstract syntax tree 或者縮寫為 AST),或者語法樹(syntax tree),是源代碼的抽象語法結(jié)構(gòu)的樹狀表現(xiàn)形式,這里特指編程語言的源代碼。

在開發(fā)生產(chǎn)中,我們經(jīng)常使用eslint和babel這些工具都和AST有聯(lián)系,v8引擎就是通過編譯器將源代碼解析為AST的。常見的應(yīng)用場景有:

  • JS反編譯,語法解析
  • Babel編譯ES6語法
  • 代碼高亮
  • 關(guān)鍵字匹配
  • 代碼壓縮

生成AST有兩個(gè)關(guān)鍵:詞法分析和語法分析 語法分析:這個(gè)階段會(huì)將源代碼拆分成最小的、不可再分的詞法單元,稱為token,代碼中的空格在JS中是直接忽略的。詞法單元之間都是獨(dú)立的,也即在該階段我們并不關(guān)心每一行代碼是通過什么方式組合在一起的。

語法分析:這個(gè)過程是將詞法單元轉(zhuǎn)換成一個(gè)由元素逐級(jí)嵌套所組成的待料了程序語法結(jié)構(gòu)的樹,被稱為抽象語法樹。將上一階段生成的 token 列表轉(zhuǎn)換為如下圖右側(cè)所示的 AST,根據(jù)這個(gè)數(shù)據(jù)結(jié)構(gòu)大致可以看出轉(zhuǎn)換之前源代碼的基本構(gòu)造。

簡而言之,詞法分析階段就是將代碼拆解成獨(dú)立的、不可再分的tokens,而語法分析階段就是將拆分后的tokens進(jìn)行解析,根據(jù)其在整個(gè)代碼上下文中的作用和聯(lián)系,去除多余的token形成抽象語法樹。

瀏覽器還不支持es6語法,需要將其轉(zhuǎn)換為es5語法,這個(gè)過程需要借助babel來實(shí)現(xiàn)。將es6源碼解析成AST,再將es6語法的抽象語法樹轉(zhuǎn)為es5的抽象語法樹,最后利用它來生成es5的源代碼。

生成字節(jié)碼

Ignition階段就是將AST轉(zhuǎn)換為字節(jié)碼,但是之前的v8版本不會(huì)經(jīng)歷此過程,最早只是直接通過AST轉(zhuǎn)成機(jī)器碼,后面的版本才開始對(duì)其進(jìn)行改進(jìn)。將AST直接轉(zhuǎn)為機(jī)器碼是存在問題的,因?yàn)椋?/p>

  • 直接轉(zhuǎn)換會(huì)帶來內(nèi)存占用過大的問題。因?yàn)閷⒊橄笳Z法樹全部生成了機(jī)器碼,而機(jī)器碼相比字節(jié)碼占用的內(nèi)存更多
  • 某些JS使用場景使用解釋器更為合適。解析成字節(jié)碼,有些代碼沒必要解析成機(jī)器碼,進(jìn)而可以減少占用大量的內(nèi)存空間

V8引擎重新引進(jìn)Ignition解釋器,將抽象語法樹轉(zhuǎn)換成字節(jié)碼后,內(nèi)存占用顯著降低,同時(shí)可以使用JIT編譯器做進(jìn)一步優(yōu)化。

字節(jié)碼是介于AST和機(jī)器碼之間的代碼,需要將其轉(zhuǎn)換為機(jī)器碼后才能執(zhí)行,字節(jié)碼可以理解為機(jī)器碼的一種抽象。

解釋器在得到AST后,會(huì)按需進(jìn)行解釋和執(zhí)行,也就是說如果某個(gè)函數(shù)沒有被調(diào)用,則不會(huì)去解釋執(zhí)行它。

解釋器創(chuàng)建了調(diào)用棧來記錄函數(shù)的調(diào)用流程,每調(diào)用一個(gè)函數(shù),解釋器就會(huì)把該函數(shù)添加進(jìn)調(diào)用棧。解釋器會(huì)為被添加進(jìn)入的函數(shù)創(chuàng)建一個(gè)棧幀,這個(gè)棧幀是用來保存函數(shù)的局部變量以及執(zhí)行語句,因此會(huì)立即執(zhí)行這個(gè)棧幀。如果正在執(zhí)行的函數(shù)還調(diào)用了其他函數(shù),那么新函數(shù)也將會(huì)被添加進(jìn)調(diào)用棧并執(zhí)行,一旦這個(gè)函數(shù)執(zhí)行結(jié)束,對(duì)應(yīng)的棧幀就會(huì)被立即銷毀。查看調(diào)用棧的方式有兩種:調(diào)用函數(shù)console.log()打印到控制臺(tái),利用瀏覽器開發(fā)者工具進(jìn)行斷點(diǎn)調(diào)試。

生成機(jī)器碼

如果發(fā)現(xiàn)一段代碼被重復(fù)執(zhí)行多次的情況,生成的字節(jié)碼以及分析數(shù)據(jù)會(huì)傳給TurboFan編譯器,它會(huì)根據(jù)分析數(shù)據(jù)的情況生成優(yōu)化好的機(jī)器碼。

TurboFan編譯器是JIT優(yōu)化的編譯器,TurboFan的編譯線程和生成字節(jié)碼不會(huì)在同一個(gè)線程上,這樣可以和Ignition解釋器相互配合著使用,不受另外一方的影響。由Ignition解釋器收集的分析數(shù)據(jù)被TurboFan編譯器使用,主要是通過一種推測(cè)優(yōu)化的技術(shù),生成已經(jīng)優(yōu)化的機(jī)器碼進(jìn)行執(zhí)行。

優(yōu)化后的機(jī)器碼作用與緩存很類似,當(dāng)解釋器再次遇到相同的內(nèi)容時(shí),就可以直接執(zhí)行優(yōu)化后的機(jī)器碼。當(dāng)然優(yōu)化后的代碼有可能會(huì)無法運(yùn)行(比如函數(shù)參數(shù)類型改變),那么會(huì)再次反優(yōu)化為字節(jié)碼交給解釋器。

3參考文章

《Javascript核心原理精講》

《前端也要懂編譯:AST 從入門到上手指南》

《編譯原理》

4寫在最后

 

當(dāng)前市面上比較主流的JS引擎編譯過程大部分類似,主要原因可能是在某些地方加入了特定的優(yōu)化,但是其核心思路和v8大體差不多。AST是比較重要的知識(shí)點(diǎn),深入了解之后有助于自己實(shí)現(xiàn)前端工具。對(duì)此可以通過多研究一些前端工具,來提升自己的業(yè)務(wù)開發(fā)效率和編程能力。

 

責(zé)任編輯:武曉燕 來源: 前端萬有引力
相關(guān)推薦

2021-12-08 07:55:41

EventLoop瀏覽器事件

2018-08-31 10:53:25

MySQL存儲(chǔ)引擎

2015-07-13 09:21:50

風(fēng)速傳感器物聯(lián)網(wǎng)

2010-09-29 09:28:04

DHCP工作原理

2020-11-06 15:20:45

瀏覽器前端架構(gòu)

2013-05-23 16:01:56

瀏覽器

2013-06-14 13:56:29

瀏覽器渲染原理

2019-01-03 13:09:58

瀏覽器緩存原理

2021-04-19 11:40:15

瀏覽器路徑

2020-03-12 11:29:51

JavaScript瀏覽器語言

2013-11-20 13:47:43

瀏覽器渲染引擎

2010-04-05 21:57:14

Netscape瀏覽器

2021-03-22 09:57:30

Godot游戲引擎Web

2024-04-10 09:05:37

2015-02-28 09:39:24

Windows 10Spartan

2012-02-01 13:42:19

2022-08-30 09:01:11

瀏覽器渲染前端

2009-04-14 08:52:46

微軟IE8瀏覽器

2012-03-20 11:41:18

海豚瀏覽器

2012-03-19 17:25:22

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)