Чому VM повинні бути "стековими машинами" або "реєструвати машини" тощо?


48

(Це надзвичайно новачок-питання).

Я трохи вивчав віртуальні машини.

Виявляється, багато з них розроблені дуже схоже на фізичні або теоретичні комп'ютери.

Я читав, що, наприклад, JVM - це "стекова машина". Що це означає (і виправте мене, якщо я помиляюся) - це те, що він зберігає всю його "тимчасову пам'ять" на стеці і робить операції над цим стеком для всіх його опкодів.

Наприклад, вихідний код 2 + 3буде переведений в байт-код, подібний до:

push 2
push 3
add

Моє запитання таке:

JVM, ймовірно, записуються за допомогою C / C ++ тощо. Якщо так, то чому JVM не виконує такий код C: 2 + 3..? Я маю на увазі, для чого потрібен стек або в інших регістрах ВМ - як у фізичному комп'ютері?

Про все це піклується основний фізичний процесор. Чому письменники VM просто не виконують інтерпретований байт-код із "звичайними" інструкціями на мові, на якій запрограмований ВМ?

Чому VM повинні емулювати обладнання, коли фактичне обладнання вже робить це для нас?

Знову ж таки, дуже новичок. Спасибі за вашу допомогу


5
Чи розглядали ви , що НЕ віртуальні машини на основі?

5
@MichaelT Ви маєте на увазі фізичні машини?
Авів Кон

Звичайно, більшість VMS Javascript не є стековими машинами та не реєструють машини - V8 / IonMonkey / Chakra / тощо - це віЗМ, які реалізують Javascript. "VM" - це лише перекладач або компілятор JIT, який може реалізувати будь-яку мову, яку бажає дизайнер.
Біллі ONeal

@BillyONeal Так, наприклад, якщо я пишу VM на якійсь мові і пишу це на C: VM аналізує рядок байт-коду "print" привіт "і виконує printf("hi");: чи вважається це віртуальний комп'ютер? Він не має "стека" або "регістрів" і нічого іншого.
Авів Кон

@Prog: Так, це правильно.
Біллі ONeal

Відповіді:


51

Машині, віртуальній чи ні, потрібна модель обчислення, яка описує, як проводиться обчислення на ній. За визначенням, як тільки він обчислює, він реалізує деяку модель обчислення. Тоді питання: яку модель нам вибрати для нашого VM? Фізичні машини обмежуються тим, що можна ефективно та ефективно зробити апаратними засобами. Але, як зазначаєте, віртуальні машини не мають таких обмежень, вони визначаються в програмному забезпеченні, використовуючи довільно мови високого рівня.

Насправді є віртуальні машини на високому рівні, як ви описуєте. Їх називають мовами програмування . Наприклад, стандарт C присвячує основну частину своїх сторінок визначенню моделі для так званої "абстрактної машини C", яка описує, як поводяться програми C, а також розширенням (як би правило) як відповідний компілятор C (або інтерпретатор) повинні поводитися.

Звичайно, ми зазвичай не називаємо це віртуальною машиною. Зазвичай VM означає, що означає щось нижчий рівень, ближчий до апаратного, не призначений для прямого запрограмування, розроблений для ефективного виконання. Цей зміщення вибору означає, що те, що приймає компонований код високого рівня (наприклад, те, що ви описуєте), не вважатиметься VM, оскільки виконується код високого рівня.

Але для досягнення суті, ось декілька причин зробити VM (наприклад, щось націлене на компілятор байт-коду) на базі регістра або тому подібне. Машини для складання та реєстрації надзвичайно прості. Існує послідовність інструкцій, деякий стан та семантика для кожної інструкції (функція State -> State). Без складних скорочень дерев, без пріоритету оператора. Проаналізувати, проаналізувати та виконати це дуже просто, оскільки це мінімальна мова (синтаксичний цукор збирається далеко) і призначена для машинного читання, а не для читання людиною.

На противагу цьому, розбір навіть найпростіших мов, схожих на С, є досить важким, і його виконання вимагає нелокальних аналізів, таких як перевірка та розповсюдження типів, усунення перевантажень, підтримка таблиці символів, вирішення ідентифікаторів рядків , перетворення лінійного тексту в AST, керований пріоритетом , і так далі. Він ґрунтується на концепціях, які є природними для людини, але повинні бути ретельно спроектовані машинами.

Наприклад, байт-код JVM випромінюється javac. Він практично ніколи не повинен читати чи писати людиною, тому природно орієнтувати його на споживання машинами. Якщо ви оптимізували його для людей, віртуальна машина буде тільки при кожному запуску читати код, аналізувати його, аналізувати це, а потім перетворити його в проміжне представлення , що нагадує така модель спрощеної машини в будь-якому випадку . Може добре вирізати середнього чоловіка.


