优化/function运行时,v8状态码会发生什么变化?

我看到了一个关于v8优化的问题,这让我在v8优化中玩了一下。 我也看到蓝鸟发布有关v8 优化杀手 。

根据v8回购,优化状态代码是2:1,2,4,8等乘法(请参阅OptimizationStatus枚举)

但是,下面的代码给了我奇怪的状态代码,如17和65,只在这些特定的情况下(见最后几行代码)。 任何想法为什么发生这种情况?

function adder(a, b) { return new Function('a', 'b', 'return b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b')(a, b); } function addereval(a, b) { return eval('b%2 ? a + b : b%3 ? a - b : b%5 ? b / a : a * b'); } function printStatus(fn) { var status = %GetOptimizationStatus(fn) switch (status) { case 1: console.log(fn.name, "function is optimized"); break; case 2: console.log(fn.name, "function is not optimized"); break; case 3: console.log(fn.name, "function is always optimized"); break; case 4: console.log(fn.name, "function is never optimized"); break; case 6: console.log(fn.name, "function is maybe deoptimized"); break; case 7: console.log(fn.name,"Function is optimized by TurboFan"); break; default: console.log(fn.name, "Unknown optimization status: ", status); break; } } printStatus(adder); printStatus(addereval); for(let i = 0; i < 263; i++) { adder(1, 2); } console.log('\n', '==== adder after invocation - result is on node v8.2.1 17 or 65 on node v8.7.0 ==='); printStatus(adder); addereval(1, 2); console.log('\n', '==== addereval after invocation - result is 65 ==='); printStatus(addereval); 

运行以下代码:

 node --trace_deopt --allow-natives-syntax FILENAME.js 

如果你觉得它更舒适,你可以使用我的要点

status是一个按位标志值,代码应该看起来更像这样:

 var status = GetOptimizationStatus(fn); if ((status & (1 << 0)) { console.log(fn.name, "kIsFunction"); } if ((status & (1 << 1)) { console.log(fn.name, "kNeverOptimize"); } // etc .. can be 'true' for several different combinations; // most notably, many different status will also include 'kIsFunction' 

考虑17〜或〜16 16 + 1 1〜或〜 (1 << 4) | (1 << 0)的“状态码” (1 << 4) | (1 << 0) 〜表示〜“kIsFunction” “kIsOptimized”。

查看位arrays的一般操作 – 以及为什么在代码中显示的条件使用&

%GetOptimizationStatus已更新为返回一组按位标志,而不是一个单一的值,文章Optimization Killers已过时。 可用的状态信息也稍有改变。

要访问新值,您需要获取返回值的二进制表示forms。 现在,例如,如果返回65 ,则二进制表示如下:

 65₁₀ = 000001000001₂ 

每个二进制数字作为一个布尔值,其含义如下:

 0 0 0 0 0 1 0 0 0 0 0 1 ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ │ │ │ │ │ │ └─╸ is function │ │ │ │ │ │ │ │ │ │ └───╸ is never optimized │ │ │ │ │ │ │ │ │ └─────╸ is always optimized │ │ │ │ │ │ │ │ └───────╸ is maybe deoptimized │ │ │ │ │ │ │ └─────────╸ is optimized │ │ │ │ │ │ └───────────╸ is optimized by TurboFan │ │ │ │ │ └─────────────╸ is interpreted │ │ │ │ └───────────────╸ is marked for optimization │ │ │ └─────────────────╸ is marked for concurrent optimization │ │ └───────────────────╸ is optimizing concurrently │ └─────────────────────╸ is executing └───────────────────────╸ topmost frame is turbo fanned 

因此, 65表示该函数是一个函数并被解释(这意味着在查询其状态时,它不是最优化的)。

要在JavaScript中访问这些值,只需使用按位AND运算符并查看该值是否为非零值:

 var status = %GetOptimizationStatus(fn); if (status & 1) console.log("function is function"); if (status & 2) console.log("function is never optimized"); if (status & 4) console.log("function is always optimized"); if (status & 8) console.log("function is maybe deoptimized"); if (status & 16) console.log("function is optimized"); if (status & 32) console.log("function is optimized by TurboFan"); if (status & 64) console.log("function is interpreted"); ... 

等等。 这里的关键是不止一个条件可以评估为真。