x86-64 with-pinned-objects can't pin constants
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
Consider:
(defun f ()
(declare (optimize (sb-c::
(let ((s #.(coerce "test\\n" 'simple-
(with-
(
* (disassemble 'f)
; disassembly for F
; Size: 62 bytes. Origin: #x5345C6BC ; F
; BC: 498B4510 MOV RAX, [R13+16] ; thread.
; C0: 488945F8 MOV [RBP-8], RAX
; C4: 488B3DC5FFFFFF MOV RDI, [RIP-59] ; "test\\n"
; CB: 48FFC7 INC RDI
; CE: 4C8BF4 MOV R14, RSP
; D1: 4883E4F0 AND RSP, -16
; D5: 31C0 XOR EAX, EAX
; D7: FF1425780D0050 CALL QWORD PTR [#x50000D78] ; printf
; DE: 498BE6 MOV RSP, R14
; E1: 488D5D10 LEA RBX, [RBP+16]
; E5: 31C9 XOR ECX, ECX
; E7: BA17011050 MOV EDX, #x50100117 ; NIL
; EC: 488BFA MOV RDI, RDX
; EF: 488BF2 MOV RSI, RDX
; F2: F9 STC
; F3: 488BE5 MOV RSP, RBP
; F6: 5D POP RBP
; F7: C3 RET
; F8: CC10 INT3 16 ; Invalid argument count trap
The disassembly shows that after loading the string, the compiler uses the same register to compute VECTOR-SAP into (which is merely an INC due to lowtag #xf).
At that point there is no tagged pointer to the string.
The compiler does this because it thinks that reloading the constant from the header is as good as computing a save location for it.
A stop-for-GC interrupt anywhere after the INC could potentially let the string move.
Specifying the TOUCH-OBJECT vop to take a descriptor-reg doesn't improve the situation because the compiler will still decide to reload the string.
I believe this could be a cause of mystery crashes (possibly https:/
Changed in sbcl: | |
status: | New → Fix Committed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |
I had to fight the compiler to convince it to avoid propagating constants. But it's not great still. It's not specific the pinned value, it changes the current behavior (and slows down the compiler (haven't measured)). And some tests fail. And some code fails to compile because of full calls to some VOPs.