如果某个函数没有优化,是否意味着声明它的所有函数都没有优化?

时间:2015-01-23 16:20:01

标签: javascript optimization v8

最近我遇到了关于V8引擎优化JavaScript程序的文章optimization killers。但这篇文章对我来说并不完全清楚,所以我想问一下这个问题。

文章指出:

  

优化编译器编译的代码可以轻松地比通用编译器生成的代码快100倍...   值得注意的是,导致优化纾困的模式会影响整个包含函数。

这是否意味着,例如,如果有一大段代码,假设一个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

一个更普遍的问题是指向一些文献,来源等。关于所有这些优化的东西,如果那些存在的话。

提前谢谢。

1 个答案:

答案 0 :(得分:5)

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

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

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

在上面的例子中,foobarbaz都不能被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调用IC进入单态状态后执行了foo(),V8调用了特定函数值的调用。但是,下次您致电optimizeWack时,会创建一个 foo,该 foo不再匹配上次调用的预期optimizeWhack值。这导致deopt。

如果您在请求优化之前重写示例以致电optimizeWhack两次,那么您会看到optimizeWhack(); optimizeWhack(); %OptimizeFunctionOnNextCall(optimizeWhack); optimizeWhack(); printStatus(optimizeWhack); // $ d8 --allow-natives-syntax test.js // Function is optimized 保持优化:

{{1}}