x86-64 with-pinned-objects can't pin constants

Bug #1989037 reported by Douglas Katzman
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Undecided
Unassigned

Bug Description

Consider:

(defun f ()
  (declare (optimize (sb-c::alien-funcall-saves-fp-and-pc 0)))
  (let ((s #.(coerce "test\\n" 'simple-base-string)))
    (with-pinned-objects (s)
      (alien-funcall (extern-alien "printf" (function void system-area-pointer))
                     (vector-sap s)))))
* (disassemble 'f)
; disassembly for F
; Size: 62 bytes. Origin: #x5345C6BC ; F
; BC: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 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://bugs.launchpad.net/sbcl/+bug/1982608) though this problem has been around for longer, and should really only affect pointer values seen by a foreign call.

Revision history for this message
Stas Boukarev (stassats) wrote :

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.

Revision history for this message
Stas Boukarev (stassats) wrote :

Take two. Might produce worse code, but at least it's localized and just results in extra moves/loads.

Revision history for this message
Stas Boukarev (stassats) wrote :
Revision history for this message
Stas Boukarev (stassats) wrote :

But for some reason this results in
Consed 1319344 bytes discounting 15540848 bytes
::: UNEXPECTED-FAILURE :DISASSEMBLE-EVERYTHING due to SIMPLE-ERROR:
        "The assertion (< DELTA 500000) failed with DELTA = 1319344."

Stas Boukarev (stassats)
Changed in sbcl:
status: New → Fix Committed
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.