As the disassembler hints, the TEST
instruction is a safepoint. It's used for synchronizing threads for the garbage collector. Safepoints are inserted in places where the compiler knows the thread is in a safe state for garbage collection to occur.
The form of the safepoint is defined in compiler/x86-64/macros.lisp:
#!+sb-safepoint
(defun emit-safepoint ()
(inst test al-tn (make-ea :byte :disp sb!vm::gc-safepoint-page-addr)))
You are of course correct about the result of the operation not being used. In this case, SBCL is interested in a side effect of the operation. Specifically, if the page containing the address happens to be protected, the instruction generates a page fault. If the page is accessible, the instruction just wastes a very small amount of time. I should point out this is probably much, much, faster than simply checking a global variable.
On Windows, the C functions map_gc_page
and unmap_gc_page
in runtime/win32-os.c are used to map and unmap the 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));
}
Unfortunately I haven't been able to track down the page fault handler, but the general idea seems to be that when a collection is needed, unmap_gc_page
will be called. Each thread will continue running until it hits one of these safepoints, and then a page fault occurs. Presumably the page fault handler would then pause that thread, and then when all threads have been paused, garbage collection runs, and then map_gc_page
is called again and the threads are allowed to resume.
The credits file honors Anton Kovalenko with introducing this mechanism.
On Linux and Mac OS X, a different synchronization mechanism is used by default, which is why the instruction isn't generated on default builds for those platforms. (I'm not sure if the PowerPC ports use safepoints by default, but obviously they don't use x86 instructions).
On the other hand, I have no idea about the CLC
instruction.