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

WebAssembly的一知半解

開發(fā) 開發(fā)工具
WebAssembly 是一個可移植的底層字節(jié)碼,它通過提供緊湊的表示、高效的驗(yàn)證和編譯以及低開銷甚至零開銷的安全執(zhí)行來滿足這些需求。

隨著互聯(lián)網(wǎng)的發(fā)展,網(wǎng)絡(luò)應(yīng)用變得越來越復(fù)雜,如3d可視化、音視頻軟件以及大型網(wǎng)絡(luò)游戲。因此,代碼的效率和安全性變得更加重要。WebAssembly 是一個可移植的底層字節(jié)碼,它通過提供緊湊的表示、高效的驗(yàn)證和編譯以及低開銷甚至零開銷的安全執(zhí)行來滿足這些需求。它不僅是一個特定的編程模型,而且是獨(dú)立于語言和平臺的一個現(xiàn)代硬件抽象。

1. 緣起

由于歷史的偶然性,JavaScript 是 Web 上唯一天生支持的編程語言。由于其在實(shí)現(xiàn)中的普遍性、快速的性能改進(jìn),或許由于純粹的需要,它已經(jīng)成為許多其他語言的編譯目標(biāo)。然而,JavaScript 有不一致的性能和各種其他的問題。

WebAssembly (簡稱“ Wasm”)用底層代碼解決了 Web上的安全、快速和可移植問題。從 ActiveX 到 Native Client 再到 asm.js,都沒有達(dá)到這種代碼格式應(yīng)該具有的屬性:

  • 安全、快速、可移植性的語義:可以安全而快速地執(zhí)行,并且與語言、硬件和平臺無關(guān),具有確定性結(jié)果并易于推理,同時與 Web 平臺能夠簡單地互操作
  • 安全有效的表達(dá)形式:機(jī)構(gòu)緊湊,很容易解碼,驗(yàn)證和編譯,對開發(fā)者來說很容易生成,支持流式和并行處理。

為什么這些目標(biāo)很重要呢? 為什么又很難呢?

安全性

代碼的安全性在 Web 上是至關(guān)重要的,因?yàn)榇a往往來自不可信的源。代碼的保護(hù)在傳統(tǒng)上是通過提供托管語言運(yùn)行時來實(shí)現(xiàn)的,如瀏覽器的 JavaScript 虛擬機(jī)或語言插件。托管增強(qiáng)了內(nèi)存的安全性,防止程序損害用戶數(shù)據(jù)或系統(tǒng)狀態(tài)。然而,托管的運(yùn)行時在傳統(tǒng)上并沒有為底層代碼提供更多的內(nèi)容,例如c/c++的程序。

快速

類似于c/c++的靜態(tài)語言,編譯器會對底層代碼提前進(jìn)行優(yōu)化。本機(jī)代碼,無論是手寫的還是編譯器優(yōu)化后的輸出,都可以充分利用機(jī)器的性能。運(yùn)行時托管和沙箱技術(shù)通常會給這些代碼帶來巨大的性能開銷。

統(tǒng)一性

除了不可避免的硬件限制之外,存在著大量的優(yōu)秀編程范例,這些范例都不應(yīng)該受到代碼格式的限制。然而,大多數(shù)的運(yùn)行時托管被設(shè)計成能很好地支持特定的語言或者編程范式,同時又給其他語言帶來了巨大的成本。

便于移植

Web 不僅跨越了許多設(shè)備,還跨越了不同的機(jī)器體系結(jié)構(gòu)、操作系統(tǒng)和瀏覽器。針對 Web 的代碼必須獨(dú)立于硬件和平臺,以允許應(yīng)用程序以相同的確定性行為跨所有的瀏覽器和硬件類型運(yùn)行。以前的低級別代碼解決方案都綁定在單一體系結(jié)構(gòu)上,或者存在著其他可移植性問題。

緊湊的機(jī)構(gòu)

通過網(wǎng)絡(luò)傳輸?shù)拇a應(yīng)該很小,以減少負(fù)載、節(jié)省帶寬并提高整體的響應(yīng)能力。Web 上的代碼通常以 JavaScript 源代碼的形式傳輸,即使對其進(jìn)行了壓縮,也遠(yuǎn)不如二進(jìn)制格式緊湊。二進(jìn)制代碼格式也并不總是針對大小進(jìn)行優(yōu)化。

WebAssembly 是第一個針對 Web 的低級別代碼解決方案,它實(shí)現(xiàn)了上述所有設(shè)計目標(biāo),是所有主要瀏覽器供應(yīng)商和在線社區(qū)為構(gòu)建高性能應(yīng)用程序的通用解決方案進(jìn)行協(xié)作的一個結(jié)果。

雖然 Web 是 WebAssembly 的緣起之地,但它的設(shè)計避免了對 Web 的任何依賴。它是一個開放標(biāo)準(zhǔn),能夠在嵌入到各種各樣的環(huán)境中,也許是第一個從開始就用形式語義學(xué)來設(shè)計的工業(yè)級語言。

2. 語言概述

盡管 WebAssembly 是一種二進(jìn)制代碼格式,本質(zhì)上仍然是一種具有語法和結(jié)構(gòu)的編程語言,這使得它更容易解釋和理解。

2.1. 基礎(chǔ)

以下是WebAssembly 中的一些基本概念。

模塊

WebAssembly 二進(jìn)制文件采用了模塊的形式。它包含函數(shù)、全局變量、表和內(nèi)存的定義,這些定義可以通過導(dǎo)入、導(dǎo)出用于復(fù)用。

雖然模塊對應(yīng)于程序的靜態(tài)表示,但模塊的動態(tài)表示是一個實(shí)例,具有完整的可變狀態(tài)。實(shí)例化一個模塊需要為所有導(dǎo)入提供定義,這些導(dǎo)入可能是從以前創(chuàng)建的實(shí)例導(dǎo)出的,通過調(diào)用導(dǎo)出函數(shù)來啟動計算。模塊提供了封裝和沙盒,客戶端只能訪問模塊的導(dǎo)出,其他內(nèi)部構(gòu)件受到保護(hù)而不被篡改; 同時,模塊只能通過客戶端提供的導(dǎo)入與其環(huán)境交互,因此客戶端對給定模塊的功能擁有完全的控制權(quán)。這兩個方面都是代碼安全的重要組成部分。

函數(shù)

模塊中的代碼被組織成單獨(dú)的函數(shù),獲取參數(shù)并返回由其函數(shù)類型定義的結(jié)果。函數(shù)可以相互調(diào)用,包括遞歸調(diào)用,運(yùn)行中的 WebAssembly 程序不能直接訪問執(zhí)行調(diào)用的堆棧。

指令

WebAssembly 在概念上是基于堆棧的機(jī)器,函數(shù)的代碼由操作堆棧上值的指令序列組成。然而,類型系統(tǒng)的布局可以在代碼中的任何點(diǎn)靜態(tài)確定,因此可以直接編譯指令之間的數(shù)據(jù)流,而無需實(shí)現(xiàn)操作堆棧。堆棧的組織僅僅是實(shí)現(xiàn)緊湊表達(dá)的一種方式,它比基于寄存器的機(jī)器尺寸要小。

trap異常

某些指令可能會產(chǎn)生一個異常的trap,這會立即中止當(dāng)前的計算。異常的trap可以不由 WebAssembly 代碼處理,一個嵌入器通常會提供處理這種情況的方法,例如,將它們具體化為 JavaScript 異常。

數(shù)值類型

WebAssembly 只有四個基本值類型可以計算。這些是整數(shù)和浮點(diǎn)數(shù),每個都有32位或64位之分,可以在普通硬件中使用。大多數(shù) WebAssembly 指令對這些數(shù)值類型提供了簡單的操作符,例如一元和二元運(yùn)算符、比較和轉(zhuǎn)換。與硬件一樣,WebAssembly 不區(qū)分有/無符號整數(shù)類型。

變量

