V8編譯流水線-CPU執行二進制代碼流程

V8運行時環境準備好後,juejin.cn/post/685457… V8開始執行JS代碼,V8須要先將JS代碼編譯成字節碼,而後再解釋執行字節碼,或者將須要優化的字節碼編譯成二進制,直接執行二進制代碼。markdown

1. 簡介

系統硬件組織模型圖結構:主要由CPU,主存儲器,各類IO總線,外部設備(硬盤,顯示器,USB等設備)組成的。函數

首先,在程序執行以前,先將咱們要執行的程序裝進內存。CPU能夠經過 內存地址,從內存中讀取數據或寫入數據。CPU和內存經過內存地址來進行交互。post

內存中的每一個存儲空間都有其對應的獨一無二的地址,這個地址就是內存地址。代碼被編譯成可執行文件後,可執行文件包含二進制的機器碼,二進制代碼會被加載進內存。學習

二進制代碼加載進內存後,CPU就從內存中取出一條指令,分析指令,執行指令,這三個過程稱爲CPU時鐘週期。二進制代碼裝載進內存後,系統將二進制代碼中的第一條指令的地址寫入到PC寄存器中,到下一個時鐘週期時,CPU就會根據PC寄存器中的內存地址,從內存中取出指令。PC寄存器中的指令取出來後,系統會作兩件事:第一件是將下一條指令的內存地址更新到PC寄存器中;第二件就是分析取出來的指令,識別不一樣類型的指令,獲取各類操做數的方法。接着CPU開始執行指令。優化

由於CPU訪問內存速度較慢,因此CPU內部會添加小型的存儲設備,好比通用寄存器。通用寄存器和內存以前的關係就相似於口袋和揹包的關係。通用寄存器容量小,讀寫速度快,內存容量大,讀寫速度慢。 通用寄存器既能夠存儲小量的數據,也能夠存儲指針。好比PC寄存器用來存放下一條執行的指令等。spa

經常使用的指令類型:指針

  • 加載的指令,做用是從內存中複製指定長度的內容到通用寄存器中,並覆蓋寄存器中原來的內容。
  • 存儲的指令,和加載指令相反,做用是將寄存器中的內容複製到內存中的某個位置,並覆蓋內存中這個位置的原有內容。
  • 更新指令,做用是複製兩個寄存器中的內容到ALU中,也能夠是一塊寄存器和一塊內存中的內容到ALU中,而後ALU將相加的結果存放到其中一個寄存器中,並覆蓋原寄存器中的內容。
  • 跳轉指令。以下圖所示。

2. 例子說明

int main()
{  
    int x = 1;
    int y = 2;
    int z = x + y;
    return z;
}
複製代碼

上面C代碼轉成二進制機器碼以下:code

pushq   %rbp  // 將rbp寄存器中的值寫到內存中的棧區域
movq    %rsp, %rbp // 將rsp寄存器中的值寫到rbp寄存器中
movl    $0, -4(%rbp)  // 將0寫到棧幀的第一個位置
movl    $1, -8(%rbp)  // 將常數1壓入棧中,x變量賦值
movl    $2, -12(%rbp)  // 將常數2壓入棧中,y變量賦值
movl    -8(%rbp), %eax  // x的值從棧中複製到eax寄存器中
addl    -12(%rbp), %eax  // eax中已經保存了x的值,此時將棧中的y值取出來,與x相加,相加的結果保存到eax中
movl    %eax, -16(%rbp)  // 將eax寄存器中保存下來的值,存放到內存中
movl    -16(%rbp), %eax  // 將內存中計算好的值加載到eax寄存器中,z變量賦值,eax寄存器中的值做爲返回值
popq    %rbp      // 執行完成,彈出當前函數棧楨
retq              // 返回
複製代碼

3. 總結

  • V8須要先將JS編譯成字節碼或者二進制代碼,而後執行。
  • CPU執行機器代碼的邏輯:首先將編譯以後的二進制代碼加載進內存,而後CPU按照指令的順序,一行一行的執行。在執行指令的過程當中,CPU引入寄存器,將中間數據存儲在寄存器中,從而加快CPU執行速度。
  • CPU使用寄存器的指令:加載指令,存儲指令,更新指令。用來在寄存器和內存,寄存器和寄存器之間傳輸數據。

寫在最後

V8相關的學習總結來自於極客時間李兵老師的課程《圖解goole V8》,若是想了解更多細節,能夠進課程查看。orm

相關文章
相關標籤/搜索