JavaScript 是一款擁有「自動垃圾回收」功能的編程語言。node
市面上具備這樣功能的語言,通常都是擁有相對應的虛擬機的,像 Java的JVM ,C#的CLR ,PHP的Zend。git
虛擬機通常實現了代碼解析,內存的管理、佈局、垃圾回收等功能。github
不像C/C++這種沒有虛擬機的語言,它們須要手動管理內存。編程
C/C++語言編譯後的文件,是能夠直接運行的。數組
我認爲學習一門開發語言,除了知道一些語法上的使用,各類API的調用之外。學習相應的虛擬機也是頗有必要的。而 JavaScript 因爲其特殊的歷史緣由,並非只有 V8 一個引擎。可是目前 V8 它是業界最優秀的 JavaScript 引擎,也就成爲了一個學習樣本。瀏覽器
現在的 JavaScript 不單單是用在瀏覽器端了,也由於 NodeJS 的關係得以在服務器端運行。和瀏覽器端不一樣的地方在於服務器端對資源的敏感性是很高的。當業務規模大了,併發量上來了,一些很細小的問題會放大。這時候一些小小的內存泄漏,都會釀造災難。服務器
因此做爲一個 JavaScript 開發者,搞清楚從敲入 console.log('hello world')
,直到後面交由CPU執行的中間過程是很重要的。併發
這也對如何用 JavaScript 這門鬆散的語言編寫出高質量的代碼是具備指導做用的。編程語言
想真正作到 JavaScript 全棧,路漫漫其修遠兮。工具
V8 做爲一個 JavaScript 引擎,最初是服役於 Google Chrome 瀏覽器的。它隨着 Chrome 的初版發佈而發佈以及開源。如今它除了 Chrome 瀏覽器,已經有不少其餘的使用者了。諸如 NodeJS、MongoDB、CouchDB 等。
JavaScript 做爲 Prototype-Based Language , 基於它使用 Prototype 繼承的特徵,V8 使用了直譯的方式,即把 JavaScript 代碼直接編譯成機器碼( Machine Code, 有些地方也叫 Native Code ),而後直接交由硬件執行。
與傳統的「編譯-解析-執行」的流程不一樣,V8 處理 JavaScript,並無二進制碼或其餘的中間碼。
簡單來講,V8主要工做就是:「把 JavaScript 直譯成機器碼,而後運行」
但這中間,每每是一個複雜的過程,它須要處理不少的難題,諸如:
編譯優化
內存管理
垃圾回收
我寫的這一系列文章,也是從這三個大點來出發,解讀V8針對這些內容的處理。
NodeJS,是怎麼引入V8的?
咱們關注 Node的源碼 目錄:
. ├── ... ├── deps │ ├── ... │ ├── v8 │ ├── ... ├── ... ├── lib │ ├── ... │ ├── buffer.js │ ├── child_process.js │ ├── console.js │ ├── ... ├── node -> out/Release/node ├── ... ├── out │ ├── ... │ ├── Release | ├── node | ├── node.d | ├── obj | └── gen | ├── ... | ├── node_natives.h | ├── ... │ ├── ... ├── src │ ├── ... │ ├── debug-agent.cc │ ├── debug-agent.h │ ├── env-inl.h │ ├── env.cc │ ├── ... ├── ...
須要關注的幾個目錄和文件:
/deps/v8
:這裏是V8源碼所在文件夾,你會發現裏面的目錄結構跟 V8源碼 十分類似。NodeJS除了移植V8源碼,還在增添了一些內容。
/src
:由C/C++編寫的核心模塊所在文件夾,由C/C++編寫的這部分模塊被稱爲「Builtin Module」
/lib
:由JavaScript編寫的核心模塊所在文件夾,這部分被稱爲「Native Code」,在編譯Node源碼的時候,會採用V8附帶的 js2c.py
工具,把全部內置的JavaScript代碼轉換成C++裏面的數組,生成 out/Release/obj/gen/node_natives.h
文件。有些 Native Module 須要藉助於 Builtin Module 實現背後的功能。
/out
:該目錄是Node源碼編譯(命令行運行 make
)後生成的目錄,裏面包含了Node的可執行文件。當在命令行中鍵入 node xxx.js
,實際就是運行了 out/Release/node
文件。
來張圖說明一下V8在Node運行時的總體過程。
Node在啓動的時候,就已經把 Native Module,Builtin Module 加載到內存裏面了。後來的 JavaScript 代碼,就須要經過 V8 進行動態編譯解析運行。