函數(shù)可以聲明可變局部變量,這實(shí)際上提供了一組零初始化的虛擬寄存器。模塊還可以聲明類型化的全局變量,這些變量可以是可變的,也可以是不可變的,并且需要顯式的初始值設(shè)定項。導(dǎo)入全局變量允許一種有限的可配置性,例如鏈接。像 WebAssembly 中的所有實(shí)體一樣,變量通過整數(shù)索引引用。

2.2 內(nèi)存

WebAssembly 的主要存儲器是大量的字節(jié)數(shù)組、線性存儲器或簡單存儲器。通過加載和存儲指令訪問內(nèi)存,其中地址只是無符號整數(shù)。

創(chuàng)建與擴(kuò)展

每個模塊最多只能定義一塊內(nèi)存區(qū)域,可以通過導(dǎo)入/導(dǎo)出與其他實(shí)例共享。創(chuàng)建的內(nèi)存區(qū)域具有初始大小,但可以動態(tài)增長。增長單元是一個頁,它被定義為64kb,這將允許在硬件上重用虛擬內(nèi)存硬件進(jìn)行邊界檢查。頁大小是固定的,而不是系統(tǒng)特定的,以防止可移植性的危險。

字節(jié)次序

由于大多數(shù)現(xiàn)代硬件都集中在 little endian 上,或者至少可以同樣很好地處理它,WebAssembly 的內(nèi)存區(qū)域同樣是little endian的字節(jié)順序。因此,內(nèi)存訪問的語義在所有引擎和平臺之間是完全確定和可移植的。

內(nèi)存安全

所有內(nèi)存訪問都是根據(jù)內(nèi)存大小動態(tài)檢查的,越界訪問將導(dǎo)致異常trap。線性內(nèi)存與代碼空間、執(zhí)行堆棧和引擎的數(shù)據(jù)結(jié)構(gòu)是分離的,因此,編譯后的程序不能破壞它們的執(zhí)行環(huán)境,不能跳轉(zhuǎn)到任意位置,或執(zhí)行其他未定義行為。要以高性能的方式與不受信任的 JavaScript 和各種 Web API進(jìn)行交互,就必須實(shí)現(xiàn)快速的進(jìn)程內(nèi)隔離。同時,WebAssembly 引擎安全地嵌入到其他托管語言運(yùn)行時中。

2.3. 控制流

WebAssembly 表示的控制流與大多數(shù)基于堆棧的機(jī)器不同。它不提供任意跳轉(zhuǎn),而是提供更類似于編程語言的結(jié)構(gòu)化控制流。通過這種構(gòu)造確保了控制流不會形成不可約減的循環(huán),不會包含堆棧高度不對齊的塊分支,或者不會分支到多字節(jié)指令的中間。這些屬性允許在一次傳遞中驗(yàn)證 WebAssembly 代碼,在一次傳遞中編譯。

控制結(jié)構(gòu)

塊、循環(huán)和 if 結(jié)構(gòu)必須由結(jié)束操作碼終止,并且必須正確嵌套才能被認(rèn)為是格式良好的結(jié)構(gòu)。這些結(jié)構(gòu)中的內(nèi)部指令序列形成一個塊。注意,循環(huán)不會自動迭代,但允許使用顯式分支手動構(gòu)造循環(huán)。每個控件結(jié)構(gòu)都帶有一個函數(shù)的類型注釋,描述其對堆棧的影響、類型化的Pop/Push值。

分支

分支可以是無條件的、條件的或索引的。它們具有“標(biāo)簽”的即時性,不表示指令流中的位置,而是通過相對嵌套深度引用外部控制結(jié)構(gòu)。因此,標(biāo)簽有效地限定了作用域: 分支只能引用它們嵌套在其中的構(gòu)造。如果一個分支從該構(gòu)造的塊中斷開,切效果取決于目標(biāo)的構(gòu)造: 對于一個塊,或者如果它是一個向前跳轉(zhuǎn)到它的結(jié)束(如 break 語句) ; 對于一個循環(huán),它是一個向后跳轉(zhuǎn)到它的開始(如 continue 語句)。分支通過隱式彈出所有未使用的操作符來解除對操作符堆棧的糾纏,類似于函數(shù)調(diào)用的返回。

