24

したがって、たとえば、PythonとJavaにはVMがありますが、CとHaskellにはありません。(私が間違っている場合は私を訂正してください)

両側の言語が何であるかを考えると、理由がわかりません。Javaは多くの点で静的ですが、Haskellは多くの動的機能を提供します。

4

8 に答える 8

28

静的と動的の関係はありません。

むしろ、基盤となるハードウェアプラットフォームから独立することです(「一度構築すれば、どこでも実行できる」-理論的には...)

実際、それは言語とも関係ありません。JVMのバイトコードを生成するCコンパイラを作成できます。x86マシンコードを生成するJavaコンパイラを作成できます。

于 2011-01-09T18:08:07.450 に答える
22

少しの間VMのことを忘れて(以下に戻ります、約束します)、この重要な事実から始めましょう:

Cにはガベージコレクションがありません。

ガベージコレクションを提供する言語には、それを実行するある種の「ランタイム」 / runtime-environment/thingが必要です。

そのため、Python、Java、Haskellには「ランタイム」が必要であり、Cは必要ありませんが、ネイティブコードに直接コンパイルできます。

psycoはPythonコードをマシンコードにコンパイルするPythonオプティマイザーでしたが、そのマシンコードの多くは、、などのC-Pythonのランタイム関数の呼び出しで構成されていたPyImport_AddModuleことに注意してくださいPyImport_GetModuleDict

Haskell / GHCは、psycoでコンパイルされたPythonと同様のボートに乗っています。Intは単純なマシン命令として追加されますが、オブジェクトなどを割り当てるより複雑なものはランタイムを呼び出します。

ほかに何か?

Cには「例外」はありません

Cに例外を追加する場合、生成されたマシンコードは、すべての関数およびすべての関数呼び出しに対していくつかの処理を実行する必要があります。

次に「クロージャ」も追加すると、さらに多くのものが追加されます。

これで、この定型的なマシンコードをすべての関数で繰り返す代わりに、サブプロシージャを呼び出して、のような必要な処理を実行することができますPyErr_Occurred

したがって、基本的に、すべての元のソース行は、いくつかの関数へのいくつかの呼び出しと、より小さな固有の部分にマップされます。

しかし、元のソースコード行ごとに多くのことを行っている限り、なぜマシンコードに煩わされるのでしょうか。

これがアイデアです(ところで、このアイデアを「仮想マシン」と呼びましょう)。

Pythonコードを表現してみましょう。例は次のとおりです。

def has_no_letters(text):
  return text.upper() == text.lower()

メモリ内のデータ構造として、たとえば次のようになります。

{ 'func_name': 'has_no_letters',
  'num_args': 1,
  'kwargs': [],
  'codez': [
    ('get_attr', 'tmp_a', 'arg_0', 'upper'),  # tmp_a = arg_0.upper
    ('func_call', 'tmp_b', 'tmp_a', []),  # tmp_b = tmp_a() # tmp_b = arg_0.upper()
    ('get_attr', 'tmp_c', 'arg_0', 'lower'),
    ('func_call', 'tmp_d', 'tmp_c', []),
    ('get_global', 'tmp_e', '=='),
    ('func_call', 'tmp_f', 'tmp_e', ['tmp_b', 'tmp_d']),
    ('return', 'tmp_f'),
  ]
}

それでは、このメモリ内データ構造を実行するインタプリタを作成しましょう。

テキストインタプリタからの直接変換に対するこれの利点について説明し、次にマシンコードへのコンパイルに対する利点について説明しましょう。

テキスト通訳者からの直接に対するVMの利点

  • VMシステムは、コードを実行する前にすべての構文エラーを表示します。
  • ループを評価する場合、VMシステムは実行するたびにソースコードを解析しません。
    • テキストからの直接インタプリタよりもVMを高速化します。
    • したがって、直接インタープリターは、変数名が長いと実行速度が遅くなり、変数名が短いと実行速度が速くなります。これにより、人々は次のようなくだらない数学者スタイルのコードを書くようになります。wt(f, d(o, e), s) <= th(i, s) + cr(a, p * d + o)

マシンコードへのコンパイルに対するVMの利点

  • プログラムを記述するメモリ内のデータ構造、つまり「VMコード」は、元のコード行ごとに同じことを何度も繰り返す定型的な完全なマシンコードよりもはるかにコンパクトになる可能性があります。これにより、メモリからフェッチする必要のある「命令」が少なくなるため、VMシステムの実行速度が向上します。
  • VMの作成は、コードをマシン化するコンパイラを作成するよりもはるかに簡単です。アセンブリ/マシンコードを知らなくても、おそらく今これを行うことができます。