Отже, що ви говорите, це те, що компіляція всього до інструкцій на стеці (тобто System.out.println("hi");компілюється в якусь інструкцію на стеку, int a = 7збирається в інструкцію про стек тощо) робить виконання програми простою та ефективнішою?
Авів Кон

2
@Prog В основному, так. Але не тільки виконання, а й аналіз. Все, що робиться програмно.

І все-таки я не розумію, для чого 2 + 3складається push 2 push 3 add. addКрок в кінці виконується з допомогою віртуальної машини Java в будь-якому випадку, запустивши код C 2 + 3. Немає іншого способу для програмістів JVM зробити це. Чому б не скомпілювати його 2 + 3, а JVM просто виконати код С 2 + 3(припускаючи, що він написаний на С) відразу?
Авів Кон

@Prog Автор JVM не може просто записати 2 + 3у вихідний код JVM, оскільки JVM повинен працювати з будь-якою програмою, виконуючи будь-які операції в будь-якому порядку. Побудова вихідного коду C та віднесення до реалізації С просто підштовхує ту саму проблему до реалізації C (і це не може бути легко, не кажучи вже про ефективніше). Повинна бути якась структура даних, яка описує програму, щоб її можна було інтерпретувати та компілювати JIT, а "людський читаний вихідний код" - це жахливий вибір структури даних з причин, викладених вище.

7
@Prog Ви здаєтеся занадто зосередженими на конкретному випадку 2 + 3. А що a + b? Тоді значення, які потрібно додати, не надходять i.argument{1,2}, вони завантажуються з локальних змінних. Про що frobnicate(x[i]) + (Foo.bar() * 2)? Використовуючи цю конструкцію, існує лише одна addоперація (для int), і вона працює незалежно від того, як були обчислені додатки. Плюс до цього, інструкція, що додає лише цілі літерали, була б безглуздою: її результат також міг бути попередньо обчислений (тобто замість add(2,3)цього повинен бути push(5)).

20

Ця відповідь зосереджена на JVM, але насправді вона стосується будь-якої ВМ.

Чому VM повинні емулювати обладнання, коли фактичне обладнання вже робить це для нас?

Вони цього не роблять, але це робить VM набагато простішим і портативнішим: Віртуальний комп'ютер, який емулює апаратне забезпечення, може використовувати ту саму обчислювальну модель, що і будь-який апаратний процесор.

Зокрема, JVM був побудований з урахуванням портативності, насправді він був побудований так, що він навіть міг бути реалізований у апаратному забезпеченні (це може бути важко повірити сьогодні, але походження Java було у вбудованому світі - конкретно, контролери інтерактивного телебачення ).

Якщо у вас є така мета, бажано, щоб VM працював якомога ближче до фізичної машини, оскільки переклад на фактичний машинний код стає простішим і тим самим швидшим. Після того, як у вас є опкоди VM, теоретично все, що вам потрібно зробити, - це перекласти на опкоди центрального процесора, на яких програма фактично працює. На практиці це не так просто.

Я маю на увазі, для чого потрібен стек або в інших регістрах ВМ - як у фізичному комп'ютері?

Використання моделі віртуальної машини на основі стека має перевагу в тому, що її можна легко перенести як на регістри, так і на стеки, тоді як навпаки це не обов'язково вірно. Віртуальний комп'ютер на основі реєстру повинен робити припущення щодо кількості регістрів, розміру регістрів тощо. У машині стеку такі припущення не потрібні.

Про все це піклується основний фізичний процесор. Чому письменники VM просто не виконують інтерпретований байт-код із "звичайними" інструкціями на мові, на якій запрограмований ВМ?

Ну, ось що роблять такі віртуальні машини, вони інтерпретують байт-код. Навіть JVM насправді робить це, принаймні до того, як починає JIT (саме вчасно): він інтерпретує байтові коди та виконує висловлювання мовою, на якій був написаний JVM (як правило, C або C ++, але є навіть один написаний в JavaScript, Doppio ). Однак зауважте, що навіть такі висловлювання були переведені машинним кодом компілятором і насправді дуже схожі на те, що виробляє компілятор Java, а саме вони використовують регістри та стек для виконання своєї роботи. Зауважте, що використання мов "інтерпретована" проти "компільована" на цей момент стає дещо розмитим .


Звичайно, все, що може бути реалізовано в програмному забезпеченні, може бути реалізовано апаратно. Крім того, JVM на даний момент (точка доступу) є компілятором JIT - він не виконує операції мовою, на якій був написаний JVM. Якби це було, Java би виконувала жахливо і ніде не була б такою життєздатною платформою, як це є сьогодні. . (Чорт, більшість реалізацій Javascript були б швидшими)
Біллі ONeal

