1. Си / Говнокод #25399

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    // https://github.com/ghc/ghc/blob/e204431e5a5e2fd16da52b04bda2798f16c51344/rts/Interpreter.c#L1184
    
            case bci_PUSH8: {
                int off = BCO_NEXT;
                Sp_subB(1);
                *(StgWord8*)Sp = *(StgWord8*)(Sp_plusB(off+1));
                goto nextInsn;
            }
    
            case bci_PUSH16: {
                int off = BCO_NEXT;
                Sp_subB(2);
                *(StgWord16*)Sp = *(StgWord16*)(Sp_plusB(off+2));
                goto nextInsn;
            }
    
            case bci_PUSH32: {
                int off = BCO_NEXT;
                Sp_subB(4);
                *(StgWord32*)Sp = *(StgWord32*)(Sp_plusB(off+4));
                goto nextInsn;
            }
    
            case bci_PUSH8_W: {
                int off = BCO_NEXT;
                *(StgWord*)(Sp_minusW(1)) = *(StgWord8*)(Sp_plusB(off));
                Sp_subW(1);
                goto nextInsn;
            }
    
            case bci_PUSH16_W: {
                int off = BCO_NEXT;
                *(StgWord*)(Sp_minusW(1)) = *(StgWord16*)(Sp_plusB(off));
                Sp_subW(1);
                goto nextInsn;
            }
    
            case bci_PUSH32_W: {
                int off = BCO_NEXT;
                *(StgWord*)(Sp_minusW(1)) = *(StgWord32*)(Sp_plusB(off));
                Sp_subW(1);
                goto nextInsn;
            }

    https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Interpreter

    > The linker lives in rts/Linker.c and is responsible for handling runtime loading of code into a Haskell process. This is something of a big blob of unpleasant code, and see DynamicGhcPrograms for information about efforts to reduce our dependence on this linker.

    Итак, тут у нас стековая машина из хачкеля, которая вродекак отвечает за динамическую загрузку какого-то говна.

    Запостил: j123123, 22 Февраля 2019

    Комментарии (92) RSS

    • Так блядь, хуйня типа Sp_subB(1); Sp_subB(2); и проч - она значит стекпоинтер декрементирует

      Что это за хуйня "*(StgWord8*)Sp" по-вашему? Типы StgWord8 StgWord16 StgWord32 определены в
      https://github.com/ghc/ghc/blob/1c2c2d3dfd4c36884b22163872feb87122b4528d/includes/stg/Types.h#L64


      Что мы видим? Обычные синонимы к херне из uint8_t int8_t uint16_t int16_t и так далее.

      А у нас тут есть херня такая, что для bci_PUSH8 мы делаем Sp_subB(1) т.е. уменьшаем стек на 1, потом кастуем: *(StgWord8*)Sp = *(StgWord8*)(Sp_plusB(off+1));

      Ну в общем какую-то херь в стек записываем из какого-то говна, но при этом стекпоинтер уменьшаем на 1. Т.е. стек у нас нихера не выровнен. И если потом будет хуйня bci_PUSH16: *(StgWord16*)Sp = *(StgWord16*)(Sp_plusB(off+2));

      Которая кастанет невыровненную хуйню в *uint16_t и потом разыменует даже. А это UB
      Ответить
      • https://github.com/ghc/ghc/blob/e204431e5a5e2fd16da52b04bda2798f16c51344/rts/Interpreter.c#L134


        #define Sp_plusB(n)  ((void *)(((StgWord8*)Sp) + (n)))
        #define Sp_minusB(n) ((void *)(((StgWord8*)Sp) - (n)))
        
        #define Sp_plusW(n)  (Sp_plusB((n) * sizeof(W_)))
        #define Sp_minusW(n) (Sp_minusB((n) * sizeof(W_)))
        
        #define Sp_addB(n)   (Sp = Sp_plusB(n))
        #define Sp_subB(n)   (Sp = Sp_minusB(n))
        #define Sp_addW(n)   (Sp = Sp_plusW(n))
        #define Sp_subW(n)   (Sp = Sp_minusW(n))
        
        #define SpW(n)       (*(StgWord*)(Sp_plusW(n)))
        #define SpB(n) (*(StgWord*)(Sp_plusB(n)))


        И кто вас блядь учил писать так макросы? Макросы принято писать КАПСОМ!
        Ответить
        • у яблока много макрософ не капсом

          да и у юнисков бывает так что есть функция foo и апнисано: "вронинг! эта функция может быть мокросом"
          Ответить
      • В S" Forth" всё в стеке занимает как минимум одну ячейку, даже символ. Именно поэтому я за S" Forth"
        Ответить
    • У нас было два пакетика GHC Core, семьдесят пять ампул C--, 5 пакетиков Spineless Tagless G-Machine или STG, солонка, наполовину наполненная LLVM, и целое море разноцветных бекендов, интерпретаторов, а так же пинта стекового языка, и 12 пузырьков ghci. Не то, чтобы всё это было категорически необходимо в языке программирования, но если уж начал обеспечивать студентов темами для masters theses, то к делу надо подходить серьёзно. Единственное, что вызывало у меня опасение — это стековые языки. Ничто в мире не бывает более беспомощным, безответственным и порочным, чем шитый код. Я знал, что рано или поздно мы перейдем и на эту дрянь.
      Ответить
      • в PHP ничего этого нет
        Именно потому я за "Haskell"
        Ответить
        • А я за «Ассемблер», потому что в нём нет ни кастов, ни UB. Можно просто изменять указатель на вершину стека и течь.
          Ответить
          • строго говоря и стек в нем не обязателен
            можно всю память выделить статически и там шарудить


            в няшной тоже можно, но надо убедица что кал-конвеншен там через регистры а не через

            я когда был мелким пиздюком и писал под tiny (когда вся мапять в одном сегменте 64К) а API биоса было на регистрах, и мне стек вообще не нужен был
            Ответить
            • Регистры иногда заканчиваются, надо где-то сохранять их содержимое. Да и в подпрограммах содержимое используемых регистров тоже надобно схоронить, а в конце восстановить. Так что без стека только совсем примитивные программы обходились.
              Ответить
              • > подпрограммах
                На фортране и бейсике отлично обходились без этих ваших автоматических переменных.
                Ответить
              • Недавно смотрел документацию по «Итаниуму» (помним, скорбим). У него была фишка, именуемая ротацией регистров. При упоминании в программе нумерных регистров PR16...PR63, GR32...GR127 и FR32...FR127 реальное обращение происходит не к регистру с указанным номером (N), а к регистру с номером N+RRB (по модулю количества регистров), где RRB –— специальный регистр, значение которого увеличивается на единицу после инструкции, передающей управление на начало цикла. Т. е. если на первой итерации цикла RRB=0, то при упоминании PR16 данные читаются из PR16, на второй итерации цикла RRB=1 и при упоминании PR16 данные читаются из PR17, на третьей итерации RRB=2 и при упоминании PR16 данные читаются из PR18 и так далее. Аппаратный кольцевой буфер!

                В «x86» вращаемых банков регистров нет, именно поэтому я за «x86».
                Ответить
                • > В «x86» вращаемых банков регистров нет, именно поэтому я за «x86».

                  Зато в x86 можно циклически сдвигать какой-нибудь регистр, и брать от него кусочек поменьше. В x86-64 например 64-битный регистр rax и его 8-битные кусочки ah и al.
                  Ответить
              • я же сказал -- статическая память.
                выделил сразу кусок и управляй ею

                хуже того: в асембреле у тебя не было никакой кучи ввиду аотстуствия ее менеджера
                вся пмять твоя
                Ответить
                • И это будет ёбаный пихдец из сотни глобалок, даже для временных переменных.

                  > в асембреле у тебя не было никакой кучи
                  В виндах и линупсах есть. И ничто не машало использовать билиботеку/написать свой для ДОЧ'а.
                  Ответить
          • > А я за «Ассемблер», потому что в нём нет ни кастов, ни UB.

            В ассемблере есть (точнее, могут быть) недокументированные инструкции, которые хуй знает что делают. Вполне можно считать это UB-ом. А еще, если взять процессор версии X, в котором инструкция A (т.е. некоторая некорректная последовательность байт, которая не может быть декодирована как инструкция) не поддерживается (при попытке ее исполнения будет брошено исключение), то в каком-то более новом процессоре версии X+1 могут додуматься в такой способ кодировать некоторые инструкции, и тогда это уже не будет приводить к броску исключения.
            Ответить
            • Но ведь это не ассемблер, а машинные коды. Разве ассемблер (программа) может скомпилировать какой-то исходный код в бинарник с невалидными инструкциями (если погромист не додумался напрямую байтики писать через db, конечно)?
              Ответить
              • Да, например если писать под Intel 80386, но использовать более свежие инструкции, доступные только начиная с 80486.
                Например
                https://ru.wikipedia.org/wiki/80486#Математическая_модель_и_набор_инструкций
                Ответить
                • ну то-есть я могу скомпилироваться под прос с MMX наример и на 286 словить инвалид опкод?
                  Ответить
                  • Ты даже в 32-битный защищенный режим перейти не сможешь, потому что 286 в 32-бит не умеет
                    Ответить
                    • Борманд гловорил что это инпельментэйшон в диване.
                      Ответить
                    • в смысле я не смогу загрузить в регистр десккриптор сегмента у кторого тип указн как 32?
                      то да

                      а так же не смогу писнуть с CR3 таблу страниц бо их тоже не было в 286 (хотя протектед мод там и был)_
                      Ответить
                • Ну нет. Это implementation-defined - я могу предсказать результат прочитав даташит на конкретный проц.

                  З.Ы. Хотя... вызов недокументированной инструкции на старом проце всё-таки UB. Хуй знает что она там делала. Вроде не гарантируется, что все неизвестные инструкции должны кидать исключение?
                  Ответить
                  • > Ну нет. Это implementation-defined - я могу предсказать результат прочитав даташит на конкретный проц.

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

                      невалидная инсрукция это INVALID OPCODE.
                      Ответить
                      • Можно пруф из спеки, что каждая не описанная в ней инструкция кидает это исключение?

                        Вроде на интеле находили недокументированные опкоды которые что-то делают и не кидают.
                        Ответить
                        • Вот тут например http://www.z80.info/zip/z80-documented.pdf описаны недокументированные опкоды к z80, которые что-то там делают, не кидая при этом исключений.
                          Ответить
                        • кажется что в volume 3 написано только что UD2 явно вызовет UD#.
                          Впрочем, про UB тоже не написано.
                          Ответить
                        • salc
                          Ответить
                          • Он документирован, оказывается.

                            The opcodes D6 and F1 are undefined opcodes reserved by the Intel 64 and IA-32 architectures.
                            Ответить
                            • иными словами возможна ситуация при которой интел зарезервирует опкод, но не привяжет к нему #UD?
                              Ответить
                              • Я думаю, что они больше так не делают.

                                Но надо ещё поискать как обстоят дела с недокументированными сочетаниями префиксов.
                                Ответить
                                • Other use of branch hint prefixes and/or other undefined opcodes with Intel 64 or IA-32 instructions is reserved; such use may cause unpredictable behavior.

                                  Other use of the 66H prefix is reserved; such use may cause unpredictable behavior.

                                  The address-size override prefix (67H) allows programs to switch between 16- and 32-bit addressing. <...> Using this prefix and/or other undefined opcodes when operands for the instruction do not reside in memory is reserved; such use may cause unpredictable behavior.
                                  Ответить
                                  • > unpredictable behavior.
                                    изобрел процессор который при использовании недокументированного префикса подымает напряжение на VRM до 12 вольт и самоуничтожается

                                    ни один копилятор или асемблер такую инструкцуию не генерит, так что вирус-убийцу процов пришлось писать на машинных колдах
                                    Ответить
                                    • На «x86» можно выполнить JMP в середину инструкции или вообще в секцию данных (если нет защиты от выполнения). Именно поэтому я за «x86».
                                      Ответить
                                      • Когда-то я тоже кодил на ассёмблере, но потом стал рекитиром.
                                        Ответить
                                        • Как ты мог кодить на ассемблере? Ведь они вымерли 65 млн. лет назад!
                                          Ответить
                                          • Ххех. У меня ещё и писюк был, с пузатым таким, голубым экраном и жужжалка для плёнки.
                                            Ответить
                          • salsa
                            Ответить
                    • Программы с «классическим» — сишко-крестовым — UB использовать нельзя: их поведение не определено где угодно (оно может «правильно» работать на каких-то платформах, но рассчитывать на это категорически нельзя).
                      Чтобы поведение какой-то конструкции было implementation-defined, оно должно быть задокументировано для всех платформ:
                      implementation-defined behavior
                      behavior, for a well-formed program construct and correct data, that depends on the implementation and
                      that each implementation documents

                      §3.12, [defns.impl.defined]

                      В результате имеем, что неподдерживаемые инструкции ассемблера — это и не UB, и не ID: с одной стороны, на платформах без поддержки данной инструкции поведение в принципе не определено (т. е. уже не ID), а с другой — на «хороших» платформах — точно задокументировано (не UB).
                      Ответить
                      • 22.15 Undefined opcodes
                        All new instructions defined for IA-32 processors use binary encodings that were reserved on earlier-generation processors. Attempting to execute a reserved opcode always results in an invalid-opcode (#UD) exception being generated.

                        6.15 Exception and interrupt reference
                        Interrupt 6 - Invalid Opcode Exception (#UD)
                        <...> The opcodes D6 and F1 are undefined opcodes reserved by the Intel 64 and IA-32 architectures. These opcodes, even through undefined, do not generate an invalid opcode exception.

                        Интел сам себе противоречит... Все опкоды равны, но некоторые равнее других.
                        Ответить
          • В асмемблере есть касты: byte, word, dworf, qword.
            Ответить
            • Это не касты, а просто хинты для выбора инструкции. Можно с тем же успехом писать movb или movl. Или вообще не писать, если по регистру и так понятно.

              На касты там больше похожи movzx и movsx.
              Ответить
              • В "fasm" нет никакого movl. Вот например:
                n dq 4
                ; ...
                mov eax, dword [n]
                n имеет тип qword, без каста в dword он будет ругатся.
                Ответить
                • А [n+4] отступит на 4 байта или на 32?
                  Ответить
                  • Не понял с чего вжрукк 32? В асамблерах же смещение никогда не умножается на размер элемента, там всё в батах считается же.
                    Ответить
                    • Да мало ли, раз он о типах знает.
                      Ответить
                      • В "TASM" такаж хуня была, если N объявлено как DD, то чтобы считать слово надо было написать WORD PTR.
                        Ответить
                    • На ГК нужен какой-нибудь валидатор русского языка. Стоит выдавать сообщение "ошибка компиляции комментария", если комментарий претендует на информативность, но написан в стиле вореций.
                      Хм, или тупо скриптом Vindicar'а скрывать всех петухов, чтобы невалидное говно вида "вжрукк" не читать.
                      Ответить
                • ебать вы открыли для себя разницу AT&Tщниго и Intelовского синтаксиса

                  праздравляю
                  Ответить
                  • Ахаха, на tio.run у "as" вот такой хеловелд;
                    .print "Hello, World!"
                    Почему тогда они у фасма они написали асамблерную программу, а не сделали так же директивой
                    display "Hello, World!"
                    ?
                    Ответить
            • > dworf
              dwarf

              dixed
              Ответить
      • Стековые языки не обязательно реализуются в шитом коде, например S" SP-FORTH" компилицца в нативный код, а 'RETRO_FORTH в байткод, просто шитый код легче декомпилить.
        Ответить
        • Ещё доебись что и регистровые ВМ могут быть на шитом коде. Я писатель, я так вижу.
          Ответить
          • И доебусь! А ещё я могу доебатся и до своих слов, ведь байткод можно считать частным случаем свёрнутого косвенного шитого кода, тогда, например, 'RETRO_FORTH тоже компилица в шитый код.
            Ответить
          • >>регистровые ВМ
            типа ллвм?
            Ответить
        • давайте пиздеть про шитый код VS байткод
          Ответить
          • Давай. Чур я зашитого кода.

            Шитый код компактный, быстрый, а его интерпретатор реализуется парой инструкций. Вот минимальный адресный интерпретатор прямого шитого кода с примерами подпрограмм:
            ; esi -- указатель инструкций
            ; ebp -- стек развраьов
            ; esp -- стек банных
            
            macro next { ; сам адресный интерпретатор, этим макросом должны заканчиватся низкоуровневые определения
                lodsd
                jmp eax
            }
            
            macro rpush x { ; запушить x в стек развратов
                sub ebp, 4
                mov dword [ebp], x
            }
            macro rpop x { ; попнуть из стека развратов в x
                mov dword x, [ebp]
                add ebp, 4
            }
            
            ; примеры низкоуровневых определений:
            false:
                push 0
                next
            
            state:
                push var_state
                next
            
            var_state dd ?
            
            store_: ; x addr !
                pop ebx
                pop dword [ebx]
                next
            
            forth_call: ; помещается в начале "высокоуровневых" определений
                rpush esi
                pop esi
                next
            
            exit: ; возврат в вызывающую подпрограмму
                rpop esi
                next
            
            left_bracket: ; пример "высокоуровневого" определения
                call forth_call
                dd false, state, store_, exit

            А в косвенном шитом коде в высокоуровневых определениях только адреса, и они могут хранится в секции с данными, а само ядро маленькое и может целиком поместиться в кешу. А вот пример адресного интерпретатора косвенного шитого кода, он не сложнее и не больше чем у прямого:
            macro next {
                lodsd
                jmp [eax]
            }
            
            forth_call: ; адресс помещается в начале "высокоуровневых" определений
                rpush esi
                mov esi, eax
                add esi, 4
                next
            
            ; пример низкоуровневого определения
            exit dd @f
            @@:
                rpop esi
                next
            
            ; пример "высокоуровневого" определения:
            left_bracket dd forth_call, false, state_, store, exit
            А в подпрограмном шитом коде адресный интерпретатор не нужен, программа состоит из цепочки call'ов, и не сложно перейти от него к обычному нативному коду.

            Теперь ваш ход.
            Ответить
            • я тогда за байткода

              каждый оп в таком коде занимает один байт. Мало того что это сильно упрощает декодер, так еще и создает компактный код.

              Возьмем стековую машину где надо сложить 2 и 2

              push 2
              push 2
              add

              всё.
              Ответить
              • Хуёвый ты оппонент, тогда я пока временно за баткод:

                В байкоде только КОП занимает один байт, но у него ещё могут быть аргументы, как в твоём примере у push (и в шитом коде тоже могут быть оргументы). Сам код получается компактный, но для его декодирования нужна как минимум одна таблица как минимум на 256 адресов (можно и меньше, но придётся добавлять условия в интерпретаторе байткола), вот примитивный интерпретатор бацкода:
                ; esi -- укахатель инструкций
                ; ebx -- адрес таблицы
                ; esp -- стек банных
                ; ebp -- стек развратов
                
                next equ jmp next_
                
                next_:
                    xor eax, eax
                    lodsb
                    jmp dword [ebx + eax * 4] ; у джумпа же так можно?
                
                ; пример реализации самих команд:
                call_:
                    rpush esi
                    pop esi
                    next
                
                exit:
                    rpop esi
                    next
                
                push_:
                    lodsd
                    push eax
                    next
                
                add_:
                    pop eax
                    add [esp], eax
                    next
                
                ; пример пожпрограссы в бакоде (PUSH_, ADD_, EXIT это сами байткоды
                my_sub:
                    db PUSH_
                    dd 2
                    db PUSH_
                    dd 2
                    db ADD_, EXIT
                Как видно интерпретатор байткода сложнее чем у прямого или косвенного шитого кода, ему требуется дополнительная память для таблицы. Но его главное преимущество в том, что сам сконпелированный ьайткод лучше переносим чем шитый код.

                У меня усё.
                Ответить
                • Интересно, а что быстрее movzx + inc или xor + lodsb?
                  Ответить
                  • Не знаю, заю только что мой вореант на байт короче.
                    Ответить
                    • Зато movzx и inc можно параллельно запустить. А lodsb будет ждать пока xor закончится.
                      Ответить
                • Интересная как у вас беседа, правда кажется что твой собеседник ничерта не понимает.

                  А я так понял из твоего объяснения что шитый код довольно сильно привязан к рахитектуре и нихуя не переносим. Чем же он тогда лучше чем обычная компиляция?

                  Только тем что "генерацию" шитого кода (кстати, а почему он так назван?) можно отвязать его "интерпретатора" (который на самом деле постамбула)
                  Ответить
                  • Он проще компиляции. И не требует RWX памяти для генерации на лету. Ебашишь адреса функций в массив да и всё.
                    Ответить
                    • А ещё шитый код легко декомпилировать, почти один в один получается ( так, кстати обычно работает ' SEE в S" Forth" )
                      Ответить
                    • Кстати, только косвенный не требует RWX памяти, в остальных видах присутствуют машкоды.
                      Ответить
                  • Косвеный шитый код можно переносить, но это сложнее чем переносить баткод, надо генерить объектный файл, а потом с ним линковатся. А форт язык простой и компилица быстро, в нём обычно всё в исходниках хранится/переносица и объектные файлы не нужны.
                    Ответить
                    • а если я написал проприетраный софт на форте ине хочу отдавать его исходник?
                      Ответить
                      • Там обычно всё в исходниках, даже части самой системы могут в исходниках хранится.
                        Если сильно хочеца генерь образ для gforth или просто бинарник. Вот только деконпелируется он просто, надо брать систему которая умеет в нативный код и оптимизации (типа SP-FORTH).
                        Ответить
                  • А ещё на декодирование одной инструкции шитого кода нужно меньше операций чем на один байткод.
                    Ответить
                  • Вот кстати годная статья по шитому коду:
                    http://www.complang.tuwien.ac.at/forth/threaded-code.html
                    там есть примеры переносимых реализаций интерпретаторов, по ним кстати видно какая сишка убогая при своей-то низкоуровневости.

                    А вот бенчмарк разных техник интерпретации шитого кода:
                    http://www.complang.tuwien.ac.at/forth/threading/Во многих случаях обычно быстрее прямой. Баткода там, к сожалению нет, но наверное за него можно считать switch threading.
                    Ответить
                    • Почему петухи срут только в коменты, а посты не высирают?
                      Ответить
                      • Потому что петухи. Хотя погоди, вот же петушиные посты:
                        http://govnokod.ru/user/26089/codes
                        http://govnokod.ru/user/25786/codes
                        http://govnokod.ru/user/26137/codes
                        http://govnokod.ru/user/26135/codes
                        Ответить
                        • В соотношении постов на один коммент срёт больше разве что борманд.
                          Ответить
                • питух, я все равно не понимаю как шитокод может быть переносимым.

                  Даже если там не
                  call 123 а просто 123: у одного проца адреса выравниваются так, у дргого этак.

                  шитокод надо гегенинирить под каждую платхорму отдельно.

                  или это ок? или это как .pyc для питона: генерится чисто для скорости, а переносица все равно сырцы?

                  то-есть как у джавоклассов: compile once, test run everywhere не полу?
                  Ответить
                  • > как шитокод может быть переносимым.
                    Токены можно легко переносить, а чтоб перенести косвенный шиткод надо генерить объектные файлы, и при загрузке просто подправить нужные адреса. Из форт-систем я знаю, что только GForth умеет делать переносимые образы:
                    http://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Fully-Relocatable-Image-Files.html#Fully-Relocatable-Image-Files
                    На счёт других языков конпилирующихся в шиткоды я не знаю.

                    Кстати, прямой шиткод тоже можно переносить как косвенный, надо просто в начале всех определений ещё вставить платформо-специфичный кусочек.

                    > генерится чисто для скорости, а переносица все равно сырцы?
                    Тип того, в стандарте нет ничего про перенос сконпелированых программ, в каждой системе может быть по своему, а миожет и вообще не быть. А ещё шиткод может выигрывать по размеру у нативного, в какои-нибудь зачуханом контроллере это может оч важно.

                    > compile once, run everywhere не полу?
                    Token threading
                    Ответить
                    • а мне понравился подход когда парсер сохраняет AST дерево в удобном формате.
                      много времени тратится на парсинг, и его результаты жалко терять.

                      Это конечно не так быстро работаит, но можно джытнуть. Но джиту же нужно сначала сипать в страницу а потом выключать ей w и включать x, да?
                      Ответить
                    • > шиткод может выигрывать по размеру у нативного, в какои-нибудь зачуханом

                      это когда вместо

                      call pituh
                      call pituh
                      call pituh

                      у меня просто
                      pituh
                      pituh
                      pituh
                      ?

                      я пока не очень понимаю как тут работает префетчер и декодер у cpu.. кажется что плохо работает.

                      в обычном коде пока вызыввают первого петуха, второй уже может с другой стнацуей вычисляться (привет мельтдаун)
                      а как быть с шитокодом? что же это, никакого спекулятивного выполнения, никакого мельдауна?
                      Ответить
            • lodsd это, конечно, быстро и коротко, но есть и минус: пропадает возможность юзать eax для вершины стека.
              Ответить

    Добавить комментарий