Как стать автором
Обновить

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

Время на прочтение5 мин
Количество просмотров13K
Всего голосов 33: ↑30 и ↓3+27
Комментарии17

Комментарии 17

Какую версию Java-байткода вы поддерживаете? Java-6?

Как я понимаю, производительность вас сильно не волнует, если вы совсем от примитивных типов отказались?

Не очень понял, как транслируется вызов статического метода (invokestatic). Какой объект используется в качестве this?

Интерфейсы у вас есть в языке? Такие же, как в Java? Как у них устроена таблица виртуальных методов?
4*спасибо за вопрос. :)

Чёткой отсылки к номеру версии байткода в документации soot я не нашёл, но последний билд проекта — от 2012 года, что наводит на мысль, что явно не 8. Скорее 6, да.

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

Вызов статики пока не реализован, но проблем тут нет вообще. Есть два простых варианта. первый — генерировать для статики специальный класс, второй — тупо делать статические методы так же как обычные, держать для них синглтон инстанс this, и при кодогенерации запрещать доступ к полям this. Спасибо ещё раз за вопрос, заодно я, кажется, определился с реализацией. :)

Интерфейсы запроектированы. Реализация реально не дошла. Есть два варианта реализации. Первый. Предпочтительный. Реально все пойнтера виртуальной машины таскают с собой пойнтер на интерфейс, по которому и происходит обращение к vmt. Это позволит реализовать cast с заменой в пойнтере интерфейса на любой нужный. Дальше вызов по vmt[ordinal интерфейса]. Второй вариант совсем тупой — invokedynamic. Но он пока без полиморфизма. Что, впрочем, тоже решается легко — передавать сигнатуру вместо имени метода.
>> Надо сказать, что эти виртуальные машины изрядно, хотя и совершенно случайно, похожи.

>> Как эта часть устроена в JVM, я не знаю до сих пор

Гм…

>> К примеру, локально, в точке вызова, совершенно невозможно выяснить, объектный это вызов (первый параметр — this), или нет.

А в чём проблема?
В байткоде это всегда invokestatic, а метод и так знает, что он статический.

>> Чёткой отсылки к номеру версии байткода в документации soot я не нашёл, но последний билд проекта — от 2012 года

Currently, Soot can process code from the following sources:

— Java (bytecode and source code up to Java 7), including other languages that compile to Java bytecode, e.g. Scala


© http://sable.github.io/soot/#what-input-formats-does-soot-provide

Последний коммит — две недели назад: https://github.com/Sable/soot/graphs/commit-activity
О. Спасибо. А я уж было слегка грустил и задумывался, не переехать ли на ASM.

Про invoke — откровенно говоря, не помню деталей. Давно делал ту версию. Вполне возможно, что мне тупо не пришло в голову опереться на тип invoke.
Рад, что вы решили написать статью на Хабре. Приятно иметь возможность пообщаться с таким интересным человеком, так сказать, воочию.

Теперь по делу. Не считаете ли вы, что персистентную ОС с единым адресным пространством сегодня стоило бы разрабатывать без ВМ, а на основе ЯП с гарантиями защиты памяти типа Rust?
Спасибо на добром слове.

Ограничивать ОС одним ЯП, да ещё и не самым популярным — затея спорная. Да и гарантии защиты памяти даёт не сам язык, а среда исполнения+генератор кода. В Фантоме виртуальная машина самодостаточна с точки зрения обеспечения надёжности, но это же всё равно промежуточный этап — дальше будет генерация бинарного кода из байткода (JIT), и ВМ как таковая исчезнет, останется только в виде промежуточного представления программы.
Да, ограничиваться одним языком не стоит, тут вы правы. Просто смущает мысль о необходимости раздутой среды исполнения, похожей на JVM. Дело в том, что разработчики Rust продемонстрировали, что можно почти полностью отказаться от среды исполнения (как в C), но обеспечить безопасность памяти и параллелизма на основе статического анализа (при наличии соотв. системы типов, разумеется). Потому тут напрашивается какое-то подмножество LLVM-IR, над которым тоже можно было бы проводить подобные проверки. Т.е., по-сути, это та же ВМ, но с минимальной средой исполнения (только проверки границ массива, стека, ещё что-то, без чего нельзя обойтись).
Оно и в Яве давно так, интерпретатор почти уже не используется. Можно её вообще скомпилировать в бинарник (gcj, part of gcc compilers collection). Как таковая среда — это библиотека. Если она не нужна, можно получить сишный размер программы.
К сожалению, GCJ мертв. Из AOT компиляции для java байткода знаю только Excelsior JET
Жаль. Хороший был проект. А почему, известно? Люди ушли, или проблемы?
По моему мнению это связано с появлением проекта OpenJDK, куда устремились люди и средства корпораций. Посмотрите на даты, очень похоже на это.
НЛО прилетело и опубликовало эту надпись здесь
А какой именно поддержки?
НЛО прилетело и опубликовало эту надпись здесь
На уровне виртуальной машины это, вроде бы, большого смысла не имеет, там только проверка типов специфична. Вот раскрыть шаблон при генерации JIT — это интересно. Но нет, сейчас такого нет, потому что, для начала, пока нет JIT.
Не все так тривиально. Например, за invokedynamic там целая вселенная в runtime чтобы было производительно. Плюс есть всякие intrisics:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/classfile/vmSymbols.hpp#l581

Вообще, не совсем понятно зачем такое делать в практическом смысле? JVM имеет много уровней оптимизации в compile/runtime. И последние добавляемые в язык/байткод фичи тесно завязаны на runtime. Если ваш runtime отличается существенно, то и производительности не видать.

Далее, что насчет jmm? Java это прежде всего спецификация. Если вы хотите поддерживать java программы, нужно будет гарантировать и совместимость. А там есть очень нетривиальные вещи. Та же java memory model.

Не говорю, что это вам не по силам, но действительно ли это цель?
Задачей, очевидно, является не написание VM, а создание ОС с персистентной ортогональностью и виртуальной машиной в глобальной памяти. (Блекджеком и шахматами и поэтессами повеяло, да?)

С обычной явской VM я этот вес не подниму точно. С таким подходом — поднял до уровня proof of concept. То есть — пока оно себя оправдывает. Мне, кроме всего, важно понять ограничения и возможности подхода, а это хорошо делать с развязанными руками.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории