Согласование дизайна виртуальной машины с ее основным языком программирования

В качестве фона для побочного проекта я читал о различных проектах виртуальных машин, и JVM, конечно же, получила наибольшее количество прессы. Я также посмотрел на BEAM (Erlang), RH GHC (вроде, но не совсем VM) и некоторые реализации JavaScript. У Python также есть интерпретатор байт-кода, который, как я знаю, существует, но о котором я мало читал.

То, что я не нашел, является хорошим объяснением того, почему определенные варианты дизайна виртуальной машины делаются для конкретного языка. Мне особенно интересны варианты дизайна, которые бы подходили для параллельных и / или очень динамичных (Ruby, JavaScript, Lisp) языков.


Изменить: В ответ на комментарий с просьбой конкретности вот пример. JVM использует стек машины, а затем регистровую машину, которая была очень противоречивой, когда Ja была впервые введена. Оказалось, что инженеры, спроектировавшие JVM, сделали это с целью переносимости платформы, и преобразование стековой машины обратно в машину регистрации стало проще и эффективнее, чем преодоление несоответствия импеданса, когда было слишком много или слишком мало виртуальных регистров.

Вот еще один пример: для Хаскелла статья, которую нужно рассмотреть, - это реализация ленивых функциональных языков на стандартном оборудовании: G-машина Spineless Tagless. Это сильно отличается от любого другого типа ВМ, о котором я знаю. И на самом деле GHC (главная реализация Haskell) не запускается, а используется как промежуточный этап компиляции. Пейтон-Джонс перечисляет не менее 8 других виртуальных машин, которые не работают. Я хотел бы понять, почему некоторые виртуальные машины преуспевают там, где другие терпят неудачу.

3 ответа

Решение

Я отвечу на ваш вопрос с другой темы: что такое ВМ? ВМ - это всего лишь спецификация для "интерпретатора" языка более низкого уровня, чем исходный язык. Здесь я использую значение черного ящика для слова "переводчик". Мне все равно, как виртуальная машина реализована (как intetereter байт-кода, JIT-компилятор, что угодно). Если сформулировать это так, то с точки зрения дизайна виртуальная машина - не самое интересное, это язык низкого уровня.

Идеальный язык VM будет делать две вещи. Во-первых, это облегчит компиляцию исходного языка в него. И во-вторых, это также облегчит интерпретацию на целевой платформе (ах) (где, опять-таки, интерпретатор может быть реализован очень наивно или может быть действительно сложным JIT, таким как Hotspot или V8).

Очевидно, что существует напряжение между этими двумя желаемыми свойствами, но они более или менее образуют две конечные точки на линии, проходящей через пространство проектирования всех возможных виртуальных машин. (Или, возможно, более сложная форма, чем линия, потому что это не плоское евклидово пространство, но вы поняли идею). Если вы создадите свой язык виртуальной машины далеко за пределами этой линии, это будет не очень полезно. Это то, что ограничивает дизайн виртуальной машины: поместить ее куда-то в эту идеальную линию.

Эта линия также объясняет, почему виртуальные машины высокого уровня имеют тенденцию быть очень специфичными для языка, в то время как виртуальные машины низкого уровня более независимы от языка, но не предоставляют много услуг. Виртуальная машина высокого уровня по своей природе близка к исходному языку, что отличает его от других, разных исходных языков. Низкоуровневая виртуальная машина по своей природе близка к целевой платформе, таким образом, близко к концу платформы идеальных линий для многих языков, но эта низкоуровневая виртуальная машина также будет довольно далеко от конца, который легко компилировать до идеальной линии. большинство исходных языков.

Теперь, в более широком смысле, концептуально любой компилятор можно рассматривать как серию преобразований из исходного языка в промежуточные формы, которые сами по себе можно рассматривать как языки для виртуальных машин. Виртуальные машины для промежуточных языков могут никогда не быть построены, но они могут быть. Компилятор в конечном итоге выдает окончательную форму. И эта окончательная форма сама будет языком для ВМ. Мы можем назвать эту виртуальную машину "JVM", "V8"... или мы можем назвать эту виртуальную машину "x86", "ARM" и т. Д.

Надеюсь, это поможет.

Один из методов создания виртуальной машины - просто перейти по цепочке компиляции, превращая ваш исходный язык во все более и более низкоуровневые промежуточные языки. Как только вы обнаружите достаточно низкоуровневый язык, подходящий для плоского представления (т. Е. Тот, который можно сериализовать в последовательность "инструкций"), это в значительной степени ваша виртуальная машина. И ваш интерпретатор VM или JIT-компилятор просто продолжат цепочку преобразований с той точки, которую вы выбрали для сериализации.

Некоторые методы сериализации очень распространены - например, использование представления псевдостека для деревьев выражений (как в.NET CLR, которая вообще не является "реальной" машиной стека). В противном случае вы можете использовать SSA-форму для сериализации, как в LLVM, или просто 3-адресную виртуальную машину с бесконечным числом регистров (как в Dalvik). На самом деле не имеет значения, какой путь вы выберете, поскольку это всего лишь сериализация, и впоследствии она будет десериализована, чтобы продолжить ваш обычный способ компиляции.

Это немного другая история, если вы собираетесь немедленно интерпретировать код виртуальной машины, а не компилировать его. В настоящее время нет единого мнения о том, какие виртуальные машины лучше подходят для интерпретации. Обе виртуальные машины, основанные на стеке (или, я бы сказал, Forth), и на основе регистров оказались эффективными.

Я нашел эту книгу полезной. Здесь обсуждаются многие вопросы, о которых вы спрашиваете. (обратите внимание, я никоим образом не связан с Amazon, и я не продвигаю Amazon; просто это было самое простое место для ссылок).

http://rads.stackru.com/amzn/click/1852339691

Другие вопросы по тегам