Привет,
Ruvim Pinka wrote:
> Привет!
>
> On 12/21/06, Dmitry Yakimov <
[hidden email]> wrote:
>
>>> Т.е., основная его цель — это замена (альтернатива) обычному оптимизатору?
>>>
>> Да
>>
>
> Предполагается же, что он сможет дать лучший результат?
Более того утверждается это.
Зная информацию о форт словах мы можем провести макроподстановку и
constant folding прямо в форт коде, и это будет платформонезависимо.
А также произвести другие платформонезависимые оптимизации, например
замена медленного DO LOOP на быстрый и естественный для машины FOR NEXT.
А зная стековую нотацию всех слов (достаточно знать стековую нотацию
примитивов и winapi слов чтобы рассчитать стековую нотацию
высокоуровневых слов) мы можем разложить не верхние два элемента стека
по регистрам, как сейчас в SPF, а 4, 5, 6, сколько нужно.
Смотри какие оптимизации можно провести на уровне платфоронезависимого
форта:
Оптимизации (в таком порядке):
0. Сделаем макроподстановку вызываемых слов.
Уровень вложения и размер подставляемого слова.
1. Constant propagation
Константы переводим в литералы, затем применяем Constant folding
2. Constant folding
10 10 * -> 100
3. Оптимизация деления на константу.
Заменит деление на константы сдвигами и умножениями, например:
x/9 -> (x*57)>>9
x/2 -> x << 1
4. Dead code elimination
0 IF THEN или BEGIN 0 WHILE ... REPEAT
5. Замена циклов DO LOOP где не используется I J циклом FOR NEXT
(LEAVE эмулируется R> DROP)
6. Loop unrolling.
До определенного предела делаем LOOP unrolling, если в цикле не
используется I J и параметры цикла константы
Data flow analysis
7. Исключим циклы типа SWAP SWAP, OVER OVER 2DROP и т.п.
8. Сделаем замену более оптимальными конструкциями, например
OVER OVER NIP -> DUP
\ если справа примитивы!
DUP + -> 2*
SWAP OVER -> TUCK
>R DROP R> -> NIP
ROT ROT -> -ROT
DROP DROP -> 2DROP
OVER OVER -> 2DUP
>R SWAP R> SWAP -> ROT
>R DUP R> SWAP -> OVER
>R ROT ROT R> ROT ROT -> 2SWAP
2>R 2DUP 2R> 2SWAP -> 2OVER
NEGATE + -> -
XOR 0= -> =
DUP >R @ + R> ! -> +!
DUP 0< -> S>D
8. По возможности объединим литералы в группы, это даст более оптимальный
код на стадии щелевого оптимизатора
Даже если после всего этого не делать распределение регистров а просто
сделать тупую макроподстановку примитивов, это уже будет неплохо, и это
опять будет почти платформо независимо.
> — т.к. в
> "руках" у него целиком определение в шитом коде, которое он
> разворачивает и оптимизирует, в отличии от подстановщика, который
> имеет только начало определения (целиком на последнем шаге только), и
> оно в маш-коде, и с ограничениями из-за ветвлений (когда есть
> неразрешенные ссылки вперед и т.п.). Вообще, это вопрос к Михаилу,
> сильно ли мешают оптимизатору перечисленные особенности.
>
Это дополнительные трудности, типа декомпиляции асм кода, что сейчас
делается, и компиляция его обратно в асм код.
> [...]
>
>> Да, но кто будет сразу портировать JIT? Наверное сначала просто
>> портируют быстренько 10 примитивов и VM чтобы запустить и работало, и
>> надо ли JIT портировать на новую платформу - еще встанет вопрос - нужен
>> ли он там или скорости достаточно.
>>
>
> понял :)
>
> [...]
>
>> Например мы в ядре определили:
>>
>> : R@ R> R> DUP SWAP >R SWAP >R ;
>>
>> (это из наметков к spf5 )
>>
>> А потом когда мы делаем полноценную форт систему из ядра мы делаем так:
>> ?CODE R@ \ 94
>> LEA EBP, -4 [EBP]
>> MOV [EBP], EAX
>> MOV EAX, 4 [ESP]
>> RET
>> END-CODE
>>
>
> А перед использованием этого слова в ядро еще надо загрузить ассемблер
> (и допустимо загрузить его во временное хранилище).
>
Это будет при сборке форт системы и там асм точно будет.
>
>> где слово ?CODE компилирует R@ и заменяет им существующий R@ в
>> компилируемом кодофайле.
>>
>
> Т.е., как я понимаю: оно патчит существующий бинарный образ; или же, в
> процессе JIT-компиляции (даже лучше сказать, трансляции), берется
> новое определение вместо старого.
>
> А чем это лучше новой целевой сборки ядра из исходников, в процессе
> которой вместо высокоуровневого определения слова "R@" используется
> низкоуровневое?
>
Тем что у нас тогда будет два R@, и одно из них медленное, потому что
старое точно будет где-то использоваться.
Вопрос в том как элегантно заменить слово. Если у нас прямой шитый, то
next может выглядеть так:
_NEXT:
lodsd
jmp eax
_EXIT:
pop esi
lodsd
jmp eax
IP находится в ESI. (это все на уровне предположим, регистры не факт что
будут именно такими).
Но надо учесть что нам нужна быстрая VM.
То есть по адресу слова находится jmp ENTER
Ну мы заменим его на JMP R@ в нашем примере с R@, а оптимизатор поймет
что если первая команда примитива JMP ... то значит это редирект на
другой примитив.
Best Regards,
Dmitry Yakimov.