表達(dá)式

結(jié)構(gòu)化控制流似乎是一個嚴(yán)格的限制,但大多數(shù)高級控制結(jié)構(gòu)都可以通過合適的塊嵌套輕松表達(dá)。例如,c 樣式 switch 語句,對于無序條件之間的失敗,需要更多的技巧。各種形式的循環(huán)同樣可以用分支組合來表示。

將非結(jié)構(gòu)化的控制流轉(zhuǎn)換為結(jié)構(gòu)化形式是開發(fā)者的責(zé)任。這是 Web 編譯的既定方法,其中 JavaScript 也被限制為結(jié)構(gòu)化控件。這種限制的好處是,引擎中的許多算法更簡單、更快速。

2.4. 函數(shù)調(diào)用和表

函數(shù)體是一個塊。執(zhí)行可以通過以函數(shù)在堆棧上的結(jié)果值到達(dá)塊的末尾來完成,也可以通過退出函數(shù)塊的分支來完成,返回指令只是后者的簡寫。

調(diào)用

函數(shù)可以使用調(diào)用指令直接調(diào)用,指令可以用函數(shù)指針來模擬,該指令將運(yùn)行時索引引用到模塊定義的函數(shù)表中。表中的函數(shù)不需要具有相同的類型。相反,在不匹配的情況下,將根據(jù)提供的指令和trap的預(yù)期類型動態(tài)檢查函數(shù)的類型,保護(hù)了執(zhí)行環(huán)境的完整性。表的異構(gòu)性允許函數(shù)指針更準(zhǔn)確地表示,并簡化了動態(tài)鏈接。為了進(jìn)一步幫助動態(tài)鏈接的場景,可以通過外部API改變導(dǎo)出的表。

外部調(diào)用

