欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

JavaScript引擎V8執(zhí)行流程概述

本文首發(fā)于 vivo互聯(lián)網(wǎng)技術(shù) 微信公眾號?
鏈接:https://mp.weixin.qq.com/s/t__Jqzg1rbTlsCHXKMwh7A
作者:賴勇高

創(chuàng)新互聯(lián)建站主營額敏網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,重慶APP開發(fā)公司,額敏h5微信平臺小程序開發(fā)搭建,額敏網(wǎng)站營銷推廣歡迎額敏等地區(qū)企業(yè)咨詢

本文主要講解的是V8的技術(shù),是V8的入門篇,主要目的是了解V8的內(nèi)部機制,希望對前端,快應(yīng)用,瀏覽器,以及nodejs同學(xué)有些幫助。這里不涉及到如何編寫優(yōu)秀的前端,只是對JS內(nèi)部引擎技術(shù)的講解。

一、V8來源

JavaScript 引擎 V8 執(zhí)行流程概述

V8的名字來源于汽車的“V型8缸發(fā)動機”(V8發(fā)動機)。V8發(fā)動機主要是美國發(fā)展起來,因為馬力十足而廣為人知。V8引擎的命名是Google向用戶展示它是一款強力并且高速的JavaScript引擎。

V8未誕生之前,早期主流的JavaScript引擎是JavaScriptCore引擎。JavaScriptCore是主要服務(wù)于Webkit瀏覽器內(nèi)核,他們都是由蘋果公司開發(fā)并開源出來。據(jù)說Google是不滿意JavaScriptCore和Webkit的開發(fā)速度和運行速度,Google另起爐灶開發(fā)全新的JavaScript引擎和瀏覽器內(nèi)核引擎,所以誕生了V8和Chromium兩大引擎,到現(xiàn)在已經(jīng)是最受歡迎的瀏覽器相關(guān)軟件。

二、V8的服務(wù)對象

V8是依托Chrome發(fā)展起來的,后面確不局限于瀏覽器內(nèi)核。發(fā)展至今V8應(yīng)用于很多場景,例如流行的nodejs,weex,快應(yīng)用,早期的RN。

三、V8的早期架構(gòu)

V8引擎的誕生帶著使命而來,就是要在速度和內(nèi)存回收上進行革命的。JavaScriptCore的架構(gòu)是采用生成字節(jié)碼的方式,然后執(zhí)行字節(jié)碼。Google覺得JavaScriptCore這套架構(gòu)不行,生成字節(jié)碼會浪費時間,不如直接生成機器碼快。所以V8在前期的架構(gòu)設(shè)計上是非常激進的,采用了直接編譯成機器碼的方式。后期的實踐證明Google的這套架構(gòu)速度是有改善,但是同時也造成了內(nèi)存消耗問題??梢钥聪耉8的初期流程圖:

JavaScript 引擎 V8 執(zhí)行流程概述

早期的V8有Full-Codegen和Crankshaft兩個編譯器。V8 首先用 Full-Codegen把所有的代碼都編譯一次,生成對應(yīng)的機器碼。JS在執(zhí)行的過程中,V8內(nèi)置的Profiler篩選出熱點函數(shù)并且記錄參數(shù)的反饋類型,然后交給 Crankshaft 來進行優(yōu)化。所以Full-Codegen本質(zhì)上是生成的是未優(yōu)化的機器碼,而Crankshaft生成的是優(yōu)化過的機器碼。

四、V8早期架構(gòu)的缺陷

隨著版本的引進,網(wǎng)頁的復(fù)雜化,V8也漸漸的暴露出了自己架構(gòu)上的缺陷:

  1. Full-Codegen編譯直接生成機器碼,導(dǎo)致內(nèi)存占用大

  2. Full-Codegen編譯直接生成機器碼,導(dǎo)致編譯時間長,導(dǎo)致啟動速度慢

  3. Crankshaft 無法優(yōu)化try,catch和finally等關(guān)鍵字劃分的代碼塊

  4. Crankshaft新加語法支持,需要為此編寫適配不同的Cpu架構(gòu)代碼

