博客 / 詳情

返回

V8引擎編譯js原理

網絡請求》scriptText》Parser轉義》AST》Ignition編譯》ByteCode字節碼》提取循環執行》優化編譯器

image.png

  1. 執行js代碼
  2. 解析源碼並轉成抽象語法樹(AST)
  3. 基於AST,Ignition解釋器產出字節碼
  4. 同時運行代碼並收集類型反饋
  5. 引擎檢測到常用行為(循環)發生,以及使用的數據類型,為了更高效,字節碼可以反饋數據一起被髮送到優化編譯器。優化編譯器會經過假設實現高度優化的機器碼【內聯緩存技術(inline cashing)】
  6. 如果某些時候,其中一個假設不成立,優化編輯器就會取消優化,並回到解釋器

AST
image.png
JavaScript解析器傳成AST樹:
image.png^解析後的ast樹
從上圖中可以看出,我們只需要遍歷這個樹就能得知let關鍵字和其值。

執行上下文
一個變量提升可以看出來:

function () {
  var x;
  let n;
      {
        var l
        let m
    }
console.log(x,n,l)
console.log(m)
}

如果我們打印以上x,n,l,m
這時候會發現l,x,n都會打印,但m會報錯。
它們可以用以下包含形式解釋:
[var x=undefined; var l=undefiend]
[[let n[let m]]]
image.png
從上面可以看出關係是var定義的變量是在同一個區間內。而let定義的變量在同一個區間內的區域內。
var默認值為undefined,而let沒有任何默認值。

javascript在執行時候,同步任務總是自上而下執行。
異步任務需要先判斷是宏任務還是微任務。宏任務進宏任務隊列,微任務進微任務隊列。

宏任務
可以將每次執行棧執行的代碼當做是一個宏任務

  • I/O
  • setTimeout
  • setInterval
  • setlmmediate
  • requestAnimationFrame

微任務
宏任務 執行完,會在渲染前,將執行期間所產生的所有 微任務 都執行完

  • process.nextTick (nodejs)
  • MutationObserver
  • Promise.then catch finally

先執行宏任務的第一個。在宏觀上,因為我們把同步代碼歸為宏任務。同步任務就是第一個宏任務,但其實它沒進宏任務隊列。宏觀上講:宏任務》微任務。
好理解講:同步任務(第一個宏任務)》微任務》宏任務

事件循環:
image.png
分析:
同步任務:log(1),log(7),直接執行。因此1,7先打印;
微任務:log(3),settimeout => log(4),log(5),因此能執行的只有3,5; settimeout => log(4)被壓入宏任務棧。
宏任務:log(2),log(6),log(4)所以最後打印:2,6,4;

垃圾回收有幾個常見的算法
引用計數,缺點也非常明顯
標記清除
標記清除壓縮
Cheney 算法,是目前用在 v8 新生代垃圾回收

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.