函數(shù)可以導(dǎo)入到模塊中,直接和間接調(diào)用都可以調(diào)用導(dǎo)入的函數(shù),并且通過導(dǎo)出/導(dǎo)入,多個模塊實(shí)例可以通信。此外,導(dǎo)入機(jī)制作為一個安全的外部函數(shù)接口( , WebAssembly 程序通過它可以與其嵌入環(huán)境通信。例如,在 Web 上導(dǎo)入的函數(shù)可能是由 JavaScript 定義的宿主函數(shù)??缭秸Z言邊界的值將根據(jù) JavaScript 規(guī)則自動轉(zhuǎn)換。

2.5. 確定性結(jié)果

WebAssembly 試圖在不犧牲性能的情況下為低級代碼提供一個可移植的目標(biāo)。硬件行為不同的地方通常包括整數(shù)除以零,溢出或浮點(diǎn)轉(zhuǎn)換以及對齊等。WebAssembly 的設(shè)計以最小的執(zhí)行開銷為所有這些硬件提供確定性語義。

然而,依賴于實(shí)現(xiàn)的行為仍然有三個來源可以被視為非確定性的:

NaN有效載荷:WebAssembly 遵循 IEEE 754標(biāo)準(zhǔn)進(jìn)行浮點(diǎn)運(yùn)算。但是,IEEE 并沒有在所有情況下為 NaN 值指定精確的位模式,cpu 之間存在顯著差異,而在每個數(shù)值操作之后進(jìn)行規(guī)范化的開銷太大?;?JavaScript 引擎的經(jīng)驗(yàn),可以提供足夠的保證來支持像 NaN-tagging 這樣的技術(shù)。

資源耗盡:資源總是有限的,而且在設(shè)備之間差異很大。特別是,引擎可能會出現(xiàn)內(nèi)存不足,調(diào)用指令也可能由于堆棧溢出而產(chǎn)生異常trap,但是,WebAssembly 本身無法觀察到這些情況,只是中止了計算。

宿主函數(shù):WebAssembly 程序可以調(diào)用本身不確定或者更改 WebAssembly 狀態(tài)的宿主函數(shù)。當(dāng)然,調(diào)用宿主函數(shù)的結(jié)果也超出了 WebAssembly 的語義范圍。

2.6. 二進(jìn)制格式

WebAssembly 作為抽象語法的二進(jìn)制編碼進(jìn)行傳輸,這種編碼被設(shè)計為最小化尺寸大型和解碼時間。二進(jìn)制文件表示一個單獨(dú)的模塊,并根據(jù)其中聲明的不同類型的實(shí)體被劃分為若干部分。函數(shù)體的代碼被推遲到所有聲明之后的一個單獨(dú)的部分,以便在函數(shù)體開始通過網(wǎng)絡(luò)到達(dá)時啟用流式編譯。引擎還可以并行編譯函數(shù)體。。該格式還允許用戶自定義的部分,這些部分可能會被引擎忽略。

3. 語義的感知

WebAssembly 語義由兩部分組成: 定義驗(yàn)證的靜態(tài)語義和定義執(zhí)行的動態(tài)語義。在這兩種情況下,對于聲明性規(guī)范來說都是方便而有效的工具。最后,形式化能夠輕松地證明WebAssembly 規(guī)范,機(jī)器驗(yàn)證結(jié)果的正確性,以及構(gòu)建一個可證明的正確解釋器。

執(zhí)行

執(zhí)行是根據(jù)一個標(biāo)準(zhǔn)的小步驟縮減關(guān)系來定義的,其中每個計算步驟都被描述為一系列指令的重寫規(guī)則。堆棧只是由一個指令序列中所有前導(dǎo)標(biāo)識的指令組成,當(dāng)指令序列被減少為與結(jié)果值堆棧相對應(yīng)的常量時,執(zhí)行終止

為了處理控制構(gòu)造,使用少量輔助管理的指令擴(kuò)展語法,這些輔助指令只在還原過程中臨時出現(xiàn),框架本質(zhì)上是函數(shù)調(diào)用的調(diào)用框架。

存儲區(qū)為程序的全局狀態(tài)建模,并記錄已分配的函數(shù)、全局、表和內(nèi)存實(shí)例的列表。存儲組件之一的索引稱為地址,模塊實(shí)例將指令中出現(xiàn)的靜態(tài)索引映射到存儲中各自的動態(tài)地址。為此,除了函數(shù)本地變量的狀態(tài)之外,每個幀還攜帶一個到它所在的模塊實(shí)例的鏈接,實(shí)現(xiàn)可以通過將生成的機(jī)器代碼專門化為模塊實(shí)例來消除這些閉包。

存儲、幀和指令序列的三元組一起構(gòu)成一個配置,表示 WebAssembly 抽象機(jī)器在給定時間點(diǎn)的完整狀態(tài)。一般的約簡規(guī)則是重寫配置,而不僅僅是指令序列。

驗(yàn)證

在 Web 上,代碼是從不可信的來源獲取的,必須經(jīng)過驗(yàn)證。Webasembly 的驗(yàn)證規(guī)則簡潔地定義為類型系統(tǒng)。這種類型系統(tǒng),在設(shè)計成在一個單一的線性有效檢查。

指令的類型是指定其所需輸入堆棧和提供的輸出堆棧的函數(shù)類型。每條規(guī)則由一個結(jié)論和一個可能是空的前提列表組成。它可以被解讀為: 如果所有前提都成立,結(jié)論就成立。每個指令都有一個規(guī)則,定義何時類型良好。當(dāng)且僅當(dāng)規(guī)則能歸納地推導(dǎo)出它是類型良好的程序時,該程序才有效。

例如,常量和數(shù)值運(yùn)算符的規(guī)則是公理,甚至不需要一個前提??刂茦?gòu)造的規(guī)則要求它們的類型匹配顯式注釋,并且在檢查內(nèi)部塊時使用本地標(biāo)簽擴(kuò)展上下文。當(dāng)鍵入分支指令時,會在上下文中查找標(biāo)簽類型,這需要堆棧上的適當(dāng)操作符來匹配連接點(diǎn)上的堆棧。

可靠性

