V8引擎的解析過程

認(rèn)識瀏覽器的內(nèi)核

  • 不同的瀏覽器又不同的內(nèi)核組成
    • Gecko:早期被Netscape和Mozilla Friefox瀏覽器使用狂窑;
    • Trident:微軟開發(fā),被IE4~IE11瀏覽器使用泉哈,但是Edge瀏覽器已經(jīng)轉(zhuǎn)向Blink;
    • Webkit:蘋果基于KHTML開發(fā)丛晦、開源的,用于Safari烫沙、Google Chrome之前也在使用;
    • Blink:是Webkit的一個分支锌蓄,Google開發(fā),目前應(yīng)用于Google Chrome瘸爽、Edge您访、Opera等洋只;
  • 事實上辆沦,我們經(jīng)常說的瀏覽器內(nèi)核指的是瀏覽器的排版引擎:
    • 排版引擎(layout engine)污桦,也稱為瀏覽器引擎(browser engine)、頁面渲染引擎(rendering engine)或模板引擎迷殿。

瀏覽器的工作原理

  • JavaScript代碼蔚晨,在瀏覽器中是如何被執(zhí)行的?
    瀏覽器加載文件.png

瀏覽器渲染過程

  • 但是在這個執(zhí)行過程中银择,HTML解析的時候遇到了JavaScript標(biāo)簽,應(yīng)該怎么辦累舷?

    • 會停止解析HTML,而去加載和執(zhí)行JavaScript代碼被盈;


      瀏覽器渲染過程.png
  • 那么,JavaScript代碼由誰來執(zhí)行呢只怎?

    • JavaScript引擎

認(rèn)識JavaScript引擎

  • 為什么需要JavaScript引擎呢?

    • 我們前面說過身堡,高級的編程語言都是需要轉(zhuǎn)成最終的機器指令來執(zhí)行的;
    • 事實上我們編寫的JavaScript無論你交給瀏覽器或者Node執(zhí)行,最后都是需要被CPU執(zhí)行的殿漠;
    • 但是CPU只認(rèn)識自己的指令集,實際上是機器語言佩捞,才能被CPU所執(zhí)行;
    • 所以我們需要JavaScript引擎幫助我們將JavaScript代碼翻譯成CPU指令來執(zhí)行一忱;
  • 比較常見的JavaScript引擎有哪些呢?

    • SpiderMonkey:第一款JavaScript引擎帘营,由Brendan Eich開發(fā)(也就是JavaScript作者);
    • Chakra:微軟開發(fā)芬迄,用于IT瀏覽器;
    • JavaScriptCore:Webkit中的JavaScript引擎禀梳,Apple公司開發(fā);
    • V8:Google開發(fā)的強大JavaScript引擎算途,也幫助Chrome從眾多瀏覽器中脫穎而出;

瀏覽器內(nèi)核和JS引擎的關(guān)系

  • 這里我們先以Webkit為例嘴瓤,Webkit事實上由兩部分組成的:
    • WebCore: 負(fù)責(zé)HTML解析扫外、布局筛谚、渲染等相關(guān)的工作;
    • JavaScriptCore:解析停忿、執(zhí)行JavaScript代碼;
  • 在小程序中編寫的JavaScript代碼就是被JSCore執(zhí)行的瞎嬉;


    瀏覽器內(nèi)核和JS引擎的關(guān)系.png

V8引擎的原理

  • 我們來看一些官方對V8引擎的定義:

    • V8是用C++編寫的Google開源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等氧枣。
    • 它實現(xiàn)ECMAScript和WebAssembly,并在Windows 7或更高版本便监,macOS 10.12+和使用x64碳想,IA-32,ARM或MIPS處理器的Linux系統(tǒng)上運行胧奔。
    • V8可以獨立運行,也可以嵌入到任何C++應(yīng)用程序中龙填。
      V8引擎的原理.png
  • Parse對JavaScript源代碼進行解析,包括詞法分析和語法分析

const name = "why"
// 詞法分析: 
tokens: [{type: "keyword", value: "const"}, 
{type: 'identifier', value: 'name'}]
  • 根據(jù)tokens進行語法分析岩遗,生成AST抽象語法樹
  • Ignition將ast轉(zhuǎn)為字節(jié)碼(因為不同的環(huán)境<window,Linux,mac>能執(zhí)行的機器指令不同),字節(jié)碼再轉(zhuǎn)為匯編代碼再轉(zhuǎn)為機器指令
  • TurboFan收集信息宿礁,比如類型信息(例如某個執(zhí)行頻率較高的函數(shù)),將這些字節(jié)碼直接生成機器碼。
  • Deoptimization操作對機器指令進行反向操作蔬芥,把機器指令轉(zhuǎn)為字節(jié)碼