五、V8的現(xiàn)有架構(gòu)

為了解決上述缺點,V8采用JavaScriptCore的架構(gòu),生成字節(jié)碼。這里是不是感覺Google又繞回來了。V8采用生成字節(jié)碼的方式,整體流程如下圖:

JavaScript 引擎 V8 執(zhí)行流程概述

Ignition是V8的解釋器,背后的原始動機是減少移動設(shè)備上的內(nèi)存消耗。在Ignition之前,V8的Full-codegen基線編譯器生成的代碼通常占據(jù)Chrome整體JavaScript堆的近三分之一。這為Web應(yīng)用程序的實際數(shù)據(jù)留下了更少的空間。

Ignition的字節(jié)碼可以直接用TurboFan生成優(yōu)化的機器代碼,而不必像Crankshaft那樣從源代碼重新編譯。Ignition的字節(jié)碼在V8中提供了更清晰且更不容易出錯的基線執(zhí)行模型,簡化了去優(yōu)化機制,這是V8 自適應(yīng)優(yōu)化的關(guān)鍵特性。最后,由于生成字節(jié)碼比生成Full-codegen的基線編譯代碼更快,因此激活I(lǐng)gnition通常會改善腳本啟動時間,從而改善網(wǎng)頁加載。

TurboFan是V8的優(yōu)化編譯器,TurboFan項目最初于2013年底啟動,旨在解決Crankshaft的缺點。Crankshaft只能優(yōu)化JavaScript語言的子集。例如,它不是設(shè)計用于使用結(jié)構(gòu)化異常處理優(yōu)化JavaScript代碼,即由JavaScript的try,catch和finally關(guān)鍵字劃分的代碼塊。很難在Crankshaft中添加對新語言功能的支持,因為這些功能幾乎總是需要為九個支持的平臺編寫特定于體系結(jié)構(gòu)的代碼。

采用新架構(gòu)后的優(yōu)勢

不同架構(gòu)下V8的內(nèi)存對比,如圖:

JavaScript 引擎 V8 執(zhí)行流程概述

結(jié)論:可以明顯看出Ignition+TurboFan架構(gòu)比Full-codegen+Crankshaft架構(gòu)內(nèi)存降低一半多。

不同架構(gòu)網(wǎng)頁速度提升對比,如圖:

JavaScript 引擎 V8 執(zhí)行流程概述

結(jié)論:可以明顯看出Ignition+TurboFan架構(gòu)比Full-codegen+Crankshaft架構(gòu)70%網(wǎng)頁速度是有提升的。

接下來我們大致的講解下現(xiàn)有架構(gòu)的每個流程:

六、V8的詞法分析和語法分析

學(xué)過編譯原理的同學(xué)可以知道,JS文件只是一個源碼,機器是無法執(zhí)行的,詞法分析就是把源碼的字符串分割出來,生成一系列的token,如下圖可知不同的字符串對應(yīng)不同的token類型。

JavaScript 引擎 V8 執(zhí)行流程概述

詞法分析完后,接下來的階段就是進行語法分析。語法分析語法分析的輸入就是詞法分析的輸出,輸出是AST抽象語法樹。當程序出現(xiàn)語法錯誤的時候,V8在語法分析階段拋出異常。

JavaScript 引擎 V8 執(zhí)行流程概述

七、V8 AST抽象語法樹

下圖是一個add函數(shù)的抽象語法樹數(shù)據(jù)結(jié)構(gòu)

JavaScript 引擎 V8 執(zhí)行流程概述

V8 Parse階段后,接下來就是根據(jù)抽象語法樹生成字節(jié)碼。如下圖可以看出add函數(shù)生成對應(yīng)的字節(jié)碼:

JavaScript 引擎 V8 執(zhí)行流程概述

BytecodeGenerator類的作用是根據(jù)抽象語法樹生成對應(yīng)的字節(jié)碼,不同的node會對應(yīng)一個字節(jié)碼生成函數(shù),函數(shù)開頭為Visit****。如下圖+號對應(yīng)的函數(shù)字節(jié)碼生成:

JavaScript 引擎 V8 執(zhí)行流程概述