WebAssembly 系統(tǒng)類型具有標(biāo)準(zhǔn)的可靠性屬性。約簡規(guī)則實(shí)際上涵蓋了有效程序可能出現(xiàn)的所有執(zhí)行狀態(tài)。這意味著沒有類型安全的違規(guī),如無效調(diào)用或非法訪問局部變量,它保證了內(nèi)存安全,并確保了代碼地址或調(diào)用堆棧的不可訪問性。它還意味著操作符堆棧的使用是結(jié)構(gòu)化的,其布局在所有程序點(diǎn)上都是靜態(tài)確定的,這對于在基于寄存器的機(jī)器上的高效編譯至關(guān)重要。此外,它還建立了內(nèi)存和狀態(tài)封裝,即模塊和函數(shù)邊界上的抽象屬性,這些屬性不會泄漏信息。

機(jī)械化證明

WebAssembly 中的引用解釋器包括了將形式規(guī)則直接轉(zhuǎn)譯為可執(zhí)行代碼。雖然這兩個任務(wù)基本上都很簡單,但它們總是容易出現(xiàn)測試沒有發(fā)現(xiàn)的細(xì)微錯誤。機(jī)器化語義驗(yàn)證不僅在于驗(yàn)證 WebAssembly 本身,還在于為其他形式化方法的應(yīng)用程序提供了基礎(chǔ),例如驗(yàn)證針對 WebAssembly 的編譯器或證明程序的性質(zhì)、程序等價性和安全性。

4. 標(biāo)準(zhǔn)化

WebAssembly 的形式化語義能夠促進(jìn)標(biāo)準(zhǔn)化的形成。

核心語言

WebAssembly語言的定義遵循形式化,并指定抽象語法、類型規(guī)則、約簡規(guī)則和抽象存儲。二進(jìn)制格式和文本格式作為屬性文法給出,準(zhǔn)確地描述了它們產(chǎn)生的抽象語法。對于工業(yè)級語言來說,這種嚴(yán)謹(jǐn)和精確程度可能是前所未有的。

形式化:一個廣泛使用的標(biāo)準(zhǔn)不能假定所有讀者都熟悉語義的形式化符號,將正式規(guī)則集中放在標(biāo)準(zhǔn)文檔中,即使不直接閱讀這些規(guī)則的開發(fā)者也會從中受益。

引用解釋器:隨著瀏覽器對 WebAssembly 的產(chǎn)品化實(shí)現(xiàn),引用解釋器近似于“可執(zhí)行的規(guī)范”被用來開發(fā)測試套件,來測試具體的實(shí)現(xiàn)和形式規(guī)范,以及構(gòu)建新特性的原型。

顯然,形式化的語義并非在所有情況下都是直截了當(dāng)?shù)?。WebAssembly 的實(shí)現(xiàn)包括了多階段提案流程。在提案的不同階段,維護(hù)者必須提供: (1)非正式的描述,(2)非正式規(guī)范,(3)原型實(shí)現(xiàn),(4)全面的測試套件,(5)形式規(guī)范,(6)引用解釋器中的實(shí)現(xiàn),(7)獨(dú)立生產(chǎn)系統(tǒng)中的實(shí)現(xiàn)。

嵌入執(zhí)行環(huán)境

WebAssembly 類似于虛擬指令集的程序架構(gòu),因?yàn)樗欢x程序如何加載到執(zhí)行引擎,也不定義程序如何執(zhí)行 i/o。這種設(shè)計分離可以將 WebAssembly 實(shí)現(xiàn)嵌入到執(zhí)行環(huán)境中。嵌入機(jī)制定義了模塊如何加載、導(dǎo)入和導(dǎo)出如何解析、trap如何處理,并提供用于訪問環(huán)境的外部函數(shù)。

為了加強(qiáng)平臺獨(dú)立性,WebAssembly標(biāo)準(zhǔn)被分層為單獨(dú)的文檔: 核心規(guī)范只定義了虛擬指令集架構(gòu),單獨(dú)的嵌入規(guī)范定義了它與具體主機(jī)環(huán)境的交互。