于 2011-01-10T23:28:55.800 に答える
4

VM(仮想マシン)は、実際には、言語の実装を作成する際の複雑さを回避するための言語設計者向けのツールです。

基本的には、仮想コンピューターの仕様と、そのコンピューターの各部分が互いにどのように相互作用するかです。この仕様では、実際の言語で使用できるかどうかに関係なく、いくつかの仮定をコーディングできます。

この仕様では、通常、プロセッサ/プロセッサの動作、メモリの動作、可能な読み取り/書き込みバリアなど、およびそれと対話するためのより単純なアセンブリ言語を定義します。

最終的な言語は通常、作成しているテキストファイルからそのマシン用に作成された表現に変換(コンパイル)されます。

これにはいくつかの利点があります。

  • 言語を特定のハードウェアアーキテクチャから切り離します
  • 通常、何が起こるかを制御できます
  • さまざまな人がさまざまなアーキテクチャに移植できます
  • コードを最適化するための詳細情報があります

クールさの要素もあります。仮想マシンを作成したようです:)。

于 2011-01-09T18:16:36.970 に答える
4

仮想マシンは基本的に、マシンコードに近い言語を解釈するインタプリタです。実マシンが実マシンコードを解釈するとき、仮想マシンは作成されたマシンコードを解釈します。一部のVMは、実際のコンピューターのマシンコードを解釈します。これらはエミュレーターと呼ばれます。

単純なアセンブリのような言語のインタプリタを作成してから、完全な高級言語のインタプリタを作成する方が簡単です。その上、多くの高水準コード構造は、多くの場合、いくつかの基本原則に対する単なる構文糖衣です。したがって、これらの複雑な概念をすべて単純なVM言語に変換するコンパイラーを作成する方が簡単なので、複雑なインタープリターを作成する必要はありませんが、単純なインタープリター(VM)を使用することができます。そして、VMを最適化するためのより多くの時間があります。

これが基本的に、最近のほとんどの言語(実際のマシンコードにコンパイルされない)の実装方法です。

インタプリタ(VM)とコンパイラは別々のプログラム(javaとなどjavac)にすることも、1つのプログラム(RubyやPythonなど)にすることもできます。

于 2011-01-09T19:52:17.783 に答える
3

仮想マシンに関するウィキペディアのエントリから:

「仮想マシン(VM)は、物理マシンのようにプログラムを実行するマシン(つまりコンピューター)のソフトウェア実装です。」

仮想マシンの最大の利点は、理論的には、コードの移植性です。「一度書けば、どこでも実行できます」

おそらく、仮想マシンの最もよく知られている例は、元々Javaコードを実行するように設計されたJVMですが、現在ではClojureやScalaなどの言語にもますます使用されています。

動的言語に固有のことは何もありません。つまり、VMが必要です。ただし、VM上に構築できるインタプリタが必要です。

于 2011-01-09T18:12:27.043 に答える
2

「必要」はありません。これらの言語はいずれも、特定のアーキテクチャで言語のセマンティクスを実装するためにマシンコードを直接出力するコンパイラを提供します。

仮想マシンのアイデアは、すべての異なるハードウェアおよびソフトウェアメーカー間のアーキテクチャの違いを抽象化して、開発者が1台のマシンに書き込むことができるようにすることです。

于 2011-01-09T18:10:02.817 に答える
2

JavaとPythonは、プラットフォームの独立性を維持する方法でコンパイルできます。これはC#にも当てはまります。利点は、VMが、このほとんど強く型付けされたバイトコードを、比較的低いオーバーヘッドで非常に優れたプラットフォーム固有のコードに変換できることです。Javaは「一度ビルドすればどこでも実行できる」ことを目的としているため、JVMが作成されました。

于 2011-01-09T18:10:30.610 に答える
2

プログラミング言語を作成したと想像してみてください。言語のセマンティクスを理解し、優れた構文を開発しました。

ただし、テキスト表現だけでは不十分です。プログラムの実行時にテキストを何度も解析する必要があるのは非効率的であるため、メモリ内のバイナリ表現を追加するのは自然なことです。これをカスタムメモリマネージャーと組み合わせると、基本的にVMが得られます。

ここで、追加のポイントとして、メモリ内表現とランタイムローダーをシリアル化するためのバイトコード形式を開発するか、スクリプト言語の方法を使いたい場合はeval()関数を開発します。

グランドフィナーレには、JITを追加します。

于 2011-01-09T21:58:35.720 に答える