Как работает виртуальная машина?

Asked
Viewd5319

18

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

С той оговоркой, что я это сделал, меня сбивает с толку то, что многие нескомпилированные языки допускают использование переменных с «либеральными» системами типов. Например, в Python я могу написать следующее:

 x = "Hello world!"
x = 2**1000
 

Строки и большие целые числа совершенно не связаны и занимают разное количество места в памяти, так как же можно представить этот код в среде на основе стека? Что именно здесь происходит? Указывает ли x на новое место в стеке, а старые строковые данные остаются без ссылок? Эти языки не используют стек? Если нет, то как они представляют переменные внутри?

  • Связанный вопрос: http://stackoverflow.com/questions/688803/how-does-a-register-based-virtual-machine-work

    lothar29 мая 2009, 21:18

5 ответов

7

Вероятно, ваш вопрос должен быть озаглавлен как «Как работают динамические языки ?».

Все просто, они хранят информацию о типе переменной вместе с ней в памяти. И это делается не только в интерпретируемых или JIT-компилируемых языках, но и в языках с исходной компиляцией, таких как Objective-C.

  • Ага, понятно. Но что происходит во время переназначения? Если новые данные больше старых, где они размещаются и что становится со старыми данными?

    Martin29 мая 2009, 21:10
  • Фактическое содержимое объекта может быть сохранено в другом месте, и только ссылка будет сохранена на месте. Существует множество методов реализации динамического языка. Что происходит на самом деле, зависит от конкретной реализации вашего языка.

    Mehrdad Afshari29 мая 2009, 21:12
  • верно ... вводится значение, а не переменная.

    sean riley29 мая 2009, 22:25
1

Ключ ко многим из того, «как виртуальные машины обрабатывают такие переменные», на самом деле сводится к метаданным ... Сохраненная, а затем обновленная метаинформация дает виртуальной машине гораздо лучшее представление о том, как выделить, а затем выполнить правильное дело с переменными.

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

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

1

Чтобы ответить на часть ваших вопросов, я бы порекомендовал технический доклад Google о python , где даны ответы на некоторые из ваших вопросов, касающихся динамических языков; например, что такое переменная (это не указатель и не ссылка, а в случае python метка).

2

ВМ не имеет ничего общего с языком. Любой язык может работать поверх виртуальной машины (виртуальная машина Java уже поддерживает сотни языков).

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

Это чрезвычайно низкий уровень, и во многих случаях он сильно основан на стеке - вместо регистров математические вычисления на машинном уровне относятся к местоположениям относительно текущего указателя стека.

При использовании обычных скомпилированных языков для одного шага требуется множество инструкций. a + может выглядеть так: «Захватите элемент из точки относительно указателя стека в регистр a, возьмите другой элемент в регистр b. Добавьте регистры a и b. поместите регистр a в место относительно указателя стека.

ВМ делает все это с помощью одной короткой инструкции, возможно, одного или двух байтов вместо 4 или 8 байтов НА ИНСТРУКЦИЮ на машинном языке (в зависимости от 32- или 64-разрядной архитектуры), что (предположение) должно означать около 16 или 32 байт x86 на 1-2 байта машинного кода. (Могу ошибаться, мой последний код для x86 был в эпоху 80286)

Microsoft использовала (вероятно, до сих пор использует) виртуальные машины в своих офисных продуктах, чтобы уменьшить объем кода.

Процедура создания кода виртуальной машины такая же, как и при создании машинного языка, только с другим типом процессора.

Виртуальные машины могут также реализовать собственные механизмы безопасности, восстановления после ошибок и памяти, которые очень тесно связаны с языком.

Некоторые из моих описаний здесь краткие и по памяти. Если вы хотите самостоятельно изучить определение байт-кода, это будет весело:

http://java.sun.com /docs/books/jvms/second_edition/html/Instructions2.doc.html

2

В большинстве языков виртуальных машин переменные могут быть концептуализированы как указатели (или ссылки) на память в куче, даже если сама переменная находится в стеке. Для языков с примитивными типами (например, int и bool в Java) они также могут храниться в стеке, но им нельзя назначать новые типы динамически.

Если игнорировать примитивные типы, все переменные, существующие в стеке, имеют свои фактические значения, хранящиеся в куче. Таким образом, если вы динамически переназначаете им значение, исходное значение теряется (и память очищается с помощью некоторого алгоритма сборки мусора), а новое значение выделяется в новом бите памяти.

  • Зачем вообще используется стек, если он содержит только указатели на кучу? Разве не было бы разумнее хранить указатели внутри себя и просто пропустить весь стековый подход?

    Martin30 мая 2009, 12:31