在瀏覽器中,可以通過 JavaScript API 加載、編譯和調(diào)用 WebAssembly 模塊。粗略的方法是(1)從給定源獲取二進(jìn)制模塊,例如,作為網(wǎng)絡(luò)資源,(2)實(shí)例化它,提供必要的導(dǎo)入,(3)調(diào)用所需的導(dǎo)出函數(shù)。由于編譯和實(shí)例化可能比較慢,因此它們作為異步方法提供,其結(jié)果包裝在承諾中。JavaScript API 還允許在外部創(chuàng)建和初始化內(nèi)存或表,或者作為導(dǎo)出訪問它們。

作為一種底層語言,WebAssembly 不提供任何內(nèi)置的對象模型,這種設(shè)計為開發(fā)者提供了最大的靈活性,并且不像以前的虛擬機(jī)那樣,不鎖定任何特定的編程范式/對象模型。生產(chǎn)者可以在 WebAssembly 之上定義通用的 ABI,這樣模塊就可以在不同的應(yīng)用程序中進(jìn)行互操作了。這個關(guān)注點(diǎn)的分離對于將 WebAssembly 作為一種通用的代碼格式至關(guān)重要。

5. 實(shí)現(xiàn)中的一些考量

WebAssembly 的主要設(shè)計目標(biāo)是在不犧牲安全性和可移植性的情況下實(shí)現(xiàn)高性能。

V8(Chrome)、 SpiderMonkey (Firefox)和 JavaScriptCore (WebKit)重用其JS編譯器來提前編譯 WebAssembly 模塊。這樣可以獲得可預(yù)測的高性能,啟動速度更快,并且可能降低內(nèi)存消耗。在這些實(shí)現(xiàn)中,使用了相同的使用抽象控制和操作符堆棧的算法策略。在解碼過程中,對傳入字節(jié)碼進(jìn)行一次驗(yàn)證,不需要額外的中間表示。

SpiderMonkey 引擎包括了兩個 WebAssembly 編譯層。第一種是快速的基線 JIT,JIT 不創(chuàng)建中間表示(Intermediate Representation,IR) ,但是會跟蹤寄存器狀態(tài),并嘗試在前進(jìn)傳遞中執(zhí)行簡單的寄存器分配?;€ JIT 僅用于快速啟動,而優(yōu)化 JIT 在后臺并行編譯模塊。V8在原型配置中包含類似的基線 JIT。優(yōu)化 JIT 可以獲得 JavaScript 的頂級執(zhí)行,并將其重用于 WebAssembly。V8和 SpiderMonkey 都使用基于SSA的中間表示。WebAssembly 的結(jié)構(gòu)化控制流對此有很大的幫助,使得解碼算法更簡單、更有效,并且避免了通常 JIT 的局限性。

通過設(shè)計,可以通過動態(tài)邊界檢查保證 WebAssembly 中的所有內(nèi)存訪問是安全的,這相當(dāng)于根據(jù)內(nèi)存的當(dāng)前大小檢查地址。引擎將從進(jìn)程中的某個基址開始,在一個很大的連續(xù)范圍內(nèi)分配內(nèi)存。為了快速訪問,基址可以存儲在一個專用的機(jī)器寄存器中,一個更積極的策略是將每個實(shí)例的機(jī)器代碼專門化到一個特定的基地址,將它作為一個常量直接嵌入到代碼中。

在64位平臺上,引擎可以利用虛擬內(nèi)存來完全消除內(nèi)存訪問的邊界檢查。引擎只是保留8GB的虛擬地址空間,除了啟動附近的有效內(nèi)存部分,所有頁標(biāo)記為不可訪問。由于 WebAssembly 內(nèi)存地址和偏移量是32位整數(shù)加上一個靜態(tài)常數(shù),任何訪問都不能超過8GB的地址空間。因此,JIT 可以簡單地發(fā)出普通的加載/存儲指令,并依靠硬件保護(hù)機(jī)制來捕獲越界訪問。

通過超前編譯, WebAssembly 模塊的編譯可以并行化,將各個函數(shù)分配到不同的線程,這樣做明顯地提高了性能。例如,v8和 SpiderMonkey 使用8個編譯線程,在編譯速度上都提高了5-6倍。此外,WebAssembly 二進(jìn)制格式的設(shè)計支持流媒體,在加載完整的二進(jìn)制文件之前,引擎可以開始編譯單個函數(shù)。當(dāng)與并行化結(jié)合時,這最小化了冷啟動時間。

代碼緩存除了冷啟動時間之外,熱啟動時間也很重要,因?yàn)橛脩艨赡軙磸?fù)訪問相同的 Web 頁面。IndexedDB 數(shù)據(jù)庫的 JavaScript API 允許 JavaScript 操作和編譯 WebAssembly 模塊,并將其編譯后的表示作為一個不透明的 blob 存儲。這允許 JavaScript 應(yīng)用程序在下載和編譯它之前,首先向 IndexedDB 查詢 WebAssembly 模塊的緩存版本。在 v8和 SpiderMonkey 中,這種機(jī)制可以使啟動時間提高數(shù)秒的數(shù)量級。字節(jié)碼驗(yàn)證的速度和簡單性是獲得良好性能和高保證的關(guān)鍵,WebAssembly 不像 JVM 字節(jié)碼驗(yàn)證那樣有150頁說明,而只是一頁形式化符號。

6. 小結(jié)

WebAssembly 側(cè)重于支持底層代碼,特別是從 c/c + + 編譯而來的代碼。通過包含相關(guān)的原語(如尾調(diào)用、堆棧切換或協(xié)同程序) ,WebAssembly 可能會發(fā)展成為高級語言,但是,一個非常重要的目標(biāo)是提供對內(nèi)置在所有 Web 瀏覽器中的垃圾收集器的訪問,從而消除在編譯 Web 與 JavaScript 時候的相關(guān)缺陷。除了 Web 之外,WebAssembly 還可能在其他領(lǐng)域找到廣泛的用途,例如內(nèi)容傳輸網(wǎng)絡(luò)中的沙盒,智能合約或區(qū)塊鏈上的去中心化計算,作為移動設(shè)備的代碼格式,甚至僅僅作為提供便攜式運(yùn)行時的單獨(dú)引擎。

【參考文獻(xiàn)與關(guān)聯(lián)閱讀】

https://webassembly.org/

https://webassembly.github.io/spec/.

http://asmjs.org

 

https://cacm.acm.org/magazines/2018/12/23288-bringing-the-web-up-to-speed-with-webassembly/fulltext

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2021-05-06 10:26:49

穩(wěn)定幣加密貨幣

2022-02-20 21:44:29

軟件系統(tǒng)架構(gòu)

2020-03-09 09:56:13

高并發(fā)高可用架構(gòu)

2021-10-18 11:42:23

數(shù)據(jù)系統(tǒng)權(quán)衡

2021-03-26 00:20:34

NFT區(qū)塊鏈數(shù)據(jù)庫

2022-11-16 12:48:38

2020-02-04 18:27:38

人工智能倫理學(xué)一知半解

2022-01-26 09:53:23

計算機(jī)體系結(jié)構(gòu)

2025-07-02 04:00:00

2020-06-17 14:13:29

索引數(shù)據(jù)庫場景

2024-02-05 08:35:32

VuenextTickDOM

2018-04-04 19:07:11

區(qū)塊鏈人工智能應(yīng)用場景

2019-10-21 09:32:48

緩存架構(gòu)分層

2020-05-07 10:29:29

瀏覽器Sessioncookie

2012-08-20 14:39:34

Me WidgetEmotion UI華為

2018-12-05 08:26:52

物聯(lián)網(wǎng)智能物聯(lián)網(wǎng)技術(shù)

2019-04-02 10:51:29

瀏覽器緩存前端

2019-08-29 09:30:20

Java泛型構(gòu)造器

2020-12-14 18:02:25

區(qū)塊鏈人民幣技術(shù)

2013-08-02 10:52:10

Android UI控件
點(diǎn)贊
收藏

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