Register-Based VM
VM をレジスタベースの実行モデルに切り替え、実行時の高速化と、デフォルトとは異なる VM の形状を得ます。
vmRegisterBased オプションは、VM をデフォルトのスタックベースのバイトコードからレジスタベースの実行モデルに切り替えます。場合によっては VM の実行時パフォーマンスが約 10〜20% 向上しますが、その代わりに難読化後のバンドルがやや大きくなります。
このオプションを有効にすると Stateful Opcodes(vmStatefulOpcodes)がオフになります。両者は互換性がないため、vmStatefulOpcodes が有効だった場合、レジスタベースのビルドではそれが通知なく無効になります。
スタックベースとレジスタベースの違い
スタックベースの VM はオペランドを暗黙のスタックに保持します。各値はプッシュされ、次の命令で消費され、結果が再びプッシュされます。一方、レジスタベースの VM はオペランドを直接指定するため、同じ処理をより少ない命令で表現でき、命令間でプッシュやポップのやり取りが発生しません。これが実行時の高速化の理由であり、同時にバイトコードがやや大きくなる理由でもあります。各命令は、読み書きするレジスタをスタック上で暗黙にしておくのではなく、明示的に記述する必要があるからです。
どちらのモデルも、コードの動作や VM が保護する内容は変わりません。同じ仮想化ロジックの 2 つのエンコード方式にすぎず、レジスタベースはわずかなサイズと引き換えにわずかな速度を得るものです。
使いどころ
VM の実行コストが重要な場合に使います。 仮想化されたコードは設計上、プレーンな JavaScript より低速です。そのため、アニメーションループ、フレームごとのハンドラー、負荷の高いパース処理などのホットパスでは、レジスタベースのエグゼキューターで削減できる約 10〜20% は、バンドルが大きくなることに見合う価値があります。まれにしか実行されないコードでは、通常はサイズの増加に見合いません。効果はコードによって異なるため、自分のホットパスで測定してください。
VM の形状を変える効果もあります。 構造的に異なるバイトコードとエグゼキューターを出力するため、出力には一般的なスタックベース VM とは異なるフィンガープリントが残ります。そのスタックベースの形状に合わせて調整された、パターンに基づく汎用的な解析では、レジスタベースのビルドは認識されにくくなります。つまり、配布する VM をデフォルトから遠ざける方法の 1 つです。
内部の仕組み
これはネイティブなレジスタベースのコンパイラーではありません。通常のスタックベースのコンパイラーが、このオプションがない場合とまったく同じようにバイトコードを生成し、その後、別の変換段階がそのバイトコードをレジスタベースの形式に書き換えます。レジスタベースへの変換はそれらすべての後段に位置するため、対象の指定、バイトコードのエンコード、ディスパッチャーのオプションなど、VM 難読化のほとんどの部分は影響を受けません(Stateful Opcodes は例外です。上記を参照してください)。
要件
vmObfuscationが必要です。このオプションはvmObfuscationが生成する VM の形を変えるだけです。- 難読化ツールのバージョン 7.12.0 以降。
このオプションは実験的です。 レジスタベースへの書き換えはデフォルトのスタックベースの処理より新しく、実績も少ないため、配布する前に vmRegisterBased を有効にした状態でコードが正しく動作することをテストしてください。これはどの VM オプションにも当てはまる助言ですが、ここでは特に重要です。
例
レジスタベースの実行は VM 難読化の他の機能と組み合わせられます。Bytecode Encoding、Compact Dispatcher、VM Self Defending、VM Domain Lock は、いずれもデフォルトのスタックベース VM とまったく同じように動作します。変わるのはバイトコードの実行方法であり、それを包む保護ではありません。
