如果某些函数未优化,是否意味着声明它的所有函数也未优化?

if some function is not optimized does it mean that all functions where it is declared are not optimized either?

最近看到这篇文章optimization killers,讲的是V8引擎对JavaScript程序的优化。但是这篇文章对我来说不是很清楚,所以我想问几个关于这个东西的问题。

文章指出:

Code compiled by the optimizing compiler can easily be, say, 100x faster than the code generated by the generic compiler... It is important to note that patterns that cause optimization bailouts affect the entire containing function.

这是否意味着,如果,例如,一些大的代码,比方说一个 JavaScript 库,它是 IIFE(立即调用的函数表达式)的形式包含一个 try {} catch(e) {} 语句在它里面被另一个函数声明包裹,那么整个库没有优化?

好像是这样,因为我试过运行这个命令$ node --trace_opt --trace_deopt --allow-natives-syntax try_catch.js,而try_catch.js如下:

//Function that contains the pattern to be inspected (using with statement)
function optimizeWhack() {
    foo();
    function foo() {
        try {} catch(e) {}
    }
    return 12
}

function printStatus(fn) {
    switch(%GetOptimizationStatus(fn)) {
        case 1: console.log("Function is optimized"); break;
        case 2: console.log("Function is not optimized"); break;
        case 3: console.log("Function is always optimized"); break;
        case 4: console.log("Function is never optimized"); break;
        case 6: console.log("Function is maybe deoptimized"); break;
    }
}

//Fill type-info
optimizeWhack();

%OptimizeFunctionOnNextCall(optimizeWhack);
//The next call
optimizeWhack();

//Check
printStatus(optimizeWhack);

我得到的回复是这个,function is not optimized:

$ node --trace_opt --trace_deopt --allow-natives-syntax try_catch.js 
[deoptimize context: ea2f6f14679]
[optimizing: optimizeWhack / ea2f6fc9c29 - took 0.033, 0.064, 0.000 ms]
**** DEOPT: optimizeWhack at bailout #1, address 0x0, frame size 8
[deoptimizing: begin 0xea2f6fc9c29 optimizeWhack @1]
  translating optimizeWhack => node=3, height=8
    0x7fff113fa238: [top + 40] <- 0xd7de9006c91 ; [sp + 40] 0xd7de9006c91 <JS Global Object>
    0x7fff113fa230: [top + 32] <- 0x1bca01a663fc ; caller's pc
    0x7fff113fa228: [top + 24] <- 0x7fff113fa268 ; caller's fp
    0x7fff113fa220: [top + 16] <- 0xea2f6f14679; context
    0x7fff113fa218: [top + 8] <- 0xea2f6fc9c29; function
    0x7fff113fa210: [top + 0] <- 0xea2f6fca051 ; rbx 0xea2f6fca051 <JS Function foo>
[deoptimizing: end 0xea2f6fc9c29 optimizeWhack => node=3, pc=0x1bca01a665ff, state=NO_REGISTERS, alignment=no padding, took 0.074 ms]
[removing optimized code for: optimizeWhack]
Function is not optimized

一个更普遍的问题是让我参考一些文献、资源等关于所有这些优化的东西,如果这些东西存在的话。

提前致谢。

V8 的优化编译器是基于函数的,因此如果它无法优化某些不影响任何其他函数的函数 - 包括那些包含此不可优化函数声明的函数。

优化编译器不支持的几乎所有语句也只有局部效果 - 它们禁用包含它们的特定函数的优化,但不影响包含该函数的函数。但是有一个例外:直接 eval 影响所有封闭函数。

function foo() {
  function bar() {
    function baz() {
      eval(str);
    }
  }
}

在上面的例子中none of foo, bar, baz 可以通过V8的Crankshaft进行优化。

现在以您的示例为例:从日志中您可以看到 optimizeWhack 在您请求优化后确实得到了优化

[optimizing: optimizeWhack / ea2f6fc9c29 - took 0.033, 0.064, 0.000 ms]

然而,当执行进入优化函数时,它取消了优化

*** DEOPT: optimizeWhack at bailout #1, address 0x0, frame size 8
[deoptimizing: begin 0xea2f6fc9c29 optimizeWhack @1]

deopt的原因如下:因为你执行了optimizeWhack once call IC at foo()进入了单态状态,V8专门调用了一个特定的函数值。但是,下次您调用 optimizeWack 时,将创建一个 new foo,它不再匹配上次调用的预期 foo 值。这会导致 deopt。

如果您重写示例以在请求优化之前调用 optimizeWhack 两次,那么您将看到 optimizeWhack 保持优化:

optimizeWhack();
optimizeWhack();

%OptimizeFunctionOnNextCall(optimizeWhack);
optimizeWhack();

printStatus(optimizeWhack);

// $ d8 --allow-natives-syntax test.js
// Function is optimized