gpt4 book ai didi

assembly - 了解 SBCL 进入/退出程序集样板代码

转载 作者:太空宇宙 更新时间:2023-11-03 18:33:40 25 4
gpt4 key购买 nike

背景

当在 Windows 上使用 64 位 Steel Bank Common Lisp 实现一个简单的身份函数时:

(defun a (x)
(declare (fixnum x))
(declare (optimize (speed 3) (safety 0)))
(the fixnum x))

我发现反汇编是这样的:

* (disassemble 'a)

; disassembly for A
; Size: 13 bytes
; 02D7DFA6: 84042500000F20 TEST AL, [#x200F0000] ; safepoint
; no-arg-parsing entry point
; AD: 488BE5 MOV RSP, RBP
; B0: F8 CLC
; B1: 5D POP RBP
; B2: C3 RET

我理解这些行:

mov rsp, rbp
pop rbp
ret

从函数操作执行标准返回,但我不明白为什么会有这些行:

TEST AL, [#x200F0000]  // My understanding is that this sets flags based on bitwise and of AL and contents of memory 0x200F0000

CLC // My understanding is that this clears the carry flag.

问题

  1. 为什么 SBCL 生成测试指令,但从不使用标志?
  2. 为什么 SBCL 在函数返回前清除进位标志?

最佳答案

正如反汇编器提示的那样,TEST 指令是一个安全点。它用于为垃圾收集器同步线程。安全点插入到编译器知道线程处于安全状态以进行垃圾收集的位置。

安全点的形式在compiler/x86-64/macros.lisp中定义:

#!+sb-safepoint
(defun emit-safepoint ()
(inst test al-tn (make-ea :byte :disp sb!vm::gc-safepoint-page-addr)))

您对于未使用操作的结果当然是正确的。在这种情况下,SBCL 对操作的副作用感兴趣。具体来说,如果包含该地址的页面恰好受到保护,则该指令会产生页面错误。如果页面可访问,该指令只会浪费非常的时间。我应该指出,这可能比简单地检查全局变量要快得多。

在 Windows 上,runtime/win32-os.c 中的 C 函数 map_gc_pageunmap_gc_page用于映射和取消映射页面:

void map_gc_page()
{
DWORD oldProt;
AVER(VirtualProtect((void*) GC_SAFEPOINT_PAGE_ADDR, sizeof(lispobj),
PAGE_READWRITE, &oldProt));
}

void unmap_gc_page()
{
DWORD oldProt;
AVER(VirtualProtect((void*) GC_SAFEPOINT_PAGE_ADDR, sizeof(lispobj),
PAGE_NOACCESS, &oldProt));
}

不幸的是我没能找到页面错误处理程序,但一般的想法似乎是当需要收集时,unmap_gc_page 将被调用。每个线程将继续运行,直到它达到这些安全点之一,然后发生页面错误。据推测,页面错误处理程序随后会暂停该线程,然后当所有线程都已暂停时,垃圾收集将运行,然后再次调用 map_gc_page 并允许线程恢复。

感谢 Anton Kovalenko 介绍了这种机制。

在 Linux 和 Mac OS X 上,默认使用不同的同步机制,这就是为什么在这些平台的默认构建中不生成指令的原因。 (我不确定 PowerPC 端口是否默认使用安全点,但显然它们不使用 x86 指令)。

另一方面,我对CLC指令一无所知。

关于assembly - 了解 SBCL 进入/退出程序集样板代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21859232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com