Re: master: Faster keyword argument checking in CLOS
Charles Zhang via Sbcl-commits <[email protected]> Sat, 9 May 2026 21:22:42 +0000 (UTC)
| Newsgroups | gmane.lisp.steel-bank.cvs,gmane.lisp.steel-bank.devel |
|---|---|
| Message-ID | <[email protected]> |
But what’s with the removed tests and the ansi test failure? On Saturday, May 9, 2026, 11:19 PM, stassats via Sbcl-commits <[email protected]> wrote: The branch "master" has been updated in SBCL: via c7921a02d8b8ff95914108b2395069bdc7f299aa (commit) from 9ce4f6ccc4a20abe3161ab68ac60d0f654611f25 (commit) - Log ----------------------------------------------------------------- commit c7921a02d8b8ff95914108b2395069bdc7f299aa Author: Stas Boukarev <[email protected]> Date: Sat May 9 22:49:45 2026 +0300 Faster keyword argument checking in CLOS Copy what convert-more-entry is doing and inline it. --- src/pcl/combin.lisp | 68 +++++++++++++++++++++----------------------------- src/pcl/fngen.lisp | 3 ++- tests/ansi-tests.sh | 2 +- tests/clos.impure.lisp | 4 --- 4 files changed, 32 insertions(+), 45 deletions(-) diff --git a/src/pcl/combin.lisp b/src/pcl/combin.lisp index 6037c651a..7fd56f15e 100644 --- a/src/pcl/combin.lisp +++ b/src/pcl/combin.lisp @@ -576,46 +576,36 @@ (aver any-keyp) (values (if allowp t keys) nopt))))) -(defun check-applicable-keywords (start valid-keys more-context more-count) - (let ((allow-other-keys-seen nil) - (allow-other-keys nil) - (i start)) - (declare (type index i more-count) - (optimize speed)) - (flet ((current-value () - (sb-c::%more-arg more-context i))) - (declare (inline current-value)) - (collect ((invalid)) - (loop - (when (>= i more-count) - (when (and (invalid) (not allow-other-keys)) - (%program-error "~@<invalid keyword argument~P: ~ - ~{~S~^, ~} (valid keys are ~{~S~^, ~}).~@:>" - (length (invalid)) (invalid) valid-keys)) - (return)) - (let ((key (current-value))) - (incf i) - (cond - ((not (symbolp key)) - (%program-error "~@<keyword argument not a symbol: ~S.~@:>" - key)) - ((= i more-count) - (sb-c::%odd-key-args-error)) - ((eq key :allow-other-keys) - ;; only the leftmost :ALLOW-OTHER-KEYS has any effect - (unless allow-other-keys-seen - (setq allow-other-keys-seen t - allow-other-keys (current-value)))) - ((eq t valid-keys)) - ((not (memq key valid-keys)) (invalid key)))) - (incf i)))))) - (defun wrap-with-applicable-keyword-check (effective valid-keys keyargs-start) - `(let ((.valid-keys. ',valid-keys) - (.keyargs-start. ',keyargs-start)) - (multiple-value-bind (.more-context. .more-count.) (sb-c::%rest-context .rest.) - (check-applicable-keywords - .keyargs-start. .valid-keys. .more-context. .more-count.)) + `(progn + (multiple-value-bind (more-context more-count) (sb-c::%rest-context .rest.) + (declare (ignorable more-context)) + ;; Similar to what SB-C::CONVERT-MORE-ENTRY does + (let ((count (- more-count ,keyargs-start))) + (when ,(if (zerop keyargs-start) + `(oddp count) + `(and (plusp count) + (oddp count))) + (sb-c::%odd-key-args-error))) + ,@(unless (eq valid-keys t) + (let ((restart (sb-c:make-restart-location))) + `((let (allowp + (lose (make-unbound-marker)) + (index more-count)) + (declare (index index)) + (loop until (<= index ,keyargs-start) + do (decf (truly-the index index) 2) + (let ((key (sb-c::%more-arg more-context index))) + (case key + (,(remove :allow-other-keys valid-keys)) + (:allow-other-keys + (setf allowp (sb-c::%more-arg more-context (1+ index)))) + (t + (setf lose key))))) + (if (or (unbound-marker-p lose) + allowp) + (sb-c::restart-point ,restart) + (sb-c::%unknown-key-arg-error lose ,restart))))))) ,effective)) ;;;; the STANDARD method combination type. This is coded by hand diff --git a/src/pcl/fngen.lisp b/src/pcl/fngen.lisp index 6eb140875..60d2b060a 100644 --- a/src/pcl/fngen.lisp +++ b/src/pcl/fngen.lisp @@ -97,7 +97,8 @@ (defun default-constantp (form) (and (constantp form) - (not (typep (constant-form-value form) '(or symbol fixnum cons layout))))) + (not (typep (constant-form-value form) '(or symbol fixnum cons layout + sb-c::restart-location))))) (defun default-test-converter (form) (if (default-constantp form) diff --git a/tests/ansi-tests.sh b/tests/ansi-tests.sh index fb8dc92ce..6e807d0e3 100755 --- a/tests/ansi-tests.sh +++ b/tests/ansi-tests.sh @@ -56,7 +56,7 @@ rm -fr sandbox/scratch "SUBSTITUTE-IF.FOLD.3" "SUBSTITUTE-IF.FOLD.2" "SUBSTITUTE-IF.FOLD.1" "SUBSTITUTE.FOLD.4" "SUBSTITUTE.FOLD.3" "SUBSTITUTE.FOLD.2" "SUBSTITUTE.FOLD.1" "SUBSTITUTE-IF-NOT.FOLD.3" - "MISC.598" "IMAGPART.4" + "MISC.598" "IMAGPART.4" "SHARED-INITIALIZE.ERROR.4" (append #+x86 (list "CIS.4") #+(or arm riscv (and arm64 (not darwin))) (list "EXP.ERROR.4" "EXP.ERROR.5" "EXP.ERROR.6" "EXP.ERROR.7" "EXPT.ERROR.4" diff --git a/tests/clos.impure.lisp b/tests/clos.impure.lisp index af142e6e9..f8e25dd69 100644 --- a/tests/clos.impure.lisp +++ b/tests/clos.impure.lisp @@ -1352,10 +1352,6 @@ (assert-error (shared-initialize (make-instance 'shared-initialize-keyword-check) nil :a) program-error)) -(with-test (:name (:check-keyword-args shared-initialize :non-keyword :error)) - (assert-error (shared-initialize (make-instance 'shared-initialize-keyword-check) nil '(abc) 1) - program-error)) - ;;; verify that we can still detect no primary methods and invalid qualifiers (defmethod gf-with-keys-and-no-primary-method :around ((x integer) &key b) ----------------------------------------------------------------------- hooks/post-receive -- SBCL _______________________________________________ Sbcl-commits mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sbcl-commits _______________________________________________ Sbcl-commits mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sbcl-commits