void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
  FeedbackSlot slot = feedback_spec()->AddBinaryOpICSlot();
  Expression* subexpr;
  Smi* literal;

  if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
    VisitForAccumulatorValue(subexpr);
    builder()->SetExpressionPosition(expr);
    builder()->BinaryOperationSmiLiteral(expr->op(), literal,
                                         feedback_index(slot));
  } else {
    Register lhs = VisitForRegisterValue(expr->left());
    VisitForAccumulatorValue(expr->right());
    builder()->SetExpressionPosition(expr);  //  保存源碼位置 用于調(diào)試
    builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot)); //  生成Add字節(jié)碼
  }
}

上述可知有個源碼位置記錄,然后下圖可知源碼和字節(jié)碼位置的對應(yīng)關(guān)系:

JavaScript 引擎 V8 執(zhí)行流程概述

生成字節(jié)碼,那字節(jié)碼如何執(zhí)行的呢?接下來講解下:

八、字節(jié)碼

首先說下V8字節(jié)碼:

  1. ?每個字節(jié)碼指定其輸入和輸出作為寄存器操作數(shù)

  2. ?Ignition 使用registers寄存器 r0,r1,r2... 和累加器寄存器(accumulator register)

  3. ?registers寄存器:函數(shù)參數(shù)和局部變量保存在用戶可見的寄存器中

  4. 累加器:是非用戶可見寄存器,用于保存中間結(jié)果

如下圖ADD字節(jié)碼:

JavaScript 引擎 V8 執(zhí)行流程概述

字節(jié)碼執(zhí)行

下面一系列圖表示每個字節(jié)碼執(zhí)行時,對應(yīng)寄存器和累加器的變化,add函數(shù)傳入10,20的參數(shù),最終累加器返回的結(jié)果是50。

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

每個字節(jié)碼對應(yīng)一個處理函數(shù),字節(jié)碼處理程序保存的地址在dispatch_table_中。執(zhí)行字節(jié)碼時會調(diào)用到對應(yīng)的字節(jié)碼處理程序進行執(zhí)行。Interpreter類成員dispatch_table_保存了每個字節(jié)碼的處理程序地址。

JavaScript 引擎 V8 執(zhí)行流程概述

JavaScript 引擎 V8 執(zhí)行流程概述

例如ADD字節(jié)碼對應(yīng)的處理函數(shù)是(當執(zhí)行ADD字節(jié)碼時候,會調(diào)用InterpreterBinaryOpAssembler類):

IGNITION_HANDLER(Add, InterpreterBinaryOpAssembler) {
   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
}

void BinaryOpWithFeedback(BinaryOpGenerator generator) {
    Node* reg_index = BytecodeOperandReg(0);
    Node* lhs = LoadRegister(reg_index);
    Node* rhs = GetAccumulator();
    Node* context = GetContext();
    Node* slot_index = BytecodeOperandIdx(1);
    Node* feedback_vector = LoadFeedbackVector();
    BinaryOpAssembler binop_asm(state());
    Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,                            
feedback_vector, false);
    SetAccumulator(result);  // 將ADD計算的結(jié)果設(shè)置到累加器中
    Dispatch(); // 處理下一條字節(jié)碼

}

其實到此JS代碼就已經(jīng)執(zhí)行完成了。在執(zhí)行過程中,發(fā)現(xiàn)有熱點函數(shù),V8會啟用Turbofan進行優(yōu)化編譯,直接生成機器碼。所以接下來講解下Turbofan優(yōu)化編譯器:

九、Turbofan

Turbofan是根據(jù)字節(jié)碼和熱點函數(shù)反饋類型生成優(yōu)化后的機器碼,Turbofan很多優(yōu)化過程,基本和編譯原理的后端優(yōu)化差不多,采用的sea-of-node。

JavaScript 引擎 V8 執(zhí)行流程概述

add函數(shù)優(yōu)化:

function add(x, y) {
  return x+y;
}
add(1, 2);
%OptimizeFunctionOnNextCall(add);
add(1, 2);

