一般的にはそうではありません。ただし、どちらのタイプも想定し、そのために最適化することができます。詳細は、JITの種類によって異なります。
いわゆるトレーシングJITコンパイラは、プログラムを解釈および監視し、1回の実行(ループ反復など)のタイプ、ブランチなどを記録します。彼らはこれらの観察結果を記録し、コードが実行されたときにこれらの仮定がまだ正しいことを(非常に高速に)チェックし、次にこれらの仮定に基づいて次のコードから一体を最適化します。たとえば、関数が常に真の引数を使用してループで呼び出され、それに1つ追加された場合、JITコンパイラは最初にこのような命令を記録します(呼び出しフレーム管理、メモリ割り当て、変数の間接参照などは無視します。重要ではありませんが、多くのコードを取り、最適化されているためです):
; calculate arg
guard_true(arg)
boxed_object o1 = box_int(6)
guard_is_boxed_int(o1)
int i1 = unbox_int(o1)
int i2 = 1
i3 = add_int(res2, res3)
次に、次のように最適化します。
; calculate arg
; may even be elided, arg may be constant without you realizing it
guard_true(arg)
; guard_is_boxed_int constant-folded away
; unbox_int constant-folded away
; add_int constant-folded away
int i3 = 7
ガードを移動して以前のコードを最適化したり、組み合わせてガードを減らしたり、冗長な場合は省略したり、強化して最適化を増やしたりすることもできます。ガードが頻繁に失敗する場合、または一部のコードが役に立たなくなる場合は、破棄できます。または、少なくともガードの失敗時に別のバージョンにジャンプするようにパッチを適用します。
他のJITは、より静的なアプローチを採用しています。たとえば、少なくともいくつかの操作を認識するために、迅速で不正確な型推論を行うことができます。一部のJITコンパイラは関数スコープでのみ動作するため(したがって、メソッドJITコンパイラと呼ばれることもあります)、コードスニペットをあまり活用できない可能性があります(JITコンパイラのトレースが非常に人気がある理由の1つ)。それにもかかわらず、それらは存在します-例は、MozillaのJavaScriptエンジンの最新リビジョンであるIon Monkeyですが、JITのトレースからもインスピレーションを得ているようです。また、常に有効ではない最適化の追加(たとえば、後で変更される可能性のある関数のインライン化)を挿入し、それらが間違ったときに削除することもできます。
他のすべてが失敗した場合、インタープリターが行うことを実行し、オブジェクトをボックス化し、それらへのポインターを使用し、データにタグを付け、タグに基づいてコードを選択できます。しかし、これは非常に非効率的であり、JITコンパイラーの全体的な目的はそのオーバーヘッドを取り除くことであるため、合理的な代替手段がない場合(またはまだウォーミングアップ中)にのみそれを行います。