2
@BillyONeal "Замість того, щоб компілювати метод за методом, саме вчасно, Java HotSpot VM негайно запускає програму за допомогою інтерпретатора та аналізує код під час запуску для виявлення критичних гарячих точок у програмі. Потім він фокусує увагу глобальний оптимізатор нативного коду на гарячих точках ", цитується з oracle.com/technetwork/java/whitepaper-135217.html#2 , розділ" Виявлення гарячих точок "
miraculixx

Так. "Оптимізатор нативного коду" == компіляція JIT. Існує фаза перекладача коду, який, здається, не є "гарячим", щоб уникнути рідко використовуваних речей JITing. Але це не означає, що JITing взагалі не робиться.
Біллі ONeal

Дякую за відповідь. Що я зібрав з вашої відповіді, це те, що причини емуляції апаратних засобів у віртуальному вікні (він також має "стеки" або "регістри" і т. Д.) Тому, що це спрощує згодом компіляцію байт-коду або вихідного коду до фактичного машинного коду фізичний процесор. Однак, окрім цього - чи є щось, що можна отримати від емуляції апаратних засобів у VM? Я досі не розумію, чому хтось, хто розробляє VM, міг би думати про "стек-машину" або "реєструвати машину" і т.д., коли насправді ми говоримо про програмне забезпечення. Я щось пропускаю?
Авів Кон

@Prog Добре, у вас мова програмування, скажімо X. Як ви будете запускати її програми? Ви можете інтерпретувати джерело або компілювати його до машинного коду, або компілювати його в якийсь проміжний код. Тепер у вас є інша мова програмування, Y, і ви хочете реалізувати її за допомогою X. Якщо обидві реалізації інтерпретатора, у вас буде інтерпретатор Y працювати на інтерпретаторі X, і це буде дуже повільно.
18446744073709551615

11

Чому VM повинні бути "стековими машинами" або "реєструвати машини" тощо?

Вони не. Якщо вам потрібна віртуальна машина, це може бути все, що завгодно.

Існуючі віртуальні машини з'явилися як рішення таких ситуацій, як: Дійсно геніальна ідея прийшла мені в голову, я винайшов нову мову програмування! Але я повинен генерувати код. (Яке нудне завдання!) Але я не хочу генерувати код i8086, оскільки він некрасивий, і я не хочу генерувати код 68k, тому що всі інші використовують Intel. Також є VAX, але в мене немає ні VAX, ні комп’ютера, ні книги VAX. Тому я буду генерувати код для якогось процесора, який фізично не існує, і реалізувати цей процесор у програмному забезпеченні. Специфікація цього ВМ складе главу моєї дипломної роботи. Теоретично можна буде компілювати його до рідного коду будь-якого процесора, але це не я.

З іншого боку, позначення типу "2 + 3", ймовірно, не будуть використовуватися ВМ в осяжному майбутньому, оскільки це передбачає зробити багато перетворень до того, як щось може бути виконане.


Дякую за відповідь. Тож, що я зібрав з вашої відповіді, полягає в тому, що мотивація до створення VM, що імітує фізичні процесори, полягає в тому, що це спрощує подальшу реалізацію компіляторів, які компілюють у фактичний машинний код. Але крім цього - чи є якісь переваги для проектування VM з точки зору "стекової машини" або "машини реєстрації" тощо?
Авів Кон

1
Регістри вимагають алгоритмів розподілу регістрів, які потребують як теорії, так і налагодження. Машина стека (у тому числі нульовий операнд) може просто розмістити дані в стеку. Інструкція OTOH зазвичай реалізує обмежену кількість регістрів, а не стек змінних розмірів. Таким чином, стеки простіші для програмного забезпечення, регістри простіші для апаратних засобів і, можливо, тому трохи швидші.
18446744073709551615

-2

Щоб відповісти на актуальне запитання. Термін "віртуальна МАШИНА" означає, що ВСЕ програмне забезпечення та обладнання моделюються / емулюються. Якщо ви використовуєте базове програмне забезпечення / обладнання для виконання інструкцій, у вас немає VM, у вас є компілятор / інтерпретатор.


це лише твоя думка, чи ти можеш якось підкріпити це?
гнат

@Kyrelel - це неправда. "ВСЕ" апаратне забезпечення імітується в "системному" або "повному" VM. Не всі віртуальні машини заповнені. Наприклад, BSD VM шар має назву "віртуальна машина", незважаючи на те, що обладнання там не емульовано.
Netch

Я не думаю, що питання стосується термінології, але чому віртуальні машини реалізують функціонал, який, здавалося б, вже обробляється фактичним обладнанням
Ryan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.