V8是有函數(shù)可以直接調(diào)用指定優(yōu)化哪個函數(shù),執(zhí)行%OptimizeFunctionOnNextCall主動調(diào)用Turbofan優(yōu)化add函數(shù),根據(jù)上次調(diào)用的參數(shù)反饋優(yōu)化add函數(shù),很明顯這次的反饋是整型數(shù),所以turbofan會根據(jù)參數(shù)是整型數(shù)進行優(yōu)化直接生成機器碼,下次函數(shù)調(diào)用直接調(diào)用優(yōu)化好的機器碼。(注意執(zhí)行V8需要加上 --allow-natives-syntax,OptimizeFunctionOnNextCall為內(nèi)置函數(shù),只有加上 --allow-natives-syntax,JS才能調(diào)用內(nèi)置函數(shù) ,否則執(zhí)行會報錯)。

JS的add函數(shù)生成對應(yīng)的機器碼如下:

JavaScript 引擎 V8 執(zhí)行流程概述

這里會涉及small interger小整數(shù)概念,可以查看這篇文章https://zhuanlan.zhihu.com/p/82854566

如果把add函數(shù)的傳入?yún)?shù)改成字符

function add(x, y) {
  return x+y;
}
add(1, 2);
%OptimizeFunctionOnNextCall(add);
add(1, 2);

優(yōu)化后的add函數(shù)生成對應(yīng)的機器碼如下:

JavaScript 引擎 V8 執(zhí)行流程概述

對比上面兩圖,add函數(shù)傳入不同的參數(shù),經(jīng)過優(yōu)化生成不同的機器碼。

如果傳入的是整型,則本質(zhì)上是直接調(diào)用add匯編指令

如果傳入的是字符串,則本質(zhì)上是調(diào)用V8的內(nèi)置Add函數(shù)

到此V8的整體執(zhí)行流程就結(jié)束了。文章中可能存在理解不正確的地方敬請指出。

  • 參考文章
  1. https://v8.dev/docs

  2. https://docs.google.com/presentation/d/1HgDDXBYqCJNasBKBDf9szap1j4q4wnSHhOYpaNy5mHU/edit#slide=id.g17d335048f\_1\_1105

  3. https://docs.google.com/presentation/d/1Z9iIHojKDrXvZ27gRX51UxHD-bKf1QcPzSijntpMJBM/edit#slide=id.p

  4. https://zhuanlan.zhihu.com/p/82854566

網(wǎng)站標題:JavaScript引擎V8執(zhí)行流程概述
網(wǎng)頁路徑:http://aaarwkj.com/article14/peiege.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、Google、靜態(tài)網(wǎng)站、網(wǎng)站設(shè)計、定制網(wǎng)站、域名注冊

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
草草在线成年免费视频| 久久精品国产一区二区三区不卡| 亚洲精品色播一区二区| 午夜毛片免费在线播放| 声入人心第一季在线观看| 亚洲桃色一区二区三区四区| 青青草原精品视频在线| 黄色黄色片黄色片黄色| 亚洲日本高清一二三区| 色婷婷狠狠久久综合中文一本 | 五十路八十路息与子交尾| 久久中文字幕av一区| 麻豆亚洲av熟女国产| 日本免费一区二区三区手机在线| 蜜桃国产精品视频网站| 好吊妞在线新免费视频| 国产亚洲国产av网站在线| 日韩高清精品一区二区| 99热这里只有精品中文| 人妻精品久久一区二区三区| 日韩精品一区二区三区夜色| 国产女同互慰一区二区| 国产一级二级三级久久| 少妇的诱惑免费在线看| 欧美黑人在线一区二区| 国内传媒视频免费观看| 亚洲中文字幕永久免费| 国产在线观看国产精品| 99热久久精品免费精品| 人妻中文字幕在线一二区| 午夜91激情福利视频| 蜜桃av网站免费观看| 美女口爆吞精一区二区| 男人的天堂在线观看黄片| 色桃子av一区二区三区| 日韩人妻有码中文字幕| 日本成人午夜福利电影| 欧美国产精品一区二区免费| 成人精品颜射少妇内射| 97久久精品亚洲中文字幕| 激情啪啪啪的免费网站|