master: Fix arena-related crash
snuglas via Sbcl-commits <[email protected]> Thu, 16 Jul 2026 15:50:31 +0000
| Newsgroups | gmane.lisp.steel-bank.cvs |
|---|---|
| Message-ID | <[email protected]> |
The branch "master" has been updated in SBCL:
via 8796281182447fa2091610881629204729b04793 (commit)
from e3c2db021f4f5138ec1f04b3c0c83148c362a45d (commit)
- Log -----------------------------------------------------------------
commit 8796281182447fa2091610881629204729b04793
Author: Douglas Katzman <[email protected]>
Date: Thu Jul 16 15:46:05 2026 +0000
Fix arena-related crash
---
src/code/target-defstruct.lisp | 11 +++++++----
tests/arena.impure.lisp | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/code/target-defstruct.lisp b/src/code/target-defstruct.lisp
index 6130d606c..93540faf3 100644
--- a/src/code/target-defstruct.lisp
+++ b/src/code/target-defstruct.lisp
@@ -614,6 +614,7 @@
(h (progn ,@body)))
(if (< h ,nbuckets) ,resultform)))))))
+;;; Unclear why this is in SB-PCL package. It's used more from here.
(declaim (inline sb-pcl::search-struct-slot-name-vector))
(defun sb-pcl::search-struct-slot-name-vector (mapper slot-name)
(declare (optimize (sb-c::insert-array-bounds-checks 0)))
@@ -665,6 +666,7 @@
;;; until the function is called (which may never occur), and secondly the caller
;;; is never delayed by waiting for the compiler.
(defun install-struct-slot-mapper (layout)
+ (declare (sb-c::tlab :system))
(let* ((dd (layout-dd layout))
(slots (dd-slots dd))
(keys (map 'vector #'dsd-name slots))
@@ -683,6 +685,7 @@
(return-from install-struct-slot-mapper
(setf (layout-slot-mapper layout) vector)))
(let ((me (%make-slot-mapper-fn))
+ (name `(slot-mapper ,(dd-name dd)))
(pairs (map 'list #'cons keys values)))
(setf (sb-kernel:%funcallable-instance-fun me)
(lambda (symbol)
@@ -692,13 +695,13 @@
(let ((old (layout-slot-mapper layout)))
(if (neq old me) ; if it's not ME, then it's either the second stage mapper
;; or else a compiled perfect-hash-based mapper. Either way, punt.
- (funcall old symbol)
- (let* ((new (make-second-stage-slot-mapper vector))
+ (funcall (the function old) symbol)
+ (let* ((new (lambda (symbol)
+ (sb-pcl::search-struct-slot-name-vector vector symbol)))
(actual-old
(%layout-slot-cas layout (get-dsd-index layout slot-mapper) me new)))
(when (eq actual-old me)
- (install-hash-based-slot-mapper
- layout pairs unique-hashes `(slot-mapper ,(dd-name dd))))
+ (install-hash-based-slot-mapper layout pairs unique-hashes name))
(funcall new symbol))))))
(setf (layout-slot-mapper layout) me))))
diff --git a/tests/arena.impure.lisp b/tests/arena.impure.lisp
index b88097da9..6b87ea20b 100644
--- a/tests/arena.impure.lisp
+++ b/tests/arena.impure.lisp
@@ -727,3 +727,23 @@
(sb-thread:join-thread thread)
(assert (heap-allocated-p (sb-thread:thread-name thread))))
(destroy-arena arena))))
+
+(defstruct fleemazoid a b c d e f g)
+(defun get-a-slot (inst sym) (slot-value (the fleemazoid inst) sym))
+;; Just in case we decide that this file can run in --evaluator-mode interpret
+;; (which it currently can't) ensure that slot-value uses the layout slot mapper.
+(compile 'get-a-slot)
+(test-util:with-test (:name :slot-mapper-not-in-arena)
+ (let ((a (sb-vm:new-arena 65536)))
+ (sb-vm:with-arena (a)
+ (get-a-slot (make-fleemazoid :c "hi-c") 'c))
+ (destroy-arena a)
+ ;; There's no way to know when the background compile is done, we can't really
+ ;; do any better than to wait a little. Deciding based on whether the finalizer's
+ ;; work queue is empty constitutes a data race- it grabs an item and then compiles,
+ ;; so you don't know when COMPILE is actually done.
+ (sleep .1)
+ (let ((fun (sb-kernel::layout-slot-mapper (sb-kernel:find-layout 'fleemazoid))))
+ (assert (sb-kernel:simple-fun-p fun))
+ (let ((name (sb-kernel:%simple-fun-name fun)))
+ (assert (sb-ext:heap-allocated-p name))))))
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL