Отключение JIT и управление потоком кода в MSIL (собственной виртуальной машине)

StackOverflow https://stackoverflow.com/questions/618909

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пишу свой собственный скриптовый язык на C #, с некоторыми функциями, которые мне нравятся, и я решил использовать MSIL в качестве байт-кода вывода (Reflection.Emit довольно полезен, и мне не нужно придумывать другой байт-код).Он работает, выдает исполняемый файл, который можно запустить (даже декомпилированный с помощью Reflector :)) и работает довольно быстро.

Но - я хочу запустить несколько "процессов" в одном процессе + одном потоке и контролировать назначенное им процессорное время вручную (также реализовать гораздо более надежный IPC, предлагаемый .NET framework), Есть ли какой-нибудь способ полностью отключить JIT и создать собственную виртуальную машину, используя пошаговую инструкцию за инструкцией.NET framework (и контролировать использование памяти и т.д.), Без необходимости писать что-либо самостоятельно, или для достижения этого я должен написать всю интерпретацию MSIL целиком?

ПРАВКА 1):Я знаю, что интерпретация IL - не самая быстрая вещь во вселенной :)

ПРАВКА 2):Чтобы уточнить - я хочу, чтобы моя виртуальная машина была своего рода "операционной системой" - она получает некоторое процессорное время и делит его между процессами, контролирует выделение памяти для них и так далее.Это не обязательно должно быть ни быстрым, ни эффективным, это просто подтверждение концепции для некоторых моих экспериментов.Мне не нужно реализовывать это на уровне обработки каждой инструкции - если это должно быть сделано .NET, я не буду возражать, я просто хочу сказать :выполните первую инструкцию и подождите, пока я не скажу вам, что делать дальше.

ПРАВКА 3):Я понял, что ICorDebug, возможно, может удовлетворить мои потребности, теперь рассматривая реализацию среды выполнения Mono.

Это было полезно?

Решение

Вы могли бы использовать Моно - Я считаю, что это позволяет интерпретировать IL вместо того, чтобы подменять его.Тот факт, что это открытый исходный код, означает (при условии лицензирования), что вы также должны иметь возможность изменять его в соответствии с вашими потребностями.

По общему признанию, Mono не обладает всеми функциональными возможностями .NET, но это мочь делайте все, что вам нужно.

Другие советы

Имейте в виду, что MSIL был разработан для анализа JIT-компилятором.Это не очень подходит для переводчика.Хорошим примером, возможно, является инструкция ADD.Он используется для добавления широкого спектра значений типа value:байт, короткий, int32, int64, ushort, uint32, uint64.Ваш компилятор знает, какой тип add требуется, но вы потеряете информацию об этом типе при генерации MSIL.

Теперь вам нужно найти его обратно во время выполнения, а это требует проверки типов значений в стеке оценки.Очень медленно.

Легко интерпретируемый IL содержит специальные инструкции ДОБАВЛЕНИЯ, такие как ADD8, ADD16 и т.д.

Реализация Microsoft среды выполнения Common Language Runtime имеет только одну систему выполнения - JIT.Mono, с другой стороны, поставляется как с JIT, так и с интерпретатором.

Я, однако, не до конца понимаю, что именно вы хотите заняться собой и что бы вы хотели оставить для реализации Microsoft:

Есть ли какой-нибудь способ полностью отключить JIT и создать собственную виртуальную машину?

и

...без необходимости писать что-либо самостоятельно, или для достижения этого я должен написать весь MSIL interpretate целиком?

это в некотором роде противоречит друг другу.

Если вы считаете, что можете написать лучшую систему выполнения, чем Microsoft JIT, вам придется написать ее с нуля.Однако имейте в виду, что как microsofts, так и monos JIT являются высокооптимизированными компиляторами. (Перестрелка на языке программирования)

Точное планирование процессорного времени для процессов операционной системы невозможно из пользовательского режима.Это задача операционной системы.

Идеей может быть некоторая реализация зеленых потоков, но это определенно тема для неуправляемого кода.Если это то, что вы хотите, взгляните на CLR hosting API.

Я бы посоветовал вам попробовать реализовать свой язык на CIL.В конце концов, он компилируется вплоть до raw x86.Если вас не волнует проверяемость, вы можете использовать указатели там, где это необходимо.

Одна вещь, которую вы могли бы рассмотреть, - это генерация кода в стиле конечного автомата.Позвольте мне объяснить, что я под этим подразумеваю.

Когда вы пишете методы генератора на C # с возвратом yield, метод компилируется во внутренний класс IEnumerator, который реализует конечный автомат.Код метода компилируется в логические блоки, которые завершаются инструкцией yield return или yield break, и каждый блок соответствует пронумерованному состоянию.Поскольку каждый возврат yield должен содержать значение, каждый блок заканчивается сохранением значения в локальном поле.Объект enumerator, чтобы сгенерировать свое следующее значение, вызывает метод, который состоит из гигантского оператора switch для текущего номера состояния, чтобы запустить текущий блок, затем изменяет состояние и возвращает значение локального поля.

Ваш язык сценариев мог бы генерировать свои методы в аналогичном стиле, где метод соответствует объекту конечного автомата, а виртуальная машина выделяет время, продвигая конечный автомат в течение отведенного времени.Несколько хитрых моментов в этом методе:реализовать такие вещи, как вызовы методов и блоки try / finally, сложнее, чем генерировать обычный MSIL.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top