суббота, 5 февраля 2011 г.

[prog] Пара трюков из реализации виртуальной машины Ovm для RTJS

В прошлый раз, когда я писал о Real-Time Java Specification, я дал ссылочку на список материалов от разработчиков виртуальной машины Ovm. За прошедшее время удалось прочесть большую статью A Real-Time Java Virtual Machine with Applications in Avionics оттуда. Сама статья для меня оказалась мало полезной и не очень интересной, т.к. ни виртуальными машинами для Java, ни Real-Time Java я не занимаюсь. Хотя любопытно было узнать, что под управлением этого Ovm люди умудрились запустить небольшой беспилотник. Но две вещи запомнились.

Во-первых, интересным образом разработчики Ovm поступили с многопоточностью и диспетчеризацией потоков. Поскольку Ovm работает на одной нити ОС, то всю диспетчеризацию Java-потоков Ovm делает сама. И для того, чтобы прерывать текущий поток и передавать управление другому потоку они сделали следующее: при трансляции Java-исходников просто напросто добавляются специальные вызовы в код (называемые Poll Check-ами). Т.е. если изначально программист написал что-то вроде:

void someMethod() {
   ...
   while(...) {
      ...
   }
}

То во время трансляции он будет преобразован в:

void someMethod() {
   POOLCHECK();
   ...
   while(...) {
      ...
      POOLCHECK();
   }
}

А внутри конструкции POOLCHEK происходит проверка необходимости передиспетчеризации нитей. Т.е. не внешний по отношению к коду диспетчер определяет, пора ли текущую нить прервать, а сама текущая нить время от времени озадачивается вопросом “А не пора ли дать управление кому-нибудь другому?”

Во-вторых, разработка Ovm шла еще до появления Java 1.5 с аннотациями, поэтому каких-то специальных средств связать метаинформацию с кодом у разработчиков Ovm не было. И они поступили очень остроумно, на мой взгляд – задействовали для этих целей инструкцию throws:

void storeCheck(VM_Address src, int offset, VM_Address tgt)
   throws PragmaNoPollcheck, PragmaNoBarriers, PragmaInline
{
   int sb = src.asInt() >>> blockShift;
   int tb = tgt.asInt() >>> blockShift;
   if (sb != tb) storeCheckSlow(sb, tb);
}

Здесь PragmaNoPollcheck, PragmaNoBarriers и PragmaInline – это не имена исключений, которые могут выбрасываться из метода, а инструкции для Ovm-овского компилятора.

Забавный подход. Который демонстрирует, что любые штатные возможности могут использованны самым непредсказуемым образом (здесь я с ностальгией вспоминаю игрушку Lode Runner, реализованную на алфавитно-цифровых дисплеях Robotron 1715).

Комментариев нет: