[譯]WebAssembly 中的 Memory

原文連接:https://fanmingfei.com/posts/...html

這是系列文章第二篇:git


WebAssembly中的內存與JavaScript中的內存有所不一樣。使用WebAssembly,您能夠直接訪問原始字節碼...這可能使人擔心。可是,它的確比你想象中的要安全。瀏覽器

什麼是 memory 對象?

當 WebAssembly 模塊被實例化時,它須要一個 memory 對象。你能夠建立一個新的WebAssembly.Memory並傳遞該對象。若是沒有建立 memory 對象,在模塊實例化的時候將會自動建立,而且傳遞給實例。安全

JS引擎建立一個ArrayBuffer(我在另外一篇文章中解釋)來作這件事情。ArrayBuffer 是 JS 引用的 JavaScript 對象。JS 爲你分配內存。你告訴它須要多少內存,它會建立一個對應大小的ArrayBuffer。函數

React.js requesting a new memory object and JS engine creating one

數組的索引能夠視爲內存地址。若是你須要增長它的內存,你可使用 grow 方法讓數組變大。post

ArrayBuffer 作了兩件事情,一件是作 WebAssembly 的內存,另一件是作 JavaScript 的對象。編碼

  1. 它使 JS 和 WebAssembly 之間傳遞內容更方便。

  2. 使內存管理更安全。

JS 和 WebAssembly 之間傳值

由於 ArrayBuffer 是一個 JavaScript 對象,這意味着 JavaScript 也能夠獲取到這個 memory 中的字節。因此經過這種方式, WebAssembly 和 JavaScript 能夠共享內存,而且相互傳值。

使用數組索引來訪問每一個字節,而不是使用內存地址。

好比,WebAssembly 想將一個字符串寫入內存。它須要將字符串轉換成字節碼。

WebAssembly robot putting string "Hello" through decoder ring

而後把這些字節碼放進數組。

WebAssembly robot putting bytes into memory

而後將字符串所在的內存位置的第一個位置,也就是數組的某個索引,傳遞給 JavaScript。JavaScript 能夠根據索引從 ArrayBuffer 中拿到字符串

WebAssembly robot returning index of first byte in string

如今,不少人並不知道如何在 JavaScript 中使用字節碼。你須要將字節碼轉換爲有用的內容,好比說字符串。

在一些瀏覽器中,你可使用TextDecoderTextEncoderAPI來處理。或者你能夠在你的js文件裏添加一些幫助函數。好比,Emscripten就能夠幫你添加編碼和解碼的方法。

JS engine pulling out bytes, and React.js decoding them

因此,WebAssembly memory 最好的地方就是它是一個 JS 對象。WebAssembly 和 JavaScript 能夠直接使用 memory 互相傳值。

讓 memory 存取更安全

另一個好處是,WebAssembly memory 只是一個 JavaScript 對象:安全。經過防止瀏覽器級內存泄漏並提供內存隔離,使事情變得更安全。

內存泄漏

正如我在內存管理的文章中提到的,當你管理本身的內存時,你可能會忘記清除它。這可能致使系統內存不足。

若是 WebAssembly 模塊實例直接訪問內存,而且若是在超出範圍以前忘記清除該內存,那麼瀏覽器可能會泄漏內存。

由於內存對象只是一個JavaScript對象,因此它自己就被垃圾回收器跟蹤(儘管它的內容不會垃圾回收)。

也就是說,WebAssembly 實例被移除之後,全部的內存數組將會被回收。

Garbage collector cleaning up memory object

內存隔離

當人們聽到WebAssembly讓你直接訪問內存時,他們可能有點緊張。他們認爲,一個惡意的 WebAssembly 模塊可能會進入並在內存中幹壞事,這是絕對不容許的。但事實並不是如此。

ArrayBuffer 提供了邊界。WebAssembly 模塊能夠直接管理的內存是受限制的。

Red arrows pointing to the boundaries of the memory object

它能夠直接管理該數組內部的字節,但它看不到任何超出此數組範圍的內容。

例如,內存中的任何其它 JS 對象,如 window 對象,WebAssembly沒法訪問。這對安全性很是重要。

每當 WebAssembly 中有操做內存時,引擎會進行數組限制檢查,以確保該地址位於 WebAssembly 實例的內存中。

若是代碼嘗試訪問超出範圍的地址,引擎將拋出異常。這保護了其它的內存。

WebAssembly trying to store out of bounds and being rejected

因此這就是 memory 相關的內容。在下一篇文章中,咱們將看研究一些關於安全性的其它類型的 import 數據:table import

About

Lin Clark

Lin 是Mozilla Developer Relations團隊的工程師。她使用 JavaScript、WebAssembly、Rust 和 Servo,也畫一些漫畫。

相關文章
相關標籤/搜索