簡體   English   中英

V8 是否監控優化機器代碼的執行?

[英]Does V8 monitor the execution of optimized machine code?

AFAIK,V8 中大致有兩種代碼對象。 一種是由Ignition解釋的javascript字節碼,另一種是由Turbofan編譯優化的機器碼。 根據execution/frames.h ,V8 為每種代碼 object 構造不同的堆棧幀。 這意味着 V8 在執行之前應該知道callee的類型。

當未優化的代碼(JS 字節碼)調用優化的代碼時,我猜 Ignition 可以正確處理這種情況,為優化的代碼構建一個新的堆棧幀。 但是,當優化后的代碼(機器代碼)調用未優化的代碼時,我很好奇 V8 如何確定callee是否未優化。 如果機器代碼直接在處理器上運行,沒有什么可以幫助 V8 確定callee的類型。

此外,在我的理解中,V8 應該檢測某些代碼依賴是否受到損害,以標記或取消優化無效的代碼對象。 如果 V8 不監視機器代碼的執行,這似乎也不可行。

所以我的問題是:

  1. V8 是否監控(優化的)機器代碼的執行? 如果是這樣,它是如何發生的?

  2. 如果1為 false,那么 V8 如何檢查代碼依賴的失效或者檢測callee是否被編譯?

(這里是 V8 開發人員。)

V8 為每種代碼 object 構建不同的堆棧幀。 這意味着 V8 在執行之前應該知道被調用者的類型。

堆棧框架由需要它們的人設置,因此調用者不必檢查被調用者。 (如果必須的話,他們可以。)

如果機器代碼直接在處理器上運行,沒有什么可以幫助 V8 確定被調用者的類型。

V8 可以發出檢查被調用者類型的機器代碼。 但是重復我自己:知道被調用者的優化狀態是沒有必要的。

V8 是否監控(優化的)機器代碼的執行?

不,它沒有。

V8如何檢查代碼依賴的失效

依賴項安裝在可以更改的東西(例如地圖、保護器)上。 當發生這種變化時,注冊的代碼依賴項將被取消優化(即,當它們在堆棧上有激活時標記為“延遲取消優化”,否則就被丟棄)。

【V8如何檢測被調用者是否編譯?

它不需要。 當 function 尚未編譯時,其“代碼”將是觸發編譯的存根。

查看您在評論中給出的具體示例:

var b = false;

function change_o() {
  // as long as b is false, this won't be reassigned ...
  if (b) o = { y : 1, x : 0};
}

var o = { x : 1 };

function f() {
  change_o();
  // ... and thus o.x can be compiled down
  return o.x;
}

// f and change_o are compiled somewhen 
f(); f(); f(); // ...

// a precondition changes
b = true;

// during execution of change_o o is reassigned and changes its shape, accessing o.x will now need a different offset and thus f (which is currently on the stack) becomes invalid
f();

因此,在賦值o =發生的那一刻,運行時會跳轉到一些去優化邏輯,該邏輯必須基於錯誤假設使所有代碼無效。 使從非編譯代碼到編譯代碼的調用無效很容易,只需從某種注冊表中刪除對編譯代碼的引用,沒有人會再調用它。 使來自已編譯函數的未來調用無效到已編譯的 function 更難,但如果調用使用某種間接,則可以重寫此間接以重定向所有未來的調用。 這留下了兩種失效問題:

  • 當前評估的 function 需要失效(-> 急切的去優化),這也不是問題,因為它是 function 退出去優化例程
  • 調用評估的 function 的 function 需要無效(-> 延遲去優化),這是有問題的,因為它們可能在堆棧中的某個位置,並且繼續執行有時會恢復到它們(例如上面示例中的f

但是在后一種情況下,有一種方法可以查找和替換這些函數:每次 function call s 到另一個時,它會將返回地址推入堆棧(參見例如x86 堆棧用法),並且當被調用的ret執行 C指令,它會彈出地址並跳轉到那里。 因此,通過掃描堆棧以查找位於無效函數內部的返回地址,並將其替換為另一個地址,當內部 function (如change_o )返回f時,它實際上並沒有跳回編譯后的f代碼,而是跳入處理程序,然后它可以進行必要的調整。

所以 V8 不會“監控”執行,它會在必要時通過重寫堆棧來主動修改它。

可以在此處找到詳細的演練。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM