Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Common lisp 如果编译后的函数正在使用,SBCL什么时候用更新的版本替换该函数?_Common Lisp_Sbcl - Fatal编程技术网

Common lisp 如果编译后的函数正在使用,SBCL什么时候用更新的版本替换该函数?

Common lisp 如果编译后的函数正在使用,SBCL什么时候用更新的版本替换该函数?,common-lisp,sbcl,Common Lisp,Sbcl,例如,如果一个循环在每次迭代时调用'FOO',而我在循环退出之前重新编译'FOO',会发生什么 SBCL用于处理此类情况的具体机制是什么?SBCL是一个仅编译的实现,因此您的问题的答案很容易找到: * (defun foo (x) (print x)) FOO * (describe 'foo) COMMON-LISP-USER::FOO [symbol] FOO names a compiled function: Lambda-list: (X) Derived type:

例如,如果一个循环在每次迭代时调用'FOO',而我在循环退出之前重新编译'FOO',会发生什么


SBCL用于处理此类情况的具体机制是什么?

SBCL是一个仅编译的实现,因此您的问题的答案很容易找到:

* (defun foo (x) (print x))

FOO
* (describe 'foo)

COMMON-LISP-USER::FOO
  [symbol]

FOO names a compiled function:
  Lambda-list: (X)
  Derived type: (FUNCTION (T) (VALUES T &OPTIONAL))
  Source form:
    (SB-INT:NAMED-LAMBDA FOO
        (X)
      (BLOCK FOO (PRINT X)))

* (disassemble (lambda ()(loop repeat 10 do (foo 1))))

; disassembly for (LAMBDA ())
; Size: 91 bytes. Origin: #x1002F7F564
; 64:       BE14000000       MOV ESI, 20                      ; no-arg-parsing entry point
; 69:       EB3E             JMP L1
; 6B:       0F1F440000       NOP
; 70: L0:   488BCE           MOV RCX, RSI
; 73:       4883E902         SUB RCX, 2
; 77:       488BF1           MOV RSI, RCX
; 7A:       488D5C24F0       LEA RBX, [RSP-16]
; 7F:       4883EC18         SUB RSP, 24
; 83:       BA02000000       MOV EDX, 2
; 88:       488975F8         MOV [RBP-8], RSI
; 8C:       488B057DFFFFFF   MOV RAX, [RIP-131]               ; #<FDEFINITION object for FOO>
; 93:       B902000000       MOV ECX, 2
; 98:       48892B           MOV [RBX], RBP
; 9B:       488BEB           MOV RBP, RBX
; 9E:       FF5009           CALL QWORD PTR [RAX+9]
; A1:       480F42E3         CMOVB RSP, RBX
; A5:       488B75F8         MOV RSI, [RBP-8]
; A9: L1:   4885F6           TEST RSI, RSI
; AC:       7FC2             JNLE L0
; AE:       BA17001020       MOV EDX, 537919511
; B3:       488BE5           MOV RSP, RBP
; B6:       F8               CLC
; B7:       5D               POP RBP
; B8:       C3               RET
; B9:       0F0B0A           BREAK 10                         ; error trap
; BC:       02               BYTE #X02
; BD:       19               BYTE #X19                        ; INVALID-ARG-COUNT-ERROR
; BE:       9A               BYTE #X9A                        ; RCX
NIL
第一个肯定调用
fdefinition
,第二个肯定不调用,第一个更接近循环的反汇编

最后,可以使用Paulo Madeira的显式测试:

(progn (sb-thread:make-thread (lambda () (sleep 5.1) (defun foo (x) (print (1+ x))))) 
       (dotimes (i 10) (sleep 1) (foo 1))) 

开始显示2。

这一定是某种优化的
fdefinition
访问器,因为
(progn(sb线程:make线程(lambda()(sleep 5.1)(defun foo(x)(print(1+x‘))))(dotimes(i10)(sleep 1)(foo 1))
开始显示
2
。哎呀,我猜我误解了反汇编。对不起,你问题的答案很容易找到,但这与SBCL的汇编无关;正如我们所看到的,仅仅基于拆卸并不是那么容易。一个更方便、更简单的测试就足够了,例如,
(dotimes(i10)(foo1)(when(=i4)(defun foo(x)(print(1+x‘)))
。尽管如此,编译器还是可以推断,既然循环中有对
foo
的重新定义,它将使用按名称查找来编译对
foo
的调用,而不是在循环之前获取函数对象。即使使用线程,如果没有适当的内存屏障(取决于体系结构),循环线程也可能看不到新定义,但这是另一个主题。
(progn (sb-thread:make-thread (lambda () (sleep 5.1) (defun foo (x) (print (1+ x))))) 
       (dotimes (i 10) (sleep 1) (foo 1)))