Если мы добавим вызов к jit_disassemble()
в ваш код, мы увидим, что сгенерированный код для вашей f
функции выглядит следующим образом:
0x7f2511280000 sub $0x30,%rsp
0x7f2511280004 mov %rbx,0x28(%rsp)
0x7f2511280009 mov %rbp,(%rsp)
0x7f251128000d mov %rsp,%rbp
0x7f2511280010 sub $0x18,%rsp
0x7f2511280014 mov %rdi,%rax
0x7f2511280017 mov %rsi,%r10
0x7f251128001a mov %rdx,%r11
0x7f251128001d nopl (%rax)
0x7f2511280020 test %r10,%r10
0x7f2511280023 je 0x7f2511280040
0x7f2511280029 movslq (%r11),%rbx
0x7f251128002c mov %rbx,%rdi
0x7f251128002f add $0x4,%r11
0x7f2511280033 sub $0x1,%r10
0x7f2511280037 jmpq 0x7f2511280020
0x7f251128003c nopl 0x0(%rax)
0x7f2511280040 callq *%rax
0x7f2511280042 xor %rax,%rax
0x7f2511280045 mov %rbp,%rsp
0x7f2511280048 mov 0x28(%rsp),%rbx
0x7f251128004d mov (%rsp),%rbp
0x7f2511280051 add $0x30,%rsp
0x7f2511280055 retq
Если мы посмотрим на код, сгенерированный jit_pushargr
, проблема становится очевидной:
0x7f251128002c mov %rbx,%rdi
Таким образом, это устанавливает значение *argv
в качестве первого аргумента вызываемой функции (rdi
является регистром, который содержит первый аргумент в x64 Соглашение о вызовах). Это происходит несколько раз, потому что это в al oop, но это всегда первый установленный аргумент. Таким образом, когда функция вызывается после l oop, rdi
будет содержать значение, которое было записано в него последним в l oop (то есть последнем значении внутри argv
) и других регистрах аргументов / ячейках памяти. не будет записано вообще.
Способ, которым работает jit_pushargr
, заключается в том, что он будет записывать первый аргумент при первом вызове, а затем второй аргумент при вызове второго время и так далее. Но в вашем коде вы вызываете его только один раз, поэтому первый аргумент записывается только один раз.
Поэтому для создания функции применения с использованием молнии вам нужно будет вызвать jit_pushargr
* 1020. * раз. Это означает, что вместо генерации общей функции apply вы захотите определить саму функцию apply в обычном C и вместо этого сгенерировать вспомогательную функцию, которая выдвигает заданное количество аргументов.
В качестве альтернативы вы можете сделать это полностью без молнии, и вместо этого используйте libffi для этого, который был бы более традиционным инструментом для подобных применений и не потребовал бы затрат на генерацию нового кода каждый раз, когда вызывается apply
. Конечно, это не помешает вам вызывать функцию apply
из кода, сгенерированного молнией.