メインコンテンツまでスキップ

逃避解析を一時的に無効化

· 約3分
Mathias Bynens ([@mathias](https://twitter.com/mathias)), サンドボックスエスケープ解析者

JavaScriptでは、割り当てられたオブジェクトが現在の関数外でアクセス可能になる場合、オブジェクトが「逃避」したとみなされます。通常、V8は新しいオブジェクトをJavaScriptヒープに割り当てますが、_逃避解析_を使用すると、最適化コンパイラがオブジェクトの寿命が関数のアクティベーションに限定されていることを確証できる場合に、そのオブジェクトを特別に扱えることがわかります。新しく割り当てられたオブジェクトへの参照がそれを生成する関数から逃避しない場合、JavaScriptエンジンはそのオブジェクトをヒープに明示的に割り当てる必要がありません。代わりに、オブジェクトの値を関数のローカル変数として効果的に扱うことができます。それによって、スタックやレジスタにこれらの値を格納したり、場合によっては値を完全に最適化して無くしたりするなどの多種多様な最適化が可能になります。逃避するオブジェクト(正確には逃避しないことを証明できないオブジェクト)は、ヒープに割り当てる必要があります。

例えば、逃避解析を使用すると、V8が以下のコードを効果的に書き換えることができます:

function foo(a, b) {
const object = { a, b };
return object.a + object.b;
// 注: `object` は逃避しません。
}

…次のコードに書き換えられ、内部最適化がいくつか可能になります:

function foo(a, b) {
const object_a = a;
const object_b = b;
return object_a + object_b;
}

V8 v6.1以前では、複雑で導入以来多くのバグを生み出していた逃避解析の実装を使用していました。この実装は削除され、新しい逃避解析コードベースがV8 v6.2にて利用可能となっています。

しかし、Chromeのセキュリティ脆弱性がV8 v6.1の以前の逃避解析の実装に関して発見され、責任を持って公開されました。ユーザーを保護するため、Chrome 61では逃避解析を無効化しました。Node.jsは影響を受けないはずです。エクスプロイトは信頼されていないJavaScriptの実行に依存しているためです。

逃避解析を無効化すると、上述の最適化が無効化されるためパフォーマンスに悪影響を及ぼします。具体的には、次のES2015機能が一時的な遅延を被る可能性があります:

  • 分割代入
  • for-of 反復処理
  • 配列スプレッド
  • レストパラメータ

逃避解析を無効化するのは一時的な措置であることに注意してください。Chrome 62では、V8 v6.2で導入された新しい — そして最重要事項として有効化された — 逃避解析の実装を提供します。