V8引擎的架構(gòu)

  • V8引擎本身的源碼非常復(fù)雜,大概有超過100w行C++代碼笔诵,通過了解它的架構(gòu),我們可以知道它是如何對JavaScript執(zhí)行的:
  • Parse模塊會將JavaScript代碼轉(zhuǎn)換成AST(抽象語法樹)嗤放,這是因為解析器并不直接認(rèn)識JavaScript代碼壁酬;
    • 如果函數(shù)沒有被調(diào)用次酌,那么是不會被轉(zhuǎn)換成AST的舆乔;
    • Parse的V8官方文檔:https://v8.dev/blog/scanner
  • Ignition是一個解析器,會將AST轉(zhuǎn)換成ByteCode(字節(jié)碼)
    • 同時會收集TurboFan優(yōu)化所需要的信息(比如函數(shù)參數(shù)的類型信息希俩,有了類型才能進行真實的運算);
    • 如果函數(shù)只調(diào)用一次颜武,Ignition會解析執(zhí)行ByteCode;
    • Ignition的V8官方文檔:https://v8.dev/blog/ignition-interpreter
  • TurboFan是一個編譯器鳞上,可以將字節(jié)碼編譯為CPU可以直接執(zhí)行的機器碼这吻;
    • 如果一個函數(shù)被多次調(diào)用唾糯,那么就會被標(biāo)記為熱點函數(shù)怠硼,那么就會經(jīng)過TurboFan轉(zhuǎn)換成優(yōu)化的機器碼移怯,提高代碼的執(zhí)行性能;
    • 但是舟误,機器碼實際上也會被還原為ByteCode,這是因為如果后續(xù)執(zhí)行函數(shù)的過程中嵌溢,類型發(fā)生了變化(比如sum函數(shù)原來執(zhí)行的是number類型同云,后來執(zhí)行變成了string類型)堵腹,之前優(yōu)化的機器碼并不能正確的處理運算,就會逆向的轉(zhuǎn)換成字節(jié)碼疚顷;
    • TurboFan的V8官方文檔:https://v8.dev/blog/turbofan-jit

V8執(zhí)行的細(xì)節(jié)

  • 那么我們的JavaScript源碼是如何被解析(Parse過程)的呢?
  • Blink將源碼交給V8引擎腿堤,Stream獲取到源碼并且進行編碼轉(zhuǎn)換;
  • Scanner會進行詞法分析(lexicla annalysis)笆檀,詞法分析會將代碼轉(zhuǎn)換成tokens;
  • 接下來tokens會被轉(zhuǎn)換成AST樹酗洒,經(jīng)過Parser和PreParser:
    • Parser就是直接將tokens轉(zhuǎn)成AST樹架構(gòu)士修;
    • PreParser稱之為預(yù)解析樱衷,為什么需要預(yù)解析呢?
      • 這是因為并不是所有的JavaScript代碼矩桂,在一開始時就會被執(zhí)行。那么對所有的JavaScript代碼進行解析侄榴,必然會影響網(wǎng)頁的運行效率;
      • 所以V8引擎實現(xiàn)了Lazy Parsing(延遲解析)的方案癞蚕,它的作用是將不必要的函數(shù)進行預(yù)解析蕊爵,也就是只解析暫時需要的內(nèi)容在辆,而對函數(shù)的全量解析是在函數(shù)被調(diào)用時才會進行证薇;
      • 比如我們在一個函數(shù)outer內(nèi)部定義了另外一個函數(shù)inner匆篓,那么inner函數(shù)就會進行預(yù)解析;


        V8引擎的解析圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸦概,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子窗市,更是在濱河造成了極大的恐慌,老刑警劉巖咨察,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摄狱,居然都是意外死亡脓诡,警方通過查閱死者的電腦和手機媒役,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酣衷,“玉大人,你說我怎么就攤上這事穿仪。” “怎么了牡借?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钠龙。 經(jīng)常有香客問我御铃,道長,這世上最難降的妖魔是什么上真? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮睡互,結(jié)果婚禮上根竿,老公的妹妹穿的比我還像新娘。我一直安慰自己寇壳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布壳炎。 她就那樣靜靜地躺著,像睡著了一般匿辩。 火紅的嫁衣襯著肌膚如雪腰耙。 梳的紋絲不亂的頭發(fā)上铲球,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音稼病,去河邊找鬼。 笑死溯饵,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丰刊。 我是一名探鬼主播隘谣,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼寻歧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秩仆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤澄耍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后齐莲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡选酗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芒填。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呜叫。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖朱庆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椎工,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布维蒙,位于F島的核電站,受9級特大地震影響颅痊,放射性物質(zhì)發(fā)生泄漏殖熟。R本人自食惡果不足惜斑响,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舰罚。 院中可真熱鬧,春花似錦营罢、人聲如沸赏陵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽考传。三九已至吃型,卻和暖如春僚楞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镜硕。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兴枯,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓财剖,卻偏偏與公主長得像悠夯,于是被迫代替她去往敵國和親躺坟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容