質問

私はC#で、好きな機能を備えた独自のスクリプト言語を書いています。MSILを出力のバイトコードとして使用することを選択しました(Reflection.Emitは非常に便利で、別のバイトコードを考え出す必要はありません)。動作し、実行可能ファイルを出力します。実行可能(Reflectorで逆コンパイルすることもできます)。非常に高速です。

しかし、1つのプロセス+ 1つのスレッドで複数の「プロセス」を実行し、割り当てられたCPU時間を手動で制御したい(.NETフレームワークによって提供されるはるかに堅牢なIPCも実装したい)JITを完全に無効にする方法はありますか独自のVMを作成し、.NETフレームワークを使用して命令後の命令をステップ実行し(メモリ使用量などを制御します)、自分で何かを書く必要はありませんか、これを達成するにはMSILインタプリタ全体を書く必要がありますか?

編集1):ILの解釈は宇宙で最速のものではないことを知っています:

EDIT 2):明確にするために-VMをある種の「オペレーティングシステム」にしたい-CPU時間を取得してプロセス間で分割し、メモリ割り当てを制御するなど。高速で効果的である必要はありませんが、私の実験のいくつかの概念実証にすぎません。すべての命令を処理するレベルで実装する必要はありません-.NETでこれを行う必要がある場合、私はただ言いたいだけです:1つの命令をステップし、次のステップを指示するまで待ちます。

編集3):ICorDebugが私のニーズを達成できるかもしれないことに気づき、Monoのランタイムの実装を検討しています。

役に立ちましたか?

解決

Mono を使用できます-JITする代わりにILを解釈するオプションが許可されると思います。それがオープンソースであるという事実は、あなたがあなたのニーズに応じてそれを修正することができるべきであることを意味します(ライセンスの対象となります)。

Monoには.NETのすべての機能が搭載されているわけではありませんが、確かに-必要な機能はすべて 必要です。

他のヒント

MSILはJITコンパイラによって解析されるように設計されていることに注意してください。通訳にはあまり適していません。よい例は、おそらくADD命令です。バイト、ショート、int32、int64、ushort、uint32、uint64など、さまざまな値タイプの値を追加するために使用されます。コンパイラーはどのような種類の追加が必要かを知っていますが、MSILを生成するときにそのタイプ情報は失われます。

ここで、実行時にそれを見つける必要があり、評価スタック上の値のタイプを確認する必要があります。非常に遅い。

簡単に解釈できるILには、ADD8、ADD16などの専用のADD命令があります。

Microsoftの共通言語ランタイムの実装には、JITという実行システムが1つしかありません。一方、MonoにはJITとインタープリターの両方が付属しています。

ただし、自分が何をしたいのか、 Microsoftの実装に何を残したいのかを正確には理解していません:

  

JITを完全に無効にして独自のVMを作成する方法はありますか?

and

  

...自分で何かを書く必要なしに、またはこれを達成するために、MSILインタプリタ全体を書く必要がありますか?

は矛盾しています。

考えてみると、Microsoft JITよりも優れた実行システムを作成できます。最初から作成する必要があります。ただし、Microsoft JITとMonos JITの両方が高度に最適化されたコンパイラであることに注意してください。 (プログラミング言語の銃撃戦)

ユーザーモードからオペレーティングシステムプロセスのCPU時間を正確にスケジュールすることはできません。それがオペレーティングシステムのタスクです。

グリーンスレッドの実装の一部はアイデアかもしれませんが、それは間違いなくアンマネージコードのトピックです。それが必要な場合は、CLRホスティングAPIをご覧ください。

CILで言語を実装することをお勧めします。結局、それは生のx86にコンパイルされます。検証可能性を気にしない場合は、必要に応じてポインターを使用できます。

実行を検討できることの1つは、ステートマシンスタイルでコードを生成することです。これが何を意味するのか説明させてください。

C#でyield returnを使用してジェネレーターメソッドを記述すると、メソッドは、ステートマシンを実装する内部IEnumeratorクラスにコンパイルされます。メソッドのコードは、yield returnまたはyield breakステートメントで終了する論理ブロックにコンパイルされ、各ブロックは番号付き状態に対応します。各yield returnは値を提供する必要があるため、各ブロックはローカルフィールドに値を保存することで終了します。列挙子オブジェクトは、その次の値を生成するために、現在のブロックを実行するために現在の状態番号の巨大なswitchステートメントで構成されるメソッドを呼び出し、状態を進めてローカルフィールドの値を返します。

スクリプト言語は同様のスタイルでメソッドを生成できます。メソッドはステートマシンオブジェクトに対応し、VMは割り当てられた時間中にステートマシンを進めることで時間を割り当てます。このメソッドのいくつかのトリッキーな部分:メソッド呼び出しやtry / finallyブロックなどの実装は、ストレートMSILを生成するよりも困難です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top