每六周,我們都邑建立一個 V8 的新分支,作為我們宣告流程的一部分。每一個版本都是在 Chrome Beta 里程碑之前從 V8 的 Git master 分支出來的。本日(2018-03-27),我們很愉快地宣告,我們宣告了一個新的分支:V8 version 6.6,在幾個星期內,我們會宣告 Chrome 66 Stable 版,在此之前它依舊處於測試階段。V8 v6.6 供應了面向開發人員的一些很酷的特徵。本文供應了預期宣告的一些亮點預覽。
JavaScript 言語新特徵
Function.prototype.toString() 如今返回源代碼的一切內容,包括空格和詮釋。以下是一箇舊行動和新行動的對照例子:
// 注重 `function` 關鍵詞之前的詮釋以及空格
function /* a comment */ foo () {}
// 之前版本:
foo.toString();
// → 'function foo() {}'
// ^ no comment
// ^ no space
// 新版本:
foo.toString();
// → 'function /* comment */ foo () {}'
行分隔符(U+2028)和段落分隔符(U+2029)如今許可出如今字符串筆墨中,matching JSON。之前,這些標記被視為字符串中的行結束符,因而運用它們會致使 SyntaxError
異常。
在異常捕捉的 catch
子句中可以不加參數: catch 的參數可以省略了 optional-catch-binding。如果您不須要在異常代碼中處置懲罰 exception 對象,這異常有效。
try {
doSomethingThatMightThrow();
} catch { // → Look mom, no binding!
handleException();
}
除了 String.prototype.trim()
外,V8 如今完成了 String.prototype.trimStart() 和 String.prototype.trimEnd()。此功用之前是經由歷程非標準 trimLeft()
和 trimRight()
要領供應的,這些要領依然是新要領的別號,用於向後兼容。
const string = ' hello world ';
string.trimStart();
// → 'hello world '
string.trimEnd();
// → ' hello world'
string.trim();
// → 'hello world'
Array.prototype.values() 要領返回了數組的迭代接口,就像 ES2015 的 Map
和 Set
一樣:如今我們可以運用 keys
、values
、entries
舉行遍歷。此變動有可能與現有的 JavaScript 代碼不兼容。如果您發明某個網站有新鮮的行動或代碼運轉中斷了,請嘗試經由歷程 chrome://flags/#enable-array-prototype-values
禁用此功用,並提出問題。
緩存實行過的代碼
“冷加載(cold load)”和“溫加載(warm load)”這兩個術語在關於加載機能方面是盡人皆知的。在 V8 中,另有熱加載(hot load)的觀點。我們以 Chrome 為例申明加載的差別級別:
- 冷加載(cold load):Chrome 初次看到接見的網頁,而且基礎沒有任何數據緩存。
- 溫加載(warm load):Chrome 會記着網頁已被接見,而且可以從緩存中檢索某些資本(比方圖象和劇本源文件)。V8 意想到頁面運用了雷同的劇本文件,因而將編譯后的代碼與劇本文件一同緩存在磁盤緩存中。
- 熱加載(hot load):Chrome 第三次接見網頁時,從磁盤緩存載入劇本文件時,它還向 V8 供應上次加載時期緩存的代碼。V8 可以運用這個緩存代碼來防備必需從頭最先剖析和編譯劇本。
在 V8 v6.6 之前,我們在頂層編譯后馬上緩存天生的代碼。V8 只編譯已知在頂層編譯歷程當中馬上實行的函數,並將其他函數標記為耽誤編譯。這意味着緩存代碼只包括頂級代碼,而一切其他函數必需在每次頁面加載時從頭最先舉行耽誤編譯。從版本 6.6 最先,V8 會緩存頂級代碼實行以後的劇本天生的代碼。在我們實行劇本時,更多的函數會被編譯而且可以被包括在緩存中。因而,這些函數不須要在將來頁面加載時編譯,從而將熱加載(hot load)場景中的編譯和剖析時候收縮 20-60%。對最終用戶可見的是,供應了一個不太擁堵的主線程,因而會更順暢,而且有更快的加載體驗。
以後我們會編寫此主題相干的細緻博客文章。(已宣告並翻譯:V8 6.6 進一步革新緩存機能)
背景編譯
一段時候以來,V8 已可以在背景線程上剖析 JavaScript 代碼。跟着客歲宣告的 V8 新的 Ignition 字節碼詮釋器,我們擴大了這個功用,以便在背景線程大將 JavaScript 源代碼編譯為字節碼。這使得嵌入 V8 引擎的軟件可以在主線程中實行更多事情,來實行更多的 JavaScript 劇本。我們在 Chrome 66 中啟用了此功用,在一般的網站上,主線程編譯時候減少了 5% 到 20%。有關更多細緻信息,請參閱[此功用的最新博客文章(https://v8project.blogspot.co…。
移除 AST 編碼
客歲 Ignition 和 TurboFan 推出后,我們繼承從簡化編譯流水線(pipeline)中獲益。之前在代碼剖析(parsing)后還須要一個名為 “AST Numbering(AST編碼)” 的階段,用來對天生的籠統語法樹中的節點舉行編號,以後編譯器運用此節點時可以有配合的援用點。
跟着時候的推移,這個后處置懲罰歷程(post-processing)已擴大到包括其他功用:為天生器和異步函數的停息點舉行編號,網絡須要急切編譯的內部函數,初始化筆墨字面量或檢測不可優化的代碼形式。
經由歷程新的流水線(pipeline),Ignition 字節碼成為經常使用的援用點,而且不再須要編號 – 然則,依然須要別的的功用,而且依然保留了 AST 編號。
在 V8 v6.6 中,我們終究想法移除了其他的功用或將其挪動到了其他地方,這些事情在剖析歷程當中完成,從而防備了對 AST 的遍歷。這致使現實編譯時候進步了 3-5%。
異步機能革新
我們為 Promise 和異步函數取得了一些不錯的機能革新,特別是想法縮小了異步函數和 promise 鏈之間的差異。
另外,異步天生器和異步迭代的機能也獲得明顯進步,在行將宣告的 Node 10 LTS 版中會包括 V8 v6.6。
作為一個例子,斟酌下面的斐波那契序列:
async function* fibonacciSequence() {
for (let a = 0, b = 1;;) {
yield a;
const c = a + b;
a = b;
b = c;
}
}
async function fibonacci(id, n) {
for await (const value of fibonacciSequence()) {
if (n-- === 0) return value;
}
}
我們已測量了這類形式在 Babel transpilation 之前和以後的革新:
末了,字節碼革新也進步了這些“可停息”函數的運轉時機能:天生器,異步函數和模塊,並減少了它們的編譯大小。我們設計在行將宣告的版本中進一步革新異步函數和異步天生器的機能,敬請關注。
數組機能革新
Array#reduce
關於 holey double arrays 吞吐量機能進步了 10 倍以上(請參閱我們的博客文章,相識 “holey 數組”和 “packed 數組”是什麼)。
不受信託的代碼庇護
在 V8 v6.6 中,我們針對旁路信道破綻採取了更多減緩步伐,以防備信息泄漏給不可托的 JavaScript 和 WebAssembly 代碼。
不再須要 GYP
這是第一個沒有 GYP 文件的 V8 正式版本。如果您的產物須要 GYP 文件,則須要自行將它們複製到您本身的源代碼庫中。
內存剖析
Chrome 的 DevTools 如今可以跟蹤和快照 C++ DOM 對象,並顯現 JavaScript 援用的一切可接見的 DOM 對象。這個特徵是 V8 渣滓網絡器的新 C++ 跟蹤機制的優點之一。欲相識更多信息,請檢察特地的博客文章:Chrome 66 運用 DevTools 跟蹤 JS 對象和 DOM 對象的援用。
V8 API
請運用 git log branch-heads/6.5..branch-heads/6.6 include/v8.h
獵取 API 的變動列表。
關於運用 git 的 V8 開發者,可以經由歷程 git checkout -b 6.6 -t branch-heads/6.6
簽出 V8 v6.6 中的新功用舉行實驗。或許,您可以定閱 Chrome 的 Beta 頻道,如許可以儘快嘗試新功用。